Skip to content

Commit

Permalink
Merge branch 'development' into feature/history/remember-search-query
Browse files Browse the repository at this point in the history
* development: (35 commits)
  Translated using Weblate (Hungarian)
  Translated using Weblate (French)
  Translated using Weblate (Chinese (Simplified Han script))
  Translated using Weblate (Serbian)
  Translated using Weblate (Italian)
  Translated using Weblate (English (United Kingdom))
  Translated using Weblate (French)
  Translated using Weblate (Czech)
  Translated using Weblate (Bulgarian)
  Translated using Weblate (Italian)
  Translated using Weblate (Turkish)
  Translated using Weblate (German)
  Translated using Weblate (Spanish)
  Add Playlist Sort By Video Duration (FreeTubeApp#5627)
  Translated using Weblate (Estonian)
  Translated using Weblate (Italian)
  Translated using Weblate (French)
  Translated using Weblate (Chinese (Simplified Han script))
  Translated using Weblate (Serbian)
  Translated using Weblate (Serbian)
  ...
  • Loading branch information
PikachuEXE committed Oct 12, 2024
2 parents 707f950 + bc80ec2 commit 1be051e
Show file tree
Hide file tree
Showing 31 changed files with 412 additions and 87 deletions.
2 changes: 2 additions & 0 deletions _scripts/ProcessLocalesPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ class ProcessLocalesPlugin {
}

for (let [locale, data] of this.locales) {
// eslint-disable-next-line no-async-promise-executor
promises.push(new Promise(async (resolve) => {
if (IS_DEV_SERVER && compiler.fileTimestamps) {
const filePath = join(this.inputDir, `${locale}.yaml`)
Expand Down Expand Up @@ -131,6 +132,7 @@ class ProcessLocalesPlugin {
})

compiler.hooks.afterCompile.tap(PLUGIN_NAME, (compilation) => {
// eslint-disable-next-line no-extra-boolean-cast
if (!!compiler.watching) {
// watch locale files for changes
compilation.fileDependencies.addAll(this.filePaths)
Expand Down
2 changes: 1 addition & 1 deletion _scripts/getShakaLocales.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const { readFileSync, readdirSync } = require('fs')
function getPreloadedLocales() {
const localesFile = readFileSync(`${__dirname}/../node_modules/shaka-player/dist/locales.js`, 'utf-8')

const localesLine = localesFile.match(/^\/\/ LOCALES: ([\w, -]+)$/m)
const localesLine = localesFile.match(/^\/\/ LOCALES: ([\w ,-]+)$/m)

if (!localesLine) {
throw new Error("Failed to parse shaka-player's preloaded locales")
Expand Down
4 changes: 2 additions & 2 deletions _scripts/patchShaka.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ async function removeRobotoFont() {
let cssContents = readFileSync(cssFileHandle, 'utf-8')

const beforeReplacement = cssContents.length
cssContents = cssContents.replace(/@font-face\{font-family:Roboto;[^}]+\}/, '')
cssContents = cssContents.replace(/@font-face{font-family:Roboto;[^}]+}/, '')

if (cssContents.length !== beforeReplacement) {
ftruncateSync(cssFileHandle)
Expand Down Expand Up @@ -100,7 +100,7 @@ async function replaceAndDownloadMaterialIconsFont() {
let newFontCSS = text.match(/(@font-face\s*{[^}]+})/)[1].replaceAll('\n', '')


const urlMatch = newFontCSS.match(/https:\/\/fonts\.gstatic\.com\/s\/materialiconsround\/(?<version>[^\/]+)\/[^.]+\.(?<extension>[\w]+)/)
const urlMatch = newFontCSS.match(/https:\/\/fonts\.gstatic\.com\/s\/materialiconsround\/(?<version>[^/]+)\/[^.]+\.(?<extension>\w+)/)

const url = urlMatch[0]
const { version, extension } = urlMatch.groups
Expand Down
59 changes: 49 additions & 10 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ const compat = new FlatCompat({
})

export default [
{
ignores: [
'dist/',
'eslint.config.mjs'
]
},
...fixupConfigRules(
compat.config({
extends: ['standard']
Expand All @@ -37,9 +43,7 @@ export default [
'**/*.{js,vue}',
],
ignores: [
'**/node_modules',
'**/_scripts',
'**/dist',
'_scripts/',
],
plugins: {
unicorn: eslintPluginUnicorn,
Expand Down Expand Up @@ -125,9 +129,7 @@ export default [
{
files: ['**/*.json'],
ignores: [
'**/node_modules/**',
'**/_scripts/**',
'**/dist/**',
'_scripts/',
],

languageOptions: {
Expand All @@ -152,10 +154,8 @@ export default [
{
files: ['**/*.{yml,yaml}'],
ignores: [
'**/node_modules/**',
'**/_scripts/**',
'**/dist/**',
'**/.github/**',
'.github/',
'_scripts/'
],

languageOptions: {
Expand Down Expand Up @@ -192,4 +192,43 @@ export default [
},
},
},
{
files: ['_scripts/*.js'],
languageOptions: {
globals: {
...globals.node
},
ecmaVersion: 'latest',
},

plugins: {
unicorn: eslintPluginUnicorn,
},

rules: {
'no-console': 'off',
'n/no-path-concat': 'off',
'unicorn/better-regex': 'error',
}
},
{
files: ['_scripts/*.mjs'],
languageOptions: {
globals: {
...globals.node,
},
ecmaVersion: 'latest',
sourceType: 'module',
},

plugins: {
unicorn: eslintPluginUnicorn,
},

rules: {
'no-console': 'off',
'n/no-path-concat': 'off',
'unicorn/better-regex': 'error',
}
}
]
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@
"lint-all": "run-p lint lint-json",
"lint": "run-p eslint-lint lint-style",
"lint-fix": "run-p eslint-lint-fix lint-style-fix",
"eslint-lint": "eslint --config eslint.config.mjs \"./src/**/*.js\" \"./src/**/*.vue\" \"./static/**/*.js\"",
"eslint-lint-fix": "eslint --config eslint.config.mjs --fix \"./src/**/*.js\" \"./src/**/*.vue\" \"./static/**/*.js\"",
"eslint-lint": "eslint --config eslint.config.mjs \"./src/**/*.js\" \"./src/**/*.vue\" \"./static/**/*.js\" \"./_scripts/*.js\" \"./_scripts/*.mjs\"",
"eslint-lint-fix": "eslint --config eslint.config.mjs --fix \"./src/**/*.js\" \"./src/**/*.vue\" \"./static/**/*.js\" \"./_scripts/*.js\" \"./_scripts/*.mjs\"",
"lint-json": "eslint --config eslint.config.mjs \"./static/**/*.json\"",
"lint-style": "stylelint \"**/*.{css,scss}\"",
"lint-style-fix": "stylelint --fix \"**/*.{css,scss}\"",
Expand Down
90 changes: 53 additions & 37 deletions src/renderer/components/data-settings/data-settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -875,6 +875,7 @@ export default defineComponent({
// to the app, so we'll only grab the data we need here.

const playlistObject = {}
const videoIdToBeAddedSet = new Set()

Object.keys(playlistData).forEach((key) => {
if ([requiredKeys, optionalKeys, ignoredKeys].every((ks) => !ks.includes(key))) {
Expand All @@ -888,6 +889,7 @@ export default defineComponent({

if (videoObjectHasAllRequiredKeys) {
videoArray.push(video)
videoIdToBeAddedSet.add(video.videoId)
}
})

Expand All @@ -901,48 +903,62 @@ export default defineComponent({
const playlistObjectKeys = Object.keys(playlistObject)
const playlistObjectHasAllRequiredKeys = requiredKeys.every((k) => playlistObjectKeys.includes(k))

if (playlistObjectHasAllRequiredKeys) {
const existingPlaylist = this.allPlaylists.find((playlist) => {
return playlist.playlistName === playlistObject.playlistName
})
if (!playlistObjectHasAllRequiredKeys) {
const message = this.$t('Settings.Data Settings.Playlist insufficient data', { playlist: playlistData.playlistName })
showToast(message)
return
}

if (existingPlaylist !== undefined) {
playlistObject.videos.forEach((video) => {
let videoExists = false
if (video.playlistItemId != null) {
// Find by `playlistItemId` if present
videoExists = existingPlaylist.videos.some((x) => {
// Allow duplicate (by videoId) videos to be added
return x.videoId === video.videoId && x.playlistItemId === video.playlistItemId
})
} else {
// Older playlist exports have no `playlistItemId` but have `timeAdded`
// Which might be duplicate for copied playlists with duplicate `videoId`
videoExists = existingPlaylist.videos.some((x) => {
// Allow duplicate (by videoId) videos to be added
return x.videoId === video.videoId && x.timeAdded === video.timeAdded
})
}
const existingPlaylist = this.allPlaylists.find((playlist) => {
return playlist.playlistName === playlistObject.playlistName
})

if (!videoExists) {
// Keep original `timeAdded` value
const payload = {
_id: existingPlaylist._id,
videoData: video,
}
if (existingPlaylist === undefined) {
this.addPlaylist(playlistObject)
return
}

this.addVideo(payload)
}
})
// Update playlist's `lastUpdatedAt`
this.updatePlaylist({ _id: existingPlaylist._id })
const duplicateVideoPresentInToBeAdded = playlistObject.videos.length > videoIdToBeAddedSet.size
const existingVideoIdSet = existingPlaylist.videos.reduce((video) => videoIdToBeAddedSet.add(video.videoId), new Set())
const duplicateVideoPresentInExistingPlaylist = existingPlaylist.videos.length > existingVideoIdSet.size
const shouldAddDuplicateVideos = duplicateVideoPresentInToBeAdded || duplicateVideoPresentInExistingPlaylist

playlistObject.videos.forEach((video) => {
let videoExists = false
if (shouldAddDuplicateVideos) {
if (video.playlistItemId != null) {
// Find by `playlistItemId` if present
videoExists = existingPlaylist.videos.some((x) => {
// Allow duplicate (by videoId) videos to be added
return x.videoId === video.videoId && x.playlistItemId === video.playlistItemId
})
} else {
// Older playlist exports have no `playlistItemId` but have `timeAdded`
// Which might be duplicate for copied playlists with duplicate `videoId`
videoExists = existingPlaylist.videos.some((x) => {
// Allow duplicate (by videoId) videos to be added
return x.videoId === video.videoId && x.timeAdded === video.timeAdded
})
}
} else {
this.addPlaylist(playlistObject)
videoExists = existingPlaylist.videos.some((x) => {
// Disallow duplicate (by videoId) videos to be added
return x.videoId === video.videoId
})
}
} else {
const message = this.$t('Settings.Data Settings.Playlist insufficient data', { playlist: playlistData.playlistName })
showToast(message)
}

if (!videoExists) {
// Keep original `timeAdded` value
const payload = {
_id: existingPlaylist._id,
videoData: video,
}

this.addVideo(payload)
}
})
// Update playlist's `lastUpdatedAt`
this.updatePlaylist({ _id: existingPlaylist._id })
})

showToast(this.$t('Settings.Data Settings.All playlists has been successfully imported'))
Expand Down
10 changes: 10 additions & 0 deletions src/renderer/components/ft-list-video/ft-list-video.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,11 @@ export default defineComponent({
published: undefined,
isLive: false,
is4k: false,
is8k: false,
isNew: false,
isVr180: false,
isVr360: false,
is3D: false,
hasCaptions: false,
isUpcoming: false,
isPremium: false,
Expand Down Expand Up @@ -662,6 +667,11 @@ export default defineComponent({
this.isLive = this.data.liveNow || this.data.lengthSeconds === 'undefined'
this.isUpcoming = this.data.isUpcoming || this.data.premiere
this.is4k = this.data.is4k
this.is8k = this.data.is8k
this.isNew = this.data.isNew
this.isVr180 = this.data.isVr180
this.isVr360 = this.data.isVr360
this.is3D = this.data.is3d
this.hasCaptions = this.data.hasCaptions
this.isPremium = this.data.premium || false
this.viewCount = this.data.viewCount
Expand Down
42 changes: 41 additions & 1 deletion src/renderer/components/ft-list-video/ft-list-video.vue
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,17 @@
> • {{ $tc('Global.Counts.Watching Count', viewCount, {count: parsedViewCount}) }}</span>
</div>
<div
v-if="is4k || hasCaptions"
v-if="is4k || hasCaptions || is8k || isNew || isVr180 || isVr360 || is3D"
class="videoTagLine"
>
<div
v-if="isNew"
class="videoTag"
:aria-label="$t('Search Listing.Label.New')"
role="img"
>
{{ $t('Search Listing.Label.New') }}
</div>
<div
v-if="is4k"
class="videoTag"
Expand All @@ -157,6 +165,38 @@
>
{{ $t('Search Listing.Label.4K') }}
</div>
<div
v-if="is8k"
class="videoTag"
:aria-label="$t('Search Listing.Label.8K')"
role="img"
>
{{ $t('Search Listing.Label.8K') }}
</div>
<div
v-if="isVr180"
class="videoTag"
:aria-label="$t('Search Listing.Label.VR180')"
role="img"
>
{{ $t('Search Listing.Label.VR180') }}
</div>
<div
v-if="isVr360"
class="videoTag"
:aria-label="$t('Search Listing.Label.360 Video')"
role="img"
>
{{ $t('Search Listing.Label.360 Video') }}
</div>
<div
v-if="is3D"
class="videoTag"
:aria-label="$t('Search Listing.Label.3D')"
role="img"
>
{{ $t('Search Listing.Label.3D') }}
</div>
<div
v-if="hasCaptions"
class="videoTag"
Expand Down
25 changes: 24 additions & 1 deletion src/renderer/helpers/playlists.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ export const SORT_BY_VALUES = {
AuthorDescending: 'author_descending',
VideoTitleAscending: 'video_title_ascending',
VideoTitleDescending: 'video_title_descending',
VideoDurationAscending: 'video_duration_ascending',
VideoDurationDescending: 'video_duration_descending',
Custom: 'custom'
}

Expand All @@ -19,7 +21,9 @@ export function getSortedPlaylistItems(playlistItems, sortOrder, locale, reverse
sortOrder === SORT_BY_VALUES.VideoTitleAscending ||
sortOrder === SORT_BY_VALUES.VideoTitleDescending ||
sortOrder === SORT_BY_VALUES.AuthorAscending ||
sortOrder === SORT_BY_VALUES.AuthorDescending
sortOrder === SORT_BY_VALUES.AuthorDescending ||
sortOrder === SORT_BY_VALUES.VideoDurationAscending ||
sortOrder === SORT_BY_VALUES.VideoDurationDescending
) {
collator = new Intl.Collator([locale, 'en'])
}
Expand All @@ -31,6 +35,19 @@ export function getSortedPlaylistItems(playlistItems, sortOrder, locale, reverse
})
}

export function videoDurationPresent(video) {
if (typeof video.lengthSeconds !== 'number') { return false }

return !(isNaN(video.lengthSeconds) || video.lengthSeconds === 0)
}

export function videoDurationWithFallback(video) {
if (videoDurationPresent(video)) { return video.lengthSeconds }

// Fallback
return 0
}

function compareTwoPlaylistItems(a, b, sortOrder, collator) {
switch (sortOrder) {
case SORT_BY_VALUES.DateAddedNewest:
Expand All @@ -45,6 +62,12 @@ function compareTwoPlaylistItems(a, b, sortOrder, collator) {
return collator.compare(a.author, b.author)
case SORT_BY_VALUES.AuthorDescending:
return collator.compare(b.author, a.author)
case SORT_BY_VALUES.VideoDurationAscending: {
return videoDurationWithFallback(a) - videoDurationWithFallback(b)
}
case SORT_BY_VALUES.VideoDurationDescending: {
return videoDurationWithFallback(b) - videoDurationWithFallback(a)
}
default:
console.error(`Unknown sortOrder: ${sortOrder}`)
return 0
Expand Down
Loading

0 comments on commit 1be051e

Please sign in to comment.