feat(playlist): clean up selected inactive desktop sources (#1593) (#1596)

This commit is contained in:
4gray authored and GitHub committed 2026-09-13 10:39:14 +02:00
1 parent cbc918b096
commit bd848aaad6
53 files changed
+1980 -87

No files matched your search

@@ -1,3 +1,4 @@
import { SourceActivityService } from '@iptvnator/services';
import { TestBed } from '@angular/core/testing';
import { MatSnackBar } from '@angular/material/snack-bar';
import { Store } from '@ngrx/store';
@@ -108,6 +109,18 @@ describe('ElectronService', () => {
jest.restoreAllMocks();
});
it('protects all startup-refresh sources until the request settles, including failure', async () => {
let reject!: (error: Error) => void;
electronBridge.autoUpdatePlaylists.mockReturnValue(new Promise((_, r) => { reject = r; }));
const pending = service.sendIpcEvent(AUTO_UPDATE_PLAYLISTS, [{ _id: 'startup' }]);
const activity = TestBed.inject(SourceActivityService);
expect(activity.isBusy('startup')).toBe(true);
expect(activity.isBusy('other')).toBe(false);
reject(new Error('refresh failed'));
await expect(pending).rejects.toThrow('refresh failed');
expect(activity.isBusy('startup')).toBe(false);
});
it.each([401, 403])('preserves a health HTTP %s rejection without global error handling', async (status) => {
const error = new Error(`Error invoking remote method: Error: HTTP Error ${status}`);
electronBridge.xtreamRequest.mockRejectedValue(error);
+22 -12
View File
@@ -4,7 +4,11 @@ import { Store } from '@ngrx/store';
import { TranslateService } from '@ngx-translate/core';
import { PlaylistActions } from '@iptvnator/m3u-state';
import { DialogService } from '@iptvnator/ui/components';
import { DataService, SettingsStore } from '@iptvnator/services';
import {
DataService,
SettingsStore,
SourceActivityService,
} from '@iptvnator/services';
import {
AUTO_UPDATE_PLAYLISTS,
AutoUpdatePlaylistsResult,
@@ -57,6 +61,7 @@ interface ErrorStatus {
export class ElectronService extends DataService {
private eventListeners: { [key: string]: () => void } = {};
private messageListeners = new Map<string, EventListener>();
private readonly sourceActivity = inject(SourceActivityService);
private readonly snackBar = inject(MatSnackBar);
private readonly dialogService = inject(DialogService);
private readonly store = inject(Store);
@@ -237,17 +242,22 @@ export class ElectronService extends DataService {
if (type === AUTO_UPDATE_PLAYLISTS) {
const data = payload as Playlist[];
const result = await window.electron.autoUpdatePlaylists(
data,
this.settingsStore.getTrustOptions()
);
this.store.dispatch(
PlaylistActions.updateManyPlaylists({
playlists: result.playlists,
})
);
this.reportAutoUpdatePlaylistsResult(result);
return result as T;
const release = this.sourceActivity.begin(data.map((p) => p._id));
try {
const result = await window.electron.autoUpdatePlaylists(
data,
this.settingsStore.getTrustOptions()
);
this.store.dispatch(
PlaylistActions.updateManyPlaylists({
playlists: result.playlists,
})
);
this.reportAutoUpdatePlaylistsResult(result);
return result as T;
} finally {
release();
}
}
this.logger.debug('Unknown IPC event type:', type);
+27
View File
@@ -1807,5 +1807,32 @@
"cancelled": "Check cancelled",
"checking": "Checking…"
}
},
"SOURCE_CLEANUP": {
"TITLE": "Clean up inactive sources…",
"SCOPE": "All network sources in your library, regardless of page filters.",
"CONSEQUENCES": "Delete only sources you select. Their saved favourites, history and playback progress will also be removed. Downloaded files are kept.",
"SUMMARY": "Checked {{checked}}/{{total}} · Available {{available}} · Deleted {{deleted}} · Skipped {{skipped}} · Failed {{failed}}",
"SELECT_ALL": "Select all candidates",
"SELECT_NONE": "Deselect all",
"UNTITLED": "Untitled source",
"DELETE": "Delete selected · {{count}}",
"CLOSE": "Close",
"STOP": "Stop after current source",
"CLEANUP_WARNING": "Source deleted; some follow-up cleanup failed",
"GROUP": {
"confirmed": "Confirmed inactive accounts",
"uncertain": "Review before deleting",
"skipped": "Skipped sources",
"results": "Deletion results"
},
"STATUS": {
"checking": "Checking…",
"skipped": "Playing, busy, changed or no longer present",
"deleting": "Deleting…",
"deleted": "Deleted",
"failed": "Deletion failed — select to retry"
},
"DELETE_PROGRESS": "Processed {{done}} of {{total}} selected sources"
}
}
+27
View File
@@ -1807,5 +1807,32 @@
"cancelled": "Check cancelled",
"checking": "Checking…"
}
},
"SOURCE_CLEANUP": {
"TITLE": "Clean up inactive sources…",
"SCOPE": "All network sources in your library, regardless of page filters.",
"CONSEQUENCES": "Delete only sources you select. Their saved favourites, history and playback progress will also be removed. Downloaded files are kept.",
"SUMMARY": "Checked {{checked}}/{{total}} · Available {{available}} · Deleted {{deleted}} · Skipped {{skipped}} · Failed {{failed}}",
"SELECT_ALL": "Select all candidates",
"SELECT_NONE": "Deselect all",
"UNTITLED": "Untitled source",
"DELETE": "Delete selected · {{count}}",
"CLOSE": "Close",
"STOP": "Stop after current source",
"CLEANUP_WARNING": "Source deleted; some follow-up cleanup failed",
"GROUP": {
"confirmed": "Confirmed inactive accounts",
"uncertain": "Review before deleting",
"skipped": "Skipped sources",
"results": "Deletion results"
},
"STATUS": {
"checking": "Checking…",
"skipped": "Playing, busy, changed or no longer present",
"deleting": "Deleting…",
"deleted": "Deleted",
"failed": "Deletion failed — select to retry"
},
"DELETE_PROGRESS": "Processed {{done}} of {{total}} selected sources"
}
}
+27
View File
@@ -1807,5 +1807,32 @@
"cancelled": "Check cancelled",
"checking": "Checking…"
}
},
"SOURCE_CLEANUP": {
"TITLE": "Clean up inactive sources…",
"SCOPE": "All network sources in your library, regardless of page filters.",
"CONSEQUENCES": "Delete only sources you select. Their saved favourites, history and playback progress will also be removed. Downloaded files are kept.",
"SUMMARY": "Checked {{checked}}/{{total}} · Available {{available}} · Deleted {{deleted}} · Skipped {{skipped}} · Failed {{failed}}",
"SELECT_ALL": "Select all candidates",
"SELECT_NONE": "Deselect all",
"UNTITLED": "Untitled source",
"DELETE": "Delete selected · {{count}}",
"CLOSE": "Close",
"STOP": "Stop after current source",
"CLEANUP_WARNING": "Source deleted; some follow-up cleanup failed",
"GROUP": {
"confirmed": "Confirmed inactive accounts",
"uncertain": "Review before deleting",
"skipped": "Skipped sources",
"results": "Deletion results"
},
"STATUS": {
"checking": "Checking…",
"skipped": "Playing, busy, changed or no longer present",
"deleting": "Deleting…",
"deleted": "Deleted",
"failed": "Deletion failed — select to retry"
},
"DELETE_PROGRESS": "Processed {{done}} of {{total}} selected sources"
}
}
+27
View File
@@ -1807,5 +1807,32 @@
"cancelled": "Check cancelled",
"checking": "Checking…"
}
},
"SOURCE_CLEANUP": {
"TITLE": "Clean up inactive sources…",
"SCOPE": "All network sources in your library, regardless of page filters.",
"CONSEQUENCES": "Delete only sources you select. Their saved favourites, history and playback progress will also be removed. Downloaded files are kept.",
"SUMMARY": "Checked {{checked}}/{{total}} · Available {{available}} · Deleted {{deleted}} · Skipped {{skipped}} · Failed {{failed}}",
"SELECT_ALL": "Select all candidates",
"SELECT_NONE": "Deselect all",
"UNTITLED": "Untitled source",
"DELETE": "Delete selected · {{count}}",
"CLOSE": "Close",
"STOP": "Stop after current source",
"CLEANUP_WARNING": "Source deleted; some follow-up cleanup failed",
"GROUP": {
"confirmed": "Confirmed inactive accounts",
"uncertain": "Review before deleting",
"skipped": "Skipped sources",
"results": "Deletion results"
},
"STATUS": {
"checking": "Checking…",
"skipped": "Playing, busy, changed or no longer present",
"deleting": "Deleting…",
"deleted": "Deleted",
"failed": "Deletion failed — select to retry"
},
"DELETE_PROGRESS": "Processed {{done}} of {{total}} selected sources"
}
}
+27
View File
@@ -1807,5 +1807,32 @@
"cancelled": "Check cancelled",
"checking": "Checking…"
}
},
"SOURCE_CLEANUP": {
"TITLE": "Clean up inactive sources…",
"SCOPE": "All network sources in your library, regardless of page filters.",
"CONSEQUENCES": "Delete only sources you select. Their saved favourites, history and playback progress will also be removed. Downloaded files are kept.",
"SUMMARY": "Checked {{checked}}/{{total}} · Available {{available}} · Deleted {{deleted}} · Skipped {{skipped}} · Failed {{failed}}",
"SELECT_ALL": "Select all candidates",
"SELECT_NONE": "Deselect all",
"UNTITLED": "Untitled source",
"DELETE": "Delete selected · {{count}}",
"CLOSE": "Close",
"STOP": "Stop after current source",
"CLEANUP_WARNING": "Source deleted; some follow-up cleanup failed",
"GROUP": {
"confirmed": "Confirmed inactive accounts",
"uncertain": "Review before deleting",
"skipped": "Skipped sources",
"results": "Deletion results"
},
"STATUS": {
"checking": "Checking…",
"skipped": "Playing, busy, changed or no longer present",
"deleting": "Deleting…",
"deleted": "Deleted",
"failed": "Deletion failed — select to retry"
},
"DELETE_PROGRESS": "Processed {{done}} of {{total}} selected sources"
}
}
+27
View File
@@ -1807,5 +1807,32 @@
"cancelled": "Check cancelled",
"checking": "Checking…"
}
},
"SOURCE_CLEANUP": {
"TITLE": "Clean up inactive sources…",
"SCOPE": "All network sources in your library, regardless of page filters.",
"CONSEQUENCES": "Delete only sources you select. Their saved favourites, history and playback progress will also be removed. Downloaded files are kept.",
"SUMMARY": "Checked {{checked}}/{{total}} · Available {{available}} · Deleted {{deleted}} · Skipped {{skipped}} · Failed {{failed}}",
"SELECT_ALL": "Select all candidates",
"SELECT_NONE": "Deselect all",
"UNTITLED": "Untitled source",
"DELETE": "Delete selected · {{count}}",
"CLOSE": "Close",
"STOP": "Stop after current source",
"CLEANUP_WARNING": "Source deleted; some follow-up cleanup failed",
"GROUP": {
"confirmed": "Confirmed inactive accounts",
"uncertain": "Review before deleting",
"skipped": "Skipped sources",
"results": "Deletion results"
},
"STATUS": {
"checking": "Checking…",
"skipped": "Playing, busy, changed or no longer present",
"deleting": "Deleting…",
"deleted": "Deleted",
"failed": "Deletion failed — select to retry"
},
"DELETE_PROGRESS": "Processed {{done}} of {{total}} selected sources"
}
}
+27
View File
@@ -1807,5 +1807,32 @@
"cancelled": "Check cancelled",
"checking": "Checking…"
}
},
"SOURCE_CLEANUP": {
"TITLE": "Clean up inactive sources…",
"SCOPE": "All network sources in your library, regardless of page filters.",
"CONSEQUENCES": "Delete only sources you select. Their saved favourites, history and playback progress will also be removed. Downloaded files are kept.",
"SUMMARY": "Checked {{checked}}/{{total}} · Available {{available}} · Deleted {{deleted}} · Skipped {{skipped}} · Failed {{failed}}",
"SELECT_ALL": "Select all candidates",
"SELECT_NONE": "Deselect all",
"UNTITLED": "Untitled source",
"DELETE": "Delete selected · {{count}}",
"CLOSE": "Close",
"STOP": "Stop after current source",
"CLEANUP_WARNING": "Source deleted; some follow-up cleanup failed",
"GROUP": {
"confirmed": "Confirmed inactive accounts",
"uncertain": "Review before deleting",
"skipped": "Skipped sources",
"results": "Deletion results"
},
"STATUS": {
"checking": "Checking…",
"skipped": "Playing, busy, changed or no longer present",
"deleting": "Deleting…",
"deleted": "Deleted",
"failed": "Deletion failed — select to retry"
},
"DELETE_PROGRESS": "Processed {{done}} of {{total}} selected sources"
}
}
+27
View File
@@ -1807,5 +1807,32 @@
"cancelled": "Check cancelled",
"checking": "Checking…"
}
},
"SOURCE_CLEANUP": {
"TITLE": "Clean up inactive sources…",
"SCOPE": "All network sources in your library, regardless of page filters.",
"CONSEQUENCES": "Delete only sources you select. Their saved favourites, history and playback progress will also be removed. Downloaded files are kept.",
"SUMMARY": "Checked {{checked}}/{{total}} · Available {{available}} · Deleted {{deleted}} · Skipped {{skipped}} · Failed {{failed}}",
"SELECT_ALL": "Select all candidates",
"SELECT_NONE": "Deselect all",
"UNTITLED": "Untitled source",
"DELETE": "Delete selected · {{count}}",
"CLOSE": "Close",
"STOP": "Stop after current source",
"CLEANUP_WARNING": "Source deleted; some follow-up cleanup failed",
"GROUP": {
"confirmed": "Confirmed inactive accounts",
"uncertain": "Review before deleting",
"skipped": "Skipped sources",
"results": "Deletion results"
},
"STATUS": {
"checking": "Checking…",
"skipped": "Playing, busy, changed or no longer present",
"deleting": "Deleting…",
"deleted": "Deleted",
"failed": "Deletion failed — select to retry"
},
"DELETE_PROGRESS": "Processed {{done}} of {{total}} selected sources"
}
}
+27
View File
@@ -1807,5 +1807,32 @@
"cancelled": "Check cancelled",
"checking": "Checking…"
}
},
"SOURCE_CLEANUP": {
"TITLE": "Clean up inactive sources…",
"SCOPE": "All network sources in your library, regardless of page filters.",
"CONSEQUENCES": "Delete only sources you select. Their saved favourites, history and playback progress will also be removed. Downloaded files are kept.",
"SUMMARY": "Checked {{checked}}/{{total}} · Available {{available}} · Deleted {{deleted}} · Skipped {{skipped}} · Failed {{failed}}",
"SELECT_ALL": "Select all candidates",
"SELECT_NONE": "Deselect all",
"UNTITLED": "Untitled source",
"DELETE": "Delete selected · {{count}}",
"CLOSE": "Close",
"STOP": "Stop after current source",
"CLEANUP_WARNING": "Source deleted; some follow-up cleanup failed",
"GROUP": {
"confirmed": "Confirmed inactive accounts",
"uncertain": "Review before deleting",
"skipped": "Skipped sources",
"results": "Deletion results"
},
"STATUS": {
"checking": "Checking…",
"skipped": "Playing, busy, changed or no longer present",
"deleting": "Deleting…",
"deleted": "Deleted",
"failed": "Deletion failed — select to retry"
},
"DELETE_PROGRESS": "Processed {{done}} of {{total}} selected sources"
}
}
+27
View File
@@ -1807,5 +1807,32 @@
"cancelled": "Check cancelled",
"checking": "Checking…"
}
},
"SOURCE_CLEANUP": {
"TITLE": "Clean up inactive sources…",
"SCOPE": "All network sources in your library, regardless of page filters.",
"CONSEQUENCES": "Delete only sources you select. Their saved favourites, history and playback progress will also be removed. Downloaded files are kept.",
"SUMMARY": "Checked {{checked}}/{{total}} · Available {{available}} · Deleted {{deleted}} · Skipped {{skipped}} · Failed {{failed}}",
"SELECT_ALL": "Select all candidates",
"SELECT_NONE": "Deselect all",
"UNTITLED": "Untitled source",
"DELETE": "Delete selected · {{count}}",
"CLOSE": "Close",
"STOP": "Stop after current source",
"CLEANUP_WARNING": "Source deleted; some follow-up cleanup failed",
"GROUP": {
"confirmed": "Confirmed inactive accounts",
"uncertain": "Review before deleting",
"skipped": "Skipped sources",
"results": "Deletion results"
},
"STATUS": {
"checking": "Checking…",
"skipped": "Playing, busy, changed or no longer present",
"deleting": "Deleting…",
"deleted": "Deleted",
"failed": "Deletion failed — select to retry"
},
"DELETE_PROGRESS": "Processed {{done}} of {{total}} selected sources"
}
}
+27
View File
@@ -1807,5 +1807,32 @@
"cancelled": "Check cancelled",
"checking": "Checking…"
}
},
"SOURCE_CLEANUP": {
"TITLE": "Clean up inactive sources…",
"SCOPE": "All network sources in your library, regardless of page filters.",
"CONSEQUENCES": "Delete only sources you select. Their saved favourites, history and playback progress will also be removed. Downloaded files are kept.",
"SUMMARY": "Checked {{checked}}/{{total}} · Available {{available}} · Deleted {{deleted}} · Skipped {{skipped}} · Failed {{failed}}",
"SELECT_ALL": "Select all candidates",
"SELECT_NONE": "Deselect all",
"UNTITLED": "Untitled source",
"DELETE": "Delete selected · {{count}}",
"CLOSE": "Close",
"STOP": "Stop after current source",
"CLEANUP_WARNING": "Source deleted; some follow-up cleanup failed",
"GROUP": {
"confirmed": "Confirmed inactive accounts",
"uncertain": "Review before deleting",
"skipped": "Skipped sources",
"results": "Deletion results"
},
"STATUS": {
"checking": "Checking…",
"skipped": "Playing, busy, changed or no longer present",
"deleting": "Deleting…",
"deleted": "Deleted",
"failed": "Deletion failed — select to retry"
},
"DELETE_PROGRESS": "Processed {{done}} of {{total}} selected sources"
}
}
+27
View File
@@ -1807,5 +1807,32 @@
"cancelled": "Check cancelled",
"checking": "Checking…"
}
},
"SOURCE_CLEANUP": {
"TITLE": "Clean up inactive sources…",
"SCOPE": "All network sources in your library, regardless of page filters.",
"CONSEQUENCES": "Delete only sources you select. Their saved favourites, history and playback progress will also be removed. Downloaded files are kept.",
"SUMMARY": "Checked {{checked}}/{{total}} · Available {{available}} · Deleted {{deleted}} · Skipped {{skipped}} · Failed {{failed}}",
"SELECT_ALL": "Select all candidates",
"SELECT_NONE": "Deselect all",
"UNTITLED": "Untitled source",
"DELETE": "Delete selected · {{count}}",
"CLOSE": "Close",
"STOP": "Stop after current source",
"CLEANUP_WARNING": "Source deleted; some follow-up cleanup failed",
"GROUP": {
"confirmed": "Confirmed inactive accounts",
"uncertain": "Review before deleting",
"skipped": "Skipped sources",
"results": "Deletion results"
},
"STATUS": {
"checking": "Checking…",
"skipped": "Playing, busy, changed or no longer present",
"deleting": "Deleting…",
"deleted": "Deleted",
"failed": "Deletion failed — select to retry"
},
"DELETE_PROGRESS": "Processed {{done}} of {{total}} selected sources"
}
}
+27
View File
@@ -1807,5 +1807,32 @@
"cancelled": "Check cancelled",
"checking": "Checking…"
}
},
"SOURCE_CLEANUP": {
"TITLE": "Clean up inactive sources…",
"SCOPE": "All network sources in your library, regardless of page filters.",
"CONSEQUENCES": "Delete only sources you select. Their saved favourites, history and playback progress will also be removed. Downloaded files are kept.",
"SUMMARY": "Checked {{checked}}/{{total}} · Available {{available}} · Deleted {{deleted}} · Skipped {{skipped}} · Failed {{failed}}",
"SELECT_ALL": "Select all candidates",
"SELECT_NONE": "Deselect all",
"UNTITLED": "Untitled source",
"DELETE": "Delete selected · {{count}}",
"CLOSE": "Close",
"STOP": "Stop after current source",
"CLEANUP_WARNING": "Source deleted; some follow-up cleanup failed",
"GROUP": {
"confirmed": "Confirmed inactive accounts",
"uncertain": "Review before deleting",
"skipped": "Skipped sources",
"results": "Deletion results"
},
"STATUS": {
"checking": "Checking…",
"skipped": "Playing, busy, changed or no longer present",
"deleting": "Deleting…",
"deleted": "Deleted",
"failed": "Deletion failed — select to retry"
},
"DELETE_PROGRESS": "Processed {{done}} of {{total}} selected sources"
}
}
+27
View File
@@ -1807,5 +1807,32 @@
"cancelled": "Check cancelled",
"checking": "Checking…"
}
},
"SOURCE_CLEANUP": {
"TITLE": "Clean up inactive sources…",
"SCOPE": "All network sources in your library, regardless of page filters.",
"CONSEQUENCES": "Delete only sources you select. Their saved favourites, history and playback progress will also be removed. Downloaded files are kept.",
"SUMMARY": "Checked {{checked}}/{{total}} · Available {{available}} · Deleted {{deleted}} · Skipped {{skipped}} · Failed {{failed}}",
"SELECT_ALL": "Select all candidates",
"SELECT_NONE": "Deselect all",
"UNTITLED": "Untitled source",
"DELETE": "Delete selected · {{count}}",
"CLOSE": "Close",
"STOP": "Stop after current source",
"CLEANUP_WARNING": "Source deleted; some follow-up cleanup failed",
"GROUP": {
"confirmed": "Confirmed inactive accounts",
"uncertain": "Review before deleting",
"skipped": "Skipped sources",
"results": "Deletion results"
},
"STATUS": {
"checking": "Checking…",
"skipped": "Playing, busy, changed or no longer present",
"deleting": "Deleting…",
"deleted": "Deleted",
"failed": "Deletion failed — select to retry"
},
"DELETE_PROGRESS": "Processed {{done}} of {{total}} selected sources"
}
}
+27
View File
@@ -1807,5 +1807,32 @@
"cancelled": "Check cancelled",
"checking": "Checking…"
}
},
"SOURCE_CLEANUP": {
"TITLE": "Clean up inactive sources…",
"SCOPE": "All network sources in your library, regardless of page filters.",
"CONSEQUENCES": "Delete only sources you select. Their saved favourites, history and playback progress will also be removed. Downloaded files are kept.",
"SUMMARY": "Checked {{checked}}/{{total}} · Available {{available}} · Deleted {{deleted}} · Skipped {{skipped}} · Failed {{failed}}",
"SELECT_ALL": "Select all candidates",
"SELECT_NONE": "Deselect all",
"UNTITLED": "Untitled source",
"DELETE": "Delete selected · {{count}}",
"CLOSE": "Close",
"STOP": "Stop after current source",
"CLEANUP_WARNING": "Source deleted; some follow-up cleanup failed",
"GROUP": {
"confirmed": "Confirmed inactive accounts",
"uncertain": "Review before deleting",
"skipped": "Skipped sources",
"results": "Deletion results"
},
"STATUS": {
"checking": "Checking…",
"skipped": "Playing, busy, changed or no longer present",
"deleting": "Deleting…",
"deleted": "Deleted",
"failed": "Deletion failed — select to retry"
},
"DELETE_PROGRESS": "Processed {{done}} of {{total}} selected sources"
}
}
+27
View File
@@ -1807,5 +1807,32 @@
"cancelled": "Проверка отменена",
"checking": "Проверяется…"
}
},
"SOURCE_CLEANUP": {
"TITLE": "Очистить неактивные…",
"SCOPE": "Все сетевые источники библиотеки, независимо от фильтров страницы.",
"CONSEQUENCES": "Удаляются только выбранные источники, вместе с их избранным, историей и прогрессом воспроизведения. Скачанные файлы сохраняются.",
"SUMMARY": "Проверено {{checked}}/{{total}} · Доступно {{available}} · Удалено {{deleted}} · Пропущено {{skipped}} · Ошибок {{failed}}",
"SELECT_ALL": "Выбрать всех кандидатов",
"SELECT_NONE": "Снять выбор",
"UNTITLED": "Источник без названия",
"DELETE": "Удалить выбранные · {{count}}",
"CLOSE": "Закрыть",
"STOP": "Остановить после текущего",
"CLEANUP_WARNING": "Источник удалён; часть дополнительной очистки не выполнена",
"GROUP": {
"confirmed": "Подтверждённо неактивные аккаунты",
"uncertain": "Требуют решения",
"skipped": "Пропущенные источники",
"results": "Результаты удаления"
},
"STATUS": {
"checking": "Проверяется…",
"skipped": "Воспроизводится, занят, изменён или уже отсутствует",
"deleting": "Удаляется…",
"deleted": "Удалён",
"failed": "Не удалось удалить — выберите для повтора"
},
"DELETE_PROGRESS": "Обработано {{done}} из {{total}} выбранных источников"
}
}
+27
View File
@@ -1807,5 +1807,32 @@
"cancelled": "Check cancelled",
"checking": "Checking…"
}
},
"SOURCE_CLEANUP": {
"TITLE": "Clean up inactive sources…",
"SCOPE": "All network sources in your library, regardless of page filters.",
"CONSEQUENCES": "Delete only sources you select. Their saved favourites, history and playback progress will also be removed. Downloaded files are kept.",
"SUMMARY": "Checked {{checked}}/{{total}} · Available {{available}} · Deleted {{deleted}} · Skipped {{skipped}} · Failed {{failed}}",
"SELECT_ALL": "Select all candidates",
"SELECT_NONE": "Deselect all",
"UNTITLED": "Untitled source",
"DELETE": "Delete selected · {{count}}",
"CLOSE": "Close",
"STOP": "Stop after current source",
"CLEANUP_WARNING": "Source deleted; some follow-up cleanup failed",
"GROUP": {
"confirmed": "Confirmed inactive accounts",
"uncertain": "Review before deleting",
"skipped": "Skipped sources",
"results": "Deletion results"
},
"STATUS": {
"checking": "Checking…",
"skipped": "Playing, busy, changed or no longer present",
"deleting": "Deleting…",
"deleted": "Deleted",
"failed": "Deletion failed — select to retry"
},
"DELETE_PROGRESS": "Processed {{done}} of {{total}} selected sources"
}
}
+27
View File
@@ -1807,5 +1807,32 @@
"cancelled": "Check cancelled",
"checking": "Checking…"
}
},
"SOURCE_CLEANUP": {
"TITLE": "Clean up inactive sources…",
"SCOPE": "All network sources in your library, regardless of page filters.",
"CONSEQUENCES": "Delete only sources you select. Their saved favourites, history and playback progress will also be removed. Downloaded files are kept.",
"SUMMARY": "Checked {{checked}}/{{total}} · Available {{available}} · Deleted {{deleted}} · Skipped {{skipped}} · Failed {{failed}}",
"SELECT_ALL": "Select all candidates",
"SELECT_NONE": "Deselect all",
"UNTITLED": "Untitled source",
"DELETE": "Delete selected · {{count}}",
"CLOSE": "Close",
"STOP": "Stop after current source",
"CLEANUP_WARNING": "Source deleted; some follow-up cleanup failed",
"GROUP": {
"confirmed": "Confirmed inactive accounts",
"uncertain": "Review before deleting",
"skipped": "Skipped sources",
"results": "Deletion results"
},
"STATUS": {
"checking": "Checking…",
"skipped": "Playing, busy, changed or no longer present",
"deleting": "Deleting…",
"deleted": "Deleted",
"failed": "Deletion failed — select to retry"
},
"DELETE_PROGRESS": "Processed {{done}} of {{total}} selected sources"
}
}
+27
View File
@@ -1807,5 +1807,32 @@
"cancelled": "Check cancelled",
"checking": "Checking…"
}
},
"SOURCE_CLEANUP": {
"TITLE": "Clean up inactive sources…",
"SCOPE": "All network sources in your library, regardless of page filters.",
"CONSEQUENCES": "Delete only sources you select. Their saved favourites, history and playback progress will also be removed. Downloaded files are kept.",
"SUMMARY": "Checked {{checked}}/{{total}} · Available {{available}} · Deleted {{deleted}} · Skipped {{skipped}} · Failed {{failed}}",
"SELECT_ALL": "Select all candidates",
"SELECT_NONE": "Deselect all",
"UNTITLED": "Untitled source",
"DELETE": "Delete selected · {{count}}",
"CLOSE": "Close",
"STOP": "Stop after current source",
"CLEANUP_WARNING": "Source deleted; some follow-up cleanup failed",
"GROUP": {
"confirmed": "Confirmed inactive accounts",
"uncertain": "Review before deleting",
"skipped": "Skipped sources",
"results": "Deletion results"
},
"STATUS": {
"checking": "Checking…",
"skipped": "Playing, busy, changed or no longer present",
"deleting": "Deleting…",
"deleted": "Deleted",
"failed": "Deletion failed — select to retry"
},
"DELETE_PROGRESS": "Processed {{done}} of {{total}} selected sources"
}
}