mirror of
https://github.com/spoopyghosty0/frameport.git
synced 2026-10-20 10:01:33 +02:00
- Screenshots tab: Copy image (a button on the card under the pointer, the right-click menu and the viewer) puts the full-size screenshot on this PC's clipboard (core/clipboard.py: Windows/WSL PowerShell bitmap + file, macOS osascript, Linux wl-copy/xclip; Flet's set_image in web mode) - Clicking a holiday badge showers the window: New Year confetti, winter snow, Valentine hearts, digits of pi, clovers, hopping eggs, bouncing pumpkins (moved like the confetti: one page update per phase) - Perfect pacing after 2.5 minutes on target; the Perfect pacing pill and line stay until the rate slips - Full charge: only the ring pulses (with a glow behind it), the percentage stays put - Upload hop a little slower
131 lines
5.2 KiB
Python
131 lines
5.2 KiB
Python
"""Right-click menus in the Files and Screenshots tabs: what they offer, and that a right-click on one of several
|
|
selected items acts on the whole selection (as in a file manager)."""
|
|
from types import SimpleNamespace
|
|
|
|
from frameport.install.files import Entry
|
|
from frameport.ui import components as C
|
|
from frameport.ui.views.files import FilesView
|
|
from frameport.ui.views.screenshots import ALL, ScreenshotsView
|
|
|
|
|
|
class FakeApp(SimpleNamespace):
|
|
def __init__(self):
|
|
super().__init__(copied=[], page=SimpleNamespace(run_task=lambda fn, *a, **k: None))
|
|
|
|
def copy(self, text):
|
|
self.copied.append(text)
|
|
|
|
|
|
def labels(actions):
|
|
return [a[0] if a else "—" for a in actions]
|
|
|
|
|
|
def test_menu_targets_selection_or_single():
|
|
assert C.menu_targets("a", ["a", "b"]) == ["a", "b"]
|
|
assert C.menu_targets("c", ["a", "b"]) == ["c"] # outside the selection: only the clicked item
|
|
assert C.menu_targets("a", ["a"]) == ["a"]
|
|
|
|
|
|
def files_view():
|
|
v = FilesView(FakeApp())
|
|
v.loc = {"id": "videos", "label": "Videos", "path": "/home/x/Videos", "android": "/sdcard/Movies"}
|
|
v.path = "/home/x/Videos/trips"
|
|
v.entries = [Entry("clips", "/home/x/Videos/trips/clips", True, 0, 0),
|
|
Entry("a.mp4", "/home/x/Videos/trips/a.mp4", False, 10, 0),
|
|
Entry("b.mp4", "/home/x/Videos/trips/b.mp4", False, 20, 0)]
|
|
return v
|
|
|
|
|
|
def test_files_menu_single_entry_and_folder_space():
|
|
v = files_view()
|
|
folder = labels(v.menu_actions(v.entries[0]))
|
|
assert folder[:4] == ["Open", "Download to this PC…", "Rename…", "Copy path"]
|
|
assert "Select" in folder and folder[-1] == "Delete…"
|
|
actions = v.menu_actions(v.entries[1])
|
|
assert "Open" not in labels(actions)
|
|
dict((a[0], a[2]) for a in actions if a)["Copy path"](None)
|
|
assert v.app.copied == ["/sdcard/Movies/trips/a.mp4"] # as games see it
|
|
space = labels(v.menu_actions(None))
|
|
assert space[:3] == ["Upload files…", "Upload folder…", "New folder…"] and "Refresh" in space
|
|
|
|
|
|
def test_files_menu_on_a_selection_acts_on_all_of_it():
|
|
v = files_view()
|
|
v.selected = {v.entries[1].path, v.entries[2].path}
|
|
multi = labels(v.menu_actions(v.entries[2]))
|
|
assert "Download 2 items to this PC…" in multi and "Delete 2 items…" in multi
|
|
assert "Rename…" not in multi and "Clear selection" in multi
|
|
assert "Download to this PC…" in labels(v.menu_actions(v.entries[0])) # not in the selection: just that one
|
|
|
|
|
|
def test_files_menu_keeps_lepton_links_safe():
|
|
v = files_view()
|
|
v.loc = {"id": "app:x", "label": "Game", "path": "/base/external", "android": "/sdcard"}
|
|
v.path = "/base/external"
|
|
link = Entry("Movies", "/base/external/Movies", True, 0, 0, link=True)
|
|
v.entries = [link]
|
|
got = labels(v.menu_actions(link))
|
|
assert "Rename…" not in got and "Delete…" not in got and "Select" not in got
|
|
|
|
|
|
def screenshots_view():
|
|
v = ScreenshotsView(FakeApp())
|
|
v.shots = [{"path": f"/s/{i}.jpg", "package": "com.x" if i < 2 else "", "title": "X", "time": 1} for i in range(3)]
|
|
v._fill_dropdown()
|
|
return v
|
|
|
|
|
|
def test_screenshots_menu():
|
|
v = screenshots_view()
|
|
v.games = [{"package": "com.x", "title": "X", "count": 2}, {"package": "", "count": 1}]
|
|
v._fill_dropdown()
|
|
one = labels(v.menu_actions(v.shots[0]))
|
|
assert one[:4] == ["View", "Copy image", "Download…", "Show only this game's screenshots"]
|
|
assert one[-1] == "Delete…"
|
|
assert "Show only screenshots not from a FramePort game" in labels(v.menu_actions(v.shots[2]))
|
|
v.filter = "com.x"
|
|
assert not any("Show only" in x for x in labels(v.menu_actions(v.shots[0])))
|
|
v.filter = ALL
|
|
v.selected = {v.shots[0]["path"], v.shots[1]["path"]}
|
|
multi = labels(v.menu_actions(v.shots[1]))
|
|
assert "Download 2 screenshots…" in multi and "Delete 2 screenshots…" in multi and "View" not in multi
|
|
assert "Copy image" not in multi # (the clipboard holds one picture)
|
|
assert labels(v.menu_actions(None))[:2] == ["Download all (3)…", "Select all"]
|
|
|
|
|
|
def test_drag_select_paints_a_selection():
|
|
sel = set()
|
|
d = C.DragSelect(lambda k: k in sel, lambda k, on: (sel.add if on else sel.discard)(k),
|
|
can_select=lambda k: k != "locked")
|
|
d.hover("a", True) # just hovering: nothing happens
|
|
assert sel == set()
|
|
d.start() # press on "a" and drag
|
|
for k in ("b", "locked", "c"):
|
|
d.hover(k, True)
|
|
d.hover("b", True) # passing an item again doesn't flip it back
|
|
d.end()
|
|
assert sel == {"a", "b", "c"}
|
|
d.hover("d", True) # after the drag: hover only
|
|
assert "d" not in sel
|
|
|
|
|
|
def test_drag_select_from_a_selected_item_deselects():
|
|
sel = {"a", "b", "c"}
|
|
d = C.DragSelect(lambda k: k in sel, lambda k, on: (sel.add if on else sel.discard)(k))
|
|
d.hover("b", True)
|
|
d.start()
|
|
d.hover("c", True)
|
|
d.end()
|
|
assert sel == {"a"}
|
|
|
|
|
|
def test_drag_select_from_empty_space_selects_and_calls_on_start():
|
|
sel, started = set(), []
|
|
d = C.DragSelect(lambda k: k in sel, lambda k, on: (sel.add if on else sel.discard)(k),
|
|
on_start=lambda: started.append(1))
|
|
d.hover("a", True)
|
|
d.hover("a", False) # left the item: the drag starts on empty space
|
|
d.start()
|
|
d.hover("x", True)
|
|
assert sel == {"x"} and started == [1]
|