Skip to content

Commit

Permalink
feat: sync indicator when disable
Browse files Browse the repository at this point in the history
Signed-off-by: Innei <i@innei.in>
  • Loading branch information
Innei committed Sep 14, 2024
1 parent 8454691 commit 945ddda
Show file tree
Hide file tree
Showing 7 changed files with 215 additions and 134 deletions.
1 change: 1 addition & 0 deletions locales/app/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@
"signin.continue_with_github": "Continue with GitHub",
"signin.continue_with_google": "Continue with Google",
"signin.sign_in_to": "Sign in to",
"sync_indicator.disabled": "Due to security reasons, sync is disabled.",
"sync_indicator.offline": "Offline",
"sync_indicator.synced": "Synced with server",
"tip_modal.amount": "Amount",
Expand Down
18 changes: 18 additions & 0 deletions src/renderer/src/components/icons/PhCloudWarning.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { SVGProps } from "react"

export function PhCloudWarning(props: SVGProps<SVGSVGElement>) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="1em"
height="1em"
viewBox="0 0 256 256"
{...props}
>
<path
fill="currentColor"
d="M160 40a88.09 88.09 0 0 0-78.71 48.67A64 64 0 1 0 72 216h88a88 88 0 0 0 0-176m0 160H72a48 48 0 0 1 0-96c1.1 0 2.2 0 3.29.11A88 88 0 0 0 72 128a8 8 0 0 0 16 0a72 72 0 1 1 72 72m-8-72V88a8 8 0 0 1 16 0v40a8 8 0 0 1-16 0m20 36a12 12 0 1 1-12-12a12 12 0 0 1 12 12"
/>
</svg>
)
}
39 changes: 33 additions & 6 deletions src/renderer/src/modules/settings/helper/SyncIndicator.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import { PhCloudCheck } from "@renderer/components/icons/PhCloudCheck"
import { PhCloudWarning } from "@renderer/components/icons/PhCloudWarning"
import { PhCloudX } from "@renderer/components/icons/PhCloudX"
import { Tooltip, TooltipContent, TooltipTrigger } from "@renderer/components/ui/tooltip"
import { useAuthQuery, useIsOnline } from "@renderer/hooks/common"
import { settings } from "@renderer/queries/settings"
import { useEffect, useRef } from "react"
import { useEffect, useMemo, useRef } from "react"
import { useTranslation } from "react-i18next"

import { useSettingContextSelector } from "../modal/hooks"
import { settingSyncQueue } from "./sync-queue"

export const SyncIndicator = () => {
export const SettingSyncIndicator = () => {
const { t } = useTranslation()
const { data: remoteSettings, isLoading } = useAuthQuery(settings.get(), {})
const canSync = useSettingContextSelector((s) => s.canSync)

const isOnline = useIsOnline()
const onceRef = useRef(false)
Expand All @@ -26,17 +29,41 @@ export const SyncIndicator = () => {
}
}, [remoteSettings, isLoading])

const metaInfo: {
icon: React.FC<React.SVGProps<SVGSVGElement>>
text: string
} = useMemo(() => {
switch (true) {
case !isOnline: {
return {
icon: PhCloudX,
text: t("sync_indicator.offline"),
}
}
case !canSync: {
return {
icon: PhCloudWarning,
text: t("sync_indicator.disabled"),
}
}
default: {
return {
icon: PhCloudCheck,
text: t("sync_indicator.synced"),
}
}
}
}, [isOnline, canSync, t])

return (
<Tooltip>
<TooltipTrigger asChild>
<div className="center absolute right-2 size-5">
{isOnline ? <PhCloudCheck className="size-4" /> : <PhCloudX className="size-4" />}
<metaInfo.icon className="size-4" />
</div>
</TooltipTrigger>
<TooltipContent>
<div className="text-center text-xs">
{isOnline ? t("sync_indicator.synced") : t("sync_indicator.offline")}
</div>
<div className="text-center text-xs">{metaInfo.text}</div>
</TooltipContent>
</Tooltip>
)
Expand Down
21 changes: 21 additions & 0 deletions src/renderer/src/modules/settings/modal/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { useModalStack } from "@renderer/components/ui/modal/stacked/hooks"
import { NoopChildren } from "@renderer/components/ui/modal/stacked/utils"
import type { ExtractAtomValue, PrimitiveAtom } from "jotai"
import { atom, useAtomValue, useSetAtom } from "jotai"
import { createElement, useCallback } from "react"
import { createContext, useContextSelector } from "use-context-selector"

import { SettingModalContent } from "./content"

Expand All @@ -22,3 +25,21 @@ export const useSettingModal = () => {
[present],
)
}

