import React from "react"; import _ from "lodash"; import {Button as SButton, Dropdown, Header as SHeader, Icon, Image,} from "semantic-ui-react"; import {TagsSelector} from "../Tags"; import {encodeMediaPath, isSupportedArchive, useLocalStorage} from "./Common"; import {getFile, tagFileGroup, untagFileGroup} from "../api"; import {ArchivePreviewContent} from "./ArchivePreview"; import {CbzViewer} from "./CbzViewer"; import {StlViewer} from "react-stl-viewer"; import {Button, Modal} from "./Theme"; import {toast} from "react-semantic-toasts-2"; import {useOneQuery} from "../hooks/customHooks"; import {ShareButton} from "./Share"; import {AddToPlaylistButton} from "./AddToPlaylist"; import {pathDirectory} from "./FileBrowser"; import {InlineErrorBoundary} from "./ErrorBoundary"; import {useLocation} from "react-router"; // Routes where file views should not be tracked const EXCLUDED_TRACKING_ROUTES = [ /^\/videos\/video\//, /^\/videos\/channel\/[^/]+\/video\//, /^\/archive\/\d+/ ]; function shouldSkipTracking(pathname) { return EXCLUDED_TRACKING_ROUTES.some(pattern => pattern.test(pathname)); } function getMediaPathURL(previewFile) { if (previewFile['primary_path']) { return `/media/${encodeMediaPath(previewFile['primary_path'])}`; } else { return `/media/${encodeMediaPath(previewFile['path'])}`; } } function getDownloadPathURL(previewFile) { if (previewFile['primary_path']) { return `/download/${encodeMediaPath(previewFile['primary_path'])}`; } else { return `/download/${encodeMediaPath(previewFile['path'])}`; } } // PrusaSlicer is omitted because it only downloads from domains whitelisted by Prusa // (printables.com, thingiverse.com, cults3d.com), so it cannot fetch from a WROLPi. // Bambu Studio asks the user to confirm because a WROLPi is not one of its trusted sites. export const SLICERS = [ {key: 'orcaslicer', text: 'Orca Slicer', scheme: 'orcaslicer'}, {key: 'bambustudio', text: 'Bambu Studio', scheme: 'bambustudio'}, {key: 'cura', text: 'Cura', scheme: 'cura'}, ]; export function getSlicerURL(previewFile, scheme) { // Slicers register their own URL scheme and download the file themselves, so the // file parameter must be an absolute URL reachable from the user's computer. const absoluteURL = new URL(getMediaPathURL(previewFile), window.location.origin).href; return `${scheme}://open?file=${encodeURIComponent(absoluteURL)}`; } function OpenInSlicerButton({previewFile}) { // Browsers cannot report which slicers are installed, so remember the last one used. const [slicerKey, setSlicerKey] = useLocalStorage('preferredSlicer', SLICERS[0].key); const slicer = SLICERS.find(s => s.key === slicerKey) || SLICERS[0]; return }> {SLICERS.map(s => { // Navigate programmatically so keyboard activation (which may not // follow the href) still launches the slicer. if (e) e.preventDefault(); setSlicerKey(s.key); window.location.assign(getSlicerURL(previewFile, s.scheme)); }}/>)} } function getEpubViewerURL(previewFile) { let url = previewFile['primary_path'] ?? previewFile['path']; return `/epub/epub.html?url=/media/${encodeMediaPath(url)}` } function getIframePreviewModal(previewFile, url) { url = url || getMediaPathURL(previewFile); return