Skip to content

Commit 324b15e

Browse files
Feature: Implement sharing ui
1 parent be4fd5c commit 324b15e

8 files changed

Lines changed: 524 additions & 1 deletion

File tree

app/components/FileItem.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ interface FileItemProps {
2727
onMove?: (file: FileItemData) => void;
2828
onDownload?: (file: FileItemData) => void;
2929
onDelete?: (file: FileItemData) => void;
30+
onShare?: (file: FileItemData) => void;
3031
isSelected?: boolean;
3132
onContextMenu?: (file: FileItemData, event: React.MouseEvent) => void;
3233
}
@@ -42,6 +43,7 @@ export default function FileItem({
4243
onMove,
4344
onDownload,
4445
onDelete,
46+
onShare,
4547
isSelected = false,
4648
onContextMenu,
4749
}: FileItemProps) {
@@ -146,6 +148,7 @@ export default function FileItem({
146148
onCopy={onCopy}
147149
onMove={onMove}
148150
onDelete={onDelete}
151+
onShare={onShare}
149152
/>
150153
)}
151154
<div className="mb-1 flex h-12 w-12 items-center justify-center sm:mb-2 sm:h-16 sm:w-16">
@@ -199,6 +202,7 @@ export default function FileItem({
199202
onCopy={onCopy}
200203
onMove={onMove}
201204
onDelete={onDelete}
205+
onShare={onShare}
202206
/>
203207
)}
204208
</section>

app/components/FileItemMenu.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
ArrowRightCircleIcon,
1111
TrashIcon,
1212
EyeIcon,
13+
ShareIcon,
1314
} from "@heroicons/react/24/outline";
1415
import { useClickOutside } from "../lib/hooks";
1516
import { FileItemData } from "./FileItem";
@@ -22,6 +23,7 @@ interface FileItemMenuProps {
2223
onMove?: (file: FileItemData) => void;
2324
onDelete?: (file: FileItemData) => void;
2425
onPreview?: (file: FileItemData) => void;
26+
onShare?: (file: FileItemData) => void;
2527
position?: "top-right" | "right";
2628
}
2729

