File size: 3,983 Bytes
65b0b93
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
"""不依赖 NiceGUI 控件的页面会话状态。"""

from dataclasses import dataclass, field
from typing import Any

from core.workspace import empty_favorites, empty_history, new_workspace
from webui.constants import LOCAL_STORAGE_NAMES


@dataclass
class PageState:
    """单个浏览器页面的纯数据状态;控件引用由控制器单独持有。"""

    full_table_data: list[dict] = field(default_factory=list)
    current_segments: list[str] = field(default_factory=list)
    current_keywords: list[str] = field(default_factory=list)
    current_cached_queries: set[str] = field(default_factory=set)
    current_filter_keyword: str = 'ALL'
    current_query_str: str = ''
    full_tags_str: str = ''
    full_tags_str_sfw: str = ''

    current_related: list[Any] = field(default_factory=list)
    chip_extra_selected: set[str] = field(default_factory=set)
    selected_order: list[str] = field(default_factory=list)
    rendered_selected_chip_tags: set[str] = field(default_factory=set)
    workspace: dict = field(default_factory=new_workspace)
    history: dict = field(default_factory=empty_history)
    favorites: dict = field(default_factory=empty_favorites)
    undo_stack: list[dict] = field(default_factory=list)
    redo_stack: list[dict] = field(default_factory=list)
    pending_selection_meta: dict[str, dict[str, str]] = field(default_factory=dict)
    workspace_artist_tags: set[str] = field(default_factory=set)

    tag_weights: dict[str, float] = field(default_factory=dict)
    prompt_format: str = 'sdxl'
    selected_layers: dict[str, bool] = field(default_factory=lambda: {
        '英文': True,
        '中文扩展词': True,
        '释义': True,
        '中文核心词': True,
        'artist': True,
    })
    selected_categories: dict[str, bool] = field(default_factory=lambda: {
        'General': True,
        'Copyright': True,
        'Character': True,
    })

    related_results: list[Any] = field(default_factory=list)
    related_show_nsfw: bool = True
    related_page: int = 1
    related_page_count: int = 0
    group_render_limits: dict[str, int] = field(default_factory=dict)
    group_expanded_names: set[str] = field(default_factory=set)
    group_scroll_positions: dict[str, int] = field(default_factory=dict)
    group_render_key: tuple[str, ...] = ()
    group_candidate_sources: dict[str, str] = field(default_factory=dict)

    artist_rec_rows: list[dict] = field(default_factory=list)
    artist_rec_results: list[Any] = field(default_factory=list)
    artist_rec_top_tags: dict[str, list[str]] = field(default_factory=dict)
    artist_rec_show_nsfw: bool = True
    artist_rec_sources: dict[str, str] = field(default_factory=dict)
    artist_rec_page: int = 1
    artist_rec_page_count: int = 0
    current_artist_rec_tags: set[str] = field(default_factory=set)
    artist_result_tags: set[str] = field(default_factory=set)
    last_recommendation_seed_tags: list[str] = field(default_factory=list)
    pending_recommendation_request: dict | None = None
    recommendation_generation: int = 0

    storage_states: dict[str, str] = field(
        default_factory=lambda: {name: 'pending' for name in LOCAL_STORAGE_NAMES}
    )
    storage_session_dirty: set[str] = field(default_factory=set)
    storage_applying: set[str] = field(default_factory=set)
    storage_raw_values: dict[str, str | None] = field(default_factory=dict)


class StateField:
    """把控制器的旧属性名兼容地代理到 ``controller.state``。"""

    def __init__(self, state_name: str | None = None):
        self.state_name = state_name

    def __set_name__(self, owner, name: str) -> None:
        if self.state_name is None:
            self.state_name = name

    def __get__(self, instance, owner=None):
        if instance is None:
            return self
        return getattr(instance.state, self.state_name)

    def __set__(self, instance, value) -> None:
        setattr(instance.state, self.state_name, value)