diff --git a/src/components/AudioCell.vue b/src/components/AudioCell.vue index 17fa418f03..c515547309 100644 --- a/src/components/AudioCell.vue +++ b/src/components/AudioCell.vue @@ -7,6 +7,13 @@ size="sm" class="absolute active-arrow" /> +
+ {{ textLineNumberIndex }} +
{ } }; +// 行番号を表示するかどうか +const showTextLineNumber = computed(() => store.state.showTextLineNumber); +// 行番号 +const textLineNumberIndex = computed( + () => audioKeys.value.indexOf(props.audioKey) + 1 +); +// 行番号の幅: 2桁はデフォで入るように, 3桁以上は1remずつ広げる +const textLineNumberWidth = computed(() => { + const indexDigits = String(audioKeys.value.length).length; + if (indexDigits <= 2) return "1.5rem"; + return `${indexDigits - 0.5}rem`; +}); + // 上下に移動 const audioKeys = computed(() => store.state.audioKeys); const moveUpCell = (e?: KeyboardEvent) => { @@ -275,6 +295,21 @@ const isMultipleEngine = computed(() => store.state.engineIds.length > 1); height: 2rem; } + .line-number { + height: 2rem; + width: v-bind(textLineNumberWidth); + line-height: 2rem; + margin-right: -0.3rem; + opacity: 0.6; + text-align: right; + color: colors.$display; + &.active { + opacity: 1; + font-weight: bold; + color: colors.$primary-light; + } + } + .q-input { :deep(.q-field__control) { height: 2rem; diff --git a/src/components/SettingDialog.vue b/src/components/SettingDialog.vue index 336cdf32d9..e01a5d7556 100644 --- a/src/components/SettingDialog.vue +++ b/src/components/SettingDialog.vue @@ -527,6 +527,28 @@ ]" /> + +
行番号の表示
+
+ + + テキスト欄の左側に行番号を表示します。 + + +
+ + + +
@@ -823,6 +845,7 @@ const activePointScrollModeOptions: Record< const experimentalSetting = computed(() => store.state.experimentalSetting); +// 外観 const currentThemeNameComputed = computed({ get: () => store.state.themeSetting.currentTheme, set: (currentTheme: string) => { @@ -838,6 +861,18 @@ const availableThemeNameComputed = computed(() => { }); }); +const editorFont = computed(() => store.state.editorFont); +const changeEditorFont = (editorFont: EditorFontType) => { + store.dispatch("SET_EDITOR_FONT", { editorFont }); +}; + +const showTextLineNumber = computed(() => store.state.showTextLineNumber); +const changeShowTextLineNumber = (showTextLineNumber: boolean) => { + store.dispatch("SET_SHOW_TEXT_LINE_NUMBER", { + showTextLineNumber, + }); +}; + const currentAudioOutputDeviceComputed = computed<{ key: string; label: string; @@ -1042,11 +1077,6 @@ const changeSplitTextWhenPaste = ( store.dispatch("SET_SPLIT_TEXT_WHEN_PASTE", { splitTextWhenPaste }); }; -const editorFont = computed(() => store.state.editorFont); -const changeEditorFont = (editorFont: EditorFontType) => { - store.dispatch("SET_EDITOR_FONT", { editorFont }); -}; - const showsFilePatternEditDialog = ref(false); const selectedEngineIdRaw = ref(undefined); diff --git a/src/store/setting.ts b/src/store/setting.ts index e9e0df87ce..a463d00074 100644 --- a/src/store/setting.ts +++ b/src/store/setting.ts @@ -40,6 +40,7 @@ export const settingStoreState: SettingStoreState = { availableThemes: [], }, editorFont: "default", + showTextLineNumber: false, acceptRetrieveTelemetry: "Unconfirmed", experimentalSetting: { enablePreset: false, @@ -82,6 +83,12 @@ export const settingStore = createPartialStore({ }); } + dispatch("SET_SHOW_TEXT_LINE_NUMBER", { + showTextLineNumber: await window.electron.getSetting( + "showTextLineNumber" + ), + }); + dispatch("SET_ACCEPT_RETRIEVE_TELEMETRY", { acceptRetrieveTelemetry: await window.electron.getSetting( "acceptRetrieveTelemetry" @@ -252,6 +259,18 @@ export const settingStore = createPartialStore({ }, }, + SET_SHOW_TEXT_LINE_NUMBER: { + mutation(state, { showTextLineNumber }) { + state.showTextLineNumber = showTextLineNumber; + }, + action({ commit }, { showTextLineNumber }) { + window.electron.setSetting("showTextLineNumber", showTextLineNumber); + commit("SET_SHOW_TEXT_LINE_NUMBER", { + showTextLineNumber, + }); + }, + }, + SET_ACCEPT_RETRIEVE_TELEMETRY: { mutation(state, { acceptRetrieveTelemetry }) { state.acceptRetrieveTelemetry = acceptRetrieveTelemetry; diff --git a/src/store/type.ts b/src/store/type.ts index 88034e8c27..1833f467ac 100644 --- a/src/store/type.ts +++ b/src/store/type.ts @@ -998,6 +998,7 @@ export type SettingStoreState = { engineManifests: Record; themeSetting: ThemeSetting; editorFont: EditorFontType; + showTextLineNumber: boolean; acceptRetrieveTelemetry: AcceptRetrieveTelemetryStatus; experimentalSetting: ExperimentalSetting; splitTextWhenPaste: SplitTextWhenPasteType; @@ -1036,6 +1037,11 @@ export type SettingStoreTypes = { action(payload: { editorFont: EditorFontType }): void; }; + SET_SHOW_TEXT_LINE_NUMBER: { + mutation: { showTextLineNumber: boolean }; + action(payload: { showTextLineNumber: boolean }): void; + }; + SET_ACCEPT_RETRIEVE_TELEMETRY: { mutation: { acceptRetrieveTelemetry: AcceptRetrieveTelemetryStatus }; action(payload: { diff --git a/src/type/preload.ts b/src/type/preload.ts index 71ff3df43f..5337b79ccd 100644 --- a/src/type/preload.ts +++ b/src/type/preload.ts @@ -568,6 +568,7 @@ export const electronStoreSchema = z defaultPresetKeys: z.record(voiceIdSchema, presetKeySchema).default({}), currentTheme: z.string().default("Default"), editorFont: z.enum(["default", "os"]).default("default"), + showTextLineNumber: z.boolean().default(false), experimentalSetting: experimentalSettingSchema.passthrough().default({}), acceptRetrieveTelemetry: z .enum(["Unconfirmed", "Accepted", "Refused"]) diff --git a/tests/unit/store/Vuex.spec.ts b/tests/unit/store/Vuex.spec.ts index da9b166298..bbd54c9333 100644 --- a/tests/unit/store/Vuex.spec.ts +++ b/tests/unit/store/Vuex.spec.ts @@ -75,6 +75,7 @@ describe("store/vuex.js test", () => { availableThemes: [], }, editorFont: "default", + showTextLineNumber: false, isPinned: false, isFullscreen: false, presetItems: {}, @@ -241,6 +242,7 @@ describe("store/vuex.js test", () => { store.state.experimentalSetting.enableInterrogativeUpspeak, false ); + assert.equal(store.state.showTextLineNumber, false); assert.propertyVal( store.state.splitterPosition, "audioDetailPaneHeight",