refactor: remove ui_update_title and standardize page title
This commit is contained in:
parent
c2cb5527f5
commit
29777ff928
13 changed files with 37 additions and 55 deletions
1
FAQ.md
1
FAQ.md
|
|
@ -30,7 +30,6 @@ or the `environment:` section in `compose.yaml` file.
|
|||
| YTP_DEBUG | Whether to turn on debug mode | `false` |
|
||||
| YTP_DEBUGPY_PORT | The port to use for the debugpy debugger | `5678` |
|
||||
| YTP_EXTRACT_INFO_TIMEOUT | The timeout for extracting video information | `70` |
|
||||
| YTP_UI_UPDATE_TITLE | Whether to update the title of the page with the current stats | `true` |
|
||||
| YTP_PIP_PACKAGES | A space separated list of pip packages to install | `(not_set)` |
|
||||
| YTP_PIP_IGNORE_UPDATES | Do not update the custom pip packages | `false` |
|
||||
| YTP_PICTURES_BACKENDS | A comma separated list of pictures urls to use | `(not_set)` |
|
||||
|
|
|
|||
|
|
@ -129,9 +129,6 @@ class Config(metaclass=Singleton):
|
|||
apprise_config: str = "{config_path}{os_sep}apprise.yml"
|
||||
"""The path to the Apprise configuration file."""
|
||||
|
||||
ui_update_title: bool = True
|
||||
"""Update the title of the browser tab with the current status."""
|
||||
|
||||
pip_packages: str = ""
|
||||
"""The pip packages to install."""
|
||||
|
||||
|
|
@ -284,7 +281,6 @@ class Config(metaclass=Singleton):
|
|||
"access_log",
|
||||
"remove_files",
|
||||
"ignore_ui",
|
||||
"ui_update_title",
|
||||
"pip_ignore_updates",
|
||||
"file_logging",
|
||||
"console_enabled",
|
||||
|
|
@ -308,7 +304,6 @@ class Config(metaclass=Singleton):
|
|||
"output_template",
|
||||
"started",
|
||||
"remove_files",
|
||||
"ui_update_title",
|
||||
"max_workers",
|
||||
"max_workers_per_extractor",
|
||||
"default_preset",
|
||||
|
|
|
|||
|
|
@ -285,7 +285,7 @@
|
|||
import { useStorage } from '@vueuse/core';
|
||||
import { watch } from 'vue';
|
||||
import Hls from 'hls.js';
|
||||
import { disableOpacity, enableOpacity } from '~/utils';
|
||||
import { disableOpacity, enableOpacity, formatPageTitle } from '~/utils';
|
||||
import { useKeyboardShortcuts } from '~/composables/useKeyboardShortcuts';
|
||||
|
||||
import type { StoreItem } from '~/types/store';
|
||||
|
|
@ -319,6 +319,8 @@ const havePoster = ref(false);
|
|||
const showHelp = ref(false);
|
||||
const usingHls = ref(false);
|
||||
|
||||
useHead(() => (title.value ? { title: formatPageTitle(`Playing: ${title.value}`) } : {}));
|
||||
|
||||
let unbindMediaSessionListeners: null | (() => void) = null;
|
||||
let hls: Hls | null = null;
|
||||
let cleanupKeyboardShortcuts: null | (() => void) = null;
|
||||
|
|
@ -679,10 +681,6 @@ onBeforeUnmount(() => {
|
|||
unbindMediaSessionListeners = null;
|
||||
}
|
||||
|
||||
if (title.value) {
|
||||
window.document.title = 'YTPTube';
|
||||
}
|
||||
|
||||
if (!video.value) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -706,10 +704,6 @@ const prepareVideoPlayer = () => {
|
|||
|
||||
applyMediaSessionMetadata();
|
||||
|
||||
if (title.value) {
|
||||
window.document.title = `YTPTube - Playing: ${title.value}`;
|
||||
}
|
||||
|
||||
if (!video.value) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ const state = reactive<ConfigState>({
|
|||
app: {
|
||||
download_path: '/downloads',
|
||||
remove_files: false,
|
||||
ui_update_title: true,
|
||||
output_template: '',
|
||||
ytdlp_version: '',
|
||||
max_workers: 20,
|
||||
|
|
|
|||
|
|
@ -497,6 +497,7 @@ import { useStorage } from '@vueuse/core';
|
|||
import moment from 'moment';
|
||||
import { useMediaQuery } from '~/composables/useMediaQuery';
|
||||
import type { toastPosition } from '~/composables/useNotification';
|
||||
import { formatPageTitle } from '~/utils';
|
||||
import type { YTDLPOption } from '~/types/ytdlp';
|
||||
import { useDialog } from '~/composables/useDialog';
|
||||
import Dialog from '~/components/Dialog.vue';
|
||||
|
|
@ -750,10 +751,17 @@ const sidebarItems = computed<
|
|||
.filter((section) => section.items.some((group) => group.length > 0));
|
||||
});
|
||||
|
||||
const pageTitle = computed(() => {
|
||||
const match = getActiveNavItem(route, navigationAvailability.value);
|
||||
return match?.navbarTitle || match?.label || 'YTPTube';
|
||||
});
|
||||
const activeNavItem = computed(() => getActiveNavItem(route, navigationAvailability.value));
|
||||
|
||||
const pageTitle = computed(
|
||||
() => activeNavItem.value?.navbarTitle || activeNavItem.value?.label || 'YTPTube',
|
||||
);
|
||||
|
||||
const documentTitle = computed(() => activeNavItem.value?.pageLabel || pageTitle.value);
|
||||
|
||||
useHead(() => ({
|
||||
title: formatPageTitle(documentTitle.value),
|
||||
}));
|
||||
|
||||
const buildTooltip = computed(
|
||||
() =>
|
||||
|
|
|
|||
|
|
@ -527,6 +527,7 @@ import moment from 'moment';
|
|||
import { useStorage } from '@vueuse/core';
|
||||
import type { DropdownMenuItem } from '@nuxt/ui';
|
||||
import type { FileItem } from '~/types/filebrowser';
|
||||
import { formatPageTitle } from '~/utils';
|
||||
import { requirePageShell } from '~/utils/topLevelNavigation';
|
||||
|
||||
const route = useRoute();
|
||||
|
|
@ -559,6 +560,7 @@ const pageShell = requirePageShell('files');
|
|||
const hasItems = computed(() => filteredItems.value.length > 0);
|
||||
const hasSelected = computed(() => selectedElms.value.length > 0);
|
||||
const displayedItemPaths = computed(() => filteredItems.value.map((item) => item.path));
|
||||
const browserPageTitle = computed(() => `File Browser: /${sTrim(browserPath.value || '/', '/')}`);
|
||||
const currentDirectoryName = computed(
|
||||
() => breadcrumbItems.value[breadcrumbItems.value.length - 1]?.name || 'Home',
|
||||
);
|
||||
|
|
@ -752,6 +754,10 @@ const itemSizeLabel = (item: FileItem): string => {
|
|||
return item.type === 'file' ? formatBytes(item.size) : ucFirst(item.type);
|
||||
};
|
||||
|
||||
useHead(() => ({
|
||||
title: formatPageTitle(decodeURIComponent(browserPageTitle.value)),
|
||||
}));
|
||||
|
||||
const updateUrl = (dir: string, page?: number): void => {
|
||||
const normalizedDir = dir.replace(/^\/+/, '').replace(/\/+$/, '');
|
||||
const displayDir = normalizedDir ? normalizedDir : '/';
|
||||
|
|
@ -762,8 +768,6 @@ const updateUrl = (dir: string, page?: number): void => {
|
|||
if (fullUrl !== window.location.href) {
|
||||
history.replaceState({ path: normalizedDir || '/', title }, title, stateUrl);
|
||||
}
|
||||
|
||||
useHead({ title: decodeURIComponent(title) });
|
||||
};
|
||||
|
||||
const handleClick = (item: FileItem): void => {
|
||||
|
|
|
|||
|
|
@ -193,8 +193,6 @@ const toast = useNotification();
|
|||
const config = useYtpConfig();
|
||||
const pageShell = requirePageShell('changelog');
|
||||
|
||||
useHead({ title: 'CHANGELOG' });
|
||||
|
||||
const PROJECT = 'ytptube';
|
||||
const REPO = `https://github.com/arabcoders/${PROJECT}`;
|
||||
const REPO_URL = `https://arabcoders.github.io/${PROJECT}/CHANGELOG.json?version={version}`;
|
||||
|
|
|
|||
|
|
@ -327,8 +327,6 @@ import type { AutoCompleteOptions } from '~/types/autocomplete';
|
|||
import { disableOpacity, enableOpacity } from '~/utils';
|
||||
import { requirePageShell } from '~/utils/topLevelNavigation';
|
||||
|
||||
useHead({ title: 'Console' });
|
||||
|
||||
const MAX_HISTORY_ITEMS = 50;
|
||||
const ACTIVE_SESSION_STATUSES = ['starting', 'running', 'reconnecting'];
|
||||
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@
|
|||
<script setup lang="ts">
|
||||
import Markdown from '~/components/Markdown.vue';
|
||||
import { DOCS_ENTRIES, getDocsEntryBySlug } from '~/composables/useDocs';
|
||||
import { formatPageTitle } from '~/utils';
|
||||
import { requirePageShell } from '~/utils/topLevelNavigation';
|
||||
|
||||
const route = useRoute();
|
||||
|
|
@ -71,7 +72,7 @@ const docEntry = computed(() => {
|
|||
const pageShell = computed(() => requirePageShell(docEntry.value.id));
|
||||
|
||||
useHead(() => ({
|
||||
title: docEntry.value.title,
|
||||
title: formatPageTitle(docEntry.value.title),
|
||||
}));
|
||||
|
||||
const pageCardUi = {
|
||||
|
|
|
|||
|
|
@ -781,8 +781,7 @@ const embed_url = ref('');
|
|||
const isRefreshing = ref(false);
|
||||
const autoRefreshInterval = ref<ReturnType<typeof setInterval> | null>(null);
|
||||
|
||||
const queueCount = computed(() => stateStore.count());
|
||||
const hasQueueContent = computed(() => queueCount.value > 0 || query.value.trim().length > 0);
|
||||
const hasQueueContent = computed(() => stateStore.count() > 0 || query.value.trim().length > 0);
|
||||
const contentStyle = computed<'grid' | 'list'>(() =>
|
||||
isMobile.value ? 'grid' : display_style.value,
|
||||
);
|
||||
|
|
@ -812,14 +811,6 @@ const thumbnailRatioClass = computed(() =>
|
|||
thumbnail_ratio.value === 'is-16by9' ? 'aspect-video' : 'aspect-[3/1]',
|
||||
);
|
||||
|
||||
const getTitle = (): string => {
|
||||
if (!config.app.ui_update_title) {
|
||||
return 'YTPTube';
|
||||
}
|
||||
|
||||
return `YTPTube: ( ${stateStore.count()}/${config.app.max_workers}:${config.app.max_workers_per_extractor} )`;
|
||||
};
|
||||
|
||||
const refreshQueue = async (): Promise<void> => {
|
||||
if (isRefreshing.value) {
|
||||
return;
|
||||
|
|
@ -871,8 +862,6 @@ onMounted(async () => {
|
|||
window.history.replaceState({}, '', url.toString());
|
||||
}
|
||||
|
||||
useHead({ title: getTitle() });
|
||||
|
||||
if (Object.keys(pendingDownloadFormItem.value).length > 0) {
|
||||
await toNewDownload(pendingDownloadFormItem.value);
|
||||
pendingDownloadFormItem.value = {};
|
||||
|
|
@ -891,18 +880,6 @@ watch(toggleFilter, () => {
|
|||
}
|
||||
});
|
||||
|
||||
watch(
|
||||
() => stateStore.queue,
|
||||
() => {
|
||||
if (!config.app.ui_update_title) {
|
||||
return;
|
||||
}
|
||||
|
||||
useHead({ title: getTitle() });
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
|
||||
watch(
|
||||
() => socket.isConnected,
|
||||
(connected) => {
|
||||
|
|
|
|||
|
|
@ -497,8 +497,6 @@ onBeforeUnmount(() => {
|
|||
scrollTimeout = null;
|
||||
}
|
||||
});
|
||||
|
||||
useHead({ title: 'Logs' });
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
|||
2
ui/app/types/config.d.ts
vendored
2
ui/app/types/config.d.ts
vendored
|
|
@ -7,8 +7,6 @@ type AppConfig = {
|
|||
download_path: string;
|
||||
/** Indicates if files should be removed after download */
|
||||
remove_files: boolean;
|
||||
/** Indicates if the UI should update the title with the current download status */
|
||||
ui_update_title: boolean;
|
||||
/** Output template for yt-dlp, e.g. "%(title)s.%(ext)s" */
|
||||
output_template: string;
|
||||
/** yt-dlp version, e.g. "2023.10.01" */
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import type { convert_args_response, Paginated } from '~/types/responses';
|
|||
import type { StoreItem } from '~/types/store';
|
||||
|
||||
const AG_SEPARATOR = '.';
|
||||
const APP_TITLE = 'YTPTube';
|
||||
|
||||
const separators = [
|
||||
{ name: 'Comma', value: ',' },
|
||||
|
|
@ -971,7 +972,18 @@ const parse_api_error = async (json: unknown): Promise<string> => {
|
|||
return 'Unknown error occurred';
|
||||
};
|
||||
|
||||
const formatPageTitle = (title?: string | null): string => {
|
||||
const normalized = title?.trim();
|
||||
|
||||
if (!normalized || normalized === APP_TITLE) {
|
||||
return APP_TITLE;
|
||||
}
|
||||
|
||||
return `${normalized} | ${APP_TITLE}`;
|
||||
};
|
||||
|
||||
export {
|
||||
APP_TITLE,
|
||||
separators,
|
||||
convertCliOptions,
|
||||
getSeparatorsName,
|
||||
|
|
@ -1019,4 +1031,5 @@ export {
|
|||
parse_list_response,
|
||||
parse_api_response,
|
||||
parse_api_error,
|
||||
formatPageTitle,
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue