Skip to content

Commit

Permalink
guild homepage revamp
Browse files Browse the repository at this point in the history
  • Loading branch information
jay3332 committed Jul 10, 2024
1 parent d27129d commit 6d45b27
Show file tree
Hide file tree
Showing 7 changed files with 177 additions and 109 deletions.
154 changes: 75 additions & 79 deletions src/Entrypoint.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ import {Toaster} from "solid-toast";
import 'tippy.js/dist/tippy.css';
import 'tippy.js/animations/shift-away.css';
import App from "./App";
import {NewGuildModalContextProvider} from "./components/guilds/NewGuildModal";
import {HeaderContextProvider} from "./components/ui/Header";

import {Settings, SettingsRoot} from "./pages/settings/SettingsLayout";
import {GuildSettings, GuildSettingsRoot} from "./pages/guilds/settings/GuildSettings";
Expand Down Expand Up @@ -62,6 +60,7 @@ const GuildSettingsRole = lazy(() => import('./pages/guilds/settings/Role'))
const GuildSettingsRoleOverview = lazy(() => import('./pages/guilds/settings/RoleOverview'))
const GuildSettingsRolePermissions = lazy(() => import('./pages/guilds/settings/RolePermissions'))
const GuildSettingsRoleMembers = lazy(() => import('./pages/guilds/settings/RoleMembers'))
const GuildSettingsEmojis = lazy(() => import('./pages/guilds/settings/Emojis'))

// Guild Channel Settings
const GuildChannelSettingsOverview = lazy(() => import('./pages/channels/settings/Overview'))
Expand Down Expand Up @@ -129,84 +128,81 @@ const Entrypoint: Component = () => {
})

