Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/i18n/locales/de-DE.ts
Original file line number Diff line number Diff line change
Expand Up @@ -977,6 +977,11 @@ export const deDE: LanguagePack = {
'ui.pictureEmptyReadyHint':
'Drücken Sie Enter oder klicken Sie auf Vergleichen, um diese Bilder zu vergleichen.',
'ui.pictureIdenticalHint': 'Diese Bilder stimmen überein. Keine Pixelunterschiede.',
'ui.textEditEmptyHint':
'Wählen Sie eine Datei mit Durchsuchen (oder fügen Sie einen Pfad ein), dann auf Öffnen klicken.',
'ui.textEditEmptyReadyHint':
'Drücken Sie Enter oder klicken Sie auf Öffnen, um diese Datei zu laden.',
'ui.textEditNeedsPath': 'Wählen Sie zuerst einen Dateipfad.',
'ui.registryExportHint':
'Compare exported .reg files, offline REGF hive files (SYSTEM/SOFTWARE/NTUSER.DAT), or live HKLM/HKCU keys on Windows.',
'ui.nextConflict': 'Next Conflict',
Expand Down
5 changes: 4 additions & 1 deletion src/i18n/locales/en-US.ts
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ export const enUS: LanguagePack = {
'ui.off': 'Off',
'ui.open': 'Open',
'ui.openAll': 'Open All',
'ui.openATextFileToBeginEditing': 'Open a text file to begin editing',
'ui.openATextFileToBeginEditing': 'Browse or paste a path, then Open to begin editing',
'ui.openClipboard': 'Open Clipboard',
'ui.openSuggestedView': 'Open Suggested View',
'ui.openTextMerge': 'Open Text Merge',
Expand Down Expand Up @@ -945,6 +945,9 @@ export const enUS: LanguagePack = {
'Choose left and right images with Browse (or paste paths), then click Compare.',
'ui.pictureEmptyReadyHint': 'Press Enter or click Compare to compare these images.',
'ui.pictureIdenticalHint': 'These images match. No pixel differences to show.',
'ui.textEditEmptyHint': 'Choose a file with Browse (or paste a path), then click Open.',
'ui.textEditEmptyReadyHint': 'Press Enter or click Open to load this file.',
'ui.textEditNeedsPath': 'Choose a file path first.',
'ui.registryExportHint':
'Compare exported .reg files, offline REGF hive files (SYSTEM/SOFTWARE/NTUSER.DAT), or live HKLM/HKCU keys on Windows.',
'ui.nextConflict': 'Next Conflict',
Expand Down
6 changes: 5 additions & 1 deletion src/i18n/locales/es-ES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ export const esES: LanguagePack = {
'ui.onedrive': 'OneDrive',
'ui.open': 'Abrir',
'ui.openAll': 'Abrir todo',
'ui.openATextFileToBeginEditing': 'Abra un archivo de texto para comenzar a editar',
'ui.openATextFileToBeginEditing': 'Examinar o pegar una ruta, luego Abrir para editar',
'ui.openClipboard': 'Abrir portapapeles',
'ui.openSuggestedView': 'Abrir vista sugerida',
'ui.openTextMerge': 'Abrir combinación de texto',
Expand Down Expand Up @@ -964,6 +964,10 @@ export const esES: LanguagePack = {
'Elija las imágenes izquierda y derecha con Examinar (o pegue rutas) y luego haga clic en Comparar.',
'ui.pictureEmptyReadyHint': 'Pulse Intro o haga clic en Comparar para comparar estas imágenes.',
'ui.pictureIdenticalHint': 'Estas imágenes coinciden. No hay diferencias de píxeles.',
'ui.textEditEmptyHint':
'Elija un archivo con Examinar (o pegue una ruta) y luego haga clic en Abrir.',
'ui.textEditEmptyReadyHint': 'Pulse Intro o haga clic en Abrir para cargar este archivo.',
'ui.textEditNeedsPath': 'Elija primero una ruta de archivo.',
'ui.registryExportHint':
'Compare exported .reg files, offline REGF hive files (SYSTEM/SOFTWARE/NTUSER.DAT), or live HKLM/HKCU keys on Windows.',
'ui.nextConflict': 'Next Conflict',
Expand Down
7 changes: 6 additions & 1 deletion src/i18n/locales/fr-FR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ export const frFR: LanguagePack = {
'ui.onedrive': 'OneDrive',
'ui.open': 'Ouvrir',
'ui.openAll': 'Tout ouvrir',
'ui.openATextFileToBeginEditing': "Ouvrez un fichier texte pour commencer l'édition",
'ui.openATextFileToBeginEditing': 'Parcourir ou coller un chemin, puis Ouvrir pour modifier',
'ui.openClipboard': 'Ouvrir le Presse-papiers',
'ui.openSuggestedView': 'Ouvrir la vue suggérée',
'ui.openTextMerge': 'Ouvrir la fusion de texte',
Expand Down Expand Up @@ -970,6 +970,11 @@ export const frFR: LanguagePack = {
'ui.pictureEmptyReadyHint':
'Appuyez sur Entrée ou cliquez sur Comparer pour comparer ces images.',
'ui.pictureIdenticalHint': 'Ces images correspondent. Aucune différence de pixel.',
'ui.textEditEmptyHint':
'Choisissez un fichier avec Parcourir (ou collez un chemin), puis cliquez sur Ouvrir.',
'ui.textEditEmptyReadyHint':
'Appuyez sur Entrée ou cliquez sur Ouvrir pour charger ce fichier.',
'ui.textEditNeedsPath': "Choisissez d'abord un chemin de fichier.",
'ui.registryExportHint':
'Compare exported .reg files, offline REGF hive files (SYSTEM/SOFTWARE/NTUSER.DAT), or live HKLM/HKCU keys on Windows.',
'ui.nextConflict': 'Next Conflict',
Expand Down
5 changes: 4 additions & 1 deletion src/i18n/locales/ja-JP.ts
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ export const jaJP: LanguagePack = {
'ui.off': 'Off',
'ui.open': 'Open',
'ui.openAll': 'Open All',
'ui.openATextFileToBeginEditing': 'Open a text file to begin editing',
'ui.openATextFileToBeginEditing': 'Browse or paste a path, then Open to begin editing',
'ui.openClipboard': 'Open Clipboard',
'ui.openSuggestedView': 'Open Suggested View',
'ui.openTextMerge': 'Open Text Merge',
Expand Down Expand Up @@ -945,6 +945,9 @@ export const jaJP: LanguagePack = {
'Choose left and right images with Browse (or paste paths), then click Compare.',
'ui.pictureEmptyReadyHint': 'Press Enter or click Compare to compare these images.',
'ui.pictureIdenticalHint': 'These images match. No pixel differences to show.',
'ui.textEditEmptyHint': 'Choose a file with Browse (or paste a path), then click Open.',
'ui.textEditEmptyReadyHint': 'Press Enter or click Open to load this file.',
'ui.textEditNeedsPath': 'Choose a file path first.',
'ui.registryExportHint':
'Compare exported .reg files, offline REGF hive files (SYSTEM/SOFTWARE/NTUSER.DAT), or live HKLM/HKCU keys on Windows.',
'ui.nextConflict': 'Next Conflict',
Expand Down
5 changes: 4 additions & 1 deletion src/i18n/locales/ko-KR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ export const koKR: LanguagePack = {
'ui.onedrive': 'OneDrive',
'ui.open': '열기',
'ui.openAll': '모두 열기',
'ui.openATextFileToBeginEditing': '편집을 시작하려면 텍스트 파일을 여세요.',
'ui.openATextFileToBeginEditing': '찾아보거나 경로를 붙여넣은 다음 열기로 편집을 시작하세요',
'ui.openClipboard': '클립보드 열기',
'ui.openSuggestedView': '추천 보기 열기',
'ui.openTextMerge': '텍스트 병합 열기',
Expand Down Expand Up @@ -938,6 +938,9 @@ export const koKR: LanguagePack = {
'찾아보기로 왼쪽·오른쪽 이미지를 선택하거나 경로를 붙여넣은 다음 비교를 클릭하세요.',
'ui.pictureEmptyReadyHint': 'Enter를 누르거나 비교를 클릭해 이미지를 비교하세요.',
'ui.pictureIdenticalHint': '이미지가 일치합니다. 픽셀 차이가 없습니다.',
'ui.textEditEmptyHint': '찾아보기로 파일을 선택하거나 경로를 붙여넣은 다음 열기를 클릭하세요.',
'ui.textEditEmptyReadyHint': 'Enter를 누르거나 열기를 클릭해 이 파일을 불러오세요.',
'ui.textEditNeedsPath': '먼저 파일 경로를 선택하세요.',
'ui.registryExportHint':
'Compare exported .reg files, offline REGF hive files (SYSTEM/SOFTWARE/NTUSER.DAT), or live HKLM/HKCU keys on Windows.',
'ui.nextConflict': 'Next Conflict',
Expand Down
5 changes: 4 additions & 1 deletion src/i18n/locales/zh-CN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ export const zhCN: LanguagePack = {
'ui.onedrive': 'OneDrive',
'ui.open': '打开',
'ui.openAll': '全部打开',
'ui.openATextFileToBeginEditing': '打开文本文件开始编辑',
'ui.openATextFileToBeginEditing': '浏览或粘贴路径,然后点打开开始编辑',
'ui.openClipboard': '打开剪贴板',
'ui.openSuggestedView': '打开建议视图',
'ui.openTextMerge': '打开文本合并',
Expand Down Expand Up @@ -906,6 +906,9 @@ export const zhCN: LanguagePack = {
'ui.pictureEmptyCompareHint': '用浏览选择左右图像(或粘贴路径),然后点比较。',
'ui.pictureEmptyReadyHint': '按 Enter 或点比较以比较这些图像。',
'ui.pictureIdenticalHint': '这些图像一致。没有像素差异。',
'ui.textEditEmptyHint': '用浏览选择文件(或粘贴路径),然后点打开。',
'ui.textEditEmptyReadyHint': '按 Enter 或点打开以加载此文件。',
'ui.textEditNeedsPath': '请先选择文件路径。',
'ui.registryExportHint':
'可比较导出的 .reg、离线 REGF 配置单元(SYSTEM/SOFTWARE/NTUSER.DAT),或在 Windows 上比较实时 HKLM/HKCU 键。',
'ui.nextConflict': '下一冲突',
Expand Down
5 changes: 4 additions & 1 deletion src/i18n/locales/zh-TW.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ export const zhTW: LanguagePack = {
'ui.onedrive': 'OneDrive',
'ui.open': '開啟',
'ui.openAll': '全部開啟',
'ui.openATextFileToBeginEditing': '開啟文字檔開始編輯',
'ui.openATextFileToBeginEditing': '瀏覽或貼上路徑,然後按開啟開始編輯',
'ui.openClipboard': '開啟剪貼簿',
'ui.openSuggestedView': '開啟建議檢視',
'ui.openTextMerge': '開啟文字合併',
Expand Down Expand Up @@ -908,6 +908,9 @@ export const zhTW: LanguagePack = {
'ui.pictureEmptyCompareHint': '用瀏覽選擇左右影像(或貼上路徑),然後按比較。',
'ui.pictureEmptyReadyHint': '按 Enter 或點比較以比較這些影像。',
'ui.pictureIdenticalHint': '這些影像一致。沒有像素差異。',
'ui.textEditEmptyHint': '用瀏覽選擇檔案(或貼上路徑),然後按開啟。',
'ui.textEditEmptyReadyHint': '按 Enter 或點開啟以載入此檔案。',
'ui.textEditNeedsPath': '請先選擇檔案路徑。',
'ui.registryExportHint':
'可比較匯出的 .reg、離線 REGF 登錄檔(SYSTEM/SOFTWARE/NTUSER.DAT),或在 Windows 上比較即時 HKLM/HKCU 鍵。',
'ui.nextConflict': '下一衝突',
Expand Down
4 changes: 2 additions & 2 deletions src/styles/textEditChromeDensity.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ describe('text-edit path-meta border', () => {
})

describe('text edit path meta format chip', () => {
it('shows Text Edit path meta format chip as Everything Else', () => {
expect(editView).toMatch(/format-label="Everything Else"/)
it('shows Text Edit path meta format chip as Text', () => {
expect(editView).toMatch(/:format-label="\$t\('ui\.text'\)"/)
})
})
31 changes: 31 additions & 0 deletions src/views/TextEditView.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,37 @@ describe('TextEditView', () => {
).toBeUndefined()
})

it('shows a friendly empty state and path placeholder before open', async () => {
const wrapper = mountTextEditView()

expect(wrapper.find('[data-testid="text-edit-empty-hint"]').text()).toContain(
'Choose a file with Browse',
)
expect(wrapper.find('[data-testid="text-edit-path"]').attributes('placeholder')).toContain(
'Browse or paste a file path',
)
expect(wrapper.find('[data-testid="text-edit-open"]').attributes('title')).toContain(
'file path first',
)
expect(wrapper.text()).toContain('Text')

await wrapper.find('[data-testid="text-edit-path"]').setValue('D:/workspace/notes.txt')
expect(wrapper.find('[data-testid="text-edit-empty-hint"]').text()).toContain('Open')
expect(wrapper.find('[data-testid="text-edit-open"]').attributes('disabled')).toBeUndefined()
})

it('opens the file on Enter when a path is set', async () => {
const wrapper = mountTextEditView()

await wrapper.find('[data-testid="text-edit-path"]').setValue('D:/workspace/notes.txt')
await wrapper.find('[data-testid="text-edit-path"]').trigger('keydown.enter')
await flushPromises()

expect(readTextFile).toHaveBeenCalledWith('D:/workspace/notes.txt')
expect(wrapper.find('[data-testid="text-edit-empty-hint"]').exists()).toBe(false)
expect(wrapper.find('[data-testid="text-edit-editor"]').element).toBeTruthy()
})

it('opens a text file and shows metadata for the loaded document', async () => {
const wrapper = mountTextEditView()

Expand Down
52 changes: 45 additions & 7 deletions src/views/TextEditView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { useTabsStore } from '@/stores/tabs'
import { useSettingsStore, type FontFamilyId } from '@/stores/settings'
import { useStatusBarStore } from '@/stores/statusBar'
import { elapsedSecondsSince } from '@/app/statusBarPhrases'
import { formatCompareError } from '@/app/compareError'
import {
applyOverwriteTyping,
isInsertToggleKey,
Expand Down Expand Up @@ -99,6 +100,28 @@ const fileTitle = computed(() => {
const dirty = computed(() => editorText.value !== savedText.value)
const dirtyLabel = computed(() => (dirty.value ? t('status.unsavedChanges') : t('status.saved')))

const openNeedsPath = computed(() => !pathInput.value.trim())

const textEditEmptyStateMessage = computed(() => {
if (document.value) {
return ''
}

if (pathInput.value.trim()) {
return t('ui.textEditEmptyReadyHint')
}

return t('ui.textEditEmptyHint')
})

function onTextEditPathEnter(): void {
if (openNeedsPath.value || loading.value) {
return
}

void openDocument()
}

watchEffect(() => {
let comparisonStatus = t('status.noDocumentLoaded')

Expand Down Expand Up @@ -177,13 +200,17 @@ async function browseTextEditPath(): Promise<void> {
}

async function openDocument(): Promise<void> {
if (!pathInput.value.trim()) {
return
}

const startedAt = performance.now()

loading.value = true
error.value = ''

try {
const result = await readTextFile(pathInput.value)
const result = await readTextFile(pathInput.value.trim())

document.value = result
loadTimeSeconds.value = elapsedSecondsSince(startedAt)
Expand All @@ -194,7 +221,7 @@ async function openDocument(): Promise<void> {
setSaveStatus('status.loaded')
currentFindIndex.value = 0
} catch (event) {
error.value = String(event)
error.value = formatCompareError(event, t)
} finally {
loading.value = false
}
Expand Down Expand Up @@ -237,7 +264,7 @@ async function saveDocument(): Promise<void> {
count: result.bytesWritten,
})
} catch (event) {
error.value = String(event)
error.value = formatCompareError(event, t)
} finally {
saving.value = false
}
Expand Down Expand Up @@ -993,8 +1020,10 @@ const textEditToolbarCommands = computed(() => {
class="path-input"
data-testid="text-edit-path"
type="text"
:title="pathInput"
:title="pathInput || $t('ui.remoteUriHint')"
:placeholder="$t('ui.textPathPlaceholder')"
:aria-label="$t('ui.textFilePath')"
@keydown.enter.prevent="onTextEditPathEnter"
/>
<SessionPathActions
browse-test-id="text-edit-browse"
Expand All @@ -1007,9 +1036,9 @@ const textEditToolbarCommands = computed(() => {
type="button"
class="bc-path-load"
data-testid="text-edit-open"
:disabled="loading || !pathInput"
:disabled="loading || openNeedsPath"
:aria-label="$t('ui.open')"
:title="$t('ui.open')"
:title="openNeedsPath ? $t('ui.textEditNeedsPath') : $t('ui.open')"
@click="openDocument"
>
{{ $t('ui.open') }}
Expand All @@ -1027,7 +1056,7 @@ const textEditToolbarCommands = computed(() => {
>
<PathMetaFooter
:stamp="document?.fileStamp ?? null"
format-label="Everything Else"
:format-label="$t('ui.text')"
:encoding="document?.encoding"
:line-ending="document?.lineEnding"
:show-milliseconds="settings.showMillisecondsInTimestamps"
Expand Down Expand Up @@ -1092,10 +1121,19 @@ const textEditToolbarCommands = computed(() => {
<NAlert
v-if="error"
type="error"
data-testid="text-edit-error"
:bordered="false"
>{{ error }}</NAlert
>

<p
v-if="!document && !error"
class="empty"
data-testid="text-edit-empty-hint"
>
{{ textEditEmptyStateMessage }}
</p>

<div
ref="editorHostRef"
class="editor-host"
Expand Down
Loading