chore: enforce lint across codebase and ban "maybe" in identifiers

Remove member-ordering and complexity eslint-disable comments by reordering
class members and applying targeted fixes. Add metoyou/no-maybe-in-naming,
type-safe WebRTC e2e harness helpers, and resolve remaining lint errors so
npm run lint exits cleanly.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-11 11:08:26 +02:00
parent b630bacdc6
commit 79c6f91cd6
138 changed files with 4286 additions and 2310 deletions

View File

@@ -49,28 +49,45 @@ type ThemeStudioWorkspace = 'editor' | 'inspector' | 'layout';
})
export class ThemeSettingsComponent {
readonly modal = inject(SettingsModalService);
readonly theme = inject(ThemeService);
readonly themeLibrary = inject(ThemeLibraryService);
readonly registry = inject(ThemeRegistryService);
readonly picker = inject(ElementPickerService);
readonly layoutSync = inject(LayoutSyncService);
private readonly appI18n = inject(AppI18nService);
readonly editorRef = viewChild<ThemeJsonCodeEditorComponent>('jsonEditorRef');
readonly draftText = this.theme.draftText;
readonly draftErrors = this.theme.draftErrors;
readonly draftIsValid = this.theme.draftIsValid;
readonly statusMessage = this.theme.statusMessage;
readonly isDraftDirty = this.theme.isDraftDirty;
readonly isFullscreen = this.modal.themeStudioFullscreen;
readonly activeTheme = this.theme.activeTheme;
readonly builtInPresets = this.theme.builtInPresets;
readonly draftTheme = this.theme.draftTheme;
readonly THEME_ANIMATION_FIELDS = THEME_ANIMATION_FIELD_HINTS;
readonly animationKeys = this.theme.knownAnimationClasses;
readonly layoutContainers = this.layoutSync.containers();
readonly themeEntries = this.registry.entries();
readonly workspaceTabs = computed(() => [
{
key: 'editor' as const,
@@ -88,15 +105,23 @@ export class ThemeSettingsComponent {
description: this.appI18n.instant('theme.studio.workspaces.layout.description')
}
]);
readonly mountedKeyCounts = computed(() => this.registry.mountedKeyCounts());
readonly activeWorkspace = signal<ThemeStudioWorkspace>('editor');
readonly activeEditorTab = signal<ThemeEditorTab>('json');
readonly cssOnlyText = signal('');
readonly explorerQuery = signal('');
readonly selectedContainer = signal<ThemeContainerKey>('roomLayout');
readonly selectedElementKey = signal<string>('chatRoomMainPanel');
readonly selectedElement = computed(() => this.registry.getDefinition(this.selectedElementKey()));
readonly selectedElementCapabilities = computed(() => {
const selected = this.selectedElement();
@@ -111,24 +136,31 @@ export class ThemeSettingsComponent {
selected.supportsIcon ? this.appI18n.instant('theme.studio.capabilities.iconSlot') : null
].filter((value): value is string => value !== null);
});
readonly selectedContainerItems = computed(() => this.layoutSync.itemsForContainer(this.selectedContainer()));
readonly selectedLayoutContainer = computed(() => {
return this.layoutContainers.find((container) => container.key === this.selectedContainer()) ?? this.layoutContainers[0];
});
readonly selectedElementGrid = computed(() => {
return this.selectedContainerItems().find((item) => item.key === this.selectedElementKey()) ?? null;
});
readonly activeWorkspaceInfo = computed(() => {
return this.workspaceTabs().find((workspace) => workspace.key === this.activeWorkspace()) ?? this.workspaceTabs()[0];
});
readonly localizedFilteredEntries = computed(() =>
this.filteredEntries().map((entry) => this.localizeRegistryEntry(entry))
);
readonly localizedSelectedElement = computed(() => {
const selected = this.selectedElement();
return selected ? this.localizeRegistryEntry(selected) : null;
});
readonly visiblePropertyHints = computed(() => {
const selected = this.selectedElement();
@@ -148,9 +180,11 @@ export class ThemeSettingsComponent {
return true;
});
});
readonly mountedEntries = computed(() => {
return this.themeEntries.filter((entry) => entry.pickerVisible || entry.layoutEditable);
});
readonly filteredEntries = computed(() => {
const query = this.explorerQuery().trim()
.toLowerCase();
@@ -165,17 +199,29 @@ export class ThemeSettingsComponent {
return haystack.includes(query);
});
});
readonly draftLineCount = computed(() => this.draftText().split('\n').length);
readonly draftCharacterCount = computed(() => this.draftText().length);
readonly draftErrorCount = computed(() => this.draftErrors().length);
readonly mountedEntryCount = computed(() => this.mountedEntries().length);
readonly llmGuideCopyMessage = signal<string | null>(null);
readonly savedThemesAvailable = this.themeLibrary.isAvailable;
readonly savedThemes = this.themeLibrary.entries;
readonly savedThemesBusy = this.themeLibrary.isBusy;
readonly savedThemesPath = this.themeLibrary.savedThemesPath;
readonly selectedSavedTheme = this.themeLibrary.selectedEntry;
private readonly appI18n = inject(AppI18nService);
private llmGuideCopyTimeoutId: ReturnType<typeof setTimeout> | null = null;
constructor() {
@@ -485,6 +531,26 @@ export class ThemeSettingsComponent {
return (this.mountedKeyCounts()[entry.key] ?? 0) > 0;
}
presetDisplayName(presetKey: string, fallbackName: string): string {
const localized = this.appI18n.instant(`theme.presets.${presetKey}.name`);
return localized === `theme.presets.${presetKey}.name` ? fallbackName : localized;
}
presetDescription(presetKey: string, fallbackDescription?: string): string | undefined {
if (!fallbackDescription) {
return undefined;
}
const localized = this.appI18n.instant(`theme.presets.${presetKey}.description`);
return localized === `theme.presets.${presetKey}.description` ? fallbackDescription : localized;
}
isDefaultPresetName(name: string): boolean {
return name === this.appI18n.instant('theme.presets.toju-default-dark-11.name');
}
private focusEditor(): void {
this.withEditorReady((editor) => {
editor.focus();
@@ -815,26 +881,6 @@ export class ThemeSettingsComponent {
}, 4000);
}
presetDisplayName(presetKey: string, fallbackName: string): string {
const localized = this.appI18n.instant(`theme.presets.${presetKey}.name`);
return localized === `theme.presets.${presetKey}.name` ? fallbackName : localized;
}
presetDescription(presetKey: string, fallbackDescription?: string): string | undefined {
if (!fallbackDescription) {
return undefined;
}
const localized = this.appI18n.instant(`theme.presets.${presetKey}.description`);
return localized === `theme.presets.${presetKey}.description` ? fallbackDescription : localized;
}
isDefaultPresetName(name: string): boolean {
return name === this.appI18n.instant('theme.presets.toju-default-dark-11.name');
}
private localizeRegistryEntry(entry: ThemeRegistryEntry): ThemeRegistryEntry {
return {
...entry,
@@ -853,4 +899,5 @@ export class ThemeSettingsComponent {
return text.indexOf(`"${key}"`, sectionIndex);
}
}