mirror of
				https://github.com/mickael-kerjean/filestash.git
				synced 2025-11-01 02:43:35 +08:00 
			
		
		
		
	feature (chromecast): canary release with chromecast image
This commit is contained in:
		| @ -82,17 +82,6 @@ async function setup_blue_death_screen() { | ||||
|     }; | ||||
| } | ||||
|  | ||||
| // async function setup_chromecast() { | ||||
| //     if (!window.CONFIG["enable_chromecast"]) { | ||||
| //         return Promise.resolve(); | ||||
| //     } else if (!("chrome" in window)) { | ||||
| //         return Promise.resolve(); | ||||
| //     } else if (location.hostname === "localhost" || location.hostname === "127.0.0.1") { | ||||
| //         return Promise.resolve(); | ||||
| //     } | ||||
| //     return window.Chromecast.init(); | ||||
| // } | ||||
|  | ||||
| async function setup_history() { | ||||
|     window.history.replaceState({}, ""); | ||||
| } | ||||
|  | ||||
| @ -6,76 +6,60 @@ export async function init() { | ||||
|     } else if (location.hostname === "localhost" || location.hostname === "127.0.0.1") { | ||||
|         return Promise.resolve(); | ||||
|     } | ||||
|     // return Chromecast.init(); | ||||
|     return Chromecast.init(); | ||||
| } | ||||
|  | ||||
| // import { Session } from "./session"; | ||||
| // import { currentShare, objectGet } from "../helpers/"; | ||||
| export const Chromecast = new class ChromecastManager { | ||||
|     init() { | ||||
|         return new Promise((resolve) => { | ||||
|             const script = document.createElement("script"); | ||||
|             script.src = "https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"; | ||||
|             script.onerror = () => resolve(null); | ||||
|             window["__onGCastApiAvailable"] = function(isAvailable) { | ||||
|                 if (isAvailable) window.cast.framework.CastContext.getInstance().setOptions({ | ||||
|                     receiverApplicationId: window.chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID, | ||||
|                     autoJoinPolicy: window.chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED, | ||||
|                 }); | ||||
|                 resolve(null); | ||||
|             }; | ||||
|             document.head.appendChild(script); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
| // class ChromecastManager { | ||||
| //     init() { | ||||
| //         return new Promise((done) => { | ||||
| //             const script = document.createElement("script"); | ||||
| //             script.src = "https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"; | ||||
| //             script.onerror = () => done() | ||||
| //             window["__onGCastApiAvailable"] = function(isAvailable) { | ||||
| //                 if (isAvailable) cast.framework.CastContext.getInstance().setOptions({ | ||||
| //                     receiverApplicationId: chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID, | ||||
| //                     autoJoinPolicy: chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED, | ||||
| //                 }); | ||||
| //                 done(); | ||||
| //             }; | ||||
| //             document.head.appendChild(script) | ||||
| //         }); | ||||
| //     } | ||||
|     createLink(apiPath) { | ||||
|         const target = new URL(location.origin + apiPath); | ||||
|         const shareID = new URLSearchParams(location.search).get("search"); | ||||
|         if (shareID) target.searchParams.append("share", shareID); | ||||
|         return target.toString(); | ||||
|     } | ||||
|  | ||||
| //     origin() { | ||||
| //         return location.origin; | ||||
| //     }; | ||||
|     createRequest(mediaInfo) { | ||||
|         if (!window.BEARER_TOKEN) throw new Error("Invalid account"); | ||||
|         // TODO: it would be much much nicer to set the authorization from an HTTP header | ||||
|         // but this would require to create a custom web receiver app, setup accounts on | ||||
|         // google, etc,... Until that happens, we're setting the authorization within the | ||||
|         // url. Once we have that app, the authorisation will come from a customData field | ||||
|         // of a chrome.cast.media.LoadRequest | ||||
|         const target = new URL(mediaInfo.contentId); | ||||
|         target.searchParams.append("authorization", window.BEARER_TOKEN); | ||||
|         mediaInfo.contentId = target.toString(); | ||||
|         return new window.chrome.cast.media.LoadRequest(mediaInfo); | ||||
|     } | ||||
|  | ||||
| //     createLink(apiPath) { | ||||
| //         const shareID = currentShare(); | ||||
| //         if (shareID) { | ||||
| //             const target = new URL(this.origin() + apiPath); | ||||
| //             target.searchParams.append("share", shareID); | ||||
| //             return target.toString(); | ||||
| //         } | ||||
| //         const target = new URL(this.origin() + apiPath) | ||||
| //         return target.toString(); | ||||
| //     } | ||||
|     context() { | ||||
|         if (!window.chrome?.cast?.isAvailable) return; | ||||
|         return window.cast.framework.CastContext.getInstance(); | ||||
|     } | ||||
|  | ||||
| //     createRequest(mediaInfo) { | ||||
| //         let prior = Promise.resolve(); | ||||
| //         if (!Session.authorization) prior = Session.currentUser(); | ||||
| //         return prior.then(() => { | ||||
| //             if (!Session.authorization) throw new Error("Invalid account"); | ||||
| //             // TODO: it would be much much nicer to set the authorization from an HTTP header | ||||
| //             // but this would require to create a custom web receiver app, setup accounts on | ||||
| //             // google, etc,... Until that happens, we're setting the authorization within the | ||||
| //             // url. Once we have that app, the authorisation will come from a customData field | ||||
| //             // of a chrome.cast.media.LoadRequest | ||||
| //             const target = new URL(mediaInfo.contentId); | ||||
| //             target.searchParams.append("authorization", Session.authorization); | ||||
| //             mediaInfo.contentId = target.toString(); | ||||
| //             return new chrome.cast.media.LoadRequest(mediaInfo); | ||||
| //         }); | ||||
| //     } | ||||
|     session() { | ||||
|         const context = this.context(); | ||||
|         if (!context) return; | ||||
|         return context.getCurrentSession(); | ||||
|     } | ||||
|  | ||||
| //     context() { | ||||
| //         if (!objectGet(window.chrome, ["cast", "isAvailable"])) { | ||||
| //             return; | ||||
| //         } | ||||
| //         return cast.framework.CastContext.getInstance(); | ||||
| //     } | ||||
| //     session() { | ||||
| //         const context = this.context(); | ||||
| //         if (!context) return; | ||||
| //         return context.getCurrentSession(); | ||||
| //     } | ||||
| //     media() { | ||||
| //         const session = this.session(); | ||||
| //         if (!session) return; | ||||
| //         return session.getMediaSession(); | ||||
| //     } | ||||
| // } | ||||
| // export const Chromecast = new ChromecastManager(); | ||||
|     media() { | ||||
|         const session = this.session(); | ||||
|         if (!session) return; | ||||
|         return session.getMediaSession(); | ||||
|     } | ||||
| }(); | ||||
|  | ||||
| @ -8,7 +8,10 @@ export function getSession() { | ||||
|         method: "GET", | ||||
|         responseType: "json" | ||||
|     }).pipe( | ||||
|         rxjs.map(({ responseJSON }) => responseJSON.result) | ||||
|         rxjs.map(({ responseJSON }) => responseJSON.result), | ||||
|         rxjs.tap(({ authorization }) => { | ||||
|             if (authorization) window.BEARER_TOKEN = authorization; | ||||
|         }), | ||||
|     ); | ||||
| } | ||||
|  | ||||
|  | ||||
| @ -198,7 +198,7 @@ export default async function(render) { | ||||
|             return rxjs.of(null).pipe( | ||||
|                 rxjs.tap(() => toggleLoader(true)), | ||||
|                 rxjs.mergeMap(() => createSession(formData)), | ||||
|                 rxjs.tap(({ responseJSON, responseHeaders }) => { | ||||
|                 rxjs.tap(({ responseJSON }) => { | ||||
|                     let redirectURL = toHref("/files/"); | ||||
|                     const GET = getURLParams(); | ||||
|                     if (GET["next"]) redirectURL = GET["next"]; | ||||
|  | ||||
| @ -13,7 +13,7 @@ export default function(render) { | ||||
|     effect(deleteSession().pipe( | ||||
|         rxjs.mergeMap(setup_config), | ||||
|         rxjs.tap(() => { | ||||
|             window.CONFIG["logout"] ? location.href = window.CONFIG["logout"] : navigate(toHref("/")) | ||||
|             window.CONFIG["logout"] ? location.href = window.CONFIG["logout"] : navigate(toHref("/")); | ||||
|         }), | ||||
|         rxjs.catchError(ctrlError(render)), | ||||
|     )); | ||||
|  | ||||
| @ -1,11 +1,15 @@ | ||||
| import { createElement, createRender } from "../../lib/skeleton/index.js"; | ||||
| import { createElement, createRender, onDestroy } from "../../lib/skeleton/index.js"; | ||||
| import { toHref } from "../../lib/skeleton/router.js"; | ||||
| import rxjs, { effect, onLoad, onClick } from "../../lib/rx.js"; | ||||
| import { animate } from "../../lib/animate.js"; | ||||
| import { extname } from "../../lib/path.js"; | ||||
| import { loadCSS } from "../../helpers/loader.js"; | ||||
| import { qs } from "../../lib/dom.js"; | ||||
| import { createLoader } from "../../components/loader.js"; | ||||
| import notification from "../../components/notification.js"; | ||||
| import t from "../../locales/index.js"; | ||||
| import ctrlError from "../ctrl_error.js"; | ||||
| import { Chromecast } from "../../model/chromecast.js"; | ||||
|  | ||||
| import { transition, getFilename, getDownloadUrl } from "./common.js"; | ||||
|  | ||||
| @ -44,6 +48,7 @@ export default function(render) { | ||||
|         buttonDownload(getFilename(), getDownloadUrl()), | ||||
|         buttonFullscreen(qs($page, ".component_image_container")), | ||||
|         buttonInfo({ toggle: toggleInfo }), | ||||
|         buttonChromecast(getFilename(), getDownloadUrl()), | ||||
|     ); | ||||
|  | ||||
|     effect(onLoad($photo).pipe( | ||||
| @ -85,6 +90,13 @@ export default function(render) { | ||||
|     componentPager(createRender(qs($page, ".component_pager"))); | ||||
| } | ||||
|  | ||||
| export function init() { | ||||
|     return Promise.all([ | ||||
|         loadCSS(import.meta.url, "./application_image.css"), | ||||
|         initPager(), initMetadata(), | ||||
|     ]); | ||||
| } | ||||
|  | ||||
| function buttonInfo({ toggle }) { | ||||
|     const $el = createElement(` | ||||
|         <span> | ||||
| @ -98,9 +110,51 @@ function buttonInfo({ toggle }) { | ||||
|     return $el; | ||||
| } | ||||
|  | ||||
| export function init() { | ||||
|     return Promise.all([ | ||||
|         loadCSS(import.meta.url, "./application_image.css"), | ||||
|         initPager(), initMetadata(), | ||||
|     ]); | ||||
| function buttonChromecast(filename, downloadURL) { | ||||
|     const context = Chromecast.context(); | ||||
|     if (!context) return; | ||||
|  | ||||
|     const chromecastSetup = (event) => { | ||||
|         switch (event.sessionState) { | ||||
|         case window.cast.framework.SessionState.SESSION_STARTED: | ||||
|             chromecastLoader(); | ||||
|             break; | ||||
|         } | ||||
|     }; | ||||
|     const chromecastLoader = () => { | ||||
|         const session = Chromecast.session(); | ||||
|         if (!session) return; | ||||
|  | ||||
|         const link = Chromecast.createLink("/" + toHref(downloadURL)); | ||||
|         const media = new window.chrome.cast.media.MediaInfo( | ||||
|             link, | ||||
|             window.CONFIG.mime[extname(filename)], | ||||
|         ); | ||||
|         media.metadata = new window.chrome.cast.media.PhotoMediaMetadata(); | ||||
|         media.metadata.title = filename; | ||||
|         media.metadata.images = [ | ||||
|             new window.chrome.cast.Image(location.origin + "/" + toHref("/assets/icons/photo.png")), | ||||
|         ]; | ||||
|         try { | ||||
|             const req = Chromecast.createRequest(media); | ||||
|             session.loadMedia(req); | ||||
|         } catch (err) { | ||||
|             console.error(err); | ||||
|             notification.error(t("Cannot establish a connection")); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     context.addEventListener( | ||||
|         window.cast.framework.CastContextEventType.SESSION_STATE_CHANGED, | ||||
|         chromecastSetup, | ||||
|     ); | ||||
|     onDestroy(() => context.removeEventListener( | ||||
|         window.cast.framework.CastContextEventType.SESSION_STATE_CHANGED, | ||||
|         chromecastSetup, | ||||
|     )); | ||||
|  | ||||
|     const media = Chromecast.media(); | ||||
|     if (media && media.media && media.media.mediaCategory === "IMAGE") chromecastLoader(); | ||||
|  | ||||
|     return document.createElement("google-cast-launcher"); | ||||
| } | ||||
|  | ||||
| @ -30,7 +30,6 @@ export default async function(render) { | ||||
|  | ||||
|     const map = window.L.map("map"); | ||||
|  | ||||
|  | ||||
|     const fileview = [getFilename()]; | ||||
|     for (let i=0; i<fileview.length; i++) { | ||||
|         await cat(fileview[i]).pipe(rxjs.mergeMap(async(content) => { | ||||
|  | ||||
							
								
								
									
										4
									
								
								public/global.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								public/global.d.ts
									
									
									
									
										vendored
									
									
								
							| @ -1,10 +1,12 @@ | ||||
| interface Window { | ||||
|     chrome: object; | ||||
|     chrome: any; | ||||
|     cast: any; | ||||
|     overrides: { | ||||
|         [key: string]: any; | ||||
|         "xdg-open"?: (mime: string) => void; | ||||
|     }; | ||||
|     CONFIG: Config; | ||||
|     BEARER_TOKEN?: string; | ||||
| } | ||||
|  | ||||
| interface Config { | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 MickaelK
					MickaelK