Skip to content

Commit 69dffd5

Browse files
committed
Merge branch 'main' into FROS-Create-Server/Channel-UI
2 parents 92aa930 + e7f7ed1 commit 69dffd5

31 files changed

Lines changed: 697 additions & 220 deletions

.github/workflows/db-tests.yml

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,32 @@
1-
name: Database Tests
1+
# name: Database Tests
22

3-
on: push
3+
# on: push
44

5-
jobs:
6-
test-db:
7-
runs-on: ubuntu-latest
5+
# jobs:
6+
# test-db:
7+
# runs-on: ubuntu-latest
88

9-
env:
10-
SUPABASE_ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }}
11-
PROJECT_ID: ${{ secrets.PROJECT_ID }}
12-
SUPABASE_DATABASE_PASSWORD: ${{ secrets.DATABASE_PASSWORD }}
9+
# env:
10+
# SUPABASE_ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }}
11+
# PROJECT_ID: ${{ secrets.PROJECT_ID }}
12+
# SUPABASE_DATABASE_PASSWORD: ${{ secrets.DATABASE_PASSWORD }}
1313

14-
steps:
15-
- uses: actions/checkout@v3
16-
with:
17-
persist-credentials: false
18-
fetch-depth: 0
14+
# steps:
15+
# - uses: actions/checkout@v3
16+
# with:
17+
# persist-credentials: false
18+
# fetch-depth: 0
1919

20-
- uses: actions/setup-node@v3
21-
with:
22-
node-version: 16
20+
# - uses: actions/setup-node@v3
21+
# with:
22+
# node-version: 16
2323

24-
- uses: supabase/setup-cli@v1
25-
with:
26-
version: latest
24+
# - uses: supabase/setup-cli@v1
25+
# with:
26+
# version: latest
2727

28-
- run: supabase link --project-ref $PROJECT_ID
28+
# - run: supabase link --project-ref $PROJECT_ID
2929

30-
- run: supabase db start
30+
# - run: supabase db start
3131

32-
- run: supabase test db --debug
32+
# - run: supabase test db --debug

components/home/InviteEmbed.tsx

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
import { useServers } from '@/lib/store';
2+
import { getInviteAndServer } from '@/services/invites.service';
3+
import { addUserToServer } from '@/services/profile.service';
4+
import { ServerInvite } from '@/types/dbtypes';
5+
import { useSupabaseClient } from '@supabase/auth-helpers-react';
6+
import { PostgrestError } from '@supabase/supabase-js';
7+
import { useRouter } from 'next/router';
8+
import { useEffect, useState } from 'react';
9+
import InvalidInviteIcon from '../icons/InvalidInviteIcon';
10+
import LoadingIcon from '../icons/LoadingIcon';
11+
import ServersIcon from '../icons/ServersIcon';
12+
import { OverflowMarquee } from './OverflowMarquee';
13+
import { ServerMemberStats } from './ServerMemberStats';
14+
15+
export function InviteEmbed({ invite_code }: { invite_code: string }) {
16+
const servers = useServers();
17+
const supabase = useSupabaseClient();
18+
const router = useRouter();
19+
const [invite, setInvite] = useState<ServerInvite | null>(null);
20+
const [ userInServer, setUserInServer ] = useState<boolean>(false);
21+
const [ error, setErrorText ] = useState<PostgrestError | null>(null);
22+
23+
useEffect(() => {
24+
async function handleAsync() {
25+
const { data, error } = await getInviteAndServer(supabase, invite_code);
26+
27+
if (error) {
28+
setErrorText(error);
29+
return;
30+
}
31+
32+
if (data) {
33+
console.log(data);
34+
setInvite(data);
35+
}
36+
37+
setUserInServer(servers.some((s) => s.server_id === data.servers.id));
38+
};
39+
40+
handleAsync();
41+
}, [invite_code, supabase, servers]);
42+
43+
if (!invite) {
44+
return (
45+
<div className="flex
46+
flex-row
47+
items-center
48+
justify-center
49+
bg-slate-700
50+
p-4
51+
rounded-md
52+
border-solid
53+
border-2
54+
border-slate-800/50
55+
w-full
56+
max-w-xl
57+
overflow-hidden
58+
">
59+
<div className="flex flex-col justify-center space-y-2 items-start max-w-full">
60+
<div className="text-xl font-semibold tracking-wide text-left overflow-hidden w-[45ch]">
61+
{ !!error ? <h1>{error.hint || 'Invalid invite.'}</h1> : <h1>Loading</h1>}
62+
</div>
63+
<div className="flex-shrink-0 bg-zinc-700 p-2 rounded-lg border-solid border-2 border-slate-800/50 ">
64+
{ !!error ? <InvalidInviteIcon className='w-7 h-7 fill-red-400'/> : <LoadingIcon className='w-7 h-7 stroke-frost-300'/> }
65+
</div>
66+
</div>
67+
</div>
68+
);
69+
}
70+
71+
return (
72+
<div className="flex
73+
flex-row
74+
items-center
75+
justify-center
76+
bg-slate-700
77+
p-4
78+
rounded-md
79+
border-solid
80+
border-2
81+
border-slate-800/50
82+
w-full
83+
max-w-xl
84+
overflow-hidden
85+
">
86+
<div className="flex flex-col justify-center space-y-2 items-start max-w-full">
87+
<div className="text-xl font-semibold tracking-wide text-left overflow-hidden w-[45ch]">
88+
<OverflowMarquee
89+
content={`You have been invited to join ${invite.servers.name}!`}
90+
maxLength={50}
91+
/>
92+
</div>
93+
<div className="flex flex-row w-full space-x-3 items-center">
94+
<div className="flex-shrink-0 bg-zinc-700 p-2 rounded-lg border-solid border-2 border-slate-800/50 ">
95+
<ServersIcon
96+
server={invite.servers}
97+
hovered={false}
98+
className='w-7 h-7'
99+
/>
100+
</div>
101+
<div className="flex flex-col justify-center items-start px-2">
102+
{!!invite.servers.description && (
103+
<div className="text-slate-400 font-semibold w-[39ch] flex-grow">
104+
<OverflowMarquee
105+
content={invite.servers.description}
106+
maxLength={40}
107+
/>
108+
</div>
109+
)}
110+
<ServerMemberStats
111+
server={invite.servers}
112+
flexStyle="flex flex-row space-x-4 font-semibold items-center justify-center flex-grow"
113+
/>
114+
</div>
115+
<button
116+
className="bg-green-700
117+
hover:bg-green-600
118+
text-white
119+
font-semibold
120+
py-2
121+
px-4
122+
rounded-md
123+
flex-shrink-0
124+
align-middle
125+
disabled:bg-gray-600
126+
"
127+
disabled={userInServer}
128+
onClick={async () => {
129+
await addUserToServer(supabase, invite.servers.id);
130+
router.push(`/?c=${invite.channel_id}`, '/');
131+
}}
132+
>
133+
{userInServer ? 'Joined' : 'Join'}
134+
</button>
135+
</div>
136+
</div>
137+
</div>
138+
);
139+
}

