91 lines
3.2 KiB
Python
91 lines
3.2 KiB
Python
|
|
"""Macros page — list macros, show steps, delete. Recording is voice-only."""
|
||
|
|
|
||
|
|
import flet as ft
|
||
|
|
|
||
|
|
from gui import services as svc
|
||
|
|
|
||
|
|
|
||
|
|
def build(page: ft.Page) -> ft.Control:
|
||
|
|
list_view = ft.Column(spacing=8, expand=True, scroll=ft.ScrollMode.AUTO)
|
||
|
|
|
||
|
|
def render():
|
||
|
|
list_view.controls.clear()
|
||
|
|
macros = svc.macros_all()
|
||
|
|
rec_on, rec_name = svc.macros_recording()
|
||
|
|
if rec_on:
|
||
|
|
list_view.controls.append(_recording_banner(rec_name))
|
||
|
|
if not macros:
|
||
|
|
list_view.controls.append(
|
||
|
|
ft.Text(
|
||
|
|
"Макросов пока нет. Запиши голосом: «Запиши макрос работа», "
|
||
|
|
"потом скажи команды, потом «Сохрани макрос».",
|
||
|
|
color="#8aa0a8",
|
||
|
|
)
|
||
|
|
)
|
||
|
|
for m in sorted(macros, key=lambda x: x["name"]):
|
||
|
|
list_view.controls.append(_macro_card(m, on_delete=lambda n=m["name"]: do_delete(n)))
|
||
|
|
page.update()
|
||
|
|
|
||
|
|
def do_delete(name: str) -> None:
|
||
|
|
if svc.macros_delete(name):
|
||
|
|
page.open(ft.SnackBar(content=ft.Text(f"Удалил «{name}»", color="white"), bgcolor="#33d3a4"))
|
||
|
|
render()
|
||
|
|
|
||
|
|
render()
|
||
|
|
|
||
|
|
return ft.Column(
|
||
|
|
[
|
||
|
|
ft.Row([
|
||
|
|
ft.Text("Макросы", size=24, weight=ft.FontWeight.W_700),
|
||
|
|
ft.FilledButton(text="Обновить", icon=ft.Icons.REFRESH, on_click=lambda e: render()),
|
||
|
|
], alignment=ft.MainAxisAlignment.SPACE_BETWEEN),
|
||
|
|
list_view,
|
||
|
|
],
|
||
|
|
expand=True,
|
||
|
|
spacing=10,
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def _recording_banner(name: str | None) -> ft.Control:
|
||
|
|
return ft.Container(
|
||
|
|
content=ft.Row([
|
||
|
|
ft.Icon(ft.Icons.FIBER_MANUAL_RECORD, color="#ff5757"),
|
||
|
|
ft.Text(
|
||
|
|
f"Идёт запись макроса «{name or '—'}». "
|
||
|
|
"Произнесите команды, затем «Сохрани макрос».",
|
||
|
|
),
|
||
|
|
]),
|
||
|
|
bgcolor="#3a2020",
|
||
|
|
border_radius=8,
|
||
|
|
padding=10,
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def _macro_card(m: dict, on_delete) -> ft.Control:
|
||
|
|
steps = m.get("steps", [])
|
||
|
|
preview = steps[:5]
|
||
|
|
extra = len(steps) - len(preview)
|
||
|
|
return ft.Container(
|
||
|
|
content=ft.Column([
|
||
|
|
ft.Row([
|
||
|
|
ft.Text(m["name"], weight=ft.FontWeight.W_600, size=14),
|
||
|
|
ft.Container(
|
||
|
|
content=ft.Text(f"{m['steps_count']} шагов", size=10),
|
||
|
|
bgcolor="#1e3a44",
|
||
|
|
padding=ft.padding.symmetric(horizontal=8, vertical=2),
|
||
|
|
border_radius=10,
|
||
|
|
),
|
||
|
|
], alignment=ft.MainAxisAlignment.SPACE_BETWEEN),
|
||
|
|
ft.Column([
|
||
|
|
ft.Text(f"• {s}", size=11, color="#a8b8c0") for s in preview
|
||
|
|
] + ([ft.Text(f"+ ещё {extra}…", size=11, color="#5a6a72", italic=True)] if extra > 0 else []),
|
||
|
|
spacing=2),
|
||
|
|
ft.Row([
|
||
|
|
ft.OutlinedButton(text="Удалить", icon=ft.Icons.DELETE, on_click=lambda e: on_delete()),
|
||
|
|
]),
|
||
|
|
], spacing=8),
|
||
|
|
bgcolor="#15252b",
|
||
|
|
border_radius=8,
|
||
|
|
padding=12,
|
||
|
|
)
|