Skip to content

Commit

Permalink
feat: dedicated mode toggle
Browse files Browse the repository at this point in the history
  • Loading branch information
dromzeh committed Feb 19, 2025
1 parent 1bf6ebf commit bf97201
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 43 deletions.
20 changes: 4 additions & 16 deletions src/app/[game]/[category]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export async function generateMetadata(props: Props): Promise<Metadata> {

return {
title: `${FormatGameName(response.game)} ${FormatCategoryName(response.asset)} • wanderer.moe`,
description: `${FormatGameName(response.game)} ${FormatCategoryName(response.asset)} assets on wanderer.moe`,
description: `Current ${FormatCategoryName(response.asset)} assets for ${FormatGameName(response.game)} available on wanderer.moe`,
};
}

Expand Down Expand Up @@ -119,24 +119,12 @@ export default async function GameCategoryPage(props: Readonly<Props>) {
<div>
<Alert>
<div className="flex flex-row items-center gap-2 p-1">
<img
src="https://cdn.wanderer.moe/cdn-cgi/image/width=64,height=64,quality=75/wuthering-waves/emotes/T_ChatEmo_C_01.png"
alt="ww emote"
className="w-12 h-12"
/>
<div className="flex flex-col">
<AlertDescription className="text-muted-foreground flex flex-col">
<p>
<span className="text-primary">
Single Click:
</span>{" "}
Select Asset
</p>
<p>
<span className="text-primary">
Double Click:
</span>{" "}
View Asset
Toggle between view and multi-select
mode from the Mode button. Tap or click
on an asset to view/select.
</p>
</AlertDescription>
</div>
Expand Down
24 changes: 15 additions & 9 deletions src/components/asset/asset-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { useAppDispatch, useAppSelector } from "~/redux/store";
import {
toggleAssetSelection,
isAssetSelected,
getSelectMode,
} from "~/redux/slice/asset-slice";

export function AssetItem({
Expand All @@ -35,21 +36,26 @@ export function AssetItem({

const dispatch = useAppDispatch();

const isSelected = isAssetSelected(
useAppSelector((state) => state.assets),
asset,
const isSelected = useAppSelector((state) =>
isAssetSelected(state.assets, asset),
);
const selectMode = useAppSelector((state) => getSelectMode(state.assets));

const handleClick = (e: React.MouseEvent) => {
e.stopPropagation();
if (selectMode) {
dispatch(toggleAssetSelection(asset));
} else {
setDialogOpen(true);
}
};

return (
<Dialog open={dialogOpen} onOpenChange={setDialogOpen}>
<div className="flex flex-col gap-2">
<Card
className={`group p-2 rounded-lg ring-2 ease-linear transition-all cursor-pointer ${isSelected ? "ring-primary" : "ring-transparent"} hover:ring-primary`}
onDoubleClick={() => setDialogOpen(true)}
onClick={(e) => {
e.stopPropagation();
dispatch(toggleAssetSelection(asset));
}}
onClick={handleClick}
>
<div className="flex items-center justify-center relative">
<img
Expand All @@ -61,7 +67,7 @@ export function AssetItem({
<div className="absolute inset-0" />
<Button
size="icon"
className="rounded-full absolute bottom-1 right-1 transition-opacity opacity-100 md:opacity-0 md:group-hover:opacity-100"
className="rounded-full absolute bottom-1 right-1 transition-opacity opacity-0 md:group-hover:opacity-100"
onClick={(e) => {
e.stopPropagation();
setDialogOpen(true);
Expand Down
2 changes: 0 additions & 2 deletions src/components/asset/download-indicator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,6 @@ function ShowMassDownloadProgress() {
error instanceof AxiosError &&
error.message === "Network Error"
) {
// TODO: this is either CORS or a user network issue
// fetching assets on 0.1% of all downloads sometimes causes a CORS error and i don't know why ??
userErrorMessage = "Failed to fetch assets, try again later";
isCorsError = true;
}
Expand Down
71 changes: 55 additions & 16 deletions src/components/category/asset-handler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,23 @@ import {
DropdownMenuTrigger,
DropdownMenuItem,
} from "~/components/ui/dropdown-menu";
import { Ellipsis, FilterIcon, LinkIcon, ToggleRight } from "lucide-react";
import {
Ellipsis,
FilterIcon,
LinkIcon,
ToggleRight,
SquareMousePointer,
Eye,
} from "lucide-react";
import { toast } from "sonner";
import Masonry from "react-masonry-css";
import { useAppDispatch, useAppSelector } from "~/redux/store";

import {
toggleAssetSelection,
isAssetSelected,
toggleSelectMode,
getSelectMode,
} from "~/redux/slice/asset-slice";
import { FormatCategoryName, FormatGameName } from "~/lib/format";

Expand Down Expand Up @@ -93,22 +102,52 @@ export function AssetHandler({
700: 2,
};

const dispatch = useAppDispatch();

return (
<div className="flex flex-col gap-4">
<div className="flex flex-row gap-2">
<Input
type="search"
className="bg-background"
placeholder="Search assets"
value={search}
onChange={(e) => setSearch(e.target.value)}
/>
<FilterOptions
filter={filter}
setFilter={setFilter}
filterList={filterList}
/>
<MoreOptions assets={assets} game={game} category={category} />
<div className="flex sm:flex-row flex-col gap-2">
<div className="flex-1">
<Input
type="search"
className="bg-background w-full"
placeholder="Search assets..."
value={search}
onChange={(e) => setSearch(e.target.value)}
/>
</div>
<div className="flex flex-row gap-2 max-sm:w-full">
<Button
variant={"secondary"}
onClick={() => dispatch(toggleSelectMode())}
className="relative group max-sm:w-full min-w-[120px] flex items-center"
>
{useAppSelector((state) =>
getSelectMode(state.assets),
) ? (
<SquareMousePointer
className={`w-4 h-4 mr-2 transition-transform`}
/>
) : (
<Eye
className={`w-4 h-4 mr-2 transition-transform`}
/>
)}
{useAppSelector((state) => getSelectMode(state.assets))
? "Mode: Multi-Select"
: "Mode: View"}
</Button>
<FilterOptions
filter={filter}
setFilter={setFilter}
filterList={filterList}
/>
<MoreOptions
assets={filteredAssets}
game={game}
category={category}
/>
</div>
</div>
<Masonry
breakpointCols={breakpointColumnsObj}
Expand Down Expand Up @@ -235,7 +274,7 @@ function SelectAllAssets({
<DropdownMenuItem onClick={handleSelectAll}>
<div className="flex flex-row gap-2 items-center transition-all duration-150">
<ToggleRight size={16} className="translate-y-[1px]" />
Toggle Selection
{allSelected ? "Deselect All" : "Select All"}
</div>
</DropdownMenuItem>
);
Expand Down
7 changes: 7 additions & 0 deletions src/redux/slice/asset-slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import type { Asset } from "~/lib/types";
export interface IAssetState {
isMassDownloading: boolean;
selectedAssets: Asset[];
selectMode: boolean;
}

const initialState: IAssetState = {
isMassDownloading: false,
selectedAssets: [],
selectMode: false,
};

export const assetSlice = createSlice({
Expand Down Expand Up @@ -36,6 +38,9 @@ export const assetSlice = createSlice({
clearSelectedAssets: (state) => {
state.selectedAssets = [];
},
toggleSelectMode: (state) => {
state.selectMode = !state.selectMode;
},
},
});

Expand All @@ -45,12 +50,14 @@ export const isAssetSelected = (state: IAssetState, asset: Asset) =>
);

export const getSelectedAssets = (state: IAssetState) => state.selectedAssets;
export const getSelectMode = (state: IAssetState) => state.selectMode;

export const {
setSelectedAssets,
setIsMassDownloading,
toggleAssetSelection,
clearSelectedAssets,
toggleSelectMode,
} = assetSlice.actions;

export default assetSlice.reducer;

0 comments on commit bf97201

Please sign in to comment.