components/home/MessageContent.tsx

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,50 @@
1+
import { AnchorHTMLAttributes, Fragment } from 'react';
12
import ReactMarkdown from 'react-markdown';
23
import rehypeHighlight from 'rehype-highlight';
34
import rehypeKatex from 'rehype-katex';
45
import remarkBreaks from 'remark-breaks';
56
import remarkGfm from 'remark-gfm';
67
import remarkMath from 'remark-math';
8+
import { InviteEmbed } from './InviteEmbed';
9+
10+
function CustomAnchorTag(props: AnchorHTMLAttributes<HTMLAnchorElement>) {
11+
// If the link is to our domain, let's see if it's a server invite
12+
if (props.href?.startsWith(window.location.href) && props.href?.includes('/invite/')) {
13+
const inviteCode = props.href.split('/invite/')[1];
14+
return (
15+
<>
16+
<a className="text-frost-300" {...props} target="_blank"/>
17+
<InviteEmbed invite_code={inviteCode} />
18+
</>
19+
);
20+
}
21+
22+
return (
23+
<a
24+
data-tooltip-id="link-id"
25+
data-tooltip-place="top"
26+
data-tooltip-content={`${props.href}`}
27+
target="_blank"
28+
className="text-frost-300"
29+
{...props}
30+
>
31+
{props.children}
32+
</a>
33+
);
34+
}
735

836
export default function MessageContent({ messageContent }: { messageContent: string }) {
937
return (
1038
<ReactMarkdown
39+
className='w-full'
1140
components={{
1241
ul: ({ children }) => <ul className="list-disc ml-6">{children}</ul>,
1342
ol: ({ children }) => <ol className="list-decimal ml-6">{children}</ol>,
1443
// TODO: Add support for providing alt text for images
1544
img: (props) => (
1645
<img className="max-w-4xl" alt="Attachment" {...props}></img>
1746
),
18-
a: (props) => (
19-
<>
20-
<a
21-
data-tooltip-id="link-id"
22-
data-tooltip-place="top"
23-
data-tooltip-content={`${props.href}`}
24-
className="text-frost-300"
25-
{...props}
26-
>
27-
{props.children}
28-
</a>
29-
</>
30-
),
47+
a: CustomAnchorTag,
3148
h1: (props) => <h1 className="text-2xl font-bold" {...props}></h1>,
3249
h2: (props) => <h2 className="text-xl font-bold" {...props}></h2>,
3350
h3: (props) => <h3 className="text-lg font-bold" {...props}></h3>,
@@ -48,6 +65,7 @@ export default function MessageContent({ messageContent }: { messageContent: str
4865
{...props}
4966
></blockquote>
5067
),
68+
p: Fragment,
5169
}}
5270
rehypePlugins={[
5371
[rehypeHighlight, { detect: false, ignoreMissing: true }],
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { useState } from 'react';
2+
import Marquee from 'react-fast-marquee';
3+
4+
export function OverflowMarquee({ content, maxLength }: { content: string, maxLength: number }) {
5+
const [ isHovered, setIsHovered ] = useState(false);
6+
7+
return (
8+
<>
9+
{content.length > maxLength ? (
10+
<span
11+
onMouseEnter={() => setIsHovered(true)}
12+
onMouseLeave={() => setIsHovered(false)}
13+
className='inline-block max-w-full -mb-2 overflow-hidden whitespace-nowrap'
14+
>
15+
{isHovered ? (
16+
<Marquee
17+
play={isHovered}
18+
direction={'left'}
19+
gradient={false}
20+
className='w-full overflow-hidden'
21+
>
22+
{`${content}\u00A0\u00A0\u00A0\u00A0`}
23+
</Marquee>
24+
) : (`${content.slice(0, maxLength + 1)}...`)}
25+
</span>
26+
) : (content)
27+
}
28+
</>
29+
);
30+
}

0 commit comments

Comments
 (0)