setting sticky header for settings and profile

This commit is contained in:
balzack 2024-11-13 00:26:01 -08:00
parent e41d1faad7
commit 67499e1749
9 changed files with 195 additions and 169 deletions

View File

@ -19,7 +19,7 @@ const theme = createTheme({
'databag-green': ['#eef6f2', '#cce5d9', '#aad4bf', '#68c4af', '#559e83', '#559e83', '#3c7759', '#2b5540', '#1a3326', '#09110d'],
'dark-surface': ['#000000', '#111111', '#222222', '#333333', '#444444', '#555555', '#666666', '#777777', '#888888', '#999999'],
'light-surface': ['#ffffff', '#eeeeee', '#dddddd', '#cccccc', '#bbbbbb', '#aaaaaa', '#999999', '#888888', '#777777', '#666666'],
'dark-text': ['#ffffff', '#eeeeee', '#dddddd', '#cccccc', '#bbbbbb', '#aaaaaa', '#999999', '#888888', '#777777', '#666666'],
'dark-text': ['#ffffff', '#eeeeee', '#dddddd', '#cccccc', '#bbbbbb', '#aaaaaa', '#999999', '#666666', '#444444', '#222222'],
'light-text': ['#000000', '#111111', '#222222', '#333333', '#444444', '#555555', '#666666', '#777777', '#888888', '#999999'],
'dark-databag-green': ['#99bb99', '#559e83', '#559e83', '#559e83', '#559e83', '#559e83', '#559e83', '#559e83', '#559e83', '#559e83'],
'light-databag-green': ['#888888', '#448844', '#448844', '#448844', '#448844', '#448844', '#448844', '#448844', '#448844', '#448844'],

View File

@ -53,7 +53,7 @@
text-overflow: ellipsis;
overflow: hidden;
font-style: italic;
color: var(--mantine-color-text-9);
color: var(--mantine-color-text-7);
}
.handle {

View File

@ -1,5 +1,3 @@
import {NativeModules, Platform} from 'react-native';
export const en = {
unknown: 'Unknown',
sealed: 'Sealed',

View File

@ -14,7 +14,7 @@
padding-left: 16px;
padding-right: 16px;
padding-bottom: 8px;
border-bottom: 2px solid var(--mantine-color-text-9);
border-bottom: 2px solid var(--mantine-color-text-8);
width: 100%;
.input {

View File

@ -46,7 +46,7 @@ export function Content({ select }: { select: (focus: Focus) => void }) {
</Button>
)}
</div>
{channels.length === 0 && <div className={classes.none}>{state.strings.noContacts}</div>}
{channels.length === 0 && <div className={classes.none}>{state.strings.noTopics}</div>}
{channels.length !== 0 && <div className={classes.channels}>{channels}</div>}
{state.layout === 'large' && (
<div className={classes.bar}>

View File

@ -1,21 +1,21 @@
.contact {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
padding-left: 16px;
padding-right: 16px;
padding-top: 8px;
padding-bottom: 4px;
width: 100%;
height: 100%;
.detail {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
flex-grow: 1;
width: 100%;
overflow: scroll;
padding-left: 16px;
padding-right: 16px;
}
.header {
@ -23,6 +23,11 @@
flex-direction: row;
align-items: center;
width: 100%;
border-bottom: 1px solid var(--mantine-color-text-9);
padding-left: 16px;
padding-right: 16px;
height: 48px;
flex-shrink: 0;
}
.close {

View File

@ -237,12 +237,12 @@ export function Profile({ params, close }: { params: ProfileParams; close?: () =
return (
<div className={classes.contact}>
<div className={classes.header}>
{close && <IconX size={28} className={classes.match} />}
<Text className={classes.label}>{`${state.handle}${state.node ? '/' + state.node : ''}`}</Text>
{close && <IconX size={30} className={classes.close} onClick={close} />}
</div>
<div className={classes.detail}>
<div className={classes.header}>
{close && <IconX size={28} className={classes.match} />}
<Text className={classes.label}>{`${state.handle}${state.node ? '/' + state.node : ''}`}</Text>
{close && <IconX size={30} className={classes.close} onClick={close} />}
</div>
<div className={classes.image}>
<Image radius="md" src={state.imageUrl} />
</div>

View File

@ -85,13 +85,10 @@
display: flex;
flex-direction: column;
align-items: center;
padding-left: 16px;
padding-right: 16px;
padding-top: 8px;
padding-bottom: 8px;
gap: 2px;
height: 100%;
.header {
.headerLabel {
font-size: 22px;
text-align: center;
text-wrap: nowrap;
@ -100,6 +97,28 @@
width: 100%;
}
.header {
padding-top: 4px;
padding-bottom: 4px;
padding-left: 16px;
padding-right: 16px;
width: 100%;
height: 48px;
flex-shrink: 0;
border-bottom: 1px solid var(--mantine-color-text-7);
}
.detail {
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
overflow: scroll;
padding-left: 16px;
padding-right: 16px;
width: 100%;
}
.image {
position: relative;
width: 90%;

View File

@ -336,180 +336,184 @@ export function Settings({ showLogout }: { showLogout: boolean }) {
<>
{state.profileSet && (
<div className={classes.settings}>
<Text className={classes.header}>{`${state.profile.handle}${state.profile.node ? '/' + state.profile.node : ''}`}</Text>
<div className={classes.image}>
{state.profile.imageSet && (
<div className={classes.imageSet}>
<Image radius="md" src={state.imageUrl} />
<div className={classes.edit}>
<UnstyledButton className={classes.imageEdit} size="compact-md" onClick={imageOpen}>
<span className={classes.editLabel}>{state.strings.edit}</span>
</UnstyledButton>
<div className={classes.header}>
<Text className={classes.headerLabel}>{`${state.profile.handle}${state.profile.node ? '/' + state.profile.node : ''}`}</Text>
</div>
<div className={classes.detail}>
<div className={classes.image}>
{state.profile.imageSet && (
<div className={classes.imageSet}>
<Image radius="md" src={state.imageUrl} />
<div className={classes.edit}>
<UnstyledButton className={classes.imageEdit} size="compact-md" onClick={imageOpen}>
<span className={classes.editLabel}>{state.strings.edit}</span>
</UnstyledButton>
</div>
</div>
</div>
)}
{!state.profile.imageSet && (
<div className={classes.imageUnset} onClick={imageOpen}>
<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>
</div>
{!state.profile.name && <Text className={classes.nameUnset}>{state.strings.name}</Text>}
{state.profile.name && <Text className={classes.nameSet}>{state.profile.name}</Text>}
<div className={classes.entry}>
<div className={classes.entryIcon}>
<IconMapPin />
)}
{!state.profile.imageSet && (
<div className={classes.imageUnset} onClick={imageOpen}>
<Image radius="md" src={state.imageUrl} />
<Text className={classes.unsetEdit}>{state.strings.edit}</Text>
</div>
)}
</div>
{!state.profile.location && <Text className={classes.entryUnset}>{state.strings.location}</Text>}
{state.profile.location && <Text className={classes.entrySet}>{state.profile.location}</Text>}
</div>
<div className={classes.entry}>
<div className={classes.entryIcon}>
<IconBook />
<div className={classes.section}>
<div className={classes.divider} />
<UnstyledButton className={classes.sectionEdit} onClick={detailsOpen}>
{state.strings.edit}
</UnstyledButton>
</div>
{!state.profile.description && <Text className={classes.entryUnset}>{state.strings.description}</Text>}
{state.profile.description && <Text className={classes.entrySet}>{state.profile.description}</Text>}
</div>
<div className={classes.divider} />
<div className={classes.entry}>
<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)} />
</div>
<div className={classes.entry}>
<div className={classes.entryIcon}>
<IconCloudLock />
</div>
<Text className={classes.entryLabel} onClick={setSeal}>
{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)} />
</div>
<div className={classes.divider} />
{showLogout && (
{!state.profile.name && <Text className={classes.nameUnset}>{state.strings.name}</Text>}
{state.profile.name && <Text className={classes.nameSet}>{state.profile.name}</Text>}
<div className={classes.entry}>
<div className={classes.entryIcon}>
<IconLogout />
<IconMapPin />
</div>
<Text className={classes.entryLabel} onClick={logout}>
{state.strings.logout}
{!state.profile.location && <Text className={classes.entryUnset}>{state.strings.location}</Text>}
{state.profile.location && <Text className={classes.entrySet}>{state.profile.location}</Text>}
</div>
<div className={classes.entry}>
<div className={classes.entryIcon}>
<IconBook />
</div>
{!state.profile.description && <Text className={classes.entryUnset}>{state.strings.description}</Text>}
{state.profile.description && <Text className={classes.entrySet}>{state.profile.description}</Text>}
</div>
<div className={classes.divider} />
<div className={classes.entry}>
<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)} />
</div>
<div className={classes.entry}>
<div className={classes.entryIcon}>
<IconCloudLock />
</div>
<Text className={classes.entryLabel} onClick={setSeal}>
{state.strings.manageTopics}
</Text>
</div>
)}
<div className={classes.entry}>
<div className={classes.entryIcon}>
<IconTicket />
</div>
<Text className={classes.entryLabel}>{state.strings.mfaTitle}</Text>
<Switch className={classes.entryControl} checked={state.config.mfaEnabled} onChange={(ev) => setMfa(ev.currentTarget.checked)} />
</div>
<div className={classes.entry}>
<div className={classes.entryIcon}>
<IconLogin />
</div>
<Text className={classes.entryLabel} onClick={changeOpen}>
{state.strings.changeLogin}
</Text>
</div>
<div className={classes.divider} />
<div className={classes.entry}>
<div className={classes.entryIcon}>
<IconUserCancel />
</div>
<Text className={classes.entryLabel}>{state.strings.blockedContacts}</Text>
</div>
<div className={classes.entry}>
<div className={classes.entryIcon}>
<IconFolderCancel />
</div>
<Text className={classes.entryLabel}>{state.strings.blockedTopics}</Text>
</div>
<div className={classes.entry}>
<div className={classes.entryIcon}>
<IconMessage2Cancel />
</div>
<Text className={classes.entryLabel}>{state.strings.blockedMessages}</Text>
</div>
<div className={classes.divider} />
<div className={classes.selects}>
<div className={classes.entry}>
<div className={classes.entryIcon}>
<IconClock />
<IconBell />
</div>
<Text className={classes.controlLabel}>{state.strings.timeFormat}</Text>
<Radio.Group name="timeFormat" className={classes.radio} value={state.timeFormat} onChange={actions.setTimeFormat}>
<Group mt="xs">
<Radio value="12h" label={state.strings.timeUs} />
<Radio value="24h" label={state.strings.timeEu} />
</Group>
</Radio.Group>
<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 && (
<div className={classes.entry}>
<div className={classes.entryIcon}>
<IconLogout />
</div>
<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>
<Switch className={classes.entryControl} checked={state.config.mfaEnabled} onChange={(ev) => setMfa(ev.currentTarget.checked)} />
</div>
<div className={classes.entry}>
<div className={classes.entryIcon}>
<IconCalendar />
<IconLogin />
</div>
<Text className={classes.controlLabel}>{state.strings.dateFormat}</Text>
<Radio.Group name="dateFormat" className={classes.radio} value={state.dateFormat} onChange={actions.setDateFormat}>
<Group mt="xs">
<Radio value="mm/dd" label={state.strings.dateUs} />
<Radio value="dd/mm" label={state.strings.dateEu} />
</Group>
</Radio.Group>
<Text className={classes.entryLabel} onClick={changeOpen}>
{state.strings.changeLogin}
</Text>
</div>
<div className={classes.divider} />
<div className={classes.entry}>
<div className={classes.entryIcon}>
<IconUserCancel />
</div>
<Text className={classes.entryLabel}>{state.strings.blockedContacts}</Text>
</div>
<div className={classes.entry}>
<div className={classes.entryIcon}>
<IconBrightness />
<IconFolderCancel />
</div>
<Text className={classes.controlLabel}>{state.strings.theme}</Text>
<Select className={classes.entryControl} size="xs" data={state.themes} value={state.scheme} onChange={(theme) => actions.setTheme(theme as string)} />
<Text className={classes.entryLabel}>{state.strings.blockedTopics}</Text>
</div>
<div className={classes.entry}>
<div className={classes.entryIcon}>
<IconWorld />
<IconMessage2Cancel />
</div>
<Text className={classes.controlLabel}>{state.strings.language}</Text>
<Select className={classes.entryControl} size="xs" data={state.languages} value={state.language} onChange={(language) => actions.setLanguage(language as string)} />
<Text className={classes.entryLabel}>{state.strings.blockedMessages}</Text>
</div>
<div className={classes.entry}>
<div className={classes.entryIcon}>
<IconMicrophone />
<div className={classes.divider} />
<div className={classes.selects}>
<div className={classes.entry}>
<div className={classes.entryIcon}>
<IconClock />
</div>
<Text className={classes.controlLabel}>{state.strings.timeFormat}</Text>
<Radio.Group name="timeFormat" className={classes.radio} value={state.timeFormat} onChange={actions.setTimeFormat}>
<Group mt="xs">
<Radio value="12h" label={state.strings.timeUs} />
<Radio value="24h" label={state.strings.timeEu} />
</Group>
</Radio.Group>
</div>
<Text className={classes.controlLabel}>{state.strings.microphone}</Text>
<Select
className={classes.entryControl}
size="xs"
data={[{ value: '', label: state.strings.default }, ...state.audioInputs]}
value={state.audioId ? state.audioId : ''}
onChange={actions.setAudio}
/>
</div>
<div className={classes.entry}>
<div className={classes.entryIcon}>
<IconVideo />
<div className={classes.entry}>
<div className={classes.entryIcon}>
<IconCalendar />
</div>
<Text className={classes.controlLabel}>{state.strings.dateFormat}</Text>
<Radio.Group name="dateFormat" className={classes.radio} value={state.dateFormat} onChange={actions.setDateFormat}>
<Group mt="xs">
<Radio value="mm/dd" label={state.strings.dateUs} />
<Radio value="dd/mm" label={state.strings.dateEu} />
</Group>
</Radio.Group>
</div>
<div className={classes.entry}>
<div className={classes.entryIcon}>
<IconBrightness />
</div>
<Text className={classes.controlLabel}>{state.strings.theme}</Text>
<Select className={classes.entryControl} size="xs" data={state.themes} value={state.scheme} onChange={(theme) => actions.setTheme(theme as string)} />
</div>
<div className={classes.entry}>
<div className={classes.entryIcon}>
<IconWorld />
</div>
<Text className={classes.controlLabel}>{state.strings.language}</Text>
<Select className={classes.entryControl} size="xs" data={state.languages} value={state.language} onChange={(language) => actions.setLanguage(language as string)} />
</div>
<div className={classes.entry}>
<div className={classes.entryIcon}>
<IconMicrophone />
</div>
<Text className={classes.controlLabel}>{state.strings.microphone}</Text>
<Select
className={classes.entryControl}
size="xs"
data={[{ value: '', label: state.strings.default }, ...state.audioInputs]}
value={state.audioId ? state.audioId : ''}
onChange={actions.setAudio}
/>
</div>
<div className={classes.entry}>
<div className={classes.entryIcon}>
<IconVideo />
</div>
<Text className={classes.controlLabel}>{state.strings.camera}</Text>
<Select
className={classes.entryControl}
size="xs"
data={[{ value: '', label: state.strings.default }, ...state.videoInputs]}
value={state.videoId ? state.videoId : ''}
onChange={actions.setVideo}
/>
</div>
<Text className={classes.controlLabel}>{state.strings.camera}</Text>
<Select
className={classes.entryControl}
size="xs"
data={[{ value: '', label: state.strings.default }, ...state.videoInputs]}
value={state.videoId ? state.videoId : ''}
onChange={actions.setVideo}
/>
</div>
</div>
</div>