From bfb1f9c5db26eaa2781478de3ab7f85a1bcbeada Mon Sep 17 00:00:00 2001 From: "J. Lavoie" Date: Thu, 16 Nov 2023 17:33:35 +0000 Subject: [PATCH 001/707] Translated using Weblate (German) Currently translated at 100.0% (726 of 726 strings) Translation: FreeTube/Translations Translate-URL: https://hosted.weblate.org/projects/free-tube/translations/de/ --- static/locales/de-DE.yaml | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/static/locales/de-DE.yaml b/static/locales/de-DE.yaml index 086e9a973..03df018a4 100644 --- a/static/locales/de-DE.yaml +++ b/static/locales/de-DE.yaml @@ -427,7 +427,7 @@ Settings: Hide Chapters: Kapitel ausblenden Hide Upcoming Premieres: Anstehende Premieren ausblenden Hide Channels: Videos aus Kanälen ausblenden - Hide Channels Placeholder: Kanalname oder Kanal-ID + Hide Channels Placeholder: Kanal-ID Display Titles Without Excessive Capitalisation: Titel ohne übermäßige Großschreibung anzeigen Hide Channel Playlists: Kanal-Wiedergabelisten ausblenden @@ -448,6 +448,12 @@ Settings: Blur Thumbnails: Vorschaubilder unscharf machen Hide Profile Pictures in Comments: Profilbilder in den Kommentaren ausblenden Hide Subscriptions Community: Abo-Gemeinschaft ausblenden + Hide Channels Invalid: Kanal-ID war ungültig + Hide Channels Disabled Message: Einige Kanäle wurden mit ID gesperrt und nicht + verarbeitet. Die Funktion wird blockiert, während diese IDs aktualisieren + Hide Channels Already Exists: Kanal-ID bereits vorhanden + Hide Channels API Error: Fehler beim Abrufen von Benutzern mit der bereitgestellten + ID. Bitte überprüfen Sie erneut, ob der Ausweis korrekt ist. The app needs to restart for changes to take effect. Restart and apply change?: Die App muss neu gestartet werden, damit die Änderungen wirksam werden. Neu starten und Änderung übernehmen? @@ -1021,11 +1027,10 @@ Tooltips: und aktiviert einen benutzerdefinierten In-Memory-Image-Cache. Dies führt zu einer erhöhten RAM-Auslastung. Distraction Free Settings: - Hide Channels: Gebe einen Kanalnamen oder eine Kanal-ID ein, um zu verhindern, - dass alle Videos, Wiedergabelisten und der Kanal selbst in der Suche, den Trends, - den beliebtesten und den empfohlenen Videos angezeigt werden. Der eingegebene - Kanalname muss vollständig übereinstimmen und es wird zwischen Groß- und Kleinschreibung - unterschieden. + Hide Channels: Gebe eine Kanal-ID ein, um zu verhindern, dass alle Videos, Wiedergabelisten + und der Kanal selbst in der Suche, den Trends, den beliebtesten und den empfohlenen + Videos angezeigt werden. Die eingegebene Kanal-ID muss vollständig übereinstimmen + und es wird zwischen Groß- und Kleinschreibung unterschieden. Hide Subscriptions Live: Diese Einstellung wird durch die App-weite Einstellung „{appWideSetting}“ im Abschnitt „{subsection}“ der „{settingsSection}“ außer Kraft gesetzt From b19a6661623201b3cd58d95f04e70006810107d5 Mon Sep 17 00:00:00 2001 From: "J. Lavoie" Date: Thu, 16 Nov 2023 17:34:44 +0000 Subject: [PATCH 002/707] Translated using Weblate (French) Currently translated at 100.0% (726 of 726 strings) Translation: FreeTube/Translations Translate-URL: https://hosted.weblate.org/projects/free-tube/translations/fr/ --- static/locales/fr-FR.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/locales/fr-FR.yaml b/static/locales/fr-FR.yaml index 1200b6e56..5a9b91d7d 100644 --- a/static/locales/fr-FR.yaml +++ b/static/locales/fr-FR.yaml @@ -464,7 +464,7 @@ Settings: Hide Channels Disabled Message: Certaines chaînes ont été bloquées à l'aide d'un identifiant et n'ont pas été traitées. La fonctionnalité est bloquée tant que ces identifiants sont mis à jour - Hide Channels Already Exists: ID de chaîne déjà existant + Hide Channels Already Exists: L'identifiant de la chaîne existe déjà Hide Channels API Error: Erreur de récupération de l'utilisateur portant l'identifiant fourni. Veuillez vérifier à nouveau si l'ID est correct. The app needs to restart for changes to take effect. Restart and apply change?: L'application From 466fb39ee632848f3499688eca1a5a9ea0cda830 Mon Sep 17 00:00:00 2001 From: "J. Lavoie" Date: Thu, 16 Nov 2023 17:35:46 +0000 Subject: [PATCH 003/707] Translated using Weblate (English (United Kingdom)) Currently translated at 100.0% (726 of 726 strings) Translation: FreeTube/Translations Translate-URL: https://hosted.weblate.org/projects/free-tube/translations/en_GB/ --- static/locales/en_GB.yaml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/static/locales/en_GB.yaml b/static/locales/en_GB.yaml index d6595d791..5ba44273f 100644 --- a/static/locales/en_GB.yaml +++ b/static/locales/en_GB.yaml @@ -427,7 +427,7 @@ Settings: Hide Sharing Actions: Hide sharing actions Hide Chapters: Hide chapters Hide Channels: Hide videos from channels - Hide Channels Placeholder: Channel name or ID + Hide Channels Placeholder: Channel ID Display Titles Without Excessive Capitalisation: Display Titles Without Excessive Capitalisation Hide Featured Channels: Hide featured channels @@ -447,6 +447,12 @@ Settings: Hide Subscriptions Videos: Hide subscriptions videos Hide Subscriptions Community: Hide subscriptions community Hide Profile Pictures in Comments: Hide profile pictures in comments + Hide Channels Invalid: Channel ID provided was invalid + Hide Channels Disabled Message: Some channels were blocked using ID and weren't + processed. Feature is blocked while those IDs are updating + Hide Channels Already Exists: Channel ID already exists + Hide Channels API Error: Error retrieving user with the ID provided. Please check + again if the ID is correct. The app needs to restart for changes to take effect. Restart and apply change?: The app needs to restart for changes to take effect. Do you want to restart and apply the changes? @@ -957,9 +963,9 @@ Tooltips: Replace HTTP Cache: Disables Electron's disk-based HTTP cache and enables a custom in-memory image cache. Will lead to increased RAM usage. Distraction Free Settings: - Hide Channels: Enter a channel name or channel ID to hide all videos, playlists - and the channel itself from appearing in search, trending, most popular and - recommended. The channel name entered must be a complete match and is case sensitive. + Hide Channels: Enter a channel ID to hide all videos, playlists and the channel + itself from appearing in search, trending, most popular and recommended. The + channel ID entered must be a complete match and is case sensitive. Hide Subscriptions Live: This setting is overridden by the app-wide ‘{appWideSetting}’ setting, in the ‘{subsection}’ section of the ‘{settingsSection}’ SponsorBlock Settings: From c70dc6a5be09df2322b05af22ff35f4cc37708b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=DA=95=D8=A7=D8=B3=D8=AA=DB=8C?= Date: Thu, 16 Nov 2023 16:21:51 +0000 Subject: [PATCH 004/707] Translated using Weblate (Kurdish (Central)) Currently translated at 13.9% (101 of 726 strings) Translation: FreeTube/Translations Translate-URL: https://hosted.weblate.org/projects/free-tube/translations/ckb/ --- static/locales/ckb.yaml | 204 ++++++++++++++++++++-------------------- 1 file changed, 103 insertions(+), 101 deletions(-) diff --git a/static/locales/ckb.yaml b/static/locales/ckb.yaml index 3142e8420..246c1fb83 100644 --- a/static/locales/ckb.yaml +++ b/static/locales/ckb.yaml @@ -1,53 +1,55 @@ # Put the name of your locale in the same language -Locale Name: '' -FreeTube: '' +Locale Name: 'ئیگلیزی (وڵاتە یەکگرتووەکانی ئەمریکا)' +FreeTube: 'فریتیوب' # Currently on Subscriptions, Playlists, and History -'This part of the app is not ready yet. Come back later when progress has been made.': > +'This part of the app is not ready yet. Come back later when progress has been made.': >- + بەشێک لە بەرنامۆچکە هێشتا ئامادە نییە. کە ڕەوتەکە درووست کرا دووبارە وەرەوە. # Webkit Menu Bar -File: '' -New Window: '' -Preferences: '' -Quit: '' -Edit: '' -Undo: '' -Redo: '' -Cut: '' -Copy: '' -Paste: '' -Delete: '' -Select all: '' -Reload: '' -Force Reload: '' -Toggle Developer Tools: '' -Actual size: '' +File: 'پەڕگە' +New Window: 'پەنجەرەی نوێ' +Preferences: 'هەڵبژاردەکان' +Quit: 'دەرچوون' +Edit: 'دەستکاری' +Undo: 'پووچکردنەوە' +Redo: 'کردنەوە' +Cut: 'بڕین' +Copy: 'لەبەرگرتنەوە' +Paste: 'لکاندن' +Delete: 'سڕینەوە' +Select all: 'دیاریکردنی گشتیان' +Reload: 'بارکردنەوە' +Force Reload: 'باکردنەوەی بەزۆر' +Toggle Developer Tools: 'زامنی ئامرازەکانی گەشەپێدەر' +Actual size: 'قەبارەی ڕاستەقینە' Zoom in: '' Zoom out: '' Toggle fullscreen: '' -Window: '' +Window: 'پەنجەرە' Minimize: '' -Close: '' -Back: '' -Forward: '' -Open New Window: '' +Close: 'داخستن' +Back: 'دواوە' +Forward: 'پێشەوە' +Open New Window: 'کردنەوەی پەنجەرەیەکی نوێ' -Version {versionNumber} is now available! Click for more details: '' -Download From Site: '' +Version {versionNumber} is now available! Click for more details: 'وەشانی {versionNumber} + ئێستا بەردەستە! بۆ زانیاری زۆرتر کرتە بکە' +Download From Site: 'داگرتن لە وێبگە' A new blog is now available, {blogTitle}. Click to view more: '' -Are you sure you want to open this link?: '' +Are you sure you want to open this link?: 'دڵنیایت دەتەوێت ئەم بەستەرە بکەیتەوە؟' # Global # Anything shared among components / views should be put here Global: - Videos: '' + Videos: 'ڤیدیۆکان' Shorts: '' - Live: '' + Live: 'ڕاستەوخۆ' Community: '' Counts: - Video Count: '' - Channel Count: '' - Subscriber Count: '' - View Count: '' + Video Count: '١ ڤیدیۆ | {count} ڤیدیۆ' + Channel Count: '١ کەناڵ | {count} کەناڵ' + Subscriber Count: '١ بەشداربوو | {count} بەشداربوو' + View Count: 'بینینەک | {count} بینین' Watching Count: '' # Search Bar @@ -58,32 +60,32 @@ Search Bar: Search Filters: Search Filters: '' Sort By: - Sort By: '' + Sort By: 'ڕیزکردن بە' Most Relevant: '' - Rating: '' - Upload Date: '' + Rating: 'هەڵسەنگاندن' + Upload Date: 'ڕێکەوتی بارکردن' View Count: '' Time: - Time: '' - Any Time: '' - Last Hour: '' - Today: '' - This Week: '' - This Month: '' - This Year: '' + Time: 'کات' + Any Time: 'هەر کاتێک' + Last Hour: 'پێش کاتژمێرێک' + Today: 'ئەمڕۆ' + This Week: 'ئەم هەفتەیە' + This Month: 'ئەم مانگە' + This Year: 'ئەمساڵ' Type: - Type: '' - All Types: '' - Videos: '' - Channels: '' - Movies: '' + Type: 'جۆر' + All Types: 'گشت جۆرەکان' + Videos: 'ڤیدیۆ' + Channels: 'کەناڵ' + Movies: 'فیلم' #& Playlists Duration: - Duration: '' - All Durations: '' - Short (< 4 minutes): '' - Medium (4 - 20 minutes): '' - Long (> 20 minutes): '' + Duration: 'ماوە' + All Durations: 'گشت ماوەکان' + Short (< 4 minutes): 'کورت (< ٤ خولەک)' + Medium (4 - 20 minutes): 'ناوەند (٤ - ٢٠ خولەک)' + Long (> 20 minutes): 'درێژ (> ٢٠ خولەک)' # On Search Page Search Results: '' Fetching results. Please wait: '' @@ -99,32 +101,32 @@ Subscriptions: This profile has a large number of subscriptions. Forcing RSS to avoid rate limiting: '' 'Your Subscription list is currently empty. Start adding subscriptions to see them here.': '' Disabled Automatic Fetching: '' - Empty Channels: '' + Empty Channels: 'کەناڵە بەشداربووەکانت هێشتا هیچ ڤیدیۆیەکیان نییە.' 'Getting Subscriptions. Please wait.': '' Empty Posts: '' Refresh Subscriptions: '' - Load More Videos: '' + Load More Videos: 'بارکردنی ڤیدیۆی زۆرتر' Load More Posts: '' Subscriptions Tabs: '' All Subscription Tabs Hidden: '' -More: '' +More: 'زۆرتر' Channels: - Channels: '' - Title: '' + Channels: 'کەناڵەکان' + Title: 'پێڕستی کەناڵەکان' Search bar placeholder: '' - Count: '' - Empty: '' + Count: '{number} کەناڵ دۆزرانەوە.' + Empty: 'ئێستا پێڕستی کەناڵەکانت بەتاڵە.' Unsubscribe: '' Unsubscribed: '' Unsubscribe Prompt: '' Trending: Trending: '' Default: '' - Music: '' - Gaming: '' - Movies: '' + Music: 'مۆسیقا' + Gaming: 'یاری' + Movies: 'فیلم' Trending Tabs: '' -Most Popular: '' +Most Popular: 'باوترین' Playlists: '' User Playlists: Your Playlists: '' @@ -134,17 +136,17 @@ User Playlists: Search bar placeholder: '' History: # On History Page - History: '' - Watch History: '' + History: 'مێژوو' + Watch History: 'مێژووی تەمەشاکردن' Your history list is currently empty.: '' Empty Search Message: '' Search bar placeholder: "" Settings: # On Settings Page - Settings: '' + Settings: 'ڕێکخستنەکان' The app needs to restart for changes to take effect. Restart and apply change?: '' General Settings: - General Settings: '' + General Settings: 'ڕێکخستنە گشتییەکان' Check for Updates: '' Check for Latest Blog Posts: '' Fallback to Non-Preferred Backend on Failure: '' @@ -159,14 +161,14 @@ Settings: Video View Type: Video View Type: '' Grid: '' - List: '' + List: 'پێڕست' Thumbnail Preference: Thumbnail Preference: '' Default: '' Beginning: '' - Middle: '' - End: '' - Hidden: '' + Middle: 'ناوەڕاست' + End: 'کۆتایی' + Hidden: 'شاراوە' Blur: '' Current Invidious Instance: '' The currently set default instance is {instance}: '' @@ -179,11 +181,11 @@ Settings: #! List countries External Link Handling: External Link Handling: '' - Open Link: '' - Ask Before Opening Link: '' - No Action: '' + Open Link: 'کردنەوەی بەستەر' + Ask Before Opening Link: 'پێش کردنەوەی بەستەر بپرسە' + No Action: 'هیچ مەکە' Theme Settings: - Theme Settings: '' + Theme Settings: 'ڕێکخستنەکانی ڕووکار' Match Top Bar with Main Color: '' Expand Side Bar by Default: '' Disable Smooth Scrolling: '' @@ -192,32 +194,32 @@ Settings: Hide FreeTube Header Logo: '' Base Theme: Base Theme: '' - Black: '' - Dark: '' + Black: 'ڕەش' + Dark: 'تاریک' System Default: '' - Light: '' + Light: 'ڕووناک' Dracula: '' Catppuccin Mocha: '' Pastel Pink: '' Hot Pink: '' Main Color Theme: - Main Color Theme: '' - Red: '' - Pink: '' - Purple: '' - Deep Purple: '' + Main Color Theme: 'ڕەنگی سەرەکی ڕووکار' + Red: 'سوور' + Pink: 'پەمبە' + Purple: 'وەنەوشەیی' + Deep Purple: 'وەنەوشەیی تۆخ' Indigo: '' - Blue: '' - Light Blue: '' + Blue: 'شین' + Light Blue: 'شینی ئاڵ' Cyan: '' Teal: '' - Green: '' - Light Green: '' + Green: 'کەسک' + Light Green: 'کەسکی ئاڵ' Lime: '' - Yellow: '' + Yellow: 'زەرد' Amber: '' - Orange: '' - Deep Orange: '' + Orange: 'نارنجی' + Deep Orange: 'نارنجی تۆخ' Dracula Cyan: '' Dracula Green: '' Dracula Orange: '' @@ -239,14 +241,14 @@ Settings: Catppuccin Mocha Sapphire: '' Catppuccin Mocha Blue: '' Catppuccin Mocha Lavender: '' - Secondary Color Theme: '' + Secondary Color Theme: 'ڕەنگی لاوەکی ڕووکار' #* Main Color Theme Player Settings: - Player Settings: '' + Player Settings: 'ڕێکخستنەکانی لێدەر' Force Local Backend for Legacy Formats: '' - Play Next Video: '' + Play Next Video: 'لێدانی ڤیدیۆی دواتر' Turn on Subtitles by Default: '' - Autoplay Videos: '' + Autoplay Videos: 'خۆلێدانی ڤیدیۆ' Proxy Videos Through Invidious: '' Autoplay Playlists: '' Enable Theatre Mode by Default: '' @@ -268,7 +270,7 @@ Settings: Audio Formats: '' Default Quality: Default Quality: '' - Auto: '' + Auto: 'خۆکار' 144p: '' 240p: '' 360p: '' @@ -285,7 +287,7 @@ Settings: Quality Label: '' Ask Path: '' Folder Label: '' - Folder Button: '' + Folder Button: 'دیاریکردنی بوخچە' File Name Label: '' File Name Tooltip: '' Error: @@ -294,16 +296,16 @@ Settings: Comment Auto Load: Comment Auto Load: '' External Player Settings: - External Player Settings: '' - External Player: '' + External Player Settings: 'ڕێکخستنەکانی لێدەری دەرەکی' + External Player: 'لێدەری دەرەکی' Ignore Unsupported Action Warnings: '' Custom External Player Executable: '' Custom External Player Arguments: '' Players: None: - Name: '' + Name: 'هیچیان' Privacy Settings: - Privacy Settings: '' + Privacy Settings: 'ڕێکخستنەکانی نهێنێتی' Remember History: '' Save Watched Progress: '' Save Watched Videos With Last Viewed Playlist: '' From 582df9543efd314f39983ff60d986c809ab99fa4 Mon Sep 17 00:00:00 2001 From: absidue <48293849+absidue@users.noreply.github.com> Date: Fri, 17 Nov 2023 03:08:10 +0100 Subject: [PATCH 005/707] Move hideOutlines to the utils store instead of using provide/inject (#4246) --- src/constants.js | 6 ---- src/renderer/App.js | 28 ++++++------------- src/renderer/App.vue | 2 +- .../components/ft-prompt/ft-prompt.js | 11 ++++---- src/renderer/store/modules/utils.js | 17 +++++++++++ src/renderer/views/Channel/Channel.js | 5 +--- .../views/Subscriptions/Subscriptions.js | 11 ++++---- src/renderer/views/Trending/Trending.js | 11 ++++---- 8 files changed, 46 insertions(+), 45 deletions(-) diff --git a/src/constants.js b/src/constants.js index 4693d8576..bd80da2ff 100644 --- a/src/constants.js +++ b/src/constants.js @@ -70,11 +70,6 @@ const SyncEvents = { } } -// https://v2.vuejs.org/v2/api/#provide-inject -const Injectables = { - SHOW_OUTLINES: 'showOutlines' -} - // Utils const MAIN_PROFILE_ID = 'allChannels' @@ -82,6 +77,5 @@ export { IpcChannels, DBActions, SyncEvents, - Injectables, MAIN_PROFILE_ID } diff --git a/src/renderer/App.js b/src/renderer/App.js index 21db0394f..81185f934 100644 --- a/src/renderer/App.js +++ b/src/renderer/App.js @@ -10,7 +10,7 @@ import FtButton from './components/ft-button/ft-button.vue' import FtToast from './components/ft-toast/ft-toast.vue' import FtProgressBar from './components/ft-progress-bar/ft-progress-bar.vue' import { marked } from 'marked' -import { Injectables, IpcChannels } from '../constants' +import { IpcChannels } from '../constants' import packageDetails from '../../package.json' import { openExternalLink, openInternalPath, showToast } from './helpers/utils' @@ -30,15 +30,9 @@ export default defineComponent({ FtToast, FtProgressBar }, - provide: function () { - return { - [Injectables.SHOW_OUTLINES]: this.showOutlines - } - }, data: function () { return { dataReady: false, - hideOutlines: true, showUpdatesBanner: false, showBlogBanner: false, showReleaseNotes: false, @@ -59,6 +53,9 @@ export default defineComponent({ showProgressBar: function () { return this.$store.getters.getShowProgressBar }, + outlinesHidden: function () { + return this.$store.getters.getOutlinesHidden + }, isLocaleRightToLeft: function () { return this.locale === 'ar' || this.locale === 'fa' || this.locale === 'he' || this.locale === 'ur' || this.locale === 'yi' || this.locale === 'ku' @@ -291,7 +288,7 @@ export default defineComponent({ activateKeyboardShortcuts: function () { document.addEventListener('keydown', this.handleKeyboardShortcuts) document.addEventListener('mousedown', () => { - this.hideOutlines = true + this.hideOutlines() }) }, @@ -316,7 +313,7 @@ export default defineComponent({ } switch (event.key) { case 'Tab': - this.hideOutlines = false + this.showOutlines() break case 'L': case 'l': @@ -517,15 +514,6 @@ export default defineComponent({ } }, - /** - * provided to all child components, see `provide` near the top of this file - * after injecting it, they can show outlines during keyboard navigation - * e.g. cycling through tabs with the arrow keys - */ - showOutlines: function () { - this.hideOutlines = false - }, - ...mapMutations([ 'setInvidiousInstancesList' ]), @@ -542,7 +530,9 @@ export default defineComponent({ 'setupListenersToSyncWindows', 'updateBaseTheme', 'updateMainColor', - 'updateSecColor' + 'updateSecColor', + 'showOutlines', + 'hideOutlines' ]) } }) diff --git a/src/renderer/App.vue b/src/renderer/App.vue index ed2ec6545..e0394fae9 100644 --- a/src/renderer/App.vue +++ b/src/renderer/App.vue @@ -3,7 +3,7 @@ v-if="dataReady" id="app" :class="{ - hideOutlines: hideOutlines, + hideOutlines: outlinesHidden, isLocaleRightToLeft: isLocaleRightToLeft }" > diff --git a/src/renderer/components/ft-prompt/ft-prompt.js b/src/renderer/components/ft-prompt/ft-prompt.js index d52a93daf..f6fbf0b55 100644 --- a/src/renderer/components/ft-prompt/ft-prompt.js +++ b/src/renderer/components/ft-prompt/ft-prompt.js @@ -1,8 +1,8 @@ import { defineComponent } from 'vue' +import { mapActions } from 'vuex' import FtCard from '../../components/ft-card/ft-card.vue' import FtFlexBox from '../../components/ft-flex-box/ft-flex-box.vue' import FtButton from '../../components/ft-button/ft-button.vue' -import { Injectables } from '../../../constants' import { sanitizeForHtmlId } from '../../helpers/accessibility' export default defineComponent({ @@ -12,9 +12,6 @@ export default defineComponent({ 'ft-flex-box': FtFlexBox, 'ft-button': FtButton }, - inject: { - showOutlines: Injectables.SHOW_OUTLINES - }, props: { label: { type: String, @@ -101,6 +98,10 @@ export default defineComponent({ const direction = (e.key === 'ArrowLeft') ? -1 : 1 this.focusItem(parseInt(currentIndex) + direction) } - } + }, + + ...mapActions([ + 'showOutlines' + ]) } }) diff --git a/src/renderer/store/modules/utils.js b/src/renderer/store/modules/utils.js index a8ca1498d..4ec7a5df6 100644 --- a/src/renderer/store/modules/utils.js +++ b/src/renderer/store/modules/utils.js @@ -19,6 +19,7 @@ import { const state = { isSideNavOpen: false, + outlinesHidden: true, sessionSearchHistory: [], popularCache: null, trendingCache: { @@ -51,6 +52,10 @@ const getters = { return state.isSideNavOpen }, + getOutlinesHidden() { + return state.outlinesHidden + }, + getCurrentVolume () { return state.currentVolume }, @@ -117,6 +122,14 @@ const getters = { } const actions = { + showOutlines({ commit }) { + commit('setOutlinesHidden', false) + }, + + hideOutlines({ commit }) { + commit('setOutlinesHidden', true) + }, + async downloadMedia({ rootState }, { url, title, extension, fallingBackPath }) { if (!process.env.IS_ELECTRON) { openExternalLink(url) @@ -633,6 +646,10 @@ const mutations = { state.isSideNavOpen = !state.isSideNavOpen }, + setOutlinesHidden(state, value) { + state.outlinesHidden = value + }, + setShowProgressBar (state, value) { state.showProgressBar = value }, diff --git a/src/renderer/views/Channel/Channel.js b/src/renderer/views/Channel/Channel.js index af5f1f815..1cec8b70d 100644 --- a/src/renderer/views/Channel/Channel.js +++ b/src/renderer/views/Channel/Channel.js @@ -32,7 +32,6 @@ import { parseLocalListVideo, parseLocalSubscriberCount } from '../../helpers/api/local' -import { Injectables } from '../../../constants' export default defineComponent({ name: 'Channel', @@ -48,9 +47,6 @@ export default defineComponent({ 'ft-subscribe-button': FtSubscribeButton, 'channel-about': ChannelAbout }, - inject: { - showOutlines: Injectables.SHOW_OUTLINES - }, data: function () { return { isLoading: false, @@ -1870,6 +1866,7 @@ export default defineComponent({ }, ...mapActions([ + 'showOutlines', 'updateSubscriptionDetails' ]) } diff --git a/src/renderer/views/Subscriptions/Subscriptions.js b/src/renderer/views/Subscriptions/Subscriptions.js index b6bb7244a..c36ff32cd 100644 --- a/src/renderer/views/Subscriptions/Subscriptions.js +++ b/src/renderer/views/Subscriptions/Subscriptions.js @@ -1,4 +1,5 @@ import { defineComponent } from 'vue' +import { mapActions } from 'vuex' import SubscriptionsVideos from '../../components/subscriptions-videos/subscriptions-videos.vue' import SubscriptionsLive from '../../components/subscriptions-live/subscriptions-live.vue' @@ -7,7 +8,6 @@ import SubscriptionsCommunity from '../../components/subscriptions-community/sub import FtCard from '../../components/ft-card/ft-card.vue' import FtFlexBox from '../../components/ft-flex-box/ft-flex-box.vue' -import { Injectables } from '../../../constants' export default defineComponent({ name: 'Subscriptions', @@ -19,9 +19,6 @@ export default defineComponent({ 'ft-card': FtCard, 'ft-flex-box': FtFlexBox }, - inject: { - showOutlines: Injectables.SHOW_OUTLINES - }, data: function () { return { currentTab: 'videos' @@ -148,6 +145,10 @@ export default defineComponent({ this.$refs[visibleTabs[index]].focus() this.showOutlines() } - } + }, + + ...mapActions([ + 'showOutlines' + ]) } }) diff --git a/src/renderer/views/Trending/Trending.js b/src/renderer/views/Trending/Trending.js index 1aa453333..d308c9c88 100644 --- a/src/renderer/views/Trending/Trending.js +++ b/src/renderer/views/Trending/Trending.js @@ -1,4 +1,5 @@ import { defineComponent } from 'vue' +import { mapActions } from 'vuex' import FtCard from '../../components/ft-card/ft-card.vue' import FtLoader from '../../components/ft-loader/ft-loader.vue' import FtElementList from '../../components/ft-element-list/ft-element-list.vue' @@ -8,7 +9,6 @@ import FtFlexBox from '../../components/ft-flex-box/ft-flex-box.vue' import { copyToClipboard, showToast } from '../../helpers/utils' import { getLocalTrending } from '../../helpers/api/local' import { invidiousAPICall } from '../../helpers/api/invidious' -import { Injectables } from '../../../constants' export default defineComponent({ name: 'Trending', @@ -19,9 +19,6 @@ export default defineComponent({ 'ft-icon-button': FtIconButton, 'ft-flex-box': FtFlexBox }, - inject: { - showOutlines: Injectables.SHOW_OUTLINES - }, data: function () { return { isLoading: false, @@ -191,6 +188,10 @@ export default defineComponent({ } break } - } + }, + + ...mapActions([ + 'showOutlines' + ]) } }) From c57daa8cb27c227868d8214c07a506e492787517 Mon Sep 17 00:00:00 2001 From: Benjababe Date: Fri, 17 Nov 2023 11:05:53 +0800 Subject: [PATCH 006/707] add image to poll & updated quiz style (#4318) --- .../ft-community-poll/ft-community-poll.css | 35 +++++++++++++------ .../ft-community-poll/ft-community-poll.js | 6 ++++ .../ft-community-poll/ft-community-poll.vue | 7 +++- 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/src/renderer/components/ft-community-poll/ft-community-poll.css b/src/renderer/components/ft-community-poll/ft-community-poll.css index 5c8dc43d0..c35738a1b 100644 --- a/src/renderer/components/ft-community-poll/ft-community-poll.css +++ b/src/renderer/components/ft-community-poll/ft-community-poll.css @@ -11,9 +11,7 @@ display: block; float: var(--float-left-ltr-rtl-value); block-size: 10px; - inset-inline-start: 5px; position: relative; - inset-block-start: 8px; inline-size: 10px; } @@ -29,30 +27,45 @@ } .option-text { - border-radius: 5px; - border-style: solid; - border-width: 2px; - padding-block: 5px; - padding-inline: 25px; + margin-inline-start: 10px; } .option { + display: flex; + align-items: center; padding-block-end: 10px; + border-radius: 5px; + border-style: solid; + border-width: 1px; + padding-block: 5px; + padding-inline-start: 10px; + margin-block-end: 10px; +} + +.option > img { + margin-inline-start: 10px; + block-size: 125px; } .correct-option { + border-color: #78da71; + border-width: 2px; +} + +.correct-option .filled-circle { background-color: #78da71; } .incorrect-option { - background-color: #dd4e4e; + border-color: #dd4e4e; + border-width: 2px; } -.reveal-answer { - text-align: center; +.reveal-answer { + justify-content: center; cursor: pointer; } -.reveal-answer:hover > .option-text, .reveal-answer:focus > .option-text { +.reveal-answer:hover, .reveal-answer:focus { background-color: var(--side-nav-hover-color) } diff --git a/src/renderer/components/ft-community-poll/ft-community-poll.js b/src/renderer/components/ft-community-poll/ft-community-poll.js index 866bc3bad..fb44894cd 100644 --- a/src/renderer/components/ft-community-poll/ft-community-poll.js +++ b/src/renderer/components/ft-community-poll/ft-community-poll.js @@ -18,5 +18,11 @@ export default defineComponent({ formattedVotes: function () { return formatNumber(this.data.totalVotes) }, + }, + methods: { + // Use smallest as it's resized to 125px anyways and they're usually all larger than that + findSmallestPollImage: function (images) { + return images.reduce((prev, img) => (img.height < prev.height) ? img : prev, images[0]).url + } } }) diff --git a/src/renderer/components/ft-community-poll/ft-community-poll.vue b/src/renderer/components/ft-community-poll/ft-community-poll.vue index fc7f90470..0f3151a8f 100644 --- a/src/renderer/components/ft-community-poll/ft-community-poll.vue +++ b/src/renderer/components/ft-community-poll/ft-community-poll.vue @@ -13,13 +13,13 @@
{{ choice.text }}
@@ -29,6 +29,11 @@ class="option poll-option" > +
{{ choice.text }}
From ce3dbdc6350ff31c7ea1ba1b897749796c8966b4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Nov 2023 13:13:49 +0000 Subject: [PATCH 007/707] Bump actions/github-script from 6 to 7 (#4361) Bumps [actions/github-script](https://github.com/actions/github-script) from 6 to 7. - [Release notes](https://github.com/actions/github-script/releases) - [Commits](https://github.com/actions/github-script/compare/v6...v7) --- updated-dependencies: - dependency-name: actions/github-script dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ca7fcd2f9..63a54a471 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -64,7 +64,7 @@ jobs: - name: Set Version Number Variable id: versionNumber - uses: actions/github-script@v6 + uses: actions/github-script@v7 env: IS_DEV: ${{ contains(github.ref, 'development') }} IS_RC: ${{ contains(github.ref, 'RC') }} From 1f3f1c84c988bac69e9dbc4683b55852c502a756 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Nov 2023 13:15:33 +0000 Subject: [PATCH 008/707] Bump the eslint group with 1 update (#4360) Bumps the eslint group with 1 update: [eslint](https://github.com/eslint/eslint). - [Release notes](https://github.com/eslint/eslint/releases) - [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md) - [Commits](https://github.com/eslint/eslint/compare/v8.53.0...v8.54.0) --- updated-dependencies: - dependency-name: eslint dependency-type: direct:development update-type: version-update:semver-minor dependency-group: eslint ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index be152bc19..137d47d5a 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ "css-minimizer-webpack-plugin": "^5.0.1", "electron": "^27.0.4", "electron-builder": "^24.6.4", - "eslint": "^8.53.0", + "eslint": "^8.54.0", "eslint-config-prettier": "^9.0.0", "eslint-config-standard": "^17.1.0", "eslint-plugin-import": "^2.29.0", diff --git a/yarn.lock b/yarn.lock index 7525f8f41..4c6de495d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1206,10 +1206,10 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@8.53.0": - version "8.53.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.53.0.tgz#bea56f2ed2b5baea164348ff4d5a879f6f81f20d" - integrity sha512-Kn7K8dx/5U6+cT1yEhpX1w4PCSg0M+XyRILPgvwcEBjerFWCwQj5sbr3/VmxqV0JGHCBCzyd6LxypEuehypY1w== +"@eslint/js@8.54.0": + version "8.54.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.54.0.tgz#4fab9a2ff7860082c304f750e94acd644cf984cf" + integrity sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ== "@fastify/busboy@^2.0.0": version "2.0.0" @@ -3857,15 +3857,15 @@ eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4 resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== -eslint@^8.53.0: - version "8.53.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.53.0.tgz#14f2c8244298fcae1f46945459577413ba2697ce" - integrity sha512-N4VuiPjXDUa4xVeV/GC/RV3hQW9Nw+Y463lkWaKKXKYMvmRiRDAtfpuPFLN+E1/6ZhyR8J2ig+eVREnYgUsiag== +eslint@^8.54.0: + version "8.54.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.54.0.tgz#588e0dd4388af91a2e8fa37ea64924074c783537" + integrity sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA== dependencies: "@eslint-community/eslint-utils" "^4.2.0" "@eslint-community/regexpp" "^4.6.1" "@eslint/eslintrc" "^2.1.3" - "@eslint/js" "8.53.0" + "@eslint/js" "8.54.0" "@humanwhocodes/config-array" "^0.11.13" "@humanwhocodes/module-importer" "^1.0.1" "@nodelib/fs.walk" "^1.2.8" From 74598a62b699db2719378d055c88ae8723fe898f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Nov 2023 13:17:36 +0000 Subject: [PATCH 009/707] Bump electron from 27.0.4 to 27.1.0 (#4363) Bumps [electron](https://github.com/electron/electron) from 27.0.4 to 27.1.0. - [Release notes](https://github.com/electron/electron/releases) - [Changelog](https://github.com/electron/electron/blob/main/docs/breaking-changes.md) - [Commits](https://github.com/electron/electron/compare/v27.0.4...v27.1.0) --- updated-dependencies: - dependency-name: electron dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 137d47d5a..fca6fde36 100644 --- a/package.json +++ b/package.json @@ -89,7 +89,7 @@ "copy-webpack-plugin": "^11.0.0", "css-loader": "^6.8.1", "css-minimizer-webpack-plugin": "^5.0.1", - "electron": "^27.0.4", + "electron": "^27.1.0", "electron-builder": "^24.6.4", "eslint": "^8.54.0", "eslint-config-prettier": "^9.0.0", diff --git a/yarn.lock b/yarn.lock index 4c6de495d..88c111144 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3432,10 +3432,10 @@ electron-to-chromium@^1.4.535: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.554.tgz#04e09c2ee31dc0f1546174033809b54cc372740b" integrity sha512-Q0umzPJjfBrrj8unkONTgbKQXzXRrH7sVV7D9ea2yBV3Oaogz991yhbpfvo2LMNkJItmruXTEzVpP9cp7vaIiQ== -electron@^27.0.4: - version "27.0.4" - resolved "https://registry.yarnpkg.com/electron/-/electron-27.0.4.tgz#2666c61d0e14f470edb4d8ba7eb6c9171588e53a" - integrity sha512-ob29rN1mtiyAXzF8HsHd5jh8bYKd9OQDakfdOExi0F7epU97gXPHaj6JPjbBJ/vpki5d32SyKVePW4vxeNZk1A== +electron@^27.1.0: + version "27.1.0" + resolved "https://registry.yarnpkg.com/electron/-/electron-27.1.0.tgz#d759885e552d7d926526cfc433ab312796f74a9a" + integrity sha512-XPdJiO475QJ8cx59/goWNNWnlV0vab+Ut3occymos7VDxkHV5mFrlW6tcGi+M3bW6gBfwpJocWMng8tw542vww== dependencies: "@electron/get" "^2.0.0" "@types/node" "^18.11.18" From e7310bd47917667b7b70d3b6bd5f497b83754e98 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Nov 2023 13:25:45 +0000 Subject: [PATCH 010/707] Bump @silvermine/videojs-quality-selector from 1.3.0 to 1.3.1 (#4362) Bumps [@silvermine/videojs-quality-selector](https://github.com/silvermine/videojs-quality-selector) from 1.3.0 to 1.3.1. - [Changelog](https://github.com/silvermine/videojs-quality-selector/blob/master/CHANGELOG.md) - [Commits](https://github.com/silvermine/videojs-quality-selector/compare/v1.3.0...v1.3.1) --- updated-dependencies: - dependency-name: "@silvermine/videojs-quality-selector" dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index fca6fde36..2aa6c85e6 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "@fortawesome/free-solid-svg-icons": "^6.4.2", "@fortawesome/vue-fontawesome": "^2.0.10", "@seald-io/nedb": "^4.0.2", - "@silvermine/videojs-quality-selector": "^1.3.0", + "@silvermine/videojs-quality-selector": "^1.3.1", "autolinker": "^4.0.0", "electron-context-menu": "^3.6.1", "lodash.debounce": "^4.0.8", diff --git a/yarn.lock b/yarn.lock index 88c111144..a2ef9530a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1431,10 +1431,10 @@ localforage "^1.9.0" util "^0.12.4" -"@silvermine/videojs-quality-selector@^1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@silvermine/videojs-quality-selector/-/videojs-quality-selector-1.3.0.tgz#6527d73929edea60419b0a189d4babbc21cb2600" - integrity sha512-Ps63kVXHyod0vNEEtogkVtE+8I6ozMTcRowAPqKF1Ggjr0yl7d8L2fGCnHL919MV2tBRVxnGpYaMmVVcRq6Hjw== +"@silvermine/videojs-quality-selector@^1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@silvermine/videojs-quality-selector/-/videojs-quality-selector-1.3.1.tgz#23307dd3d5be442f7aa127c01820f16a3d9476a3" + integrity sha512-uo6gs2HVG2TD0bpZAl0AT6RkDXzk9PnAxtmmW5zXexa2uJvkdFT64QvJoMlEUd2FUUwqYqqAuWGFDJdBh5+KcQ== dependencies: underscore "1.13.1" From 58fe474d9fa9305b689c92ac7476de6293c791ee Mon Sep 17 00:00:00 2001 From: Jason <84899178+jasonhenriquez@users.noreply.github.com> Date: Mon, 20 Nov 2023 20:01:18 +0000 Subject: [PATCH 011/707] Make landing page configurable (#4200) * Implement customizable landing pages * Implement curated list for default landing page dropdown options * Update top nav link to redirect back to selected landing page * Update top nav title to be 'Go to {page}' for improved clarity * Remove landing page from selection and/or restore selection to default if is no longer valid --- src/renderer/App.js | 14 ++- .../general-settings/general-settings.js | 51 +++++++--- .../general-settings/general-settings.vue | 1 - src/renderer/components/top-nav/top-nav.js | 14 +++ src/renderer/components/top-nav/top-nav.vue | 8 +- src/renderer/router/index.js | 95 ++++++++++--------- static/locales/en-US.yaml | 1 + 7 files changed, 120 insertions(+), 64 deletions(-) diff --git a/src/renderer/App.js b/src/renderer/App.js index 81185f934..ea50ffe27 100644 --- a/src/renderer/App.js +++ b/src/renderer/App.js @@ -108,6 +108,10 @@ export default defineComponent({ return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light' }, + landingPage: function() { + return '/' + this.$store.getters.getLandingPage + }, + externalLinkOpeningPromptNames: function () { return [ this.$t('Yes'), @@ -133,7 +137,7 @@ export default defineComponent({ $route () { // react to route changes... // Hide top nav filter panel on page change - this.$refs.topNav.hideFilters() + this.$refs.topNav?.hideFilters() } }, created () { @@ -175,7 +179,13 @@ export default defineComponent({ }) this.$router.afterEach((to, from) => { - this.$refs.topNav.navigateHistory() + this.$refs.topNav?.navigateHistory() + }) + + this.$router.onReady(() => { + if (this.$router.currentRoute.path !== this.landingPage && this.landingPage !== '/subscriptions') { + this.$router.push({ path: this.landingPage }) + } }) }) }, diff --git a/src/renderer/components/general-settings/general-settings.js b/src/renderer/components/general-settings/general-settings.js index 589ebb53e..d682bbba5 100644 --- a/src/renderer/components/general-settings/general-settings.js +++ b/src/renderer/components/general-settings/general-settings.js @@ -27,20 +27,6 @@ export default defineComponent({ 'invidious', 'local' ], - defaultPageNames: [ - 'Subscriptions', - 'Trending', - 'Most Popular', - 'Playlists', - 'History' - ], - defaultPageValues: [ - 'subscriptions', - 'trending', - 'mostPopular', - 'playlists', - 'history' - ], viewTypeValues: [ 'grid', 'list' @@ -57,6 +43,15 @@ export default defineComponent({ '', 'openLinkAfterPrompt', 'doNothing' + ], + includedDefaultPageNames: [ + 'subscriptions', + 'subscribedChannels', + 'trending', + 'popular', + 'userPlaylists', + 'history', + 'settings' ] } }, @@ -79,10 +74,38 @@ export default defineComponent({ checkForBlogPosts: function () { return this.$store.getters.getCheckForBlogPosts }, + hidePlaylists: function () { + return this.$store.getters.getHidePlaylists + }, + hidePopularVideos: function () { + return this.$store.getters.getHidePopularVideos + }, + hideTrendingVideos: function () { + return this.$store.getters.getHideTrendingVideos + }, + defaultPages: function () { + let includedPageNames = this.includedDefaultPageNames + if (this.hideTrendingVideos) includedPageNames = includedPageNames.filter((pageName) => pageName !== 'trending') + if (this.hidePlaylists) includedPageNames = includedPageNames.filter((pageName) => pageName !== 'userPlaylists') + if (!(!this.hidePopularVideos && (this.backendFallback || this.backendPreference === 'invidious'))) includedPageNames = includedPageNames.filter((pageName) => pageName !== 'popular') + return this.$router.getRoutes().filter((route) => includedPageNames.includes(route.name)) + }, + defaultPageNames: function () { + return this.defaultPages.map((route) => this.$t(route.meta.title)) + }, + defaultPageValues: function () { + // avoid Vue parsing issues by excluding '/' from path values + return this.defaultPages.map((route) => route.path.substring(1)) + }, backendPreference: function () { return this.$store.getters.getBackendPreference }, landingPage: function () { + const landingPage = this.$store.getters.getLandingPage + // invalidate landing page selection & restore to default value if no longer valid + if (!this.defaultPageValues.includes(landingPage)) { + this.updateLandingPage('subscriptions') + } return this.$store.getters.getLandingPage }, region: function () { diff --git a/src/renderer/components/general-settings/general-settings.vue b/src/renderer/components/general-settings/general-settings.vue index 0279708b8..0aad1a08b 100644 --- a/src/renderer/components/general-settings/general-settings.vue +++ b/src/renderer/components/general-settings/general-settings.vue @@ -43,7 +43,6 @@ @change="handlePreferredApiBackend" /> route.path === '/' + this.landingPage) + .meta.title + ) + }) + }, + enableSearchSuggestions: function () { return this.$store.getters.getEnableSearchSuggestions }, diff --git a/src/renderer/components/top-nav/top-nav.vue b/src/renderer/components/top-nav/top-nav.vue index 03cd544ce..69a54ab70 100644 --- a/src/renderer/components/top-nav/top-nav.vue +++ b/src/renderer/components/top-nav/top-nav.vue @@ -59,10 +59,10 @@ dir="ltr" role="link" tabindex="0" - :title="$t('Subscriptions.Subscriptions')" - @click="navigate('subscriptions')" - @keydown.space.prevent="navigate('subscriptions')" - @keydown.enter.prevent="navigate('subscriptions')" + :title="headerLogoTitle" + @click="navigate(landingPage)" + @keydown.space.prevent="navigate(landingPage)" + @keydown.enter.prevent="navigate(landingPage)" >
Date: Mon, 20 Nov 2023 22:04:22 +0000 Subject: [PATCH 012/707] Translated using Weblate (Spanish) Currently translated at 100.0% (727 of 727 strings) Translation: FreeTube/Translations Translate-URL: https://hosted.weblate.org/projects/free-tube/translations/es/ --- static/locales/es.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/static/locales/es.yaml b/static/locales/es.yaml index a905606ca..28d065f85 100644 --- a/static/locales/es.yaml +++ b/static/locales/es.yaml @@ -1072,3 +1072,4 @@ Playlist will pause when current video is finished: La lista de reproducción se cuando termine el vídeo actual Playlist will not pause when current video is finished: La lista de reproducción no se detendrá cuando termine el vídeo actual +Go to page: Ir a la {page} From b49a2618481a025b69c3258ecab3ebbd89719316 Mon Sep 17 00:00:00 2001 From: Eric Date: Tue, 21 Nov 2023 00:47:24 +0000 Subject: [PATCH 013/707] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (727 of 727 strings) Translation: FreeTube/Translations Translate-URL: https://hosted.weblate.org/projects/free-tube/translations/zh_Hans/ --- static/locales/zh-CN.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/static/locales/zh-CN.yaml b/static/locales/zh-CN.yaml index 38f3b1e4f..b56ed5dc7 100644 --- a/static/locales/zh-CN.yaml +++ b/static/locales/zh-CN.yaml @@ -935,3 +935,4 @@ Hashtag: This hashtag does not currently have any videos: 此话题标签下当前没有任何短视频 Playlist will pause when current video is finished: 当前视频播完后播放列表会暂停 Playlist will not pause when current video is finished: 当前视频播完后播放列表不会暂停 +Go to page: 转到页{page} From 86bad257f55d3ee75eb70804b66caaeb671ad006 Mon Sep 17 00:00:00 2001 From: Mitchel Paulin Date: Mon, 20 Nov 2023 21:04:41 -0500 Subject: [PATCH 014/707] Add hide channel option directly to More Options menu (#4228) * Add hide channel option directly to More Options menu * Added ability to unhide channels as well from the same menu * Fix issue where unhide would not work with channelId * Replace filter with some * Remove extra hide channel * Hide by channelId rather than name * Shuffle lang terms to put channel name at the front * Do not check channel name anymore * One more spot * Fixed lang terms --- .../components/ft-list-video/ft-list-video.js | 41 ++++++++++++++++++- static/locales/en-US.yaml | 4 ++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/renderer/components/ft-list-video/ft-list-video.js b/src/renderer/components/ft-list-video/ft-list-video.js index b141ff21d..c3219b4ac 100644 --- a/src/renderer/components/ft-list-video/ft-list-video.js +++ b/src/renderer/components/ft-list-video/ft-list-video.js @@ -228,8 +228,25 @@ export default defineComponent({ { label: this.$t('Video.Open Channel in Invidious'), value: 'openInvidiousChannel' + }, + { + type: 'divider' } ) + + const hiddenChannels = JSON.parse(this.$store.getters.getChannelsHidden) + const channelShouldBeHidden = hiddenChannels.some(c => c === this.channelId) + if (channelShouldBeHidden) { + options.push({ + label: this.$t('Video.Unhide Channel'), + value: 'unhideChannel' + }) + } else { + options.push({ + label: this.$t('Video.Hide Channel'), + value: 'hideChannel' + }) + } } } @@ -434,6 +451,12 @@ export default defineComponent({ case 'openInvidiousChannel': openExternalLink(this.invidiousChannelUrl) break + case 'hideChannel': + this.hideChannel(this.channelName, this.channelId) + break + case 'unhideChannel': + this.unhideChannel(this.channelName, this.channelId) + break } }, @@ -621,12 +644,28 @@ export default defineComponent({ showToast(this.$t('Video.Video has been removed from your saved list')) }, + hideChannel: function(channelName, channelId) { + const hiddenChannels = JSON.parse(this.$store.getters.getChannelsHidden) + hiddenChannels.push(channelId) + this.updateChannelsHidden(JSON.stringify(hiddenChannels)) + + showToast(this.$t('Channel Hidden', { channel: channelName })) + }, + + unhideChannel: function(channelName, channelId) { + const hiddenChannels = JSON.parse(this.$store.getters.getChannelsHidden) + this.updateChannelsHidden(JSON.stringify(hiddenChannels.filter(c => c !== channelId))) + + showToast(this.$t('Channel Unhidden', { channel: channelName })) + }, + ...mapActions([ 'openInExternalPlayer', 'updateHistory', 'removeFromHistory', 'addVideo', - 'removeVideo' + 'removeVideo', + 'updateChannelsHidden' ]) } }) diff --git a/static/locales/en-US.yaml b/static/locales/en-US.yaml index f257cb9e9..2a1117259 100644 --- a/static/locales/en-US.yaml +++ b/static/locales/en-US.yaml @@ -628,6 +628,8 @@ Video: Copy YouTube Channel Link: Copy YouTube Channel Link Open Channel in Invidious: Open Channel in Invidious Copy Invidious Channel Link: Copy Invidious Channel Link + Hide Channel: Hide Channel + Unhide Channel: Show Channel Views: Views Loop Playlist: Loop Playlist Shuffle Playlist: Shuffle Playlist @@ -925,6 +927,8 @@ Starting download: 'Starting download of "{videoTitle}"' Downloading failed: 'There was an issue downloading "{videoTitle}"' Screenshot Success: Saved screenshot as "{filePath}" Screenshot Error: Screenshot failed. {error} +Channel Hidden: '{channel} added to channel filter' +Channel Unhidden: '{channel} removed from channel filter' Hashtag: Hashtag: Hashtag From 3fc2e547c9b7d4635fa2092e19927bd4a9057d62 Mon Sep 17 00:00:00 2001 From: Jason <84899178+jasonhenriquez@users.noreply.github.com> Date: Tue, 21 Nov 2023 02:11:15 +0000 Subject: [PATCH 015/707] Update to silently allow channel links (with IDs) (#4347) --- src/renderer/components/ft-input-tags/ft-input-tags.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/renderer/components/ft-input-tags/ft-input-tags.js b/src/renderer/components/ft-input-tags/ft-input-tags.js index f51715995..0c04f021b 100644 --- a/src/renderer/components/ft-input-tags/ft-input-tags.js +++ b/src/renderer/components/ft-input-tags/ft-input-tags.js @@ -46,8 +46,8 @@ export default defineComponent({ }, methods: { updateTags: async function (text, _e) { - // text entered add tag and update tag list - const name = text.trim() + // get text without spaces after last '/' in url, if any + const name = text.split('/').pop().trim() if (!this.validateTagName(name)) { this.$emit('invalid-name') From c219926c5e91b1ff902a724d0accaa36447edc6e Mon Sep 17 00:00:00 2001 From: absidue <48293849+absidue@users.noreply.github.com> Date: Tue, 21 Nov 2023 03:22:29 +0100 Subject: [PATCH 016/707] Fix block channel channel ID validation (#4366) --- .../components/distraction-settings/distraction-settings.js | 6 +++--- src/renderer/helpers/channels.js | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/renderer/components/distraction-settings/distraction-settings.js b/src/renderer/components/distraction-settings/distraction-settings.js index 6b3c82aca..c70420664 100644 --- a/src/renderer/components/distraction-settings/distraction-settings.js +++ b/src/renderer/components/distraction-settings/distraction-settings.js @@ -5,7 +5,7 @@ import FtToggleSwitch from '../ft-toggle-switch/ft-toggle-switch.vue' import FtInputTags from '../../components/ft-input-tags/ft-input-tags.vue' import FtFlexBox from '../ft-flex-box/ft-flex-box.vue' import { showToast } from '../../helpers/utils' -import { checkYoutubeId, findChannelTagInfo } from '../../helpers/channels' +import { checkYoutubeChannelId, findChannelTagInfo } from '../../helpers/channels' export default defineComponent({ name: 'PlayerSettings', @@ -152,7 +152,7 @@ export default defineComponent({ showToast(this.$t('Settings.Distraction Free Settings.Hide Channels Already Exists')) }, validateChannelId: function (text) { - return checkYoutubeId(text) + return checkYoutubeChannelId(text) }, findChannelTagInfo: async function (text) { return await findChannelTagInfo(text, this.backendOptions) @@ -167,7 +167,7 @@ export default defineComponent({ if (tag.invalid) continue // process if no preferred name and is possibly a YouTube ID - if (tag.preferredName === '' && checkYoutubeId(tag.name)) { + if (tag.preferredName === '' && checkYoutubeChannelId(tag.name)) { this.channelHiderDisabled = true const { preferredName, icon, iconHref, invalidId } = await this.findChannelTagInfo(tag.name) diff --git a/src/renderer/helpers/channels.js b/src/renderer/helpers/channels.js index bcc9da20c..888c13178 100644 --- a/src/renderer/helpers/channels.js +++ b/src/renderer/helpers/channels.js @@ -43,7 +43,7 @@ async function findChannelById(id, backendOptions) { * @returns {Promise<{icon: string, iconHref: string, preferredName: string} | { invalidId: boolean }>} */ export async function findChannelTagInfo(id, backendOptions) { - if (!/UC\S{22}/.test(id)) return { invalidId: true } + if (!checkYoutubeChannelId(id)) return { invalidId: true } try { const channel = await findChannelById(id, backendOptions) if (!process.env.IS_ELECTRON || backendOptions.preference === 'invidious') { @@ -71,6 +71,6 @@ export async function findChannelTagInfo(id, backendOptions) { * @param {string} id * @returns {boolean} */ -export function checkYoutubeId(id) { - return /UC\S{22}/.test(id) +export function checkYoutubeChannelId(id) { + return /^UC[\w-]{22}$/.test(id) } From ae4dedaeed327c5f2bcba936711a0e32c7ab82ae Mon Sep 17 00:00:00 2001 From: Massimo Pissarello Date: Tue, 21 Nov 2023 03:40:53 +0000 Subject: [PATCH 017/707] Translated using Weblate (Italian) Currently translated at 100.0% (731 of 731 strings) Translation: FreeTube/Translations Translate-URL: https://hosted.weblate.org/projects/free-tube/translations/it/ --- static/locales/it.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/static/locales/it.yaml b/static/locales/it.yaml index 2cfee824c..3943840a3 100644 --- a/static/locales/it.yaml +++ b/static/locales/it.yaml @@ -794,6 +794,8 @@ Video: chat dal vivo non è disponibile per questo video. Potrebbe essere stata disattivata dall'autore del caricamento. Pause on Current Video: Pausa sul video attuale + Unhide Channel: Mostra canale + Hide Channel: Nascondi canale Videos: #& Sort By Sort By: @@ -1082,3 +1084,6 @@ Playlist will pause when current video is finished: La playlist verrà messa in al termine del video attuale Playlist will not pause when current video is finished: La playlist non verrà messa in pausa al termine del video attuale +Channel Hidden: '{channel} aggiunto al filtro canali' +Go to page: Vai a {page} +Channel Unhidden: '{channel} rimosso dal filtro canali' From 55261487f984ef682fbc46a5943ae236fd995971 Mon Sep 17 00:00:00 2001 From: Jeff Huang Date: Tue, 21 Nov 2023 06:56:28 +0000 Subject: [PATCH 018/707] Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (731 of 731 strings) Translation: FreeTube/Translations Translate-URL: https://hosted.weblate.org/projects/free-tube/translations/zh_Hant/ --- static/locales/zh-TW.yaml | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/static/locales/zh-TW.yaml b/static/locales/zh-TW.yaml index cd7e48b40..2caf1973c 100644 --- a/static/locales/zh-TW.yaml +++ b/static/locales/zh-TW.yaml @@ -131,7 +131,7 @@ Settings: Preferred API Backend: Preferred API Backend: '偏好API伺服器' Local API: '本機 API' - Invidious API: 'Invidious API(應用程式介面)' + Invidious API: 'Invidious API' Video View Type: Video View Type: '影片觀看類別' Grid: '網格' @@ -141,7 +141,7 @@ Settings: Default: '預設' Beginning: '片頭' Middle: '中間' - End: '結尾' + End: '片尾' Hidden: 隱藏 Blur: 模糊 'Invidious Instance (Default is https://invidious.snopyta.org)': 'Invidious實例(預設為 @@ -410,7 +410,7 @@ Settings: Hide Channels Disabled Message: 某些頻道被使用 ID 封鎖且無法處理。當這些 ID 更新時,功能將會被封鎖 Hide Channels Already Exists: 頻道 ID 已存在 Hide Channels API Error: 使用提供的 ID 擷取使用者時發生錯誤。請再次檢查 ID 是否正確。 - The app needs to restart for changes to take effect. Restart and apply change?: 此變更需要重啟讓修改生效。重啟並且套用變更? + The app needs to restart for changes to take effect. Restart and apply change?: 必須重新啟動應用程式以生效。重新啟動並套用變更嗎? Proxy Settings: Error getting network information. Is your proxy configured properly?: 取得網路資訊時發生錯誤。您的代理伺服器設定正確嗎? City: 城市 @@ -590,12 +590,12 @@ Channel: Releases: 發布 This channel does not currently have any releases: 此頻道目前沒有任何發布 Video: - Open in YouTube: '在YouTube中開啟' - Copy YouTube Link: '複製YouTube連結' - Open YouTube Embedded Player: '開啟YouTube內嵌播放器' - Copy YouTube Embedded Player Link: '複製YouTube內嵌播放器連結' - Open in Invidious: '在Invidious中開啟' - Copy Invidious Link: '複製Invidious連結' + Open in YouTube: '在 YouTube 中開啟' + Copy YouTube Link: '複製 YouTube 連結' + Open YouTube Embedded Player: '開啟 YouTube 內嵌播放器' + Copy YouTube Embedded Player Link: '複製 YouTube 內嵌播放器連結' + Open in Invidious: '在 Invidious 中開啟' + Copy Invidious Link: '複製 Invidious 連結' Views: '觀看' Watched: '已觀看' # As in a Live Video @@ -661,10 +661,10 @@ Video: audio only: 僅音訊 video only: 僅影片 Download Video: 下載影片 - Copy Invidious Channel Link: 複製Invidious頻道連結 - Open Channel in Invidious: 在Invidious開啟頻道 - Copy YouTube Channel Link: 複製YouTube頻道連結 - Open Channel in YouTube: 在YouTube開啟頻道 + Copy Invidious Channel Link: 複製 Invidious 頻道連結 + Open Channel in Invidious: 在 Invidious 開啟頻道 + Copy YouTube Channel Link: 複製 YouTube 頻道連結 + Open Channel in YouTube: 在 YouTube 開啟頻道 Started streaming on: '開始直播時間' Streamed on: 直播於 Video has been removed from your saved list: 影片已從您的播放清單移除 @@ -722,6 +722,8 @@ Video: Upcoming: 即將到來 'Live Chat is unavailable for this stream. It may have been disabled by the uploader.': 即時聊天在此串流不可用。其可能被上傳者停用了。 Pause on Current Video: 暫停目前影片 + Unhide Channel: 顯示頻道 + Hide Channel: 隱藏頻道 Videos: #& Sort By Sort By: @@ -944,3 +946,6 @@ Hashtag: This hashtag does not currently have any videos: 此標籤目前沒有任何影片 Playlist will pause when current video is finished: 當目前影片結束時,播放清單將會暫停 Playlist will not pause when current video is finished: 當目前影片結束時,播放清單將不會暫停 +Channel Hidden: '{channel} 已新增至頻道過濾條件' +Go to page: 到 {page} +Channel Unhidden: '{channel} 已從頻道過濾條件移除' From 9d9a7691398607b0dec27605c09814fa13d48efe Mon Sep 17 00:00:00 2001 From: Fjuro Date: Tue, 21 Nov 2023 07:17:08 +0000 Subject: [PATCH 019/707] Translated using Weblate (Czech) Currently translated at 100.0% (731 of 731 strings) Translation: FreeTube/Translations Translate-URL: https://hosted.weblate.org/projects/free-tube/translations/cs/ --- static/locales/cs.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/static/locales/cs.yaml b/static/locales/cs.yaml index f4937dcee..2468582c1 100644 --- a/static/locales/cs.yaml +++ b/static/locales/cs.yaml @@ -806,6 +806,8 @@ Video: 'Live Chat is unavailable for this stream. It may have been disabled by the uploader.': Živý chat není pro tento stream k dispozici. Je možné, že byl vypnut nahrávajícím. Pause on Current Video: Pozastavit na současném videu + Unhide Channel: Zobrazit kanál + Hide Channel: Skrýt kanál Videos: #& Sort By Sort By: @@ -1036,3 +1038,6 @@ Playlist will pause when current video is finished: Po přehrání aktuálního playlist pozastaven Playlist will not pause when current video is finished: Po přehrání aktuálního videa nebude playlist pozastaven +Channel Hidden: Kanál {channel} přidán do filtru kanálů +Go to page: Přejít na {page} +Channel Unhidden: Kanál {channel} odebrán z filtrů kanálů From a9fd50227e51bf66d1a9837e3bf6fd8a12b93433 Mon Sep 17 00:00:00 2001 From: gallegonovato Date: Tue, 21 Nov 2023 09:11:11 +0000 Subject: [PATCH 020/707] Translated using Weblate (Spanish) Currently translated at 100.0% (731 of 731 strings) Translation: FreeTube/Translations Translate-URL: https://hosted.weblate.org/projects/free-tube/translations/es/ --- static/locales/es.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/static/locales/es.yaml b/static/locales/es.yaml index 28d065f85..d73a62006 100644 --- a/static/locales/es.yaml +++ b/static/locales/es.yaml @@ -827,6 +827,8 @@ Video: chat en vivo no está disponible para esta transmisión. Tal vez estaba deshabilitado antes de la retransmisión. Pause on Current Video: Pausa en el vídeo actual + Unhide Channel: Mostrar el canal + Hide Channel: Ocultar el canal Videos: #& Sort By Sort By: @@ -1073,3 +1075,5 @@ Playlist will pause when current video is finished: La lista de reproducción se Playlist will not pause when current video is finished: La lista de reproducción no se detendrá cuando termine el vídeo actual Go to page: Ir a la {page} +Channel Hidden: '{channel} añadido al filtro de canales' +Channel Unhidden: '{channel} eliminado del filtro de canales' From d1a7b84bf34d8a8f17e4389a0edcec04dbe2a419 Mon Sep 17 00:00:00 2001 From: absidue <48293849+absidue@users.noreply.github.com> Date: Tue, 21 Nov 2023 12:05:21 +0100 Subject: [PATCH 021/707] Display currently watching viewer count on live streams (#4206) * Display currently watching viewer count on live streams * Improve watching count styling Co-authored-by: Jason <84899178+jasonhenriquez@users.noreply.github.com> --------- Co-authored-by: Jason <84899178+jasonhenriquez@users.noreply.github.com> --- .../watch-video-live-chat.css | 7 +++++++ .../watch-video-live-chat.js | 20 ++++++++++++++++++- .../watch-video-live-chat.vue | 10 +++++++++- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/renderer/components/watch-video-live-chat/watch-video-live-chat.css b/src/renderer/components/watch-video-live-chat/watch-video-live-chat.css index fdf77ea22..d73676000 100644 --- a/src/renderer/components/watch-video-live-chat/watch-video-live-chat.css +++ b/src/renderer/components/watch-video-live-chat/watch-video-live-chat.css @@ -22,6 +22,13 @@ row-gap: 16px; } +.watchingCount { + font-weight: normal; + margin-inline-start: 5px; + font-size: 15px; + color: var(--tertiary-text-color); +} + .message { font-size: 18px; color: var(--tertiary-text-color); diff --git a/src/renderer/components/watch-video-live-chat/watch-video-live-chat.js b/src/renderer/components/watch-video-live-chat/watch-video-live-chat.js index 5eec0c10e..d225a6e3b 100644 --- a/src/renderer/components/watch-video-live-chat/watch-video-live-chat.js +++ b/src/renderer/components/watch-video-live-chat/watch-video-live-chat.js @@ -6,6 +6,7 @@ import FtButton from '../ft-button/ft-button.vue' import autolinker from 'autolinker' import { getRandomColorClass } from '../../helpers/colors' import { getLocalVideoInfo, parseLocalTextRuns } from '../../helpers/api/local' +import { formatNumber } from '../../helpers/utils' export default defineComponent({ name: 'WatchVideoLiveChat', @@ -30,6 +31,7 @@ export default defineComponent({ }, data: function () { return { + /** @type {import('youtubei.js').YT.LiveChat|null} */ liveChatInstance: null, isLoading: true, hasError: false, @@ -52,7 +54,9 @@ export default defineComponent({ amount: '', colorClass: '' } - } + }, + /** @type {number|null} */ + watchingCount: null, } }, computed: { @@ -74,6 +78,14 @@ export default defineComponent({ scrollingBehaviour: function () { return this.$store.getters.getDisableSmoothScrolling ? 'auto' : 'smooth' + }, + + hideVideoViews: function () { + return this.$store.getters.getHideVideoViews + }, + + formattedWatchingCount: function () { + return this.watchingCount !== null ? formatNumber(this.watchingCount) : '0' } }, beforeDestroy: function () { @@ -181,6 +193,12 @@ export default defineComponent({ } }) + this.liveChatInstance.on('metadata-update', metadata => { + if (!this.hideVideoViews && metadata.views && !isNaN(metadata.views.original_view_count)) { + this.watchingCount = metadata.views.original_view_count + } + }) + this.liveChatInstance.once('end', () => { this.hasEnded = true this.liveChatInstance = null diff --git a/src/renderer/components/watch-video-live-chat/watch-video-live-chat.vue b/src/renderer/components/watch-video-live-chat/watch-video-live-chat.vue index 3719372c1..f34c19913 100644 --- a/src/renderer/components/watch-video-live-chat/watch-video-live-chat.vue +++ b/src/renderer/components/watch-video-live-chat/watch-video-live-chat.vue @@ -42,7 +42,15 @@ v-else class="relative" > -

{{ $t("Video.Live Chat") }}

+

+ {{ $t("Video.Live Chat") }} + + {{ $tc('Global.Counts.Watching Count', watchingCount, { count: formattedWatchingCount }) }} + +

Date: Tue, 21 Nov 2023 11:59:04 +0000 Subject: [PATCH 022/707] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (731 of 731 strings) Translation: FreeTube/Translations Translate-URL: https://hosted.weblate.org/projects/free-tube/translations/zh_Hans/ --- static/locales/zh-CN.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/static/locales/zh-CN.yaml b/static/locales/zh-CN.yaml index b56ed5dc7..4dc656fd4 100644 --- a/static/locales/zh-CN.yaml +++ b/static/locales/zh-CN.yaml @@ -713,6 +713,8 @@ Video: Upcoming: 即将到来 'Live Chat is unavailable for this stream. It may have been disabled by the uploader.': 实时聊天对此音视频流不可用。上传者可能禁用了它。 Pause on Current Video: 当前视频播完后不自动播放列表中下一视频 + Unhide Channel: 显示频道 + Hide Channel: 隐藏频道 Videos: #& Sort By Sort By: @@ -936,3 +938,5 @@ Hashtag: Playlist will pause when current video is finished: 当前视频播完后播放列表会暂停 Playlist will not pause when current video is finished: 当前视频播完后播放列表不会暂停 Go to page: 转到页{page} +Channel Hidden: '{channel} 频道已添加到频道过滤器' +Channel Unhidden: 从频道过滤器删除了{channel} 频道 From cc870172908d3162f868b71b67eb2f2b9b011bac Mon Sep 17 00:00:00 2001 From: Rex_sa Date: Tue, 21 Nov 2023 13:41:24 +0000 Subject: [PATCH 023/707] Translated using Weblate (Arabic) Currently translated at 100.0% (731 of 731 strings) Translation: FreeTube/Translations Translate-URL: https://hosted.weblate.org/projects/free-tube/translations/ar/ --- static/locales/ar.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/static/locales/ar.yaml b/static/locales/ar.yaml index b5c132370..77382cc14 100644 --- a/static/locales/ar.yaml +++ b/static/locales/ar.yaml @@ -811,6 +811,8 @@ Video: 'Live Chat is unavailable for this stream. It may have been disabled by the uploader.': الدردشة المباشرة غير متاحة لهذا البث. ربما تم تعطيلها من قبل القائم بالتحميل. Pause on Current Video: توقف مؤقتًا على الفيديو الحالي + Unhide Channel: عرض القناة + Hide Channel: إخفاء القناة Videos: #& Sort By Sort By: @@ -1037,3 +1039,6 @@ Playlist will pause when current video is finished: ستتوقف قائمة ال انتهاء الفيديو الحالي Playlist will not pause when current video is finished: لن تتوقف قائمة التشغيل مؤقتًا عند انتهاء الفيديو الحالي +Channel Hidden: تم إضافة {channel} إلى مرشح القناة +Go to page: إذهب إلى {page} +Channel Unhidden: تمت إزالة {channel} من مرشح القناة From 91ceacd89d1757e93aaba73725300c8f9ff9100b Mon Sep 17 00:00:00 2001 From: NEXI Date: Tue, 21 Nov 2023 20:01:13 +0000 Subject: [PATCH 024/707] Translated using Weblate (Serbian) Currently translated at 100.0% (731 of 731 strings) Translation: FreeTube/Translations Translate-URL: https://hosted.weblate.org/projects/free-tube/translations/sr/ --- static/locales/sr.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/static/locales/sr.yaml b/static/locales/sr.yaml index 9069c65ec..696758980 100644 --- a/static/locales/sr.yaml +++ b/static/locales/sr.yaml @@ -761,6 +761,8 @@ Video: YouTube-ом. 'Live Chat is unavailable for this stream. It may have been disabled by the uploader.': Ћаскање уживо није доступно за овај стрим. Можда га је онемогућио аутор. + Unhide Channel: Прикажи канал + Hide Channel: Сакриј канал Tooltips: Subscription Settings: Fetch Feeds from RSS: 'Када је омогућено, FreeTube ће користити RSS уместо свог @@ -982,3 +984,6 @@ Screenshot Error: Снимак екрана није успео. {error} Downloading has completed: „{videoTitle}“ је завршио преузимање Loop is now enabled: Понављање је сада омогућено Downloading failed: Дошло је до проблема при преузимању „{videoTitle}“ +Channel Hidden: '{channel} је додат на филтер канала' +Go to page: Иди на {page} +Channel Unhidden: '{channel} је уклоњен из филтера канала' From 7b8d36023e6cc2899b12b95ee3af6cceda7e982f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Wed, 22 Nov 2023 11:25:35 +0000 Subject: [PATCH 025/707] Translated using Weblate (Estonian) Currently translated at 100.0% (731 of 731 strings) Translation: FreeTube/Translations Translate-URL: https://hosted.weblate.org/projects/free-tube/translations/et/ --- static/locales/et.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/static/locales/et.yaml b/static/locales/et.yaml index 6511a0ce5..2d27c9f9d 100644 --- a/static/locales/et.yaml +++ b/static/locales/et.yaml @@ -764,6 +764,8 @@ Video: 'Live Chat is unavailable for this stream. It may have been disabled by the uploader.': Otsevestlus pole selle videovoo puhul saadaval. Võib-olla on üleslaadija vestluse keelanud. Pause on Current Video: Peata hetkel esitatav video + Unhide Channel: Näita kanalit + Hide Channel: Peida kanal Videos: #& Sort By Sort By: @@ -991,3 +993,6 @@ Playlist will pause when current video is finished: Hetkel mängiva video lõppe esitusloendi esitamine peatub Playlist will not pause when current video is finished: Hetkel mängiva video lõppemisel esitusloendi esitamine jätkub +Channel Hidden: '{channel} on lisatud kanalite filtrisse' +Go to page: 'Ava leht: {page}' +Channel Unhidden: '{channel} on eemaldatud kanalite filtrist' From 62e7b439db1684ac86b0be95e7b689bd2df6be63 Mon Sep 17 00:00:00 2001 From: CelularBat <105959781+CelularBat@users.noreply.github.com> Date: Wed, 22 Nov 2023 16:14:54 +0000 Subject: [PATCH 026/707] Display more profiles on the profile drop-down list, v2 (fixed for low res, fixed linter) (#4359) * Update ft-profile-selector.css Fixed for low res, fixed linter complains * Update comment to max-block-size * comment to max-block-size fixed typo * Update ft-profile-selector.css adjust for screen with horizontal navbar (mobile) * Update src/renderer/components/ft-profile-selector/ft-profile-selector.css Co-authored-by: PikachuEXE * Update src/renderer/components/ft-profile-selector/ft-profile-selector.css Co-authored-by: PikachuEXE * Update src/renderer/components/ft-profile-selector/ft-profile-selector.css Co-authored-by: PikachuEXE --------- Co-authored-by: PikachuEXE --- .../ft-profile-selector.css | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/renderer/components/ft-profile-selector/ft-profile-selector.css b/src/renderer/components/ft-profile-selector/ft-profile-selector.css index 94ee6e91d..49d63c22a 100644 --- a/src/renderer/components/ft-profile-selector/ft-profile-selector.css +++ b/src/renderer/components/ft-profile-selector/ft-profile-selector.css @@ -27,7 +27,7 @@ inset-block-start: 60px; inset-inline-end: 10px; min-inline-size: 250px; - block-size: 400px; + block-size: auto; padding: 5px; background-color: var(--card-bg-color); box-shadow: 0 0 4px var(--scrollbar-color-hover); @@ -35,8 +35,22 @@ .profileWrapper { margin-block-start: 60px; - block-size: 340px; + block-size: auto; overflow-y: auto; + /* + profile list max height: 90% of window size - 100 px. It's scaled to be 340px on 800x600 resolution. + Offset of 100px is to compensate for the fixed size of elements above the list, which takes more screen space on lower resolutions + */ + max-block-size: calc(90vh - 100px); + min-block-size: 340px; +} + +/* Navbar changes position to horizontal with this media rule. +Height adjust for profile list so it won't cover navbar. */ +@media only screen and (max-width: 680px){ + .profileWrapper { + max-block-size: calc(95vh - 180px); + } } .profile { From e68c534e6c27436d24a9ae51c210c4fa2b1b37ae Mon Sep 17 00:00:00 2001 From: Jason <84899178+jasonhenriquez@users.noreply.github.com> Date: Wed, 22 Nov 2023 17:19:11 +0000 Subject: [PATCH 027/707] A new way to subscribe (#4238) * Implement styling for new subscribe button * Implement dropdown element and styling * Implements remaining styling and logic * Correct use of aria-selected in FT Note: was able to add aria-controls to ft-profile-selector because it keeps the hidden dropdown in the DOM. The same is not true of the ft-icon-button or ft-subscribe-button. Main point: aria-expanded should go on the button opening the dropdown, not the dropdown itself. * Resolve subscribe button staying upon bug * Remove unneeded vendor-specific transition prefixes See discussion here: https://www.web-plus-plus.com/Articles/css-transition-moz-and-webkit-vs-css3 --- .../ft-channel-bubble/ft-channel-bubble.css | 5 - .../ft-icon-button/ft-icon-button.vue | 3 +- src/renderer/components/ft-input/ft-input.css | 8 - .../ft-profile-bubble/ft-profile-bubble.css | 5 - .../ft-profile-selector.css | 5 - .../ft-profile-selector.js | 4 + .../ft-profile-selector.vue | 5 +- .../ft-subscribe-button.css | 8 - .../ft-subscribe-button.js | 89 +++++++++-- .../ft-subscribe-button.scss | 141 ++++++++++++++++++ .../ft-subscribe-button.vue | 87 ++++++++++- .../side-nav-more-options.css | 4 - src/renderer/components/side-nav/side-nav.css | 4 - src/renderer/main.js | 2 + src/renderer/views/Channel/Channel.css | 1 + .../SubscribedChannels/SubscribedChannels.vue | 3 +- static/locales/en-US.yaml | 2 + 17 files changed, 308 insertions(+), 68 deletions(-) delete mode 100644 src/renderer/components/ft-subscribe-button/ft-subscribe-button.css create mode 100644 src/renderer/components/ft-subscribe-button/ft-subscribe-button.scss diff --git a/src/renderer/components/ft-channel-bubble/ft-channel-bubble.css b/src/renderer/components/ft-channel-bubble/ft-channel-bubble.css index fcb7b96e5..1a4878d64 100644 --- a/src/renderer/components/ft-channel-bubble/ft-channel-bubble.css +++ b/src/renderer/components/ft-channel-bubble/ft-channel-bubble.css @@ -11,17 +11,12 @@ overflow: hidden; color: inherit; text-decoration: none; - -webkit-transition: background 0.2s ease-out; - -moz-transition: background 0.2s ease-out; - -o-transition: background 0.2s ease-out; transition: background 0.2s ease-out; } .bubblePadding:hover { background-color: var(--side-nav-hover-color); color: var(--side-nav-hover-text-color); - -moz-transition: background 0.2s ease-in; - -o-transition: background 0.2s ease-in; transition: background 0.2s ease-in; } diff --git a/src/renderer/components/ft-icon-button/ft-icon-button.vue b/src/renderer/components/ft-icon-button/ft-icon-button.vue index b1760e528..c699f4392 100644 --- a/src/renderer/components/ft-icon-button/ft-icon-button.vue +++ b/src/renderer/components/ft-icon-button/ft-icon-button.vue @@ -14,6 +14,7 @@ }" tabindex="0" role="button" + :aria-expanded="dropdownShown" @click="handleIconClick" @mousedown="handleIconMouseDown" @keydown.enter.prevent="handleIconClick" @@ -33,7 +34,6 @@ v-if="dropdownOptions.length > 0" class="list" role="listbox" - :aria-expanded="dropdownShown" >
  • { + return profile?.name?.length > 0 ? Array.from(profile.name)[0].toUpperCase() : '' + }) + }, + profileList: function () { return this.$store.getters.getProfileList }, + /* sort by 'All Channels' -> active profile -> unsubscribed channels -> subscribed channels */ + profileDisplayList: function () { + const mainProfileAndActiveProfile = [this.profileList[0]] + if (this.activeProfile._id !== MAIN_PROFILE_ID) { + mainProfileAndActiveProfile.push(this.activeProfile) + } + + return [ + ...mainProfileAndActiveProfile, + ...this.profileList.filter((profile, i) => + i !== 0 && !this.isActiveProfile(profile) && !this.isProfileSubscribed(profile)), + ...this.profileList.filter((profile, i) => + i !== 0 && !this.isActiveProfile(profile) && this.isProfileSubscribed(profile)) + ] + }, + activeProfile: function () { return this.$store.getters.getActiveProfile }, subscriptionInfo: function () { - return this.activeProfile.subscriptions.find((channel) => { - return channel.id === this.channelId - }) ?? null - }, - - isSubscribed: function () { - return this.subscriptionInfo !== null + return this.subscriptionInfoForProfile(this.activeProfile) }, hideChannelSubscriptions: function () { @@ -55,23 +80,27 @@ export default defineComponent({ }, subscribedText: function () { - let subscribedValue = (this.isSubscribed ? this.$t('Channel.Unsubscribe') : this.$t('Channel.Subscribe')).toUpperCase() + let subscribedValue = (this.isProfileSubscribed(this.activeProfile) ? this.$t('Channel.Unsubscribe') : this.$t('Channel.Subscribe')).toUpperCase() if (this.subscriptionCountText !== '' && !this.hideChannelSubscriptions) { subscribedValue += ' ' + this.subscriptionCountText } return subscribedValue + }, + + isProfileDropdownEnabled: function () { + return !this.hideProfileDropdownToggle && this.profileList.length > 1 } }, methods: { - handleSubscription: function () { + handleSubscription: function (profile = this.activeProfile) { if (this.channelId === '') { return } - const currentProfile = deepCopy(this.activeProfile) + const currentProfile = deepCopy(profile) - if (this.isSubscribed) { + if (this.isProfileSubscribed(profile)) { currentProfile.subscriptions = currentProfile.subscriptions.filter((channel) => { return channel.id !== this.channelId }) @@ -79,16 +108,16 @@ export default defineComponent({ this.updateProfile(currentProfile) showToast(this.$t('Channel.Channel has been removed from your subscriptions')) - if (this.activeProfile._id === MAIN_PROFILE_ID) { + if (profile._id === MAIN_PROFILE_ID) { // Check if a subscription exists in a different profile. // Remove from there as well. let duplicateSubscriptions = 0 - this.profileList.forEach((profile) => { - if (profile._id === MAIN_PROFILE_ID) { + this.profileList.forEach((profileInList) => { + if (profileInList._id === MAIN_PROFILE_ID) { return } - duplicateSubscriptions += this.unsubscribe(profile, this.channelId) + duplicateSubscriptions += this.unsubscribe(profileInList, this.channelId) }) if (duplicateSubscriptions > 0) { @@ -107,7 +136,7 @@ export default defineComponent({ this.updateProfile(currentProfile) showToast(this.$t('Channel.Added channel to your subscriptions')) - if (this.activeProfile._id !== MAIN_PROFILE_ID) { + if (profile._id !== MAIN_PROFILE_ID) { const primaryProfile = deepCopy(this.profileList.find(prof => { return prof._id === MAIN_PROFILE_ID })) @@ -122,6 +151,34 @@ export default defineComponent({ } } } + + if (this.isProfileDropdownEnabled && !this.isProfileDropdownOpen) { + this.toggleProfileDropdown() + } + }, + + handleProfileDropdownFocusOut: function () { + if (!this.$refs.subscribeButton.matches(':focus-within')) { + this.isProfileDropdownOpen = false + } + }, + + toggleProfileDropdown: function() { + this.isProfileDropdownOpen = !this.isProfileDropdownOpen + }, + + isActiveProfile: function (profile) { + return profile._id === this.activeProfile._id + }, + + subscriptionInfoForProfile: function (profile) { + return profile.subscriptions.find((channel) => { + return channel.id === this.channelId + }) ?? null + }, + + isProfileSubscribed: function (profile) { + return this.subscriptionInfoForProfile(profile) !== null }, unsubscribe: function(profile, channelId) { diff --git a/src/renderer/components/ft-subscribe-button/ft-subscribe-button.scss b/src/renderer/components/ft-subscribe-button/ft-subscribe-button.scss new file mode 100644 index 000000000..1d8667fa1 --- /dev/null +++ b/src/renderer/components/ft-subscribe-button/ft-subscribe-button.scss @@ -0,0 +1,141 @@ +.buttonList { + margin: 5px; + margin-block-end: 10px; + border-radius: 4px; + block-size: fit-content; + box-shadow: 0px 1px 2px rgb(0 0 0 / 50%); + display: flex; + flex-wrap: nowrap; + /* addresses odd clipping behavior when adjusting window size */ + background-color: var(--primary-color); +} + +.ftSubscribeButton { + position: relative; + text-align: start; +} + +/* Ensures style here overrides style of .btn */ +.subscribeButton.btn { + min-inline-size: 150px; + white-space: initial; +} + +.subscribeButton.btn, .profileDropdownToggle.btn { + align-self: center; + margin-block: 0; + margin-inline: 0; +} + +.dropdownOpened { + .subscribeButton, .profileDropdownToggle { + border-end-start-radius: 0; + border-end-end-radius: 0; + } +} + +.profileDropdownToggle.btn { + border-inline-start: none !important; + border-start-start-radius: 0; + border-end-start-radius: 0; + display: inline-block; + min-inline-size: 1em; + padding-inline: 10px; + box-sizing: content-box; +} + +.hasProfileDropdownToggle { + .subscribeButton.btn { + min-inline-size: 100px; + padding-inline: 5px; + border-inline-end: 2px solid var(--primary-color-active) !important; + border-start-end-radius: 0; + border-end-end-radius: 0; + box-sizing: content-box; + } +} + +.hasProfileDropdownToggle > .subscribeButton.btn, .profileDropdownToggle.btn { + padding-block: 5px; + padding-inline: 6px; + box-shadow: none; + flex: auto; + block-size: 2em; +} + +.profileDropdown { + background-color: var(--side-nav-color); + box-shadow: 0 1px 2px rgb(0 0 0 / 50%); + color: var(--secondary-text-color); + display: inline; + font-size: 12px; + max-block-size: 200px; + margin-block: -10px 0; + margin-inline: 5px 0; + overflow-y: scroll; + position: absolute; + text-align: center; + -webkit-user-select: none; + user-select: none; + z-index: 3; + // accounts for parent's left and right margins + inline-size: calc(100% - 10px); + + .profileList { + list-style-type: none; + margin: 0; + padding-inline: 0; + } + + .profile { + cursor: pointer; + display: flex; + gap: 0.5em; + padding-inline-start: 0.5em; + block-size: 50px; + align-items: center; + transition: background 0.2s ease-out; + + &:hover { + background-color: var(--side-nav-hover-color); + color: var(--side-nav-hover-text-color); + transition: background 0.2s ease-in; + } + + .colorOption { + inline-size: 40px; + block-size: 40px; + cursor: pointer; + align-items: center; + display: flex; + justify-content: center; + flex-shrink: 0; + border-radius: 50%; + -webkit-border-radius: 50%; + } + + .initial { + font-size: 20px; + line-height: 1em; + text-align: center; + user-select: none; + -webkit-user-select: none; + } + + .profileName { + padding-inline-end: 1em; + text-align: start; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + &.subscribed { + background-color: var(--primary-color); + + .profileName { + color: var(--text-with-main-color); + } + } + } +} diff --git a/src/renderer/components/ft-subscribe-button/ft-subscribe-button.vue b/src/renderer/components/ft-subscribe-button/ft-subscribe-button.vue index 11bf54e7e..7aded099d 100644 --- a/src/renderer/components/ft-subscribe-button/ft-subscribe-button.vue +++ b/src/renderer/components/ft-subscribe-button/ft-subscribe-button.vue @@ -1,12 +1,83 @@ - <% } %> From b65b1a6be9fb0ba79fbf4cc4b801fd501558f582 Mon Sep 17 00:00:00 2001 From: absidue <48293849+absidue@users.noreply.github.com> Date: Wed, 27 Mar 2024 01:27:57 +0100 Subject: [PATCH 572/707] Move usingElectron from computed into data (#4810) --- src/renderer/components/player-settings/player-settings.js | 5 +---- src/renderer/components/theme-settings/theme-settings.js | 5 +---- src/renderer/views/Settings/Settings.js | 5 +---- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/renderer/components/player-settings/player-settings.js b/src/renderer/components/player-settings/player-settings.js index 2ff5b839a..30f4f889d 100644 --- a/src/renderer/components/player-settings/player-settings.js +++ b/src/renderer/components/player-settings/player-settings.js @@ -26,6 +26,7 @@ export default defineComponent({ }, data: function () { return { + usingElectron: process.env.IS_ELECTRON, formatValues: [ 'dash', 'legacy', @@ -60,10 +61,6 @@ export default defineComponent({ } }, computed: { - usingElectron: function () { - return process.env.IS_ELECTRON - }, - backendPreference: function () { return this.$store.getters.getBackendPreference }, diff --git a/src/renderer/components/theme-settings/theme-settings.js b/src/renderer/components/theme-settings/theme-settings.js index e3e9c95f7..dce362993 100644 --- a/src/renderer/components/theme-settings/theme-settings.js +++ b/src/renderer/components/theme-settings/theme-settings.js @@ -20,6 +20,7 @@ export default defineComponent({ }, data: function () { return { + usingElectron: process.env.IS_ELECTRON, minUiScale: 50, maxUiScale: 300, uiScaleStep: 5, @@ -122,10 +123,6 @@ export default defineComponent({ areColorThemesEnabled: function() { return this.baseTheme !== 'hotPink' - }, - - usingElectron: function () { - return process.env.IS_ELECTRON } }, mounted: function () { diff --git a/src/renderer/views/Settings/Settings.js b/src/renderer/views/Settings/Settings.js index f7dc155cd..9bc64c6a9 100644 --- a/src/renderer/views/Settings/Settings.js +++ b/src/renderer/views/Settings/Settings.js @@ -39,14 +39,11 @@ export default defineComponent({ }, data: function () { return { + usingElectron: process.env.IS_ELECTRON, unlocked: false } }, computed: { - usingElectron: function () { - return process.env.IS_ELECTRON - }, - settingsPassword: function () { return this.$store.getters.getSettingsPassword }, From 77df063c7183896cc175ea739c737bfb73898f1d Mon Sep 17 00:00:00 2001 From: absidue <48293849+absidue@users.noreply.github.com> Date: Wed, 27 Mar 2024 01:31:11 +0100 Subject: [PATCH 573/707] Fix the web build's manifest.json file getting included in the electron build (#4815) --- _scripts/webpack.main.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_scripts/webpack.main.config.js b/_scripts/webpack.main.config.js index 0f3c706c6..0358f7919 100644 --- a/_scripts/webpack.main.config.js +++ b/_scripts/webpack.main.config.js @@ -56,7 +56,7 @@ if (!isDevMode) { to: path.join(__dirname, '../dist/static'), globOptions: { dot: true, - ignore: ['**/.*', '**/locales/**', '**/pwabuilder-sw.js', '**/dashFiles/**', '**/storyboards/**'], + ignore: ['**/.*', '**/locales/**', '**/pwabuilder-sw.js', '**/manifest.json', '**/dashFiles/**', '**/storyboards/**'], }, }, ] From d8a3ab337d084f260093580601d84e218b9b3ac7 Mon Sep 17 00:00:00 2001 From: absidue <48293849+absidue@users.noreply.github.com> Date: Wed, 27 Mar 2024 01:32:21 +0100 Subject: [PATCH 574/707] Fix the left arrow key not working on the first button in prompts (#4816) --- src/renderer/components/ft-prompt/ft-prompt.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer/components/ft-prompt/ft-prompt.js b/src/renderer/components/ft-prompt/ft-prompt.js index 4c311ef4a..060a4a006 100644 --- a/src/renderer/components/ft-prompt/ft-prompt.js +++ b/src/renderer/components/ft-prompt/ft-prompt.js @@ -77,7 +77,7 @@ export default defineComponent({ focusItem: function (value) { let index = value if (index < 0) { - index = this.promptButtons.length + index = this.promptButtons.length - 1 } else if (index >= this.promptButtons.length) { index = 0 } From b1244b7dab657828f9f393463c39d7fd79e95e88 Mon Sep 17 00:00:00 2001 From: absidue <48293849+absidue@users.noreply.github.com> Date: Wed, 27 Mar 2024 01:34:21 +0100 Subject: [PATCH 575/707] Parse compact numbers without using floating point numbers to avoid accuracy issues (#4817) --- src/renderer/helpers/api/local.js | 42 ++++++++++++++++++------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/src/renderer/helpers/api/local.js b/src/renderer/helpers/api/local.js index c8d4d350d..7bfc03c00 100644 --- a/src/renderer/helpers/api/local.js +++ b/src/renderer/helpers/api/local.js @@ -1088,32 +1088,40 @@ export function filterLocalFormats(formats, allowAv1 = false) { } /** - * Really not a fan of this :(, YouTube returns the subscribers as "15.1M subscribers" - * so we have to parse it somehow * @param {string} text */ export function parseLocalSubscriberCount(text) { - const match = text - .replace(',', '.') - .toUpperCase() - .match(/([\d.]+)\s*([KM]?)/) + const match = text.match(/(\d+)(?:[,.](\d+))?\s?([BKMbkm])\b/) - let subscribers if (match) { - subscribers = parseFloat(match[1]) + let multiplier = 0 - if (match[2] === 'K') { - subscribers *= 1000 - } else if (match[2] === 'M') { - subscribers *= 1000_000 + switch (match[3]) { + case 'K': + case 'k': + multiplier = 3 + break + case 'M': + case 'm': + multiplier = 6 + break + case 'B': + case 'b': + multiplier = 9 + break } - subscribers = Math.trunc(subscribers) - } else { - subscribers = extractNumberFromString(text) - } + let parsedDecimals + if (typeof match[2] === 'undefined') { + parsedDecimals = '0'.repeat(multiplier) + } else { + parsedDecimals = match[2].padEnd(multiplier, '0') + } - return subscribers + return parseInt(match[1] + parsedDecimals) + } else { + return extractNumberFromString(text) + } } /** From 598d970b939bee8f871ca1793b80f016ab48e766 Mon Sep 17 00:00:00 2001 From: absidue <48293849+absidue@users.noreply.github.com> Date: Wed, 27 Mar 2024 01:37:19 +0100 Subject: [PATCH 576/707] Create empty subscriptions cache objects directly instead of cloning (#4814) --- src/renderer/store/modules/subscriptions.js | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/renderer/store/modules/subscriptions.js b/src/renderer/store/modules/subscriptions.js index c85168423..2ce05c7b6 100644 --- a/src/renderer/store/modules/subscriptions.js +++ b/src/renderer/store/modules/subscriptions.js @@ -1,9 +1,3 @@ -import { deepCopy } from '../../helpers/utils' - -const defaultCacheEntryValueForForOneChannel = { - videos: null, -} - const state = { videoCache: {}, liveCache: {}, @@ -77,7 +71,7 @@ const actions = { const mutations = { updateVideoCacheByChannel(state, { channelId, videos }) { const existingObject = state.videoCache[channelId] - const newObject = existingObject != null ? existingObject : deepCopy(defaultCacheEntryValueForForOneChannel) + const newObject = existingObject ?? { videos: null } if (videos != null) { newObject.videos = videos } state.videoCache[channelId] = newObject }, @@ -86,7 +80,7 @@ const mutations = { }, updateShortsCacheByChannel(state, { channelId, videos }) { const existingObject = state.shortsCache[channelId] - const newObject = existingObject != null ? existingObject : deepCopy(defaultCacheEntryValueForForOneChannel) + const newObject = existingObject ?? { videos: null } if (videos != null) { newObject.videos = videos } state.shortsCache[channelId] = newObject }, @@ -120,7 +114,7 @@ const mutations = { }, updateLiveCacheByChannel(state, { channelId, videos }) { const existingObject = state.liveCache[channelId] - const newObject = existingObject != null ? existingObject : deepCopy(defaultCacheEntryValueForForOneChannel) + const newObject = existingObject ?? { videos: null } if (videos != null) { newObject.videos = videos } state.liveCache[channelId] = newObject }, @@ -129,7 +123,7 @@ const mutations = { }, updatePostsCacheByChannel(state, { channelId, posts }) { const existingObject = state.postsCache[channelId] - const newObject = existingObject != null ? existingObject : deepCopy(defaultCacheEntryValueForForOneChannel) + const newObject = existingObject ?? { posts: null } if (posts != null) { newObject.posts = posts } state.postsCache[channelId] = newObject }, From 4023bfa9c9271645128f3a36e7141bada661db51 Mon Sep 17 00:00:00 2001 From: Sergio Marques Date: Tue, 26 Mar 2024 23:28:57 +0000 Subject: [PATCH 577/707] Translated using Weblate (Portuguese) Currently translated at 99.3% (814 of 819 strings) Translation: FreeTube/Translations Translate-URL: https://hosted.weblate.org/projects/free-tube/translations/pt/ --- static/locales/pt.yaml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/static/locales/pt.yaml b/static/locales/pt.yaml index e2819e7c6..67357a739 100644 --- a/static/locales/pt.yaml +++ b/static/locales/pt.yaml @@ -128,7 +128,7 @@ User Playlists: Playlist Message: Esta página não é indicativa do resultado final. Apenas mostra os vídeos que foram guardados ou marcados como favoritos. Quando estiver pronta, todos os vídeos que estiverem aqui serão postos numa lista chamada 'Favoritos'. - Search bar placeholder: Procurar na lista de reprodução + Search bar placeholder: Procurar listas de reprodução Empty Search Message: Não há vídeos nesta lista de reprodução que coincidam com a sua pesquisa This playlist currently has no videos.: Esta lista de reprodução não tem vídeos @@ -196,6 +196,7 @@ User Playlists: qual adicionar o seu vídeo | Selecione uma lista de reprodução à qual adicionar os seus {videoCount} vídeos N playlists selected: '{playlistCount} selecionadas' + Added {count} Times: Adicionada {count} vez | Adicionada {count} vezes CreatePlaylistPrompt: New Playlist Name: Novo nome da lista de reprodução Create: Criar @@ -221,6 +222,7 @@ User Playlists: Enable Quick Bookmark With This Playlist: Ativar marcador rápido para esta lista de reprodução Disable Quick Bookmark: Desativar marcador rápido + Playlists with Matching Videos: Listas de reprodução coincidentes History: # On History Page History: 'Histórico' @@ -565,7 +567,7 @@ Settings: Hide Channels: Ocultar vídeos dos canais Hide Channels Placeholder: ID do canal Display Titles Without Excessive Capitalisation: Mostrar títulos sem maiúsculas - em excesso + ou pontuação em excesso Hide Featured Channels: Ocultar canais em destaque Hide Channel Playlists: Ocultar listas de reprodução dos canais Hide Channel Community: Ocultar canal Comunidade @@ -1102,9 +1104,9 @@ Tooltips: vídeos em vez de fazer uma ligação direta ao YouTube. Ignora a preferência de API. Force Local Backend for Legacy Formats: Apenas funciona quando a API Invidious - é o seu sistema usado. Se ativa, a API local será executada para usar os formatos - antigos em vez dos usados pelo Invidious. Útil quando os vídeos do Invidious - não funcionam devido a restrições geográficas. + é sistema usado. Se ativa, a API local será executada para usar os formatos + antigos em vez dos usados pelo Invidious. Útil quando os vídeos Invidious não + funcionam devido a restrições geográficas. Scroll Playback Rate Over Video Player: Com o cursor sobre o vídeo, prima e mantenha premida a tecla Ctrl (Comando em Mac) e desloque a roda do rato para controlar a taxa de reprodução. Prima e mantenha premida a tecla Ctrl (Comando em Mac) @@ -1190,3 +1192,6 @@ Go to page: Ir para {page} Channel Unhidden: '{channel} removido do filtro do canal' Tag already exists: '"{tagName}" já existe' Close Banner: Fechar banner +Age Restricted: + This channel is age restricted: Este canal tem restrições de idade + This video is age restricted: Este vídeo tem restrições de idade From b04e349b069135a1fa264b154ef37d41462e2514 Mon Sep 17 00:00:00 2001 From: absidue <48293849+absidue@users.noreply.github.com> Date: Wed, 27 Mar 2024 02:35:34 +0100 Subject: [PATCH 578/707] Fix extracting the subscriber count from channel PageHeader nodes (#4804) --- src/renderer/helpers/api/local.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/renderer/helpers/api/local.js b/src/renderer/helpers/api/local.js index 7bfc03c00..a05d85d3d 100644 --- a/src/renderer/helpers/api/local.js +++ b/src/renderer/helpers/api/local.js @@ -513,7 +513,13 @@ export function parseLocalChannelHeader(channel) { } if (header.content.metadata) { - subscriberText = header.content.metadata.metadata_rows[0].metadata_parts[1].text.text + // YouTube has already changed the indexes for where the information is stored once, + // so we should search for it instead of using hardcoded indexes, just to be safe for the future + + subscriberText = header.content.metadata.metadata_rows + .flatMap(row => row.metadata_parts ? row.metadata_parts : []) + .find(part => part.text.text?.includes('subscriber')) + ?.text.text } break From 5f2a9983315cb1230468c58d1fa0aacb7793853f Mon Sep 17 00:00:00 2001 From: absidue <48293849+absidue@users.noreply.github.com> Date: Wed, 27 Mar 2024 02:36:34 +0100 Subject: [PATCH 579/707] Fix v-observe-visibility error when playlist items are updated (#4774) --- .../ft-list-video-numbered.js | 19 ++++++++++++++++++- .../ft-list-video-numbered.vue | 4 ++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/renderer/components/ft-list-video-numbered/ft-list-video-numbered.js b/src/renderer/components/ft-list-video-numbered/ft-list-video-numbered.js index 9ed32bb8e..e4fe2d7d6 100644 --- a/src/renderer/components/ft-list-video-numbered/ft-list-video-numbered.js +++ b/src/renderer/components/ft-list-video-numbered/ft-list-video-numbered.js @@ -83,7 +83,8 @@ export default defineComponent({ data: function () { return { visible: false, - show: true + show: true, + stopWatchingInitialVisibleState: null } }, computed: { @@ -111,13 +112,29 @@ export default defineComponent({ }, created() { this.visible = this.initialVisibleState + + if (!this.initialVisibleState) { + this.stopWatchingInitialVisibleState = this.$watch('initialVisibleState', (newValue) => { + this.visible = newValue + this.stopWatchingInitialVisibleState() + this.stopWatchingInitialVisibleState = null + }) + } }, methods: { onVisibilityChanged: function (visible) { if (visible && this.shouldBeVisible) { this.visible = visible + if (this.stopWatchingInitialVisibleState) { + this.stopWatchingInitialVisibleState() + this.stopWatchingInitialVisibleState = null + } } else if (visible) { this.show = false + if (this.stopWatchingInitialVisibleState) { + this.stopWatchingInitialVisibleState() + this.stopWatchingInitialVisibleState = null + } } } } diff --git a/src/renderer/components/ft-list-video-numbered/ft-list-video-numbered.vue b/src/renderer/components/ft-list-video-numbered/ft-list-video-numbered.vue index 745a704fe..4a6c2f889 100644 --- a/src/renderer/components/ft-list-video-numbered/ft-list-video-numbered.vue +++ b/src/renderer/components/ft-list-video-numbered/ft-list-video-numbered.vue @@ -1,10 +1,10 @@ diff --git a/src/renderer/components/subscriptions-tab-ui/subscriptions-tab-ui.js b/src/renderer/components/subscriptions-tab-ui/subscriptions-tab-ui.js index 958c03539..293fd6f8f 100644 --- a/src/renderer/components/subscriptions-tab-ui/subscriptions-tab-ui.js +++ b/src/renderer/components/subscriptions-tab-ui/subscriptions-tab-ui.js @@ -80,7 +80,7 @@ export default defineComponent({ this.dataLimit = this.initialDataLimit } }, - mounted: async function () { + mounted: function () { document.addEventListener('keydown', this.keyboardShortcutHandler) }, beforeDestroy: function () { diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js index 5dad9b89b..054bbd850 100644 --- a/src/renderer/views/Playlist/Playlist.js +++ b/src/renderer/views/Playlist/Playlist.js @@ -60,7 +60,6 @@ export default defineComponent({ getPlaylistInfoDebounce: function() {}, playlistInEditMode: false, - playlistInVideoSearchMode: false, videoSearchQuery: '', promptOpen: false, @@ -112,9 +111,8 @@ export default defineComponent({ return this.continuationData !== null } }, - - searchVideoModeAllowed() { - return this.isUserPlaylistRequested + playlistInVideoSearchMode() { + return this.processedVideoSearchQuery !== '' }, searchQueryTextRequested() { return this.$route.query.searchQueryText ?? '' @@ -199,8 +197,7 @@ export default defineComponent({ created: function () { this.getPlaylistInfoDebounce = debounce(this.getPlaylistInfo, 100) - if (this.searchVideoModeAllowed && this.searchQueryTextPresent) { - this.playlistInVideoSearchMode = true + if (this.isUserPlaylistRequested && this.searchQueryTextPresent) { this.videoSearchQuery = this.searchQueryTextRequested } }, diff --git a/src/renderer/views/Playlist/Playlist.vue b/src/renderer/views/Playlist/Playlist.vue index f4e3c183b..6d999686b 100644 --- a/src/renderer/views/Playlist/Playlist.vue +++ b/src/renderer/views/Playlist/Playlist.vue @@ -22,7 +22,7 @@ :view-count="viewCount" :info-source="infoSource" :more-video-data-available="moreVideoDataAvailable" - :search-video-mode-allowed="searchVideoModeAllowed" + :search-video-mode-allowed="isUserPlaylistRequested && videoCount > 1" :search-video-mode-enabled="playlistInVideoSearchMode" :search-query-text="searchQueryTextRequested" class="playlistInfo" @@ -31,8 +31,6 @@ }" @enter-edit-mode="playlistInEditMode = true" @exit-edit-mode="playlistInEditMode = false" - @search-video-mode-on="playlistInVideoSearchMode = true" - @search-video-mode-off="playlistInVideoSearchMode = false" @search-video-query-change="(v) => videoSearchQuery = v" @prompt-open="promptOpen = true" @prompt-close="promptOpen = false" diff --git a/static/locales/en-US.yaml b/static/locales/en-US.yaml index 75eef565a..8aaedcda6 100644 --- a/static/locales/en-US.yaml +++ b/static/locales/en-US.yaml @@ -141,7 +141,7 @@ User Playlists: Your saved videos are empty. Click on the save button on the corner of a video to have it listed here: Your saved videos are empty. Click on the save button on the corner of a video to have it listed here You have no playlists. Click on the create new playlist button to create a new one.: You have no playlists. Click on the create new playlist button to create a new one. - Empty Search Message: There are no videos in this playlist that matches your search + Empty Search Message: There are no videos in this playlist that match your search Search bar placeholder: Search for Playlists Playlists with Matching Videos: Playlists with Matching Videos @@ -235,7 +235,7 @@ History: History: History Watch History: Watch History Your history list is currently empty.: Your history list is currently empty. - Empty Search Message: There are no videos in your history that matches your search + Empty Search Message: There are no videos in your history that match your search Search bar placeholder: "Search in History" Settings: # On Settings Page From 6c314f1597f28299bddfa9fec9a3430ed722109d Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 16 Apr 2024 15:48:09 +0000 Subject: [PATCH 664/707] Translated using Weblate (Japanese) Currently translated at 88.0% (720 of 818 strings) Translation: FreeTube/Translations Translate-URL: https://hosted.weblate.org/projects/free-tube/translations/ja/ --- static/locales/ja.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/static/locales/ja.yaml b/static/locales/ja.yaml index 943362756..fbd1527b4 100644 --- a/static/locales/ja.yaml +++ b/static/locales/ja.yaml @@ -109,7 +109,7 @@ Playlists: '再生リスト' User Playlists: Your Playlists: 'あなたの再生リスト' Your saved videos are empty. Click on the save button on the corner of a video to have it listed here: 保存した動画はありません。一覧に表示させるには、ビデオの角にある保存ボタンをクリックします - Playlist Message: + Playlist Message: このページは、完全に動作する動画リストではありません。保存またはお気に入りと設定した動画のみが表示されます。操作が完了すると、現在ここにあるすべての動画は「お気に入り」の動画リストに移動します。 Search bar placeholder: 動画リスト内の検索 Empty Search Message: この再生リストに、検索に一致する動画はありません @@ -467,7 +467,7 @@ Settings: Experimental Settings: Replace HTTP Cache: HTTP キャッシュの置換 Experimental Settings: 実験中の設定 - Warning: + Warning: これらの設定は実験的なものであり、有効にするとアプリのクラッシュを引き起こす恐れがあります。バックアップをとっておくことを強くお勧めします。自己責任で使用してください! Password Settings: Password Settings: パスワード設定 From 4229959852d08f4893ec0c6100ea6c3c47076e3a Mon Sep 17 00:00:00 2001 From: NicolaeFericitu Date: Tue, 16 Apr 2024 20:01:00 +0000 Subject: [PATCH 665/707] Translated using Weblate (Romanian) Currently translated at 90.7% (742 of 818 strings) Translation: FreeTube/Translations Translate-URL: https://hosted.weblate.org/projects/free-tube/translations/ro/ --- static/locales/ro.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/static/locales/ro.yaml b/static/locales/ro.yaml index 555e78d9b..967fd58fa 100644 --- a/static/locales/ro.yaml +++ b/static/locales/ro.yaml @@ -2,7 +2,8 @@ Locale Name: 'română' # Currently on Subscriptions, Playlists, and History 'This part of the app is not ready yet. Come back later when progress has been made.': >- - Această parte a aplicației nu este gata încă. Revino mai târziu pentru modificări. + Această parte a aplicației nu este încă gata. Reveniți mai târziu, când se vor face + progrese. # Webkit Menu Bar File: 'Filă' From 2b7c96eb97a1dcfc889d5397e671cee944bd17f2 Mon Sep 17 00:00:00 2001 From: PikachuEXE Date: Wed, 17 Apr 2024 04:16:08 +0800 Subject: [PATCH 666/707] Update most paginated places to auto load next page (except comments) (#4565) * * Update most paginated places to auto load next page (except comments) * * Make comment section auto load next pages too * $ Use new component to dedup auto load code * * Implement auto load next page for single playlist page * * Remove comment auto load setting * * Update tooltip text --- .../ft-auto-load-next-page-wrapper.js | 30 +++++++++++++++++++ .../ft-auto-load-next-page-wrapper.vue | 16 ++++++++++ .../general-settings/general-settings.js | 6 +++- .../general-settings/general-settings.vue | 7 +++++ .../player-settings/player-settings.js | 10 ------- .../player-settings/player-settings.vue | 8 ----- .../subscriptions-tab-ui.js | 4 ++- .../subscriptions-tab-ui.vue | 19 +++++++----- .../watch-video-comments.js | 11 +++---- src/renderer/store/modules/settings.js | 2 +- src/renderer/views/Channel/Channel.js | 6 ++-- src/renderer/views/Channel/Channel.vue | 22 ++++++++------ src/renderer/views/Hashtag/Hashtag.js | 6 ++-- src/renderer/views/Hashtag/Hashtag.vue | 23 ++++++++------ src/renderer/views/History/History.js | 6 ++-- src/renderer/views/History/History.vue | 19 +++++++----- src/renderer/views/Playlist/Playlist.js | 4 ++- src/renderer/views/Playlist/Playlist.vue | 19 +++++++----- src/renderer/views/Search/Search.js | 8 +++-- src/renderer/views/Search/Search.vue | 22 ++++++++------ .../views/UserPlaylists/UserPlaylists.js | 2 ++ .../views/UserPlaylists/UserPlaylists.vue | 19 +++++++----- static/locales/ar.yaml | 2 -- static/locales/be.yaml | 2 -- static/locales/bg.yaml | 2 -- static/locales/ckb.yaml | 2 -- static/locales/cs.yaml | 2 -- static/locales/cy.yaml | 2 -- static/locales/da.yaml | 2 -- static/locales/de-DE.yaml | 2 -- static/locales/el.yaml | 2 -- static/locales/en-US.yaml | 5 ++-- static/locales/en_GB.yaml | 2 -- static/locales/es.yaml | 2 -- static/locales/es_AR.yaml | 2 -- static/locales/et.yaml | 2 -- static/locales/eu.yaml | 2 -- static/locales/fa.yaml | 2 -- static/locales/fi.yaml | 2 -- static/locales/fr-FR.yaml | 2 -- static/locales/he.yaml | 2 -- static/locales/hr.yaml | 2 -- static/locales/hu.yaml | 2 -- static/locales/id.yaml | 2 -- static/locales/is.yaml | 2 -- static/locales/it.yaml | 2 -- static/locales/ja.yaml | 6 ++-- static/locales/lt.yaml | 2 -- static/locales/lv.yaml | 2 -- static/locales/nb_NO.yaml | 2 -- static/locales/nl.yaml | 2 -- static/locales/pl.yaml | 2 -- static/locales/pt-BR.yaml | 2 -- static/locales/pt-PT.yaml | 2 -- static/locales/pt.yaml | 2 -- static/locales/ro.yaml | 2 -- static/locales/ru.yaml | 2 -- static/locales/sm.yaml | 2 -- static/locales/sr.yaml | 2 -- static/locales/sv.yaml | 2 -- static/locales/tr.yaml | 2 -- static/locales/uk.yaml | 2 -- static/locales/vi.yaml | 2 -- static/locales/zh-CN.yaml | 2 -- static/locales/zh-TW.yaml | 2 -- 65 files changed, 179 insertions(+), 183 deletions(-) create mode 100644 src/renderer/components/ft-auto-load-next-page-wrapper/ft-auto-load-next-page-wrapper.js create mode 100644 src/renderer/components/ft-auto-load-next-page-wrapper/ft-auto-load-next-page-wrapper.vue diff --git a/src/renderer/components/ft-auto-load-next-page-wrapper/ft-auto-load-next-page-wrapper.js b/src/renderer/components/ft-auto-load-next-page-wrapper/ft-auto-load-next-page-wrapper.js new file mode 100644 index 000000000..aca042948 --- /dev/null +++ b/src/renderer/components/ft-auto-load-next-page-wrapper/ft-auto-load-next-page-wrapper.js @@ -0,0 +1,30 @@ +import { defineComponent } from 'vue' + +export default defineComponent({ + name: 'FtAutoLoadNextPageWrapper', + computed: { + generalAutoLoadMorePaginatedItemsEnabled() { + return this.$store.getters.getGeneralAutoLoadMorePaginatedItemsEnabled + }, + observeVisibilityOptions() { + if (!this.generalAutoLoadMorePaginatedItemsEnabled) { return false } + + return { + callback: (isVisible, _entry) => { + // This is also fired when **hidden** + // No point doing anything if not visible + if (!isVisible) { return } + + this.$emit('load-next-page') + }, + intersection: { + // Only when it intersects with N% above bottom + rootMargin: '0% 0% 0% 0%', + }, + // Callback responsible for loading multiple pages + once: false, + } + }, + + }, +}) diff --git a/src/renderer/components/ft-auto-load-next-page-wrapper/ft-auto-load-next-page-wrapper.vue b/src/renderer/components/ft-auto-load-next-page-wrapper/ft-auto-load-next-page-wrapper.vue new file mode 100644 index 000000000..7a2714862 --- /dev/null +++ b/src/renderer/components/ft-auto-load-next-page-wrapper/ft-auto-load-next-page-wrapper.vue @@ -0,0 +1,16 @@ + + +