Files
esengine/packages/editor-app/src/services/SettingsService.ts

154 lines
4.8 KiB
TypeScript
Raw Normal View History

2025-10-16 13:07:19 +08:00
export class SettingsService {
private static instance: SettingsService;
private settings: Map<string, any> = new Map();
private storageKey = 'editor-settings';
2025-10-16 13:07:19 +08:00
private constructor() {
this.loadSettings();
}
2025-10-16 13:07:19 +08:00
public static getInstance(): SettingsService {
if (!SettingsService.instance) {
SettingsService.instance = new SettingsService();
}
return SettingsService.instance;
2025-10-16 13:07:19 +08:00
}
private loadSettings(): void {
try {
const stored = localStorage.getItem(this.storageKey);
if (stored) {
const data = JSON.parse(stored);
this.settings = new Map(Object.entries(data));
}
} catch (error) {
console.error('[SettingsService] Failed to load settings:', error);
}
2025-10-16 13:07:19 +08:00
}
private saveSettings(): void {
try {
const data = Object.fromEntries(this.settings);
localStorage.setItem(this.storageKey, JSON.stringify(data));
} catch (error) {
console.error('[SettingsService] Failed to save settings:', error);
}
2025-10-16 13:07:19 +08:00
}
public get<T>(key: string, defaultValue: T): T {
if (this.settings.has(key)) {
return this.settings.get(key) as T;
}
return defaultValue;
2025-10-16 13:07:19 +08:00
}
public set<T>(key: string, value: T): void {
this.settings.set(key, value);
this.saveSettings();
}
2025-10-16 13:07:19 +08:00
public has(key: string): boolean {
return this.settings.has(key);
}
2025-10-16 13:07:19 +08:00
public delete(key: string): void {
this.settings.delete(key);
this.saveSettings();
}
2025-10-16 13:07:19 +08:00
public clear(): void {
this.settings.clear();
this.saveSettings();
}
2025-10-16 13:07:19 +08:00
public getAll(): Record<string, any> {
return Object.fromEntries(this.settings);
}
2025-10-16 17:10:22 +08:00
public getRecentProjects(): string[] {
return this.get<string[]>('recentProjects', []);
}
2025-10-16 17:10:22 +08:00
public addRecentProject(projectPath: string): void {
// 规范化路径,防止双重转义 | Normalize path to prevent double escaping
const normalizedPath = projectPath.replace(/\\\\/g, '\\');
const recentProjects = this.getRecentProjects();
const filtered = recentProjects.filter((p) => p !== normalizedPath);
const updated = [normalizedPath, ...filtered].slice(0, 10);
this.set('recentProjects', updated);
}
2025-10-16 17:10:22 +08:00
public removeRecentProject(projectPath: string): void {
const recentProjects = this.getRecentProjects();
const filtered = recentProjects.filter((p) => p !== projectPath);
this.set('recentProjects', filtered);
}
2025-10-16 17:10:22 +08:00
public clearRecentProjects(): void {
this.set('recentProjects', []);
}
// ==================== Script Editor Settings ====================
/**
*
* Supported script editor types
feat(i18n): 统一国际化系统架构,支持插件独立翻译 (#301) * feat(i18n): 统一国际化系统架构,支持插件独立翻译 ## 主要改动 ### 核心架构 - 增强 LocaleService,支持插件命名空间翻译扩展 - 新增 editor-runtime/i18n 模块,提供 createPluginLocale/createPluginTranslator - 新增 editor-core/tokens.ts,定义 LocaleServiceToken 等服务令牌 - 改进 PluginAPI 类型安全,使用 ServiceToken<T> 替代 any ### 编辑器本地化 - 扩展 en.ts/zh.ts 翻译文件,覆盖所有 UI 组件 - 新增 es.ts 西班牙语支持 - 重构 40+ 组件使用 useLocale() hook ### 插件本地化系统 - behavior-tree-editor: 新增 locales/ 和 useBTLocale hook - material-editor: 新增 locales/ 和 useMaterialLocale hook - particle-editor: 新增 locales/ 和 useParticleLocale hook - tilemap-editor: 新增 locales/ 和 useTilemapLocale hook - ui-editor: 新增 locales/ 和 useUILocale hook ### 类型安全改进 - 修复 Debug 工具使用公共接口替代 as any - 修复 ChunkStreamingSystem 添加 forEachChunk 公共方法 - 修复 blueprint-editor 移除不必要的向后兼容代码 * fix(behavior-tree-editor): 使用 ServiceToken 模式修复服务解析 - 创建 BehaviorTreeServiceToken 遵循"谁定义接口,谁导出Token"原则 - 使用 ServiceToken.id (symbol) 注册服务到 ServiceContainer - 更新 PluginSDKRegistry.resolveService 支持 ServiceToken 检测 - BehaviorTreeEditorPanel 现在使用类型安全的 PluginAPI.resolve * fix(behavior-tree-editor): 使用 ServiceContainer.resolve 获取类注册的服务 * fix: 修复多个包的依赖和类型问题 - core: EntityDataCollector.getEntityDetails 使用 HierarchySystem 获取父实体 - ui-editor: 添加 @esengine/editor-runtime 依赖 - tilemap-editor: 添加 @esengine/editor-runtime 依赖 - particle-editor: 添加 @esengine/editor-runtime 依赖
2025-12-09 18:04:03 +08:00
*
* 使 nameKey nameKey 使 name
* Use nameKey as translation key, fallback to name if no nameKey
*/
public static readonly SCRIPT_EDITORS = [
feat(i18n): 统一国际化系统架构,支持插件独立翻译 (#301) * feat(i18n): 统一国际化系统架构,支持插件独立翻译 ## 主要改动 ### 核心架构 - 增强 LocaleService,支持插件命名空间翻译扩展 - 新增 editor-runtime/i18n 模块,提供 createPluginLocale/createPluginTranslator - 新增 editor-core/tokens.ts,定义 LocaleServiceToken 等服务令牌 - 改进 PluginAPI 类型安全,使用 ServiceToken<T> 替代 any ### 编辑器本地化 - 扩展 en.ts/zh.ts 翻译文件,覆盖所有 UI 组件 - 新增 es.ts 西班牙语支持 - 重构 40+ 组件使用 useLocale() hook ### 插件本地化系统 - behavior-tree-editor: 新增 locales/ 和 useBTLocale hook - material-editor: 新增 locales/ 和 useMaterialLocale hook - particle-editor: 新增 locales/ 和 useParticleLocale hook - tilemap-editor: 新增 locales/ 和 useTilemapLocale hook - ui-editor: 新增 locales/ 和 useUILocale hook ### 类型安全改进 - 修复 Debug 工具使用公共接口替代 as any - 修复 ChunkStreamingSystem 添加 forEachChunk 公共方法 - 修复 blueprint-editor 移除不必要的向后兼容代码 * fix(behavior-tree-editor): 使用 ServiceToken 模式修复服务解析 - 创建 BehaviorTreeServiceToken 遵循"谁定义接口,谁导出Token"原则 - 使用 ServiceToken.id (symbol) 注册服务到 ServiceContainer - 更新 PluginSDKRegistry.resolveService 支持 ServiceToken 检测 - BehaviorTreeEditorPanel 现在使用类型安全的 PluginAPI.resolve * fix(behavior-tree-editor): 使用 ServiceContainer.resolve 获取类注册的服务 * fix: 修复多个包的依赖和类型问题 - core: EntityDataCollector.getEntityDetails 使用 HierarchySystem 获取父实体 - ui-editor: 添加 @esengine/editor-runtime 依赖 - tilemap-editor: 添加 @esengine/editor-runtime 依赖 - particle-editor: 添加 @esengine/editor-runtime 依赖
2025-12-09 18:04:03 +08:00
{ id: 'system', name: 'System Default', nameKey: 'settings.scriptEditor.systemDefault', command: '' },
{ id: 'vscode', name: 'Visual Studio Code', command: 'code' },
{ id: 'cursor', name: 'Cursor', command: 'cursor' },
{ id: 'webstorm', name: 'WebStorm', command: 'webstorm' },
{ id: 'sublime', name: 'Sublime Text', command: 'subl' },
{ id: 'custom', name: 'Custom', nameKey: 'settings.scriptEditor.custom', command: '' }
];
/**
*
* Get script editor setting
*/
public getScriptEditor(): string {
return this.get<string>('editor.scriptEditor', 'system');
}
/**
*
* Set script editor
*/
public setScriptEditor(editorId: string): void {
this.set('editor.scriptEditor', editorId);
}
/**
*
* Get custom script editor command
*/
public getCustomScriptEditorCommand(): string {
return this.get<string>('editor.customScriptEditorCommand', '');
}
/**
*
* Set custom script editor command
*/
public setCustomScriptEditorCommand(command: string): void {
this.set('editor.customScriptEditorCommand', command);
}
/**
*
* Get current script editor command
*/
public getScriptEditorCommand(): string {
const editorId = this.getScriptEditor();
if (editorId === 'custom') {
return this.getCustomScriptEditorCommand();
}
const editor = SettingsService.SCRIPT_EDITORS.find(e => e.id === editorId);
return editor?.command || '';
}
2025-10-16 13:07:19 +08:00
}