return (
<NewGuildModalContextProvider>
<HeaderContextProvider>
<main
class="relative font-sans m-0 w-[100vw] h-[100vh] text-fg"
onClick={(event) => contextMenu.setMenu(prev => {
if (prev != null && contextMenuRef != null) {
if (contextMenuRef.contains(event.target)) return prev
}
})}
>
<Show when={getApi()} fallback={
<Router>
<Route path={["/", "/login"]} component={Login} />
<Route path="/register" component={Register} />
<Route path="*" component={RedirectingLogin} />
</Router>
}>
<Toaster toastOptions={{
className: "_toast",
style: {
background: "#000000",
},
}} />
<Show when={contextMenu.menu()}>
<div
ref={contextMenuRef!}
class="z-[9999] absolute flex context-menu"
style={{ left: contextMenu.pos().x + 'px', top: contextMenu.pos().y + 'px'}}
>
{contextMenu.menu()}
</div>
<main
class="relative font-sans m-0 w-[100vw] h-[100vh] text-fg"
onClick={(event) => contextMenu.setMenu(prev => {
if (prev != null && contextMenuRef != null) {
if (contextMenuRef.contains(event.target)) return prev
}
})}
>
<Show when={getApi()} fallback={
<Router>
<Route path={["/", "/login"]} component={Login} />
<Route path="/register" component={Register} />
<Route path="*" component={RedirectingLogin} />
</Router>
}>
<Toaster toastOptions={{
className: "_toast",
style: {
background: "#000000",
},
}} />
<Show when={contextMenu.menu()}>
<div
ref={contextMenuRef!}
class="z-[9999] absolute flex context-menu"
style={{ left: contextMenu.pos().x + 'px', top: contextMenu.pos().y + 'px'}}
>
{contextMenu.menu()}
</div>
</Show>
<div class="w-full h-full overflow-hidden">
<Router>
<Route path="/bots/:botId" component={AddBot} />
<Show when={ws()} fallback={<Route path="*" component={Loading} />}>
<Route path="/settings" component={Settings}>
<Route path="/account" component={AccountSettings} />
<Route path="/appearance" component={AppearanceSettings} />
<Route path="/plugins" component={PluginsSettings} />
<Route path="/bots/:botId" component={BotSettings} />
<Route path="/bots" component={BotsSettings} />
</Route>
<Route path="/settings" component={SettingsRoot} />
<Route path="/guilds/:guildId/settings" component={GuildSettings}>
<Route path="/overview" component={GuildSettingsOverview} />
<Route path="/roles/:roleId" component={GuildSettingsRole}>
<Route path="/permissions" component={GuildSettingsRolePermissions} />
<Route path="/members" component={GuildSettingsRoleMembers} />
<Route path="/" component={GuildSettingsRoleOverview} />
</Route>
<Route path="/roles" component={GuildSettingsRoles} />
<Route path="/emojis" component={GuildSettingsEmojis} />
<Route path="/invites" component={() => 'wip'} />
</Route>
<Route path="/guilds/:guildId/settings" component={GuildSettingsRoot} />
<Route path="/guilds/:guildId/:channelId/settings" component={GuildChannelSettings}>
<Route path="/overview" component={GuildChannelSettingsOverview} />
<Route path="/permissions" component={GuildChannelSettingsPermissions} />
</Route>
<Route path="/guilds/:guildId/:channelId/settings" component={GuildChannelSettingsRoot} />
<Route component={App}>
<Route path="/loading" component={Loading} />
<Route path="/friends/requests" component={FriendRequests} />
<Route path="/friends/*" component={FriendsList} />
<Route path="/dms/:channelId" component={DmChannel} />
<Route path="/guilds/:guildId/:channelId" component={GuildChannel} />
<Route path="/guilds/:guildId" component={GuildHome} />
<Route path="/invite/:code" component={Invite} />
<Route path="/" component={Home} />
<Route path="*" component={NotFound} />
</Route>
</Show>
<div class="w-full h-full overflow-hidden">
<Router>
<Route path="/bots/:botId" component={AddBot} />
<Show when={ws()} fallback={<Route path="*" component={Loading} />}>
<Route path="/settings" component={Settings}>
<Route path="/account" component={AccountSettings} />
<Route path="/appearance" component={AppearanceSettings} />
<Route path="/plugins" component={PluginsSettings} />
<Route path="/bots/:botId" component={BotSettings} />
<Route path="/bots" component={BotsSettings} />
</Route>
<Route path="/settings" component={SettingsRoot} />
<Route path="/guilds/:guildId/settings" component={GuildSettings}>
<Route path="/overview" component={GuildSettingsOverview} />
<Route path="/roles/:roleId" component={GuildSettingsRole}>
<Route path="/permissions" component={GuildSettingsRolePermissions} />
<Route path="/members" component={GuildSettingsRoleMembers} />
<Route path="/" component={GuildSettingsRoleOverview} />
</Route>
<Route path="/roles" component={GuildSettingsRoles} />
<Route path="/invites" component={() => 'wip'} />
</Route>
<Route path="/guilds/:guildId/settings" component={GuildSettingsRoot} />
<Route path="/guilds/:guildId/:channelId/settings" component={GuildChannelSettings}>
<Route path="/overview" component={GuildChannelSettingsOverview} />
<Route path="/permissions" component={GuildChannelSettingsPermissions} />
</Route>
<Route path="/guilds/:guildId/:channelId/settings" component={GuildChannelSettingsRoot} />
<Route component={App}>
<Route path="/loading" component={Loading} />
<Route path="/friends/requests" component={FriendRequests} />
<Route path="/friends/*" component={FriendsList} />
<Route path="/dms/:channelId" component={DmChannel} />
<Route path="/guilds/:guildId/:channelId" component={GuildChannel} />
<Route path="/guilds/:guildId" component={GuildHome} />
<Route path="/invite/:code" component={Invite} />
<Route path="/" component={Home} />
<Route path="*" component={NotFound} />
</Route>
</Show>
</Router>
</div>
</Show>
</main>
</HeaderContextProvider>
</NewGuildModalContextProvider>
</Router>
</div>
</Show>
</main>
);
};

Expand Down
10 changes: 10 additions & 0 deletions src/components/icons/svg/FaceSmile.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import {JSX} from "solid-js";

