Skip to content

Commit 52ef677

Browse files
committed
Merge branch 'development' into fix/auto-trailing-slash-removal
* development: Fix: Hide 'Minimize to system tray' setting on Wayland (FreeTubeApp#9208) Translated using Weblate (Hungarian) Fix: import history from youtube adding trailing space to title (FreeTubeApp#9204) Fix keyboard shortcuts arent't working during "SABR backoff" (FreeTubeApp#9315) Fix incomplete watch progresss bar if video length has milliseconds (FreeTubeApp#9267) Translated using Weblate (Hungarian) Fix default quality not working when video aspect ratio is not 16/9 or 9/16 (FreeTubeApp#9312) Remove error when 'publishedText' is missing as it is a valid state (FreeTubeApp#9321) Fix LibRedirect download link in README (FreeTubeApp#9323) Bump actions/cache/restore from 5.0.5 to 6.0.0 (FreeTubeApp#9329) Bump actions/cache/save from 5.0.5 to 6.0.0 (FreeTubeApp#9330) Translated using Weblate (French) Fix premierDate parsing in subscription (FreeTubeApp#9309) # Conflicts: # src/renderer/components/GeneralSettings/GeneralSettings.vue
2 parents 9afbb6e + 5ce9797 commit 52ef677

14 files changed

Lines changed: 199 additions & 157 deletions

File tree

.github/workflows/build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ jobs:
103103
104104
- name: Restore pnpm cache
105105
id: restore_cache
106-
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae #v5.0.5
106+
uses: actions/cache/restore@2c8a9bd7457de244a408f35966fab2fb45fda9c8 #v6.0.0
107107
with:
108108
key: ${{ format('node-cache-{0}-{1}-pnpm-{2}', runner.os, runner.arch, hashFiles('pnpm-lock.yaml')) }}
109109
path: ${{ steps.cache_dir.outputs.cache_dir }}
@@ -376,7 +376,7 @@ jobs:
376376
path: build/freetube-${{ steps.versionNumber.outputs.version }}-arm64-mac.7z
377377

378378
- name: Save pnpm cache
379-
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae #v5.0.5
379+
uses: actions/cache/save@2c8a9bd7457de244a408f35966fab2fb45fda9c8 #v6.0.0
380380
# Only save the cache if we weren't able to restore an existing one above
381381
if: steps.restore_cache.outputs.cache-primary-key != steps.restore_cache.outputs.cache-matched-key
382382
with:

.github/workflows/linter.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ jobs:
4646
4747
- name: Restore pnpm cache
4848
id: restore_cache
49-
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae #v5.0.5
49+
uses: actions/cache/restore@2c8a9bd7457de244a408f35966fab2fb45fda9c8 #v6.0.0
5050
with:
5151
key: ${{ format('node-cache-{0}-{1}-pnpm-{2}', runner.os, runner.arch, hashFiles('pnpm-lock.yaml')) }}
5252
path: ${{ steps.cache_dir.outputs.cache_dir }}

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ longer track you using cookies or JavaScript. Your subscriptions, playlists and
7474
### Browser Extensions
7575
The following extensions open YouTube links directly in FreeTube:
7676

77-
- [LibRedirect](https://libredirect.github.io/)
77+
- [LibRedirect](https://libredirect.manerakai.com/)
7878
- [RedirectTube](https://github.com/MStankiewiczOfficial/RedirectTube)
7979

8080
LibRedirect automatically redirect YouTube links to FreeTube.
@@ -83,7 +83,7 @@ LibRedirect automatically redirect YouTube links to FreeTube.
8383
8484
RedirectTube, doesn’t automatically open YouTube links in FreeTube (although this feature can be enabled in the settings). Instead, it adds buttons to the toolbar and context menu, which you can click to open videos in FreeTube manually.
8585

86-
- Download LibRedirect from [Mozilla Add-ons](https://addons.mozilla.org/firefox/addon/libredirect/) (for Firefox based-browsers) or [developer's website](https://libredirect.github.io/download_chromium.html) (for Chrome and Chromium-based browsers).
86+
- Download LibRedirect from [Mozilla Add-ons](https://addons.mozilla.org/firefox/addon/libredirect/) (for Firefox based-browsers) or [developer's website](https://libredirect.manerakai.com/download_chromium.html) (for Chrome and Chromium-based browsers).
8787

8888
- Download RedirectTube from [Mozilla Add-ons](https://addons.mozilla.org/firefox/addon/redirecttube/) (for Firefox based-browsers) or [Chrome Web Store](https://chromewebstore.google.com/detail/redirecttube/jpbaggklodpddjcadlebabhiopjkjfjh) (for Chrome and Chromium-based browsers).
8989

src/constants.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const IpcChannels = {
44
DISABLE_PROXY: 'disable-proxy',
55
GET_SYSTEM_LOCALE: 'get-system-locale',
66
GET_NAVIGATION_HISTORY: 'get-navigation-history',
7+
IS_WAYLAND_PLATFORM: 'is-wayland-platform',
78
STOP_POWER_SAVE_BLOCKER: 'stop-power-save-blocker',
89
START_POWER_SAVE_BLOCKER: 'start-power-save-blocker',
910
CREATE_NEW_WINDOW: 'create-new-window',

src/main/index.js

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ function runApp() {
290290
let trayOnMinimize = false
291291
let trayWindows = []
292292
const trayMaximizedWindows = {}
293+
const isTrayOnMinimizeSupported = process.platform !== 'darwin' && (process.platform !== 'linux' || app.commandLine.getSwitchValue('ozone-platform') !== 'wayland')
293294

294295
const userDataPath = app.getPath('userData')
295296

@@ -346,7 +347,7 @@ function runApp() {
346347
if (!openDeepLinksInNewWindow) {
347348
// Just focus the main window (instead of starting a new instance)
348349
if (mainWindow.isMinimized()) {
349-
if (process.platform !== 'darwin' && trayOnMinimize) {
350+
if (isTrayOnMinimizeSupported && trayOnMinimize) {
350351
trayClick(mainWindow)
351352
} else {
352353
mainWindow.restore()
@@ -524,7 +525,7 @@ function runApp() {
524525
backendPreference = doc.value
525526
break
526527
case 'hideToTrayOnMinimize':
527-
if (process.platform !== 'darwin') {
528+
if (isTrayOnMinimizeSupported) {
528529
trayOnMinimize = doc.value
529530
}
530531
break
@@ -1032,7 +1033,7 @@ function runApp() {
10321033

10331034
// endregion Ensure child windows use same options since electron 14
10341035

1035-
if (process.platform !== 'darwin') {
1036+
if (isTrayOnMinimizeSupported) {
10361037
function manageTray(window, removeWindow = false) {
10371038
if (tray) {
10381039
if (!removeWindow) {
@@ -1144,7 +1145,7 @@ function runApp() {
11441145
return
11451146
}
11461147

1147-
if (process.platform !== 'darwin' && trayOnMinimize && trayWindows.length > 0) {
1148+
if (isTrayOnMinimizeSupported && trayOnMinimize && trayWindows.length > 0) {
11481149
trayClick(newWindow)
11491150
} else {
11501151
newWindow.show()
@@ -1346,6 +1347,12 @@ function runApp() {
13461347
}
13471348
})
13481349

1350+
ipcMain.handle(IpcChannels.IS_WAYLAND_PLATFORM, (event) => {
1351+
if (isFreeTubeUrl(event.senderFrame.url)) {
1352+
return app.commandLine.getSwitchValue('ozone-platform') === 'wayland'
1353+
}
1354+
})
1355+
13491356
/**
13501357
* @param {import('electron').WebContents} webContents
13511358
* @param {string | undefined} [currentPath]
@@ -1656,7 +1663,7 @@ function runApp() {
16561663
await setMenu()
16571664
break
16581665
case 'hideToTrayOnMinimize':
1659-
if (process.platform !== 'darwin') {
1666+
if (isTrayOnMinimizeSupported) {
16601667
trayOnMinimize = data.value
16611668
if (!trayOnMinimize) { showHiddenWindows() }
16621669
}
@@ -2114,7 +2121,7 @@ function runApp() {
21142121
})
21152122
}
21162123

2117-
if (process.platform !== 'darwin') {
2124+
if (isTrayOnMinimizeSupported) {
21182125
app.on('before-quit', () => {
21192126
if (tray) { tray.destroy() }
21202127
})

src/preload/interface.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@ export default {
3030
return ipcRenderer.invoke(IpcChannels.GET_SYSTEM_LOCALE)
3131
},
3232

33+
/**
34+
* @returns {Promise<boolean>}
35+
*/
36+
isWaylandPlatform: () => {
37+
return ipcRenderer.invoke(IpcChannels.IS_WAYLAND_PLATFORM)
38+
},
39+
3340
/**
3441
* @param {string} path
3542
* @param {Record<string, string> | null | undefined} query

src/renderer/components/DataSettings/DataSettings.vue

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -895,17 +895,21 @@ async function importYouTubeWatchHistory(historyData) {
895895
// remove 'Watched' and translated variants from start of title
896896
// so we get the common string prefix for all the titles
897897
const getCommonStart = (allTitles) => {
898-
const watchedTitle = allTitles[0].split(' ')
899-
allTitles.forEach((title) => {
900-
const splitTitle = title.split(' ')
901-
for (let wtIndex = 0; wtIndex <= watchedTitle.length; wtIndex++) {
902-
if (!splitTitle.includes(watchedTitle[wtIndex])) {
903-
watchedTitle.splice(wtIndex, watchedTitle.length - wtIndex)
898+
if (allTitles.length < 2) {
899+
return ''
900+
}
901+
902+
let commonStart = allTitles[0]
903+
for (let i = 1; i < allTitles.length; i++) {
904+
while (!allTitles[i].startsWith(commonStart)) {
905+
commonStart = commonStart.slice(0, -1)
906+
if (commonStart === '') {
907+
return ''
904908
}
905909
}
906-
})
910+
}
907911
908-
return watchedTitle.join(' ')
912+
return commonStart
909913
}
910914
911915
const commonStart = getCommonStart(filteredHistoryData.map(e => e.title))

src/renderer/components/GeneralSettings/GeneralSettings.vue

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
@change="updateOpenDeepLinksInNewWindow"
4343
/>
4444
<FtToggleSwitch
45-
v-if="!IS_MAC && USING_ELECTRON"
45+
v-if="!IS_MAC && !isLinuxWayland && USING_ELECTRON"
4646
:label="t('Settings.General Settings.Minimize to system tray')"
4747
:default-value="hideToTrayOnMinimize"
4848
:compact="true"
@@ -167,7 +167,7 @@
167167
</template>
168168

169169
<script setup>
170-
import { computed, onBeforeUnmount, useTemplateRef } from 'vue'
170+
import { computed, onMounted, onBeforeUnmount, ref, useTemplateRef } from 'vue'
171171
import { useI18n } from '../../composables/use-i18n-polyfill'
172172
import { useRouter } from 'vue-router'
173173
@@ -193,6 +193,15 @@ const IS_MAC = process.platform === 'darwin'
193193
const { t } = useI18n()
194194
const router = useRouter()
195195
196+
// The 'minimize' event doesn't fire on wayland
197+
// https://github.com/electron/electron/issues/51766
198+
const isLinuxWayland = ref(false)
199+
if (process.env.IS_ELECTRON && process.platform === 'linux') {
200+
onMounted(async () => {
201+
isLinuxWayland.value = await window.ftElectron.isWaylandPlatform()
202+
})
203+
}
204+
196205
/** @type {import('vue').ComputedRef<boolean>} */
197206
const checkForUpdates = computed(() => store.getters.getCheckForUpdates)
198207

src/renderer/components/ft-list-video/ft-list-video.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ export default defineComponent({
252252
if (typeof this.lengthSeconds !== 'number' || this.lengthSeconds === 0) {
253253
return 0
254254
}
255-
const percentage = (this.watchProgress / this.lengthSeconds) * 100
255+
const percentage = (Math.ceil(this.watchProgress) / this.lengthSeconds) * 100
256256
return Math.min(percentage, 100)
257257
},
258258

src/renderer/components/ft-shaka-video-player/ft-shaka-video-player.js

Lines changed: 61 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1472,7 +1472,11 @@ export default defineComponent({
14721472
const isPortrait = variants[0].height > variants[0].width
14731473

14741474
let matches = variants.filter(variant => {
1475-
return quality === (isPortrait ? variant.width : variant.height)
1475+
const { width, height } = variant
1476+
const [primary, secondary] = isPortrait ? [width, height] : [height, width]
1477+
const aspectRatio = secondary / primary
1478+
const resolution = aspectRatio > 16 / 9 ? Math.round(secondary * 9 / 16) : primary
1479+
return quality === resolution
14761480
})
14771481

14781482
if (matches.length === 0) {
@@ -2280,7 +2284,7 @@ export default defineComponent({
22802284
* @param {KeyboardEvent} event
22812285
*/
22822286
function keyboardShortcutHandler(event) {
2283-
if (!player || !hasLoaded.value) {
2287+
if (!player) {
22842288
return
22852289
}
22862290

@@ -2334,6 +2338,61 @@ export default defineComponent({
23342338
return
23352339
}
23362340

2341+
switch (event.key.toLowerCase()) {
2342+
case KeyboardShortcuts.VIDEO_PLAYER.GENERAL.FULLSCREEN:
2343+
// Toggle full screen
2344+
event.preventDefault()
2345+
ui.getControls().toggleFullScreen()
2346+
blurTooltipButtons()
2347+
break
2348+
case 'escape':
2349+
// Exit full window
2350+
if (fullWindowEnabled.value) {
2351+
event.preventDefault()
2352+
2353+
events.dispatchEvent(new CustomEvent('setFullWindow', {
2354+
detail: false
2355+
}))
2356+
}
2357+
break
2358+
case KeyboardShortcuts.VIDEO_PLAYER.GENERAL.FULLWINDOW:
2359+
// Toggle full window mode
2360+
event.preventDefault()
2361+
events.dispatchEvent(new CustomEvent('setFullWindow', {
2362+
detail: !fullWindowEnabled.value
2363+
}))
2364+
blurTooltipButtons()
2365+
break
2366+
case KeyboardShortcuts.VIDEO_PLAYER.GENERAL.THEATRE_MODE:
2367+
// Toggle theatre mode
2368+
if (props.theatrePossible) {
2369+
event.preventDefault()
2370+
2371+
events.dispatchEvent(new CustomEvent('toggleTheatreMode', {
2372+
detail: !props.useTheatreMode
2373+
}))
2374+
}
2375+
blurTooltipButtons()
2376+
break
2377+
case KeyboardShortcuts.VIDEO_PLAYER.GENERAL.MUTE:
2378+
// Toggle mute only if metakey is not pressed
2379+
if (!event.metaKey) {
2380+
event.preventDefault()
2381+
const isMuted = !video_.muted
2382+
video_.muted = isMuted
2383+
2384+
const messageIcon = isMuted ? 'volume-mute' : 'volume-high'
2385+
const message = isMuted ? '0%' : `${Math.round(video_.volume * 100)}%`
2386+
showValueChange(message, messageIcon)
2387+
}
2388+
blurTooltipButtons()
2389+
break
2390+
}
2391+
2392+
if (!hasLoaded.value) {
2393+
return
2394+
}
2395+
23372396
switch (event.key.toLowerCase()) {
23382397
case ' ':
23392398
case 'spacebar': // older browsers might return spacebar instead of a space character
@@ -2365,25 +2424,6 @@ export default defineComponent({
23652424
event.preventDefault()
23662425
changePlayBackRate(videoPlaybackRateInterval.value)
23672426
break
2368-
case KeyboardShortcuts.VIDEO_PLAYER.GENERAL.FULLSCREEN:
2369-
// Toggle full screen
2370-
event.preventDefault()
2371-
ui.getControls().toggleFullScreen()
2372-
blurTooltipButtons()
2373-
break
2374-
case KeyboardShortcuts.VIDEO_PLAYER.GENERAL.MUTE:
2375-
// Toggle mute only if metakey is not pressed
2376-
if (!event.metaKey) {
2377-
event.preventDefault()
2378-
const isMuted = !video_.muted
2379-
video_.muted = isMuted
2380-
2381-
const messageIcon = isMuted ? 'volume-mute' : 'volume-high'
2382-
const message = isMuted ? '0%' : `${Math.round(video_.volume * 100)}%`
2383-
showValueChange(message, messageIcon)
2384-
}
2385-
blurTooltipButtons()
2386-
break
23872427
case KeyboardShortcuts.VIDEO_PLAYER.GENERAL.CAPTIONS: {
23882428
// Toggle caption/subtitles
23892429

@@ -2517,35 +2557,6 @@ export default defineComponent({
25172557
showOverlayControls()
25182558
}
25192559
break
2520-
case 'escape':
2521-
// Exit full window
2522-
if (fullWindowEnabled.value) {
2523-
event.preventDefault()
2524-
2525-
events.dispatchEvent(new CustomEvent('setFullWindow', {
2526-
detail: false
2527-
}))
2528-
}
2529-
break
2530-
case KeyboardShortcuts.VIDEO_PLAYER.GENERAL.FULLWINDOW:
2531-
// Toggle full window mode
2532-
event.preventDefault()
2533-
events.dispatchEvent(new CustomEvent('setFullWindow', {
2534-
detail: !fullWindowEnabled.value
2535-
}))
2536-
blurTooltipButtons()
2537-
break
2538-
case KeyboardShortcuts.VIDEO_PLAYER.GENERAL.THEATRE_MODE:
2539-
// Toggle theatre mode
2540-
if (props.theatrePossible) {
2541-
event.preventDefault()
2542-
2543-
events.dispatchEvent(new CustomEvent('toggleTheatreMode', {
2544-
detail: !props.useTheatreMode
2545-
}))
2546-
}
2547-
blurTooltipButtons()
2548-
break
25492560
case KeyboardShortcuts.VIDEO_PLAYER.GENERAL.TAKE_SCREENSHOT:
25502561
if (enableScreenshot.value && props.format !== 'audio') {
25512562
event.preventDefault()

0 commit comments

Comments
 (0)