mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 17:06:15 -08:00
style(settings): add EPG sources handling and UI enhancements
Entire-Checkpoint: c6e522b4276c
This commit is contained in:
1 parent
4616df5d16
commit
e53a25f441
21 files changed
+265
-82
No files matched your search
@@ -232,7 +232,7 @@
|
||||
formControlName="player"
|
||||
data-test-id="select-video-player"
|
||||
>
|
||||
@for (player of players; track player) {
|
||||
@for (player of players(); track player.id) {
|
||||
<mat-option
|
||||
[value]="player.id"
|
||||
[attr.data-test-id]="player.id"
|
||||
@@ -419,70 +419,96 @@
|
||||
<div class="setting-item setting-item--full-control">
|
||||
<div class="setting-item__control">
|
||||
<ng-container formArrayName="epgUrl">
|
||||
<div class="epg-sources">
|
||||
@for (
|
||||
_ of epgUrl.controls;
|
||||
track _;
|
||||
let i = $index
|
||||
) {
|
||||
<div class="epg-source-row">
|
||||
<mat-form-field
|
||||
appearance="outline"
|
||||
subscriptSizing="dynamic"
|
||||
class="w-full"
|
||||
>
|
||||
<mat-label>{{
|
||||
'SETTINGS.EPG_URL_PLACEHOLDER'
|
||||
| translate
|
||||
}}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
type="url"
|
||||
[formControlName]="i"
|
||||
#epgField
|
||||
/>
|
||||
<mat-error>{{
|
||||
'SETTINGS.EPG_URL_ERROR'
|
||||
| translate
|
||||
}}</mat-error>
|
||||
</mat-form-field>
|
||||
@if (epgField.value) {
|
||||
<app-epg-source-status
|
||||
[url]="epgField.value"
|
||||
/>
|
||||
}
|
||||
<button
|
||||
mat-icon-button
|
||||
color="accent"
|
||||
[matTooltip]="
|
||||
'SETTINGS.REFRESH_EPG'
|
||||
| translate
|
||||
"
|
||||
type="button"
|
||||
[disabled]="
|
||||
epgField.value === ''
|
||||
"
|
||||
(click)="
|
||||
refreshEpg(epgUrl.value[i])
|
||||
"
|
||||
>
|
||||
<mat-icon>refresh</mat-icon>
|
||||
</button>
|
||||
<button
|
||||
mat-icon-button
|
||||
color="accent"
|
||||
[matTooltip]="
|
||||
'SETTINGS.REMOVE_EPG_SOURCE'
|
||||
| translate
|
||||
"
|
||||
type="button"
|
||||
(click)="removeEpgSource(i)"
|
||||
>
|
||||
<mat-icon>remove</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
@if (epgUrl.length === 0) {
|
||||
<div
|
||||
class="epg-sources-empty"
|
||||
data-test-id="epg-sources-empty"
|
||||
>
|
||||
<mat-icon
|
||||
class="epg-sources-empty__icon"
|
||||
>event_busy</mat-icon
|
||||
>
|
||||
<h4 class="epg-sources-empty__title">
|
||||
{{
|
||||
'SETTINGS.EPG_EMPTY_TITLE'
|
||||
| translate
|
||||
}}
|
||||
</h4>
|
||||
<p class="epg-sources-empty__hint">
|
||||
{{
|
||||
'SETTINGS.EPG_EMPTY_HINT'
|
||||
| translate
|
||||
}}
|
||||
</p>
|
||||
</div>
|
||||
} @else {
|
||||
<div class="epg-sources">
|
||||
@for (
|
||||
_ of epgUrl.controls;
|
||||
track _;
|
||||
let i = $index
|
||||
) {
|
||||
<div class="epg-source-row">
|
||||
<mat-form-field
|
||||
appearance="outline"
|
||||
subscriptSizing="dynamic"
|
||||
class="w-full"
|
||||
>
|
||||
<mat-label>{{
|
||||
'SETTINGS.EPG_URL_PLACEHOLDER'
|
||||
| translate
|
||||
}}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
type="url"
|
||||
[formControlName]="i"
|
||||
#epgField
|
||||
/>
|
||||
<mat-error>{{
|
||||
'SETTINGS.EPG_URL_ERROR'
|
||||
| translate
|
||||
}}</mat-error>
|
||||
</mat-form-field>
|
||||
@if (epgField.value) {
|
||||
<app-epg-source-status
|
||||
[url]="epgField.value"
|
||||
/>
|
||||
}
|
||||
<button
|
||||
mat-icon-button
|
||||
color="accent"
|
||||
[matTooltip]="
|
||||
'SETTINGS.REFRESH_EPG'
|
||||
| translate
|
||||
"
|
||||
type="button"
|
||||
[disabled]="
|
||||
epgField.value === ''
|
||||
"
|
||||
(click)="
|
||||
refreshEpg(
|
||||
epgUrl.value[i]
|
||||
)
|
||||
"
|
||||
>
|
||||
<mat-icon>refresh</mat-icon>
|
||||
</button>
|
||||
<button
|
||||
mat-icon-button
|
||||
color="accent"
|
||||
[matTooltip]="
|
||||
'SETTINGS.REMOVE_EPG_SOURCE'
|
||||
| translate
|
||||
"
|
||||
type="button"
|
||||
(click)="removeEpgSource(i)"
|
||||
>
|
||||
<mat-icon>remove</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
@@ -909,6 +935,18 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (isDesktop) {
|
||||
<div class="settings-note">
|
||||
<strong>{{
|
||||
'SETTINGS.EMBEDDED_MPV_NOTICE_TITLE' | translate
|
||||
}}</strong>
|
||||
<span>{{
|
||||
'SETTINGS.EMBEDDED_MPV_NOTICE_DESCRIPTION'
|
||||
| translate
|
||||
}}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="setting-item setting-item--full-control">
|
||||
<div class="setting-item__meta">
|
||||
<h4>{{ 'SETTINGS.COMMUNITY' | translate }}</h4>
|
||||
|
||||
@@ -297,6 +297,40 @@
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.epg-sources-empty {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
gap: 8px;
|
||||
padding: 24px 16px 16px;
|
||||
color: var(--mat-sys-on-surface-variant);
|
||||
|
||||
.epg-sources-empty__icon {
|
||||
font-size: 40px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
opacity: 0.55;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.epg-sources-empty__title {
|
||||
margin: 0;
|
||||
font-size: 0.95rem;
|
||||
font-weight: 600;
|
||||
color: var(--mat-sys-on-surface);
|
||||
}
|
||||
|
||||
.epg-sources-empty__hint {
|
||||
margin: 0;
|
||||
font-size: 0.825rem;
|
||||
line-height: 1.5;
|
||||
max-width: 360px;
|
||||
opacity: 0.75;
|
||||
}
|
||||
}
|
||||
|
||||
.epg-source-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -30,6 +30,7 @@ import {
|
||||
PlaylistsService,
|
||||
} from 'services';
|
||||
import {
|
||||
EmbeddedMpvSupport,
|
||||
Language,
|
||||
PlaylistMeta,
|
||||
StartupBehavior,
|
||||
@@ -400,6 +401,80 @@ describe('SettingsComponent', () => {
|
||||
...settings,
|
||||
});
|
||||
});
|
||||
|
||||
it('hides the embedded mpv option when the desktop support probe reports unsupported', async () => {
|
||||
window.electron = {
|
||||
...window.electron,
|
||||
getEmbeddedMpvSupport: jest.fn().mockResolvedValue({
|
||||
supported: false,
|
||||
platform: 'darwin',
|
||||
reason: 'hidden harness',
|
||||
}),
|
||||
} as unknown as typeof window.electron;
|
||||
|
||||
await component.ngOnInit();
|
||||
await fixture.whenStable();
|
||||
|
||||
expect(
|
||||
component.players().some(
|
||||
(player) => player.id === VideoPlayer.EmbeddedMpv
|
||||
)
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('shows the embedded mpv option when the desktop support probe reports supported', async () => {
|
||||
window.electron = {
|
||||
...window.electron,
|
||||
getEmbeddedMpvSupport: jest.fn().mockResolvedValue({
|
||||
supported: true,
|
||||
platform: 'darwin',
|
||||
}),
|
||||
} as unknown as typeof window.electron;
|
||||
|
||||
await component.ngOnInit();
|
||||
await fixture.whenStable();
|
||||
|
||||
expect(
|
||||
component.players().some(
|
||||
(player) => player.id === VideoPlayer.EmbeddedMpv
|
||||
)
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('does not block settings initialization while embedded mpv support is pending', async () => {
|
||||
let resolveSupport: (value: EmbeddedMpvSupport) => void;
|
||||
window.electron = {
|
||||
...window.electron,
|
||||
getEmbeddedMpvSupport: jest.fn(
|
||||
() =>
|
||||
new Promise((resolve) => {
|
||||
resolveSupport = resolve;
|
||||
})
|
||||
),
|
||||
} as unknown as typeof window.electron;
|
||||
|
||||
await expect(component.ngOnInit()).resolves.toBeUndefined();
|
||||
|
||||
expect(component.settingsForm.value).toEqual(DEFAULT_SETTINGS);
|
||||
expect(window.electron.getEmbeddedMpvSupport).toHaveBeenCalled();
|
||||
expect(
|
||||
component.players().some(
|
||||
(player) => player.id === VideoPlayer.EmbeddedMpv
|
||||
)
|
||||
).toBe(false);
|
||||
|
||||
resolveSupport!({
|
||||
supported: true,
|
||||
platform: 'darwin',
|
||||
});
|
||||
await fixture.whenStable();
|
||||
|
||||
expect(
|
||||
component.players().some(
|
||||
(player) => player.id === VideoPlayer.EmbeddedMpv
|
||||
)
|
||||
).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Version check', () => {
|
||||
|
||||
@@ -209,7 +209,9 @@
|
||||
"REMOTE_CONTROL_PORT_DESCRIPTION": "المنفذ المستخدم للتحكم عن بعد (الافتراضي: 8765).",
|
||||
"REMOVE_ALL_IN_PROGRESS": "Deleting playlist data…",
|
||||
"REMOVE_ALL_PROGRESS": "Deleting playlist data… {{current}} / {{total}}",
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again."
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again.",
|
||||
"EPG_EMPTY_TITLE": "No EPG sources yet",
|
||||
"EPG_EMPTY_HINT": "Add a URL to fetch program data for your channels."
|
||||
},
|
||||
"THEMES": {
|
||||
"DARK_THEME": "السمة الداكنة",
|
||||
|
||||
@@ -201,7 +201,9 @@
|
||||
"REMOTE_CONTROL_PORT_DESCRIPTION": "المنفذ اللي كيتستعمل للتحكم عن بعد للتطبيق. المنفذ 3000 كيتستعمل افتراضياً.",
|
||||
"REMOVE_ALL_IN_PROGRESS": "Deleting playlist data…",
|
||||
"REMOVE_ALL_PROGRESS": "Deleting playlist data… {{current}} / {{total}}",
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again."
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again.",
|
||||
"EPG_EMPTY_TITLE": "No EPG sources yet",
|
||||
"EPG_EMPTY_HINT": "Add a URL to fetch program data for your channels."
|
||||
},
|
||||
"THEMES": {
|
||||
"DARK_THEME": "المظهر الداكن",
|
||||
|
||||
@@ -203,7 +203,9 @@
|
||||
"VLC_PLAYER_PATH_DESCRIPTION": "Усталюйце шлях да прайгравальніка VLC у вашай сістэме. \nЁн будзе выкарыстоўваць прадастаўлены шлях да бінарнага файла VLC замест шляху па змаўчанні.",
|
||||
"REMOVE_ALL_IN_PROGRESS": "Deleting playlist data…",
|
||||
"REMOVE_ALL_PROGRESS": "Deleting playlist data… {{current}} / {{total}}",
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again."
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again.",
|
||||
"EPG_EMPTY_TITLE": "No EPG sources yet",
|
||||
"EPG_EMPTY_HINT": "Add a URL to fetch program data for your channels."
|
||||
},
|
||||
"THEMES": {
|
||||
"DARK_THEME": "Цёмная тэма",
|
||||
|
||||
@@ -376,7 +376,9 @@
|
||||
"PORT_PATTERN": "Nur Ziffern sind erlaubt",
|
||||
"REMOVE_ALL_IN_PROGRESS": "Deleting playlist data…",
|
||||
"REMOVE_ALL_PROGRESS": "Deleting playlist data… {{current}} / {{total}}",
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again."
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again.",
|
||||
"EPG_EMPTY_TITLE": "No EPG sources yet",
|
||||
"EPG_EMPTY_HINT": "Add a URL to fetch program data for your channels."
|
||||
},
|
||||
"THEMES": {
|
||||
"DARK_THEME": "Dunkel",
|
||||
|
||||
@@ -254,7 +254,9 @@
|
||||
"PORT_PATTERN": "Επιτρέπονται μόνο αριθμητικά ψηφία",
|
||||
"REMOVE_ALL_IN_PROGRESS": "Deleting playlist data…",
|
||||
"REMOVE_ALL_PROGRESS": "Deleting playlist data… {{current}} / {{total}}",
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again."
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again.",
|
||||
"EPG_EMPTY_TITLE": "No EPG sources yet",
|
||||
"EPG_EMPTY_HINT": "Add a URL to fetch program data for your channels."
|
||||
},
|
||||
"THEMES": {
|
||||
"DARK_THEME": "Σκούρο θέμα",
|
||||
|
||||
@@ -200,6 +200,8 @@
|
||||
"PLAYBACK": "Playback",
|
||||
"EPG_SOURCES": "EPG sources",
|
||||
"EPG_SOURCES_DESCRIPTION": "Add one or more URLs as EPG sources",
|
||||
"EPG_EMPTY_TITLE": "No EPG sources yet",
|
||||
"EPG_EMPTY_HINT": "Add a URL to fetch program data for your channels.",
|
||||
"DATA": "Data",
|
||||
"ABOUT": "About",
|
||||
"NAV_GENERAL": "General",
|
||||
|
||||
@@ -231,7 +231,9 @@
|
||||
"STREAM_FORMAT_DESCRIPTION": "Selecciona el formato de transmision predeterminado (Xtream)",
|
||||
"REMOVE_ALL_IN_PROGRESS": "Deleting playlist data…",
|
||||
"REMOVE_ALL_PROGRESS": "Deleting playlist data… {{current}} / {{total}}",
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again."
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again.",
|
||||
"EPG_EMPTY_TITLE": "No EPG sources yet",
|
||||
"EPG_EMPTY_HINT": "Add a URL to fetch program data for your channels."
|
||||
},
|
||||
"THEMES": {
|
||||
"DARK_THEME": "Tema oscuro",
|
||||
|
||||
@@ -222,7 +222,9 @@
|
||||
"REMOTE_CONTROL_PORT_DESCRIPTION": "Port utilisé pour la télécommande de l'application. Le port 8765 est utilisé par défaut.",
|
||||
"REMOVE_ALL_IN_PROGRESS": "Deleting playlist data…",
|
||||
"REMOVE_ALL_PROGRESS": "Deleting playlist data… {{current}} / {{total}}",
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again."
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again.",
|
||||
"EPG_EMPTY_TITLE": "No EPG sources yet",
|
||||
"EPG_EMPTY_HINT": "Add a URL to fetch program data for your channels."
|
||||
},
|
||||
"THEMES": {
|
||||
"DARK_THEME": "Thème foncé",
|
||||
|
||||
@@ -243,7 +243,9 @@
|
||||
"PORT_PATTERN": "Sono consentite solo cifre",
|
||||
"REMOVE_ALL_IN_PROGRESS": "Deleting playlist data…",
|
||||
"REMOVE_ALL_PROGRESS": "Deleting playlist data… {{current}} / {{total}}",
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again."
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again.",
|
||||
"EPG_EMPTY_TITLE": "No EPG sources yet",
|
||||
"EPG_EMPTY_HINT": "Add a URL to fetch program data for your channels."
|
||||
},
|
||||
"THEMES": {
|
||||
"DARK_THEME": "Tema scuro",
|
||||
|
||||
@@ -189,7 +189,9 @@
|
||||
"REMOTE_CONTROL_PORT_DESCRIPTION": "アプリケーションのリモートコントロールに使用されるポート。デフォルトではポート3000が使用されます。",
|
||||
"REMOVE_ALL_IN_PROGRESS": "Deleting playlist data…",
|
||||
"REMOVE_ALL_PROGRESS": "Deleting playlist data… {{current}} / {{total}}",
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again."
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again.",
|
||||
"EPG_EMPTY_TITLE": "No EPG sources yet",
|
||||
"EPG_EMPTY_HINT": "Add a URL to fetch program data for your channels."
|
||||
},
|
||||
"THEMES": {
|
||||
"DARK_THEME": "ダークテーマ",
|
||||
|
||||
@@ -160,7 +160,9 @@
|
||||
"REMOVE_ALL_DESCRIPTION": "Delete every M3U, Xtream, and Stalker playlist stored in the app.",
|
||||
"REMOVE_ALL_IN_PROGRESS": "Deleting playlist data…",
|
||||
"REMOVE_ALL_PROGRESS": "Deleting playlist data… {{current}} / {{total}}",
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again."
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again.",
|
||||
"EPG_EMPTY_TITLE": "No EPG sources yet",
|
||||
"EPG_EMPTY_HINT": "Add a URL to fetch program data for your channels."
|
||||
},
|
||||
"THEMES": {
|
||||
"DARK_THEME": "어두운 테마",
|
||||
|
||||
@@ -201,7 +201,9 @@
|
||||
"REMOTE_CONTROL_PORT_DESCRIPTION": "Poort voor de afstandsbediening van de applicatie. Standaard wordt poort 3000 gebruikt.",
|
||||
"REMOVE_ALL_IN_PROGRESS": "Deleting playlist data…",
|
||||
"REMOVE_ALL_PROGRESS": "Deleting playlist data… {{current}} / {{total}}",
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again."
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again.",
|
||||
"EPG_EMPTY_TITLE": "No EPG sources yet",
|
||||
"EPG_EMPTY_HINT": "Add a URL to fetch program data for your channels."
|
||||
},
|
||||
"THEMES": {
|
||||
"DARK_THEME": "Donker thema",
|
||||
|
||||
@@ -201,7 +201,9 @@
|
||||
"REMOTE_CONTROL_PORT_DESCRIPTION": "Port używany do zdalnego sterowania aplikacją. Domyślnie używany jest port 3000.",
|
||||
"REMOVE_ALL_IN_PROGRESS": "Deleting playlist data…",
|
||||
"REMOVE_ALL_PROGRESS": "Deleting playlist data… {{current}} / {{total}}",
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again."
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again.",
|
||||
"EPG_EMPTY_TITLE": "No EPG sources yet",
|
||||
"EPG_EMPTY_HINT": "Add a URL to fetch program data for your channels."
|
||||
},
|
||||
"THEMES": {
|
||||
"DARK_THEME": "Ciemny motyw",
|
||||
|
||||
@@ -220,7 +220,9 @@
|
||||
"REMOTE_CONTROL_PORT_DESCRIPTION": "Porta usada para controle remoto do aplicativo. A porta 8765 é usada por padrão.",
|
||||
"REMOVE_ALL_IN_PROGRESS": "Deleting playlist data…",
|
||||
"REMOVE_ALL_PROGRESS": "Deleting playlist data… {{current}} / {{total}}",
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again."
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again.",
|
||||
"EPG_EMPTY_TITLE": "No EPG sources yet",
|
||||
"EPG_EMPTY_HINT": "Add a URL to fetch program data for your channels."
|
||||
},
|
||||
"THEMES": {
|
||||
"DARK_THEME": "Tema escuro",
|
||||
|
||||
@@ -299,7 +299,9 @@
|
||||
"PORT_PATTERN": "Разрешены только цифры",
|
||||
"REMOVE_ALL_IN_PROGRESS": "Deleting playlist data…",
|
||||
"REMOVE_ALL_PROGRESS": "Deleting playlist data… {{current}} / {{total}}",
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again."
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again.",
|
||||
"EPG_EMPTY_TITLE": "No EPG sources yet",
|
||||
"EPG_EMPTY_HINT": "Add a URL to fetch program data for your channels."
|
||||
},
|
||||
"THEMES": {
|
||||
"DARK_THEME": "Тёмная тема",
|
||||
|
||||
@@ -255,7 +255,9 @@
|
||||
"PORT_PATTERN": "Sadece rakamlara izin verilir",
|
||||
"REMOVE_ALL_IN_PROGRESS": "Deleting playlist data…",
|
||||
"REMOVE_ALL_PROGRESS": "Deleting playlist data… {{current}} / {{total}}",
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again."
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again.",
|
||||
"EPG_EMPTY_TITLE": "No EPG sources yet",
|
||||
"EPG_EMPTY_HINT": "Add a URL to fetch program data for your channels."
|
||||
},
|
||||
"THEMES": {
|
||||
"DARK_THEME": "Koyu tema",
|
||||
|
||||
@@ -160,7 +160,9 @@
|
||||
"REMOVE_ALL_DESCRIPTION": "Delete every M3U, Xtream, and Stalker playlist stored in the app.",
|
||||
"REMOVE_ALL_IN_PROGRESS": "Deleting playlist data…",
|
||||
"REMOVE_ALL_PROGRESS": "Deleting playlist data… {{current}} / {{total}}",
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again."
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again.",
|
||||
"EPG_EMPTY_TITLE": "No EPG sources yet",
|
||||
"EPG_EMPTY_HINT": "Add a URL to fetch program data for your channels."
|
||||
},
|
||||
"THEMES": {
|
||||
"DARK_THEME": "暗黑模式",
|
||||
|
||||
@@ -206,7 +206,9 @@
|
||||
"REMOTE_CONTROL_PORT_DESCRIPTION": "用於遠端控制應用程式的連接埠。預設使用連接埠 8765。",
|
||||
"REMOVE_ALL_IN_PROGRESS": "Deleting playlist data…",
|
||||
"REMOVE_ALL_PROGRESS": "Deleting playlist data… {{current}} / {{total}}",
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again."
|
||||
"PLAYLISTS_REMOVE_FAILED": "Could not delete playlists. Please try again.",
|
||||
"EPG_EMPTY_TITLE": "No EPG sources yet",
|
||||
"EPG_EMPTY_HINT": "Add a URL to fetch program data for your channels."
|
||||
},
|
||||
"THEMES": {
|
||||
"DARK_THEME": "深色主題",
|
||||
|
||||
Reference in new issue
Block a user