interface Ctx {
canSync: PrimitiveAtom<boolean>
}
export const defaultCtx: Ctx = {
canSync: atom(true),
}
export const SettingContext = createContext<Ctx>(defaultCtx)

export const useSettingContextSelector = <T>(selector: (state: Ctx) => T) => {
// @ts-expect-error
return useAtomValue(useContextSelector(SettingContext, selector)) as ExtractAtomValue<T>
}

export const useSetSettingCanSync = () => {
const canSync = useContextSelector(SettingContext, (s) => s.canSync)
return useSetAtom(canSync)
}
97 changes: 50 additions & 47 deletions src/renderer/src/modules/settings/modal/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ import type { PointerEventHandler, PropsWithChildren } from "react"
import { Suspense, useCallback, useEffect, useRef } from "react"

import { settings } from "../constants"
import { SyncIndicator } from "../helper/SyncIndicator"
import { SettingSyncIndicator } from "../helper/SyncIndicator"
import { SettingsSidebarTitle } from "../title"
import { useSetSettingTab, useSettingTab } from "./context"
import { defaultCtx, SettingContext } from "./hooks"

export function SettingModalLayout(
props: PropsWithChildren<{
Expand Down Expand Up @@ -74,55 +75,57 @@ export function SettingModalLayout(
cursor: "grabbing",
}}
>
<Resizable
onResizeStart={handlePointDown}
enable={{
bottomRight: true,
}}
style={{ ...resizeableStyle, position: "static" }}
defaultSize={{
width: 800,
height: 700,
}}
maxHeight="80vh"
minHeight={500}
minWidth={600}
maxWidth="95vw"
className="flex flex-col"
>
{draggable && (
<div className="absolute inset-x-0 top-0 z-[1] h-8" onPointerDown={handleDrag} />
)}
<div className="flex h-0 flex-1 bg-theme-modal-background-opaque" ref={elementRef}>
<div className="flex min-h-0 w-44 flex-col border-r px-2 py-6">
<div className="mb-4 flex h-8 items-center gap-2 px-2 font-bold">
<Logo className="mr-1 size-6" />
{APP_NAME}
</div>
<nav className="flex grow flex-col">
{settings.map((t) => (
<button
key={t.path}
className={`my-0.5 flex w-full items-center rounded-lg px-2.5 py-0.5 leading-loose text-theme-foreground/70 transition-colors ${
tab === t.path ? "bg-theme-item-active text-theme-foreground/90" : ""
}`}
type="button"
onClick={() => setTab(t.path)}
>
<SettingsSidebarTitle path={t.path} className="text-[0.94rem] font-medium" />
</button>
))}
</nav>
<SettingContext.Provider value={defaultCtx}>
<Resizable
onResizeStart={handlePointDown}
enable={{
bottomRight: true,
}}
style={{ ...resizeableStyle, position: "static" }}
defaultSize={{
width: 800,
height: 700,
}}
maxHeight="80vh"
minHeight={500}
minWidth={600}
maxWidth="95vw"
className="flex flex-col"
>
{draggable && (
<div className="absolute inset-x-0 top-0 z-[1] h-8" onPointerDown={handleDrag} />
)}
<div className="flex h-0 flex-1 bg-theme-modal-background-opaque" ref={elementRef}>
<div className="flex min-h-0 w-44 flex-col border-r px-2 py-6">
<div className="mb-4 flex h-8 items-center gap-2 px-2 font-bold">
<Logo className="mr-1 size-6" />
{APP_NAME}
</div>
<nav className="flex grow flex-col">
{settings.map((t) => (
<button
key={t.path}
className={`my-0.5 flex w-full items-center rounded-lg px-2.5 py-0.5 leading-loose text-theme-foreground/70 transition-colors ${
tab === t.path ? "bg-theme-item-active text-theme-foreground/90" : ""
}`}
type="button"
onClick={() => setTab(t.path)}
>
<SettingsSidebarTitle path={t.path} className="text-[0.94rem] font-medium" />
</button>
))}
</nav>

<div className="relative -mb-5 h-8 shrink-0">
<SyncIndicator />
<div className="relative -mb-5 h-8 shrink-0">
<SettingSyncIndicator />
</div>
</div>
<div className="relative flex h-full flex-1 flex-col bg-theme-background pt-1">
<Suspense>{children}</Suspense>
</div>
</div>
<div className="relative flex h-full flex-1 flex-col bg-theme-background pt-1">
<Suspense>{children}</Suspense>
</div>
</div>
</Resizable>
</Resizable>
</SettingContext.Provider>
</m.div>
</div>
)
Expand Down
Loading

0 comments on commit 945ddda

Please sign in to comment.