mirror of
https://github.com/balzack/databag.git
synced 2025-04-23 18:15:19 +00:00
formatting source
This commit is contained in:
parent
674d0f5ae2
commit
d539fdf0bb
@ -88,7 +88,7 @@ const theme = createTheme({
|
||||
'#559e83',
|
||||
'#559e83',
|
||||
],
|
||||
'light-databag-green': [
|
||||
'light-databag-green': [
|
||||
'#888888',
|
||||
'#448844',
|
||||
'#448844',
|
||||
|
@ -22,7 +22,7 @@ import {
|
||||
IconServer,
|
||||
IconKey,
|
||||
} from '@tabler/icons-react'
|
||||
import { modals } from '@mantine/modals';
|
||||
import { modals } from '@mantine/modals'
|
||||
|
||||
export function Access() {
|
||||
const { state, actions } = useAccess()
|
||||
@ -65,12 +65,10 @@ export function Access() {
|
||||
backgroundOpacity: 0.55,
|
||||
blur: 3,
|
||||
},
|
||||
children: (
|
||||
<div>{state.strings.tryAgain}</div>
|
||||
),
|
||||
children: <div>{state.strings.tryAgain}</div>,
|
||||
cancelProps: { display: 'none' },
|
||||
confirmProps: { display: 'none' },
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
actions.setLoading(false)
|
||||
|
@ -45,7 +45,7 @@ export function useAccess() {
|
||||
}
|
||||
|
||||
const { protocol, host } = location
|
||||
updateState({ host, secure: protocol === 'https' });
|
||||
updateState({ host, secure: protocol === 'https' })
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
@ -121,8 +121,9 @@ export function useAccess() {
|
||||
updateState({ code })
|
||||
},
|
||||
setNode: (host: string) => {
|
||||
const insecure = /^(?!0)(?!.*\.$)((1?\d?\d|25[0-5]|2[0-4]\d)(\.|:\d+$|$)){4}$/.test(host);
|
||||
updateState({ host, secure: !insecure });
|
||||
const insecure =
|
||||
/^(?!0)(?!.*\.$)((1?\d?\d|25[0-5]|2[0-4]\d)(\.|:\d+$|$)){4}$/.test(host)
|
||||
updateState({ host, secure: !insecure })
|
||||
},
|
||||
setLanguage: (code: string) => {
|
||||
display.actions.setLanguage(code)
|
||||
|
@ -53,12 +53,12 @@ export function useAppContext() {
|
||||
code,
|
||||
params
|
||||
)
|
||||
updateState({ session: login });
|
||||
updateState({ session: login })
|
||||
},
|
||||
accountLogout: async () => {
|
||||
if (state.session) {
|
||||
await sdk.current.logout(state.session, false)
|
||||
updateState({ session: null });
|
||||
updateState({ session: null })
|
||||
}
|
||||
},
|
||||
accountCreate: async (
|
||||
@ -87,7 +87,7 @@ export function useAppContext() {
|
||||
token,
|
||||
params
|
||||
)
|
||||
updateState({ session });
|
||||
updateState({ session })
|
||||
},
|
||||
accountAccess: async (node: string, secure: boolean, token: string) => {
|
||||
const params = {
|
||||
@ -102,7 +102,7 @@ export function useAppContext() {
|
||||
appName: 'databag',
|
||||
}
|
||||
const session = await sdk.current.access(node, secure, token, params)
|
||||
updateState({ session });
|
||||
updateState({ session })
|
||||
},
|
||||
getAvailable: async (node: string, secure: boolean) => {
|
||||
return await sdk.current.available(node, secure)
|
||||
|
@ -1,32 +1,43 @@
|
||||
import { useState } from 'react';
|
||||
import classes from './Identity.module.css';
|
||||
import { useIdentity } from './useIdentity.hook';
|
||||
import { Text, Image, Menu, Switch } from '@mantine/core';
|
||||
import { useState } from 'react'
|
||||
import classes from './Identity.module.css'
|
||||
import { useIdentity } from './useIdentity.hook'
|
||||
import { Text, Image, Menu, Switch } from '@mantine/core'
|
||||
import {
|
||||
IconLogout,
|
||||
IconChevronRight,
|
||||
IconSettings,
|
||||
IconAddressBook
|
||||
IconAddressBook,
|
||||
} from '@tabler/icons-react'
|
||||
import { modals } from '@mantine/modals';
|
||||
import { modals } from '@mantine/modals'
|
||||
|
||||
export function Identity({ settings, contacts }: { settings: () => void, contacts: () => void }) {
|
||||
const { state, actions } = useIdentity();
|
||||
const [all, setAll] = useState(false);
|
||||
export function Identity({
|
||||
settings,
|
||||
contacts,
|
||||
}: {
|
||||
settings: () => void
|
||||
contacts: () => void
|
||||
}) {
|
||||
const { state, actions } = useIdentity()
|
||||
const [all, setAll] = useState(false)
|
||||
|
||||
const logout = () => modals.openConfirmModal({
|
||||
title: state.strings.confirmLogout,
|
||||
withCloseButton: false,
|
||||
overlayProps: {
|
||||
backgroundOpacity: 0.55,
|
||||
blur: 3,
|
||||
},
|
||||
children: (
|
||||
<Switch label={state.strings.allDevices} size="md" onChange={(ev) => actions.setAll(ev.currentTarget.checked)} />
|
||||
),
|
||||
labels: { confirm: state.strings.logout, cancel: state.strings.cancel },
|
||||
onConfirm: actions.logout,
|
||||
});
|
||||
const logout = () =>
|
||||
modals.openConfirmModal({
|
||||
title: state.strings.confirmLogout,
|
||||
withCloseButton: false,
|
||||
overlayProps: {
|
||||
backgroundOpacity: 0.55,
|
||||
blur: 3,
|
||||
},
|
||||
children: (
|
||||
<Switch
|
||||
label={state.strings.allDevices}
|
||||
size="md"
|
||||
onChange={(ev) => actions.setAll(ev.currentTarget.checked)}
|
||||
/>
|
||||
),
|
||||
labels: { confirm: state.strings.logout, cancel: state.strings.cancel },
|
||||
onConfirm: actions.logout,
|
||||
})
|
||||
|
||||
return (
|
||||
<Menu shadow="md" position="right">
|
||||
@ -34,22 +45,30 @@ export function Identity({ settings, contacts }: { settings: () => void, contact
|
||||
<div className={classes.identity}>
|
||||
<Image radius="sm" className={classes.image} src={state.imageUrl} />
|
||||
<div className={classes.text}>
|
||||
{ !state.profile.name && (
|
||||
{!state.profile.name && (
|
||||
<Text className={classes.nameUnset}>{state.strings.name}</Text>
|
||||
)}
|
||||
{ state.profile.name && (
|
||||
{state.profile.name && (
|
||||
<Text className={classes.nameSet}>{state.profile.name}</Text>
|
||||
)}
|
||||
<Text className={classes.handle}>{`${state.profile.handle}${state.profile.node ? '/' + state.profile.node : ''}`}</Text>
|
||||
<Text
|
||||
className={classes.handle}
|
||||
>{`${state.profile.handle}${state.profile.node ? '/' + state.profile.node : ''}`}</Text>
|
||||
</div>
|
||||
<IconChevronRight className={classes.icon} />
|
||||
</div>
|
||||
</Menu.Target>
|
||||
|
||||
<Menu.Dropdown>
|
||||
<Menu.Item onClick={settings} leftSection={<IconSettings />}>{ state.strings.settings }</Menu.Item>
|
||||
<Menu.Item leftSection={<IconAddressBook />}>{ state.strings.contacts }</Menu.Item>
|
||||
<Menu.Item onClick={logout} leftSection={<IconLogout />}>{ state.strings.logout }</Menu.Item>
|
||||
<Menu.Item onClick={settings} leftSection={<IconSettings />}>
|
||||
{state.strings.settings}
|
||||
</Menu.Item>
|
||||
<Menu.Item leftSection={<IconAddressBook />}>
|
||||
{state.strings.contacts}
|
||||
</Menu.Item>
|
||||
<Menu.Item onClick={logout} leftSection={<IconLogout />}>
|
||||
{state.strings.logout}
|
||||
</Menu.Item>
|
||||
</Menu.Dropdown>
|
||||
</Menu>
|
||||
)
|
||||
|
@ -2,7 +2,7 @@ import { useState, useContext, useEffect } from 'react'
|
||||
import { DisplayContext } from '../context/DisplayContext'
|
||||
import { AppContext } from '../context/AppContext'
|
||||
import { ContextType } from '../context/ContextType'
|
||||
import { Profile } from 'databag-client-sdk';
|
||||
import { Profile } from 'databag-client-sdk'
|
||||
|
||||
export function useIdentity() {
|
||||
const app = useContext(AppContext) as ContextType
|
||||
@ -13,7 +13,7 @@ export function useIdentity() {
|
||||
profile: {} as Profile,
|
||||
profileSet: false,
|
||||
imageUrl: null,
|
||||
});
|
||||
})
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const updateState = (value: any) => {
|
||||
@ -21,29 +21,32 @@ export function useIdentity() {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const identity = app.state.session?.getIdentity();
|
||||
const identity = app.state.session?.getIdentity()
|
||||
if (!identity) {
|
||||
console.log('session not set in identity hook');
|
||||
}
|
||||
else {
|
||||
console.log('session not set in identity hook')
|
||||
} else {
|
||||
const setProfile = (profile: Profile) => {
|
||||
updateState({ profile, profileSet: true, imageUrl: identity.getProfileImageUrl() })
|
||||
updateState({
|
||||
profile,
|
||||
profileSet: true,
|
||||
imageUrl: identity.getProfileImageUrl(),
|
||||
})
|
||||
}
|
||||
identity.addProfileListener(setProfile)
|
||||
return () => {
|
||||
identity.removeProfileListener(setProfile);
|
||||
identity.removeProfileListener(setProfile)
|
||||
}
|
||||
}
|
||||
}, []);
|
||||
}, [])
|
||||
|
||||
const actions = {
|
||||
setAll: (all: boolean) => {
|
||||
updateState({ all });
|
||||
updateState({ all })
|
||||
},
|
||||
logout: async () => {
|
||||
await app.actions.accountLogout(state.all);
|
||||
await app.actions.accountLogout(state.all)
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return { state, actions };
|
||||
return { state, actions }
|
||||
}
|
||||
|
@ -25,16 +25,15 @@ export function useRoot() {
|
||||
|
||||
useEffect(() => {
|
||||
const { pathname, node, session } = app.state || {}
|
||||
const path = pathname === '/session' || pathname === '/node' || pathname === '/access' ? pathname : '/';
|
||||
const path =
|
||||
pathname === '/session' || pathname === '/node' || pathname === '/access'
|
||||
? pathname
|
||||
: '/'
|
||||
if (path === '/session' && !session) {
|
||||
navigate('/')
|
||||
} else if (path === '/node' && !node) {
|
||||
navigate('/')
|
||||
} else if (
|
||||
path === '/' &&
|
||||
!session &&
|
||||
!node
|
||||
) {
|
||||
} else if (path === '/' && !session && !node) {
|
||||
navigate('/access')
|
||||
} else if (path !== '/node' && node) {
|
||||
navigate('/node')
|
||||
|
@ -13,17 +13,16 @@
|
||||
height: 100%;
|
||||
width: 33%;
|
||||
min-width: 325px;
|
||||
background: var(--mantine-color-surface-2);
|
||||
background: var(--mantine-color-surface-2);
|
||||
}
|
||||
|
||||
.right {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
background: var(--mantine-color-surface-3);
|
||||
background: var(--mantine-color-surface-3);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.screen {
|
||||
width: 100%;
|
||||
@ -33,7 +32,7 @@
|
||||
background-color: var(--mantine-color-surface-1);
|
||||
overflow: auto;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.tabs {
|
||||
position: absolute;
|
||||
@ -48,8 +47,8 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: var(--mantine-color-tab-2);
|
||||
color: var(--mantine-color-dbgreen-1);
|
||||
background: var(--mantine-color-tab-2);
|
||||
color: var(--mantine-color-dbgreen-1);
|
||||
padding-bottom: 8px;
|
||||
padding-top: 8px;
|
||||
cursor: pointer;
|
||||
@ -61,14 +60,14 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: var(--mantine-color-tab-1);
|
||||
color: var(--mantine-color-dbgreen-0);
|
||||
background: var(--mantine-color-tab-1);
|
||||
color: var(--mantine-color-dbgreen-0);
|
||||
padding-bottom: 8px;
|
||||
padding-top: 8px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background: var(--mantine-color-tab-3);
|
||||
background: var(--mantine-color-tab-3);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,72 +1,99 @@
|
||||
import React, { useState, useContext } from 'react'
|
||||
import { Text, Drawer, Button } from '@mantine/core'
|
||||
import { AppContext } from '../context/AppContext'
|
||||
import { DisplayContext } from '../context/DisplayContext';
|
||||
import { DisplayContext } from '../context/DisplayContext'
|
||||
import { ContextType } from '../context/ContextType'
|
||||
import classes from './Session.module.css'
|
||||
import { IconAddressBook, IconMessages, IconSettings } from '@tabler/icons-react'
|
||||
import { Settings } from '../settings/Settings';
|
||||
import { Identity } from '../identity/Identity';
|
||||
import { useDisclosure } from '@mantine/hooks';
|
||||
import {
|
||||
IconAddressBook,
|
||||
IconMessages,
|
||||
IconSettings,
|
||||
} from '@tabler/icons-react'
|
||||
import { Settings } from '../settings/Settings'
|
||||
import { Identity } from '../identity/Identity'
|
||||
import { useDisclosure } from '@mantine/hooks'
|
||||
|
||||
export function Session() {
|
||||
const [ tab, setTab ] = useState('channels');
|
||||
const [tab, setTab] = useState('channels')
|
||||
const app = useContext(AppContext) as ContextType
|
||||
const display = useContext(DisplayContext) as ContextType
|
||||
const [settings, { open: openSettings, close: closeSettings }] = useDisclosure(false);
|
||||
const [settings, { open: openSettings, close: closeSettings }] =
|
||||
useDisclosure(false)
|
||||
|
||||
const click = () => {
|
||||
console.log("SESSION DRAWER", openSettings);
|
||||
openSettings();
|
||||
console.log('SESSION DRAWER', openSettings)
|
||||
openSettings()
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={classes.session}>
|
||||
{ display.state.layout === 'small' && (
|
||||
{display.state.layout === 'small' && (
|
||||
<>
|
||||
<div className={classes.screen}>
|
||||
{ tab === 'settings' && (
|
||||
<Settings showLogout={true} />
|
||||
)}
|
||||
{tab === 'settings' && <Settings showLogout={true} />}
|
||||
</div>
|
||||
<div className={classes.tabs}>
|
||||
{ tab === 'channels' && (
|
||||
<div className={classes.activeTabItem}><IconMessages className={classes.tabIcon} /></div>
|
||||
{tab === 'channels' && (
|
||||
<div className={classes.activeTabItem}>
|
||||
<IconMessages className={classes.tabIcon} />
|
||||
</div>
|
||||
)}
|
||||
{ tab !== 'channels' && (
|
||||
<div className={classes.idleTabItem} onClick={() => setTab('channels')}><IconMessages className={classes.tabIcon} /></div>
|
||||
{tab !== 'channels' && (
|
||||
<div
|
||||
className={classes.idleTabItem}
|
||||
onClick={() => setTab('channels')}
|
||||
>
|
||||
<IconMessages className={classes.tabIcon} />
|
||||
</div>
|
||||
)}
|
||||
<div className={classes.tabDivider} />
|
||||
{ tab === 'contacts' && (
|
||||
<div className={classes.activeTabItem}><IconAddressBook className={classes.tabIcon} /></div>
|
||||
{tab === 'contacts' && (
|
||||
<div className={classes.activeTabItem}>
|
||||
<IconAddressBook className={classes.tabIcon} />
|
||||
</div>
|
||||
)}
|
||||
{ tab !== 'contacts' && (
|
||||
<div className={classes.idleTabItem} onClick={() => setTab('contacts')}><IconAddressBook className={classes.tabIcon} /></div>
|
||||
{tab !== 'contacts' && (
|
||||
<div
|
||||
className={classes.idleTabItem}
|
||||
onClick={() => setTab('contacts')}
|
||||
>
|
||||
<IconAddressBook className={classes.tabIcon} />
|
||||
</div>
|
||||
)}
|
||||
<div className={classes.tabDivider} />
|
||||
{ tab === 'settings' && (
|
||||
<div className={classes.activeTabItem}><IconSettings className={classes.tabIcon} /></div>
|
||||
{tab === 'settings' && (
|
||||
<div className={classes.activeTabItem}>
|
||||
<IconSettings className={classes.tabIcon} />
|
||||
</div>
|
||||
)}
|
||||
{ tab !== 'settings' && (
|
||||
<div className={classes.idleTabItem} onClick={() => setTab('settings')}><IconSettings className={classes.tabIcon} /></div>
|
||||
{tab !== 'settings' && (
|
||||
<div
|
||||
className={classes.idleTabItem}
|
||||
onClick={() => setTab('settings')}
|
||||
>
|
||||
<IconSettings className={classes.tabIcon} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{ display.state.layout === 'large' && (
|
||||
{display.state.layout === 'large' && (
|
||||
<div className={classes.display}>
|
||||
<div className={classes.left}>
|
||||
<Identity settings={click} contacts={() => {}} />
|
||||
</div>
|
||||
<div className={classes.right}>
|
||||
</div>
|
||||
<Drawer opened={settings} onClose={closeSettings} withCloseButton={false} size="sm" position="right">
|
||||
<div className={classes.right}></div>
|
||||
<Drawer
|
||||
opened={settings}
|
||||
onClose={closeSettings}
|
||||
withCloseButton={false}
|
||||
size="sm"
|
||||
position="right"
|
||||
>
|
||||
<Settings showLogout={false} />
|
||||
</Drawer>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,135 +1,170 @@
|
||||
import { useSettings } from './useSettings.hook';
|
||||
import { Modal, Textarea, TextInput, PasswordInput, Radio, Group, Select, Switch, Text, Image, Button, UnstyledButton } from '@mantine/core';
|
||||
import classes from './Settings.module.css';
|
||||
import { IconLock, IconUser, IconClock, IconIdBadge, IconCalendar, IconUsers, IconVideo, IconMicrophone, IconWorld, IconBrightness, IconTicket, IconCloudLock, IconBell, IconEye, IconBook, IconMapPin, IconLogout, IconLogin } from '@tabler/icons-react'
|
||||
import { modals } from '@mantine/modals';
|
||||
import { useSettings } from './useSettings.hook'
|
||||
import {
|
||||
Modal,
|
||||
Textarea,
|
||||
TextInput,
|
||||
PasswordInput,
|
||||
Radio,
|
||||
Group,
|
||||
Select,
|
||||
Switch,
|
||||
Text,
|
||||
Image,
|
||||
Button,
|
||||
UnstyledButton,
|
||||
} from '@mantine/core'
|
||||
import classes from './Settings.module.css'
|
||||
import {
|
||||
IconLock,
|
||||
IconUser,
|
||||
IconClock,
|
||||
IconIdBadge,
|
||||
IconCalendar,
|
||||
IconUsers,
|
||||
IconVideo,
|
||||
IconMicrophone,
|
||||
IconWorld,
|
||||
IconBrightness,
|
||||
IconTicket,
|
||||
IconCloudLock,
|
||||
IconBell,
|
||||
IconEye,
|
||||
IconBook,
|
||||
IconMapPin,
|
||||
IconLogout,
|
||||
IconLogin,
|
||||
} from '@tabler/icons-react'
|
||||
import { modals } from '@mantine/modals'
|
||||
import { useDisclosure } from '@mantine/hooks'
|
||||
import { useCallback, useState, useRef } from 'react'
|
||||
import Cropper from 'react-easy-crop';
|
||||
import { Area } from 'react-easy-crop/types';
|
||||
import Cropper from 'react-easy-crop'
|
||||
import { Area } from 'react-easy-crop/types'
|
||||
|
||||
export function Settings({ showLogout }: { showLogout: boolean }) {
|
||||
const imageFile = useRef(null as null | HTMLInputElement);
|
||||
const { state, actions } = useSettings();
|
||||
const [changeOpened, { open: changeOpen, close: changeClose }] = useDisclosure(false)
|
||||
const [detailsOpened, { open: detailsOpen, close: detailsClose }] = useDisclosure(false)
|
||||
const [imageOpened, { open: imageOpen, close: imageClose }] = useDisclosure(false)
|
||||
const [savingLogin, setSavingLogin] = useState(false);
|
||||
const [savingDetails, setSavingDetails] = useState(false);
|
||||
const [savingImage, setSavingImage] = useState(false);
|
||||
const [savingRegistry, setSavingRegistry] = useState(false);
|
||||
const [savingNotifications, setSavingNotifications] = useState(false);
|
||||
const imageFile = useRef(null as null | HTMLInputElement)
|
||||
const { state, actions } = useSettings()
|
||||
const [changeOpened, { open: changeOpen, close: changeClose }] =
|
||||
useDisclosure(false)
|
||||
const [detailsOpened, { open: detailsOpen, close: detailsClose }] =
|
||||
useDisclosure(false)
|
||||
const [imageOpened, { open: imageOpen, close: imageClose }] =
|
||||
useDisclosure(false)
|
||||
const [savingLogin, setSavingLogin] = useState(false)
|
||||
const [savingDetails, setSavingDetails] = useState(false)
|
||||
const [savingImage, setSavingImage] = useState(false)
|
||||
const [savingRegistry, setSavingRegistry] = useState(false)
|
||||
const [savingNotifications, setSavingNotifications] = useState(false)
|
||||
|
||||
const logout = () => modals.openConfirmModal({
|
||||
title: state.strings.confirmLogout,
|
||||
withCloseButton: false,
|
||||
overlayProps: {
|
||||
backgroundOpacity: 0.55,
|
||||
blur: 3,
|
||||
},
|
||||
children: (
|
||||
<Switch label={state.strings.allDevices} size="md" onChange={(ev) => actions.setAll(ev.currentTarget.checked)} />
|
||||
),
|
||||
labels: { confirm: state.strings.logout, cancel: state.strings.cancel },
|
||||
onConfirm: actions.logout,
|
||||
});
|
||||
const logout = () =>
|
||||
modals.openConfirmModal({
|
||||
title: state.strings.confirmLogout,
|
||||
withCloseButton: false,
|
||||
overlayProps: {
|
||||
backgroundOpacity: 0.55,
|
||||
blur: 3,
|
||||
},
|
||||
children: (
|
||||
<Switch
|
||||
label={state.strings.allDevices}
|
||||
size="md"
|
||||
onChange={(ev) => actions.setAll(ev.currentTarget.checked)}
|
||||
/>
|
||||
),
|
||||
labels: { confirm: state.strings.logout, cancel: state.strings.cancel },
|
||||
onConfirm: actions.logout,
|
||||
})
|
||||
|
||||
const setRegistry = async (checked: boolean) => {
|
||||
if (!savingRegistry) {
|
||||
setSavingRegistry(true);
|
||||
setSavingRegistry(true)
|
||||
try {
|
||||
if (checked) {
|
||||
await actions.enableRegistry();
|
||||
await actions.enableRegistry()
|
||||
} else {
|
||||
await actions.disableRegistry();
|
||||
await actions.disableRegistry()
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
showError()
|
||||
}
|
||||
catch (err) {
|
||||
console.log(err);
|
||||
showError();
|
||||
}
|
||||
setSavingRegistry(false);
|
||||
setSavingRegistry(false)
|
||||
}
|
||||
}
|
||||
|
||||
const setNotifications = async (checked: boolean) => {
|
||||
if (!savingNotifications) {
|
||||
setSavingNotifications(true);
|
||||
setSavingNotifications(true)
|
||||
try {
|
||||
if (checked) {
|
||||
await actions.enableNotifications();
|
||||
await actions.enableNotifications()
|
||||
} else {
|
||||
await actions.disableNotifications();
|
||||
await actions.disableNotifications()
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
showError()
|
||||
}
|
||||
catch (err) {
|
||||
console.log(err);
|
||||
showError();
|
||||
}
|
||||
setSavingNotifications(false);
|
||||
setSavingNotifications(false)
|
||||
}
|
||||
}
|
||||
|
||||
const setDetails = async () => {
|
||||
if (!savingDetails) {
|
||||
setSavingDetails(true);
|
||||
setSavingDetails(true)
|
||||
try {
|
||||
await actions.setDetails();
|
||||
detailsClose();
|
||||
await actions.setDetails()
|
||||
detailsClose()
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
showError()
|
||||
}
|
||||
catch (err) {
|
||||
console.log(err);
|
||||
showError();
|
||||
}
|
||||
setSavingDetails(false);
|
||||
setSavingDetails(false)
|
||||
}
|
||||
}
|
||||
|
||||
const clickSelect = () => {
|
||||
if (imageFile.current) {
|
||||
imageFile.current.click();
|
||||
imageFile.current.click()
|
||||
}
|
||||
}
|
||||
|
||||
const selectImage = (target: HTMLInputElement) => {
|
||||
if (target.files) {
|
||||
var reader = new FileReader();
|
||||
var reader = new FileReader()
|
||||
reader.onload = () => {
|
||||
if (typeof reader.result === 'string') {
|
||||
actions.setEditImage(reader.result);
|
||||
actions.setEditImage(reader.result)
|
||||
}
|
||||
}
|
||||
reader.readAsDataURL(target.files[0]);
|
||||
reader.readAsDataURL(target.files[0])
|
||||
}
|
||||
}
|
||||
|
||||
const setImage = async () => {
|
||||
if (!savingImage) {
|
||||
setSavingImage(true);
|
||||
setSavingImage(true)
|
||||
try {
|
||||
await actions.setImage();
|
||||
imageClose();
|
||||
await actions.setImage()
|
||||
imageClose()
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
showError()
|
||||
}
|
||||
catch (err) {
|
||||
console.log(err);
|
||||
showError();
|
||||
}
|
||||
setSavingImage(false);
|
||||
setSavingImage(false)
|
||||
}
|
||||
}
|
||||
|
||||
const setLogin = async () => {
|
||||
if (!savingLogin) {
|
||||
setSavingLogin(true);
|
||||
if (!savingLogin) {
|
||||
setSavingLogin(true)
|
||||
try {
|
||||
await actions.setLogin();
|
||||
changeClose();
|
||||
await actions.setLogin()
|
||||
changeClose()
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
showError()
|
||||
}
|
||||
catch (err) {
|
||||
console.log(err);
|
||||
showError();
|
||||
}
|
||||
setSavingLogin(false);
|
||||
setSavingLogin(false)
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,58 +176,71 @@ export function Settings({ showLogout }: { showLogout: boolean }) {
|
||||
backgroundOpacity: 0.55,
|
||||
blur: 3,
|
||||
},
|
||||
children: (
|
||||
<Text>{state.strings.tryAgain}</Text>
|
||||
),
|
||||
children: <Text>{state.strings.tryAgain}</Text>,
|
||||
cancelProps: { display: 'none' },
|
||||
confirmProps: { display: 'none' },
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
const onCropComplete = useCallback((crop: Area) => {
|
||||
actions.setEditImageCrop(crop)
|
||||
// eslint-disable-next-line
|
||||
}, []);
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<>
|
||||
{ state.profileSet && (
|
||||
{state.profileSet && (
|
||||
<div className={classes.settings}>
|
||||
<Text className={classes.header}>{`${state.profile.handle}${state.profile.node ? '/' + state.profile.node : ''}`}</Text>
|
||||
<Text
|
||||
className={classes.header}
|
||||
>{`${state.profile.handle}${state.profile.node ? '/' + state.profile.node : ''}`}</Text>
|
||||
<div className={classes.image}>
|
||||
{ state.profile.imageSet && (
|
||||
{state.profile.imageSet && (
|
||||
<div className={classes.imageSet}>
|
||||
<Image radius="md" src={state.imageUrl} />
|
||||
<Image radius="md" src={state.imageUrl} />
|
||||
<div className={classes.edit}>
|
||||
<Button size="compact-md" variant="outlined" onClick={imageOpen}>{ state.strings.edit }</Button>
|
||||
<Button
|
||||
size="compact-md"
|
||||
variant="outlined"
|
||||
onClick={imageOpen}
|
||||
>
|
||||
{state.strings.edit}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{ !state.profile.imageSet && (
|
||||
{!state.profile.imageSet && (
|
||||
<div className={classes.imageUnset} onClick={imageOpen}>
|
||||
<Image radius="md" src={state.imageUrl} />
|
||||
<Text className={classes.unsetEdit}>{ state.strings.edit }</Text>
|
||||
<Image radius="md" src={state.imageUrl} />
|
||||
<Text className={classes.unsetEdit}>{state.strings.edit}</Text>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className={classes.section}>
|
||||
<div className={classes.divider} />
|
||||
<UnstyledButton className={classes.sectionEdit} onClick={detailsOpen}>{ state.strings.edit }</UnstyledButton>
|
||||
<UnstyledButton
|
||||
className={classes.sectionEdit}
|
||||
onClick={detailsOpen}
|
||||
>
|
||||
{state.strings.edit}
|
||||
</UnstyledButton>
|
||||
</div>
|
||||
{ !state.profile.name && (
|
||||
{!state.profile.name && (
|
||||
<Text className={classes.nameUnset}>{state.strings.name}</Text>
|
||||
)}
|
||||
{ state.profile.name && (
|
||||
{state.profile.name && (
|
||||
<Text className={classes.nameSet}>{state.profile.name}</Text>
|
||||
)}
|
||||
<div className={classes.entry}>
|
||||
<div className={classes.entryIcon}>
|
||||
<IconMapPin />
|
||||
</div>
|
||||
{ !state.profile.location && (
|
||||
<Text className={classes.entryUnset}>{state.strings.location}</Text>
|
||||
{!state.profile.location && (
|
||||
<Text className={classes.entryUnset}>
|
||||
{state.strings.location}
|
||||
</Text>
|
||||
)}
|
||||
{ state.profile.location && (
|
||||
{state.profile.location && (
|
||||
<Text className={classes.entrySet}>{state.profile.location}</Text>
|
||||
)}
|
||||
</div>
|
||||
@ -200,11 +248,15 @@ export function Settings({ showLogout }: { showLogout: boolean }) {
|
||||
<div className={classes.entryIcon}>
|
||||
<IconBook />
|
||||
</div>
|
||||
{ !state.profile.description && (
|
||||
<Text className={classes.entryUnset}>{state.strings.description}</Text>
|
||||
{!state.profile.description && (
|
||||
<Text className={classes.entryUnset}>
|
||||
{state.strings.description}
|
||||
</Text>
|
||||
)}
|
||||
{ state.profile.description && (
|
||||
<Text className={classes.entrySet}>{state.profile.description}</Text>
|
||||
{state.profile.description && (
|
||||
<Text className={classes.entrySet}>
|
||||
{state.profile.description}
|
||||
</Text>
|
||||
)}
|
||||
</div>
|
||||
<div className={classes.divider} />
|
||||
@ -212,43 +264,59 @@ export function Settings({ showLogout }: { showLogout: boolean }) {
|
||||
<div className={classes.entryIcon}>
|
||||
<IconEye />
|
||||
</div>
|
||||
<Text className={classes.entryLabel}>{ state.strings.registry }</Text>
|
||||
<Switch className={classes.entryControl} checked={state.config.searchable} onChange={(ev) => setRegistry(ev.currentTarget.checked)} />
|
||||
<Text className={classes.entryLabel}>{state.strings.registry}</Text>
|
||||
<Switch
|
||||
className={classes.entryControl}
|
||||
checked={state.config.searchable}
|
||||
onChange={(ev) => setRegistry(ev.currentTarget.checked)}
|
||||
/>
|
||||
</div>
|
||||
<div className={classes.entry}>
|
||||
<div className={classes.entryIcon}>
|
||||
<IconCloudLock />
|
||||
</div>
|
||||
<Text className={classes.entryLabel}>{ state.strings.manageTopics }</Text>
|
||||
<Text className={classes.entryLabel}>
|
||||
{state.strings.manageTopics}
|
||||
</Text>
|
||||
</div>
|
||||
<div className={classes.entry}>
|
||||
<div className={classes.entryIcon}>
|
||||
<IconBell />
|
||||
</div>
|
||||
<Text className={classes.entryLabel}>{ state.strings.enableNotifications }</Text>
|
||||
<Switch className={classes.entryControl} checked={state.config.pushEnabled} onChange={(ev) => setNotifications(ev.currentTarget.checked)} />
|
||||
<Text className={classes.entryLabel}>
|
||||
{state.strings.enableNotifications}
|
||||
</Text>
|
||||
<Switch
|
||||
className={classes.entryControl}
|
||||
checked={state.config.pushEnabled}
|
||||
onChange={(ev) => setNotifications(ev.currentTarget.checked)}
|
||||
/>
|
||||
</div>
|
||||
<div className={classes.divider} />
|
||||
{ showLogout && (
|
||||
{showLogout && (
|
||||
<div className={classes.entry}>
|
||||
<div className={classes.entryIcon}>
|
||||
<IconLogout />
|
||||
</div>
|
||||
<Text className={classes.entryLabel} onClick={logout}>{ state.strings.logout }</Text>
|
||||
<Text className={classes.entryLabel} onClick={logout}>
|
||||
{state.strings.logout}
|
||||
</Text>
|
||||
</div>
|
||||
)}
|
||||
<div className={classes.entry}>
|
||||
<div className={classes.entryIcon}>
|
||||
<IconTicket />
|
||||
</div>
|
||||
<Text className={classes.entryLabel}>{ state.strings.mfaTitle }</Text>
|
||||
<Text className={classes.entryLabel}>{state.strings.mfaTitle}</Text>
|
||||
<Switch className={classes.entryControl} />
|
||||
</div>
|
||||
<div className={classes.entry}>
|
||||
<div className={classes.entryIcon}>
|
||||
<IconLogin />
|
||||
</div>
|
||||
<Text className={classes.entryLabel} onClick={changeOpen}>{ state.strings.changeLogin }</Text>
|
||||
<Text className={classes.entryLabel} onClick={changeOpen}>
|
||||
{state.strings.changeLogin}
|
||||
</Text>
|
||||
</div>
|
||||
<div className={classes.divider} />
|
||||
<div className={classes.selects}>
|
||||
@ -256,7 +324,9 @@ export function Settings({ showLogout }: { showLogout: boolean }) {
|
||||
<div className={classes.entryIcon}>
|
||||
<IconClock />
|
||||
</div>
|
||||
<Text className={classes.controlLabel}>{ state.strings.timeFormat }</Text>
|
||||
<Text className={classes.controlLabel}>
|
||||
{state.strings.timeFormat}
|
||||
</Text>
|
||||
<Radio.Group
|
||||
name="timeFormat"
|
||||
className={classes.radio}
|
||||
@ -264,8 +334,8 @@ export function Settings({ showLogout }: { showLogout: boolean }) {
|
||||
onChange={actions.setTimeFormat}
|
||||
>
|
||||
<Group mt="xs">
|
||||
<Radio value="12h" label={ state.strings.timeUs } />
|
||||
<Radio value="24h" label={ state.strings.timeEu } />
|
||||
<Radio value="12h" label={state.strings.timeUs} />
|
||||
<Radio value="24h" label={state.strings.timeEu} />
|
||||
</Group>
|
||||
</Radio.Group>
|
||||
</div>
|
||||
@ -273,7 +343,9 @@ export function Settings({ showLogout }: { showLogout: boolean }) {
|
||||
<div className={classes.entryIcon}>
|
||||
<IconCalendar />
|
||||
</div>
|
||||
<Text className={classes.controlLabel}>{ state.strings.dateFormat }</Text>
|
||||
<Text className={classes.controlLabel}>
|
||||
{state.strings.dateFormat}
|
||||
</Text>
|
||||
<Radio.Group
|
||||
name="dateFormat"
|
||||
className={classes.radio}
|
||||
@ -281,8 +353,8 @@ export function Settings({ showLogout }: { showLogout: boolean }) {
|
||||
onChange={actions.setDateFormat}
|
||||
>
|
||||
<Group mt="xs">
|
||||
<Radio value="mm/dd" label={ state.strings.dateUs } />
|
||||
<Radio value="dd/mm" label={ state.strings.dateEu } />
|
||||
<Radio value="mm/dd" label={state.strings.dateUs} />
|
||||
<Radio value="dd/mm" label={state.strings.dateEu} />
|
||||
</Group>
|
||||
</Radio.Group>
|
||||
</div>
|
||||
@ -290,7 +362,9 @@ export function Settings({ showLogout }: { showLogout: boolean }) {
|
||||
<div className={classes.entryIcon}>
|
||||
<IconBrightness />
|
||||
</div>
|
||||
<Text className={classes.controlLabel}>{ state.strings.theme }</Text>
|
||||
<Text className={classes.controlLabel}>
|
||||
{state.strings.theme}
|
||||
</Text>
|
||||
<Select
|
||||
className={classes.entryControl}
|
||||
size="xs"
|
||||
@ -303,7 +377,9 @@ export function Settings({ showLogout }: { showLogout: boolean }) {
|
||||
<div className={classes.entryIcon}>
|
||||
<IconWorld />
|
||||
</div>
|
||||
<Text className={classes.controlLabel}>{ state.strings.language }</Text>
|
||||
<Text className={classes.controlLabel}>
|
||||
{state.strings.language}
|
||||
</Text>
|
||||
<Select
|
||||
className={classes.entryControl}
|
||||
size="xs"
|
||||
@ -316,11 +392,16 @@ export function Settings({ showLogout }: { showLogout: boolean }) {
|
||||
<div className={classes.entryIcon}>
|
||||
<IconMicrophone />
|
||||
</div>
|
||||
<Text className={classes.controlLabel}>{ state.strings.microphone }</Text>
|
||||
<Text className={classes.controlLabel}>
|
||||
{state.strings.microphone}
|
||||
</Text>
|
||||
<Select
|
||||
className={classes.entryControl}
|
||||
size="xs"
|
||||
data={[ { value: '', label: state.strings.default }, ...state.audioInputs ]}
|
||||
data={[
|
||||
{ value: '', label: state.strings.default },
|
||||
...state.audioInputs,
|
||||
]}
|
||||
value={state.audioId ? state.audioId : ''}
|
||||
onChange={actions.setAudio}
|
||||
/>
|
||||
@ -329,11 +410,16 @@ export function Settings({ showLogout }: { showLogout: boolean }) {
|
||||
<div className={classes.entryIcon}>
|
||||
<IconVideo />
|
||||
</div>
|
||||
<Text className={classes.controlLabel}>{ state.strings.camera }</Text>
|
||||
<Text className={classes.controlLabel}>
|
||||
{state.strings.camera}
|
||||
</Text>
|
||||
<Select
|
||||
className={classes.entryControl}
|
||||
size="xs"
|
||||
data={[ { value: '', label: state.strings.default }, ...state.videoInputs ]}
|
||||
data={[
|
||||
{ value: '', label: state.strings.default },
|
||||
...state.videoInputs,
|
||||
]}
|
||||
value={state.videoId ? state.videoId : ''}
|
||||
onChange={actions.setVideo}
|
||||
/>
|
||||
@ -357,9 +443,7 @@ export function Settings({ showLogout }: { showLogout: boolean }) {
|
||||
leftSection={<IconUser />}
|
||||
rightSection={state.taken ? <IconUsers /> : null}
|
||||
placeholder={state.strings.username}
|
||||
onChange={(event) =>
|
||||
actions.setHandle(event.currentTarget.value)
|
||||
}
|
||||
onChange={(event) => actions.setHandle(event.currentTarget.value)}
|
||||
error={state.taken}
|
||||
/>
|
||||
<PasswordInput
|
||||
@ -368,9 +452,7 @@ export function Settings({ showLogout }: { showLogout: boolean }) {
|
||||
value={state.password}
|
||||
leftSection={<IconLock />}
|
||||
placeholder={state.strings.password}
|
||||
onChange={(event) =>
|
||||
actions.setPassword(event.currentTarget.value)
|
||||
}
|
||||
onChange={(event) => actions.setPassword(event.currentTarget.value)}
|
||||
/>
|
||||
<PasswordInput
|
||||
className={classes.input}
|
||||
@ -378,9 +460,7 @@ export function Settings({ showLogout }: { showLogout: boolean }) {
|
||||
value={state.confirm}
|
||||
leftSection={<IconLock />}
|
||||
placeholder={state.strings.confirmPassword}
|
||||
onChange={(event) =>
|
||||
actions.setConfirm(event.currentTarget.value)
|
||||
}
|
||||
onChange={(event) => actions.setConfirm(event.currentTarget.value)}
|
||||
/>
|
||||
<div className={classes.control}>
|
||||
<Button variant="default" onClick={changeClose}>
|
||||
@ -390,7 +470,13 @@ export function Settings({ showLogout }: { showLogout: boolean }) {
|
||||
variant="filled"
|
||||
onClick={setLogin}
|
||||
loading={savingLogin}
|
||||
disabled={state.taken || !state.checked || !state.handle || !state.password || state.confirm !== state.password}
|
||||
disabled={
|
||||
state.taken ||
|
||||
!state.checked ||
|
||||
!state.handle ||
|
||||
!state.password ||
|
||||
state.confirm !== state.password
|
||||
}
|
||||
>
|
||||
{state.strings.save}
|
||||
</Button>
|
||||
@ -412,9 +498,7 @@ export function Settings({ showLogout }: { showLogout: boolean }) {
|
||||
leftSectionPointerEvents="none"
|
||||
leftSection={<IconIdBadge />}
|
||||
placeholder={state.strings.name}
|
||||
onChange={(event) =>
|
||||
actions.setName(event.currentTarget.value)
|
||||
}
|
||||
onChange={(event) => actions.setName(event.currentTarget.value)}
|
||||
/>
|
||||
<TextInput
|
||||
className={classes.input}
|
||||
@ -423,9 +507,7 @@ export function Settings({ showLogout }: { showLogout: boolean }) {
|
||||
leftSectionPointerEvents="none"
|
||||
leftSection={<IconMapPin />}
|
||||
placeholder={state.strings.location}
|
||||
onChange={(event) =>
|
||||
actions.setLocation(event.currentTarget.value)
|
||||
}
|
||||
onChange={(event) => actions.setLocation(event.currentTarget.value)}
|
||||
/>
|
||||
<Textarea
|
||||
className={classes.input}
|
||||
@ -465,31 +547,43 @@ export function Settings({ showLogout }: { showLogout: boolean }) {
|
||||
>
|
||||
<div className={classes.change}>
|
||||
<div className={classes.cropper}>
|
||||
<Cropper image={state.editImage} crop={state.crop} zoom={state.zoom} aspect={1}
|
||||
onCropChange={actions.setCrop} onCropComplete={(area, crop) => onCropComplete(crop)} onZoomChange={actions.setZoom} />
|
||||
<Cropper
|
||||
image={state.editImage}
|
||||
crop={state.crop}
|
||||
zoom={state.zoom}
|
||||
aspect={1}
|
||||
onCropChange={actions.setCrop}
|
||||
onCropComplete={(area, crop) => onCropComplete(crop)}
|
||||
onZoomChange={actions.setZoom}
|
||||
/>
|
||||
</div>
|
||||
<div className={classes.imageSelect}>
|
||||
<input type='file' id='file' accept="image/*" ref={imageFile} onChange={e => selectImage(e.target)} style={{display: 'none'}}/>
|
||||
<Button variant="default" className={classes.select} onClick={clickSelect}>
|
||||
<input
|
||||
type="file"
|
||||
id="file"
|
||||
accept="image/*"
|
||||
ref={imageFile}
|
||||
onChange={(e) => selectImage(e.target)}
|
||||
style={{ display: 'none' }}
|
||||
/>
|
||||
<Button
|
||||
variant="default"
|
||||
className={classes.select}
|
||||
onClick={clickSelect}
|
||||
>
|
||||
{state.strings.selectImage}
|
||||
</Button>
|
||||
<div className={classes.control}>
|
||||
<Button variant="default" onClick={imageClose}>
|
||||
{state.strings.cancel}
|
||||
</Button>
|
||||
<Button
|
||||
variant="filled"
|
||||
onClick={setImage}
|
||||
loading={savingImage}
|
||||
>
|
||||
<Button variant="filled" onClick={setImage} loading={savingImage}>
|
||||
{state.strings.save}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
</>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1,18 +1,23 @@
|
||||
import { useEffect, useState, useContext, useRef } from 'react'
|
||||
import { AppContext } from '../context/AppContext';
|
||||
import { DisplayContext } from '../context/DisplayContext';
|
||||
import { ContextType } from '../context/ContextType';
|
||||
import { Session, Settings, Identity, type Profile, type Config } from 'databag-client-sdk'
|
||||
import { AppContext } from '../context/AppContext'
|
||||
import { DisplayContext } from '../context/DisplayContext'
|
||||
import { ContextType } from '../context/ContextType'
|
||||
import {
|
||||
Session,
|
||||
Settings,
|
||||
Identity,
|
||||
type Profile,
|
||||
type Config,
|
||||
} from 'databag-client-sdk'
|
||||
import { Point, Area } from 'react-easy-crop/types'
|
||||
|
||||
const IMAGE_DIM = 192;
|
||||
const DEBOUNCE_MS = 1000;
|
||||
const IMAGE_DIM = 192
|
||||
const DEBOUNCE_MS = 1000
|
||||
|
||||
export function useSettings() {
|
||||
|
||||
const display = useContext(DisplayContext) as ContextType;
|
||||
const app = useContext(AppContext) as ContextType;
|
||||
const debounce = useRef(setTimeout(() => {}, 0));
|
||||
const display = useContext(DisplayContext) as ContextType
|
||||
const app = useContext(AppContext) as ContextType
|
||||
const debounce = useRef(setTimeout(() => {}, 0))
|
||||
|
||||
const [state, setState] = useState({
|
||||
config: {} as Config,
|
||||
@ -41,7 +46,7 @@ export function useSettings() {
|
||||
location: '',
|
||||
handle: '',
|
||||
clip: { w: 0, h: 0, x: 0, y: 0 },
|
||||
crop: { x: 0, y: 0},
|
||||
crop: { x: 0, y: 0 },
|
||||
zoom: 1,
|
||||
editImage: undefined,
|
||||
})
|
||||
@ -52,11 +57,11 @@ export function useSettings() {
|
||||
}
|
||||
|
||||
const getSession = () => {
|
||||
const session = app.state?.session;
|
||||
const settings = session?.getSettings();
|
||||
const identity = session?.getIdentity();
|
||||
const session = app.state?.session
|
||||
const settings = session?.getSettings()
|
||||
const identity = session?.getIdentity()
|
||||
if (!settings || !identity) {
|
||||
console.log('session not set in settings hook');
|
||||
console.log('session not set in settings hook')
|
||||
}
|
||||
return { settings, identity }
|
||||
}
|
||||
@ -64,24 +69,44 @@ export function useSettings() {
|
||||
useEffect(() => {
|
||||
const { settings, identity } = getSession()
|
||||
const setConfig = (config: Config) => {
|
||||
updateState({ config })
|
||||
updateState({ config })
|
||||
}
|
||||
settings.addConfigListener(setConfig);
|
||||
settings.addConfigListener(setConfig)
|
||||
const setProfile = (profile: Profile) => {
|
||||
const { handle, name, location, description } = profile;
|
||||
const url = identity.getProfileImageUrl();
|
||||
updateState({ profile, handle, name, location, description, imageUrl: url, editImage: url, profileSet: true })
|
||||
const { handle, name, location, description } = profile
|
||||
const url = identity.getProfileImageUrl()
|
||||
updateState({
|
||||
profile,
|
||||
handle,
|
||||
name,
|
||||
location,
|
||||
description,
|
||||
imageUrl: url,
|
||||
editImage: url,
|
||||
profileSet: true,
|
||||
})
|
||||
}
|
||||
identity.addProfileListener(setProfile)
|
||||
return () => {
|
||||
settings.removeConfigListener(setConfig);
|
||||
identity.removeProfileListener(setProfile);
|
||||
return () => {
|
||||
settings.removeConfigListener(setConfig)
|
||||
identity.removeProfileListener(setProfile)
|
||||
}
|
||||
}, []);
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
const { strings, dateFormat, timeFormat, themes, scheme, languages, language, audioId, audioInputs, videoId, videoInputs } =
|
||||
display.state
|
||||
const {
|
||||
strings,
|
||||
dateFormat,
|
||||
timeFormat,
|
||||
themes,
|
||||
scheme,
|
||||
languages,
|
||||
language,
|
||||
audioId,
|
||||
audioInputs,
|
||||
videoId,
|
||||
videoInputs,
|
||||
} = display.state
|
||||
updateState({
|
||||
strings,
|
||||
dateFormat,
|
||||
@ -99,68 +124,72 @@ export function useSettings() {
|
||||
|
||||
const actions = {
|
||||
getUsernameStatus: async (username: string) => {
|
||||
const { settings } = getSession();
|
||||
return await settings.getUsernameStatus(username);
|
||||
const { settings } = getSession()
|
||||
return await settings.getUsernameStatus(username)
|
||||
},
|
||||
setLogin: async () => {
|
||||
const { settings } = getSession();
|
||||
await settings.setLogin(state.handle, state.password);
|
||||
const { settings } = getSession()
|
||||
await settings.setLogin(state.handle, state.password)
|
||||
},
|
||||
enableNotifications: async () => {
|
||||
const { settings } = getSession();
|
||||
await settings.enableNotifications();
|
||||
const { settings } = getSession()
|
||||
await settings.enableNotifications()
|
||||
},
|
||||
disableNotifications: async () => {
|
||||
const { settings } = getSession();
|
||||
await settings.disableNotifications();
|
||||
const { settings } = getSession()
|
||||
await settings.disableNotifications()
|
||||
},
|
||||
enableRegistry: async () => {
|
||||
const { settings } = getSession();
|
||||
await settings.enableRegistry();
|
||||
const { settings } = getSession()
|
||||
await settings.enableRegistry()
|
||||
},
|
||||
disableRegistry: async () => {
|
||||
const { settings } = getSession();
|
||||
await settings.disableRegistry();
|
||||
const { settings } = getSession()
|
||||
await settings.disableRegistry()
|
||||
},
|
||||
enableMFA: async () => {
|
||||
const { settings } = getSession();
|
||||
return await settings.enableMFA();
|
||||
const { settings } = getSession()
|
||||
return await settings.enableMFA()
|
||||
},
|
||||
disableMFA: async () => {
|
||||
const { settings } = getSession();
|
||||
await settings.disableMFA();
|
||||
const { settings } = getSession()
|
||||
await settings.disableMFA()
|
||||
},
|
||||
confirmMFA: async (code: string) => {
|
||||
const { settings } = getSession();
|
||||
await settings.confirmMFA(code);
|
||||
const { settings } = getSession()
|
||||
await settings.confirmMFA(code)
|
||||
},
|
||||
setSeal: async (password: string) => {
|
||||
const { settings } = getSession();
|
||||
await settings.setSeal(password);
|
||||
const { settings } = getSession()
|
||||
await settings.setSeal(password)
|
||||
},
|
||||
clearSeal: async () => {
|
||||
const { settings } = getSession();
|
||||
await settings.clearSeal();
|
||||
const { settings } = getSession()
|
||||
await settings.clearSeal()
|
||||
},
|
||||
unlockSeal: async (password: string) => {
|
||||
const { settings } = getSession();
|
||||
await settings.unlockSeal(password);
|
||||
const { settings } = getSession()
|
||||
await settings.unlockSeal(password)
|
||||
},
|
||||
forgetSeal: async () => {
|
||||
const { settings } = getSession();
|
||||
await settings.forgetSeal();
|
||||
const { settings } = getSession()
|
||||
await settings.forgetSeal()
|
||||
},
|
||||
setProfileData: async (name: string, location: string, description: string) => {
|
||||
const { identity } = getSession();
|
||||
await identity.setProfileData(name, location, description);
|
||||
setProfileData: async (
|
||||
name: string,
|
||||
location: string,
|
||||
description: string
|
||||
) => {
|
||||
const { identity } = getSession()
|
||||
await identity.setProfileData(name, location, description)
|
||||
},
|
||||
setProfileImage: async (image: string) => {
|
||||
const { identity } = getSession();
|
||||
await identity.setProfileImage(image);
|
||||
const { identity } = getSession()
|
||||
await identity.setProfileImage(image)
|
||||
},
|
||||
getProfileImageUrl: () => {
|
||||
const { identity } = getSession();
|
||||
return identity.getProfileImageUrl();
|
||||
const { identity } = getSession()
|
||||
return identity.getProfileImageUrl()
|
||||
},
|
||||
setLanguage: (code: string) => {
|
||||
display.actions.setLanguage(code)
|
||||
@ -169,103 +198,110 @@ export function useSettings() {
|
||||
display.actions.setTheme(theme)
|
||||
},
|
||||
setVideo: (device: string | null) => {
|
||||
display.actions.setVideoInput(device ? device : null);
|
||||
display.actions.setVideoInput(device ? device : null)
|
||||
},
|
||||
setAudio: (device: string | null) => {
|
||||
display.actions.setAudioInput(device ? device : null);
|
||||
display.actions.setAudioInput(device ? device : null)
|
||||
},
|
||||
setDateFormat: (format: string) => {
|
||||
display.actions.setDateFormat(format);
|
||||
display.actions.setDateFormat(format)
|
||||
},
|
||||
setTimeFormat: (format: string) => {
|
||||
display.actions.setTimeFormat(format);
|
||||
display.actions.setTimeFormat(format)
|
||||
},
|
||||
setAll: (all: boolean) => {
|
||||
updateState({ all });
|
||||
updateState({ all })
|
||||
},
|
||||
logout: async () => {
|
||||
await app.actions.accountLogout(state.all);
|
||||
await app.actions.accountLogout(state.all)
|
||||
},
|
||||
setHandle: (handle: string) => {
|
||||
updateState({ handle, taken: false, checked: false });
|
||||
clearTimeout(debounce.current);
|
||||
updateState({ handle, taken: false, checked: false })
|
||||
clearTimeout(debounce.current)
|
||||
if (!handle || handle === state.profile.handle) {
|
||||
updateState({ available: true, checked: true});
|
||||
}
|
||||
else {
|
||||
updateState({ available: true, checked: true })
|
||||
} else {
|
||||
debounce.current = setTimeout(async () => {
|
||||
const { settings } = getSession();
|
||||
const available = await settings.getUsernameStatus(handle);
|
||||
updateState({ taken: !available, checked: true });
|
||||
}, DEBOUNCE_MS);
|
||||
const { settings } = getSession()
|
||||
const available = await settings.getUsernameStatus(handle)
|
||||
updateState({ taken: !available, checked: true })
|
||||
}, DEBOUNCE_MS)
|
||||
}
|
||||
},
|
||||
setPassword: (password: string) => {
|
||||
updateState({ password });
|
||||
updateState({ password })
|
||||
},
|
||||
setConfirm: (confirm: string) => {
|
||||
updateState({ confirm });
|
||||
updateState({ confirm })
|
||||
},
|
||||
setName: (name: string) => {
|
||||
updateState({ name });
|
||||
updateState({ name })
|
||||
},
|
||||
setLocation: (location: string) => {
|
||||
updateState({ location });
|
||||
updateState({ location })
|
||||
},
|
||||
setDescription: (description: string) => {
|
||||
updateState({ description });
|
||||
updateState({ description })
|
||||
},
|
||||
setDetails: async () => {
|
||||
const { identity } = getSession();
|
||||
const { name, location, description } = state;
|
||||
await identity.setProfileData(name, location, description);
|
||||
const { identity } = getSession()
|
||||
const { name, location, description } = state
|
||||
await identity.setProfileData(name, location, description)
|
||||
},
|
||||
setCrop: (crop: Point) => {
|
||||
updateState({ crop });
|
||||
updateState({ crop })
|
||||
},
|
||||
setZoom: (zoom: number) => {
|
||||
updateState({ zoom });
|
||||
updateState({ zoom })
|
||||
},
|
||||
setEditImageCrop: (clip: Area) => {
|
||||
updateState({ clip });
|
||||
updateState({ clip })
|
||||
},
|
||||
setEditImage: (editImage: string) => {
|
||||
updateState({ editImage });
|
||||
updateState({ editImage })
|
||||
},
|
||||
setImage: async () => {
|
||||
const { identity } = getSession();
|
||||
const { identity } = getSession()
|
||||
const processImg = () => {
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
let img = new Image();
|
||||
let img = new Image()
|
||||
img.onload = () => {
|
||||
try {
|
||||
const canvas = document.createElement("canvas");
|
||||
const context = canvas.getContext('2d');
|
||||
const canvas = document.createElement('canvas')
|
||||
const context = canvas.getContext('2d')
|
||||
if (!context) {
|
||||
throw new Error('failed to allocate context');
|
||||
throw new Error('failed to allocate context')
|
||||
}
|
||||
canvas.width = IMAGE_DIM;
|
||||
canvas.height = IMAGE_DIM;
|
||||
context.imageSmoothingQuality = "medium";
|
||||
context.drawImage(img, state.clip.x, state.clip.y, state.clip.width, state.clip.height,
|
||||
0, 0, IMAGE_DIM, IMAGE_DIM);
|
||||
resolve(canvas.toDataURL());
|
||||
}
|
||||
catch (err) {
|
||||
console.log(err);
|
||||
reject();
|
||||
canvas.width = IMAGE_DIM
|
||||
canvas.height = IMAGE_DIM
|
||||
context.imageSmoothingQuality = 'medium'
|
||||
context.drawImage(
|
||||
img,
|
||||
state.clip.x,
|
||||
state.clip.y,
|
||||
state.clip.width,
|
||||
state.clip.height,
|
||||
0,
|
||||
0,
|
||||
IMAGE_DIM,
|
||||
IMAGE_DIM
|
||||
)
|
||||
resolve(canvas.toDataURL())
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
reject()
|
||||
}
|
||||
}
|
||||
if (!state.editImage) {
|
||||
throw new Error('invalid edit image');
|
||||
throw new Error('invalid edit image')
|
||||
}
|
||||
img.onerror = reject;
|
||||
img.src = state.editImage;
|
||||
});
|
||||
};
|
||||
const dataUrl = await processImg();
|
||||
const data = dataUrl.split(",")[1];
|
||||
await identity.setProfileImage(data);
|
||||
img.onerror = reject
|
||||
img.src = state.editImage
|
||||
})
|
||||
}
|
||||
const dataUrl = await processImg()
|
||||
const data = dataUrl.split(',')[1]
|
||||
await identity.setProfileImage(data)
|
||||
},
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user