diff --git a/src/components/common/settings/sections/server/InviteSettingsSection.tsx b/src/components/common/settings/sections/server/InviteSettingsSection.tsx
new file mode 100644
index 0000000..949311a
--- /dev/null
+++ b/src/components/common/settings/sections/server/InviteSettingsSection.tsx
@@ -0,0 +1,74 @@
+import React, {useEffect, useState} from 'react';
+import {Pressable, View} from 'react-native';
+import {observer} from 'mobx-react-lite';
+
+import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
+
+import {API, Server} from 'revolt.js';
+
+import {currentTheme, styles} from '../../../../../Theme';
+import {Text} from '../../../atoms';
+
+export const InviteSettingsSection = observer(({server}: {server: Server}) => {
+ const [reload, triggerReload] = useState(0);
+ const [invites, setInvites] = useState(null as API.Invite[] | null);
+ useEffect(() => {
+ async function fetchInvites() {
+ const i = await server.fetchInvites();
+ setInvites(i);
+ }
+
+ fetchInvites();
+ }, [server, reload]);
+
+ return (
+ <>
+ Invites
+ {invites ? (
+ invites.length ? (
+ invites.map(i => (
+
+
+
+ {i._id}
+
+
+ @{i.creator} - #{i.channel}
+
+
+ {i._id.length === 8 ? (
+ {
+ server.client.deleteInvite(i._id);
+ triggerReload(reload + 1);
+ }}>
+
+
+
+
+ ) : null}
+
+ ))
+ ) : (
+ No invites
+ )
+ ) : (
+ Fetching invites...
+ )}
+ >
+ );
+});
diff --git a/src/components/common/settings/sections/server/OverviewSettingsSection.tsx b/src/components/common/settings/sections/server/OverviewSettingsSection.tsx
new file mode 100644
index 0000000..c11c416
--- /dev/null
+++ b/src/components/common/settings/sections/server/OverviewSettingsSection.tsx
@@ -0,0 +1,92 @@
+import React from 'react';
+import {View} from 'react-native';
+import {observer} from 'mobx-react-lite';
+
+import {Server} from 'revolt.js';
+
+import {currentTheme} from '../../../../../Theme';
+import {GapView} from '../../../../layout';
+import {InputWithButton, Link, Text} from '../../../atoms';
+
+export const OverviewSettingsSection = observer(
+ ({server}: {server: Server}) => {
+ return (
+ <>
+ Overview
+
+ Server name
+
+ {
+ server.edit({
+ name: v,
+ });
+ }}
+ buttonContents={{
+ type: 'icon',
+ name: 'save',
+ pack: 'regular',
+ }}
+ backgroundColor={currentTheme.backgroundSecondary}
+ skipIfSame
+ cannotBeEmpty
+ emptyError={'Server names cannot be empty!'}
+ />
+
+
+ Server description
+
+
+
+ Server descriptions support Markdown formatting.
+
+
+
+
+ {
+ server.edit({
+ description: v,
+ });
+ }}
+ buttonContents={{type: 'string', content: 'Set description'}}
+ backgroundColor={currentTheme.backgroundSecondary}
+ skipIfSame
+ // @ts-expect-error this is passed down to the TextInput
+ multiline
+ extraStyles={{
+ container: {
+ flexDirection: 'column',
+ alignItems: 'flex-start',
+ },
+ input: {width: '100%'},
+ button: {marginHorizontal: 0},
+ }}
+ />
+
+ System messages
+
+ When members join/leave or are kicked/banned, you can receive
+ messages. (not final copy)
+
+
+ new {server.system_messages?.user_joined} leave{' '}
+ {server.system_messages?.user_left} kick{' '}
+ {server.system_messages?.user_kicked} ban{' '}
+ {server.system_messages?.user_banned}
+
+ >
+ );
+ },
+);
diff --git a/src/components/common/settings/sections/server/RoleSettingsSection.tsx b/src/components/common/settings/sections/server/RoleSettingsSection.tsx
new file mode 100644
index 0000000..1eb40f9
--- /dev/null
+++ b/src/components/common/settings/sections/server/RoleSettingsSection.tsx
@@ -0,0 +1,122 @@
+import React from 'react';
+import {Pressable, View} from 'react-native';
+import {observer} from 'mobx-react-lite';
+
+import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
+
+import {Server} from 'revolt.js';
+
+import {SettingsSection} from '../../../../../lib/types';
+import {currentTheme, styles} from '../../../../../Theme';
+import {GapView} from '../../../../layout';
+import {Text} from '../../../atoms';
+
+export const RoleSettingsSection = observer(
+ ({server, callback}: {server: Server; callback: Function}) => {
+ const [subsection, setSubsection] = React.useState(null as SettingsSection);
+
+ return (
+ <>
+ {
+ subsection ? setSubsection(null) : callback();
+ }}>
+
+
+ Back
+
+
+ {subsection ? (
+ <>
+
+ {server.roles![subsection].name}
+
+ {subsection}
+
+ Rank
+ {/* {
+ setRankValue(v);
+ }}
+ /> */}
+ {server.roles![subsection].rank}
+
+ Permissions
+ {server.roles![subsection].permissions.a}
+
+ Colour
+ {server.roles![subsection].colour}
+ >
+ ) : (
+ <>
+ Roles
+ {server.orderedRoles.map(r => (
+
+
+
+ {r.name}
+
+ {r.id}
+
+ {
+ setSubsection(r.id);
+ }}>
+
+
+
+
+
+ ))}
+ >
+ )}
+ >
+ );
+ },
+);
diff --git a/src/components/common/settings/sections/server/index.ts b/src/components/common/settings/sections/server/index.ts
new file mode 100644
index 0000000..7255f3b
--- /dev/null
+++ b/src/components/common/settings/sections/server/index.ts
@@ -0,0 +1,3 @@
+export {InviteSettingsSection} from './InviteSettingsSection';
+export {OverviewSettingsSection} from './OverviewSettingsSection';
+export {RoleSettingsSection} from './RoleSettingsSection';
diff --git a/src/components/sheets/ServerSettingsSheet.tsx b/src/components/sheets/ServerSettingsSheet.tsx
index b39ca73..9916f94 100644
--- a/src/components/sheets/ServerSettingsSheet.tsx
+++ b/src/components/sheets/ServerSettingsSheet.tsx
@@ -12,7 +12,12 @@ import {app, client} from '../../Generic';
import {MAX_SIDE_HQ} from '../../lib/consts';
import {SettingsSection} from '../../lib/types';
import {currentTheme, styles} from '../../Theme';
-import {ContextButton, InputWithButton, Link, Text} from '../common/atoms';
+import {ContextButton, Text} from '../common/atoms';
+import {
+ InviteSettingsSection,
+ RoleSettingsSection,
+ OverviewSettingsSection,
+} from '../common/settings/sections/server';
import {GapView} from '../layout';
const Image = FastImage;
@@ -30,20 +35,6 @@ export const ServerSettingsSheet = observer(
return i;
}, [server.name]);
- // React.useEffect(() => {
- // async function getAuthInfo() {
- // const e = await client.api.get('/auth/account/');
- // const m = await client.api.get('/auth/mfa/');
- // const s = await client.api.get('/auth/session/all');
- // setAuthInfo({
- // email: e.email,
- // mfaEnabled: m.totp_mfa ?? m.security_key_mfa ?? false,
- // sessions: s,
- // });
- // }
- // getAuthInfo();
- // }, []);
-
return (
- ) : (
+ ) : section !== 'roles' ? (
- )}
+ ) : null}
) : section === 'overview' ? (
-
- Overview
-
- Server name
-
- {
- server.edit({
- name: v,
- });
- }}
- buttonContents={{
- type: 'icon',
- name: 'save',
- pack: 'regular',
- }}
- backgroundColor={currentTheme.backgroundSecondary}
- skipIfSame
- cannotBeEmpty
- emptyError={'Server names cannot be empty!'}
- />
-
-
- Server description
-
-
-
- Server descriptions support Markdown formatting.
-
-
-
-
- {
- server.edit({
- description: v,
- });
- }}
- buttonContents={{type: 'string', content: 'Set description'}}
- backgroundColor={currentTheme.backgroundSecondary}
- skipIfSame
- // @ts-expect-error this is passed down to the TextInput
- multiline
- extraStyles={{
- container: {
- flexDirection: 'column',
- alignItems: 'flex-start',
- },
- input: {width: '100%'},
- button: {marginHorizontal: 0},
- }}
- />
-
+
+ ) : section === 'roles' ? (
+ setSection(null)}
+ />
+ ) : section === 'invites' ? (
+
) : section === 'info' ? (
<>
About