Skip to content

Commit 68e2d71

Browse files
authored
feat: add Quick Link page (#67)
1 parent bd05d32 commit 68e2d71

File tree

2 files changed

+148
-0
lines changed

2 files changed

+148
-0
lines changed

sdk-playground/packages/client/src/App.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import OrientationLockState from './pages/OrientationLockState';
2121
import OrientationUpdates from './pages/OrientationUpdates';
2222
import LayoutMode from './pages/LayoutMode';
2323
import PlatformBehaviors from './pages/PlatformBehaviors';
24+
import QuickLink from './pages/QuickLink';
2425
import ShareLink from './pages/ShareLink';
2526
import VoiceState from './pages/VoiceState';
2627
import VisibilityListener from './pages/VisibilityListener';
@@ -137,6 +138,11 @@ const routes: Record<string, AppRoute> = {
137138
name: 'Open Share Moment Dialog',
138139
component: OpenShareMomentDialog,
139140
},
141+
quickLink: {
142+
path: '/quick-link',
143+
name: 'Quick Link',
144+
component: QuickLink,
145+
},
140146
shareLink: {
141147
path: '/share-link',
142148
name: 'Share Link',
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
import React from 'react';
2+
import discordSdk from '../discordSdk';
3+
import {DiscordAPI, RequestType} from '../DiscordAPI';
4+
import {authStore} from '../stores/authStore';
5+
6+
function arrayBufferToString(maybeBuffer: ArrayBuffer | string): string {
7+
return typeof maybeBuffer === 'string' ? maybeBuffer : new TextDecoder().decode(maybeBuffer);
8+
}
9+
10+
function fileToBase64(file: File) {
11+
return new Promise<string>((resolve, reject) => {
12+
const reader = new FileReader();
13+
reader.readAsDataURL(file);
14+
15+
reader.onload = (ev) => {
16+
if (ev.target == null) {
17+
return;
18+
}
19+
const {result} = ev.target;
20+
if (result == null || result === '') {
21+
return;
22+
}
23+
const imageString = arrayBufferToString(result);
24+
resolve(imageString);
25+
};
26+
reader.onerror = (error) => reject(error);
27+
});
28+
}
29+
30+
export default function QuickLink() {
31+
const applicationId = import.meta.env.VITE_APPLICATION_ID;
32+
const [title, setTitle] = React.useState<string>('Baby Brick');
33+
const [description, setDescription] = React.useState<string>('I\'m small but mighty...just like a Brick!');
34+
const [customId, setCustomId] = React.useState<string | undefined >(undefined);
35+
const [image, setImage] = React.useState<string | undefined>();
36+
37+
const [hasPressedSend, setHasPressedSend] = React.useState<boolean>(false);
38+
const [didSend, setDidSend] = React.useState<boolean>(false);
39+
40+
const inputImageRef = React.useRef<HTMLInputElement>(null);
41+
42+
const onImageChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
43+
const file = event.target.files?.[0];
44+
if (file == null) {
45+
return;
46+
}
47+
const image = await fileToBase64(file);
48+
setImage(image);
49+
};
50+
51+
const handleTitleChange= (event: React.ChangeEvent<HTMLInputElement>) => {
52+
setTitle(event.target.value);
53+
};
54+
const handleDescriptionChange= (event: React.ChangeEvent<HTMLTextAreaElement>) => {
55+
setDescription(event.target.value);
56+
};
57+
const handleCustomIdChange = (event: React.ChangeEvent<HTMLInputElement>) => {
58+
setCustomId(event.target.value);
59+
};
60+
61+
const auth = authStore.getState();
62+
63+
64+
const doShareLink = async () => {
65+
// Generate the quick activity link
66+
const {link_id} = await DiscordAPI.request<{link_id: string}>(
67+
{
68+
method: RequestType.POST,
69+
endpoint: `/applications/${applicationId}/quick-links/`,
70+
headers: {
71+
'Content-Type': 'application/json',
72+
},
73+
body: {
74+
custom_id: customId,
75+
description,
76+
image,
77+
title,
78+
},
79+
stringifyBody: true,
80+
},
81+
auth.access_token,
82+
);
83+
84+
// Open the Share modal with the generated link
85+
const {success} = await discordSdk.commands.shareLink({
86+
message: 'Come try out new features!',
87+
link_id: link_id
88+
});
89+
90+
setHasPressedSend(true);
91+
setDidSend(success);
92+
};
93+
94+
return (
95+
<div style={{padding: 32}}>
96+
<p> Image: </p>
97+
<input
98+
accept="image/jpeg, image/jpg, image/png"
99+
name="image"
100+
onChange={onImageChange}
101+
ref={inputImageRef}
102+
type="file"
103+
/>
104+
<br />
105+
106+
<p> Title: </p>
107+
<input
108+
value={title}
109+
onChange={handleTitleChange}
110+
placeholder="Type a title for the embed"
111+
style={{ width: '400px', padding: '8px' }}
112+
/>
113+
<br/>
114+
115+
<p> Description: </p>
116+
<textarea
117+
value={description}
118+
onChange={handleDescriptionChange}
119+
placeholder="Type a description for the embed"
120+
style={{ width: '400px', padding: '8px' }}
121+
/>
122+
<br/>
123+
<p> Custom ID: </p>
124+
<input
125+
type="text"
126+
value={customId}
127+
onChange={handleCustomIdChange}
128+
placeholder="What's your custom ID?"
129+
style={{ width: '400px', padding: '8px' }}
130+
/>
131+
<br/>
132+
<br/>
133+
134+
<p>
135+
Clicking the button will generate a quick link and open the share link dialog
136+
</p>
137+
138+
<button onClick={doShareLink}>Click to Share</button>
139+
{ hasPressedSend ? (didSend ? (<p> Succesfully shared! </p>) : (<p> Did not share </p>)) : null }
140+
</div>
141+
);
142+
}

0 commit comments

Comments
 (0)