From 02f4deebe5d70fd846b3d7563daa6fd4cef827d1 Mon Sep 17 00:00:00 2001 From: Tim Haasdyk Date: Wed, 22 Jan 2025 17:35:14 +0100 Subject: [PATCH] Integrate PR feedback --- .../viewer/src/lib/DictionaryEntry.svelte | 51 +++++------------- .../object-editors/SenseEditor.svelte | 2 +- frontend/viewer/src/lib/parts-of-speech.ts | 5 +- .../viewer/src/lib/writing-system-service.ts | 52 +++++++++++++++++-- 4 files changed, 64 insertions(+), 46 deletions(-) diff --git a/frontend/viewer/src/lib/DictionaryEntry.svelte b/frontend/viewer/src/lib/DictionaryEntry.svelte index f7d833838..52cc99a7e 100644 --- a/frontend/viewer/src/lib/DictionaryEntry.svelte +++ b/frontend/viewer/src/lib/DictionaryEntry.svelte @@ -1,16 +1,3 @@ -
@@ -49,7 +22,7 @@ {#each headwords as {ws, value}, i} {#if value} {#if i > 0}/{/if} - {value} + {value} {/if} {/each} @@ -63,32 +36,32 @@ {partOfSpeech} {/if} - {#each writingSystemService.analysis as ws} + {#each wsService.analysis as ws} {#if sense.gloss[ws.wsId] || sense.definition[ws.wsId]} {ws.abbreviation} {#if sense.gloss[ws.wsId]} - {sense.gloss[ws.wsId]}; + {sense.gloss[ws.wsId]}; {/if} {#if sense.definition[ws.wsId]} - {sense.definition[ws.wsId]} + {sense.definition[ws.wsId]} {/if} {/if} {/each} {#each sense.exampleSentences as example (example.id)} - {@const usedVernacular = writingSystemService.vernacular.filter(ws => !!example.sentence[ws.wsId])} - {@const usedAnalysis = writingSystemService.analysis.filter(ws => !!example.translation[ws.wsId])} + {@const usedVernacular = wsService.vernacular.filter(ws => !!example.sentence[ws.wsId])} + {@const usedAnalysis = wsService.analysis.filter(ws => !!example.translation[ws.wsId])} {#if usedVernacular.length || usedAnalysis.length} [ {#each usedVernacular as ws} - {example.sentence[ws.wsId]} + {example.sentence[ws.wsId]} {/each} {#each usedAnalysis as ws} - {example.translation[ws.wsId]} + {example.translation[ws.wsId]} {/each} ] diff --git a/frontend/viewer/src/lib/entry-editor/object-editors/SenseEditor.svelte b/frontend/viewer/src/lib/entry-editor/object-editors/SenseEditor.svelte index 2350c07fc..867b2a081 100644 --- a/frontend/viewer/src/lib/entry-editor/object-editors/SenseEditor.svelte +++ b/frontend/viewer/src/lib/entry-editor/object-editors/SenseEditor.svelte @@ -12,7 +12,7 @@ export let sense: ISense; export let readonly: boolean = false; const writingSystemService = useWritingSystemService(); - const partsOfSpeech = usePartsOfSpeech(writingSystemService); + const partsOfSpeech = usePartsOfSpeech(); const semanticDomains = useSemanticDomains(); const currentView = useCurrentView(); diff --git a/frontend/viewer/src/lib/parts-of-speech.ts b/frontend/viewer/src/lib/parts-of-speech.ts index 79c7e56c3..400bbc714 100644 --- a/frontend/viewer/src/lib/parts-of-speech.ts +++ b/frontend/viewer/src/lib/parts-of-speech.ts @@ -1,13 +1,14 @@ import {derived, type Readable, type Writable, writable} from 'svelte/store'; import type {IPartOfSpeech} from '$lib/dotnet-types'; import {useLexboxApi} from './services/service-provider'; -import type {WritingSystemService} from './writing-system-service'; +import {useWritingSystemService} from './writing-system-service'; type LabeledPartOfSpeech = IPartOfSpeech & {label: string}; let partsOfSpeechStore: Writable | null = null; -export function usePartsOfSpeech(writingSystemService: WritingSystemService): Readable { +export function usePartsOfSpeech(): Readable { + const writingSystemService = useWritingSystemService(); if (partsOfSpeechStore === null) { partsOfSpeechStore = writable([], (set) => { useLexboxApi().getPartsOfSpeech().then(partsOfSpeech => { diff --git a/frontend/viewer/src/lib/writing-system-service.ts b/frontend/viewer/src/lib/writing-system-service.ts index 2324349a3..cfcb67322 100644 --- a/frontend/viewer/src/lib/writing-system-service.ts +++ b/frontend/viewer/src/lib/writing-system-service.ts @@ -1,5 +1,5 @@ import type {IEntry, IExampleSentence, IMultiString, ISense, IWritingSystem, IWritingSystems} from '$lib/dotnet-types'; -import {getContext, setContext} from 'svelte'; +import {getContext, onDestroy, setContext} from 'svelte'; import {derived, get, type Readable} from 'svelte/store'; import type {WritingSystemSelection} from './config-types'; import {firstTruthy} from './utils'; @@ -14,12 +14,20 @@ export function useWritingSystemService(): WritingSystemService { if (!writingSystemServiceContext) throw new Error('Writing system context is not initialized. Are you in the context of a project?'); const writingSystemService = get(writingSystemServiceContext); if (!writingSystemService) throw new Error('Writing system service is not initialized.'); + const unsub = writingSystemServiceContext.subscribe((service) => { + if (service !== writingSystemService) console.warn('Writing system service changed unexpectedly.'); + }); + onDestroy(unsub); return writingSystemService; } export class WritingSystemService { - constructor(private readonly writingSystems: IWritingSystems) { } + private readonly wsColors: WritingSystemColors; + + constructor(private readonly writingSystems: IWritingSystems) { + this.wsColors = calcWritingSystemColors(writingSystems); + } allWritingSystems(selection: Extract = 'vernacular-analysis'): IWritingSystem[] { return this.pickWritingSystems(selection); @@ -47,9 +55,9 @@ export class WritingSystemService { ws = ws ?? 'vernacular-analysis'; switch (ws) { case 'vernacular-analysis': - return [...new Set([...this.writingSystems.vernacular, ...this.writingSystems.analysis].sort())]; + return [...this.writingSystems.vernacular, ...this.writingSystems.analysis]; case 'analysis-vernacular': - return [...new Set([...this.writingSystems.analysis, ...this.writingSystems.vernacular].sort())]; + return [...this.writingSystems.analysis, ...this.writingSystems.vernacular]; case 'first-analysis': return [this.writingSystems.analysis[0]]; case 'first-vernacular': @@ -129,7 +137,43 @@ export class WritingSystemService { return this.first(example.sentence, this.vernacular) || this.first(example.translation, this.analysis) || ''; } + wsColor(ws: string, type: 'vernacular' | 'analysis'): string { + const colors = this.wsColors[type]; + return colors[ws]; + } + private first(value: IMultiString, writingSystems: IWritingSystem[]): string | undefined { return firstTruthy(writingSystems, ws => value[ws.wsId]); } } + +type WritingSystemColors = { + vernacular: Record; + analysis: Record; +} + +function calcWritingSystemColors(writingSystems: IWritingSystems): WritingSystemColors { + const wsColors = { + vernacular: {} as Record, + analysis: {} as Record, + }; + writingSystems.vernacular.forEach((ws, i) => { + wsColors.vernacular[ws.wsId] = vernacularColors[i % vernacularColors.length]; + }); + writingSystems.analysis.forEach((ws, i) => { + wsColors.analysis[ws.wsId] = analysisColors[i % analysisColors.length]; + }); + return wsColors; +} + +const vernacularColors = [ + 'text-emerald-400 dark:text-emerald-300', + 'text-fuchsia-600 dark:text-fuchsia-300', + 'text-lime-600 dark:text-lime-200', +] as const; + +const analysisColors = [ + 'text-blue-500 dark:text-blue-300', + 'text-yellow-500 dark:text-yellow-200', + 'text-rose-500 dark:text-rose-400', +] as const;