xinyu-pro 0.22.1 → 0.22.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -54,7 +54,10 @@ function rowToPlugin(row: Record<string, unknown>) {
54
54
  uiSlots: parseJsonField(row.ui_slots),
55
55
  ...perms,
56
56
  publicExports: parseJsonField(row.public_exports),
57
- dependencies: parseJsonField(row.dependencies),
57
+ dependencies: (() => {
58
+ const parsed = parseJsonField(row.dependencies);
59
+ return Array.isArray(parsed) ? parsed : [];
60
+ })(),
58
61
  createdAt: row.created_at,
59
62
  updatedAt: row.updated_at,
60
63
  };
@@ -174,8 +174,8 @@ export default function SettingsPage() {
174
174
  const all = await getGameSessions();
175
175
  setSessions(all.map((s) => ({
176
176
  id: s.id,
177
- title: s.worldSetting.title,
178
- era: s.worldSetting.era,
177
+ title: s.worldSetting.title as string,
178
+ era: s.worldSetting.era as string,
179
179
  count: s.messages.length,
180
180
  })));
181
181
  };
@@ -1414,6 +1414,19 @@ export default function SettingsPage() {
1414
1414
  }
1415
1415
  };
1416
1416
 
1417
+ useEffect(() => {
1418
+ const tabId = localStorage.getItem('settingTabId');
1419
+ if (tabId && CATEGORIES.some(cat => cat.id === tabId)) {
1420
+ for (const cat of CATEGORIES) {
1421
+ if (cat.id === tabId) {
1422
+ setActiveCategory(cat.id);
1423
+ break;
1424
+ }
1425
+ }
1426
+ localStorage.setItem('settingTabId', '')
1427
+ }
1428
+ });
1429
+
1417
1430
  return (
1418
1431
  <>
1419
1432
  <div className="h-screen flex flex-col overflow-hidden" style={{ backgroundColor: 'var(--color-bg-primary)' }}>
@@ -2,10 +2,12 @@
2
2
 
3
3
  import React, { useState } from 'react';
4
4
  import { useTheme } from './ThemeProvider';
5
+ import { useRouterHistory } from '@/lib/router-history';
5
6
 
6
7
  export function ThemeSwitcher({ buttonStyle = {} }: { buttonStyle?: React.CSSProperties }) {
7
8
  const { config, activeTheme, setActiveThemeId } = useTheme();
8
9
  const [isOpen, setIsOpen] = useState(false);
10
+ const { navigate } = useRouterHistory();
9
11
 
10
12
  return (
11
13
  <div className="relative">
@@ -20,10 +22,14 @@ export function ThemeSwitcher({ buttonStyle = {} }: { buttonStyle?: React.CSSPro
20
22
  }}
21
23
  title="切换主题"
22
24
  >
23
- <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
24
- <circle cx="12" cy="12" r="5" />
25
- <path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42" />
26
- </svg>
25
+ { activeTheme.isDark ?
26
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
27
+ <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" />
28
+ </svg> :
29
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
30
+ <circle cx="12" cy="12" r="5" />
31
+ <path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42" />
32
+ </svg> }
27
33
  <span className="text-sm hidden sm:inline">{activeTheme.name}</span>
28
34
  <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
29
35
  <path d="M6 9l6 6 6-6" />
@@ -43,19 +49,31 @@ export function ThemeSwitcher({ buttonStyle = {} }: { buttonStyle?: React.CSSPro
43
49
  boxShadow: '0 4px 24px var(--color-shadow)',
44
50
  }}
45
51
  >
46
- <div className="p-2">
47
- <p
48
- className="text-xs font-medium px-3 py-1 mb-1"
49
- style={{ color: 'var(--color-text-muted)' }}
50
- >
51
- 预设主题
52
- </p>
53
- {config.presets.map((theme) => (
52
+ <div className="p-2 flex flex-col gap-2">
53
+ <div className="flex justify-between items-center">
54
+ <p
55
+ className="text-xs font-medium px-3 py-1"
56
+ style={{ color: 'var(--color-text-muted)' }}
57
+ >
58
+ 主题
59
+ </p>
60
+ <button
61
+ className="text-xs font-medium px-3 py-1 border rounded-md transition-colors"
62
+ style={{ color: 'var(--color-text-muted)', borderColor: 'var(--color-border)' }}
63
+ onClick={() => {
64
+ setIsOpen(false);
65
+ localStorage.setItem('settingTabId', 'theme');
66
+ navigate('/settings');
67
+ }}
68
+ >
69
+ 更多
70
+ </button>
71
+ </div>
72
+ {([...config.presets, ...config.importedThemes]).map((theme) => (
54
73
  <button
55
74
  key={theme.id}
56
75
  onClick={() => {
57
76
  setActiveThemeId(theme.id);
58
- setIsOpen(false);
59
77
  }}
60
78
  className="w-full flex items-center gap-3 px-3 py-2 rounded-md text-left transition-colors"
61
79
  style={{
@@ -80,9 +98,6 @@ export function ThemeSwitcher({ buttonStyle = {} }: { buttonStyle?: React.CSSPro
80
98
  </div>
81
99
  <div>
82
100
  <div className="text-sm font-medium">{theme.name}</div>
83
- <div className="text-xs" style={{ color: 'var(--color-text-muted)' }}>
84
- {theme.description}
85
- </div>
86
101
  </div>
87
102
  {activeTheme.id === theme.id && (
88
103
  <svg className="ml-auto" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
@@ -92,7 +107,7 @@ export function ThemeSwitcher({ buttonStyle = {} }: { buttonStyle?: React.CSSPro
92
107
  </button>
93
108
  ))}
94
109
 
95
- {config.customTheme && (
110
+ {/* {config.customTheme && (
96
111
  <>
97
112
  <div className="my-1 border-t" style={{ borderColor: 'var(--color-border)' }} />
98
113
  <button
@@ -130,7 +145,7 @@ export function ThemeSwitcher({ buttonStyle = {} }: { buttonStyle?: React.CSSPro
130
145
  )}
131
146
  </button>
132
147
  </>
133
- )}
148
+ )} */}
134
149
  </div>
135
150
  </div>
136
151
  </>
@@ -774,7 +774,7 @@ class PluginRuntimeEngine {
774
774
  if (!callerInstance) {
775
775
  throw new Error(`[PluginRuntime] 调用方插件 ${callerPluginId} 未加载`);
776
776
  }
777
- const callerDeps = callerInstance.manifest.dependencies || [];
777
+ const callerDeps = Array.isArray(callerInstance.manifest.dependencies) ? callerInstance.manifest.dependencies : [];
778
778
  const hasDeclaredDep = callerDeps.some(d => d.pluginId === targetPluginId);
779
779
  if (!hasDeclaredDep) {
780
780
  throw new Error(`[PluginRuntime] 插件 ${callerPluginId} 未声明对 ${targetPluginId} 的依赖,请在 manifest.dependencies 中添加`);
@@ -844,7 +844,7 @@ class PluginRuntimeEngine {
844
844
 
845
845
  /** 检查插件的依赖状态 */
846
846
  checkDependencies(manifest: PluginManifest): DependencyStatus[] {
847
- const deps = manifest.dependencies || [];
847
+ const deps = Array.isArray(manifest.dependencies) ? manifest.dependencies : [];
848
848
  return deps.map(dep => {
849
849
  const targetInstance = this.state.instances.get(dep.pluginId);
850
850
  if (!targetInstance) {
@@ -897,7 +897,7 @@ class PluginRuntimeEngine {
897
897
  visiting.add(id);
898
898
 
899
899
  const manifest = manifestMap.get(id);
900
- if (manifest?.dependencies) {
900
+ if (Array.isArray(manifest?.dependencies)) {
901
901
  for (const dep of manifest.dependencies) {
902
902
  if (manifestMap.has(dep.pluginId)) {
903
903
  visit(dep.pluginId);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xinyu-pro",
3
- "version": "0.22.1",
3
+ "version": "0.22.3",
4
4
  "private": false,
5
5
  "description": "星语 Pro - AI 驱动的互动叙事平台",
6
6
  "author": "RestRegular",
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/version.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.22.1",
2
+ "version": "0.22.3",
3
3
  "name": "xinyu-pro",
4
4
  "displayName": "星语 Pro",
5
5
  "description": "AI 驱动的互动叙事平台"