diff --git a/matrixgw_frontend/src/api/ApiClient.ts b/matrixgw_frontend/src/api/ApiClient.ts index fdb7da3..fcd4f11 100644 --- a/matrixgw_frontend/src/api/ApiClient.ts +++ b/matrixgw_frontend/src/api/ApiClient.ts @@ -4,21 +4,21 @@ interface RequestParams { uri: string; method: "GET" | "POST" | "DELETE" | "PATCH" | "PUT"; allowFail?: boolean; - jsonData?: any; + jsonData?: unknown; formData?: FormData; upProgress?: (progress: number) => void; downProgress?: (e: { progress: number; total: number }) => void; } interface APIResponse { - data: any; + data: unknown; status: number; } export class ApiError extends Error { public code: number; - public data: number; - constructor(message: string, code: number, data: any) { + public data: unknown; + constructor(message: string, code: number, data: unknown) { super(`HTTP status: ${code}\nMessage: ${message}\nData=${data}`); this.code = code; this.data = data; @@ -57,6 +57,7 @@ export class APIClient { */ static async exec(args: RequestParams): Promise { let body: string | undefined | FormData = undefined; + // eslint-disable-next-line @typescript-eslint/no-explicit-any const headers: any = {}; // JSON request diff --git a/matrixgw_frontend/src/routes/MatrixAuthCallback.tsx b/matrixgw_frontend/src/routes/MatrixAuthCallback.tsx index 3eafadc..1d5aa19 100644 --- a/matrixgw_frontend/src/routes/MatrixAuthCallback.tsx +++ b/matrixgw_frontend/src/routes/MatrixAuthCallback.tsx @@ -41,7 +41,7 @@ export function MatrixAuthCallback(): React.ReactElement { }; load(); - }, [code, state]); + }, [code, info, navigate, snackbar, state]); if (error) return ( diff --git a/matrixgw_frontend/src/utils/DateUtils.ts b/matrixgw_frontend/src/utils/DateUtils.ts index 7c680b9..0bf9610 100644 --- a/matrixgw_frontend/src/utils/DateUtils.ts +++ b/matrixgw_frontend/src/utils/DateUtils.ts @@ -1,3 +1,5 @@ +import { format } from "date-and-time"; + /** * Get UNIX time * @@ -15,3 +17,62 @@ export function time(): number { export function timeMs(): number { return new Date().getTime(); } + +export function formatDateTime(time: number): string { + const t = new Date(); + t.setTime(1000 * time); + return format(t, "DD/MM/YYYY HH:mm:ss"); +} + +export function formatDate(time: number): string { + const t = new Date(); + t.setTime(1000 * time); + return format(t, "DD/MM/YYYY"); +} + +export function timeDiff(a: number, b: number): string { + let diff = b - a; + + if (diff === 0) return "now"; + if (diff === 1) return "1 second"; + + if (diff < 60) { + return `${diff} seconds`; + } + + diff = Math.floor(diff / 60); + + if (diff === 1) return "1 minute"; + if (diff < 60) { + return `${diff} minutes`; + } + + diff = Math.floor(diff / 60); + + if (diff === 1) return "1 hour"; + if (diff < 24) { + return `${diff} hours`; + } + + const diffDays = Math.floor(diff / 24); + + if (diffDays === 1) return "1 day"; + if (diffDays < 31) { + return `${diffDays} days`; + } + + diff = Math.floor(diffDays / 31); + + if (diff < 12) { + return `${diff} month`; + } + + const diffYears = Math.floor(diffDays / 365); + + if (diffYears === 1) return "1 year"; + return `${diffYears} years`; +} + +export function timeDiffFromNow(t: number): string { + return timeDiff(t, time()); +} diff --git a/matrixgw_frontend/src/utils/RoomEventsManager.ts b/matrixgw_frontend/src/utils/RoomEventsManager.ts index 9c20f10..2efb88a 100644 --- a/matrixgw_frontend/src/utils/RoomEventsManager.ts +++ b/matrixgw_frontend/src/utils/RoomEventsManager.ts @@ -236,7 +236,7 @@ export class RoomEventsManager { // Adapt receipts to be event-indexed this.receiptsEventsMap.clear(); - for (const [_userId, receipt] of receiptsUsersMap) { + for (const receipt of [...receiptsUsersMap.values()]) { if (!this.receiptsEventsMap.has(receipt.event_id)) this.receiptsEventsMap.set(receipt.event_id, [receipt]); else this.receiptsEventsMap.get(receipt.event_id)!.push(receipt); diff --git a/matrixgw_frontend/src/widgets/TimeWidget.tsx b/matrixgw_frontend/src/widgets/TimeWidget.tsx index 253a0e0..1813af3 100644 --- a/matrixgw_frontend/src/widgets/TimeWidget.tsx +++ b/matrixgw_frontend/src/widgets/TimeWidget.tsx @@ -1,65 +1,10 @@ import { Tooltip } from "@mui/material"; -import { format } from "date-and-time"; -import { time } from "../utils/DateUtils"; - -export function formatDateTime(time: number): string { - const t = new Date(); - t.setTime(1000 * time); - return format(t, "DD/MM/YYYY HH:mm:ss"); -} - -export function formatDate(time: number): string { - const t = new Date(); - t.setTime(1000 * time); - return format(t, "DD/MM/YYYY"); -} - -export function timeDiff(a: number, b: number): string { - let diff = b - a; - - if (diff === 0) return "now"; - if (diff === 1) return "1 second"; - - if (diff < 60) { - return `${diff} seconds`; - } - - diff = Math.floor(diff / 60); - - if (diff === 1) return "1 minute"; - if (diff < 60) { - return `${diff} minutes`; - } - - diff = Math.floor(diff / 60); - - if (diff === 1) return "1 hour"; - if (diff < 24) { - return `${diff} hours`; - } - - const diffDays = Math.floor(diff / 24); - - if (diffDays === 1) return "1 day"; - if (diffDays < 31) { - return `${diffDays} days`; - } - - diff = Math.floor(diffDays / 31); - - if (diff < 12) { - return `${diff} month`; - } - - const diffYears = Math.floor(diffDays / 365); - - if (diffYears === 1) return "1 year"; - return `${diffYears} years`; -} - -export function timeDiffFromNow(t: number): string { - return timeDiff(t, time()); -} +import { + formatDateTime, + formatDate, + timeDiff, + timeDiffFromNow, +} from "../utils/DateUtils"; export function TimeWidget(p: { time?: number; diff --git a/matrixgw_frontend/src/widgets/dashboard/DashboardSidebar.tsx b/matrixgw_frontend/src/widgets/dashboard/DashboardSidebar.tsx index c733355..6c5f7a1 100644 --- a/matrixgw_frontend/src/widgets/dashboard/DashboardSidebar.tsx +++ b/matrixgw_frontend/src/widgets/dashboard/DashboardSidebar.tsx @@ -62,7 +62,7 @@ export default function DashboardSidebar({ if (!isOverSmViewport) { setExpanded(false); } - }, [expanded, setExpanded, isOverSmViewport]); + }, [setExpanded, isOverSmViewport]); const hasDrawerTransitions = isOverSmViewport && isOverMdViewport; @@ -159,7 +159,7 @@ export default function DashboardSidebar({ }, }; }, - [expanded, !expanded] + [expanded] ); const sidebarContextValue = React.useMemo(() => { @@ -168,7 +168,7 @@ export default function DashboardSidebar({ fullyExpanded: isFullyExpanded, hasDrawerTransitions, }; - }, [handlePageItemClick, !expanded, isFullyExpanded, hasDrawerTransitions]); + }, [handlePageItemClick, isFullyExpanded, hasDrawerTransitions]); return ( diff --git a/matrixgw_frontend/src/widgets/messages/MainMessagesWidget.tsx b/matrixgw_frontend/src/widgets/messages/MainMessagesWidget.tsx index d5c60a8..9437353 100644 --- a/matrixgw_frontend/src/widgets/messages/MainMessagesWidget.tsx +++ b/matrixgw_frontend/src/widgets/messages/MainMessagesWidget.tsx @@ -43,7 +43,7 @@ export function MainMessageWidget(): React.ReactElement { ready={!!rooms && !!users} errMsg="Failed to initialize messaging component!" build={() => ( - <_MainMessageWidget + setRooms((r) => cb(r!))} @@ -53,7 +53,7 @@ export function MainMessageWidget(): React.ReactElement { ); } -function _MainMessageWidget(p: { +function MainMessageWidgetInner(p: { rooms: Room[]; users: UsersMap; onRoomsListUpdate: (cb: (a: Room[]) => Room[]) => void; @@ -79,7 +79,7 @@ function _MainMessageWidget(p: { [p.rooms] ); - const [_refreshCount, setRefreshCount] = React.useState(0); + const setRefreshCount = React.useState(0)[1]; const [roomMgr, setRoomMgr] = React.useState(); const loadRoom = async () => { diff --git a/matrixgw_frontend/src/widgets/messages/MatrixWS.tsx b/matrixgw_frontend/src/widgets/messages/MatrixWS.tsx index 8e376cb..ea9061a 100644 --- a/matrixgw_frontend/src/widgets/messages/MatrixWS.tsx +++ b/matrixgw_frontend/src/widgets/messages/MatrixWS.tsx @@ -75,7 +75,7 @@ export function MatrixWS(p: { }; return () => ws.close(); - }, [connCount]); + }, [connCount, snackbar]); return ( diff --git a/matrixgw_frontend/src/widgets/messages/RoomMessagesList.tsx b/matrixgw_frontend/src/widgets/messages/RoomMessagesList.tsx index 4553ab6..e0e2cf7 100644 --- a/matrixgw_frontend/src/widgets/messages/RoomMessagesList.tsx +++ b/matrixgw_frontend/src/widgets/messages/RoomMessagesList.tsx @@ -49,10 +49,11 @@ export function RoomMessagesList(p: { const messagesEndRef = React.createRef(); // Automatically scroll to bottom when number of messages change + const lastEventId = p.manager.messages.at(-1)?.event_id; React.useEffect(() => { if (messagesEndRef) messagesEndRef.current?.scrollIntoView({ behavior: "instant" }); - }, [p.manager.messages.at(-1)?.event_id]); + }, [lastEventId, messagesEndRef]); // Watch scroll to detect when user reach the top to load older messages const handleScroll = async () => { @@ -185,8 +186,8 @@ function RoomMessage(p: { try { await MatrixApiEvent.DeleteEvent(p.room, p.message.event_id); } catch (e) { - console.error(`Failed to delete message!`, e), - alert(`Failed to delete message!${e}`); + console.error(`Failed to delete message!`, e); + alert(`Failed to delete message!${e}`); } }; diff --git a/matrixgw_frontend/src/widgets/messages/TypingNotice.tsx b/matrixgw_frontend/src/widgets/messages/TypingNotice.tsx index 4223811..578718d 100644 --- a/matrixgw_frontend/src/widgets/messages/TypingNotice.tsx +++ b/matrixgw_frontend/src/widgets/messages/TypingNotice.tsx @@ -17,7 +17,7 @@ export function TypingNotice(p: { p.manager.typingUsers.includes(u.user_id) && u.user_id !== user.info.matrix_user_id ), - [p.manager.typingUsers] + [p.manager.typingUsers, p.users, user.info.matrix_user_id] ); if (users.length === 0) return <>;