diff --git a/desktop/CHANGELOG.md b/desktop/CHANGELOG.md index 37dc4451e1..842dee397a 100644 --- a/desktop/CHANGELOG.md +++ b/desktop/CHANGELOG.md @@ -2,6 +2,7 @@ ## v1.7.12 (Unreleased) +- Improved video player with streaming support (for processed videos). - . ## v1.7.11 diff --git a/web/packages/gallery/components/viewer/FileViewer.tsx b/web/packages/gallery/components/viewer/FileViewer.tsx index d9a091794e..e9d5b7bb28 100644 --- a/web/packages/gallery/components/viewer/FileViewer.tsx +++ b/web/packages/gallery/components/viewer/FileViewer.tsx @@ -63,7 +63,6 @@ import { moreButtonID, moreMenuID, resetMoreMenuButtonOnMenuClose, - shouldUsePlayerV2, type FileViewerPhotoSwipeDelegate, } from "./photoswipe"; @@ -829,7 +828,6 @@ export const FileViewer: React.FC = ({ const pswp = new FileViewerPhotoSwipe({ initialIndex, - disableDownload, haveUser, delegate: delegateRef.current!, onClose: () => { @@ -1152,22 +1150,12 @@ const Shortcuts: React.FC = ({ + - { - /* TODO(HLS): */ - shouldUsePlayerV2() && ( - - ) - } = ({ action={t("pan")} shortcut={formattedListJoin([ut("W A S D"), t("drag")])} /> - { - /* TODO(HLS): */ - shouldUsePlayerV2() && ( - - ) - } + {haveUser && ( diff --git a/web/packages/gallery/components/viewer/data-source.ts b/web/packages/gallery/components/viewer/data-source.ts index 125a47686f..5b388e98f2 100644 --- a/web/packages/gallery/components/viewer/data-source.ts +++ b/web/packages/gallery/components/viewer/data-source.ts @@ -10,7 +10,6 @@ import type { EnteFile } from "ente-media/file"; import { fileCaption } from "ente-media/file-metadata"; import { FileType } from "ente-media/file-type"; import { ensureString } from "ente-utils/ensure"; -import { shouldUsePlayerV2 } from "./photoswipe"; /** * This is a subset of the fields expected by PhotoSwipe itself (see the @@ -467,22 +466,18 @@ const enqueueUpdates = async ( createHLSPlaylistItemDataValidity(), ); } else { - if (shouldUsePlayerV2()) { - // See: [Note: Caching HLS playlist data] - // - // TODO(HLS): As an optimization, we can handle the logged in vs - // public albums case separately once we have the status-diff - // state, we don't need to mark status-diff case as transient. - // - // Note that setting the transient flag is not too expensive, - // since the underlying videoURL is still cached by the download - // manager. So effectively, under normal circumstance, it just - // adds one API call (to recheck if an HLS playlist now exists - // for the given file). - update({ ...videoURLD, isTransient: true }); - } else { - update(videoURLD); - } + // See: [Note: Caching HLS playlist data] + // + // TODO(HLS): As an optimization, we can handle the logged in vs + // public albums case separately once we have the status-diff state, + // we don't need to mark status-diff case as transient. + // + // Note that setting the transient flag is not too expensive, since + // the underlying videoURL is still cached by the download manager. + // So effectively, under normal circumstance, it just adds one API + // call (to recheck if an HLS playlist now exists for the given + // file). + update({ ...videoURLD, isTransient: true }); } }; @@ -523,9 +518,8 @@ const enqueueUpdates = async ( } try { - // TODO(HLS): let hlsPlaylistData: HLSPlaylistData | undefined; - if (shouldUsePlayerV2() && file.metadata.fileType == FileType.video) { + if (file.metadata.fileType == FileType.video) { hlsPlaylistData = await hlsPlaylistDataForFile( file, downloadManager.publicAlbumsCredentials, diff --git a/web/packages/gallery/components/viewer/photoswipe.ts b/web/packages/gallery/components/viewer/photoswipe.ts index ba1cd986cb..736b0b20c2 100644 --- a/web/packages/gallery/components/viewer/photoswipe.ts +++ b/web/packages/gallery/components/viewer/photoswipe.ts @@ -1,8 +1,6 @@ import log from "ente-base/log"; -import { albumsAppOrigin } from "ente-base/origins"; import type { EnteFile } from "ente-media/file"; import { FileType } from "ente-media/file-type"; -import { settingsSnapshot } from "ente-new/photos/services/settings"; import "hls-video-element"; import { t } from "i18next"; import "media-chrome"; @@ -92,10 +90,7 @@ export interface FileViewerPhotoSwipeDelegate { ) => void; } -type FileViewerPhotoSwipeOptions = Pick< - FileViewerProps, - "initialIndex" | "disableDownload" -> & { +type FileViewerPhotoSwipeOptions = Pick & { /** * `true` if we're running in the context of a logged in user, and so * various actions that modify the file should be shown. @@ -163,19 +158,6 @@ export const moreButtonID = "ente-pswp-more-button"; */ export const moreMenuID = "ente-pswp-more-menu"; -// TODO(HLS): -let _shouldUsePlayerV2: boolean | undefined; -export const shouldUsePlayerV2 = () => - // Enable for internal users and public albums - (_shouldUsePlayerV2 ??= - settingsSnapshot().isInternalUser || isPublicAlbumApp()); - -const isPublicAlbumApp = () => { - const currentURL = new URL(window.location.href); - const albumsURL = new URL(albumsAppOrigin()); - return currentURL.host == albumsURL.host; -}; - /** * A wrapper over {@link PhotoSwipe} to tailor its interface for use by our file * viewer. @@ -206,7 +188,6 @@ export class FileViewerPhotoSwipe { constructor({ initialIndex, - disableDownload, haveUser, delegate, onClose, @@ -340,32 +321,20 @@ export class FileViewerPhotoSwipe { if (itemData.fileType === FileType.video) { const { videoPlaylistURL, videoURL } = itemData; - if ( - videoPlaylistURL && - shouldUsePlayerV2() && - videoQuality == "auto" - ) { + if (videoPlaylistURL && videoQuality == "auto") { const mcID = `ente-mc-hls-${file.id}`; return { ...itemData, html: hlsVideoHTML(videoPlaylistURL, mcID), mediaControllerID: mcID, }; - } else if (videoURL && shouldUsePlayerV2()) { + } else if (videoURL) { const mcID = `ente-mc-orig-${file.id}`; return { ...itemData, html: videoHTML(videoURL, mcID), mediaControllerID: mcID, }; - } else if (videoURL) { - return { - ...itemData, - html: videoHTMLBrowserControls( - videoURL, - !!disableDownload, - ), - }; } } @@ -532,17 +501,6 @@ export class FileViewerPhotoSwipe { } } - // TODO(HLS): Temporary gate - if (!shouldUsePlayerV2()) { - const qualityMenu = - container?.querySelector("#ente-quality-menu"); - if (qualityMenu instanceof MediaChromeMenu) { - // Hide the auto option - qualityMenu.radioGroupItems[0]!.hidden = true; - } - return; - } - const qualityMenu = container?.querySelector("#ente-quality-menu"); if (qualityMenu instanceof MediaChromeMenu) { const { videoPlaylistURL, fileID } = itemData; @@ -755,19 +713,6 @@ export class FileViewerPhotoSwipe { */ let videoVideoEl: HTMLVideoElement | undefined; - /** - * Callback attached to video playback events when showing video files. - * - * These are needed to hide the caption when a video is playing on a - * file of type video. - */ - let onVideoPlayback: (() => void) | undefined; - - /** - * The DOM element showing the caption for the current file. - */ - let captionElement: HTMLElement | undefined; - pswp.on("change", () => { const itemData = currSlideData(); @@ -784,19 +729,6 @@ export class FileViewerPhotoSwipe { } }); - // Clear existing listeners, if any. - if (videoVideoEl && onVideoPlayback) { - videoVideoEl.removeEventListener("play", onVideoPlayback); - videoVideoEl.removeEventListener("pause", onVideoPlayback); - videoVideoEl.removeEventListener("ended", onVideoPlayback); - videoVideoEl = undefined; - onVideoPlayback = undefined; - } - - // Reset. - showIf(captionElement!, true); - - // Attach new listeners, if needed. if (itemData.fileType == FileType.video) { // We use content.element instead of container here because // pswp.currSlide.container.getElementsByTagName("video") does @@ -807,17 +739,8 @@ export class FileViewerPhotoSwipe { // pause the video in "contentDeactivate". const contentElement = pswp.currSlide?.content.element; videoVideoEl = queryVideoElement(contentElement) ?? undefined; - - if (videoVideoEl) { - onVideoPlayback = () => { - if (!shouldUsePlayerV2()) - showIf(captionElement!, !!videoVideoEl?.paused); - }; - - videoVideoEl.addEventListener("play", onVideoPlayback); - videoVideoEl.addEventListener("pause", onVideoPlayback); - videoVideoEl.addEventListener("ended", onVideoPlayback); - } + } else { + videoVideoEl = undefined; } }); @@ -841,16 +764,6 @@ export class FileViewerPhotoSwipe { * the current slide. */ const videoToggleMuteIfPossible = () => { - // TODO(HLS): Temporary gate - if (!shouldUsePlayerV2()) { - const video = videoVideoEl; - if (!video) return; - - video.muted = !video.muted; - - return; - } - // Go via the media chrome mute button when muting, because // otherwise the local storage that the media chrome internally // manages ('media-chrome-pref-muted' which can be 'true' or @@ -1131,7 +1044,6 @@ export class FileViewerPhotoSwipe { // the p, and the padding on the div. html: "

