diff --git a/package.json b/package.json index 78d4687..b38d8c7 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,8 @@ "react-icons": "^4.1.0", "react-is": "^17.0.1", "react-tooltip": "^4.2.11", - "styled-components": "^5.2.1" + "styled-components": "^5.2.1", + "swr": "^0.3.9" }, "devDependencies": { "@babel/core": "^7.12.10", diff --git a/src/backend-worker/handlers/create-roleypoly-data.ts b/src/backend-worker/handlers/create-roleypoly-data.ts new file mode 100644 index 0000000..e4394ed --- /dev/null +++ b/src/backend-worker/handlers/create-roleypoly-data.ts @@ -0,0 +1,80 @@ +import KSUID from 'ksuid'; +import { CategoryType, Features, GuildData as GuildDataT } from 'roleypoly/common/types'; +import { respond } from '../utils/api-tools'; +import { GuildData } from '../utils/kv'; + +// Temporary use. +export const CreateRoleypolyData = async (request: Request): Promise => { + const data: GuildDataT = { + id: '386659935687147521', + message: + 'Hey, this is kind of a demo setup so features/use cases can be shown off.\n\nThanks for using Roleypoly <3', + features: Features.Preview, + categories: [ + { + id: KSUID.randomSync().string, + name: 'Demo Roles', + type: CategoryType.Multi, + hidden: false, + position: 0, + roles: [ + '557825026406088717', + '557824994269200384', + '557824893241131029', + '557812915386843170', + '557812901717737472', + '557812805546541066', + ], + }, + { + id: KSUID.randomSync().string, + name: 'Colors', + type: CategoryType.Single, + hidden: false, + position: 1, + roles: ['394060232893923349', '394060145799331851', '394060192846839809'], + }, + { + id: KSUID.randomSync().string, + name: 'Test Roles', + type: CategoryType.Multi, + hidden: false, + position: 5, + roles: ['558104828216213505', '558103534453653514', '558297233582194728'], + }, + { + id: KSUID.randomSync().string, + name: 'Region', + type: CategoryType.Multi, + hidden: false, + position: 3, + roles: [ + '397296181803483136', + '397296137066774529', + '397296218809827329', + '397296267283267605', + ], + }, + { + id: KSUID.randomSync().string, + name: 'Opt-in Channels', + type: CategoryType.Multi, + hidden: false, + position: 4, + roles: ['414514823959674890', '764230661904007219'], + }, + { + id: KSUID.randomSync().string, + name: 'Pronouns', + type: CategoryType.Multi, + hidden: false, + position: 2, + roles: ['485916566790340608', '485916566941335583', '485916566311927808'], + }, + ], + }; + + await GuildData.put(data.id, data); + + return respond({ ok: true }); +}; diff --git a/src/backend-worker/index.ts b/src/backend-worker/index.ts index 6b2bf51..635bf6b 100644 --- a/src/backend-worker/index.ts +++ b/src/backend-worker/index.ts @@ -1,4 +1,5 @@ import { BotJoin } from './handlers/bot-join'; +import { CreateRoleypolyData } from './handlers/create-roleypoly-data'; import { GetPickerData } from './handlers/get-picker-data'; import { GetSession } from './handlers/get-session'; import { GetSlug } from './handlers/get-slug'; @@ -29,6 +30,7 @@ router.add('GET', 'x-headers', (request) => { return new Response(JSON.stringify(headers)); }); +router.add('GET', 'x-create-roleypoly-data', CreateRoleypolyData); addEventListener('fetch', (event: FetchEvent) => { event.respondWith(router.handle(event.request)); diff --git a/src/backend-worker/router.ts b/src/backend-worker/router.ts index 4528a06..91f5859 100644 --- a/src/backend-worker/router.ts +++ b/src/backend-worker/router.ts @@ -1,3 +1,6 @@ +import { addCORS } from './utils/api-tools'; +import { uiPublicURI } from './utils/config'; + export type Handler = (request: Request) => Promise | Response; type RoutingTree = { @@ -20,6 +23,8 @@ export class Router { 500: this.serverError, }; + private uiURL = new URL(uiPublicURI); + addFallback(which: keyof Fallbacks, handler: Handler) { this.fallbacks[which] = handler; } @@ -46,13 +51,21 @@ export class Router { if (handler) { try { - return handler(request); + const response = await handler(request); + + // this.wrapCORS(request, response); + + return response; } catch (e) { console.error(e); return this.fallbacks[500](request); } } + if (lowerMethod === 'options') { + return new Response(null, addCORS({})); + } + return this.fallbacks[404](request); } diff --git a/src/backend-worker/utils/api-tools.ts b/src/backend-worker/utils/api-tools.ts index 16f50b5..977c0b9 100644 --- a/src/backend-worker/utils/api-tools.ts +++ b/src/backend-worker/utils/api-tools.ts @@ -4,6 +4,7 @@ import { permissions as Permissions, } from '../../common/utils/hasPermission'; import { Handler } from '../router'; +import { uiPublicURI } from './config'; import { Sessions, WrappedKVNamespace } from './kv'; export const formData = (obj: Record): string => { @@ -12,8 +13,18 @@ export const formData = (obj: Record): string => { .join('&'); }; -export const respond = (obj: Record, init?: ResponseInit) => - new Response(JSON.stringify(obj), init); +export const addCORS = (init: ResponseInit = {}) => ({ + ...init, + headers: { + ...(init.headers || {}), + 'access-control-allow-origin': uiPublicURI, + 'access-control-allow-method': '*', + 'access-control-allow-headers': '*', + }, +}); + +export const respond = (obj: Record, init: ResponseInit = {}) => + new Response(JSON.stringify(obj), addCORS(init)); export const resolveFailures = ( handleWith: () => Response, diff --git a/src/common/utils/isomorphicFetch.ts b/src/common/utils/isomorphicFetch.ts new file mode 100644 index 0000000..6a37bc6 --- /dev/null +++ b/src/common/utils/isomorphicFetch.ts @@ -0,0 +1,56 @@ +import { NextPageContext } from 'next'; +import getConfig from 'next/config'; +import nookies from 'nookies'; +import useSWR from 'swr'; + +export const getPublicURI = (context?: NextPageContext) => { + if (context?.req) { + const { publicRuntimeConfig } = getConfig(); + return publicRuntimeConfig.apiPublicURI; + } else { + return typeof localStorage !== 'undefined' && localStorage.getItem('api_uri'); + } +}; + +export const getSessionKey = (context?: NextPageContext) => { + if (context?.req) { + return nookies.get(context)['rp_session_key']; + } else { + return ( + typeof sessionStorage !== 'undefined' && sessionStorage.getItem('session_key') + ); + } +}; + +export const apiFetch = async ( + path: string, + init?: RequestInit, + context?: NextPageContext +): Promise => { + const sessionKey = getSessionKey(context); + if (!sessionKey) { + return null; + } + + const authorizedInit: RequestInit = { + ...(init || {}), + headers: { + ...(init?.headers || {}), + authorization: `Bearer ${sessionKey}`, + }, + }; + + const response = await fetch(`${getPublicURI(context)}${path}`, authorizedInit); + + if (response.status >= 400) { + const reason = (await response.json())['error']; + throw new Error(`Fetch failed: ${reason}`); + } + + return response.json() as Promise; +}; + +export const swrFetch = (path: string, context?: NextPageContext) => + useSWR(path, (url: string): Promise => apiFetch(url, undefined, context), { + revalidateOnFocus: false, + }); diff --git a/src/common/utils/sortBy.ts b/src/common/utils/sortBy.ts index e74ec5b..d81848d 100644 --- a/src/common/utils/sortBy.ts +++ b/src/common/utils/sortBy.ts @@ -1,7 +1,7 @@ -export const sortBy = ( +export const sortBy = ( array: T[], - key: keyof T, - predicate?: (a: T[keyof T], b: T[keyof T]) => number + key: Key, + predicate?: (a: T[typeof key], b: T[typeof key]) => number ) => { return array.sort((a, b) => { if (predicate) { diff --git a/src/design-system/atoms/avatar/Avatar.stories.tsx b/src/design-system/atoms/avatar/Avatar.stories.tsx index 91fde10..b734fca 100644 --- a/src/design-system/atoms/avatar/Avatar.stories.tsx +++ b/src/design-system/atoms/avatar/Avatar.stories.tsx @@ -9,6 +9,7 @@ export default { }, args: { initials: 'KR', + hash: 'aa', }, }; diff --git a/src/design-system/atoms/avatar/Avatar.tsx b/src/design-system/atoms/avatar/Avatar.tsx index edc6a48..15ea17a 100644 --- a/src/design-system/atoms/avatar/Avatar.tsx +++ b/src/design-system/atoms/avatar/Avatar.tsx @@ -5,13 +5,14 @@ export type AvatarProps = { src?: string; children?: string | React.ReactNode; size?: number; + hash?: string; deliberatelyEmpty?: boolean; }; /** Chuldren is recommended to not be larger than 2 uppercase letters. */ export const Avatar = (props: AvatarProps) => ( - {props.src && ( + {props.src && props.hash && ( ` opacity: 0; pointer-events: none; `} - ${onSmallScreen(css` - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; - min-width: unset; - width: 100vw; - height: 100vh; - `)}; + ${onSmallScreen( + css` + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + min-width: unset; + width: 100vw; + height: 100vh; + ` + )}; `; export const DefocusHandler = styled.div` @@ -84,4 +86,5 @@ export const PopoverHeadCloser = styled.div` export const PopoverContent = styled.div` padding: 5px; + overflow-y: hidden; `; diff --git a/src/design-system/atoms/popover/Popover.tsx b/src/design-system/atoms/popover/Popover.tsx index 5e46ac9..4e50540 100644 --- a/src/design-system/atoms/popover/Popover.tsx +++ b/src/design-system/atoms/popover/Popover.tsx @@ -16,13 +16,14 @@ type PopoverProps = { canDefocus?: boolean; onExit?: (type: 'escape' | 'defocus' | 'explicit') => void; headContent: React.ReactNode; + preferredWidth?: number; }; export const Popover = (props: PopoverProps) => { globalOnKeyUp(['Escape'], () => props.onExit?.('escape'), props.active); return ( <> - + props.onExit?.('explicit')}> diff --git a/src/design-system/atoms/role/Role.styled.tsx b/src/design-system/atoms/role/Role.styled.tsx index fd5faa6..cdbc5be 100644 --- a/src/design-system/atoms/role/Role.styled.tsx +++ b/src/design-system/atoms/role/Role.styled.tsx @@ -32,8 +32,7 @@ export const Circle = styled.div` svg { width: 10px; height: 10px; - fill-opacity: ${(props) => - props.selected || props.disabled || props.type !== 'delete' ? 1 : 0}; + fill-opacity: ${(props) => (props.selected || props.disabled ? 1 : 0)}; transition: fill-opacity ${transitions.in2in}s ease-in-out; fill: ${(props) => props.disabled && props.defaultColor diff --git a/src/design-system/molecules/guild-nav/GuildNav.tsx b/src/design-system/molecules/guild-nav/GuildNav.tsx index 133bb2b..d085a39 100644 --- a/src/design-system/molecules/guild-nav/GuildNav.tsx +++ b/src/design-system/molecules/guild-nav/GuildNav.tsx @@ -1,5 +1,6 @@ import Link from 'next/link'; import * as React from 'react'; +import Scrollbars from 'react-custom-scrollbars'; import { GoStar, GoZap } from 'react-icons/go'; import ReactTooltip from 'react-tooltip'; import { GuildSlug, UserGuildPermissions } from 'roleypoly/common/types'; @@ -29,14 +30,23 @@ const Badges = (props: { guild: GuildSlug }) => { export const GuildNav = (props: Props) => (
- {sortBy(props.guilds, 'id').map((guild) => ( - - - - - - - ))} - + + {sortBy(props.guilds, 'name', (a: string, b: string) => + a.toLowerCase() > b.toLowerCase() ? 1 : -1 + ).map((guild) => ( + + + + + + + ))} + +
); diff --git a/src/design-system/molecules/nav-slug/NavSlug.tsx b/src/design-system/molecules/nav-slug/NavSlug.tsx index c7dafa5..95f2b41 100644 --- a/src/design-system/molecules/nav-slug/NavSlug.tsx +++ b/src/design-system/molecules/nav-slug/NavSlug.tsx @@ -11,9 +11,11 @@ type Props = { export const NavSlug = (props: Props) => ( ( 'icons', 512 )} + hash={props.guildSlug.icon} > {avatarUtils.initialsFromName(props.guildSlug.name)} diff --git a/src/design-system/molecules/server-masthead/ServerMasthead.tsx b/src/design-system/molecules/server-masthead/ServerMasthead.tsx index 298da5c..bed98af 100644 --- a/src/design-system/molecules/server-masthead/ServerMasthead.tsx +++ b/src/design-system/molecules/server-masthead/ServerMasthead.tsx @@ -1,14 +1,13 @@ import Link from 'next/link'; import * as React from 'react'; import { GoPencil } from 'react-icons/go'; -import { Guild } from 'roleypoly/common/types'; -import { guild } from 'roleypoly/common/types/storyData'; +import { GuildSlug } from 'roleypoly/common/types'; import { Avatar, utils } from 'roleypoly/design-system/atoms/avatar'; import { AccentTitle, AmbientLarge } from 'roleypoly/design-system/atoms/typography'; import { Editable, Icon, Name, Wrapper } from './ServerMasthead.styled'; export type ServerMastheadProps = { - guild: Guild; + guild: GuildSlug; editable: boolean; }; @@ -17,8 +16,9 @@ export const ServerMasthead = (props: ServerMastheadProps) => { {utils.initialsFromName(props.guild.name)} diff --git a/src/design-system/molecules/user-avatar-group/UserAvatarGroup.tsx b/src/design-system/molecules/user-avatar-group/UserAvatarGroup.tsx index d2b8956..7640749 100644 --- a/src/design-system/molecules/user-avatar-group/UserAvatarGroup.tsx +++ b/src/design-system/molecules/user-avatar-group/UserAvatarGroup.tsx @@ -19,6 +19,7 @@ export const UserAvatarGroup = (props: Props) => ( {utils.initialsFromName(props.user.username)} diff --git a/src/design-system/organisms/masthead/Authed.tsx b/src/design-system/organisms/masthead/Authed.tsx index b979364..0183e4f 100644 --- a/src/design-system/organisms/masthead/Authed.tsx +++ b/src/design-system/organisms/masthead/Authed.tsx @@ -62,6 +62,7 @@ export const Authed = (props: Props) => { canDefocus position="bottom left" active={serverPopoverState} + preferredWidth={560} onExit={() => setServerPopoverState(false)} > {() => } diff --git a/src/design-system/organisms/role-picker/RolePicker.tsx b/src/design-system/organisms/role-picker/RolePicker.tsx index 78f7b00..27c53d2 100644 --- a/src/design-system/organisms/role-picker/RolePicker.tsx +++ b/src/design-system/organisms/role-picker/RolePicker.tsx @@ -1,16 +1,19 @@ +import NextLink from 'next/link'; import * as React from 'react'; import { GoInfo } from 'react-icons/go'; import { Category, CategoryType, - Guild, GuildData, + GuildSlug, Member, Role, } from 'roleypoly/common/types'; import { ReactifyNewlines } from 'roleypoly/common/utils/ReactifyNewlines'; +import { sortBy } from 'roleypoly/common/utils/sortBy'; import { FaderOpacity } from 'roleypoly/design-system/atoms/fader'; import { Space } from 'roleypoly/design-system/atoms/space'; +import { Link } from 'roleypoly/design-system/atoms/typography'; import { PickerCategory } from 'roleypoly/design-system/molecules/picker-category'; import { ResetSubmit } from 'roleypoly/design-system/molecules/reset-submit'; import { ServerMasthead } from 'roleypoly/design-system/molecules/server-masthead'; @@ -23,7 +26,7 @@ import { } from './RolePicker.styled'; export type RolePickerProps = { - guild: Guild; + guild: GuildSlug; guildData: GuildData; member: Member; roles: Role[]; @@ -81,32 +84,34 @@ export const RolePicker = (props: RolePickerProps) => { {props.guildData.categories.length !== 0 ? ( <>
- {props.guildData.categories.map((category, idx) => ( - - - category.roles.includes(roleId) - )} - roles={ - category.roles - .map((role) => - props.roles.find((r) => r.id === role) - ) - .filter((r) => r !== undefined) as Role[] - } - onChange={handleChange(category)} - wikiMode={false} - type={ - category.type === CategoryType.Single - ? 'single' - : 'multi' - } - /> - - ))} + {sortBy(props.guildData.categories, 'position').map( + (category, idx) => ( + + + category.roles.includes(roleId) + )} + roles={ + category.roles + .map((role) => + props.roles.find((r) => r.id === role) + ) + .filter((r) => r !== undefined) as Role[] + } + onChange={handleChange(category)} + wikiMode={false} + type={ + category.type === CategoryType.Single + ? 'single' + : 'multi' + } + /> + + ) + )}
{
There are currently no roles available for you to choose from. + {props.editable && ( + <> + {' '} + + Add some roles! + + + )}
)} diff --git a/src/design-system/templates/landing/Landing.tsx b/src/design-system/templates/landing/Landing.tsx index c9d49d9..0a437f0 100644 --- a/src/design-system/templates/landing/Landing.tsx +++ b/src/design-system/templates/landing/Landing.tsx @@ -1,9 +1,10 @@ import * as React from 'react'; import { AppShell } from 'roleypoly/design-system/organisms/app-shell'; import { Landing } from 'roleypoly/design-system/organisms/landing'; +import { ProvidableAppShellProps } from 'roleypoly/providers/appShellData'; -export const LandingTemplate = () => ( - +export const LandingTemplate = (props: ProvidableAppShellProps) => ( + ); diff --git a/src/design-system/templates/role-picker/RolePicker.tsx b/src/design-system/templates/role-picker/RolePicker.tsx index a692a59..c7e61f6 100644 --- a/src/design-system/templates/role-picker/RolePicker.tsx +++ b/src/design-system/templates/role-picker/RolePicker.tsx @@ -5,7 +5,7 @@ import { RolePickerProps, } from 'roleypoly/design-system/organisms/role-picker'; -export type RolePickerTemplateProps = RolePickerProps & AppShellProps; +export type RolePickerTemplateProps = RolePickerProps & Omit; export const RolePickerTemplate = (props: RolePickerTemplateProps) => { const { user, guilds, activeGuildId, ...pickerProps } = props; diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 56777a0..d5a0661 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -1,8 +1,6 @@ -import NextApp, { AppContext, AppProps } from 'next/app'; -import nookies from 'nookies'; +import { AppProps } from 'next/app'; import * as React from 'react'; import { InjectTypekitFont } from 'roleypoly/design-system/atoms/fonts'; -import { AuthProvider } from 'roleypoly/providers/auth/AuthContext'; type Props = AppProps & { sessionKey: string | null; @@ -11,26 +9,7 @@ type Props = AppProps & { const App = (props: Props) => ( <> - - - + ); export default App; - -export const getInitialProps = async (context: AppContext) => { - let sessionKey: string | null = null; - - if (context.ctx.req) { - const key = nookies.get(context.ctx)['rp_session_key']; - if (key) { - sessionKey = key; - } - } else { - sessionKey = sessionStorage.getItem('session_key'); - } - - const pageProps = await NextApp.getInitialProps(context); - - return { ...pageProps, sessionKey }; -}; diff --git a/src/pages/index.tsx b/src/pages/index.tsx index f2b62ad..f0b8a5e 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,5 +1,20 @@ +import { useRouter } from 'next/router'; import * as React from 'react'; import { LandingTemplate } from 'roleypoly/design-system/templates/landing'; +import { useAppShellProps } from 'roleypoly/providers/appShellData'; -const Index = () => ; +const Index = () => { + const { + appShellProps: { guilds, user }, + } = useAppShellProps(); + const router = useRouter(); + + React.useEffect(() => { + if (user || guilds) { + router.replace('/servers'); + } + }, [guilds, user]); + + return ; +}; export default Index; diff --git a/src/pages/machinery/logout.tsx b/src/pages/machinery/logout.tsx index d85f516..39e97bc 100644 --- a/src/pages/machinery/logout.tsx +++ b/src/pages/machinery/logout.tsx @@ -14,6 +14,7 @@ type Props = { const Logout = (props: Props) => { React.useEffect(() => { sessionStorage.removeItem('session_key'); + sessionStorage.removeItem('session_data'); location.href = '/'; }, []); diff --git a/src/pages/machinery/new-session.tsx b/src/pages/machinery/new-session.tsx index 571ac61..95e4d89 100644 --- a/src/pages/machinery/new-session.tsx +++ b/src/pages/machinery/new-session.tsx @@ -1,4 +1,5 @@ import { NextPageContext } from 'next'; +import getConfig from 'next/config'; import nookies from 'nookies'; import * as React from 'react'; import { Hero } from 'roleypoly/design-system/atoms/hero'; @@ -7,15 +8,18 @@ import { AppShell } from 'roleypoly/design-system/organisms/app-shell'; type Props = { sessionID: string; + apiURI: string; }; const NewSession = (props: Props) => { - const { sessionID } = props; + const { sessionID, apiURI } = props; + React.useEffect(() => { sessionStorage.setItem('session_key', sessionID); + localStorage.setItem('api_uri', apiURI); // TODO: set better location.href = '/'; - }, [sessionID]); + }, [sessionID, apiURI]); return ( @@ -26,7 +30,11 @@ const NewSession = (props: Props) => { ); }; -export const getServerSideProps = (context: NextPageContext): { props: Props } => { +export const getServerSideProps = async ( + context: NextPageContext +): Promise<{ props: Props }> => { + const { publicRuntimeConfig } = getConfig(); + const apiURI = publicRuntimeConfig.apiPublicURI; const sessionID = context.query.session_id as string; if (!sessionID) { throw new Error("I shouldn't be here today."); @@ -39,7 +47,7 @@ export const getServerSideProps = (context: NextPageContext): { props: Props } = sameSite: 'strict', }); - return { props: { sessionID } }; + return { props: { sessionID, apiURI } }; }; export default NewSession; diff --git a/src/pages/s/[id].tsx b/src/pages/s/[id].tsx new file mode 100644 index 0000000..9ed6cc3 --- /dev/null +++ b/src/pages/s/[id].tsx @@ -0,0 +1,59 @@ +import { NextPage, NextPageContext } from 'next'; +import Head from 'next/head'; +import * as React from 'react'; +import { PresentableGuild, UserGuildPermissions } from 'roleypoly/common/types'; +import { apiFetch } from 'roleypoly/common/utils/isomorphicFetch'; +import { RolePickerTemplate } from 'roleypoly/design-system/templates/role-picker'; +import { useAppShellProps } from 'roleypoly/providers/appShellData'; + +type Props = { + data: PresentableGuild; +}; + +const RolePickerPage: NextPage = (props) => { + const { appShellProps } = useAppShellProps(); + + return ( + <> + + Picking roles on {props.data.guild.name} - Roleypoly + + { + console.log(i); + }} + /> + + ); +}; + +RolePickerPage.getInitialProps = async (context: NextPageContext): Promise => { + const serverID = context.query.id; + if (!serverID) { + throw new Error('serverID missing'); + } + + const pickerData = await apiFetch( + `/get-picker-data/${serverID}`, + undefined, + context + ); + + if (!pickerData) { + throw new Error('TODO: picker fetch failed'); + } + + return { + data: pickerData, + }; +}; + +export default RolePickerPage; diff --git a/src/pages/s/[id]/edit.tsx b/src/pages/s/[id]/edit.tsx new file mode 100644 index 0000000..6b6185a --- /dev/null +++ b/src/pages/s/[id]/edit.tsx @@ -0,0 +1,10 @@ +import Link from 'next/link'; +import * as React from 'react'; + +const ServerEditor = () => ( +
+ Go back +
+); + +export default ServerEditor; diff --git a/src/pages/servers.tsx b/src/pages/servers.tsx new file mode 100644 index 0000000..9a2fb1e --- /dev/null +++ b/src/pages/servers.tsx @@ -0,0 +1 @@ +export default () =>
; diff --git a/src/providers/appShellData.tsx b/src/providers/appShellData.tsx new file mode 100644 index 0000000..0f42fdd --- /dev/null +++ b/src/providers/appShellData.tsx @@ -0,0 +1,27 @@ +import { NextPageContext } from 'next'; +import { SessionData } from 'roleypoly/common/types'; +import { swrFetch } from 'roleypoly/common/utils/isomorphicFetch'; +import { AppShellProps } from 'roleypoly/design-system/organisms/app-shell'; + +export type ProvidableAppShellProps = { + user: AppShellProps['user']; + guilds: AppShellProps['guilds']; +}; + +export const useAppShellProps = (context?: NextPageContext) => { + const { data, error } = swrFetch>( + '/get-session', + context + ); + + const props: ProvidableAppShellProps = { + user: data?.user, + guilds: data?.guilds, + }; + + return { + appShellProps: props, + isLoading: !error && !data, + isError: error, + }; +}; diff --git a/src/providers/auth/AuthContext.tsx b/src/providers/auth/AuthContext.tsx deleted file mode 100644 index eaf7224..0000000 --- a/src/providers/auth/AuthContext.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import * as React from 'react'; - -type AuthContextType = { - sessionKey: string | null; - setSessionKey: (value: string | null) => void; -}; - -type Props = { - sessionKey: string | null; - children: React.ReactNode; -}; - -const AuthContext = React.createContext({ - sessionKey: null, - setSessionKey: () => {}, -}); - -export const AuthProvider = (props: Props) => { - const [sessionKey, setSessionKey] = React.useState(props.sessionKey); - - return ( - - {props.children} - - ); -}; - -export const useAuth = () => { - const authCtx = React.useContext(AuthContext); - if (!authCtx) { - throw new Error('useAuth used without AuthProvider'); - } - - return authCtx; -}; - -export const isAuthenticated = () => { - const authCtx = useAuth(); - return authCtx.sessionKey !== null; -}; diff --git a/src/providers/auth/index.ts b/src/providers/auth/index.ts deleted file mode 100644 index dc39de3..0000000 --- a/src/providers/auth/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './AuthContext'; diff --git a/yarn.lock b/yarn.lock index 572dc00..5cfeff6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5603,6 +5603,11 @@ depd@~1.1.2: resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= +dequal@2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.2.tgz#85ca22025e3a87e65ef75a7a437b35284a7e319d" + integrity sha512-q9K8BlJVxK7hQYqa6XISGmBZbtQQWVXSrRrWreHC94rMt1QL/Impruc+7p2CYSYuVIUr+YCt6hjrs1kkdJRTug== + des.js@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" @@ -13282,6 +13287,13 @@ svg-tags@^1.0.0: resolved "https://registry.yarnpkg.com/svg-tags/-/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764" integrity sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q= +swr@^0.3.9: + version "0.3.9" + resolved "https://registry.yarnpkg.com/swr/-/swr-0.3.9.tgz#a179a795244c7b68684af6a632f1ad579e6a69e0" + integrity sha512-lyN4SjBzpoW4+v3ebT7JUtpzf9XyzrFwXIFv+E8ZblvMa5enSNaUBs4EPkL8gGA/GDMLngEmB53o5LaNboAPfg== + dependencies: + dequal "2.0.2" + symbol-tree@^3.2.2, symbol-tree@^3.2.4: version "3.2.4" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"