@@ -33,6 +35,7 @@ export default function FileItemMenu({
3335
onMove,
3436
onDelete,
3537
onPreview,
38+
onShare,
3639
position = "right",
3740
}: FileItemMenuProps) {
3841
const [showMenu, setShowMenu] = useState(false);
@@ -104,6 +107,13 @@ export default function FileItemMenu({
104107
className: "text-gray-700 hover:bg-gray-100 border-b border-gray-100",
105108
iconClassName: "text-gray-500",
106109
},
110+
{
111+
label: "Share",
112+
icon: ShareIcon,
113+
action: onShare,
114+
className: "text-gray-700 hover:bg-gray-100 border-b border-gray-100",
115+
iconClassName: "text-gray-500",
116+
},
107117
// Only show Move for files, not folders
108118
...(file.type === "file"
109119
? [

app/components/FileList.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ interface FileListProps {
1616
onFileMove?: (file: FileItemData) => void;
1717
onFileDownload?: (file: FileItemData) => void;
1818
onFileDelete?: (file: FileItemData) => void;
19+
onFileShare?: (file: FileItemData) => void;
1920
selectedFileIds: string[];
2021
onFileContextMenu?: (file: FileItemData, event: React.MouseEvent) => void;
2122
}
@@ -33,6 +34,7 @@ export default function FileList({
3334
onFileMove,
3435
onFileDownload,
3536
onFileDelete,
37+
onFileShare,
3638
selectedFileIds,
3739
onFileContextMenu,
3840
}: FileListProps) {
@@ -73,6 +75,7 @@ export default function FileList({
7375
onMove={onFileMove}
7476
onDownload={onFileDownload}
7577
onDelete={onFileDelete}
78+
onShare={onFileShare}
7679
isSelected={selectedFileIds.includes(file.id)}
7780
onContextMenu={onFileContextMenu}
7881
/>
@@ -93,6 +96,7 @@ export default function FileList({
9396
onMove={onFileMove}
9497
onDownload={onFileDownload}
9598
onDelete={onFileDelete}
99+
onShare={onFileShare}
96100
isSelected={selectedFileIds.includes(file.id)}
97101
onContextMenu={onFileContextMenu}
98102
/>

app/components/FileManager.tsx

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
ArrowRightCircleIcon,
1313
TrashIcon,
1414
EyeIcon,
15+
ShareIcon,
1516
} from "@heroicons/react/24/outline";
1617
import AuthWrapper from "./AuthWrapper";
1718
import Header from "./Header";
@@ -24,6 +25,7 @@ import RenameDialog from "./RenameDialog";
2425
import PreviewModal from "./PreviewModal";
2526
import MoveDialog from "./MoveDialog";
2627
import DeleteConfirmDialog from "./DeleteConfirmDialog";
28+
import ShareDialog, { AccessLevel } from "./ShareDialog";
2729
import FileUploadHandler from "./FileUploadHandler";
2830
import ContextMenu, { ContextMenuAction } from "./ContextMenu";
2931
import { FileItemData } from "./FileItem";
@@ -94,6 +96,8 @@ export default function FileManager() {
9496
const [showDeleteDialog, setShowDeleteDialog] = useState(false);
9597
const [fileToDelete, setFileToDelete] = useState<FileItemData | null>(null);
9698
const [isDeleting, setIsDeleting] = useState(false);
99+
const [showShareDialog, setShowShareDialog] = useState(false);
100+
const [fileToShare, setFileToShare] = useState<FileItemData | null>(null);
97101
const [contextMenuState, setContextMenuState] = useState<ContextMenuState | null>(null);
98102

99103
const closeContextMenu = () => setContextMenuState(null);
@@ -392,6 +396,17 @@ export default function FileManager() {
392396
}
393397
};
394398

399+
const handleShare = (file: FileItemData) => {
400+
setFileToShare(file);
401+
setShowShareDialog(true);
402+
};
403+
404+
const handleShareConfirm = async (webId: string, accessLevel: AccessLevel) => {
405+
// TODO: Implement actual sharing logic
406+
console.log(`Sharing ${fileToShare?.name} with ${webId} as ${accessLevel}`);
407+
toast.success(`Shared with ${webId} as ${accessLevel}`);
408+
};
409+
395410
const handleDragEnter = (event: React.DragEvent<HTMLElement>) => {
396411
if (!hasFilesInDrag(event)) return;
397412
event.preventDefault();
@@ -633,6 +648,14 @@ export default function FileManager() {
633648
closeContextMenu();
634649
handleCopy(file);
635650
},
651+
},
652+
{
653+
label: "Share",
654+
icon: ShareIcon,
655+
onClick: () => {
656+
closeContextMenu();
657+
handleShare(file);
658+
},
636659
}
637660
);
638661

@@ -823,6 +846,7 @@ export default function FileManager() {
823846
onFileMove={handleMove}
824847
onFileDownload={handleDownload}
825848
onFileDelete={handleDelete}
849+
onFileShare={handleShare}
826850
selectedFileIds={selectedFileIds}
827851
onFileContextMenu={handleFileContextMenu}
828852
/>
@@ -888,6 +912,15 @@ export default function FileManager() {
888912
onConfirm={handleDeleteConfirm}
889913
isDeleting={isDeleting}
890914
/>
915+
<ShareDialog
916+
isOpen={showShareDialog}
917+
onClose={() => {
918+
setShowShareDialog(false);
919+
setFileToShare(null);
920+
}}
921+
file={fileToShare}
922+
onShare={handleShareConfirm}
923+
/>
891924
{isDragActive && (
892925
<div className="pointer-events-none fixed inset-0 z-40 flex flex-col items-center justify-center bg-purple-500/10">
893926
<div className="rounded-2xl border border-purple-400 bg-white/90 px-8 py-6 text-center shadow-lg">

0 commit comments

Comments
 (0)