Skip to content

Commit

Permalink
renamed some things and remade collection classes
Browse files Browse the repository at this point in the history
  • Loading branch information
fekoneko committed Jul 24, 2024
1 parent cfc59a2 commit a30c35e
Show file tree
Hide file tree
Showing 28 changed files with 202 additions and 434 deletions.
4 changes: 2 additions & 2 deletions src-tauri/src/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub struct Work {
pub struct ImageAsset {
name: String,
path: String,
image_dimensions: ImageDimensions,
dimensions: ImageDimensions,
}

#[derive(serde::Serialize)]
Expand Down Expand Up @@ -287,7 +287,7 @@ fn add_asset(asset: &PathBuf, work: &mut Work) {
work.assets.push(ImageAsset {
name: asset_name.to_string_lossy().to_string(),
path: asset.to_string_lossy().to_string(),
image_dimensions: ImageDimensions {
dimensions: ImageDimensions {
width: asset_width,
height: asset_height,
},
Expand Down
2 changes: 1 addition & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { WorksViewer } from '@/components/layout/works-viewer/WorksViewer';
import { CollectionProvider } from '@/contexts/CollectionContext';
import { SearchProvider } from '@/contexts/SearchContext';
import { ThemeButton } from '@/components/layout/ThemeButton';
import { useLocalStorage } from '@/hooks/useLocalStorage';
import { useLocalStorage } from '@/hooks/use-local-storage';
import { FC, useCallback } from 'react';

export type Theme = 'light' | 'dark';
Expand Down
16 changes: 6 additions & 10 deletions src/components/layout/FavoriteButton.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,19 @@
import { SearchContext } from '@/contexts/SearchContext';
import { useKeyboardEvent } from '@/hooks/useKeyboardEvent';
import { useKeyboardEvent } from '@/hooks/use-keyboard-event';
import { FC, useCallback, useContext, useEffect, useState } from 'react';

export const FavoriteButton: FC = () => {
const { search, setSearch } = useContext(SearchContext);
const [prevSearchRequest, setPrevSearchRequest] = useState('');

const toggleFavorites = useCallback(
() =>
setSearch((prev) => ({
request: prev?.request === '#favorites' ? prevSearchRequest : '#favorites',
mode: prev?.mode ?? 'all',
})),
() => setSearch((prev) => (prev === '#favorites' ? prevSearchRequest : '#favorites')),
[setSearch, prevSearchRequest],
);

useEffect(() => {
if (!search || search.request === '#favorites') return;
setPrevSearchRequest(search.request);
if (search === '#favorites') return;
setPrevSearchRequest(search);
}, [search]);

useKeyboardEvent(
Expand All @@ -37,9 +33,9 @@ export const FavoriteButton: FC = () => {
<button
role="button"
onClick={toggleFavorites}
className="hover:bg-text/10 focus:bg-text/10 rounded-full px-[0.58rem] py-2 text-lg focus:outline-none"
className="rounded-full px-[0.58rem] py-2 text-lg hover:bg-text/10 focus:bg-text/10 focus:outline-none"
>
{search?.request === '#favorites' ? '❌' : '⭐'}
{search === '#favorites' ? '❌' : '⭐'}
</button>
);
};
4 changes: 2 additions & 2 deletions src/components/layout/header/CollectionButton.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { FC, useCallback, useContext, useEffect, useRef } from 'react';
import { CollectionContext } from '@/contexts/CollectionContext';
import { useLocalStorage } from '@/hooks/useLocalStorage';
import { useKeyboardEvent } from '@/hooks/useKeyboardEvent';
import { useLocalStorage } from '@/hooks/use-local-storage';
import { useKeyboardEvent } from '@/hooks/use-keyboard-event';

export const CollectionButton: FC = () => {
const { collection, loadCollection } = useContext(CollectionContext);
Expand Down
38 changes: 7 additions & 31 deletions src/components/layout/header/Searchbar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { SearchContext } from '@/contexts/SearchContext';
import { useKeyboardEvent } from '@/hooks/useKeyboardEvent';
import { useWanakana } from '@/hooks/useWanakana';
import { useKeyboardEvent } from '@/hooks/use-keyboard-event';
import { useWanakana } from '@/hooks/use-wanakana';
import { FC, useContext, useRef, useState } from 'react';

export const Searchbar: FC = () => {
Expand All @@ -11,14 +11,6 @@ export const Searchbar: FC = () => {

useWanakana(inputRef, {}, kanaConversion);

const toggleSearchMode = () => {
setSearch((prev) => ({
request: prev?.request ?? '',
mode: prev?.mode === 'all' ? 'works' : prev?.mode === 'works' ? 'users' : 'all',
}));
inputRef.current?.focus();
};

const toggleKanaConversion = () => {
setKanaConversion((prev) => !prev);
inputRef.current?.focus();
Expand All @@ -30,8 +22,6 @@ export const Searchbar: FC = () => {

useKeyboardEvent('keydown', 'Escape', () => inputRef.current?.blur(), [inputRef.current]);

useKeyboardEvent('keyup', 'Backquote', toggleSearchMode, [], { alt: true });

useKeyboardEvent('keyup', 'Backquote', toggleKanaConversion, [], { control: true });

return (
Expand All @@ -40,36 +30,22 @@ export const Searchbar: FC = () => {
e.preventDefault();
inputRef.current?.blur();
}}
className="border-text-header flex min-w-0 grow basis-40 gap-1 rounded-full border-2"
className="flex min-w-0 grow basis-40 gap-1 rounded-full border-2 border-text-header"
>
<input
ref={inputRef}
placeholder={isInputInFocus ? 'Search here' : 'Press / to search'}
className="placeholder:text-text-header/80 min-w-0 grow bg-transparent py-1.5 pl-3 focus:outline-none"
value={search?.request ?? ''}
onInput={(e) =>
setSearch((prev) => ({
request: (e.target as HTMLInputElement).value,
mode: prev?.mode ?? 'all',
}))
}
className="min-w-0 grow bg-transparent py-1.5 pl-3 placeholder:text-text-header/80 focus:outline-none"
value={search}
onInput={(e) => setSearch((e.target as HTMLInputElement).value)}
onFocus={() => setIsInputInFocus(true)}
onBlur={() => setIsInputInFocus(false)}
/>

<button
onClick={toggleSearchMode}
type="button"
className="hover:bg-text-header/20 focus:bg-text-header/20 rounded-l-3xl rounded-r-md pl-3 pr-2 focus:outline-none"
title="Toggle search mode"
>
{search?.mode === 'works' ? 'Works' : search?.mode === 'users' ? 'Users' : 'All'}
</button>
<div className="bg-text-header/40 my-2 w-[3px] rounded-full" />
<button
onClick={toggleKanaConversion}
type="button"
className="hover:bg-text-header/20 focus:bg-text-header/20 rounded-l-md rounded-r-3xl pl-2 pr-3 focus:outline-none"
className="rounded-l-md rounded-r-3xl pl-2 pr-3 hover:bg-text-header/20 focus:bg-text-header/20 focus:outline-none"
title="Toggle romaji-to-kana conversion"
>
{kanaConversion ? 'カ' : 'A'}
Expand Down
17 changes: 7 additions & 10 deletions src/components/layout/works-viewer/AssetImageView.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ImageAsset } from '@/lib/Collection';
import { ImageAsset } from '@/lib/collection';
import { FC, SVGProps, useEffect } from 'react';

export interface AssetImageViewProps extends SVGProps<SVGSVGElement> {
Expand All @@ -8,10 +8,10 @@ export interface AssetImageViewProps extends SVGProps<SVGSVGElement> {
export const AssetImageView: FC<AssetImageViewProps> = ({ asset, ...svgProps }) => {
useEffect(() => {
const imageElement = document.createElementNS('http://www.w3.org/2000/svg', 'image');
imageElement.setAttribute('id', asset.imageId);
imageElement.setAttribute('width', (asset.imageDimensions.width ?? 100).toString());
imageElement.setAttribute('height', (asset.imageDimensions.height ?? 100).toString());
imageElement.setAttribute('href', asset.mediaPath);
imageElement.setAttribute('id', asset.path);
imageElement.setAttribute('width', asset.dimensions.width.toString());
imageElement.setAttribute('height', asset.dimensions.height.toString());
imageElement.setAttribute('href', asset.path); // TODO: fix media path
imageElement.setAttribute('decoding', 'async');

let originElement = document.getElementById('images-origin');
Expand All @@ -27,11 +27,8 @@ export const AssetImageView: FC<AssetImageViewProps> = ({ asset, ...svgProps })
}, [asset]);

return (
<svg
{...svgProps}
viewBox={`0 0 ${asset.imageDimensions.width ?? 100} ${asset.imageDimensions.height ?? 100}`}
>
<use href={'#' + asset.imageId} />
<svg {...svgProps} viewBox={`0 0 ${asset.dimensions.width} ${asset.dimensions.height}`}>
<use href={'#' + asset.path} />
</svg>
);
};
10 changes: 5 additions & 5 deletions src/components/layout/works-viewer/WorkCard.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Fragment } from 'react/jsx-runtime';
import { Work } from '@/lib/Collection';
import { Work } from '@/lib/collection';
import { FC, RefObject, memo, useEffect, useRef } from 'react';
import { AnimateScroll } from '@/hooks/useAnimateScroll';
import { AnimateScroll } from '@/hooks/use-animate-scroll';
import { AssetImageView } from '@/components/layout/works-viewer/AssetImageView';

interface WorkCardContents {
Expand All @@ -21,15 +21,15 @@ const WorkCardContents: FC<WorkCardContents> = memo(({ work }: WorkCardContents)
/>
)}
</div>
<p className="border-text/50 bg-background text-text absolute right-0 top-0 -mr-2 -mt-0.5 rounded-lg border px-2 shadow-md transition-colors [:hover>&]:invisible">
<p className="absolute right-0 top-0 -mr-2 -mt-0.5 rounded-lg border border-text/50 bg-background px-2 text-text shadow-md transition-colors [:hover>&]:invisible">
x{work.assets.length}
</p>
</div>
) : (
<div />
)}
<div className="overflow-hidden p-2 text-left">
<h2 className="text-text-accent whitespace-nowrap text-lg font-bold">
<h2 className="whitespace-nowrap text-lg font-bold text-text-accent">
{work.title ?? 'Untitled'}
</h2>
<p className="mb-2 whitespace-nowrap text-sm font-semibold">
Expand Down Expand Up @@ -92,7 +92,7 @@ export const WorkCard: FC<WorkCardProps> = memo(
onClick={() => selectIndex(index)}
tabIndex={-1}
className={
'border-text/30 grid w-full grid-cols-[3fr_8fr] items-center gap-2 rounded-xl border-2 p-1 shadow-md focus:outline-none' +
'grid w-full grid-cols-[3fr_8fr] items-center gap-2 rounded-xl border-2 border-text/30 p-1 shadow-md focus:outline-none' +
(active ? ' border-text/60 bg-text/20' : ' hover:bg-text/10')
}
>
Expand Down
14 changes: 7 additions & 7 deletions src/components/layout/works-viewer/WorkDetails.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { CollectionContext } from '@/contexts/CollectionContext';
import { useAnimateScroll } from '@/hooks/useAnimateScroll';
import { useKeyboardEvent } from '@/hooks/useKeyboardEvent';
import { Work } from '@/lib/Collection';
import { useAnimateScroll } from '@/hooks/use-animate-scroll';
import { useKeyboardEvent } from '@/hooks/use-keyboard-event';
import { Work } from '@/lib/collection';
import { FC, Fragment, useContext, useEffect, useRef, useState } from 'react';

interface WorkDetailsContentsProps {
Expand Down Expand Up @@ -119,11 +119,11 @@ const WorkDetailsContents: FC<WorkDetailsContentsProps> = ({ work, expanded }) =
</tr>
)}

{work.dateTime && (
{work.uploadTime && (
<tr>
<td className="align-top">uploaded: </td>
<td>
<p>{work.dateTime.toDateString()}</p>
<p>{work.uploadTime}</p>
</td>
</tr>
)}
Expand All @@ -141,12 +141,12 @@ const WorkDetailsContents: FC<WorkDetailsContentsProps> = ({ work, expanded }) =
</tr>
)}

{work.pageUrl && (
{work.url && (
<tr>
<td />
<td>
<a
href={work.pageUrl}
href={work.url}
target="blank"
tabIndex={expanded ? 0 : -1}
className="text-blue-500 hover:underline"
Expand Down
12 changes: 6 additions & 6 deletions src/components/layout/works-viewer/WorkView.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useKeyboardEvent } from '@/hooks/useKeyboardEvent';
import { useTimeout } from '@/hooks/useTimeout';
import { Work } from '@/lib/Collection';
import { useKeyboardEvent } from '@/hooks/use-keyboard-event';
import { useTimeout } from '@/hooks/use-timeout';
import { Work } from '@/lib/collection';
import { FC, useEffect, useState } from 'react';
import { AssetImageView } from '@/components/layout/works-viewer/AssetImageView';

Expand Down Expand Up @@ -61,20 +61,20 @@ export const WorkView: FC<WorkViewProps> = ({ work, fullscreenMode }) => {
className={
'relative z-20 flex grow basis-0 items-center justify-center overflow-hidden shadow-lg transition-[border-radius] duration-1000' +
(!controlsShown ? ' cursor-none' : '') +
(!fullscreenMode ? ' border-text/30 rounded-xl border-2' : '')
(!fullscreenMode ? ' rounded-xl border-2 border-text/30' : '')
}
>
{work?.assets?.length && work.assets[pageNumber] ? (
<>
<AssetImageView asset={work.assets[pageNumber]} className="z-30 size-full" />

<div className="absolute z-20 flex size-full items-center justify-center">
<div className="bg-background absolute size-full" />
<div className="absolute size-full bg-background" />
<AssetImageView
asset={work.assets[pageNumber]}
className="size-full scale-[3] blur-[0.4rem]"
/>
<div className="bg-background/40 absolute size-full" />
<div className="absolute size-full bg-background/40" />
</div>

<button
Expand Down
21 changes: 9 additions & 12 deletions src/components/layout/works-viewer/WorksList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ import {
useRef,
useState,
} from 'react';
import { useWorks } from '@/hooks/useWorks';
import { Work } from '@/lib/Collection';
import { useWorks } from '@/hooks/use-works';
import { Work } from '@/lib/collection';
import { SearchContext } from '@/contexts/SearchContext';
import { useKeyboardEvent } from '@/hooks/useKeyboardEvent';
import { useKeyboardEvent } from '@/hooks/use-keyboard-event';
import { WorkCard } from '@/components/layout/works-viewer/WorkCard';
import { RenderInViewport } from '@/components/render/RenderInViewport';
import { useTimeout } from '@/hooks/useTimeout';
import { useAnimateScroll, AnimateScroll } from '@/hooks/useAnimateScroll';
import { useTimeout } from '@/hooks/use-timeout';
import { useAnimateScroll, AnimateScroll } from '@/hooks/use-animate-scroll';
import { CollectionContext } from '@/contexts/CollectionContext';

const workCardChunkSize = 20;
Expand Down Expand Up @@ -137,7 +137,7 @@ const WorkListCards: FC<WorkListCardsProps> = memo(
const workIndex = chunkIndex * workCardChunkSize + workIndexInChunk;
return (
<WorkCard
key={work.path}
key={work.path} // TODO: relativePath
work={work}
index={workIndex}
selectIndex={setSelectedIndex}
Expand All @@ -161,10 +161,7 @@ interface WorksListProps {
export const WorksList: FC<WorksListProps> = ({ selectWork }) => {
const { search } = useContext(SearchContext);
const { collection } = useContext(CollectionContext);
const works = useWorks(
search,
useCallback((error: unknown) => console.error(error), []),
);
const works = useWorks(search);

const [scrolledToTheTop, setScrolledToTheTop] = useState(true);
const [scrolledToTheBottom, setScrolledToTheBottom] = useState(false);
Expand Down Expand Up @@ -194,7 +191,7 @@ export const WorksList: FC<WorksListProps> = ({ selectWork }) => {
>
<div className="flex flex-col gap-2 py-2 [direction:ltr]">
<WorkListCards
works={works}
works={works ?? []}
selectWork={selectWork}
scrollContainerRef={scrollContainerRef}
animateScroll={animateScroll}
Expand All @@ -203,7 +200,7 @@ export const WorksList: FC<WorksListProps> = ({ selectWork }) => {
</div>
</div>

{search?.request === '#favorites' && (
{search === '#favorites' && (
<button
onClick={() => collection?.favorites.clear()}
className="pb-2 hover:text-text-accent hover:underline focus:text-text-accent focus:outline-none"
Expand Down
4 changes: 2 additions & 2 deletions src/components/layout/works-viewer/WorksViewer.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { WorksList } from '@/components/layout/works-viewer/WorksList';
import { WorkView } from '@/components/layout/works-viewer/WorkView';
import { FC, useCallback, useEffect, useRef, useState } from 'react';
import { Work } from '@/lib/Collection';
import { Work } from '@/lib/collection';
import { WorkDetails } from '@/components/layout/works-viewer/WorkDetails';
import { animated, useSpring } from '@react-spring/web';
import { useKeyboardEvent } from '@/hooks/useKeyboardEvent';
import { useKeyboardEvent } from '@/hooks/use-keyboard-event';
import { FavoriteButton } from '@/components/layout/FavoriteButton';

type TransitionState = 'preview' | 'transition' | 'fullscreen';
Expand Down
6 changes: 3 additions & 3 deletions src/contexts/CollectionContext.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { PropsWithChildren, createContext, useCallback, useState } from 'react';
import { Collection } from '@/lib/Collection';
import { Collection, createCollection } from '@/lib/collection/collection';

interface CollectionContextValue {
collection: Collection | undefined;
Expand All @@ -11,8 +11,8 @@ export const CollectionContext = createContext({} as CollectionContextValue);
export const CollectionProvider = ({ children }: PropsWithChildren) => {
const [collection, setCollection] = useState<Collection>();

const loadCollection = useCallback((collectionPath: string) => {
setCollection(new Collection(collectionPath));
const loadCollection = useCallback(async (collectionPath: string) => {
setCollection(await createCollection(collectionPath));
}, []);

return (
Expand Down
Loading

0 comments on commit a30c35e

Please sign in to comment.