diff --git a/components/app/Appbar.vue b/components/app/Appbar.vue index 4f8bfb97..fd67744f 100644 --- a/components/app/Appbar.vue +++ b/components/app/Appbar.vue @@ -100,14 +100,14 @@ export default { this.isCastAvailable = data && data.value } }, - mounted() { + async mounted() { AbsAudioPlayer.getIsCastAvailable().then((data) => { this.isCastAvailable = data && data.value }) - this.onCastAvailableUpdateListener = AbsAudioPlayer.addListener('onCastAvailableUpdate', this.onCastAvailableUpdate) + this.onCastAvailableUpdateListener = await AbsAudioPlayer.addListener('onCastAvailableUpdate', this.onCastAvailableUpdate) }, beforeDestroy() { - if (this.onCastAvailableUpdateListener) this.onCastAvailableUpdateListener.remove() + this.onCastAvailableUpdateListener?.remove() } } diff --git a/components/app/AudioPlayer.vue b/components/app/AudioPlayer.vue index 7684fb90..ec129319 100644 --- a/components/app/AudioPlayer.vue +++ b/components/app/AudioPlayer.vue @@ -140,13 +140,6 @@ export default { readyTrackWidth: 0, seekedTime: 0, seekLoading: false, - onPlaybackSessionListener: null, - onPlaybackClosedListener: null, - onPlayingUpdateListener: null, - onMetadataListener: null, - onProgressSyncFailing: null, - onProgressSyncSuccess: null, - onPlaybackSpeedChangedListener: null, touchStartY: 0, touchStartTime: 0, playerSettings: { @@ -883,14 +876,14 @@ export default { async init() { await this.loadPlayerSettings() - this.onPlaybackSessionListener = AbsAudioPlayer.addListener('onPlaybackSession', this.onPlaybackSession) - this.onPlaybackClosedListener = AbsAudioPlayer.addListener('onPlaybackClosed', this.onPlaybackClosed) - this.onPlaybackFailedListener = AbsAudioPlayer.addListener('onPlaybackFailed', this.onPlaybackFailed) - this.onPlayingUpdateListener = AbsAudioPlayer.addListener('onPlayingUpdate', this.onPlayingUpdate) - this.onMetadataListener = AbsAudioPlayer.addListener('onMetadata', this.onMetadata) - this.onProgressSyncFailing = AbsAudioPlayer.addListener('onProgressSyncFailing', this.showProgressSyncIsFailing) - this.onProgressSyncSuccess = AbsAudioPlayer.addListener('onProgressSyncSuccess', this.showProgressSyncSuccess) - this.onPlaybackSpeedChangedListener = AbsAudioPlayer.addListener('onPlaybackSpeedChanged', this.onPlaybackSpeedChanged) + AbsAudioPlayer.addListener('onPlaybackSession', this.onPlaybackSession) + AbsAudioPlayer.addListener('onPlaybackClosed', this.onPlaybackClosed) + AbsAudioPlayer.addListener('onPlaybackFailed', this.onPlaybackFailed) + AbsAudioPlayer.addListener('onPlayingUpdate', this.onPlayingUpdate) + AbsAudioPlayer.addListener('onMetadata', this.onMetadata) + AbsAudioPlayer.addListener('onProgressSyncFailing', this.showProgressSyncIsFailing) + AbsAudioPlayer.addListener('onProgressSyncSuccess', this.showProgressSyncSuccess) + AbsAudioPlayer.addListener('onPlaybackSpeedChanged', this.onPlaybackSpeedChanged) }, async screenOrientationChange() { if (this.isRefreshingUI) return @@ -984,14 +977,9 @@ export default { document.body.removeEventListener('touchend', this.touchend) document.body.removeEventListener('touchmove', this.touchmove) - if (this.onPlayingUpdateListener) this.onPlayingUpdateListener.remove() - if (this.onMetadataListener) this.onMetadataListener.remove() - if (this.onPlaybackSessionListener) this.onPlaybackSessionListener.remove() - if (this.onPlaybackClosedListener) this.onPlaybackClosedListener.remove() - if (this.onPlaybackFailedListener) this.onPlaybackFailedListener.remove() - if (this.onProgressSyncFailing) this.onProgressSyncFailing.remove() - if (this.onProgressSyncSuccess) this.onProgressSyncSuccess.remove() - if (this.onPlaybackSpeedChangedListener) this.onPlaybackSpeedChangedListener.remove() + if (AbsAudioPlayer.removeAllListeners) { + AbsAudioPlayer.removeAllListeners() + } clearInterval(this.playInterval) } } diff --git a/components/app/AudioPlayerContainer.vue b/components/app/AudioPlayerContainer.vue index 958fc968..1040e61b 100644 --- a/components/app/AudioPlayerContainer.vue +++ b/components/app/AudioPlayerContainer.vue @@ -351,11 +351,11 @@ export default { } } }, - mounted() { - this.onLocalMediaProgressUpdateListener = AbsAudioPlayer.addListener('onLocalMediaProgressUpdate', this.onLocalMediaProgressUpdate) - this.onSleepTimerEndedListener = AbsAudioPlayer.addListener('onSleepTimerEnded', this.onSleepTimerEnded) - this.onSleepTimerSetListener = AbsAudioPlayer.addListener('onSleepTimerSet', this.onSleepTimerSet) - this.onMediaPlayerChangedListener = AbsAudioPlayer.addListener('onMediaPlayerChanged', this.onMediaPlayerChanged) + async mounted() { + this.onLocalMediaProgressUpdateListener = await AbsAudioPlayer.addListener('onLocalMediaProgressUpdate', this.onLocalMediaProgressUpdate) + this.onSleepTimerEndedListener = await AbsAudioPlayer.addListener('onSleepTimerEnded', this.onSleepTimerEnded) + this.onSleepTimerSetListener = await AbsAudioPlayer.addListener('onSleepTimerSet', this.onSleepTimerSet) + this.onMediaPlayerChangedListener = await AbsAudioPlayer.addListener('onMediaPlayerChanged', this.onMediaPlayerChanged) this.playbackSpeed = this.$store.getters['user/getUserSetting']('playbackRate') console.log(`[AudioPlayerContainer] Init Playback Speed: ${this.playbackSpeed}`) @@ -370,10 +370,10 @@ export default { this.$eventBus.$on('device-focus-update', this.deviceFocused) }, beforeDestroy() { - if (this.onLocalMediaProgressUpdateListener) this.onLocalMediaProgressUpdateListener.remove() - if (this.onSleepTimerEndedListener) this.onSleepTimerEndedListener.remove() - if (this.onSleepTimerSetListener) this.onSleepTimerSetListener.remove() - if (this.onMediaPlayerChangedListener) this.onMediaPlayerChangedListener.remove() + this.onLocalMediaProgressUpdateListener?.remove() + this.onSleepTimerEndedListener?.remove() + this.onSleepTimerSetListener?.remove() + this.onMediaPlayerChangedListener?.remove() this.$eventBus.$off('abs-ui-ready', this.onReady) this.$eventBus.$off('play-item', this.playLibraryItem) diff --git a/components/connection/ServerConnectForm.vue b/components/connection/ServerConnectForm.vue index 7f1a461b..f3a3470c 100644 --- a/components/connection/ServerConnectForm.vue +++ b/components/connection/ServerConnectForm.vue @@ -17,6 +17,11 @@

{{ $strings.MessageOldServerConnectionWarning }}

{{ $strings.LabelMoreInfo }} + +
+

{{ $strings.MessageOldServerAuthWarning }}

+ {{ $strings.LabelMoreInfo }} +
{{ $strings.ButtonAddNewServer }} @@ -155,9 +160,20 @@ export default { cancelText: this.$strings.ButtonOk }) }, + showOldAuthWarningDialog() { + Dialog.alert({ + title: 'Old Server Auth Warning', + message: this.$strings.MessageOldServerAuthWarningHelp, + cancelText: this.$strings.ButtonOk + }) + }, checkIdUuid(userId) { return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(userId) }, + checkIsUsingOldAuth(config) { + if (!config.version) return true + return !this.$isValidVersion(config.version, '2.26.0') + }, /** * Initiates the login process using OpenID via OAuth2.0. * 1. Verifying the server's address @@ -505,7 +521,7 @@ export default { try { var urlObject = new URL(url) if (protocolOverride) urlObject.protocol = protocolOverride - return urlObject.href + return urlObject.href.replace(/\/$/, '') // Remove trailing slash } catch (error) { console.error('Invalid URL', error) return null @@ -889,7 +905,7 @@ export default { return authRes }, setForceReloginForNewAuth() { - this.error = 'A new authentication system was added in server v2.26.0. Re-login is required for this server connection.' + this.error = this.$strings.MessageOldServerAuthReLoginRequired this.showAuth = true }, init() { diff --git a/components/readers/ComicReader.vue b/components/readers/ComicReader.vue index e18885e3..bd7ed4e1 100644 --- a/components/readers/ComicReader.vue +++ b/components/readers/ComicReader.vue @@ -245,6 +245,7 @@ export default { async extract() { this.loading = true + // TODO: Handle JWT auth refresh const buff = await this.$axios.$get(this.url, { responseType: 'blob', headers: { diff --git a/components/readers/MobiReader.vue b/components/readers/MobiReader.vue index 556c145b..a3d5c112 100644 --- a/components/readers/MobiReader.vue +++ b/components/readers/MobiReader.vue @@ -84,6 +84,7 @@ export default { }, async initMobi() { // Fetch mobi file as blob + // TODO: Handle JWT auth refresh var buff = await this.$axios.$get(this.url, { responseType: 'blob', headers: { diff --git a/components/widgets/DownloadProgressIndicator.vue b/components/widgets/DownloadProgressIndicator.vue index 28bde581..8e389c7d 100644 --- a/components/widgets/DownloadProgressIndicator.vue +++ b/components/widgets/DownloadProgressIndicator.vue @@ -78,15 +78,15 @@ export default { this.$store.commit('globals/updateDownloadItemPart', itemPart) } }, - mounted() { - this.downloadItemListener = AbsDownloader.addListener('onDownloadItem', (data) => this.onDownloadItem(data)) - this.itemPartUpdateListener = AbsDownloader.addListener('onDownloadItemPartUpdate', (data) => this.onDownloadItemPartUpdate(data)) - this.completeListener = AbsDownloader.addListener('onItemDownloadComplete', (data) => this.onItemDownloadComplete(data)) + async mounted() { + this.downloadItemListener = await AbsDownloader.addListener('onDownloadItem', (data) => this.onDownloadItem(data)) + this.itemPartUpdateListener = await AbsDownloader.addListener('onDownloadItemPartUpdate', (data) => this.onDownloadItemPartUpdate(data)) + this.completeListener = await AbsDownloader.addListener('onItemDownloadComplete', (data) => this.onItemDownloadComplete(data)) }, beforeDestroy() { - if (this.downloadItemListener) this.downloadItemListener.remove() - if (this.completeListener) this.completeListener.remove() - if (this.itemPartUpdateListener) this.itemPartUpdateListener.remove() + this.downloadItemListener?.remove() + this.completeListener?.remove() + this.itemPartUpdateListener?.remove() } } \ No newline at end of file diff --git a/pages/account.vue b/pages/account.vue index ceb65842..dbcfc50c 100644 --- a/pages/account.vue +++ b/pages/account.vue @@ -4,6 +4,10 @@ +
+

Server version: v{{ serverVersion }}

+
+ {{ $strings.ButtonSwitchServerUser }}logout
@@ -43,6 +47,10 @@ export default { }, serverAddress() { return this.serverConnectionConfig.address + }, + serverVersion() { + // Saved in server connection config after 0.9.81 + return this.serverConnectionConfig.version } }, methods: { diff --git a/pages/media/_id/history.vue b/pages/media/_id/history.vue index d63b7b66..f231aff5 100644 --- a/pages/media/_id/history.vue +++ b/pages/media/_id/history.vue @@ -200,7 +200,7 @@ export default { this.onMediaItemHistoryUpdatedListener = await AbsAudioPlayer.addListener('onMediaItemHistoryUpdated', this.onMediaItemHistoryUpdated) }, beforeDestroy() { - if (this.onMediaItemHistoryUpdatedListener) this.onMediaItemHistoryUpdatedListener.remove() + this.onMediaItemHistoryUpdatedListener?.remove() } } diff --git a/strings/en-us.json b/strings/en-us.json index 8ee7a956..e25c8e6c 100644 --- a/strings/en-us.json +++ b/strings/en-us.json @@ -325,6 +325,9 @@ "MessageNoSeries": "No series", "MessageNoUpdatesWereNecessary": "No updates were necessary", "MessageNoUserPlaylists": "You have no playlists", + "MessageOldServerAuthReLoginRequired": "A new authentication system was added in server v2.26.0. Re-login is required for this server connection.", + "MessageOldServerAuthWarning": "Server is using out-dated authentication", + "MessageOldServerAuthWarningHelp": "Authentication was updated in server v2.26.0 to use a more secure method. A future app update will require server version v2.26.0 or higher. You will need to re-login after updating the server.", "MessageOldServerConnectionWarning": "Server connection config is using an old user ID. Please delete and re-add this server connection.", "MessageOldServerConnectionWarningHelp": "You originally set up the connection to this server prior to the database migration in 2.3.0, released June 2023. A future server update will remove the ability to sign in with this old connection. Please delete the existing server connection and connect again (using the same server address and credentials). If you have any downloaded media on this device, the media will need to be downloaded again to sync with the server.", "MessagePodcastSearchField": "Enter search term or RSS feed URL",