- новый api/: /pipeline/process (yt-dlp, субтитры или Vosk, LLM/экстрактивная суммаризация), /videos, /llm; старый код перенесён в api_legacy/ - web/: Flet UI (flet 0.28.3 + flet-web, порт 8550) - Dockerfile.api: ffmpeg слоем из mwader/static-ffmpeg, pip с кэш-маунтом - requirements/pyproject: убраны moviepy, imageio-ffmpeg, битый asyncio - README с инструкцией запуска и загрузкой Vosk-модели Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
92 lines
2.2 KiB
Python
92 lines
2.2 KiB
Python
"""Centralized colors and reusable Flet widgets.
|
|
|
|
Palette is inspired by the dark-purple theme of the related project
|
|
(api-copp): #2F184B base surface, #9b72cf accent.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import flet as ft
|
|
|
|
|
|
BG = "#14101e"
|
|
SURFACE = "#2f184b"
|
|
SURFACE_2 = "#3a2160"
|
|
SURFACE_3 = "#1c1230"
|
|
BORDER = "#4a2f6f"
|
|
ACCENT = "#9b72cf"
|
|
ACCENT_2 = "#c0a4e8"
|
|
TEXT = "#ece5f5"
|
|
MUTED = "#a89ec0"
|
|
DANGER = "#e35a72"
|
|
OK = "#6dd58c"
|
|
|
|
|
|
def card(*controls: ft.Control, padding: int = 22) -> ft.Container:
|
|
return ft.Container(
|
|
content=ft.Column(controls=list(controls), spacing=12, tight=True),
|
|
bgcolor=SURFACE,
|
|
border=ft.border.all(1, BORDER),
|
|
border_radius=12,
|
|
padding=padding,
|
|
)
|
|
|
|
|
|
def primary_button(text: str, on_click) -> ft.ElevatedButton:
|
|
return ft.ElevatedButton(
|
|
text=text,
|
|
on_click=on_click,
|
|
bgcolor=ACCENT,
|
|
color="#ffffff",
|
|
style=ft.ButtonStyle(
|
|
shape=ft.RoundedRectangleBorder(radius=8),
|
|
padding=ft.padding.symmetric(horizontal=18, vertical=12),
|
|
),
|
|
)
|
|
|
|
|
|
def secondary_button(text: str, on_click) -> ft.OutlinedButton:
|
|
return ft.OutlinedButton(
|
|
text=text,
|
|
on_click=on_click,
|
|
style=ft.ButtonStyle(
|
|
color=TEXT,
|
|
side=ft.BorderSide(1, BORDER),
|
|
shape=ft.RoundedRectangleBorder(radius=8),
|
|
padding=ft.padding.symmetric(horizontal=18, vertical=12),
|
|
),
|
|
)
|
|
|
|
|
|
def text_field(
|
|
label: str,
|
|
value: str = "",
|
|
hint: str | None = None,
|
|
password: bool = False,
|
|
on_change=None,
|
|
expand: bool | int | None = True,
|
|
) -> ft.TextField:
|
|
return ft.TextField(
|
|
label=label,
|
|
value=value,
|
|
hint_text=hint or "",
|
|
password=password,
|
|
can_reveal_password=password,
|
|
on_change=on_change,
|
|
bgcolor=SURFACE_3,
|
|
color=TEXT,
|
|
border_color=BORDER,
|
|
focused_border_color=ACCENT,
|
|
cursor_color=ACCENT_2,
|
|
label_style=ft.TextStyle(color=MUTED, size=12),
|
|
text_size=14,
|
|
expand=expand,
|
|
)
|
|
|
|
|
|
def section_title(text: str) -> ft.Text:
|
|
return ft.Text(text, color=TEXT, size=18, weight=ft.FontWeight.W_600)
|
|
|
|
|
|
def hint(text: str) -> ft.Text:
|
|
return ft.Text(text, color=MUTED, size=12)
|