Skip to content

Commit

Permalink
receiver: select all files checkbox
Browse files Browse the repository at this point in the history
  • Loading branch information
bruncanepa committed Feb 2, 2024
1 parent 9d448aa commit 6714063
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 81 deletions.
2 changes: 1 addition & 1 deletion client/src/components/ActivityLog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const ActivityLog: FC<ActivityLogProps> = ({
<Heading as="h3">Activity</Heading>
{!!myAlias && (
<Text style={{ fontWeight: "bold", marginBottom: "5%" }}>
You are: {myAlias}
You are: '{myAlias}'
</Text>
)}
{items.length ? (
Expand Down
110 changes: 70 additions & 40 deletions client/src/components/Files.tsx
Original file line number Diff line number Diff line change
@@ -1,66 +1,96 @@
import { FC } from "react";
import { Text, CloseButton, Flex, Checkbox } from "@chakra-ui/react";
import { Text, CloseButton, Flex, Checkbox, Button } from "@chakra-ui/react";
import { DataFileListItem } from "dto/peer";
import { formatBytes } from "utils/file/formatBytes";
import { Progress } from "./Progress";

interface FilesProps {
files: DataFileListItem[];
onClickItem: (file: DataFileListItem) => void;
filesProgressMap?: Record<string, number>;
isDisabled?: boolean;
itemType: "checkbox" | "removable";
onDownload?: () => void;
onClickItem: (file: DataFileListItem[], selectAllValue?: boolean) => void;
}

export const Files: FC<FilesProps> = ({
files,
onClickItem,
filesProgressMap,
isDisabled,
itemType,
onDownload,
onClickItem,
}) => {
const isRemovable = itemType === "removable";
const isCheckbox = itemType === "checkbox";

if (!files.length) return <Text>No files</Text>;

return (
<Flex direction="column" width="100%">
{files.map((file) => (
<Flex
key={file.id}
justifyContent="space-between"
alignItems="center"
borderBottom="1px solid lightgrey"
padding="1% 0"
>
<Flex columnGap="0.5em">
{isCheckbox && (
<Checkbox
onChange={() => onClickItem(file)}
isChecked={file.selected}
isDisabled={isDisabled}
/>
)}
<Flex direction="column" justifyContent="center">
<Text>{file.name}</Text>
<Text fontSize="8px">{formatBytes(file.size)}</Text>
</Flex>
</Flex>
<Flex justifyContent="center" alignItems="center">
{file.selected &&
!!filesProgressMap &&
!!filesProgressMap[file.id] && (
<Progress progress={filesProgressMap[file.id]} />
)}
{isRemovable && (
<CloseButton
isDisabled={isDisabled}
onClick={() => onClickItem(file)}
>
X
</CloseButton>
)}
<Flex width="100%" direction="column" overflow="scroll">
{!!onDownload && (
<>
<Button
minHeight="40px"
isDisabled={isDisabled || !files.some((f) => f.selected)}
onClick={onDownload}
>
Download
</Button>
<Flex columnGap="0.5em" margin="3% 0 3% 0">
<Checkbox
onChange={(event) => onClickItem(files, event.target.checked)}
isDisabled={isDisabled}
/>
<Text fontWeight="bold">Select all</Text>
</Flex>
</>
)}

{files.length ? (
<Flex direction="column" overflow="scroll">
{files.map((file) => (
<Flex
key={file.id}
justifyContent="space-between"
alignItems="center"
borderTop="1px solid lightgrey"
padding="1% 0"
>
<Flex columnGap="0.5em">
{isCheckbox && (
<Checkbox
onChange={() => onClickItem([file])}
isChecked={file.selected}
isDisabled={isDisabled}
/>
)}
<Flex direction="column" justifyContent="center">
<Text>{file.name}</Text>
<Text fontSize="8px">{formatBytes(file.size)}</Text>
</Flex>
</Flex>
<Flex justifyContent="center" alignItems="center">
{file.selected &&
!!filesProgressMap &&
!!filesProgressMap[file.id] && (
<Progress progress={filesProgressMap[file.id]} />
)}
{isRemovable && (
<CloseButton
isDisabled={isDisabled}
onClick={() => onClickItem([file])}
>
X
</CloseButton>
)}
</Flex>
</Flex>
))}
</Flex>
))}
) : (
<Text>No files</Text>
)}
</Flex>
);
};
30 changes: 8 additions & 22 deletions client/src/components/Receiver.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,28 +65,14 @@ const Receiver: FC<ReceiverProps> = ({ sharedId: roomId }) => {
{Boolean(room) ? (
<Box flex={1} flexDirection="column">
<Heading as="h3">Files</Heading>

{files.length ? (
<>
<Button
isDisabled={
downloadButtonClicked || !files.some((f) => f.selected)
}
onClick={onDownload}
>
Download
</Button>
<Files
files={files}
onClickItem={onSelectFile}
filesProgressMap={downloadFileProgressMap}
isDisabled={downloadButtonClicked}
itemType="checkbox"
/>
</>
) : (
<Text>No files</Text>
)}
<Files
files={files}
onClickItem={onSelectFile}
filesProgressMap={downloadFileProgressMap}
isDisabled={downloadButtonClicked}
itemType="checkbox"
onDownload={onDownload}
/>
</Box>
) : (
<Text>Loading...</Text>
Expand Down
1 change: 0 additions & 1 deletion client/src/components/Sender.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ interface SenderProps {}

const Sender: FC<SenderProps> = () => {
const {
myId,
files,
peers,
peersAliases,
Expand Down
4 changes: 2 additions & 2 deletions client/src/hooks/useActivityLog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export const useActivityLogs = (

const add = (log: ActivityLog) => {
if (log.type.endsWith("ERROR")) toast.error(new Error(log.type));

const aliases = peersAliases.current; // get reference now, as setActivityLogs callback is async
setActivityLogs((logs) =>
log.type === "FILES_TRANSFER_PROGRESS"
? logs
Expand All @@ -66,7 +66,7 @@ export const useActivityLogs = (
date: new Date(),
id: new Date().toISOString() + log.type,
data: undefined, // TODO
alias: log.peerId ? peersAliases.current[log.peerId] || "Owner" : "Server",
alias: log.peerId ? aliases[log.peerId] || "Owner" : "Server",
},
"id"
)
Expand Down
22 changes: 11 additions & 11 deletions client/src/hooks/usePeer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,12 @@ export const usePeer = ({
}: UsePeerProps) => {
const toast = useToast();
const peerIsSender = isSender(peerType);
const serverPeerRef = useRef<Peer>();
const myPeerRef = useRef<Peer>();
const peersRef = useRef<Record<string, DataConnection>>({}); // "We recommend keeping track of connections..." https://peerjs.com/docs/#peerconnections
const [peersAliasesRef, setPeersAliasesRef] = useUpdatableRef<
Record<string, string>
>({});
useOnTabUnloaded(Boolean(serverPeerRef.current));
useOnTabUnloaded(Boolean(myPeerRef.current));

const { activityLogs, addActivityLog } = useActivityLogs(peersAliasesRef);

Expand Down Expand Up @@ -112,8 +112,8 @@ export const usePeer = ({
const _onClose = () => {
if (peersRef.current[peerId]) {
toast.info(`Disconnected from ${peersAliasesRef.current[peerId]}`);
addActivityLog({ peerId, type: "CONNECTION_CLOSE" }); // before _updatePeers
_updatePeers("remove", peerId, conn);
addActivityLog({ peerId, type: "CONNECTION_CLOSE" });
}
};
conn
Expand All @@ -133,23 +133,23 @@ export const usePeer = ({
if (state === "disconnected") _onClose();
})
.on("error", (err: PeerError<string>) => {
addActivityLog({ peerId, type: "LISTEN_CONNECTION_ERROR", data: err });
toast.error(err);
if (resultCallback) resultCallback(err);
addActivityLog({ peerId, type: "LISTEN_CONNECTION_ERROR", data: err });
});
};

const startSession = (): Promise<string> =>
new Promise<string>((resolve, reject) => {
serverPeerRef.current = new Peer(genPeerId(), {
myPeerRef.current = new Peer(genPeerId(), {
host: "127.0.0.1",
port: 8081,
path: "/sockets",
debug: 3,
secure: false,
});
addActivityLog({ type: "CREATE_SESSION_REQUESTED" });
serverPeerRef.current
myPeerRef.current
.on("open", (id: string) => {
addActivityLog({ type: "CREATE_SESSION_OK" });
resolve(id);
Expand Down Expand Up @@ -180,7 +180,7 @@ export const usePeer = ({
if (peersRef.current[peerId]) {
peersRef.current[peerId].close();
}
const conn = serverPeerRef.current?.connect(peerId, { reliable: true });
const conn = myPeerRef.current?.connect(peerId, { reliable: true });
if (!conn) {
const errMsg = "Connection can't be established";
addActivityLog({ peerId, type: "NEW_CONNECTION_ERROR", data: errMsg });
Expand Down Expand Up @@ -212,12 +212,12 @@ export const usePeer = ({
type: toActivityLogType(msg.type, "OK"),
});
} catch (err) {
toast.error(err as Error, "error sending message to room");
addActivityLog({
peerId,
type: toActivityLogType(msg.type, "ERROR"),
data: err,
});
toast.error(err as Error, "error sending message to room");
}
};

Expand All @@ -232,7 +232,7 @@ export const usePeer = ({
try {
addActivityLog({ type: messageType });
listenToServerEvents(payload.type, onServerEvent);
serverPeerRef.current?.socket.send({ type: "PEER_DROP", payload });
myPeerRef.current?.socket.send({ type: "PEER_DROP", payload });
addActivityLog({ type: toActivityLogType(messageType, "OK") });
} catch (err) {
toast.error(err as Error, "error sending message to server");
Expand All @@ -247,7 +247,7 @@ export const usePeer = ({
messageType: ServerMessageType,
onServerEvent: (d: ServerMessage<T>) => any
) => {
serverPeerRef.current?.socket?.once(
myPeerRef.current?.socket?.once(
SocketEventType.Message,
(message: ServerMessageWrapped<T>) => {
if (message.type === "PEER_DROP") {
Expand All @@ -273,7 +273,7 @@ export const usePeer = ({
};

return {
myId: serverPeerRef.current?.id || "",
myId: myPeerRef.current?.id || "",
peers: Object.keys(peersRef.current).map((p) => peersRef.current[p].peer),
peersAliasesRef,
activityLogs,
Expand Down
10 changes: 8 additions & 2 deletions client/src/hooks/usePeerReceiver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,15 @@ export const usePeerReceiver = ({ roomId }: usePeerReceiverProps) => {
}
};

const onSelectFile = (file: DataFileListItem) =>
const onSelectFile = (files: DataFileListItem[], selectAllValue?: boolean) =>
setFiles((fs) =>
ImmutableArray.update(fs, { ...file, selected: !file.selected }, "id")
files.length === 1
? ImmutableArray.update(
fs,
{ ...files[0], selected: !files[0].selected },
"id"
)
: files.map((f) => ({ ...f, selected: selectAllValue }))
);

const roomOnwerPeer = peers.length ? peers[0] : undefined;
Expand Down
4 changes: 2 additions & 2 deletions client/src/hooks/usePeerSender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,11 @@ export const usePeerSender = () => {
}
};

const onRemoveFile = (fileRemoved: DataFileListItem) => {
const onRemoveFile = (fileRemoved: DataFileListItem[]) => {
updateFilesRef(
ImmutableArray.remove(
filesRef.current,
(file) => file.id !== fileRemoved.id
(file) => file.id !== fileRemoved[0].id
)
);
_sendFileListRes(...peers);
Expand Down
1 change: 1 addition & 0 deletions client/src/hooks/useToast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export const useToast = () => {
const error = (err: Error, title?: string, options: UseToastOptions = {}) =>
toast({
...mergeOptions(options),
duration: null,
title: err.message
? `${title + " "}${err.message}`
: title || "An error ocurred",
Expand Down

0 comments on commit 6714063

Please sign in to comment.