tangled
alpha
login
or
join now
shi.gg
/
mellow-web
4
fork
atom
The weeb for the next gen discord boat - Wamellow
wamellow.com
bot
discord
4
fork
atom
overview
issues
pulls
pipelines
add image v2
shi.gg
4 months ago
0fa4bef1
30ff8f8e
verified
This commit was signed with the committer's
known signature
.
shi.gg
SSH Key Fingerprint:
SHA256:f/mKQ+wsL4JFEMsfMBVIpFfwyYH0N5+n6IHwZA0Q+U0=
+23
-21
3 changed files
expand all
collapse all
unified
split
app
dashboard
[guildId]
greeting
farewell
page.tsx
welcome
page.tsx
components
inputs
image-url-input.tsx
+1
-1
app/dashboard/[guildId]/greeting/farewell/page.tsx
···
88
defaultMessage={data.message}
89
messageAttachmentComponent={(guild!.flags & GuildFlags.FarewellCard) !== 0 && (
90
<Image
91
-
src={`https://image-api.wamellow.com/?type=leave&username=${encodeURIComponent(user!.username)}&members=1090&hash=${encodeURIComponent(user!.id)}/${encodeURIComponent(user!.avatar!)}${data.card.background ? `&background=${encodeURIComponent(data.card.background)}` : ""}`}
92
width={1_024 / 2}
93
height={(256 + 16) / 2}
94
loading="lazy"
···
88
defaultMessage={data.message}
89
messageAttachmentComponent={(guild!.flags & GuildFlags.FarewellCard) !== 0 && (
90
<Image
91
+
src={`https://images-v2.wamellow.com/api/greet?type=leave&username=${encodeURIComponent(user!.username)}&member_count=${guild!.memberCount}&avatar_url=${encodeURIComponent(`https://cdn.discordapp.com/avatars/${user!.id}/${user!.avatar!}.png`)}${data.card.background ? `&background_url=${encodeURIComponent(data.card.background)}` : ""}`}
92
width={1_024 / 2}
93
height={(256 + 16) / 2}
94
loading="lazy"
+1
-1
app/dashboard/[guildId]/greeting/welcome/page.tsx
···
181
defaultMessage={data.message}
182
messageAttachmentComponent={(guild!.flags & GuildFlags.WelcomeCard) !== 0 && (
183
<Image
184
-
src={`https://image-api.wamellow.com/?type=join&username=${encodeURIComponent(user!.username)}&members=1090&hash=${encodeURIComponent(user!.id)}/${encodeURIComponent(user!.avatar!)}${data.card.background ? `&background=${encodeURIComponent(data.card.background)}` : ""}`}
185
width={1_024 / 2}
186
height={(256 + 16) / 2}
187
loading="lazy"
···
181
defaultMessage={data.message}
182
messageAttachmentComponent={(guild!.flags & GuildFlags.WelcomeCard) !== 0 && (
183
<Image
184
+
src={`https://images-v2.wamellow.com/api/greet?type=join&username=${encodeURIComponent(user!.username)}&member_count=${guild!.memberCount}&avatar_url=${encodeURIComponent(`https://cdn.discordapp.com/avatars/${user!.id}/${user!.avatar!}.png`)}${data.card.background ? `&background_url=${encodeURIComponent(data.card.background)}` : ""}`}
185
width={1_024 / 2}
186
height={(256 + 16) / 2}
187
loading="lazy"
+21
-19
components/inputs/image-url-input.tsx
···
11
Success = 2
12
}
13
0
0
0
0
0
14
interface Props {
15
name: string;
16
url: string;
···
38
39
const [value, setValue] = useState<string>("");
40
const [defaultStatealue, setdefaultStatealue] = useState<string>("");
41
-
const [imagestate, setImagestate] = useState<"ERRORED" | "SUCCESS" | undefined>(undefined);
42
43
useEffect(() => {
44
if (!defaultStatealue) setdefaultStatealue(defaultState);
···
46
}, [defaultState]);
47
48
useEffect(() => {
49
-
if (!value?.length) setImagestate("SUCCESS");
50
-
// else setImagestate(undefind);
51
}, [value]);
52
53
useEffect(() => {
54
-
if (imagestate !== "SUCCESS" || defaultStatealue === value) return;
55
setError(null);
56
setState(State.Loading);
57
···
101
102
<div className="flex items-center gap-2">
103
<span className="text-lg dark:text-neutral-300 text-neutral-700 font-medium">{name}</span>
104
-
{state === State.Success && <TailSpin stroke="#d4d4d4" strokeWidth={8} className="relative h-3 w-3 overflow-visible" />}
105
</div>
106
107
<div className="lg:flex mt-1 w-full gap-4">
···
111
setValue={(v) => {
112
setValue(v);
113
setState(State.Idle);
114
-
if (imagestate === "SUCCESS") setImagestate(undefined);
115
}}
116
disabled={disabled}
117
placeholder="Paste a direct image url..."
···
121
122
<div className="max-w-1/2 w-full">
123
124
-
{value && imagestate !== "ERRORED" ?
125
/* eslint-disable-next-line @next/next/no-img-element */
126
<img
127
src={value}
128
alt="upload"
129
-
className={cn("w-full", "rounded-md", "aspect-4/1")}
130
-
onError={() => setImagestate("ERRORED")}
131
-
onLoad={() => setImagestate("SUCCESS")}
132
/>
133
:
134
<div className={cn(
135
"w-full border-2 rounded-md flex items-center justify-center dark:border-wamellow border-wamellow-100",
136
-
imagestate === "ERRORED" && "dark:border-red-500 border-red-300",
137
ratio
138
)}>
139
-
{imagestate === "ERRORED" ?
140
<div className="text-red-400 m-4">
141
-
<div className="font-medium">Enter a <span className="underline underline-red-400">valid</span> image url!</div>
142
<div className="text-xs">
143
<div>Recommended resolution: 1024x256</div>
144
-
<div>Recommended type: .png</div>
145
</div>
146
{/* eslint-disable-next-line @next/next/no-img-element */}
147
<img
148
src={value}
149
-
alt="upload"
150
className="w-0 h-0"
151
-
onLoad={() => setImagestate("SUCCESS")}
152
/>
153
</div>
154
:
···
162
</div>
163
164
<div className="flex">
165
-
{error &&
166
<div className="ml-auto text-red-500 text-sm">
167
{error}
168
</div>
169
-
}
170
</div>
171
-
172
</div>
173
);
174
}
···
11
Success = 2
12
}
13
14
+
enum ImageState {
15
+
Errored = 1,
16
+
Success = 2
17
+
}
18
+
19
interface Props {
20
name: string;
21
url: string;
···
43
44
const [value, setValue] = useState<string>("");
45
const [defaultStatealue, setdefaultStatealue] = useState<string>("");
46
+
const [imagestate, setImagestate] = useState<ImageState | undefined>(undefined);
47
48
useEffect(() => {
49
if (!defaultStatealue) setdefaultStatealue(defaultState);
···
51
}, [defaultState]);
52
53
useEffect(() => {
54
+
if (!value?.length) setImagestate(ImageState.Success);
0
55
}, [value]);
56
57
useEffect(() => {
58
+
if (imagestate !== ImageState.Success || defaultStatealue === value) return;
59
setError(null);
60
setState(State.Loading);
61
···
105
106
<div className="flex items-center gap-2">
107
<span className="text-lg dark:text-neutral-300 text-neutral-700 font-medium">{name}</span>
108
+
{state === State.Loading && <TailSpin stroke="#d4d4d4" strokeWidth={8} className="relative h-3 w-3 overflow-visible" />}
109
</div>
110
111
<div className="lg:flex mt-1 w-full gap-4">
···
115
setValue={(v) => {
116
setValue(v);
117
setState(State.Idle);
118
+
if (imagestate === ImageState.Success) setImagestate(undefined);
119
}}
120
disabled={disabled}
121
placeholder="Paste a direct image url..."
···
125
126
<div className="max-w-1/2 w-full">
127
128
+
{value && imagestate !== ImageState.Errored ?
129
/* eslint-disable-next-line @next/next/no-img-element */
130
<img
131
src={value}
132
alt="upload"
133
+
className={cn("rounded-lg w-full h-full object-cover aspect-906/256", ratio)}
134
+
onError={() => setImagestate(ImageState.Errored)}
135
+
onLoad={() => setImagestate(ImageState.Success)}
136
/>
137
:
138
<div className={cn(
139
"w-full border-2 rounded-md flex items-center justify-center dark:border-wamellow border-wamellow-100",
140
+
imagestate === ImageState.Errored && "dark:border-red-500 border-red-300",
141
ratio
142
)}>
143
+
{imagestate === ImageState.Errored ?
144
<div className="text-red-400 m-4">
145
+
<div className="font-medium">Enter a valid image url!</div>
146
<div className="text-xs">
147
<div>Recommended resolution: 1024x256</div>
148
+
<div>Supported types: .png, .jpg, .jpeg, .webp</div>
149
</div>
150
{/* eslint-disable-next-line @next/next/no-img-element */}
151
<img
152
src={value}
0
153
className="w-0 h-0"
154
+
onLoad={() => setImagestate(ImageState.Success)}
155
/>
156
</div>
157
:
···
165
</div>
166
167
<div className="flex">
168
+
{error && (
169
<div className="ml-auto text-red-500 text-sm">
170
{error}
171
</div>
172
+
)}
173
</div>
0
174
</div>
175
);
176
}