File size: 4,339 Bytes
494c9e4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import {
    DEFAULT_EXCLUDE_GENERATED_PATTERNS_TEXT,
    DEFAULT_EXCLUDE_PROMPT_PATTERNS_TEXT,
    EXCLUDE_GENERATED_PATTERNS_ENABLED_STORAGE_KEY,
    EXCLUDE_GENERATED_PATTERNS_STORAGE_KEY,
    EXCLUDE_PROMPT_PATTERNS_ENABLED_STORAGE_KEY,
    EXCLUDE_PROMPT_PATTERNS_STORAGE_KEY,
} from './attributionExcludePromptPatternsStorage';

type BindExcludePatternsUiStorageKeys = {
    textKey: string;
    enabledKey: string;
};

type BindExcludePatternsUiOptions = {
    storageKeys: BindExcludePatternsUiStorageKeys;
    textInput: HTMLInputElement | HTMLTextAreaElement | null;
    enableCheckbox: HTMLInputElement | null;
    /** 列表在失焦提交后、或使能变化后触发(如 inspector.reapply) */
    onEffectiveChange: () => void;
    /** 键从未写入(`null`)时填充,与持久化 `''`(用户清空)区分 */
    defaultTextWhenKeyAbsent?: string;
};

export type BindExcludePromptPatternsUiOptions = Omit<BindExcludePatternsUiOptions, 'storageKeys' | 'defaultTextWhenKeyAbsent'>;

/**
 * 从 localStorage 回填、同步文本框禁用态、绑定持久化与回调(多组 key 共用实现)。
 */
function bindExcludePatternsUi(options: BindExcludePatternsUiOptions): void {
    const { storageKeys, textInput, enableCheckbox, onEffectiveChange, defaultTextWhenKeyAbsent } = options;
    const { textKey, enabledKey } = storageKeys;

    try {
        const savedExclude = localStorage.getItem(textKey);
        if (textInput) {
            if (savedExclude !== null) {
                textInput.value = savedExclude;
            } else if (defaultTextWhenKeyAbsent !== undefined) {
                textInput.value = defaultTextWhenKeyAbsent;
            }
        }
        const savedEnabled = localStorage.getItem(enabledKey);
        if (enableCheckbox) {
            enableCheckbox.checked = savedEnabled === null ? true : savedEnabled === '1';
        }
    } catch {
        // 读取失败则保持 HTML 默认
    }

    function syncTextInputDisabled(): void {
        if (!textInput) return;
        textInput.disabled = !enableCheckbox?.checked;
    }
    syncTextInputDisabled();

    enableCheckbox?.addEventListener('change', () => {
        try {
            if (textInput) {
                localStorage.setItem(textKey, textInput.value);
            }
            localStorage.setItem(enabledKey, enableCheckbox.checked ? '1' : '0');
        } catch {
            /* ignore */
        }
        syncTextInputDisabled();
        onEffectiveChange();
    });

    textInput?.addEventListener('blur', () => {
        try {
            localStorage.setItem(textKey, textInput.value);
        } catch {
            /* ignore */
        }
        onEffectiveChange();
    });

    window.addEventListener('storage', (event: StorageEvent) => {
        if (event.storageArea !== localStorage) return;
        const k = event.key;
        if (k !== textKey && k !== enabledKey) {
            return;
        }
        if (k === textKey && textInput) textInput.value = event.newValue ?? '';
        if (k === enabledKey && enableCheckbox) {
            enableCheckbox.checked = event.newValue === null ? true : event.newValue === '1';
        }
        syncTextInputDisabled();
        onEffectiveChange();
    });
}

/**
 * Exclude prompt patterns:Attribution 与 Generate & Attribute 页共用,storage 见 {@link attributionExcludePromptPatternsStorage}。
 */
export function bindExcludePromptPatternsUi(options: BindExcludePromptPatternsUiOptions): void {
    bindExcludePatternsUi({
        storageKeys: {
            textKey: EXCLUDE_PROMPT_PATTERNS_STORAGE_KEY,
            enabledKey: EXCLUDE_PROMPT_PATTERNS_ENABLED_STORAGE_KEY,
        },
        ...options,
        defaultTextWhenKeyAbsent: DEFAULT_EXCLUDE_PROMPT_PATTERNS_TEXT,
    });
}

/** Exclude generated patterns:仅 Generate & Attribute 页绑定;storage 键见 {@link attributionExcludePromptPatternsStorage}。 */
export function bindExcludeGeneratedPatternsUi(options: BindExcludePromptPatternsUiOptions): void {
    bindExcludePatternsUi({
        storageKeys: {
            textKey: EXCLUDE_GENERATED_PATTERNS_STORAGE_KEY,
            enabledKey: EXCLUDE_GENERATED_PATTERNS_ENABLED_STORAGE_KEY,
        },
        ...options,
        defaultTextWhenKeyAbsent: DEFAULT_EXCLUDE_GENERATED_PATTERNS_TEXT,
    });
}