Skip to content

Commit

Permalink
feat: make player more friendly, add loop button, and auto next then …
Browse files Browse the repository at this point in the history
…disabled \ loading error, optimize render files list (use previewImage instead of fullsize)
  • Loading branch information
d0kur0 committed Jan 26, 2024
1 parent 693580b commit 388c72a
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 37 deletions.
36 changes: 33 additions & 3 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Route, Routes } from "@solidjs/router";
import { NotificationsProvider, HopeProvider, Box } from "@hope-ui/solid";
import { Link, Route, Routes } from "@solidjs/router";

Check failure on line 1 in src/App.tsx

View workflow job for this annotation

GitHub Actions / Lint code with ESLint

'Link' is defined but never used
import { NotificationsProvider, HopeProvider, Box, Heading, Anchor, Button } from "@hope-ui/solid";
import { useStore } from "@nanostores/solid";
import { $files } from "./stores/media";
import { ErrorBoundary, Match, onMount, Switch } from "solid-js";
Expand All @@ -14,6 +14,36 @@ import { ViewPort } from "./components/ViewPort";

const { ipcRenderer } = window.require("electron");

function ErrorScreen(props: { err: Error }) {
return (
<Box css={{ p: 16, px: 42 }}>
<Heading css={{ fontSize: "2rem" }}>Какая-то ошибка</Heading>

<Box css={{ mt: 24 }}>
Какая-то рантайм ошибка, скорее всего потому, что разработчик сделал что-то хуево. <br />
Если возникает часто и хочется фикса, можно создать ишью{" "}
<Anchor css={{ color: "$accent10" }} external href="https://github.com/d0kur0/webm-desktop/issues">
гитхабе
</Anchor>{" "}
программы.
</Box>

<Button onClick={location.reload} css={{ mt: 24 }} colorScheme="warning">
Перезагрузить страницу
</Button>

<Heading css={{ fontSize: "1.5rem", mt: 24 }}>Отладочная инфа</Heading>

<Box css={{ mt: 19, backgroundColor: "$neutral5", p: 15, borderRadius: 15 }}>
<Box>{props.err?.name}</Box>
<Box>{props.err?.cause as never}</Box>
<Box>{props.err?.message}</Box>
<Box>{props.err?.stack}</Box>
</Box>
</Box>
);
}

