import React, { useEffect, useReducer, useRef } from "react"; import filepath from "path"; import ReactCSSTransitionGroup from "react-addons-css-transition-group"; import { MenuBar } from "./menubar"; import { Bundle, Icon, NgIf, Loader, EventEmitter, EventReceiver } from "../../components/"; import { alert, randomString, notify, getMimeType, currentShare } from "../../helpers/"; import { Chromecast } from "../../model/"; import { Pager } from "./pager"; import { t } from "../../locales/"; import "./imageviewer.scss"; import "./pager.scss"; const SmallExif = (props) => ( {(Comp) => } ); const LargeExif = (props) => ( {(Comp) => } ); export function ImageViewerComponent({ filename, data, path, subscribe, unsubscribe }) { const [state, setState] = useReducer((s, a) => { return { ...s, ...a }; }, { preload: null, refresh: 0, show_exif: false, is_loaded: false, draggable: false, }); const $container = useRef(); const refresh = () => setState({ refresh: state.refresh + 1 }); const shortcut = (e) => { if (e.keyCode === 27) setState({ show_exif: false }); else if (e.keyCode === 73) setState({ show_exif: !state.show_exif }); }; useEffect(() => { setState({ is_loaded: false }); subscribe("media::preload", (preload) => { setState({ preload: preload }); }); document.addEventListener("webkitfullscreenchange", refresh); document.addEventListener("mozfullscreenchange", refresh); document.addEventListener("fullscreenchange", refresh); document.addEventListener("keydown", shortcut); return () => { unsubscribe("media::preload"); document.removeEventListener("webkitfullscreenchange", refresh); document.removeEventListener("mozfullscreenchange", refresh); document.removeEventListener("fullscreenchange", refresh); document.removeEventListener("keydown", shortcut); }; }, [data]); const chromecastSetup = (event) => { switch (event.sessionState) { case cast.framework.SessionState.SESSION_STARTED: chromecastHandler(); break; } }; const chromecastHandler = (event) => { const session = Chromecast.session(); if (!session) return; const link = Chromecast.createLink(data); const media = new chrome.cast.media.MediaInfo( link, getMimeType(filename), ); media.metadata = new chrome.cast.media.PhotoMediaMetadata(); media.metadata.title = filename; media.metadata.images = [ new chrome.cast.Image(Chromecast.origin() + "/assets/icons/photo.png"), ]; Chromecast.createRequest(media) .then((req) => session.loadMedia(req)) .catch((err) => { console.error(err) notify.send(t("Cannot establish a connection"), "error"); }); }; useEffect(() => { const context = Chromecast.context(); if (!context) return; document.getElementById("chromecast-target").append(document.createElement("google-cast-launcher")); context.addEventListener( cast.framework.CastContextEventType.SESSION_STATE_CHANGED, chromecastSetup, ); chromecastHandler(); return () => { context.removeEventListener( cast.framework.CastContextEventType.SESSION_STATE_CHANGED, chromecastSetup, ); }; }, []); const hasExif = (fname) => { const ext = filepath.extname(fname).toLowerCase().substring(1); return ["jpg", "jpeg", "tiff", "tif"].indexOf(ext) !== -1; }; const toggleExif = () => { if (window.innerWidth < 580) { alert.now(); } else { setState({ show_exif: !state.show_exif, }); } }; const requestFullScreen = () => { if ("webkitRequestFullscreen" in document.body) { $container.current.webkitRequestFullscreen(); } else if ("mozRequestFullScreen" in document.body) { $container.current.mozRequestFullScreen(); } }; return (
setState({ is_loaded: true })} url={data} />
{ t("Info") }
setState({ draggable: files.length > 1 ? true : false })} next={(e) => setState({ preload: e })} />
); } export const ImageViewer = EventReceiver(EventEmitter(ImageViewerComponent)); class ImageFancyComponent extends React.Component { constructor(props) { super(props); this.state = { isLoading: true, isError: false, drag_init: { x: null, t: null }, drag_current: { x: null, t: null }, hasAction: false, }; this.img = new Image(); this.img.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="; } UNSAFE_componentWillReceiveProps(nextProp) { if (nextProp.url !== this.props.url) { this.setState({ isLoading: true, isError: false, drag_current: { x: 0 }, hasAction: false, }); } } onLoad() { this.setState({ isLoading: false }); this.props.onLoad(); } onError(w) { this.setState({ isError: true }); } imageDragStart(e) { if(!this.props.draggable) return; const t = new Date(); if (e.touches) { this.setState({ drag_init: { x: e.touches[0].clientX, t: t }, hasAction: true, }); } else { this.setState({ drag_init: { x: e.pageX, t: t }, hasAction: true, }); } if (e.dataTransfer) e.dataTransfer.setDragImage(this.img, 0, 0); } imageDragEnd(e) { const drag_end = { x: function(dragX, touch) { if (dragX !== null) return dragX; if (touch && touch[0]) { return touch[0].clientX; } return 0; }(e.pageX || null, e.changedTouches || null), t: new Date(), }; const direction = function(x_current, x_init) { if (x_current.t - x_init.t > 200 && Math.abs(x_current.x - x_init.x) < (window.innerWidth < 500 ? window.innerWidth / 3 : 250)) { return "neutral"; } return x_current.x > x_init.x ? "right" : "left"; }(drag_end, this.state.drag_init); if (direction === "left") { return this.setState({ drag_current: { x: - window.innerWidth }, hasAction: false, }, () => { this.props.emit("media::next"); }); } else if (direction === "right") { return this.setState({ drag_current: { x: + window.innerWidth }, hasAction: false, }, () => { this.props.emit("media::previous"); }); } return this.setState({ drag_current: { x: 0 }, hasAction: false, }); } imageDrag(e) { if (e.pageX > 0) { this.setState({ drag_current: { x: e.pageX - this.state.drag_init.x }, }); } else if (e.touches && e.touches[0].clientX > 0) { this.setState({ drag_current: { x: e.touches[0].clientX - this.state.drag_init.x }, }); } } render() { if (this.state.isError) { return (
{ t("Can't load this picture") }
); } if (this.state.isLoading) { return (
); } return (
); } } const ImageFancy = EventEmitter(ImageFancyComponent); function Img({ src, ...props }) { const image_url = (url, size) => { return url+"&size="+parseInt(Math.max(window.innerWidth*size, window.innerHeight*size)); }; if (!src) return null; return ( ); }