feat(ui): overhaul default channel editor with full param override visual editor

- Port classic ParamOverrideEditorModal to default as standalone dialog (~3200 lines)
  with two-panel layout, drag-to-reorder, 23 operation modes, template library,
  visual/JSON dual mode, conditions management, and legacy format support
- Redesign channel drawer layout with clear visual hierarchy (CardHeading vs SubHeading)
  and bordered sub-modules for Field Passthrough and Upstream Model Detection
- Replace header override JsonEditor with plain textarea matching classic behavior
- Add searchable channel type combobox with scroll fix
- Add 100+ i18n keys across all 6 locales (en, zh, fr, ja, ru, vi)
This commit is contained in:
CaIon
2026-04-29 18:09:11 +08:00
parent 3b592895c6
commit b44faec66b
15 changed files with 5658 additions and 892 deletions
+29
View File
@@ -59,6 +59,7 @@ export const channelFormSchema = z.object({
// Upstream model update settings (stored in settings JSON)
upstream_model_update_check_enabled: z.boolean().optional(),
upstream_model_update_auto_sync_enabled: z.boolean().optional(),
upstream_model_update_ignored_models: z.string().optional(),
})
export type ChannelFormValues = z.infer<typeof channelFormSchema>
@@ -113,6 +114,9 @@ export const CHANNEL_FORM_DEFAULT_VALUES: ChannelFormValues = {
allow_inference_geo: false,
allow_speed: false,
claude_beta_query: false,
upstream_model_update_check_enabled: false,
upstream_model_update_auto_sync_enabled: false,
upstream_model_update_ignored_models: '',
}
// ============================================================================
@@ -166,6 +170,7 @@ export function transformChannelToFormDefaults(
let claudeBetaQuery = false
let upstreamModelUpdateCheckEnabled = false
let upstreamModelUpdateAutoSyncEnabled = false
let upstreamModelUpdateIgnoredModels = ''
if (channel.settings) {
try {
@@ -185,6 +190,11 @@ export function transformChannelToFormDefaults(
parsed.upstream_model_update_check_enabled === true
upstreamModelUpdateAutoSyncEnabled =
parsed.upstream_model_update_auto_sync_enabled === true
upstreamModelUpdateIgnoredModels = Array.isArray(
parsed.upstream_model_update_ignored_models
)
? parsed.upstream_model_update_ignored_models.join(',')
: ''
} catch (error) {
// eslint-disable-next-line no-console
console.error('Failed to parse channel settings:', error)
@@ -233,6 +243,7 @@ export function transformChannelToFormDefaults(
allow_safety_identifier: allowSafetyIdentifier,
upstream_model_update_check_enabled: upstreamModelUpdateCheckEnabled,
upstream_model_update_auto_sync_enabled: upstreamModelUpdateAutoSyncEnabled,
upstream_model_update_ignored_models: upstreamModelUpdateIgnoredModels,
}
}
@@ -336,7 +347,25 @@ function buildSettingsJSON(formData: ChannelFormValues): string {
settingsObj.upstream_model_update_check_enabled =
formData.upstream_model_update_check_enabled === true
settingsObj.upstream_model_update_auto_sync_enabled =
settingsObj.upstream_model_update_check_enabled === true &&
formData.upstream_model_update_auto_sync_enabled === true
settingsObj.upstream_model_update_ignored_models = Array.from(
new Set(
String(formData.upstream_model_update_ignored_models || '')
.split(',')
.map((model) => model.trim())
.filter(Boolean)
)
)
if (
!Array.isArray(settingsObj.upstream_model_update_last_detected_models) ||
settingsObj.upstream_model_update_check_enabled !== true
) {
settingsObj.upstream_model_update_last_detected_models = []
}
if (typeof settingsObj.upstream_model_update_last_check_time !== 'number') {
settingsObj.upstream_model_update_last_check_time = 0
}
}
return JSON.stringify(settingsObj)