function Routing() {
return (
<Routes>
Expand All @@ -38,7 +68,7 @@ export function App() {
<NotificationsProvider placement="bottom">
<WindowBar />

<ErrorBoundary fallback={(err) => <Box css={{ p: 16 }}>{err.toString()}</Box>}>
<ErrorBoundary fallback={(err) => <ErrorScreen err={err} />}>
<Switch>
<Match when={media().loading}>
<MediaLoading />
Expand Down
26 changes: 7 additions & 19 deletions src/components/FilePreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,25 +116,13 @@ export function FilePreview(props: FilePreviewProps) {
</Box>
</Box>

{isImage() && (
<img
src={props.file.url}
alt="preview image"
style={mediaElementStyles}
onLoad={() => setIsLoading(false)}
onError={() => setIsLoadingFailed(true)}
/>
)}

{isImage() || (
<video
src={`${props.file.url}#t=0.1`}
style={mediaElementStyles}
preload="metadata"
onError={() => setIsLoadingFailed(true)}
onLoadedData={() => setIsLoading(false)}
/>
)}
<img
src={props.file.previewUrl}
alt="preview image"
style={mediaElementStyles}
onLoad={() => setIsLoading(false)}
onError={() => setIsLoadingFailed(true)}
/>

{isLoading() && (
<Box css={centerPositionStyles}>
Expand Down
84 changes: 69 additions & 15 deletions src/components/Player.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { Box, Button, ButtonGroup, Spinner } from "@hope-ui/solid";
import { Box, Button, ButtonGroup, Spinner, Tooltip } from "@hope-ui/solid";
import { AiOutlineCloudDownload } from "solid-icons/ai";
import { FaRegularCopy } from "solid-icons/fa";
import { FaSolidVolumeHigh } from "solid-icons/fa";
import { TbPlayerTrackNextFilled, TbPlayerTrackPrevFilled } from "solid-icons/tb";
import { createEffect, createMemo, createSignal, JSX } from "solid-js";
import { createEffect, createMemo, createSignal, JSX, onMount } from "solid-js";
import { ExtendedFile, isFileImage } from "../utils/grabbing";
import { VsDebugPause, VsPlay } from "solid-icons/vs";
import { RiSystemLoopLeftFill } from "solid-icons/ri";

function formatSeconds(seconds: number) {
if (isNaN(seconds)) return "...";
Expand All @@ -16,6 +17,7 @@ function formatSeconds(seconds: number) {

export function Player(props: { file: ExtendedFile; onNext?: () => void; onPrev?: () => void }) {
const [getError, setError] = createSignal(false);
const [getIsLoop, setIsLoop] = createSignal(!!localStorage.loop || false);
const [getPaused, setPaused] = createSignal(true);
const [getVolume, setVolume] = createSignal(localStorage.volume !== undefined ? +localStorage.volume : 0.5);
const [getLoading, setLoading] = createSignal(true);
Expand All @@ -26,6 +28,10 @@ export function Player(props: { file: ExtendedFile; onNext?: () => void; onPrev?

let videoRef: HTMLVideoElement;

onMount(() => {
videoRef && (videoRef.volume = getVolume());
});

const togglePaused = () => {
videoRef.paused ? videoRef.play() : videoRef.pause();
};
Expand Down Expand Up @@ -63,29 +69,64 @@ export function Player(props: { file: ExtendedFile; onNext?: () => void; onPrev?
link.remove();
};

const toggleIsLoop = () => {
getIsLoop() ? localStorage.removeItem("loop") : localStorage.setItem("loop", "true");
setIsLoop((v) => !v);
};

const onPlay = () => {
setError(false);
setPaused(false);
};

const onLoadStart = () => {
setError(false);
setLoading(true);
};

const onCanPlay = () => {
setError(false);
setLoading(false);
};

const onPause = () => {
setPaused(true);
};

const onError = () => {
setError(true);
props.onNext?.();
};

const onEnded = () => {
getIsLoop() || props.onNext?.();
};

createEffect(() => {
videoRef && (videoRef.volume = getVolume());
});

createEffect(() => {
console.log(props.file);
setError(false);
setLoading(true);
});

return (
<Box css={{ height: "100%", backgroundColor: "#000", position: "relative" }}>
{isImage() || (
<Box
as="video"
autoplay
loop
onPlay={() => setPaused(false)}
onPause={() => setPaused(true)}
onError={() => setError(true)}
onCanPlay={() => setLoading(false)}
onLoadStart={() => setLoading(true)}
loop={getIsLoop()}
onPlay={onPlay}
onPause={onPause}
onError={onError}
onEnded={onEnded}
onCanPlay={onCanPlay}
onLoadStart={onLoadStart}
onTimeUpdate={handleChangeCurrentTime}
onDurationChange={handleChangeDuration}
as="video"
ref={videoRef!}
css={{ height: "100%", width: "100%", maxHeight: "100%" }}
src={props.file.url}
Expand Down Expand Up @@ -142,6 +183,15 @@ export function Player(props: { file: ExtendedFile; onNext?: () => void; onPrev?
<Button onClick={props.onNext}>
<TbPlayerTrackNextFilled />
</Button>
<Tooltip withArrow label={`Повтор видео: ${getIsLoop() ? "вкл" : "выкл"}`}>
<Button
disabled={isImage()}
colorScheme={getIsLoop() ? "danger" : "accent"}
onClick={toggleIsLoop}
>
<RiSystemLoopLeftFill />
</Button>
</Tooltip>
</ButtonGroup>

<Box css={{ fontWeight: "bolder" }}>{formatSeconds(getCurrentTime())}</Box>
Expand Down Expand Up @@ -181,12 +231,16 @@ export function Player(props: { file: ExtendedFile; onNext?: () => void; onPrev?
</Box>

<ButtonGroup size="sm" variant="outline" colorScheme="warning">
<Button onClick={handleDownload}>
<AiOutlineCloudDownload />
</Button>
<Button onClick={handleCopy}>
<FaRegularCopy />
</Button>
<Tooltip withArrow label={`Скачать файл`}>
<Button onClick={handleDownload}>
<AiOutlineCloudDownload />
</Button>
</Tooltip>
<Tooltip withArrow label={`Копировать ссылку`}>
<Button onClick={handleCopy}>
<FaRegularCopy />
</Button>
</Tooltip>
</ButtonGroup>
</Box>
</Box>
Expand Down

0 comments on commit 388c72a

Please sign in to comment.