diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 63a54a471c7c6..569ded4476692 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -108,91 +108,91 @@ jobs: run: yarn run build:arm64 - name: Upload Linux .zip x64 Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.runtime, 'linux-x64') with: name: freetube_${{ steps.versionNumber.outputs.result }}_linux_portable_x64 path: build/freetube-${{ steps.versionNumber.outputs.result }}.zip - name: Upload Linux .7z x64 Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.runtime, 'linux-x64') with: name: freetube_${{ steps.versionNumber.outputs.result }}_linux_portable_x64.7z path: build/freetube-${{ steps.versionNumber.outputs.result }}.7z - name: Upload Linux .zip ARMv7l Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.runtime, 'linux-armv7l') with: name: freetube_${{ steps.versionNumber.outputs.result }}_linux_portable_armv7l path: build/freetube-${{ steps.versionNumber.outputs.result }}-armv7l.zip - name: Upload Linux .7z ARMv7l Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.runtime, 'linux-armv7l') with: name: freetube_${{ steps.versionNumber.outputs.result }}_linux_portable_armv7l.7z path: build/freetube-${{ steps.versionNumber.outputs.result }}-armv7l.7z - name: Upload Linux .zip ARM64 Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.runtime, 'linux-arm64') with: name: freetube_${{ steps.versionNumber.outputs.result }}_linux_portable_arm64 path: build/freetube-${{ steps.versionNumber.outputs.result }}-arm64.zip - name: Upload Linux .7z ARM64 Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.runtime, 'linux-arm64') with: name: freetube_${{ steps.versionNumber.outputs.result }}_linux_portable_arm64.7z path: build/freetube-${{ steps.versionNumber.outputs.result }}-arm64.7z - name: Upload .deb x64 Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.runtime, 'linux-x64') with: name: freetube_${{ steps.versionNumber.outputs.result }}_amd64.deb path: build/freetube_${{ steps.versionNumber.outputs.result }}_amd64.deb - name: Upload .deb ARMv7l Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.runtime, 'linux-armv7l') with: name: freetube_${{ steps.versionNumber.outputs.result }}_armv7l.deb path: build/freetube_${{ steps.versionNumber.outputs.result }}_armv7l.deb - name: Upload .deb ARM64 Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.runtime, 'linux-arm64') with: name: freetube_${{ steps.versionNumber.outputs.result }}_arm64.deb path: build/freetube_${{ steps.versionNumber.outputs.result }}_arm64.deb - name: Upload AppImage x64 Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.runtime, 'linux-x64') with: name: freetube_${{ steps.versionNumber.outputs.result }}_amd64.AppImage path: build/FreeTube-${{ steps.versionNumber.outputs.result }}.AppImage - name: Upload AppImage ARMv7l Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.runtime, 'linux-armv7l') with: name: freetube_${{ steps.versionNumber.outputs.result }}_armv7l.AppImage path: build/FreeTube-${{ steps.versionNumber.outputs.result }}-armv7l.AppImage - name: Upload AppImage ARM64 Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.runtime, 'linux-arm64') with: name: freetube_${{ steps.versionNumber.outputs.result }}_arm64.AppImage path: build/FreeTube-${{ steps.versionNumber.outputs.result }}-arm64.AppImage - name: Upload .rpm x64 Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.runtime, 'linux-x64') with: name: freetube_${{ steps.versionNumber.outputs.result }}_amd64.rpm @@ -201,133 +201,133 @@ jobs: # rpm are not built for armv7l - name: Upload .rpm ARM64 Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.runtime, 'linux-arm64') with: name: freetube_${{ steps.versionNumber.outputs.result }}_arm64.rpm path: build/freetube-${{ steps.versionNumber.outputs.result }}.aarch64.rpm - name: Upload Alpine .apk x64 Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.runtime, 'linux-x64') with: name: freetube_${{ steps.versionNumber.outputs.result }}_alpine_amd64.apk path: build/freetube-${{ steps.versionNumber.outputs.result }}.apk - name: Upload Alpine .apk ARMv7l Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.runtime, 'linux-armv7l') with: name: freetube_${{ steps.versionNumber.outputs.result }}_alpine_armv7l.apk path: build/freetube-${{ steps.versionNumber.outputs.result }}-armv7l.apk - name: Upload Alpine .apk ARM64 Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.runtime, 'linux-arm64') with: name: freetube_${{ steps.versionNumber.outputs.result }}_alpine_arm64.apk path: build/freetube-${{ steps.versionNumber.outputs.result }}-arm64.apk - name: Upload Pacman .pacman x64 Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.runtime, 'linux-x64') with: name: freetube_${{ steps.versionNumber.outputs.result }}_amd64.pacman path: build/freetube-${{ steps.versionNumber.outputs.result }}.pacman # - name: Upload Web Build - # uses: actions/upload-artifact@v3 + # uses: actions/upload-artifact@v4 # if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.runtime, 'linux-x64') # with: # name: freetube_${{ steps.versionNumber.outputs.result }}_static_web # path: dist/web - name: Upload Windows x64 .exe Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: startsWith(matrix.os, 'windows') && startsWith(matrix.runtime, 'win-x64') with: name: freetube-${{ steps.versionNumber.outputs.result }}-setup-x64.exe path: build/freetube Setup ${{ steps.versionNumber.outputs.result }}.exe - name: Upload Windows arm64 .exe Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: startsWith(matrix.os, 'windows') && startsWith(matrix.runtime, 'win-arm64') with: name: freetube-${{ steps.versionNumber.outputs.result }}-setup-arm64.exe path: build/freetube Setup ${{ steps.versionNumber.outputs.result }}.exe - name: Upload Windows x64 .zip Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: startsWith(matrix.os, 'windows') && startsWith(matrix.runtime, 'win-x64') with: name: freetube-${{ steps.versionNumber.outputs.result }}-win-x64-portable path: build/freetube-${{ steps.versionNumber.outputs.result }}-win.zip - name: Upload Windows x64 .7z Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: startsWith(matrix.os, 'windows') && startsWith(matrix.runtime, 'win-x64') with: name: freetube-${{ steps.versionNumber.outputs.result }}-win-x64-portable.7z path: build/freetube-${{ steps.versionNumber.outputs.result }}-win.7z - name: Upload Windows arm64 .zip Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: startsWith(matrix.os, 'windows') && startsWith(matrix.runtime, 'win-arm64') with: name: freetube-${{ steps.versionNumber.outputs.result }}-win-arm64-portable path: build/freetube-${{ steps.versionNumber.outputs.result }}-arm64-win.zip - name: Upload Windows arm64 .7z Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: startsWith(matrix.os, 'windows') && startsWith(matrix.runtime, 'win-arm64') with: name: freetube-${{ steps.versionNumber.outputs.result }}-win-arm64-portable.7z path: build/freetube-${{ steps.versionNumber.outputs.result }}-arm64-win.7z - name: Upload Windows x64 Portable Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: startsWith(matrix.os, 'windows') && startsWith(matrix.runtime, 'win-x64') with: name: freetube-${{ steps.versionNumber.outputs.result }}-portable-x64.exe path: build/freetube ${{ steps.versionNumber.outputs.result }}.exe - name: Upload Windows arm64 Portable Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: startsWith(matrix.os, 'windows') && startsWith(matrix.runtime, 'win-arm64') with: name: freetube-${{ steps.versionNumber.outputs.result }}-portable-arm64.exe path: build/freetube ${{ steps.versionNumber.outputs.result }}.exe - name: Upload Mac x64 .dmg Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: startsWith(matrix.os, 'macos') && startsWith(matrix.runtime, 'osx-x64') with: name: freetube-${{ steps.versionNumber.outputs.result }}-mac-x64.dmg path: build/freetube-${{ steps.versionNumber.outputs.result }}.dmg # - name: Upload Mac arm64 .dmg Artifact -# uses: actions/upload-artifact@v3 +# uses: actions/upload-artifact@v4 # if: startsWith(matrix.os, 'macos') && startsWith(matrix.runtime, 'osx-arm64') # with: # name: freetube-${{ steps.versionNumber.outputs.result }}-mac-arm64.dmg # path: build/freetube-${{ steps.versionNumber.outputs.result }}-arm64.dmg - name: Upload Mac x64 .zip Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: startsWith(matrix.os, 'macos') && startsWith(matrix.runtime, 'osx-x64') with: name: freetube-${{ steps.versionNumber.outputs.result }}-mac-x64.zip path: build/freetube-${{ steps.versionNumber.outputs.result }}-mac.zip - name: Upload Mac x64 .7z Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: startsWith(matrix.os, 'macos') && startsWith(matrix.runtime, 'osx-x64') with: name: freetube-${{ steps.versionNumber.outputs.result }}-mac-x64.7z path: build/freetube-${{ steps.versionNumber.outputs.result }}-mac.7z # - name: Upload Mac arm64 .zip Artifact -# uses: actions/upload-artifact@v3 +# uses: actions/upload-artifact@v4 # if: startsWith(matrix.os, 'macos') && startsWith(matrix.runtime, 'osx-arm64') # with: # name: freetube-${{ steps.versionNumber.outputs.result }}-mac-arm64.zip diff --git a/.github/workflows/calibreapp-image-actions.yml b/.github/workflows/calibreapp-image-actions.yml index f94e1ac32c843..d336cad2328ab 100644 --- a/.github/workflows/calibreapp-image-actions.yml +++ b/.github/workflows/calibreapp-image-actions.yml @@ -20,7 +20,7 @@ jobs: compressOnly: true - name: Create New Pull Request If Needed if: steps.calibre.outputs.markdown != '' - uses: peter-evans/create-pull-request@v5 + uses: peter-evans/create-pull-request@v6 with: title: Compressed Images Nightly branch-suffix: timestamp diff --git a/.github/workflows/label-issue.yml b/.github/workflows/label-issue.yml index 46eed6d43bfae..24e42dc04f3c9 100644 --- a/.github/workflows/label-issue.yml +++ b/.github/workflows/label-issue.yml @@ -11,7 +11,7 @@ jobs: triage: runs-on: ubuntu-latest steps: - - uses: github/issue-labeler@v3.3 + - uses: github/issue-labeler@v3.4 with: configuration-path: .github/issue-labeler.yml enable-versioned-regex: 0 diff --git a/_icons/iconNordicLightSmall.png b/_icons/iconNordicLightSmall.png new file mode 100644 index 0000000000000..b5b83494c8e56 Binary files /dev/null and b/_icons/iconNordicLightSmall.png differ diff --git a/_icons/textNordicLightSmall.png b/_icons/textNordicLightSmall.png new file mode 100644 index 0000000000000..b23422a08c14f Binary files /dev/null and b/_icons/textNordicLightSmall.png differ diff --git a/_scripts/webpack.renderer.config.js b/_scripts/webpack.renderer.config.js index 057be25f4a65b..385b6e29abd8d 100644 --- a/_scripts/webpack.renderer.config.js +++ b/_scripts/webpack.renderer.config.js @@ -1,5 +1,5 @@ const path = require('path') -const { readFileSync } = require('fs') +const { readFileSync, readdirSync } = require('fs') const webpack = require('webpack') const HtmlWebpackPlugin = require('html-webpack-plugin') const VueLoaderPlugin = require('vue-loader/lib/plugin') @@ -117,7 +117,8 @@ const config = { new webpack.DefinePlugin({ 'process.env.IS_ELECTRON': true, 'process.env.IS_ELECTRON_MAIN': false, - 'process.env.LOCALE_NAMES': JSON.stringify(processLocalesPlugin.localeNames) + 'process.env.LOCALE_NAMES': JSON.stringify(processLocalesPlugin.localeNames), + 'process.env.GEOLOCATION_NAMES': JSON.stringify(readdirSync(path.join(__dirname, '..', 'static', 'geolocations')).map(filename => filename.replace('.json', ''))) }), new HtmlWebpackPlugin({ excludeChunks: ['processTaskWorker'], diff --git a/jsconfig.json b/jsconfig.json index 8f5ea8a228e3c..6efa53c23ad98 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -1,5 +1,8 @@ { "vueCompilerOptions": { "target": 2.7 + }, + "compilerOptions": { + "strictNullChecks": true } } diff --git a/package.json b/package.json index e0fe5fb099682..692604f509eeb 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "marked": "^11.2.0", "path-browserify": "^1.0.1", "process": "^0.11.10", - "swiper": "^11.0.5", + "swiper": "^11.0.6", "video.js": "7.21.5", "videojs-contrib-quality-levels": "^3.0.0", "videojs-http-source-selector": "^1.1.6", @@ -77,19 +77,19 @@ "vue-observe-visibility": "^1.0.0", "vue-router": "^3.6.5", "vuex": "^3.6.2", - "youtubei.js": "^8.2.0" + "youtubei.js": "^9.0.2" }, "devDependencies": { "@babel/core": "^7.23.9", - "@babel/eslint-parser": "^7.23.9", + "@babel/eslint-parser": "^7.23.10", "@babel/plugin-proposal-class-properties": "^7.18.6", "@babel/preset-env": "^7.23.9", - "@double-great/stylelint-a11y": "^3.0.0", + "@double-great/stylelint-a11y": "^3.0.1", "babel-loader": "^9.1.3", "copy-webpack-plugin": "^12.0.2", - "css-loader": "^6.9.1", + "css-loader": "^6.10.0", "css-minimizer-webpack-plugin": "^6.0.0", - "electron": "^28.2.0", + "electron": "^28.2.2", "electron-builder": "^24.9.1", "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", @@ -99,23 +99,23 @@ "eslint-plugin-n": "^16.6.2", "eslint-plugin-prettier": "^5.1.3", "eslint-plugin-promise": "^6.1.1", - "eslint-plugin-unicorn": "^50.0.1", - "eslint-plugin-vue": "^9.20.1", + "eslint-plugin-unicorn": "^51.0.1", + "eslint-plugin-vue": "^9.21.1", "eslint-plugin-vuejs-accessibility": "^2.2.1", "eslint-plugin-yml": "^1.12.2", "html-webpack-plugin": "^5.6.0", "js-yaml": "^4.1.0", "json-minimizer-webpack-plugin": "^5.0.0", "lefthook": "^1.6.1", - "mini-css-extract-plugin": "^2.7.7", + "mini-css-extract-plugin": "^2.8.0", "npm-run-all": "^4.1.5", - "postcss": "^8.4.33", + "postcss": "^8.4.35", "postcss-scss": "^4.0.9", "prettier": "^2.8.8", "rimraf": "^5.0.5", "sass": "^1.70.0", - "sass-loader": "^14.0.0", - "stylelint": "^16.2.0", + "sass-loader": "^14.1.0", + "stylelint": "^16.2.1", "stylelint-config-sass-guidelines": "^11.0.0", "stylelint-config-standard": "^36.0.0", "stylelint-high-performance-animation": "^1.10.0", @@ -124,7 +124,7 @@ "vue-devtools": "^5.1.4", "vue-eslint-parser": "^9.4.2", "vue-loader": "^15.10.0", - "webpack": "^5.90.0", + "webpack": "^5.90.1", "webpack-cli": "^5.1.4", "webpack-dev-server": "^4.15.1", "webpack-watch-external-files-plugin": "^3.0.0", diff --git a/src/main/index.js b/src/main/index.js index 23b561cee10b4..2f8944c88df09 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -493,6 +493,8 @@ function runApp() { return '#ffd1dc' case 'hot-pink': return '#de1c85' + case 'nordic': + return '#2b2f3a' case 'system': default: return nativeTheme.shouldUseDarkColors ? '#212121' : '#f1f1f1' diff --git a/src/renderer/components/playlist-info/playlist-info.scss b/src/renderer/components/playlist-info/playlist-info.scss index be8766bfa89c2..8bf11cf0882e4 100644 --- a/src/renderer/components/playlist-info/playlist-info.scss +++ b/src/renderer/components/playlist-info/playlist-info.scss @@ -82,3 +82,10 @@ grid-template-columns: 1fr auto; column-gap: 8px; } + +@media only screen and (max-width: 1250px) { + :deep(.sharePlaylistIcon .iconDropdown) { + inset-inline-start: auto; + inset-inline-end: auto; + } +} diff --git a/src/renderer/components/playlist-info/playlist-info.vue b/src/renderer/components/playlist-info/playlist-info.vue index 68277fb44430b..1f3b11715bd63 100644 --- a/src/renderer/components/playlist-info/playlist-info.vue +++ b/src/renderer/components/playlist-info/playlist-info.vue @@ -174,6 +174,7 @@ diff --git a/src/renderer/components/side-nav-more-options/side-nav-more-options.vue b/src/renderer/components/side-nav-more-options/side-nav-more-options.vue index 6541150f21a3f..07f17810e3a1a 100644 --- a/src/renderer/components/side-nav-more-options/side-nav-more-options.vue +++ b/src/renderer/components/side-nav-more-options/side-nav-more-options.vue @@ -44,6 +44,7 @@ />
-
-
- - - -
-
- - {{ channelName }} - - -
-
-
-
-
- {{ publishedString }} {{ dateString }} -
-
- {{ parsedViewCount }} +
+
+ {{ publishedString }} {{ dateString }} • {{ parsedViewCount }}
+
+
+
+
+ + + +
+
+ + {{ channelName }} + + +
+
node.type === 'TopicChannelDetails') + name = topicChannelDetails.title.text + subscriberText = topicChannelDetails.subtitle.text + thumbnailUrl = topicChannelDetails.avatar[0].url + + if (channel.metadata.external_id) { + id = channel.metadata.external_id + } else { + id = topicChannelDetails.subscribe_button.channel_id + } + break + } + case 'InteractiveTabbedHeader': { + // example: Minecraft - Topic + // https://www.youtube.com/channel/UCQvWX73GQygcwXOTSf_VDVg + + /** + * @type {import('youtubei.js').YTNodes.InteractiveTabbedHeader} + */ + const header = channel.header + name = header.title.text + thumbnailUrl = header.box_art.at(-1).url + bannerUrl = header.banner[0]?.url + + const badges = header.badges.map(badge => badge.label).filter(tag => tag) + tags.push(...badges) + + id = channel.current_tab?.endpoint.payload.browseId + break + } + case 'PageHeader': { + // example: YouTube Gaming + // https://www.youtube.com/channel/UCOpNcN46UbXVtpKMrmU4Abg + + // User channels (an A/B test at the time of writing) + + /** + * @type {import('youtubei.js').YTNodes.PageHeader} + */ + const header = channel.header + + name = header.content.title.text.text + if (header.content.image) { + if (header.content.image.type === 'ContentPreviewImageView') { + /** @type {import('youtubei.js').YTNodes.ContentPreviewImageView} */ + const image = header.content.image + + thumbnailUrl = image.image[0].url + } else { + /** @type {import('youtubei.js').YTNodes.DecoratedAvatarView} */ + const image = header.content.image + thumbnailUrl = image.avatar?.image[0].url + } + } + + if (!thumbnailUrl && channel.metadata.thumbnail) { + thumbnailUrl = channel.metadata.thumbnail[0].url + } + + if (header.content.banner) { + bannerUrl = header.content.banner.image[0]?.url + } + + if (header.content.actions) { + const modal = header.content.actions.actions_rows[0].actions[0].on_tap.modal + + if (modal && modal.type === 'ModalWithTitleAndButton') { + /** @type {import('youtubei.js').YTNodes.ModalWithTitleAndButton} */ + const typedModal = modal + + id = typedModal.button.endpoint.next_endpoint?.payload.browseId + } + } else if (channel.metadata.external_id) { + id = channel.metadata.external_id + } + + if (header.content.metadata) { + subscriberText = header.content.metadata.metadata_rows[0].metadata_parts[1].text.text + } + + break + } + } + + return { + id, + name, + thumbnailUrl, + bannerUrl, + subscriberText, + tags + } +} + /** * @param {import('youtubei.js').YTNodes.Video[]} videos - * @param {Misc.Author} author + * @param {string} channelId + * @param {string} channelName */ -export function parseLocalChannelVideos(videos, author) { +export function parseLocalChannelVideos(videos, channelId, channelName) { const parsedVideos = videos.map(parseLocalListVideo) // fix empty author info parsedVideos.forEach(video => { - video.author = author.name - video.authorId = author.id + video.author = channelName + video.authorId = channelId }) return parsedVideos @@ -382,16 +528,17 @@ export function parseLocalChannelVideos(videos, author) { /** * @param {import('youtubei.js').YTNodes.ReelItem[]} shorts - * @param {Misc.Author} author + * @param {string} channelId + * @param {string} channelName */ -export function parseLocalChannelShorts(shorts, author) { +export function parseLocalChannelShorts(shorts, channelId, channelName) { return shorts.map(short => { return { type: 'video', videoId: short.id, title: short.title.text, - author: author.name, - authorId: author.id, + author: channelName, + authorId: channelId, viewCount: parseLocalSubscriberCount(short.views.text), lengthSeconds: '' } @@ -405,40 +552,43 @@ export function parseLocalChannelShorts(shorts, author) { /** * @param {Playlist|GridPlaylist} playlist - * @param {Misc.Author} author + * @param {string} channelId + * @param {string} chanelName */ -export function parseLocalListPlaylist(playlist, author = undefined) { - let channelName - let channelId = null - /** @type {import('youtubei.js').YTNodes.PlaylistVideoThumbnail} */ - const thumbnailRenderer = playlist.thumbnail_renderer +export function parseLocalListPlaylist(playlist, channelId = undefined, channelName = undefined) { + let internalChannelName + let internalChannelId = null + if (playlist.author && playlist.author.id !== 'N/A') { if (playlist.author instanceof Misc.Text) { - channelName = playlist.author.text + internalChannelName = playlist.author.text - if (author) { - channelId = author.id + if (channelId) { + internalChannelId = channelId } } else { - channelName = playlist.author.name - channelId = playlist.author.id + internalChannelName = playlist.author.name + internalChannelId = playlist.author.id } - } else if (author) { - channelName = author.name - channelId = author.id + } else if (channelId || channelName) { + internalChannelName = channelName + internalChannelId = channelId } else if (playlist.author?.name) { // auto-generated album playlists don't have an author // so in search results, the author text is "Playlist" and doesn't have a link or channel ID - channelName = playlist.author.name + internalChannelName = playlist.author.name } + /** @type {import('youtubei.js').YTNodes.PlaylistVideoThumbnail} */ + const thumbnailRenderer = playlist.thumbnail_renderer + return { type: 'playlist', dataSource: 'local', title: playlist.title.text, thumbnail: thumbnailRenderer ? thumbnailRenderer.thumbnail[0].url : playlist.thumbnails[0].url, - channelName, - channelId, + channelName: internalChannelName, + channelId: internalChannelId, playlistId: playlist.id, videoCount: extractNumberFromString(playlist.video_count.text) } @@ -742,7 +892,7 @@ export function parseLocalTextRuns(runs, emojiSize = 16, options = { looseChanne case 'WEB_PAGE_TYPE_CHANNEL': { const trimmedText = text.trim() // In comments, mention can be `@Channel Name` (not handle, but name) - if (CHANNEL_HANDLE_REGEX.test(trimmedText) || (options.looseChannelNameDetection && trimmedText.startsWith('@'))) { + if (CHANNEL_HANDLE_REGEX.test(trimmedText) || options.looseChannelNameDetection) { // Note that in regex `\s` must be used since the text contain non-default space (the half-width space char when we press spacebar) const spacesBefore = (spacesBeforeRegex.exec(text) || [''])[0] const spacesAfter = (spacesAfterRegex.exec(text) || [''])[0] diff --git a/src/renderer/helpers/utils.js b/src/renderer/helpers/utils.js index 0a4f3d5a8489e..4fde63b77c033 100644 --- a/src/renderer/helpers/utils.js +++ b/src/renderer/helpers/utils.js @@ -616,9 +616,10 @@ export function getVideoParamsFromUrl(url) { /** * This will match sequences of upper case characters and convert them into title cased words. + * This will also match excessive strings of punctionation and convert them to one representative character * @param {string} title the title to process * @param {number} minUpperCase the minimum number of consecutive upper case characters to match - * @returns {string} the title with upper case characters removed + * @returns {string} the title with upper case characters removed and punctuation normalized */ export function toDistractionFreeTitle(title, minUpperCase = 3) { const firstValidCharIndex = (word) => { @@ -634,7 +635,10 @@ export function toDistractionFreeTitle(title, minUpperCase = 3) { } const reg = RegExp(`[\\p{Lu}|']{${minUpperCase},}`, 'ug') - return title.replace(reg, x => capitalizedWord(x.toLowerCase())) + return title + .replaceAll(/!{2,}/g, '!') + .replaceAll(/[!?]{2,}/g, '?') + .replace(reg, x => capitalizedWord(x.toLowerCase())) } export function formatNumber(number, options = undefined) { diff --git a/src/renderer/store/modules/invidious.js b/src/renderer/store/modules/invidious.js index c104ccf09741b..759632e2ddc55 100644 --- a/src/renderer/store/modules/invidious.js +++ b/src/renderer/store/modules/invidious.js @@ -1,5 +1,4 @@ import fs from 'fs/promises' -import { pathExists } from '../../helpers/filesystem' import { createWebURL, fetchWithTimeout } from '../../helpers/utils' const state = { @@ -47,7 +46,7 @@ const actions = { /* eslint-disable-next-line n/no-path-concat */ const fileLocation = process.env.NODE_ENV === 'development' ? './static/' : `${__dirname}/static/` const filePath = `${fileLocation}${fileName}` - if (!process.env.IS_ELECTRON || await pathExists(filePath)) { + if (!process.env.IS_ELECTRON) { console.warn('reading static file for invidious instances') const fileData = process.env.IS_ELECTRON ? await fs.readFile(filePath, 'utf8') : await (await fetch(createWebURL(filePath))).text() instances = JSON.parse(fileData).filter(e => { diff --git a/src/renderer/store/modules/utils.js b/src/renderer/store/modules/utils.js index 428c92e69ac73..243520044a821 100644 --- a/src/renderer/store/modules/utils.js +++ b/src/renderer/store/modules/utils.js @@ -358,14 +358,10 @@ const actions = { }, async getRegionData ({ commit }, { locale }) { - let localePathExists + const localePathExists = process.env.GEOLOCATION_NAMES.includes(locale) // Exclude __dirname from path if not in electron const fileLocation = `${process.env.IS_ELECTRON ? process.env.NODE_ENV === 'development' ? '.' : __dirname : ''}/static/geolocations/` - if (process.env.IS_ELECTRON) { - localePathExists = await pathExists(`${fileLocation}${locale}.json`) - } else { - localePathExists = process.env.GEOLOCATION_NAMES.includes(locale) - } + const pathName = `${fileLocation}${localePathExists ? locale : 'en-US'}.json` const countries = process.env.IS_ELECTRON ? JSON.parse(await fs.readFile(pathName)) : await (await fetch(createWebURL(pathName))).json() @@ -601,15 +597,10 @@ const actions = { async getExternalPlayerCmdArgumentsData ({ commit }, payload) { const fileName = 'external-player-map.json' - let fileData /* eslint-disable-next-line n/no-path-concat */ const fileLocation = process.env.NODE_ENV === 'development' ? './static/' : `${__dirname}/static/` - if (await pathExists(`${fileLocation}${fileName}`)) { - fileData = await fs.readFile(`${fileLocation}${fileName}`) - } else { - fileData = '[{"name":"None","value":"","cmdArguments":null}]' - } + const fileData = await fs.readFile(`${fileLocation}${fileName}`) const externalPlayerMap = JSON.parse(fileData).map((entry) => { return { name: entry.name, nameTranslationKey: entry.nameTranslationKey, value: entry.value, cmdArguments: entry.cmdArguments } diff --git a/src/renderer/themes.css b/src/renderer/themes.css index 0e6ddecf4a285..fd100cc5f5f2f 100644 --- a/src/renderer/themes.css +++ b/src/renderer/themes.css @@ -5,7 +5,8 @@ .dracula, .catppuccinMocha, .pastelPink, -.hotPink { +.hotPink, +.nordic { --primary-input-color: rgba(0, 0, 0, 0.50); } @@ -15,7 +16,8 @@ .dracula, .catppuccinMocha, .pastelPink, -.hotPink { +.hotPink, +.nordic { --link-color: var(--accent-color); --link-visited-color: var(--accent-color-visited); --instance-menu-color: var(--search-bar-color); @@ -27,7 +29,8 @@ .gray, .dracula, .catppuccinMocha, -.pastelPink { +.pastelPink, +.nordic { --primary-input-color: rgba(0, 0, 0, 0.50); --side-nav-hover-text-color: var(--primary-text-color); } @@ -37,7 +40,8 @@ .black, .gray, .dracula, -.catppuccinMocha { +.catppuccinMocha, +.nordic { --side-nav-active-text-color: var(--primary-text-color); --scrollbar-text-color-hover: var(--primary-text-color); @@ -56,7 +60,8 @@ .gray, .dracula, .catppuccinMocha, -.hotPink { +.hotPink, +.nordic { --primary-shadow-color: rgba(0, 0, 0, 0.75); } @@ -237,6 +242,25 @@ it can be safely elided. This looks quite pleasant on this theme. */ text-decoration: underline; } +.nordic { + --primary-text-color: #EEEEEE; + --secondary-text-color: #ddd; + --tertiary-text-color: #EEEEEE; + --title-color: #EEEEEE; + --bg-color: #2b2f3a; + --favorite-icon-color: #FFEA00; + --card-bg-color: #2e3440; + --secondary-card-bg-color: rgba(59, 66, 82, 0.75); + --scrollbar-color: #4b566a; + --scrollbar-color-hover: #4b566a; + --side-nav-color: #2e3440; + --side-nav-hover-color: #3b4252; + --side-nav-active-color: #3b4252; + --search-bar-color: #4b566a; + --logo-icon: url("../../_icons/iconNordicLightSmall.png"); + --logo-text: url("../../_icons/textNordicLightSmall.png"); +} + .mainRed, .mainPink, .mainPurple, diff --git a/src/renderer/views/Channel/Channel.css b/src/renderer/views/Channel/Channel.css index e2b9b521360b6..a1324d2bb8237 100644 --- a/src/renderer/views/Channel/Channel.css +++ b/src/renderer/views/Channel/Channel.css @@ -217,6 +217,23 @@ } } +@media only screen and (max-width: 680px) { + .channelInfo { + flex-direction: column; + margin-block: 20px 10px; + } + .card { + max-inline-size: none; + inline-size: 100%; + } + .channelInfoActionsContainer { + flex-direction: row-reverse; + justify-content: left; + gap: 10px; + margin-block-start: 5px; + } +} + @media only screen and (max-width: 400px) { .channelInfo { justify-content: center; @@ -224,7 +241,11 @@ } .channelInfoActionsContainer { - flex-direction: column-reverse; + justify-content: center; + } + + .channelLineContainer { + padding-inline-start: 0; } .thumbnailContainer { diff --git a/src/renderer/views/Channel/Channel.js b/src/renderer/views/Channel/Channel.js index 0fedac2c90f4c..3fea114b788a0 100644 --- a/src/renderer/views/Channel/Channel.js +++ b/src/renderer/views/Channel/Channel.js @@ -25,6 +25,7 @@ import { import { getLocalChannel, getLocalChannelId, + parseLocalChannelHeader, parseLocalChannelShorts, parseLocalChannelVideos, parseLocalCommunityPosts, @@ -532,90 +533,22 @@ export default defineComponent({ return } - let channelId - let subscriberText = null - let tags = [] + const parsedHeader = parseLocalChannelHeader(channel) - switch (channel.header.type) { - case 'C4TabbedHeader': { - // example: Linus Tech Tips - // https://www.youtube.com/channel/UCXuqSBlHAE6Xw-yeJA0Tunw + const channelId = parsedHeader.id ?? this.id + const subscriberText = parsedHeader.subscriberText ?? null + let tags = parsedHeader.tags - /** - * @type {import('youtubei.js').YTNodes.C4TabbedHeader} - */ - const header = channel.header + channelThumbnailUrl = parsedHeader.thumbnailUrl ?? this.subscriptionInfo?.thumbnail + channelName = parsedHeader.name ?? this.subscriptionInfo?.name - channelId = header.author.id - channelName = header.author.name - channelThumbnailUrl = header.author.best_thumbnail.url - subscriberText = header.subscribers?.text - break - } - case 'CarouselHeader': { - // examples: Music and YouTube Gaming - // https://www.youtube.com/channel/UC-9-kyTW8ZkZNDHQJ6FgpwQ - // https://www.youtube.com/channel/UCOpNcN46UbXVtpKMrmU4Abg - - /** - * @type {import('youtubei.js').YTNodes.CarouselHeader} - */ - const header = channel.header - - /** - * @type {import('youtubei.js').YTNodes.TopicChannelDetails} - */ - const topicChannelDetails = header.contents.find(node => node.type === 'TopicChannelDetails') - channelName = topicChannelDetails.title.text - subscriberText = topicChannelDetails.subtitle.text - channelThumbnailUrl = topicChannelDetails.avatar[0].url - - if (channel.metadata.external_id) { - channelId = channel.metadata.external_id - } else { - channelId = topicChannelDetails.subscribe_button.channel_id - } - break - } - case 'InteractiveTabbedHeader': { - // example: Minecraft - Topic - // https://www.youtube.com/channel/UCQvWX73GQygcwXOTSf_VDVg - - /** - * @type {import('youtubei.js').YTNodes.InteractiveTabbedHeader} - */ - const header = channel.header - channelName = header.title.text - channelId = this.id - channelThumbnailUrl = header.box_art.at(-1).url - - const badges = header.badges.map(badge => badge.label).filter(tag => tag) - tags.push(...badges) - break - } - case 'PageHeader': { - // example: YouTube Gaming (an A/B test at the time of writing) - // https://www.youtube.com/channel/UCOpNcN46UbXVtpKMrmU4Abg - - /** - * @type {import('youtubei.js').YTNodes.PageHeader} - */ - const header = channel.header - - channelName = header.content.title.text - channelThumbnailUrl = header.content.image.image[0].url - channelId = this.id - - break - } - } - - if (channelThumbnailUrl.startsWith('//')) { + if (channelThumbnailUrl?.startsWith('//')) { channelThumbnailUrl = `https:${channelThumbnailUrl}` } this.channelName = channelName this.thumbnailUrl = channelThumbnailUrl + this.bannerUrl = parsedHeader.bannerUrl ?? null this.isFamilyFriendly = !!channel.metadata.is_family_safe if (channel.metadata.tags) { @@ -646,12 +579,6 @@ export default defineComponent({ this.updateSubscriptionDetails({ channelThumbnailUrl, channelName, channelId }) - if (channel.header.banner?.length > 0) { - this.bannerUrl = channel.header.banner[0].url - } else { - this.bannerUrl = null - } - let relatedChannels = channel.channels.map(({ author }) => ({ name: author.name, id: author.id, @@ -837,7 +764,7 @@ export default defineComponent({ return } - this.latestVideos = parseLocalChannelVideos(videosTab.videos, channel.header.author) + this.latestVideos = parseLocalChannelVideos(videosTab.videos, this.id, this.channelName) this.videoContinuationData = videosTab.has_continuation ? videosTab : null this.isElementListLoading = false } catch (err) { @@ -862,7 +789,7 @@ export default defineComponent({ */ const continuation = await this.videoContinuationData.getContinuation() - this.latestVideos = this.latestVideos.concat(parseLocalChannelVideos(continuation.videos, this.channelInstance.header.author)) + this.latestVideos = this.latestVideos.concat(parseLocalChannelVideos(continuation.videos, this.id, this.channelName)) this.videoContinuationData = continuation.has_continuation ? continuation : null } catch (err) { console.error(err) @@ -895,7 +822,7 @@ export default defineComponent({ return } - this.latestShorts = parseLocalChannelShorts(shortsTab.videos, channel.header.author) + this.latestShorts = parseLocalChannelShorts(shortsTab.videos, this.id, this.channelName) this.shortContinuationData = shortsTab.has_continuation ? shortsTab : null this.isElementListLoading = false } catch (err) { @@ -920,7 +847,7 @@ export default defineComponent({ */ const continuation = await this.shortContinuationData.getContinuation() - this.latestShorts.push(...parseLocalChannelShorts(continuation.videos, this.channelInstance.header.author)) + this.latestShorts.push(...parseLocalChannelShorts(continuation.videos, this.id, this.channelName)) this.shortContinuationData = continuation.has_continuation ? continuation : null } catch (err) { console.error(err) @@ -953,7 +880,7 @@ export default defineComponent({ return } - this.latestLive = parseLocalChannelVideos(liveTab.videos, channel.header.author) + this.latestLive = parseLocalChannelVideos(liveTab.videos, this.id, this.channelName) this.liveContinuationData = liveTab.has_continuation ? liveTab : null this.isElementListLoading = false } catch (err) { @@ -978,7 +905,7 @@ export default defineComponent({ */ const continuation = await this.liveContinuationData.getContinuation() - this.latestLive.push(...parseLocalChannelVideos(continuation.videos, this.channelInstance.header.author)) + this.latestLive.push(...parseLocalChannelVideos(continuation.videos, this.id, this.channelName)) this.liveContinuationData = continuation.has_continuation ? continuation : null } catch (err) { console.error(err) @@ -1270,7 +1197,7 @@ export default defineComponent({ return } - this.latestPlaylists = playlistsTab.playlists.map(playlist => parseLocalListPlaylist(playlist, channel.header.author)) + this.latestPlaylists = playlistsTab.playlists.map(playlist => parseLocalListPlaylist(playlist, this.id, this.channelName)) this.playlistContinuationData = playlistsTab.has_continuation ? playlistsTab : null this.isElementListLoading = false } catch (err) { @@ -1295,7 +1222,7 @@ export default defineComponent({ */ const continuation = await this.playlistContinuationData.getContinuation() - const parsedPlaylists = continuation.playlists.map(playlist => parseLocalListPlaylist(playlist, this.channelInstance.header.author)) + const parsedPlaylists = continuation.playlists.map(playlist => parseLocalListPlaylist(playlist, this.id, this.channelName)) this.latestPlaylists = this.latestPlaylists.concat(parsedPlaylists) this.playlistContinuationData = continuation.has_continuation ? continuation : null } catch (err) { @@ -1393,7 +1320,7 @@ export default defineComponent({ return } - this.latestReleases = releaseTab.playlists.map(playlist => parseLocalListPlaylist(playlist, channel.header.author)) + this.latestReleases = releaseTab.playlists.map(playlist => parseLocalListPlaylist(playlist, this.id, this.channelName)) this.releaseContinuationData = releaseTab.has_continuation ? releaseTab : null this.isElementListLoading = false } catch (err) { @@ -1418,7 +1345,7 @@ export default defineComponent({ */ const continuation = await this.releaseContinuationData.getContinuation() - const parsedReleases = continuation.playlists.map(playlist => parseLocalListPlaylist(playlist, this.channelInstance.header.author)) + const parsedReleases = continuation.playlists.map(playlist => parseLocalListPlaylist(playlist, this.id, this.channelName)) this.latestReleases = this.latestReleases.concat(parsedReleases) this.releaseContinuationData = continuation.has_continuation ? continuation : null } catch (err) { @@ -1506,7 +1433,7 @@ export default defineComponent({ return } - this.latestPodcasts = podcastTab.playlists.map(playlist => parseLocalListPlaylist(playlist, channel.header.author)) + this.latestPodcasts = podcastTab.playlists.map(playlist => parseLocalListPlaylist(playlist, this.id, this.channelName)) this.podcastContinuationData = podcastTab.has_continuation ? podcastTab : null this.isElementListLoading = false } catch (err) { @@ -1531,7 +1458,7 @@ export default defineComponent({ */ const continuation = await this.podcastContinuationData.getContinuation() - const parsedPodcasts = continuation.playlists.map(playlist => parseLocalListPlaylist(playlist, this.channelInstance.header.author)) + const parsedPodcasts = continuation.playlists.map(playlist => parseLocalListPlaylist(playlist, this.id, this.channelName)) this.latestPodcasts = this.latestPodcasts.concat(parsedPodcasts) this.releaseContinuationData = continuation.has_continuation ? continuation : null } catch (err) { @@ -1857,7 +1784,7 @@ export default defineComponent({ if (item.type === 'Video') { return parseLocalListVideo(item) } else { - return parseLocalListPlaylist(item, this.channelInstance.header.author) + return parseLocalListPlaylist(item, this.id, this.channelName) } }) diff --git a/src/renderer/views/Playlist/Playlist.scss b/src/renderer/views/Playlist/Playlist.scss index e8c2b7681d952..939f3a5cc4a5c 100644 --- a/src/renderer/views/Playlist/Playlist.scss +++ b/src/renderer/views/Playlist/Playlist.scss @@ -7,7 +7,6 @@ box-sizing: border-box; block-size: calc(100vh - 132px); margin-inline-end: 1em; - overflow-y: auto; padding: 10px; position: sticky; inset-block-start: 96px; diff --git a/src/renderer/views/Watch/Watch.scss b/src/renderer/views/Watch/Watch.scss index cf58ed9c5f23c..ad61d8af942a5 100644 --- a/src/renderer/views/Watch/Watch.scss +++ b/src/renderer/views/Watch/Watch.scss @@ -16,7 +16,7 @@ display: inline-block; max-inline-size: calc(80vh * 1.78); - @media only screen and (min-width: 901px) { + @media only screen and (min-width: 1051px) { inline-size: 300%; } } @@ -99,7 +99,7 @@ .sidebarArea { grid-area: sidebar; - @media only screen and (min-width: 901px) { + @media only screen and (min-width: 1051px) { min-inline-size: 380px; } @@ -135,7 +135,7 @@ margin-block: 0 16px; margin-inline: 0; - @media only screen and (min-width: 901px) { + @media only screen and (min-width: 1051px) { margin-block: 0 16px; margin-inline: 8px; } @@ -145,17 +145,17 @@ @include theatre-mode-template; } - @media only screen and (min-width: 901px) { + @media only screen and (min-width: 1051px) { &.useTheatreMode { @include theatre-mode-template; } } - @media only screen and (max-width: 900px) { + @media only screen and (max-width: 1050px) { @include single-column-template; } - @media only screen and (min-width: 901px) { + @media only screen and (min-width: 1051px) { .infoArea { scroll-margin-block-start: 76px; } diff --git a/static/locales/ar.yaml b/static/locales/ar.yaml index 16cc03500ed5f..7e1e53a9315a0 100644 --- a/static/locales/ar.yaml +++ b/static/locales/ar.yaml @@ -276,6 +276,7 @@ Settings: Catppuccin Mocha: كاتبوتشين موكا Pastel Pink: الباستيل الوردي Hot Pink: وردي فاقع + Nordic: بلدان الشمال الأوروبي Main Color Theme: Main Color Theme: 'لون السِمة الأساسي' Red: 'أحمر' @@ -517,8 +518,8 @@ Settings: Hide Upcoming Premieres: إخفاء العروض الأولى القادمة Hide Channels: إخفاء مقاطع الفيديو من القنوات Hide Channels Placeholder: معرف القناة - Display Titles Without Excessive Capitalisation: عرض العناوين بدون احرف كبيرة - بشكل مفرط + Display Titles Without Excessive Capitalisation: عرض العناوين بدون استخدام الأحرف + الكبيرة وعلامات الترقيم بشكل مفرط Hide Featured Channels: إخفاء القنوات المميزة Hide Channel Playlists: إخفاء قوائم تشغيل القناة Hide Channel Community: إخفاء مجتمع القناة diff --git a/static/locales/cs.yaml b/static/locales/cs.yaml index fab5bbc22d745..d4ebe99b9c920 100644 --- a/static/locales/cs.yaml +++ b/static/locales/cs.yaml @@ -292,6 +292,7 @@ Settings: Catppuccin Mocha: Catppuccin Mocha Hot Pink: Horká růžová Pastel Pink: Pastelově růžová + Nordic: Nordic Main Color Theme: Main Color Theme: 'Hlavní barva motivu' Red: 'Červená' @@ -443,7 +444,7 @@ Settings: Hide Channels: Skrýt videa z kanálů Hide Channels Placeholder: ID kanálu Display Titles Without Excessive Capitalisation: Zobrazit názvy bez nadměrného - použití velkých písmen + použití velkých písmen a interpunkce Hide Featured Channels: Skrýt doporučené kanály Hide Channel Playlists: Skrýt playlisty kanálu Hide Channel Community: Skrýt komunitu kanálu diff --git a/static/locales/de-DE.yaml b/static/locales/de-DE.yaml index f67cb6fef43fc..d4b411d365225 100644 --- a/static/locales/de-DE.yaml +++ b/static/locales/de-DE.yaml @@ -294,6 +294,7 @@ Settings: Catppuccin Mocha: Catppuccin Mocha Hot Pink: Pink Pastel Pink: Pastellrosa + Nordic: Nordic Main Color Theme: Main Color Theme: Hauptfarbe des Farbschemas Red: Rot @@ -1244,4 +1245,4 @@ Channel Unhidden: '{channel} wurde aus dem Kanalfilter entfernt' Trimmed input must be at least N characters long: Gekürzte Eingaben müssen mindestens 1 Zeichen lang sein | Gekürzte Eingaben müssen mindestens {length} Zeichen lang sein -Tag already exists: Der Tag "{tagName}" existiert bereits +Tag already exists: Die Markierung „{tagName}“ existiert bereits diff --git a/static/locales/en-US.yaml b/static/locales/en-US.yaml index 78a7ad475be6a..e3d88c90eb6b0 100644 --- a/static/locales/en-US.yaml +++ b/static/locales/en-US.yaml @@ -298,6 +298,7 @@ Settings: Catppuccin Mocha: Catppuccin Mocha Pastel Pink: Pastel Pink Hot Pink: Hot Pink + Nordic: Nordic Main Color Theme: Main Color Theme: Main Color Theme Red: Red @@ -452,7 +453,7 @@ Settings: Hide Video Description: Hide Video Description Hide Comments: Hide Comments Hide Profile Pictures in Comments: Hide Profile Pictures in Comments - Display Titles Without Excessive Capitalisation: Display Titles Without Excessive Capitalisation + Display Titles Without Excessive Capitalisation: Display Titles Without Excessive Capitalisation And Punctuation Hide Live Streams: Hide Live Streams Hide Upcoming Premieres: Hide Upcoming Premieres Hide Sharing Actions: Hide Sharing Actions diff --git a/static/locales/en_GB.yaml b/static/locales/en_GB.yaml index 5c6b5c5ec283b..37eb409998b8e 100644 --- a/static/locales/en_GB.yaml +++ b/static/locales/en_GB.yaml @@ -43,6 +43,8 @@ Global: View Count: 1 view | {count} views Watching Count: 1 watching | {count} watching Channel Count: 1 channel | {count} channels + Input Tags: + Length Requirement: Tag must be at least {number} characters long Version {versionNumber} is now available! Click for more details: 'Version {versionNumber} is now available! Click for more details' Download From Site: 'Download from site' @@ -167,6 +169,14 @@ User Playlists: There was an issue with updating this playlist.: There was an issue with updating this playlist. There were no videos to remove.: There were no videos to remove. + Reverted to use {oldPlaylistName} for quick bookmark: Reverted to use {oldPlaylistName} + for quick bookmark + This playlist is now used for quick bookmark: This playlist is now used for + quick bookmark + This playlist is now used for quick bookmark instead of {oldPlaylistName}. Click here to undo: This + playlist is now used for quick bookmark instead of {oldPlaylistName}. Click + here to undo + Quick bookmark disabled: Quick bookmark disabled AddVideoPrompt: N playlists selected: '{playlistCount} selected' Search in Playlists: Search in playlists @@ -193,6 +203,9 @@ User Playlists: Are you sure you want to delete this playlist? This cannot be undone: Are you sure you want to delete this playlist? This cannot be undone. Add to Favorites: Add to {playlistName} + Remove from Favorites: Remove from {playlistName} + Enable Quick Bookmark With This Playlist: Enable quick bookmark with this playlist + Disable Quick Bookmark: Disable quick bookmark History: # On History Page History: 'History' @@ -230,14 +243,14 @@ Settings: Hidden: Hidden 'Invidious Instance (Default is https://invidious.snopyta.org)': 'Invidious Instance (Default is https://invidious.snopyta.org)' - Region for Trending: 'Region for Trending' + Region for Trending: 'Region for trending' #! List countries View all Invidious instance information: View all Invidious instance information System Default: System default External Player: External Player External Player Executable: Custom External Player Executable Clear Default Instance: Clear default instance - Set Current Instance as Default: Set Current Instance as Default + Set Current Instance as Default: Set current instance as default Current instance will be randomized on startup: Current instance will be randomised on startup No default instance has been set: No default instance has been set @@ -245,23 +258,24 @@ Settings: is {instance} Current Invidious Instance: Current Invidious Instance External Link Handling: - No Action: No Action - Ask Before Opening Link: Ask Before Opening Link - Open Link: Open Link - External Link Handling: External Link Handling + No Action: No action + Ask Before Opening Link: Ask before opening link + Open Link: Open link + External Link Handling: External link handling Theme Settings: - Theme Settings: 'Theme Settings' + Theme Settings: 'Theme settings' Match Top Bar with Main Color: 'Match top bar with main colour' Base Theme: Base Theme: 'Base theme' Black: 'Black' Dark: 'Dark' - System Default: 'System Default' + System Default: 'System default' Light: 'Light' Dracula: 'Dracula' Catppuccin Mocha: Catppuccin Mocha Pastel Pink: Pastel pink Hot Pink: Hot pink + Nordic: Nordic Main Color Theme: Main Color Theme: 'Main colour theme' Red: 'Red' @@ -307,7 +321,7 @@ Settings: Disable Smooth Scrolling: Disable smooth scrolling Expand Side Bar by Default: Expand side bar by default Hide Side Bar Labels: Hide side bar labels - Hide FreeTube Header Logo: Hide FreeTube Header Logo + Hide FreeTube Header Logo: Hide FreeTube header logo Player Settings: Player Settings: 'Player settings' Force Local Backend for Legacy Formats: 'Force local back-end for legacy formats' @@ -581,6 +595,7 @@ Settings: Remove Password: Remove password Password Settings: Password settings Set Password: Set password + Expand All Settings Sections: Expand all settings sections About: #On About page About: About @@ -1099,3 +1114,4 @@ Playlist will pause when current video is finished: Playlist will pause when cur Playlist will not pause when current video is finished: Playlist will not pause when current video is finished Go to page: Go to {page} +Tag already exists: ‘{tagName}’ tag already exists diff --git a/static/locales/es.yaml b/static/locales/es.yaml index 09c74e9462cbe..7922cac50c1c8 100644 --- a/static/locales/es.yaml +++ b/static/locales/es.yaml @@ -287,6 +287,7 @@ Settings: Catppuccin Mocha: Catppuccin Moca Pastel Pink: Rosa pastel Hot Pink: Rosa fuerte + Nordic: Nórdico Main Color Theme: Main Color Theme: 'Color principal' Red: 'Rojo' @@ -531,8 +532,8 @@ Settings: Hide Upcoming Premieres: Ocultar los próximos estrenos Hide Channels: Ocultar vídeos de los canales Hide Channels Placeholder: ID del canal - Display Titles Without Excessive Capitalisation: Mostrar títulos sin demasiadas - mayúsculas + Display Titles Without Excessive Capitalisation: Mostrar títulos sin mayúsculas + ni signos de puntuación excesivos Hide Featured Channels: Ocultar canales recomendados Hide Channel Playlists: Ocultar las listas de reproducción de los canales Hide Channel Community: Ocultar canales de la comunidad diff --git a/static/locales/et.yaml b/static/locales/et.yaml index c70d8e3072a68..73f5ea27eedb4 100644 --- a/static/locales/et.yaml +++ b/static/locales/et.yaml @@ -286,6 +286,7 @@ Settings: Catppuccin Mocha: Catppuccin Mocha Pastel Pink: Pastelne roosa Hot Pink: Säravroosa + Nordic: Põhjala Main Color Theme: Main Color Theme: 'Põhiline värviteema' Red: 'Punane' @@ -496,7 +497,7 @@ Settings: Hide Channels: Peida kanalites leiduvad videod Hide Channels Placeholder: Kanali tunnus Display Titles Without Excessive Capitalisation: Näita pealkirju ilma liigsete - suurtähtedeta + suurtähtede ja kirjavahemärkideta Sections: General: Üldist Side Bar: Külgpaan diff --git a/static/locales/fi.yaml b/static/locales/fi.yaml index a141cd51d5d8b..a5a490450c94e 100644 --- a/static/locales/fi.yaml +++ b/static/locales/fi.yaml @@ -175,6 +175,7 @@ User Playlists: on luotu. Add to Favorites: Lisää soittolistaan {playlistName} Remove from Favorites: Poista soittolistalta {playlistName} + Remove Watched Videos: Poista katsotut videot History: # On History Page History: 'Historia' diff --git a/static/locales/fr-FR.yaml b/static/locales/fr-FR.yaml index 242445b0a6335..a9961642d8e96 100644 --- a/static/locales/fr-FR.yaml +++ b/static/locales/fr-FR.yaml @@ -145,8 +145,8 @@ User Playlists: You haven't selected any playlist yet.: Vous n'avez pas encore sélectionné de liste de lecture. "{videoCount} video(s) added to {playlistCount} playlists": 1 vidéo ajoutée - à {playlistCount} liste de lecture | {videoCount} vidéos ajoutées à {playlistCount} - listes de lecture. + à {playlistCount} listes de lecture | {videoCount} vidéos ajoutées à {playlistCount} + listes de lecture N playlists selected: '{playlistCount} Sélectionnée(s)' SinglePlaylistView: Toast: @@ -299,6 +299,7 @@ Settings: Catppuccin Mocha: Catppuccin Moka Pastel Pink: Rose pastel Hot Pink: Rose vif + Nordic: Nordic Main Color Theme: Main Color Theme: 'Couleur principale du thème' Red: 'Rouge' @@ -467,7 +468,7 @@ Settings: sûr(e) de vouloir supprimer tous les abonnements et les profils ? Cette action est définitive. Remove All Subscriptions / Profiles: Supprimer tous les Abonnements / Profils - Automatically Remove Video Meta Files: Suppression automatiquement les métafichiers + Automatically Remove Video Meta Files: Supprimer automatiquement les métafichiers vidéo Save Watched Videos With Last Viewed Playlist: Sauvegarder les vidéos regardées avec la dernière liste de lecture vue @@ -556,7 +557,7 @@ Settings: Hide Channels: Masquer les vidéos des chaînes Hide Channels Placeholder: Identifiant de la chaîne Display Titles Without Excessive Capitalisation: Afficher les titres sans majuscules - excessives + ni ponctuation excessives Hide Channel Playlists: Masquer les listes de lecture des chaînes Hide Featured Channels: Masquer les chaînes en vedette Hide Channel Community: Masquer la communauté de la chaîne @@ -1265,4 +1266,4 @@ Channel Hidden: '{channel} ajouté au filtre de chaîne' Channel Unhidden: '{channel} retiré du filtre de chaîne' Trimmed input must be at least N characters long: L'entrée tronquée doit comporter au moins 1 caractère | L'entrée tronquée doit comporter au moins {length} caractères -Tag already exists: La balise "{tagName}" existe déjà +Tag already exists: L'étiquette « {tagName} » existe déjà diff --git a/static/locales/gl.yaml b/static/locales/gl.yaml index 6138c6079e9a8..534e621214e8c 100644 --- a/static/locales/gl.yaml +++ b/static/locales/gl.yaml @@ -36,6 +36,10 @@ Global: Videos: 'Vídeos' Community: Comunidade + Shorts: Cortos + Input Tags: + Length Requirement: A etiqueta debe ser de polo menos {number} caracteres. + Live: En vivo Version {versionNumber} is now available! Click for more details: 'A versión {versionNumber} está dispoñible! Fai clic para veres máis detalles' Download From Site: 'Descargar do sitio' @@ -656,8 +660,8 @@ Video: nesta versión.' 'Chat is disabled or the Live Stream has ended.': 'O chat foi desactivado ou a transmisión en vivo rematou.' - Live chat is enabled. Chat messages will appear here once sent.: 'Chat en vivo - activado. As mensaxes aparecerán aquí ao seren enviadas.' + Live chat is enabled. Chat messages will appear here once sent.: 'Chat en vivo activado. As + mensaxes aparecerán aquí ao seren enviadas.' 'Live Chat is currently not supported with the Invidious API. A direct connection to YouTube is required.': 'Chat en vivo actualmente non soportado coa API de Invidious. Precísase dunha conexión directa con YouTube.' @@ -844,9 +848,9 @@ Tooltips: as chamadas da aplicacion.' Region for Trending: 'A rexión das tendencias permíteche escoller os vídeos máis populares nun Estado.' - External Link Handling: "Escolla o comportamento predeterminado cando se fai clic\ - \ nunha ligazón, que non se pode abrir en FreeTube.\nDe forma predeterminada,\ - \ FreeTube abrirá a ligazón na que premeches no teu navegador predeterminado.\n" + External Link Handling: "Escolla o comportamento predeterminado cando se fai clic + nunha ligazón, que non se pode abrir en FreeTube.\nDe forma predeterminada, + FreeTube abrirá a ligazón na que premeches no teu navegador predeterminado.\n" Player Settings: Force Local Backend for Legacy Formats: 'Só funcionará se a API de Invidious está escollida por defecto. Cando estea activa, a API local usará formatos antigos @@ -977,3 +981,4 @@ Chapters: capítulo actual: {chapterName}' Screenshot Success: Captura da pantalla gardada como "{filePath}" Ok: De acordo +Go to page: Ir a {page} diff --git a/static/locales/hu.yaml b/static/locales/hu.yaml index 0d431f89843d0..6e903ca9bc697 100644 --- a/static/locales/hu.yaml +++ b/static/locales/hu.yaml @@ -296,6 +296,7 @@ Settings: Catppuccin Mocha: Catppuccin Mocha Pastel Pink: Pasztell rózsaszín Hot Pink: Forró rózsaszín + Nordic: Skandináv Main Color Theme: Main Color Theme: 'Fő színtéma' Red: 'Vörös' @@ -533,14 +534,14 @@ Settings: Hide Playlists: Lejátszási listák elrejtése Hide Video Description: Videó leírásának elrejtése Hide Comments: Megjegyzések elrejtése - Hide Live Streams: Élő adatfolyamok elrejtése + Hide Live Streams: Élő közvetítések elrejtése Hide Sharing Actions: Megosztási műveletek elrejtése Hide Chapters: Fejezetek elrejtése Hide Upcoming Premieres: Közelgő első előadások elrejtése Hide Channels: Videók elrejtése a csatornákból Hide Channels Placeholder: Csatornaazonosító - Display Titles Without Excessive Capitalisation: Címek megjelenítése túlzott nagybetűk - nélkül + Display Titles Without Excessive Capitalisation: Jelenítse meg a címeket túlzott + nagybetűs írás és írásjelek nélkül Hide Featured Channels: Kiemelt csatornák elrejtése Hide Channel Playlists: Csatorna lejátszási listák elrejtése Hide Channel Community: Csatornaközösség elrejtése diff --git a/static/locales/it.yaml b/static/locales/it.yaml index 39ad919c263a2..954368901860f 100644 --- a/static/locales/it.yaml +++ b/static/locales/it.yaml @@ -287,6 +287,7 @@ Settings: Catppuccin Mocha: Cappuccino moka Pastel Pink: Rosa pastello Hot Pink: Rosa caldo + Nordic: Nordico Main Color Theme: Main Color Theme: 'Colore principale del tema' Red: 'Rosso' @@ -536,8 +537,8 @@ Settings: Hide Upcoming Premieres: Nascondi le prossime Première Hide Channels: Nascondi i video dai canali Hide Channels Placeholder: ID del canale - Display Titles Without Excessive Capitalisation: Visualizza i titoli senza un - uso eccessivo di maiuscole + Display Titles Without Excessive Capitalisation: Visualizza i titoli senza maiuscole + e punteggiatura eccessive Hide Featured Channels: Nascondi i canali in evidenza Hide Channel Playlists: Nascondi le playlist del canale Hide Channel Community: Nascondi la comunità del canale diff --git a/static/locales/nl.yaml b/static/locales/nl.yaml index 6f6d323369fb7..007e4053061f0 100644 --- a/static/locales/nl.yaml +++ b/static/locales/nl.yaml @@ -135,12 +135,35 @@ User Playlists: LatestCreatedFirst: On­langs aan­gemaakt NameDescending: Z - A NameAscending: A - Z + EarliestPlayedFirst: Eerst gespeeld + EarliestCreatedFirst: Eerst aangemaakt + LatestUpdatedFirst: Laatst bijgewerkt + EarliestUpdatedFirst: Eerst bijgewerkt + LatestPlayedFirst: Meest recent afgespeeld CreatePlaylistPrompt: Create: Aanmaken + New Playlist Name: Naam voor nieuwe afspeel­lijst AddVideoPrompt: Save: Opslaan + N playlists selected: '{playlistCount} geselecteerd' + Search in Playlists: Zoeken in afspeel­lijsten Save Changes: Wijzigingen opslaan Copy Playlist: Afspeel­lijst kopiëren + Create New Playlist: Nieuwe afspeel­lijst aanmaken + Add to Playlist: Toevoegen aan afspeel­lijst + Move Video Up: Video omhoog verplaatsen + Move Video Down: Video omlaag verplaatsen + Remove from Playlist: Verwijderen uit afspeellijst + Edit Playlist Info: Afspeel­lijst­info bewerken + Remove Watched Videos: Bekeken video's verwijderen + Add to Favorites: Toevoegen aan {playlistName} + Remove from Favorites: Verwijderen uit {playlistName} + Disable Quick Bookmark: Snelle bladwijzers uitschakelen + SinglePlaylistView: + Toast: + Video has been removed: Video is verwijderd + Quick bookmark disabled: Snelle bladwijzers uitgeschakeld + Playlist has been updated.: De afspeel­lijst is bijgewerkt. History: # On History Page History: 'Geschiedenis' @@ -209,6 +232,7 @@ Settings: Catppuccin Mocha: Catppuccin-mokka Pastel Pink: Pastel­roze Hot Pink: Heet-roze + Nordic: Noords Main Color Theme: Main Color Theme: 'Primaire themakleur' Red: 'Rood' @@ -333,6 +357,7 @@ Settings: verwijderen Save Watched Videos With Last Viewed Playlist: Houd bekeken video's bij met de afspeellijst ‘Laatst bekeken’ + Remove All Playlists: Alle afspeel­lijsten verwijderen Subscription Settings: Subscription Settings: 'Abonnement­instellingen' Hide Videos on Watch: 'Bekeken video''s verbergen' @@ -501,6 +526,7 @@ Settings: Players: None: Name: Geen + Ignore Default Arguments: Standaard­argumenten negeren Download Settings: Choose Path: Pad kiezen Download Settings: Downloadinstellingen @@ -529,6 +555,7 @@ Settings: Password Incorrect: Wachtwoord onjuist Unlock: Ontgrendelen Enter Password To Unlock: Voer wachtwoord in om instellingen te ontgrendelen + Expand All Settings Sections: Alle instellingen­secties uitvouwen About: #On About page About: 'Over' @@ -937,6 +964,10 @@ Profile: Profile Settings: Profielinstellingen Toggle Profile List: Profiellijst omschakelen Profile Name: Profiel­naam + Edit Profile Name: Profiel­naam wijzigen + Create Profile Name: Profiel­naam aanmaken + Close Profile Dropdown: Profiel­menu sluiten + Open Profile Dropdown: Profiel­menu openen A new blog is now available, {blogTitle}. Click to view more: Een nieuwe blogpost is beschikbaar, {blogTitle}. Klik voor meer informatie Download From Site: Van website downloaden @@ -1085,4 +1116,4 @@ Playlist will pause when current video is finished: Afspeellijst zal pauzeren wa de huidige video is afgelopen Playlist will not pause when current video is finished: Afspeellijst zal niet pauzeren wanneer de huidige video is afgelopen -Go to page: Naar pagina {page} +Go to page: Ga naar {page} diff --git a/static/locales/nn.yaml b/static/locales/nn.yaml index 096db71c1912c..f91adbfac311b 100644 --- a/static/locales/nn.yaml +++ b/static/locales/nn.yaml @@ -770,9 +770,9 @@ Tooltips: Invidious Instance: 'Invidious-førekomsten som FreeTube vil kople til for API-kall.' Region for Trending: 'Trendsregionen lar deg enkelt velje kva lands populære videoar du ynskjer å vise.' - External Link Handling: "Vel kva FreeTube skal gjer, når ein trykker på ei lenke,\ - \ som ikkje kan bli opna av FreeTube. \nFreeTube vil vanlegvis opne lenka i\ - \ din standardnettlesar.\n" + External Link Handling: "Vel kva FreeTube skal gjer, når ein trykker på ei lenke, + som ikkje kan bli opna av FreeTube. \nFreeTube vil vanlegvis opne lenka i din + standardnettlesar.\n" Player Settings: Force Local Backend for Legacy Formats: 'Fungerer berre med Invidious-API-et som standard. Når det er påslått, vil det lokale API-et køyre og bruke dei utdaterte diff --git a/static/locales/pl.yaml b/static/locales/pl.yaml index d07c3209a655b..78fe2c4dd64a0 100644 --- a/static/locales/pl.yaml +++ b/static/locales/pl.yaml @@ -284,6 +284,7 @@ Settings: Catppuccin Mocha: Catppuccin Mocha Hot Pink: Gorący róż Pastel Pink: Pastelowy róż + Nordic: Nordycki Main Color Theme: Main Color Theme: 'Główny kolor motywu' Red: 'Czerwony' @@ -533,8 +534,8 @@ Settings: Hide Upcoming Premieres: Schowaj nadchodzące premiery Hide Channels: Schowaj filmy z kanałów Hide Channels Placeholder: ID kanału - Display Titles Without Excessive Capitalisation: Wyświetlaj tytuły bez nadmiernych - wielkich liter + Display Titles Without Excessive Capitalisation: Wyświetlaj tytuły nie nadużywając + wielkich liter i interpunkcji Hide Channel Community: Schowaj społeczność kanału Hide Channel Shorts: Schowaj filmy Short kanału Hide Featured Channels: Schowaj polecane kanały diff --git a/static/locales/pt-BR.yaml b/static/locales/pt-BR.yaml index a4ad27157ffb0..0ecae5542d897 100644 --- a/static/locales/pt-BR.yaml +++ b/static/locales/pt-BR.yaml @@ -279,6 +279,7 @@ Settings: Catppuccin Mocha: Catppuccin Mocha Pastel Pink: Rosa Pastel Hot Pink: Rosa Choque + Nordic: Nordico Main Color Theme: Main Color Theme: 'Cor principal' Red: 'Vermelha' @@ -530,7 +531,7 @@ Settings: Hide Upcoming Premieres: Ocultar as Próximas Estréias Hide Channels Placeholder: ID do Canal Display Titles Without Excessive Capitalisation: Mostrar Títulos sem Capitalização - Excessiva + Excessiva nem Pontuação Hide Channels: Ocultar Vídeos dos Canais Sections: Side Bar: Barra lateral @@ -584,8 +585,8 @@ Settings: são pulados 'SponsorBlock API Url (Default is https://sponsor.ajay.app)': URL da API SponsorBlock (o padrão é https://sponsor.ajay.app) - Enable SponsorBlock: Ativar o Bloqueio de Patrocinadores - SponsorBlock Settings: Configurações de Bloqueio de Patrocinadores + Enable SponsorBlock: Ativar o SponsorBlock + SponsorBlock Settings: Configurações das APIs de Ajay (SponsorBlock & DeArrow) Skip Options: Show In Seek Bar: Mostrar na barra de busca Prompt To Skip: Solicitar para pular @@ -804,8 +805,8 @@ Video: Hours: 'horas' Day: 'dia' Days: 'dias' - Week: 'semana' - Weeks: 'semanas' + Week: 'Semana' + Weeks: 'Semanas' Month: 'mês' Months: 'meses' Year: 'ano' @@ -853,7 +854,7 @@ Video: outro: Conclusão intro: Introdução sponsor: Patrocinador - filler: Enchimento + filler: Preenchimento recap: Recapitulação Skipped segment: Segmentos pulados External Player: diff --git a/static/locales/pt.yaml b/static/locales/pt.yaml index a2004dfa1e31e..11ef36b06b338 100644 --- a/static/locales/pt.yaml +++ b/static/locales/pt.yaml @@ -43,6 +43,8 @@ Global: Subscriber Count: 1 assinante | {count} assinantes View Count: 1 visualização | {contagem} visualizações Watching Count: 1 a assistir | {count} a assistir + Input Tags: + Length Requirement: A etiqueta tem que ter, pelo menos, {number} caracteres Version {versionNumber} is now available! Click for more details: 'A versão {versionNumber} está disponível! Clique aqui para mais informações.' Download From Site: 'Descarregar do site' @@ -175,6 +177,9 @@ User Playlists: Playlist {playlistName} has been deleted.: A lista de reprodução {playlistName} foi eliminada. This playlist does not exist: Esta lista de reprodução não existe + This playlist is now used for quick bookmark: Esta lista de reprodução é agora + usada como marcador rápido + Quick bookmark disabled: Marcador rápido desativado AddVideoPrompt: Search in Playlists: Pesquisar nas listas de reprodução Save: Guardar @@ -212,6 +217,9 @@ User Playlists: Playlist Description: Descrição da lista de reprodução Add to Favorites: Adicionar a {playlistName} Remove from Favorites: Remover de {playlistName} + Enable Quick Bookmark With This Playlist: Ativar marcador rápido para esta lista + de reprodução + Disable Quick Bookmark: Desativar marcador rápido History: # On History Page History: 'Histórico' @@ -279,6 +287,7 @@ Settings: Catppuccin Mocha: Cappuccino mocha Pastel Pink: Rosa pastel Hot Pink: Rosa choque + Nordic: Nórdico Main Color Theme: Main Color Theme: 'Cor principal' Red: 'Vermelho' @@ -516,6 +525,8 @@ Settings: Category Color: Cor da categoria UseDeArrowTitles: Utilizar títulos de vídeo DeArrow UseDeArrowThumbnails: Usar 'DeArrow' para miniaturas + 'DeArrow Thumbnail Generator API Url (Default is https://dearrow-thumb.ajay.app)': 'URL + da API do gerador de miniaturas DeArrow (padrão: https://dearrow-thumb.ajay.app)' Proxy Settings: Error getting network information. Is your proxy configured properly?: Erro ao obter informações da rede. O seu proxy está configurado corretamente? @@ -579,6 +590,10 @@ Settings: Hide Channels Already Exists: Este ID já existe Hide Channels API Error: Não foi possível obter o utilizador através do ID. Verifique se o ID indicado está correto. + Hide Videos and Playlists Containing Text Placeholder: Palavra, fragmento de palavra + ou frase + Hide Videos and Playlists Containing Text: Ocultar vídeos e listas de reprodução + que contenham textos External Player Settings: Custom External Player Arguments: Argumentos do reprodutor externo Custom External Player Executable: Executável do reprodutor externo @@ -779,6 +794,7 @@ Channel: Hide Answers: Ocultar respostas Reveal Answers: Revelar respostas votes: '{votes} votos' + Video hidden by FreeTube: Freetube ocultou este vídeo Live: Live: Em direto This channel does not currently have any live streams: Este canal não tem, atualmente, @@ -1126,6 +1142,7 @@ Tooltips: SponsorBlock Settings: UseDeArrowTitles: Substituir títulos de vídeo por títulos enviados pelo utilizador a partir do DeArrow. + UseDeArrowThumbnails: Substituir miniaturas do vídeo por miniaturas DeArrow. Search Bar: Clear Input: Limpar entrada Are you sure you want to open this link?: Tem a certeza de que deseja abrir a ligação? @@ -1176,3 +1193,4 @@ Playlist will not pause when current video is finished: A lista de reprodução Channel Hidden: '{channel} adicionado ao filtro do canal' Go to page: Ir para {page} Channel Unhidden: '{channel} removido do filtro do canal' +Tag already exists: '"{tagName}" já existe' diff --git a/static/locales/ru.yaml b/static/locales/ru.yaml index f980c8eb2df98..1bc035777082e 100644 --- a/static/locales/ru.yaml +++ b/static/locales/ru.yaml @@ -1089,9 +1089,9 @@ Tooltips: позволяющий открыть видео (подборку, если поддерживается) во внешнем проигрывателе. Внимание, настройки Invidious не применяются ко внешним проигрывателям. DefaultCustomArgumentsTemplate: "(По умолчанию: '{defaultCustomArguments}')" - Ignore Default Arguments: Не отправлять какие-либо умолчательные аргументы во - внешний проигрыватель кроме адреса видео (например, частота проигрывания, адрес - подборки и подобное). Пользовательские аргументы всё ещё будут передаваться. + Ignore Default Arguments: 'Не передавать никаких аргументов внешнему проигрывателю + по умолчанию, кроме адреса видео (напр.: частота проигрывания, адрес списка + воспроизведения и т. д.). Пользовательские аргументы всё ещё будут передаваться.' Experimental Settings: Replace HTTP Cache: Отключает дисковый HTTP-кэш Electron и включает пользовательский кэш изображений в памяти. Приведёт к увеличению использования оперативной памяти. diff --git a/static/locales/sr.yaml b/static/locales/sr.yaml index c948239758631..8e52ad4289b26 100644 --- a/static/locales/sr.yaml +++ b/static/locales/sr.yaml @@ -296,6 +296,7 @@ Settings: Hot Pink: Врућа розе Catppuccin Mocha: Catppuccin Mocha System Default: Системски подразумевано + Nordic: Нордичка Main Color Theme: Main Color Theme: 'Главна тема боја' Red: 'Црвена' diff --git a/static/locales/ti.yaml b/static/locales/ti.yaml index c6f189c432bf0..4de64898df59f 100644 --- a/static/locales/ti.yaml +++ b/static/locales/ti.yaml @@ -1,5 +1,5 @@ # Put the name of your locale in the same language -Locale Name: 'እንግሊዘኛ (us)' +Locale Name: 'ትግርኛ' FreeTube: 'FreeTube' # Currently on Subscriptions, Playlists, and History 'This part of the app is not ready yet. Come back later when progress has been made.': >- diff --git a/static/locales/tr.yaml b/static/locales/tr.yaml index 3be02d386ded2..5a8ac1a615fa2 100644 --- a/static/locales/tr.yaml +++ b/static/locales/tr.yaml @@ -288,6 +288,7 @@ Settings: Catppuccin Mocha: Catppuccin Mocha Pastel Pink: Pastel Pembe Hot Pink: Sıcak Pembe + Nordic: Nord Main Color Theme: Main Color Theme: 'Ana Renk Teması' Red: 'Kırmızı' @@ -531,8 +532,8 @@ Settings: Hide Upcoming Premieres: Yaklaşan İlk Gösterimleri Gizle Hide Channels Placeholder: Kanal Kimliği Hide Channels: Kanallardan Videoları Gizle - Display Titles Without Excessive Capitalisation: Başlıkları Aşırı Büyük Harf Kullanmadan - Görüntüle + Display Titles Without Excessive Capitalisation: Başlıkları Aşırı Büyük Harf ve + Noktalama İşaretleri Kullanmadan Görüntüle Hide Featured Channels: Öne Çıkan Kanalları Gizle Hide Channel Playlists: Kanal Oynatma Listelerini Gizle Hide Channel Community: Kanal Topluluğunu Gizle diff --git a/static/locales/zh-CN.yaml b/static/locales/zh-CN.yaml index 9d0a0632c375d..ec1238f31957d 100644 --- a/static/locales/zh-CN.yaml +++ b/static/locales/zh-CN.yaml @@ -249,6 +249,7 @@ Settings: Catppuccin Mocha: Catppuccin Mocha Pastel Pink: Pastel Pink Hot Pink: Hot Pink + Nordic: Nordic Main Color Theme: Main Color Theme: '主题色' Red: '红' @@ -468,7 +469,7 @@ Settings: Hide Upcoming Premieres: 隐藏即将到来的首映 Hide Channels: 隐藏频道中的视频 Hide Channels Placeholder: 频道ID - Display Titles Without Excessive Capitalisation: 不用过度大写字母的方式显示标题名称 + Display Titles Without Excessive Capitalisation: 去除标题中对字母大写和标点符号的过度使用 Hide Featured Channels: 隐藏精选频道 Hide Channel Playlists: 隐藏频道播放列表 Hide Channel Community: 隐藏频道社区 diff --git a/static/locales/zh-TW.yaml b/static/locales/zh-TW.yaml index 30b4ae5642182..680a1565adcc4 100644 --- a/static/locales/zh-TW.yaml +++ b/static/locales/zh-TW.yaml @@ -250,6 +250,7 @@ Settings: Catppuccin Mocha: 卡布奇諾摩卡 Pastel Pink: 淡粉紅色 Hot Pink: 亮粉紅色 + Nordic: 北歐 Main Color Theme: Main Color Theme: '主題色' Red: '紅' @@ -469,7 +470,7 @@ Settings: Hide Upcoming Premieres: 隱藏即將到來的首映 Hide Channels Placeholder: 頻道 ID Hide Channels: 隱藏頻道中的影片 - Display Titles Without Excessive Capitalisation: 顯示沒有過多大寫的標題 + Display Titles Without Excessive Capitalisation: 顯示沒有過多大寫與標點符號的標題 Hide Featured Channels: 隱藏精選頻道 Hide Channel Playlists: 隱藏頻道播放清單 Hide Channel Community: 隱藏頻道社群 diff --git a/yarn.lock b/yarn.lock index a7b93dd187220..9d2c7c99132d9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -54,10 +54,10 @@ json5 "^2.2.3" semver "^6.3.1" -"@babel/eslint-parser@^7.23.9": - version "7.23.9" - resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.23.9.tgz#052c13b39144e21fdd1e03fc9b67e98976a1ebfc" - integrity sha512-xPndlO7qxiJbn0ATvfXQBjCS7qApc9xmKHArgI/FTEFxXas5dnjC/VqM37lfZun9dclRYcn+YQAr6uDFy0bB2g== +"@babel/eslint-parser@^7.23.10": + version "7.23.10" + resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.23.10.tgz#2d4164842d6db798873b40e0c4238827084667a2" + integrity sha512-3wSYDPZVnhseRnxRJH6ZVTNknBz76AEnyC+AYYhasjP3Yy23qz0ERR7Fcd2SHmYuSFJ2kY9gaaDd3vyqU09eSw== dependencies: "@nicolo-ribaudo/eslint-scope-5-internals" "5.1.1-v1" eslint-visitor-keys "^2.1.0" @@ -1113,10 +1113,10 @@ resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== -"@double-great/stylelint-a11y@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@double-great/stylelint-a11y/-/stylelint-a11y-3.0.0.tgz#da9eb5558f065a6488fe48f054fec64e4aae8aa1" - integrity sha512-MdBk83+r4R7AhycEGi4uueUh6rFJYIZzRrkt4Dtqc0lzNTQ101/1n54qES0SMMty/pqBYykPt/B4xdZO+wibeg== +"@double-great/stylelint-a11y@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@double-great/stylelint-a11y/-/stylelint-a11y-3.0.1.tgz#37a974be01924acf6522523cbf2d13aeb207eeb3" + integrity sha512-0wRzfuDrXnSFvZGrAizngaJBhwCgZwjAVp2Vm4zPLekKW4eXccvB7HBEkhAeVSIuGCg3ki2h7eSHEoqZNfVOew== dependencies: postcss "^8.4.32" @@ -2908,10 +2908,10 @@ css-functions-list@^3.2.1: resolved "https://registry.yarnpkg.com/css-functions-list/-/css-functions-list-3.2.1.tgz#2eb205d8ce9f9ce74c5c1d7490b66b77c45ce3ea" integrity sha512-Nj5YcaGgBtuUmn1D7oHqPW0c9iui7xsTsj5lIX8ZgevdfhmjFfKB3r8moHJtNJnctnYXJyYX5I1pp90HM4TPgQ== -css-loader@^6.9.1: - version "6.9.1" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.9.1.tgz#9ec9a434368f2bdfeffbf8f6901a1ce773586c6b" - integrity sha512-OzABOh0+26JKFdMzlK6PY1u5Zx8+Ck7CVRlcGNZoY9qwJjdfu2VWFuprTIpPW+Av5TZTVViYWcFQaEEQURLknQ== +css-loader@^6.10.0: + version "6.10.0" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.10.0.tgz#7c172b270ec7b833951b52c348861206b184a4b7" + integrity sha512-LTSA/jWbwdMlk+rhmElbDR2vbtQoTBPr7fkJE+mxrHj+7ru0hUmHafDRzWIjIHTwpitWVaqY2/UWGRca3yUgRw== dependencies: icss-utils "^5.1.0" postcss "^8.4.33" @@ -3414,10 +3414,10 @@ electron-to-chromium@^1.4.648: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.648.tgz#c7b46c9010752c37bb4322739d6d2dd82354fbe4" integrity sha512-EmFMarXeqJp9cUKu/QEciEApn0S/xRcpZWuAm32U7NgoZCimjsilKXHRO9saeEW55eHZagIDg6XTUOv32w9pjg== -electron@^28.2.0: - version "28.2.0" - resolved "https://registry.yarnpkg.com/electron/-/electron-28.2.0.tgz#ecf7097d4a1e47dd08111c0229a9d03c44f485ad" - integrity sha512-22SylXQQ9IHtwLw4D+Z4Si7OUpeDtpHfJVTjy3yv53iLg5zJKKPOCWT4ZwgYGHQZ0eldyBrYBHF/P9FPd2CcVQ== +electron@^28.2.2: + version "28.2.2" + resolved "https://registry.yarnpkg.com/electron/-/electron-28.2.2.tgz#d5aa4a33c00927d83ca893f8726f7c62aad98c41" + integrity sha512-8UcvIGFcjplHdjPFNAHVFg5bS0atDyT3Zx21WwuE4iLfxcAMsyMEOgrQX3im5LibA8srwsUZs7Cx0JAUfcQRpw== dependencies: "@electron/get" "^2.0.0" "@types/node" "^18.11.18" @@ -3772,10 +3772,10 @@ eslint-plugin-promise@^6.1.1: resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz#269a3e2772f62875661220631bd4dafcb4083816" integrity sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig== -eslint-plugin-unicorn@^50.0.1: - version "50.0.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-unicorn/-/eslint-plugin-unicorn-50.0.1.tgz#e539cdb02dfd893c603536264c4ed9505b70e3bf" - integrity sha512-KxenCZxqSYW0GWHH18okDlOQcpezcitm5aOSz6EnobyJ6BIByiPDviQRjJIUAjG/tMN11958MxaQ+qCoU6lfDA== +eslint-plugin-unicorn@^51.0.1: + version "51.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-unicorn/-/eslint-plugin-unicorn-51.0.1.tgz#3641c5e110324c3739d6cb98fc1b99ada39f477b" + integrity sha512-MuR/+9VuB0fydoI0nIn2RDA5WISRn4AsJyNSaNKLVwie9/ONvQhxOBbkfSICBPnzKrB77Fh6CZZXjgTt/4Latw== dependencies: "@babel/helper-validator-identifier" "^7.22.20" "@eslint-community/eslint-utils" "^4.4.0" @@ -3794,17 +3794,17 @@ eslint-plugin-unicorn@^50.0.1: semver "^7.5.4" strip-indent "^3.0.0" -eslint-plugin-vue@^9.20.1: - version "9.20.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-9.20.1.tgz#7ed78846898574b2cd26939f28b0b87798a7b528" - integrity sha512-GyCs8K3lkEvoyC1VV97GJhP1SvqsKCiWGHnbn0gVUYiUhaH2+nB+Dv1uekv1THFMPbBfYxukrzQdltw950k+LQ== +eslint-plugin-vue@^9.21.1: + version "9.21.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-9.21.1.tgz#da5629efa48527cec98278dca0daa90fada4caf7" + integrity sha512-XVtI7z39yOVBFJyi8Ljbn7kY9yHzznKXL02qQYn+ta63Iy4A9JFBw6o4OSB9hyD2++tVT+su9kQqetUyCCwhjw== dependencies: "@eslint-community/eslint-utils" "^4.4.0" natural-compare "^1.4.0" nth-check "^2.1.1" postcss-selector-parser "^6.0.13" semver "^7.5.4" - vue-eslint-parser "^9.4.0" + vue-eslint-parser "^9.4.2" xml-name-validator "^4.0.0" eslint-plugin-vuejs-accessibility@^2.2.1: @@ -5852,12 +5852,13 @@ min-indent@^1.0.0: resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== -mini-css-extract-plugin@^2.7.7: - version "2.7.7" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.7.tgz#4acf02f362c641c38fb913bfcb7ca2fc4a7cf339" - integrity sha512-+0n11YGyRavUR3IlaOzJ0/4Il1avMvJ1VJfhWfCn24ITQXhRr1gghbhhrda6tgtNcpZaWKdSuwKq20Jb7fnlyw== +mini-css-extract-plugin@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.8.0.tgz#1aeae2a90a954b6426c9e8311eab36b450f553a0" + integrity sha512-CxmUYPFcTgET1zImteG/LZOy/4T5rTojesQXkSNBiquhydn78tfbCE9sjIjnJ/UcjNjOC1bphTCCW5rrS7cXAg== dependencies: schema-utils "^4.0.0" + tapable "^2.2.1" minimalistic-assert@^1.0.0: version "1.0.1" @@ -6739,10 +6740,10 @@ postcss@^7.0.36: picocolors "^0.2.1" source-map "^0.6.1" -postcss@^8.4.14, postcss@^8.4.32, postcss@^8.4.33: - version "8.4.33" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.33.tgz#1378e859c9f69bf6f638b990a0212f43e2aaa742" - integrity sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg== +postcss@^8.4.14, postcss@^8.4.32, postcss@^8.4.33, postcss@^8.4.35: + version "8.4.35" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.35.tgz#60997775689ce09011edf083a549cea44aabe2f7" + integrity sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA== dependencies: nanoid "^3.3.7" picocolors "^1.0.0" @@ -7268,10 +7269,10 @@ sanitize-filename@^1.6.3: dependencies: truncate-utf8-bytes "^1.0.0" -sass-loader@^14.0.0: - version "14.0.0" - resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-14.0.0.tgz#fc8390f7cc16863622cd16f3ea07b36ba6ea8f91" - integrity sha512-oceP9wWbep/yRJ2+sMbCzk0UsXsDzdNis+N8nu9i5GwPXjy6v3DNB6TqfJLSpPO9k4+B8x8p/CEgjA9ZLkoLug== +sass-loader@^14.1.0: + version "14.1.0" + resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-14.1.0.tgz#43ba90e0cd8a15a1e932e818c525b0115a0ce8a3" + integrity sha512-LS2mLeFWA+orYxHNu+O18Xe4jR0kyamNOOUsE3NyBP4DvIL+8stHpNX0arYTItdPe80kluIiJ7Wfe/9iHSRO0Q== dependencies: neo-async "^2.6.2" @@ -7830,10 +7831,10 @@ stylelint-use-logical-spec@^5.0.1: resolved "https://registry.yarnpkg.com/stylelint-use-logical-spec/-/stylelint-use-logical-spec-5.0.1.tgz#d5aa254d615d373f18214297c0b49a03a6ca5980" integrity sha512-UfLB4LW6iG4r3cXxjxkiHQrFyhWFqt8FpNNngD+TyvgMWSokk5TYwTvBHS3atUvZhOogllTOe/PUrGE+4z84AA== -stylelint@^16.2.0: - version "16.2.0" - resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-16.2.0.tgz#60678f64d7660350fdd06415fd449f332b4fcbf6" - integrity sha512-gwqU5AkIb52wrAzzn+359S3NIJDMl02TXLUaV2tzA/L6jUdpTwNt+MCxHlc8+Hb2bUHlYVo92YeSIryF2gJthA== +stylelint@^16.2.1: + version "16.2.1" + resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-16.2.1.tgz#895d6d42523c5126ec0895f0ca2a58febeb77e89" + integrity sha512-SfIMGFK+4n7XVAyv50CpVfcGYWG4v41y6xG7PqOgQSY8M/PgdK0SQbjWFblxjJZlN9jNq879mB4BCZHJRIJ1hA== dependencies: "@csstools/css-parser-algorithms" "^2.5.0" "@csstools/css-tokenizer" "^2.2.3" @@ -7933,10 +7934,10 @@ svgo@^3.2.0: csso "^5.0.5" picocolors "^1.0.0" -swiper@^11.0.5: - version "11.0.5" - resolved "https://registry.yarnpkg.com/swiper/-/swiper-11.0.5.tgz#6ed1ad06e6906ba42fd4b93d4988f0626a49046e" - integrity sha512-rhCwupqSyRnWrtNzWzemnBLMoyYuoDgGgspAm/8iBD3jCvAWycPLH4Z3TB0O5520DHLzMx94yUMH/B9Efpa48w== +swiper@^11.0.6: + version "11.0.6" + resolved "https://registry.yarnpkg.com/swiper/-/swiper-11.0.6.tgz#787187e2711b01301b4c67b86b8e03099e2fc9f2" + integrity sha512-W/Me7MQl5rNgdM5x9i3Gll76WsyVpnHn91GhBOyL7RCFUeg62aVnflzlVfIpXzZ/87FtJOfAoDH79ZH2Yq76zA== synckit@^0.6.0: version "0.6.2" @@ -7964,7 +7965,7 @@ table@^6.8.1: string-width "^4.2.3" strip-ansi "^6.0.1" -tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0: +tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0, tapable@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== @@ -8459,7 +8460,7 @@ vue-devtools@^5.1.4: resolved "https://registry.yarnpkg.com/vue-devtools/-/vue-devtools-5.1.4.tgz#265a7458ade2affb291739176964256b597fa302" integrity sha512-EBAEXvAHUinsPzoSiElps0JgtLXUnJXKIJbP6nfdz/R63VdKBMfJ34/rFip+4iT7iMbVS5lA4W6N1jq4Hj4LCg== -vue-eslint-parser@^9.0.1, vue-eslint-parser@^9.4.0, vue-eslint-parser@^9.4.2: +vue-eslint-parser@^9.0.1, vue-eslint-parser@^9.4.2: version "9.4.2" resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-9.4.2.tgz#02ffcce82042b082292f2d1672514615f0d95b6d" integrity sha512-Ry9oiGmCAK91HrKMtCrKFWmSFWvYkpGglCeFAIqDdr9zdXmMMpJOmUJS7WWsW7fX81h6mwHmUZCQQ1E0PkSwYQ== @@ -8631,10 +8632,10 @@ webpack-watch-external-files-plugin@^3.0.0: glob "10.3.10" path "0.12.7" -webpack@^5.90.0: - version "5.90.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.90.0.tgz#313bfe16080d8b2fee6e29b6c986c0714ad4290e" - integrity sha512-bdmyXRCXeeNIePv6R6tGPyy20aUobw4Zy8r0LUS2EWO+U+Ke/gYDgsCh7bl5rB6jPpr4r0SZa6dPxBxLooDT3w== +webpack@^5.90.1: + version "5.90.1" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.90.1.tgz#62ab0c097d7cbe83d32523dbfbb645cdb7c3c01c" + integrity sha512-SstPdlAC5IvgFnhiRok8hqJo/+ArAbNv7rhU4fnWGHNVfN59HSQFaxZDSAL3IFG2YmqxuRs+IU33milSxbPlog== dependencies: "@types/eslint-scope" "^3.7.3" "@types/estree" "^1.0.5" @@ -8849,10 +8850,10 @@ yocto-queue@^1.0.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.0.0.tgz#7f816433fb2cbc511ec8bf7d263c3b58a1a3c251" integrity sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g== -youtubei.js@^8.2.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/youtubei.js/-/youtubei.js-8.2.0.tgz#5b173f41fbe6240bb44cb733ce2c1f24e0b072ca" - integrity sha512-i/F4PEURSQmSYCQCo4dWKxOCZXhqkgAuGzNG2RUCtGSmlMX8TvwNewVD/JBjH/czdNmh9SJ00onNZMMxHbt+YA== +youtubei.js@^9.0.2: + version "9.0.2" + resolved "https://registry.yarnpkg.com/youtubei.js/-/youtubei.js-9.0.2.tgz#77592a1144cdd51bb4258472265f5031b3966162" + integrity sha512-D7GoJmupYaJxTNQyHRWYw8MUdQTxRaa3c7nzM9etWQjaexepFGVlVtwl3CybLx7GopBNtBvr7RxSUUIUyNnYIg== dependencies: jintr "^1.1.0" tslib "^2.5.0"