-
- ${item.file.name}
-
-
- ${item.newName}
+
+
+ ${item.file.name}
+
${statusBadge}
+
+ ${item.newName}
+ ${conflictHint}
+
${
- item.error
- ? html`
${item.error}
`
+ errorText
+ ? html`
${errorText}
`
: ''
}
@@ -232,10 +250,16 @@ export class VirtualPreviewList extends LitElement {
min-width: 0;
}
+ .old-name-row {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ margin-bottom: 4px;
+ }
+
.old-name {
font-size: 12px;
color: var(--cdr-text-secondary, #595959);
- margin-bottom: 4px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
@@ -253,6 +277,14 @@ export class VirtualPreviewList extends LitElement {
gap: 8px;
}
+ .new-name-text {
+ flex: 1;
+ min-width: 0;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+
.new-name.conflict {
color: var(--cdr-warning-text, #fa8c16);
}
@@ -269,6 +301,12 @@ export class VirtualPreviewList extends LitElement {
color: var(--cdr-text-secondary, #595959);
}
+ .conflict-hint {
+ font-size: 12px;
+ color: var(--cdr-warning-text, #fa8c16);
+ flex-shrink: 0;
+ }
+
.error-message {
margin-top: 4px;
font-size: 12px;
diff --git a/tests/unit/virtual-preview-list.test.ts b/tests/unit/virtual-preview-list.test.ts
index 0d08077..a89c337 100644
--- a/tests/unit/virtual-preview-list.test.ts
+++ b/tests/unit/virtual-preview-list.test.ts
@@ -1,5 +1,6 @@
import { describe, expect, it } from 'vitest';
import { VirtualPreviewList } from '../../src/content/components/virtual-preview-list';
+import { I18nService } from '../../src/utils/i18n';
describe('VirtualPreviewList pending preview mapping', () => {
it('renders original name and new name for a pending preview item', async () => {
@@ -29,4 +30,92 @@ describe('VirtualPreviewList pending preview mapping', () => {
element.remove();
});
+
+ it('renders conflict items with status badge and helper text', async () => {
+ const element = new VirtualPreviewList();
+ element.items = [
+ {
+ file: {
+ id: 'file-conflict',
+ name: 'old-conflict.mkv',
+ ext: 'mkv',
+ size: 1,
+ mtime: Date.now(),
+ isDir: false,
+ },
+ newName: 'new-conflict.mkv',
+ conflict: true,
+ done: false,
+ },
+ ];
+
+ document.body.appendChild(element);
+ await element.updateComplete;
+
+ const textContent = element.shadowRoot?.textContent ?? '';
+ expect(textContent).toContain('old-conflict.mkv');
+ expect(textContent).toContain('new-conflict.mkv');
+ expect(textContent).toContain(I18nService.t('preview_badge_conflict'));
+ expect(textContent).toContain(I18nService.t('error_api_conflict'));
+
+ const badge = element.shadowRoot?.querySelector('.old-name-row .status-badge.conflict');
+ expect(badge).toBeTruthy();
+
+ element.remove();
+ });
+
+ it('shows localized extract_episode_not_found message instead of raw error key', async () => {
+ const element = new VirtualPreviewList();
+ element.items = [
+ {
+ file: {
+ id: 'file-error',
+ name: 'old-error.mkv',
+ ext: 'mkv',
+ size: 1,
+ mtime: Date.now(),
+ isDir: false,
+ },
+ newName: 'new-error.mkv',
+ conflict: false,
+ error: 'extract_episode_not_found',
+ },
+ ];
+
+ document.body.appendChild(element);
+ await element.updateComplete;
+
+ const textContent = element.shadowRoot?.textContent ?? '';
+ expect(textContent).toContain(I18nService.t('error_extract_episode_not_found'));
+
+ element.remove();
+ });
+
+ it('keeps pending badge next to old name row when showStatus is true', async () => {
+ const element = new VirtualPreviewList();
+ element.showStatus = true;
+ element.items = [
+ {
+ file: {
+ id: 'file-pending',
+ name: 'old-pending.mkv',
+ ext: 'mkv',
+ size: 1,
+ mtime: Date.now(),
+ isDir: false,
+ },
+ newName: 'new-pending.mkv',
+ conflict: false,
+ done: false,
+ },
+ ];
+
+ document.body.appendChild(element);
+ await element.updateComplete;
+
+ const badge = element.shadowRoot?.querySelector('.old-name-row .status-badge.pending');
+ expect(badge).toBeTruthy();
+
+ element.remove();
+ });
});