Skip to content

Commit

Permalink
feat: make some shit
Browse files Browse the repository at this point in the history
  • Loading branch information
d0kur0 committed Oct 21, 2023
1 parent a9aa75d commit dc1407b
Show file tree
Hide file tree
Showing 15 changed files with 550 additions and 366 deletions.
43 changes: 34 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,18 @@
"dependencies": {
"@hope-ui/solid": "^0.6.7",
"@nanostores/solid": "^0.4.2",
"@solid-primitives/masonry": "^0.0.4",
"@solid-primitives/scheduled": "^1.4.1",
"@solidjs/router": "^0.8.3",
"@stitches/core": "^1.2.8",
"bricks.js": "^1.8.0",
"electron-squirrel-startup": "^1.0.0",
"lodash": "^4.17.21",
"nanostores": "^0.9.3",
"solid-icons": "^1.0.12",
"solid-js": "^1.7.6",
"solid-mason": "^0.1.5",
"solid-transition-group": "^0.0.10",
"webm-grabber": "^1.1.1"
"webm-grabber": "^1.2.0"
},
"devDependencies": {
"@electron-forge/cli": "^6.4.2",
Expand Down
2 changes: 1 addition & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ function Routing() {
<Route path="/" component={PageDashBoard} />
<Route path="/list" component={PageListFiles} />
<Route path="/threads" component={PageThreads} />
<Route path="/thread/:threadId" component={PageListFiles} />
<Route path="/thread/:board/:threadId" component={PageListFiles} />
<Route path="/shuffle" component={PageShuffleFile} />
</Routes>
);
Expand Down
189 changes: 118 additions & 71 deletions src/components/FilePreview.tsx
Original file line number Diff line number Diff line change
@@ -1,104 +1,151 @@
import { File } from "webm-grabber";
import { Badge, Box, css, HStack, Spinner, Tag, useTheme } from "@hope-ui/solid";
import { createMemo, createSignal } from "solid-js";
import { getVendorName, isFileImage } from "../utils/grabbing";
import { Box, Spinner } from "@hope-ui/solid";
import { createEffect, createMemo, createSignal } from "solid-js";
import { ExtendedFile, isFileImage } from "../utils/grabbing";
import { JSX } from "solid-js";

type FilePreviewProps = {
file: File;
file: ExtendedFile;
onOpen?(): void;
fromThread?: boolean;
};

const overlayStyles = css({
top: 0,
left: 0,
const centerPositionStyles = {
top: "50%",
left: "50%",
position: "absolute",
transform: "translate(-50%, -50%)",
};

const mediaElementStyles: JSX.CSSProperties = {
width: "100%",
height: "100%",
display: "flex",
position: "absolute",
alignItems: "center",
borderRadius: "0px",
justifyContent: "center",
backgroundColor: "$neutral2",
});
top: 0,
left: 0,
"object-fit": "cover",
};

const badgeStyles = {
fontSize: "0.6rem",
display: "block",
backgroundColor: "rgba(54,54,54,0.87)",
padding: "2px 5px",
borderRadius: 5,
fontWeight: "bolder",
fontSize: "0.6em",
};

function stringLengthLimiter(string: string, maxLength = 36) {
return `${string.substring(0, maxLength)}${string.length > maxLength ? "..." : ""}`;
}

export function FilePreview(props: FilePreviewProps) {
const [isInViewport, setIsInViewport] = createSignal(true);

const isImage = createMemo(() => isFileImage(props.file));
const vendorNameOfFile = createMemo(() => getVendorName(props.file));

const width = createMemo(() => props.file.width);
const height = createMemo(() => props.file.height);

const [isLoading, setIsLoading] = createSignal(true);
const [isLoadingFailed, setIsLoadingFailed] = createSignal(false);

const [isHovered, setIsHovered] = createSignal(false);
let rootRef: HTMLDivElement;

createEffect(() => {
if (!rootRef) return;

const options = {
root: null,
rootMargin: "0px",
};

const observer = new IntersectionObserver(([element]) => {
setIsInViewport(element.isIntersecting);
}, options);

observer.observe(rootRef);

return () => observer.disconnect();
});

return (
<Box
as="button"
css={{
p: 0,
color: "$neutral10",
cursor: "pointer",
border: "none",
margin: 0,
shadow: `2xl`,
display: "flex",
position: "relative",
overflow: "hidden",
borderRadius: 8,
flexDirection: "column",
backgroundColor: "$neutral4",
}}
ref={rootRef!}
css={{ "aspect-ratio": `${width()}/${height()}`, padding: "10px" }}
onClick={props.onOpen}
onMouseLeave={() => setIsHovered(false)}
onMouseEnter={() => setIsHovered(true)}
>
<Box
as="img"
alt="preview image"
css={{
width: "100%",
height: "20vw",
objectFit: "cover",
height: "100%",
cursor: "pointer",
position: "relative",
}}
src={isHovered() && isImage() ? props.file.url : props.file.previewUrl}
onLoad={() => setIsLoading(false)}
onError={() => setIsLoadingFailed(true)}
/>

<Box css={{ position: "absolute", top: 5, left: 5, display: "flex", gap: 8 }}>
<Badge colorScheme={isImage() ? "neutral" : "primary"} css={badgeStyles}>
{isImage() ? "Image" : "Video"}
</Badge>

<Badge colorScheme={vendorNameOfFile() ? "warning" : "success"} css={badgeStyles}>
{vendorNameOfFile()}
</Badge>

<Badge colorScheme="accent" css={badgeStyles}>
{props.file.name}
</Badge>
</Box>
>
{isInViewport() && (
<>
<Box css={{ position: "absolute", top: 3, left: 3, zIndex: 12, display: "flex", gap: 6 }}>
<Box css={badgeStyles}>{isImage() ? "image" : "video"}</Box>
{props.fromThread || (
<>
<Box css={badgeStyles}>/{props.file.rootThread.board}/</Box>
<Box css={badgeStyles}>{props.file.rootThread.vendorName}</Box>
</>
)}
</Box>

<Box css={{ position: "absolute", bottom: 5, left: 5 }}>
<Badge colorScheme="info" css={badgeStyles}>
{stringLengthLimiter(props.file.rootThread.subject || "")}
</Badge>
</Box>
<Box
css={{
gap: 6,
left: 0,
bottom: 3,
zIndex: 12,
display: "flex",
position: "absolute",
maxWidth: "100%",
}}
>
<Box css={{ width: "100%", maxWidth: "100%", overflow: "hidden", padding: "0 5px" }}>
<Box
css={{
...badgeStyles,
width: "99%",
overflow: "hidden",
whiteSpace: "nowrap",
textOverflow: "ellipsis",
}}
>
{props.file.name}
</Box>
</Box>
</Box>

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

{isLoading() && (
<Box class={overlayStyles()}>
<Spinner />
</Box>
)}
{isImage() || (
<video
src={`${props.file.url}#t=0.1`}
style={mediaElementStyles}
preload="metadata"
onError={() => setIsLoadingFailed(true)}
onLoadedData={() => setIsLoading(false)}
/>
)}

{isLoadingFailed() && <Box class={overlayStyles()}>Loading failed</Box>}
{isLoading() && (
<Box css={centerPositionStyles}>
<Spinner />
</Box>
)}

{isLoadingFailed() && <Box css={centerPositionStyles}>Loading failed</Box>}
</>
)}
</Box>
</Box>
);
}
Loading

0 comments on commit dc1407b

Please sign in to comment.