Skip to content

Commit 923c148

Browse files
committed
feat: Make compatible with AnyShake Observer v4.2.0
1 parent d06fd74 commit 923c148

4 files changed

Lines changed: 112 additions & 39 deletions

File tree

src/Wizard.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,11 @@ export const Wizard = () => {
4141

4242
<div className="animate-fade-down animate-delay-500 p-4 md:w-1/2">
4343
<div className="sticky top-4 overflow-y-auto rounded-lg md:h-[calc(100vh-2rem)]">
44-
<CodeBlock language={schemaConfig.language} fileName={schemaConfig.fileName}>
44+
<CodeBlock
45+
language={schemaConfig.language}
46+
fileName={schemaConfig.fileName}
47+
badge={schemaConfig.compatibility}
48+
>
4549
{JSON.stringify(currentConfig, null, 4)}
4650
</CodeBlock>
4751
</div>

src/components/CodeBlock.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ interface ICodeBlock {
1111
readonly language?: string;
1212
readonly fileName?: string;
1313
readonly children: string;
14+
readonly badge?: string;
1415
}
1516

16-
export const CodeBlock = ({ fileName, language, children }: ICodeBlock) => {
17+
export const CodeBlock = ({ fileName, language, children, badge }: ICodeBlock) => {
1718
const [isCopied, setIsCopied] = useState(false);
1819

1920
const handleCopy = useCallback(async (text: string) => {
@@ -36,7 +37,10 @@ export const CodeBlock = ({ fileName, language, children }: ICodeBlock) => {
3637
return (
3738
<div className="rounded-lg bg-gray-700 p-2">
3839
<div className="flex items-center justify-between px-3">
39-
<span className="font-mono text-sm text-gray-300">{fileName ?? 'Code'}</span>
40+
<div className="flex items-center justify-center space-x-2">
41+
<span className="font-mono text-sm text-gray-300">{fileName ?? 'Code'}</span>
42+
{badge?.length && <div className="badge badge-sm badge-accent">{badge}</div>}
43+
</div>
4044
<div className="flex space-x-3">
4145
<div
4246
className="cursor-pointer opacity-60 transition-all hover:opacity-100"

src/config/schema.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export interface ISchema {
2323
interface ISchemaConfig {
2424
readonly fileName: string;
2525
readonly language: string;
26+
readonly compatibility: string;
2627
readonly schema: Record<
2728
string,
2829
{
@@ -37,6 +38,7 @@ interface ISchemaConfig {
3738
export const schemaConfig: ISchemaConfig = {
3839
fileName: 'config.json',
3940
language: 'json',
41+
compatibility: 'v4.2.0+',
4042
schema: {
4143
location: {
4244
icon: mdiMapMarker,

src/schemas/ntpclient.tsx

Lines changed: 99 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
import { mdiMinus, mdiPlus } from '@mdi/js';
2+
import Icon from '@mdi/react';
13
import { ChangeEvent, useCallback, useEffect, useRef, useState } from 'react';
24

35
import { ISchema } from '../config/schema';
46
import { sendUserAlert } from '../helpers/alert/sendUserAlert';
57

68
const defaultConfig = {
7-
endpoint: 'ntp://pool.ntp.org:123',
9+
pool: [''],
810
timeout: 5,
911
retry: 5
1012
};
@@ -19,20 +21,68 @@ export const NtpClient = ({ onCreate, onUpdate }: ISchema) => {
1921
}
2022
}, [currentConfig, onCreate]);
2123

22-
const [ntpHostname, setNtpHostname] = useState('pool.ntp.org');
23-
const [ntpPort, setNtpPort] = useState('123');
24+
const [ntpAddrs, setNtpAddrs] = useState([
25+
{ address: 'ntp-a2.nict.go.jp', port: '123' },
26+
{ address: 'ntp-a3.nict.go.jp', port: '123' },
27+
{ address: 'ntp-b2.nict.go.jp', port: '123' },
28+
{ address: 'ntp-b3.nict.go.jp', port: '123' },
29+
{ address: 'ntp-k1.nict.jp', port: '123' },
30+
{ address: 'ptbtime1.ptb.de', port: '123' },
31+
{ address: 'ptbtime2.ptb.de', port: '123' },
32+
{ address: 'ptbtime3.ptb.de', port: '123' },
33+
{ address: 'stdtime.gov.hk', port: '123' },
34+
{ address: 'time1.chu.nrc.ca', port: '123' },
35+
{ address: 'time2.chu.nrc.ca', port: '123' },
36+
{ address: 'ntp.metas.ch', port: '123' },
37+
{ address: 'hora.roa.es', port: '123' },
38+
{ address: 'minuto.roa.es', port: '123' }
39+
]);
2440

25-
const updateEndpoint = useCallback(() => {
26-
const url = new URL('ntp://');
27-
url.hostname = ntpHostname;
28-
url.port = ntpPort;
29-
return url.toString();
30-
}, [ntpHostname, ntpPort]);
41+
const handleUpdateNtpAddr = (index: number, value: string) => {
42+
setNtpAddrs((prev) =>
43+
prev.map((item, i) => (i === index ? { ...item, address: value } : item))
44+
);
45+
};
46+
47+
const handleUpdateNtpPort = (index: number, value: number) => {
48+
if (value < 0 || value > 65535) {
49+
sendUserAlert('Port must be between 0 and 65535', true);
50+
return;
51+
}
52+
setNtpAddrs((prev) => {
53+
const newNtpAddrs = [...prev];
54+
newNtpAddrs[index] = { ...newNtpAddrs[index], port: String(value) };
55+
return newNtpAddrs;
56+
});
57+
};
58+
59+
const handleAddNtpItem = () => {
60+
setNtpAddrs([...ntpAddrs, { address: '', port: '123' }]);
61+
};
62+
63+
const handleRemoveNtpItem = (index: number) => {
64+
if (ntpAddrs.length > 1) {
65+
setNtpAddrs(ntpAddrs.filter((_, i) => i !== index));
66+
} else {
67+
sendUserAlert('At least one address is required', true);
68+
}
69+
};
70+
71+
const updatePool = useCallback(() => {
72+
return ntpAddrs
73+
.filter((addr) => addr.address.length > 0)
74+
.map((addr) => {
75+
const url = new URL('ntp://');
76+
url.hostname = addr.address;
77+
url.port = addr.port;
78+
return url.toString();
79+
});
80+
}, [ntpAddrs]);
3181

3282
useEffect(() => {
33-
const newEndpoint = updateEndpoint();
34-
setCurrentConfig((prev) => ({ ...prev, endpoint: newEndpoint }));
35-
}, [updateEndpoint]);
83+
const newPool = updatePool();
84+
setCurrentConfig((prev) => ({ ...prev, pool: newPool }));
85+
}, [updatePool]);
3686

3787
const prevConfigRef = useRef(currentConfig);
3888
useEffect(() => {
@@ -55,30 +105,43 @@ export const NtpClient = ({ onCreate, onUpdate }: ISchema) => {
55105
return (
56106
<fieldset className="fieldset bg-base-200 border-base-300 rounded-box space-y-2 border p-4">
57107
<div className="flex flex-col space-y-2">
58-
<label className="label">NTP Server Hostname</label>
59-
<input
60-
type="text"
61-
className="input w-full"
62-
value={ntpHostname}
63-
onChange={({ target }) => setNtpHostname(target.value)}
64-
/>
65-
</div>
66-
67-
<div className="flex flex-col space-y-2">
68-
<label className="label">NTP Server Port</label>
69-
<input
70-
type="number"
71-
className="input w-full"
72-
value={ntpPort}
73-
onChange={({ target }) => {
74-
const numVal = Number(target.value);
75-
if (numVal < 0 || numVal > 65535) {
76-
sendUserAlert('Port must be between 0 and 65535', true);
77-
return;
78-
}
79-
setNtpPort(target.value);
80-
}}
81-
/>
108+
{ntpAddrs.map((addr, index) => (
109+
<div className="flex items-center justify-center space-x-2" key={index}>
110+
<div className="w-1/2 space-y-2 lg:w-4/6">
111+
<label className="label">Host {index + 1}</label>
112+
<input
113+
type="text"
114+
className="input w-full"
115+
value={addr.address}
116+
placeholder='e.g. "ntp-a2.nict.go.jp"'
117+
onChange={({ target }) => handleUpdateNtpAddr(index, target.value)}
118+
/>
119+
</div>
120+
<div className="w-1/2 space-y-2 lg:w-2/6">
121+
<label className="label">Port</label>
122+
<input
123+
type="number"
124+
className="input w-full"
125+
value={addr.port}
126+
onChange={({ target }) =>
127+
handleUpdateNtpPort(index, Number(target.value))
128+
}
129+
/>
130+
</div>
131+
<button
132+
className="btn btn-circle btn-sm mt-6 bg-red-400 hover:bg-red-500"
133+
onClick={() => handleRemoveNtpItem(index)}
134+
>
135+
<Icon className="text-white" path={mdiMinus} size={0.8} />
136+
</button>
137+
</div>
138+
))}
139+
<button
140+
className="btn btn-circle btn-sm bg-purple-500 hover:bg-purple-600"
141+
onClick={handleAddNtpItem}
142+
>
143+
<Icon className="text-white" path={mdiPlus} size={0.8} />
144+
</button>
82145
</div>
83146

84147
<div className="flex flex-col space-y-2">

0 commit comments

Comments
 (0)