export default function FaceSmile(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" {...props}>
{/*Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.*/}
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM164.1 325.5C182 346.2 212.6 368 256 368s74-21.8 91.9-42.5c5.8-6.7 15.9-7.4 22.6-1.6s7.4 15.9 1.6 22.6C349.8 372.1 311.1 400 256 400s-93.8-27.9-116.1-53.5c-5.8-6.7-5.1-16.8 1.6-22.6s16.8-5.1 22.6 1.6zM144.4 208a32 32 0 1 1 64 0 32 32 0 1 1 -64 0zm192-32a32 32 0 1 1 0 64 32 32 0 1 1 0-64z"/>
</svg>
)
}
8 changes: 7 additions & 1 deletion src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import './index.css';
import Entrypoint from './Entrypoint';
import {ContextMenuProvider} from "./components/ui/ContextMenu";
import {ThemeProvider} from "./client/themes";
import {NewGuildModalContextProvider} from "./components/guilds/NewGuildModal";
import {HeaderContextProvider} from "./components/ui/Header";

console.log('%cAdapt', 'font-size: 48px;')
console.log(
Expand All @@ -16,7 +18,11 @@ console.log(
const app = () => (
<ThemeProvider>
<ContextMenuProvider>
<Entrypoint />
<NewGuildModalContextProvider>
<HeaderContextProvider>
<Entrypoint />
</HeaderContextProvider>
</NewGuildModalContextProvider>
</ContextMenuProvider>
</ThemeProvider>
);
Expand Down
98 changes: 70 additions & 28 deletions src/pages/guilds/GuildHome.tsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,87 @@
import {createMemo, Show} from "solid-js";
import {Card} from "../Home";
import {useParams} from "@solidjs/router";
import {createMemo} from "solid-js";
import {A, useParams} from "@solidjs/router";
import {getApi} from "../../api/Api";
import NotFound from "../NotFound";
import Header from "../../components/ui/Header";
import GuildIcon from "../../components/guilds/GuildIcon";
import Icon from "../../components/icons/Icon";
import Users from "../../components/icons/svg/Users";
import Gear from "../../components/icons/svg/Gear";
import tooltip from "../../directives/tooltip";
import {type Message} from "../../types/message";
import {type GuildChannel} from "../../types/channel";
void tooltip

export default function GuildHome() {
const api = getApi()!
const guild = createMemo(() => api.cache!.guilds.get(BigInt(useParams().guildId)))
const guild = createMemo(() => api.cache!.guilds.get(BigInt(useParams().guildId))!)

if (!guild())
return <NotFound />

const onlineCount = createMemo(() => api.cache!.memberReactor
.get(guild().id)!
.reduce((acc, next) => api.cache!.presences.get(next)?.status === 'offline' ? acc : acc + 1, 0)
)

const recentActivity = createMemo(() => guild().channels!
.map((channel) => [channel, api.cache!.lastMessages.get(channel.id)] as const)
.filter(([, lastMessage]) => lastMessage && 'author_id' in lastMessage)
.sort(([, a], [, b]) => Number(b!.id - a!.id))
.slice(0, 3) as [GuildChannel, Message][]
)

return (
<div class="flex flex-col items-center w-full h-full p-8 mobile-xs:p-4 xl:p-12 2xl:p-16 overflow-auto">
<div class="flex flex-col p-2">
<Header>Server Home</Header>
<div class="flex items-center mobile:justify-center px-8 bg-0 rounded-xl py-12 w-full mobile:flex-col">
<Show when={guild()!.icon} keyed={false}>
<img src={guild()!.icon} alt="" class="w-24 rounded-lg mr-4"/>
</Show>
<div class="flex flex-col mobile:items-center">
<h1 class="text-4xl mobile:text-3xl text-center font-title font-bold">
Welcome to {' '}
<span
class="bg-gradient-to-r bg-clip-text overflow-ellipsis text-transparent from-accent to-secondary">
{guild()!.name}
</span>!
</h1>
</div>
</div>
<div class="flex items-center justify-center mt-4 gap-4 w-full mobile:flex-col">
<Card title="Popular Channels">
<div class="w-full h-full flex items-center justify-center">
<p class="text-center">This card is a <b>Work in Progress.</b></p> {/* TODO */}
<div class="w-full relative h-48 p-4 flex flex-row-reverse">
<figure
class="absolute rounded-xl inset-0"
style={{
...(
guild().banner
? { 'background-image': `url(${guild().banner})` }
: { 'background-color': 'rgb(var(--c-bg-0))' }
),
"background-size": "cover",
"background-position": "center",
"mask-image": "linear-gradient(to bottom, rgba(0,0,0,1), rgba(0,0,0,0))",
}}
/>
<div class="absolute flex -bottom-8 left-4 gap-x-3">
<div class="bg-bg-0/70 rounded-2xl flex items-center">
<GuildIcon
guild={guild()}
sizeClass="!rounded-2xl overflow-hidden w-20 h-20"
unread={false}
pings={0}
/>
</div>
</Card>
<Card title="Recent Activity">
<div class="w-full h-full flex items-center justify-center">
<p class="text-center">This card is a <b>Work in Progress.</b></p> {/* TODO */}
<div class="flex flex-col">
<h1 class="flex-end font-title font-bold text-fg/80 text-xl">
{guild().name}
</h1>
<span class="text-sm text-fg/60 mt-0.5">{guild().description || 'No description provided'}</span>
<span class="text-sm text-fg/60 mt-0.5">
<div class="w-2 h-2 bg-[#43b581] rounded-full inline-block align-middle" />
<span class="align-middle ml-1.5">{onlineCount()} Online</span>

<Icon icon={Users} class="select-none fill-fg/60 w-4 h-4 inline-block align-middle ml-3" />
<span class="align-middle ml-1.5">
{guild().members?.length} Member{guild().members?.length === 1 ? '' : 's'}</span>
</span>
</div>
</Card>
</div>
<div class="gap-x-2 z-[1]">
<div use:tooltip="Settings">
<A
href={`/guilds/${guild().id}/settings`}
class="flex aspect-square items-center justify-center p-3 bg-bg-3/70 rounded-full"
>
<Icon icon={Gear} class="fill-fg w-5 h-5" />
</A>
</div>
</div>
</div>
</div>
)
Expand Down
10 changes: 10 additions & 0 deletions src/pages/guilds/settings/Emojis.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Header from "../../../components/ui/Header";

export default function Emojis() {
return (
<div class="p-4">
<Header>Emojis</Header>

</div>
)
}
4 changes: 4 additions & 0 deletions src/pages/guilds/settings/GuildSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import UserTag from "../../../components/icons/svg/UserTag";
import Envelope from "../../../components/icons/svg/Envelope";
import Modal from "../../../components/ui/Modal";
import ConfirmGuildDeleteModal from "../../../components/guilds/ConfirmGuildDeleteModal";
import FaceSmile from "../../../components/icons/svg/FaceSmile";

function GuildSettingsSidebar() {
const params = useParams()
Expand Down Expand Up @@ -43,6 +44,9 @@ function GuildSettingsSidebar() {
>
Roles
</SidebarButton>
<SidebarButton large href={root() + '/emojis'} svg={FaceSmile} disabled={!perms().has('MANAGE_EMOJIS')}>
Emojis
</SidebarButton>

<SettingsSection>Management</SettingsSection>
<SidebarButton large href={root() + '/invites'} svg={Envelope} disabled={!perms().has('MANAGE_INVITES')}>
Expand Down
2 changes: 1 addition & 1 deletion src/pages/guilds/settings/Overview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ export default function Overview() {
<div class="flex flex-col gap-y-1">
<h3 class="font-light font-title text-lg">Banner</h3>
<p class="font-light text-sm text-fg/70">
This will be shown at the top of the channel sidebar.
This will be shown at the top of the channel sidebar and on the server home page.
</p>
</div>
<div class="flex mt-2 mobile:flex-col">
Expand Down

0 comments on commit 6d45b27

Please sign in to comment.