Skip to content

Commit

Permalink
fix: Star list doesn't update when starring folder through context menu
Browse files Browse the repository at this point in the history
  • Loading branch information
NriotHrreion committed Aug 6, 2024
1 parent d238311 commit 8623c4a
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 20 deletions.
32 changes: 12 additions & 20 deletions components/explorer/sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
"use-client";
import path from "path";

import React, { useEffect, useState } from "react";
import { Card } from "@nextui-org/card";
import { Button } from "@nextui-org/button";
import { Tooltip } from "@nextui-org/tooltip";
import { FilePlus2, FileUp, FolderPlus, Star } from "lucide-react";

import { getFolderIcon } from "./explorer-item";
import SidebarWidget from "./sidebar-widget";
import StarredItem from "./starred-item";

import { parseStringPath, useExplorer } from "@/hooks/useExplorer";
import { useExplorer } from "@/hooks/useExplorer";
import { useDialog } from "@/hooks/useDialog";
import { useFolder } from "@/hooks/useFolder";
import { useEmitter } from "@/hooks/useEmitter";
import { useForceUpdate } from "@/hooks/useForceUpdate";
import { storage } from "@/lib/storage";
import { starListStorageKey } from "@/lib/global";

Expand All @@ -22,6 +23,7 @@ const Sidebar: React.FC = () => {
const folder = useFolder(explorer.stringifyPath());

const [starred, setStarred] = useState(folder.getIsStarred());
const forceUpdate = useForceUpdate();

const handleCreateFolder = () => {
dialog.open("createFolder", { path: explorer.stringifyPath() });
Expand All @@ -44,6 +46,10 @@ const Sidebar: React.FC = () => {
setStarred(folder.getIsStarred());
});

useEmitter([
["star-list-change", () => forceUpdate()]
]);

return (
<div className="flex-1 flex flex-col gap-2">
<div className="flex justify-between">
Expand Down Expand Up @@ -82,23 +88,9 @@ const Sidebar: React.FC = () => {
<SidebarWidget title="星标项目">
<div>
{
(JSON.parse(storage.getItem(starListStorageKey, JSON.stringify([]))) as string[]).map((item, index) => {
const itemName = path.basename(item);

return (
<div
className="inline-block m-1"
aria-label={itemName}
key={index}>
<Tooltip content={item}>
<Button color="default" variant="flat" size="sm" onPress={() => explorer.setPath(parseStringPath(item))}>
{getFolderIcon(itemName)}
{itemName}
</Button>
</Tooltip>
</div>
);
})
(JSON.parse(storage.getItem(starListStorageKey, JSON.stringify([]))) as string[]).map((item, index) => (
<StarredItem itemPath={item} key={index}/>
))
}
</div>
</SidebarWidget>
Expand Down
60 changes: 60 additions & 0 deletions components/explorer/starred-item.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
"use client";

import path from "path";

import React from "react";
import { Button } from "@nextui-org/button";
import { Tooltip } from "@nextui-org/tooltip";
import { ContextMenuItem, useContextMenu } from "use-context-menu";

import { getFolderIcon } from "./explorer-item";

import { parseStringPath, useExplorer } from "@/hooks/useExplorer";
import { useFolder } from "@/hooks/useFolder";

interface StarredItemProps {
itemPath: string
}

const StarredItem: React.FC<StarredItemProps> = ({ itemPath }) => {
const explorer = useExplorer();
const itemName = path.basename(itemPath);
const folder = useFolder(itemPath.replace(explorer.disk, ""));

const handleOpen = () => {
explorer.setPath(parseStringPath(itemPath));
};

const handleUnstar = () => {
folder.toggleStar();
};

const { contextMenu, onContextMenu } = useContextMenu(
<>
<ContextMenuItem onSelect={() => handleOpen()}>打开</ContextMenuItem>
<ContextMenuItem onSelect={() => handleUnstar()}>取消星标</ContextMenuItem>
</>
);

return (
<div
className="inline-block m-1"
aria-label={itemName}>
<Tooltip content={itemPath}>
<Button
color="default"
variant="flat"
size="sm"
onPress={() => handleOpen()}
onContextMenu={onContextMenu}>
{getFolderIcon(itemName)}
{itemName}
</Button>
</Tooltip>

{contextMenu}
</div>
);
}

export default StarredItem;
26 changes: 26 additions & 0 deletions hooks/useEmitter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { useEffect } from "react";

import { emitter } from "@/lib/emitter";

type EmitterInstance = [string, (...args: any[]) => any];

/**
* Create an event listener with `EventEmitter`
*
* @example
* ```ts
* useEmitter([
* ["foo", () => console.log("bar")]
* ]);
*
* // in somewhere...
* new Emitter().emit("foo"); // bar
* ```
*/
export function useEmitter(instances: EmitterInstance[]) {
useEffect(() => {
instances.forEach((instance: EmitterInstance) => {
emitter.on(instance[0], (...args: any[]) => instance[1](...args));
});
}, []);
}
3 changes: 3 additions & 0 deletions hooks/useFolder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { useExplorer } from "./useExplorer";

import { storage } from "@/lib/storage";
import { starListStorageKey } from "@/lib/global";
import { emitter } from "@/lib/emitter";

interface FolderOperations extends DirectoryItemOperations {
create: (name: string, type: "folder" | "file") => Promise<void>
Expand Down Expand Up @@ -171,6 +172,8 @@ export function useFolder(fullPath: string): FolderOperations {
} else {
storage.setItem(starListStorageKey, JSON.stringify([...starList, targetPath]));
}

emitter.emit("star-list-change");
},
getIsStarred: () => {
if(typeof window === "undefined") return false;
Expand Down
7 changes: 7 additions & 0 deletions hooks/useForceUpdate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { useState } from "react";

export function useForceUpdate() {
const [, setCount] = useState(0);

return () => setCount((prev) => prev + 1);
}
3 changes: 3 additions & 0 deletions lib/emitter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import EventEmitter from "events";

export const emitter = new EventEmitter();

0 comments on commit 8623c4a

Please sign in to comment.