Skip to content

Commit 4658fe2

Browse files
authored
feat: update syncing light (#2043)
1 parent 191662d commit 4658fe2

File tree

5 files changed

+93
-82
lines changed

5 files changed

+93
-82
lines changed

apps/namadillo/src/App/Common/PulsingRing.tsx

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@ import { useScope } from "hooks/useScope";
44
import { useRef } from "react";
55
import { twMerge } from "tailwind-merge";
66

7-
type PulsingRingProps = { className?: string };
7+
type PulsingRingProps = { className?: string; size?: "small" | "large" };
88

9-
export const PulsingRing = ({ className }: PulsingRingProps): JSX.Element => {
9+
export const PulsingRing = ({
10+
className,
11+
size = "large",
12+
}: PulsingRingProps): JSX.Element => {
1013
const containerRef = useRef<HTMLDivElement>(null);
1114

1215
useScope(
@@ -46,9 +49,10 @@ export const PulsingRing = ({ className }: PulsingRingProps): JSX.Element => {
4649
[]
4750
);
4851

49-
const renderRing = (className: string): JSX.Element => {
52+
const renderRing = (className: string, key?: number): JSX.Element => {
5053
return (
5154
<span
55+
key={key}
5256
data-animation="ring"
5357
className={clsx(
5458
"block absolute aspect-square border border-yellow rounded-full",
@@ -59,14 +63,17 @@ export const PulsingRing = ({ className }: PulsingRingProps): JSX.Element => {
5963
);
6064
};
6165

66+
const ringSizes =
67+
size === "small" ?
68+
["h-[0.75em]", "h-[1.35em]", "h-[1.95em]"]
69+
: ["h-[1.8em]", "h-[3em]", "h-[4.2em]"];
70+
6271
return (
6372
<span
6473
ref={containerRef}
6574
className={twMerge("block relative leading-0", className)}
6675
>
67-
{renderRing("h-[1.8em]")}
68-
{renderRing("h-[3em]")}
69-
{renderRing("h-[4.2em]")}
76+
{ringSizes.map((sizeClass, index) => renderRing(sizeClass, index))}
7077
</span>
7178
);
7279
};

apps/namadillo/src/App/Layout/Sidebar.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
1-
import { ShieldedSyncProgress } from "App/Masp/ShieldedSyncProgress";
21
import { EpochInformation } from "App/Sidebars/EpochInformation";
32
import { ReactNode } from "react";
43

54
export const Sidebar = ({ children }: { children: ReactNode }): JSX.Element => {
65
return (
76
<aside className="flex flex-col gap-2 mt-1.5 lg:mt-0">
87
<EpochInformation />
9-
<ShieldedSyncProgress />
108
{children}
119
</aside>
1210
);
Lines changed: 70 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import { Tooltip } from "@namada/components";
22
import { indexerApiAtom } from "atoms/api";
3+
import { shieldedBalanceAtom, shieldedSyncProgress } from "atoms/balance/atoms";
34
import { fetchBlockHeightByTimestamp } from "atoms/balance/services";
45
import { chainStatusAtom } from "atoms/chain";
56
import {
67
indexerServicesSyncStatusAtom,
78
syncStatusAtom,
89
} from "atoms/syncStatus/atoms";
910
import { useAtomValue } from "jotai";
10-
import { useEffect, useState } from "react";
11+
import { useEffect, useMemo, useState } from "react";
1112
import { twMerge } from "tailwind-merge";
13+
import { PulsingRing } from "../Common/PulsingRing";
1214

1315
const formatError = (
1416
errors: (string | Error)[],
@@ -32,22 +34,28 @@ const formatError = (
3234
export const SyncIndicator = (): JSX.Element => {
3335
const syncStatus = useAtomValue(syncStatusAtom);
3436
const indexerServicesSyncStatus = useAtomValue(indexerServicesSyncStatusAtom);
37+
const api = useAtomValue(indexerApiAtom);
3538
const chainStatus = useAtomValue(chainStatusAtom);
39+
const shieldedProgress = useAtomValue(shieldedSyncProgress);
40+
const { isFetching: isShieldedFetching } = useAtomValue(shieldedBalanceAtom);
3641
const [blockHeightSync, setBlockHeightSync] = useState<boolean | null>(null);
3742
const [indexerBlockHeight, setIndexerBlockHeight] = useState<number | null>(
3843
null
3944
);
45+
const roundedProgress = useMemo(() => {
46+
// Only update when the progress changes by at least 1%
47+
return Math.min(Math.floor(shieldedProgress * 100), 100);
48+
}, [Math.floor(shieldedProgress * 100)]);
49+
4050
const { errors } = syncStatus;
4151
const { services } = indexerServicesSyncStatus;
52+
4253
const isChainStatusError =
4354
!chainStatus?.height || !chainStatus?.epoch || !blockHeightSync;
44-
const api = useAtomValue(indexerApiAtom);
45-
4655
const isError =
4756
syncStatus.isError ||
4857
indexerServicesSyncStatus.isError ||
4958
isChainStatusError;
50-
5159
const isSyncing =
5260
syncStatus.isSyncing ||
5361
indexerServicesSyncStatus.isSyncing ||
@@ -65,35 +73,65 @@ export const SyncIndicator = (): JSX.Element => {
6573
}, [chainStatus?.height]);
6674

6775
return (
68-
<div className="relative group/tooltip px-1 py-3">
69-
<div
70-
className={twMerge(
71-
"w-2 h-2 rounded-full",
72-
"bg-green-500",
73-
isSyncing && "bg-yellow-500 animate-pulse",
74-
isError && !isSyncing && "bg-red-500"
75-
)}
76-
/>
77-
<Tooltip
78-
position="bottom"
79-
className="z-10 w-max max-w-[200px] text-balance"
80-
>
81-
{isSyncing ?
82-
"Syncing"
83-
: isError ?
84-
<div>
85-
{formatError(errors, "Error")}
86-
{formatError(services, "Lagging services")}
87-
{isChainStatusError && "Chain status not loaded."}
76+
<div className="flex gap-10 px-2 py-3">
77+
{roundedProgress < 100 && !isShieldedFetching && (
78+
<div className="relative group/tooltip">
79+
<div className="relative mt-1">
80+
<PulsingRing size="small" />
81+
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-2 h-2 bg-yellow-500 rounded-full" />
8882
</div>
89-
: <div>
90-
<div>Fully synced:</div>
91-
<div>RPC Height: {chainStatus?.height}</div>
92-
<div>Indexer Height: {indexerBlockHeight}</div>
93-
<div>Epoch: {chainStatus?.epoch}</div>
94-
</div>
95-
}
96-
</Tooltip>
83+
<Tooltip
84+
position="bottom"
85+
className="z-10 w-max max-w-[220px] rounded-md p-4 -mb-6"
86+
>
87+
<div className="space-y-3">
88+
<div className="text-md text-yellow">
89+
Shielded sync: {roundedProgress}%
90+
</div>
91+
<div className="w-full bg-yellow-900 h-1">
92+
<div
93+
className="bg-yellow-500 h-1 transition-all duration-300"
94+
style={{ width: `${roundedProgress}%` }}
95+
/>
96+
</div>
97+
<div className="text-sm text-neutral-400">
98+
Syncing your shielded assets now. Balances will update in a few
99+
seconds.
100+
</div>
101+
</div>
102+
</Tooltip>
103+
</div>
104+
)}
105+
106+
<div className="relative group/tooltip">
107+
<div
108+
className={twMerge(
109+
"w-2 h-2 rounded-full",
110+
"bg-green-500",
111+
isError && "bg-red-500"
112+
)}
113+
/>
114+
<Tooltip
115+
position="bottom"
116+
className="z-10 w-max max-w-[200px] text-balance -mb-6"
117+
>
118+
{isSyncing ?
119+
"Syncing..."
120+
: isError ?
121+
<div>
122+
{formatError(errors, "Error")}
123+
{formatError(services, "Lagging services")}
124+
{isChainStatusError && "Chain status not loaded."}
125+
</div>
126+
: <div className="py-2">
127+
<div className="text-yellow font-medium">Fully synced:</div>
128+
<div>RPC Height: {chainStatus?.height}</div>
129+
<div>Indexer Height: {indexerBlockHeight}</div>
130+
<div>Epoch: {chainStatus?.epoch}</div>
131+
</div>
132+
}
133+
</Tooltip>
134+
</div>
97135
</div>
98136
);
99137
};

apps/namadillo/src/App/Layout/TopNavigation.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -91,16 +91,6 @@ export const TopNavigation = (): JSX.Element => {
9191

9292
<div className="flex-1" />
9393

94-
<button
95-
className="text-2xl text-yellow hover:text-cyan"
96-
onClick={() =>
97-
navigate(routes.settings, {
98-
state: { backgroundLocation: location },
99-
})
100-
}
101-
>
102-
<IoSettingsOutline />
103-
</button>
10494
{defaultAccount.data?.type !== AccountType.Ledger &&
10595
signArbitraryEnabled && (
10696
<button
@@ -118,6 +108,16 @@ export const TopNavigation = (): JSX.Element => {
118108

119109
<TransactionInProgressSpinner />
120110
<SyncIndicator />
111+
<button
112+
className="text-2xl text-yellow hover:text-cyan"
113+
onClick={() =>
114+
navigate(routes.settings, {
115+
state: { backgroundLocation: location },
116+
})
117+
}
118+
>
119+
<IoSettingsOutline />
120+
</button>
121121
<div className="h-[50px] flex gap-1">
122122
<NamadaAccount />
123123
<KeplrAccount />

apps/namadillo/src/App/Masp/ShieldedSyncProgress.tsx

Lines changed: 0 additions & 32 deletions
This file was deleted.

0 commit comments

Comments
 (0)