"""Plugins page — list user packs, toggle enabled, open folder.""" 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() packs = svc.plugins_all() if not packs: list_view.controls.append( ft.Column([ ft.Text( "Плагинов пока нет. Создай папку с commands.yaml в " "%APPDATA%\\com.priler.jarvis\\plugins\\, нажми «Обновить».", color="#8aa0a8", ), ]) ) for p in packs: list_view.controls.append(_pack_row(p, on_toggle=lambda n=p["name"], e=p["enabled"]: do_toggle(n, e))) page.update() def do_toggle(name: str, was_enabled: bool): ok, msg = svc.plugins_set_enabled(name, not was_enabled) page.open(ft.SnackBar( content=ft.Text( "Перезапусти main.py, чтобы применить." if ok else f"Ошибка: {msg}", color="white", ), bgcolor="#33d3a4" if ok else "#d8584f", )) render() def do_open(_): path = svc.plugins_open_folder() page.open(ft.SnackBar(content=ft.Text(f"Папка: {path}", color="white"), bgcolor="#33d3a4")) render() return ft.Column( [ ft.Row([ ft.Text("Плагины", size=24, weight=ft.FontWeight.W_700), ft.Row([ ft.OutlinedButton(text="Открыть папку", icon=ft.Icons.FOLDER_OPEN, on_click=do_open), ft.FilledButton(text="Обновить", icon=ft.Icons.REFRESH, on_click=lambda e: render()), ]), ], alignment=ft.MainAxisAlignment.SPACE_BETWEEN), ft.Text( "Папки в %APPDATA%\\com.priler.jarvis\\plugins\\, " "каждая содержит свой commands.yaml. Изменения подхватываются после рестарта main.py.", color="#8aa0a8", size=12, ), list_view, ], spacing=10, expand=True, ) def _pack_row(p: dict, on_toggle) -> ft.Control: err = p.get("error") return ft.Container( content=ft.Column([ ft.Row([ ft.Text(p["name"], weight=ft.FontWeight.W_600, size=14), ft.Container( content=ft.Text( "ошибка" if err else f"{p['command_count']} команд", size=10, color="white", ), bgcolor="#7a2c2c" if err else ("#1e6b5a" if p["enabled"] else "#404040"), padding=ft.padding.symmetric(horizontal=8, vertical=2), border_radius=10, ), ], alignment=ft.MainAxisAlignment.SPACE_BETWEEN), ft.Text(p["path"], size=10, color="#5a6a72", font_family="Cascadia Mono"), ft.Text(err, size=11, color="#ff8888") if err else ft.Container(height=0), ft.Row([ ft.Switch( value=p["enabled"], on_change=lambda e: on_toggle(), disabled=bool(err), ), ft.Text("Включён" if p["enabled"] else "Выключен", size=11, color="#33d3a4" if p["enabled"] else "#8aa0a8"), ]), ], spacing=6), bgcolor="#15252b", border_radius=8, padding=12, )