diff --git a/js/app.js b/js/app.js index 48a5d6f8..286a398b 100644 --- a/js/app.js +++ b/js/app.js @@ -5165,6 +5165,73 @@ class Application { return normalized; } + refreshVisibleModerationUi({ reason } = {}) { + const context = reason ? ` after ${reason}` : ""; + + const redecorateVideo = (video) => { + if (!video || typeof video !== "object") { + return; + } + + try { + this.decorateVideoModeration(video); + } catch (error) { + devLogger.warn( + `[Application] Failed to decorate video moderation${context}:`, + error, + ); + } + }; + + if (this.videosMap instanceof Map) { + for (const video of this.videosMap.values()) { + redecorateVideo(video); + } + } + + if (this.videoListView && Array.isArray(this.videoListView.currentVideos)) { + for (const video of this.videoListView.currentVideos) { + redecorateVideo(video); + } + } + + if (this.videoListView && Array.isArray(this.videoListView.videoCardInstances)) { + for (const card of this.videoListView.videoCardInstances) { + if (!card || typeof card !== "object") { + continue; + } + + if (card.video && typeof card.video === "object") { + redecorateVideo(card.video); + } + + if (typeof card.refreshModerationUi === "function") { + try { + card.refreshModerationUi(); + } catch (error) { + devLogger.warn( + `[Application] Failed to refresh moderation UI on card${context}:`, + error, + ); + } + } + } + } + + if (this.currentVideo && typeof this.currentVideo === "object") { + redecorateVideo(this.currentVideo); + + try { + this.videoModal?.refreshActiveVideoModeration?.({ video: this.currentVideo }); + } catch (error) { + devLogger.warn( + `[Application] Failed to refresh video modal moderation UI${context}:`, + error, + ); + } + } + } + updateActiveProfileUI(pubkey, profile = {}) { if (this.profileController) { this.profileController.handleProfileUpdated({ diff --git a/js/index.js b/js/index.js index 92415ce0..42167448 100644 --- a/js/index.js +++ b/js/index.js @@ -380,6 +380,83 @@ function startApplication() { return startupPromise; } +function wasBackForwardNavigation(event) { + if (event?.persisted) { + return true; + } + + if (typeof window === "undefined" || !window.performance) { + return false; + } + + if (typeof window.performance.getEntriesByType === "function") { + try { + const navigationEntries = window.performance.getEntriesByType("navigation"); + if (Array.isArray(navigationEntries) && navigationEntries.length) { + const latestEntry = navigationEntries[navigationEntries.length - 1]; + if (latestEntry && latestEntry.type === "back_forward") { + return true; + } + } + } catch (error) { + devLogger.warn("[pageshow] Failed to inspect navigation entries:", error); + } + } + + const navigation = window.performance.navigation; + if (!navigation || typeof navigation.type !== "number") { + return false; + } + + const backForwardType = + typeof navigation.TYPE_BACK_FORWARD === "number" + ? navigation.TYPE_BACK_FORWARD + : 2; + + return navigation.type === backForwardType; +} + +function handlePageShow(event) { + if (!wasBackForwardNavigation(event)) { + return; + } + + if (!application) { + return; + } + + Promise.resolve(applicationReadyPromise) + .catch(() => {}) + .then(() => { + if (!application) { + return null; + } + + try { + application.refreshVisibleModerationUi?.({ reason: "pageshow" }); + } catch (error) { + devLogger.warn("[pageshow] Failed to refresh moderation UI after resume:", error); + } + + if (typeof application.refreshAllVideoGrids !== "function") { + return null; + } + + return application + .refreshAllVideoGrids({ reason: "pageshow", forceMainReload: true }) + .catch((error) => { + devLogger.warn("[pageshow] Failed to refresh video grids after resume:", error); + }); + }) + .catch((error) => { + devLogger.warn("[pageshow] Failed to process resume refresh:", error); + }); +} + +if (typeof window !== "undefined" && typeof window.addEventListener === "function") { + window.addEventListener("pageshow", handlePageShow); +} + const INTERFACE_FADE_IN_ANIMATION = "interface-fade-in"; const VIDEO_THUMBNAIL_FADE_IN_ANIMATION = "video-thumbnail-fade-in";