diff --git a/src/Generic.tsx b/src/Generic.tsx index 1dce1dc..2db6a77 100644 --- a/src/Generic.tsx +++ b/src/Generic.tsx @@ -296,6 +296,11 @@ export const app = { ); }, openSettings: o => {}, + openServerSettings: (s: Server | null) => { + console.log( + `[FUNCTIONS] Tried to run uninitialised function openServerSettings (args: ${s})`, + ); + }, setMessageBoxInput: t => {}, setReplyingMessages: (m: ReplyingMessage[]) => { console.log( diff --git a/src/Modals.tsx b/src/Modals.tsx index 4eb1027..935d50b 100644 --- a/src/Modals.tsx +++ b/src/Modals.tsx @@ -5,7 +5,7 @@ import {observer} from 'mobx-react-lite'; import ImageViewer from 'react-native-image-zoom-viewer'; import MaterialCommunityIcon from 'react-native-vector-icons/MaterialCommunityIcons'; -import {API, Channel, User} from 'revolt.js'; +import {API, Channel, Server, User} from 'revolt.js'; import {app, client, openUrl, setFunction} from './Generic'; import {currentTheme} from './Theme'; @@ -19,6 +19,7 @@ import { ReportSheet, ServerInfoSheet, ServerInviteSheet, + ServerSettingsSheet, SettingsSheet, StatusSheet, } from './components/sheets/'; @@ -28,6 +29,7 @@ export const Modals = observer(() => { i: null as any, }); const [settingsVisibility, setSettingsVisibility] = React.useState(false); + const [serverSettingsServer, setServerSettingsServer] = React.useState(null as Server | null) const [inviteServer, setInviteServer] = React.useState({ inviteServer: null, inviteServerCode: '', @@ -47,6 +49,9 @@ export const Modals = observer(() => { setFunction('openSettings', async (o: boolean) => { setSettingsVisibility(o); }); + setFunction('openServerSettings', async (s: Server | null) => { + setServerSettingsServer(s); + }); setFunction('openInvite', async (i: string) => { try { let community = await client.fetchInvite(i); @@ -162,6 +167,13 @@ export const Modals = observer(() => { bot={inviteBot!} /> + setServerSettingsServer(null)}> + setServerSettingsServer(null)} /> + ); }); diff --git a/src/Theme.tsx b/src/Theme.tsx index 1502336..4315783 100644 --- a/src/Theme.tsx +++ b/src/Theme.tsx @@ -294,6 +294,15 @@ function refreshStyles() { textAlign: 'center', marginTop: '30%', }, + serverSettingsInitials: { + borderRadius: 5000, + justifyContent: 'center', + alignItems: 'center', + width: 80, + height: 80, + backgroundColor: currentTheme.backgroundSecondary, + overflow: 'hidden', + }, serverIcon: { width: 48, height: 48, diff --git a/src/components/sheets/ServerInfoSheet.tsx b/src/components/sheets/ServerInfoSheet.tsx index f47d5f4..d212e7c 100644 --- a/src/components/sheets/ServerInfoSheet.tsx +++ b/src/components/sheets/ServerInfoSheet.tsx @@ -119,40 +119,55 @@ export const ServerInfoSheet = observer(() => { alignItems: 'center', justifyContent: 'center', }}> + {server.havePermission("ManageServer") ? ( { + app.openServerSettings(server); + }}> + + + + Server Settings + ) : null} {app.settings.get('ui.showDeveloperFeatures') ? ( ) : null} {server.owner !== client.user?._id ? ( <> - { - app.openServer(); + { + app.openReportMenu({object: server, type: 'Server'}); app.openServerContextMenu(null); - server.delete(); }}> - Leave Server + Report Server { - app.openReportMenu({object: server, type: 'Server'}); + key={'server-ctx-menu-leave'} + onPress={async () => { + app.openServer(); + app.openServerContextMenu(null); + server.delete(); }}> - Report Server + Leave Server ) : null} diff --git a/src/components/sheets/ServerSettingsSheet.tsx b/src/components/sheets/ServerSettingsSheet.tsx new file mode 100644 index 0000000..b40deb0 --- /dev/null +++ b/src/components/sheets/ServerSettingsSheet.tsx @@ -0,0 +1,340 @@ +import React from 'react'; +import {Pressable, ScrollView, View} from 'react-native'; +import {observer} from 'mobx-react-lite'; + +import Clipboard from '@react-native-clipboard/clipboard'; +import FastImage from 'react-native-fast-image'; +import MaterialCommunityIcon from 'react-native-vector-icons/MaterialCommunityIcons'; +import MaterialIcon from 'react-native-vector-icons/MaterialIcons'; + +import {Server} from 'revolt.js'; + +import {app, client} from '../../Generic'; +import {MAX_SIDE_HQ} from '../../lib/consts'; +import {Setting, SettingsSection} from '../../lib/types'; +import {currentTheme, styles} from '../../Theme'; +import {ContextButton, InputWithButton, Link, Text} from '../common/atoms'; +import {GapView} from '../layout'; +const Image = FastImage; + +export const ServerSettingsSheet = observer( + ({server, setState}: {server: Server; setState: Function}) => { + const [renderCount, rerender] = React.useState(0); + const [section, setSection] = React.useState(null as SettingsSection); + + const iconURL = React.useMemo(() => server.generateIconURL(), []); + const initials = React.useMemo(() => { + let i = ''; + for (const word of server.name.split(' ')) { + i += word.charAt(0); + } + return i; + }, []); + + // 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 == null ? ( + { + setState(); + }}> + + + Close + + + ) : ( + { + setSection(null); + }}> + + + Back + + + )} + + {section == null ? ( + <> + + {iconURL ? ( + + ) : ( + + + {initials} + + + )} + + {server.name} + + General + { + setSection('overview'); + }}> + + + + Overview + + { + setSection('overview'); + }}> + + + + Channels + + Customisation + { + setSection('roles'); + }}> + + + + Roles + + { + setSection('emoji'); + }}> + + + + Emoji + + User Management + { + setSection('members'); + }}> + + + + Members + + { + setSection('invites'); + }}> + + + + Invites + + { + setSection('bans'); + }}> + + + + Bans + + {server.owner === client.user?._id ? ( + { + console.log('sussy'); + }}> + + + + Delete Server + + ) : 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 === 'info' ? ( + <> + About + + ) : null} + + + ); + }, +); diff --git a/src/components/sheets/index.tsx b/src/components/sheets/index.tsx index 63d575c..e7270c7 100644 --- a/src/components/sheets/index.tsx +++ b/src/components/sheets/index.tsx @@ -6,5 +6,6 @@ export {ProfileSheet} from './ProfileSheet'; export {ReportSheet} from './ReportSheet'; export {ServerInfoSheet} from './ServerInfoSheet'; export {ServerInviteSheet} from './ServerInviteSheet'; +export {ServerSettingsSheet} from './ServerSettingsSheet'; export {SettingsSheet} from './SettingsSheet'; export {StatusSheet} from './StatusSheet'; diff --git a/src/lib/consts.ts b/src/lib/consts.ts index 8126763..6484c24 100644 --- a/src/lib/consts.ts +++ b/src/lib/consts.ts @@ -34,6 +34,9 @@ export const DEFAULT_API_URL = 'https://api.revolt.chat'; // TODO: switch to htt // default max side param - used to specify the size of images export const DEFAULT_MAX_SIDE = '128'; +// higher max side param - used for the server settings menu +export const MAX_SIDE_HQ = "1024"; + // default amount of messages to load export const DEFAULT_MESSAGE_LOAD_COUNT = 50;