", onInit: (element, pswp) => { - captionElement = element; pswp.on("change", () => { const { fileType, alt } = currSlideData(); element.querySelector("p")!.innerText = alt ?? ""; @@ -1174,22 +1086,18 @@ export class FileViewerPhotoSwipe { const handleNextSlide = () => pswp.next(); const handleSeekBackOrPreviousSlide = () => { - // TODO(HLS): Behind temporary flag - // const vid = videoVideoEl; - const vid = shouldUsePlayerV2() ? videoVideoEl : undefined; - if (vid) { - vid.currentTime = Math.max(vid.currentTime - 5, 0); + const video = videoVideoEl; + if (video) { + video.currentTime = Math.max(video.currentTime - 5, 0); } else { handlePreviousSlide(); } }; const handleSeekForwardOrNextSlide = () => { - // TODO(HLS): Behind temporary flag - // const vid = videoVideoEl; - const vid = shouldUsePlayerV2() ? videoVideoEl : undefined; - if (vid) { - vid.currentTime = vid.currentTime + 5; + const video = videoVideoEl; + if (video) { + video.currentTime = video.currentTime + 5; } else { handleNextSlide(); } @@ -1479,13 +1387,6 @@ export class FileViewerPhotoSwipe { refreshCurrentSlideFavoriteButtonIfNeeded: () => void; } -const videoHTMLBrowserControls = (url: string, disableDownload: boolean) => ` - -`; - // Requires the following imports to register the Web components we use: // // import "hls-video-element";