Add network and syncing status and made the database controller resizebale

This commit is contained in:
KarimTamani
2025-05-26 15:04:05 +01:00
parent 4a3f266ad1
commit 6d41e73af8
10 changed files with 224 additions and 33 deletions
+142
View File
@@ -0,0 +1,142 @@
import { usePowerSync } from "@powersync/react";
import { Wifi, WifiOff } from "lucide-react";
import { useEffect, useMemo, useRef, useState } from "react";
import { Tooltip, TooltipContent, TooltipTrigger } from "../tooltip/tooltip";
import { cn, Divider, Progress } from "@heroui/react";
import { differenceInHours, differenceInMinutes, lastDayOfYear } from "date-fns";
const ConnectionStatus: React.FC = () => {
const powerSync = usePowerSync();
const [syncStatus, setSyncStatus] = useState(powerSync.currentStatus);
const [downloadProgress, setDownloadProgress] = useState<number | undefined>(undefined);
const clearProgressHandler: any = useRef(undefined);
const [lastUploadAt, setLastUploadAt] = useState<Date | undefined>(() => {
const last_upload_at = localStorage.getItem("last_upload_at");
if (last_upload_at)
return new Date(last_upload_at);
return undefined;
})
useEffect(() => {
const getLastUploadAtValue = (event: any) => {
const last_upload_at = localStorage.getItem("last_upload_at");
if (last_upload_at)
setLastUploadAt(new Date(last_upload_at));
}
window.addEventListener("storage", getLastUploadAtValue);
return () => {
window.removeEventListener('storage', getLastUploadAtValue);
}
}, [])
useEffect(() => {
const l = powerSync.registerListener({
statusChanged: (status) => {
setSyncStatus(status);
},
});
return () => l?.();
}, [powerSync]);
useEffect(() => {
if (syncStatus.downloadProgress?.downloadedOperations && syncStatus.downloadProgress?.totalOperations) {
const progress: number = Math.round(syncStatus.downloadProgress.downloadedOperations / syncStatus.downloadProgress.totalOperations * 100);
if (progress <= 100) {
setDownloadProgress(progress);
}
if (downloadProgress == 100 && !clearProgressHandler.current) {
clearProgressHandler.current = setTimeout(() => {
setDownloadProgress(undefined);
clearProgressHandler.current = undefined;
}, 700)
}
}
}, [syncStatus.downloadProgress])
const deltaUploadTime = useMemo(() => {
if (lastUploadAt) {
const currentDate = new Date();
const minutes = differenceInMinutes(currentDate, lastUploadAt)
const hours = differenceInHours(currentDate, lastUploadAt);
if (hours > 0 && hours < 24) {
return `${hours} hour ago`
}
if (minutes > 0 && minutes < 60)
return `${minutes} min ago`
if (hours > 24) {
return `${lastUploadAt.toLocaleDateString()}`
}
}
return "Just now";
}, [lastUploadAt]);
return (
<div className="flex items-center ">
<Tooltip>
<TooltipTrigger asChild>
<div className="border-1 flex gap-2 p-2 px-3 rounded-lg text-xs relative overflow-hidden dark:border-default ">
<span className={cn("flex gap-2 font-semibold", syncStatus.connected ? "text-success-400" : "text-danger-400")}>
{
syncStatus.connected ?
<Wifi className="size-4 " /> :
<WifiOff className="size-4 " />
}
{
syncStatus.connected ? "Online" : "Offline"
}
</span>
<Divider orientation="vertical" className="h-4" />
{
downloadProgress !== undefined ?
<>
<span className="text-slate-500 dark:text-white w-[96px] truncate">
Saving ...
</span>
<Progress
classNames={{
base: "max-w-md absolute bottom-[-2px] left-0 w-full ",
track: " bg-transparent",
indicator: "bg-gradient-to-r from-secondary-200 to-primary ",
}}
radius="sm"
aria-label="upload progress"
showValueLabel={false}
size="sm"
value={downloadProgress}
/>
</>
:
<span className="text-slate-500 dark:text-white w-[96px] truncate font-semibold" >
Saved {deltaUploadTime}
</span>
}
</div>
</TooltipTrigger>
<TooltipContent className="dark:bg-default-900">
Last synced {syncStatus.lastSyncedAt?.toISOString()}
</TooltipContent>
</Tooltip>
</div>
)
}
export default ConnectionStatus;
+9 -4
View File
@@ -1,6 +1,7 @@
import { NavbarBrand, NavbarContent, Navbar as NavbarContainer, Image, Dropdown, DropdownTrigger, Button, DropdownMenu, DropdownItem } from "@heroui/react";
import Menu from "../menu/menu";
import { useTheme } from "next-themes";
import ConnectionStatus from "./connection-status";
interface Props {
@@ -8,7 +9,7 @@ interface Props {
const Navbar: React.FC<Props> = ({ }) => {
const {resolvedTheme} = useTheme() ;
const { resolvedTheme } = useTheme();
return (
@@ -21,9 +22,13 @@ const Navbar: React.FC<Props> = ({ }) => {
/>
<h3 className="font-semibold ml-2 text-slate-900 text-sm dark:text-white">StackRender</h3>
<div className="ml-4">
<Menu/>
<div className="ml-4 w-full">
<div className="flex w-full justify-between">
<Menu />
<ConnectionStatus />
</div>
</div>
</nav>