Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit07c9967

Browse files
committed
refactor: change core clipboard hook API
1 parent1783ee1 commit07c9967

File tree

8 files changed

+83
-74
lines changed

8 files changed

+83
-74
lines changed

‎site/src/components/CopyButton/CopyButton.tsx‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,7 @@ export const CopyButton: FC<CopyButtonProps> = ({
1919
label,
2020
...buttonProps
2121
})=>{
22-
const{ showCopiedSuccess, copyToClipboard}=useClipboard({
23-
textToCopy:text,
24-
});
22+
const{ showCopiedSuccess, copyToClipboard}=useClipboard();
2523

2624
return(
2725
<TooltipProvider>
@@ -30,7 +28,7 @@ export const CopyButton: FC<CopyButtonProps> = ({
3028
<Button
3129
size="icon"
3230
variant="subtle"
33-
onClick={copyToClipboard}
31+
onClick={()=>copyToClipboard(text)}
3432
{...buttonProps}
3533
>
3634
{showCopiedSuccess ?<CheckIcon/> :<CopyIcon/>}

‎site/src/components/CopyableValue/CopyableValue.tsx‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ export const CopyableValue: FC<CopyableValueProps> = ({
1616
children,
1717
...attrs
1818
})=>{
19-
const{ showCopiedSuccess, copyToClipboard}=useClipboard({
20-
textToCopy:value,
19+
const{ showCopiedSuccess, copyToClipboard}=useClipboard();
20+
constclickableProps=useClickable<HTMLSpanElement>(()=>{
21+
copyToClipboard(value);
2122
});
22-
constclickableProps=useClickable<HTMLSpanElement>(copyToClipboard);
2323

2424
return(
2525
<Tooltip

‎site/src/hooks/useClickable.ts‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
typeRefObject,
55
useRef,
66
}from"react";
7+
import{useEffectEvent}from"./hookPolyfills";
78

89
// Literally any object (ideally an HTMLElement) that has a .click method
910
typeClickableElement={
@@ -43,10 +44,11 @@ export const useClickable = <
4344
role?:TRole,
4445
):UseClickableResult<TElement,TRole>=>{
4546
constref=useRef<TElement>(null);
47+
conststableOnClick=useEffectEvent(onClick);
4648

4749
return{
4850
ref,
49-
onClick,
51+
onClick:stableOnClick,
5052
tabIndex:0,
5153
role:(role??"button")asTRole,
5254

‎site/src/hooks/useClipboard.ts‎

Lines changed: 47 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,21 @@
1-
import{displayError}from"components/GlobalSnackbar/utils";
2-
import{useEffect,useRef,useState}from"react";
1+
/**
2+
* Modified version of the useClipboard hook from Coder core.
3+
*@see {@link https://github.com/coder/coder/blob/main/site/src/hooks/useClipboard.ts}
4+
*/
5+
import{useCallback,useEffect,useRef,useState}from"react";
6+
import{useEffectEvent}from"./hookPolyfills";
37

48
constCLIPBOARD_TIMEOUT_MS=1_000;
59
exportconstCOPY_FAILED_MESSAGE="Failed to copy text to clipboard";
610
exportconstHTTP_FALLBACK_DATA_ID="http-fallback";
711

812
exporttypeUseClipboardInput=Readonly<{
9-
textToCopy:string;
10-
11-
/**
12-
* Optional callback to call when an error happens. If not specified, the hook
13-
* will dispatch an error message to the GlobalSnackbar
14-
*/
1513
onError?:(errorMessage:string)=>void;
14+
clearErrorOnSuccess?:boolean;
1615
}>;
1716

1817
exporttypeUseClipboardResult=Readonly<{
19-
copyToClipboard:()=>Promise<void>;
18+
copyToClipboard:(textToCopy:string)=>Promise<void>;
2019
error:Error|undefined;
2120

2221
/**
@@ -40,47 +39,58 @@ export type UseClipboardResult = Readonly<{
4039
showCopiedSuccess:boolean;
4140
}>;
4241

43-
exportconstuseClipboard=(input:UseClipboardInput):UseClipboardResult=>{
44-
const{ textToCopy,onError:errorCallback}=input;
42+
exportconstuseClipboard=(input?:UseClipboardInput):UseClipboardResult=>{
43+
const{onError:errorCallback, clearErrorOnSuccess=true}=input??{};
44+
4545
const[showCopiedSuccess,setShowCopiedSuccess]=useState(false);
4646
const[error,setError]=useState<Error>();
4747
consttimeoutIdRef=useRef<number|undefined>(undefined);
4848

4949
useEffect(()=>{
50-
constclearIdOnUnmount=()=>window.clearTimeout(timeoutIdRef.current);
51-
returnclearIdOnUnmount;
50+
constclearTimeoutOnUnmount=()=>{
51+
window.clearTimeout(timeoutIdRef.current);
52+
};
53+
returnclearTimeoutOnUnmount;
5254
},[]);
5355

54-
consthandleSuccessfulCopy=()=>{
56+
conststableOnError=useEffectEvent(()=>{
57+
errorCallback?.(COPY_FAILED_MESSAGE);
58+
});
59+
consthandleSuccessfulCopy=useEffectEvent(()=>{
5560
setShowCopiedSuccess(true);
61+
if(clearErrorOnSuccess){
62+
setError(undefined);
63+
}
64+
5665
timeoutIdRef.current=window.setTimeout(()=>{
5766
setShowCopiedSuccess(false);
5867
},CLIPBOARD_TIMEOUT_MS);
59-
};
60-
61-
constcopyToClipboard=async()=>{
62-
try{
63-
awaitwindow.navigator.clipboard.writeText(textToCopy);
64-
handleSuccessfulCopy();
65-
}catch(err){
66-
constfallbackCopySuccessful=simulateClipboardWrite(textToCopy);
67-
if(fallbackCopySuccessful){
68-
handleSuccessfulCopy();
69-
return;
70-
}
68+
});
7169

72-
constwrappedErr=newError(COPY_FAILED_MESSAGE);
73-
if(errinstanceofError){
74-
wrappedErr.stack=err.stack;
70+
constcopyToClipboard=useCallback(
71+
async(textToCopy:string)=>{
72+
try{
73+
awaitwindow.navigator.clipboard.writeText(textToCopy);
74+
handleSuccessfulCopy();
75+
}catch(err){
76+
constfallbackCopySuccessful=simulateClipboardWrite(textToCopy);
77+
if(fallbackCopySuccessful){
78+
handleSuccessfulCopy();
79+
return;
80+
}
81+
82+
constwrappedErr=newError(COPY_FAILED_MESSAGE);
83+
if(errinstanceofError){
84+
wrappedErr.stack=err.stack;
85+
}
86+
87+
console.error(wrappedErr);
88+
setError(wrappedErr);
89+
stableOnError();
7590
}
76-
77-
console.error(wrappedErr);
78-
setError(wrappedErr);
79-
80-
constnotifyUser=errorCallback??displayError;
81-
notifyUser(COPY_FAILED_MESSAGE);
82-
}
83-
};
91+
},
92+
[stableOnError,handleSuccessfulCopy],
93+
);
8494

8595
return{ showCopiedSuccess, error, copyToClipboard};
8696
};

‎site/src/pages/CliAuthPage/CliAuthPageView.tsx‎

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,7 @@ interface CliAuthPageViewProps {
1212
}
1313

1414
exportconstCliAuthPageView:FC<CliAuthPageViewProps>=({ sessionToken})=>{
15-
constclipboard=useClipboard({
16-
textToCopy:sessionToken??"",
17-
});
18-
15+
constclipboardState=useClipboard();
1916
return(
2017
<SignInLayout>
2118
<Welcome>Session token</Welcome>
@@ -30,16 +27,20 @@ export const CliAuthPageView: FC<CliAuthPageViewProps> = ({ sessionToken }) => {
3027
className="w-full"
3128
size="lg"
3229
disabled={!sessionToken}
33-
onClick={clipboard.copyToClipboard}
30+
onClick={()=>{
31+
if(sessionToken){
32+
clipboardState.copyToClipboard(sessionToken);
33+
}
34+
}}
3435
>
35-
{clipboard.showCopiedSuccess ?(
36+
{clipboardState.showCopiedSuccess ?(
3637
<CheckIcon/>
3738
) :(
3839
<Spinnerloading={!sessionToken}>
3940
<CopyIcon/>
4041
</Spinner>
4142
)}
42-
{clipboard.showCopiedSuccess
43+
{clipboardState.showCopiedSuccess
4344
?"Session token copied!"
4445
:"Copy session token"}
4546
</Button>

‎site/src/pages/TaskPage/TaskTopbar.tsx‎

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,14 +81,11 @@ export const TaskTopbar: FC<TaskTopbarProps> = ({ task }) => {
8181
typeCopyPromptButtonProps={prompt:string};
8282

8383
constCopyPromptButton:FC<CopyPromptButtonProps>=({ prompt})=>{
84-
const{ copyToClipboard, showCopiedSuccess}=useClipboard({
85-
textToCopy:prompt,
86-
});
87-
84+
const{ copyToClipboard, showCopiedSuccess}=useClipboard();
8885
return(
8986
<Button
9087
disabled={showCopiedSuccess}
91-
onClick={copyToClipboard}
88+
onClick={()=>copyToClipboard(prompt)}
9289
size="sm"
9390
variant="subtle"
9491
className="p-0 min-w-0"

‎site/src/pages/TemplatePage/TemplateEmbedPage/TemplateEmbedPage.tsx‎

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,7 @@ export const TemplateEmbedPageView: FC<TemplateEmbedPageViewProps> = ({
7474
templateParameters,
7575
})=>{
7676
const[buttonValues,setButtonValues]=useState<ButtonValues|undefined>();
77-
constclipboard=useClipboard({
78-
textToCopy:getClipboardCopyContent(
79-
template.name,
80-
template.organization_name,
81-
buttonValues,
82-
),
83-
});
77+
constclipboard=useClipboard();
8478

8579
// template parameters is async so we need to initialize the values after it
8680
// is loaded
@@ -237,8 +231,15 @@ export const TemplateEmbedPageView: FC<TemplateEmbedPageViewProps> = ({
237231
>
238232
<Button
239233
className="rounded-full"
240-
onClick={clipboard.copyToClipboard}
241234
disabled={clipboard.showCopiedSuccess}
235+
onClick={()=>{
236+
consttextToCopy=getClipboardCopyContent(
237+
template.name,
238+
template.organization_name,
239+
buttonValues,
240+
);
241+
clipboard.copyToClipboard(textToCopy);
242+
}}
242243
>
243244
{clipboard.showCopiedSuccess ?<CheckIcon/> :<CopyIcon/>}
244245
Copy button code

‎site/src/pages/TemplatePage/TemplateEmbedPage/TemplateEmbedPageExperimental.tsx‎

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -289,14 +289,7 @@ interface ButtonPreviewProps {
289289
}
290290

291291
constButtonPreview:FC<ButtonPreviewProps>=({ template, buttonValues})=>{
292-
constclipboard=useClipboard({
293-
textToCopy:getClipboardCopyContent(
294-
template.name,
295-
template.organization_name,
296-
buttonValues,
297-
),
298-
});
299-
292+
constclipboard=useClipboard();
300293
return(
301294
<div
302295
className="sticky top-10 flex gap-16 h-96 flex-1 flex-col items-center justify-center
@@ -305,8 +298,15 @@ const ButtonPreview: FC<ButtonPreviewProps> = ({ template, buttonValues }) => {
305298
<imgsrc="/open-in-coder.svg"alt="Open in Coder button"/>
306299
<Button
307300
variant="default"
308-
onClick={clipboard.copyToClipboard}
309301
disabled={clipboard.showCopiedSuccess}
302+
onClick={()=>{
303+
consttextToCopy=getClipboardCopyContent(
304+
template.name,
305+
template.organization_name,
306+
buttonValues,
307+
);
308+
clipboard.copyToClipboard(textToCopy);
309+
}}
310310
>
311311
{clipboard.showCopiedSuccess ?<CheckOutlined/> :<FileCopyOutlined/>}{" "}
312312
Copy button code

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp