update header on desktop+mobile

This commit is contained in:
Samuel Newman
2026-05-11 15:04:14 +03:00
parent 65bf37ef5a
commit 5ea12b6adb
4 changed files with 108 additions and 48 deletions
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#000" d="M19 14h-2.417a5 5 0 0 1-9.166 0H5v4a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-4Zm0-8a1 1 0 0 0-.898-.995L18 5H6a1 1 0 0 0-1 1v6h3.126a1 1 0 0 1 .969.751 3.001 3.001 0 0 0 5.81 0l.056-.16a1 1 0 0 1 .913-.591H19V6Zm2 12a3 3 0 0 1-3 3H6a3 3 0 0 1-3-3V6a3 3 0 0 1 3-3h12l.154.004A3 3 0 0 1 21 6v12Z"/></svg>

After

Width:  |  Height:  |  Size: 387 B

+5
View File
@@ -0,0 +1,5 @@
import {createSinglePathSVG} from './TEMPLATE'
export const Inbox_Stroke2_Corner2_Rounded = createSinglePathSVG({
path: 'M19 14h-2.417a5 5 0 0 1-9.166 0H5v4a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-4Zm0-8a1 1 0 0 0-.898-.995L18 5H6a1 1 0 0 0-1 1v6h3.126a1 1 0 0 1 .969.751 3.001 3.001 0 0 0 5.81 0l.056-.16a1 1 0 0 1 .913-.591H19V6Zm2 12a3 3 0 0 1-3 3H6a3 3 0 0 1-3-3V6a3 3 0 0 1 3-3h12l.154.004A3 3 0 0 1 21 6v12Z',
})
+44 -35
View File
@@ -29,8 +29,10 @@ import {NewChat} from '#/components/dms/dialogs/NewChatDialog'
import {useRefreshOnFocus} from '#/components/hooks/useRefreshOnFocus' import {useRefreshOnFocus} from '#/components/hooks/useRefreshOnFocus'
import {ArrowRotateCounterClockwise_Stroke2_Corner0_Rounded as RetryIcon} from '#/components/icons/ArrowRotate' import {ArrowRotateCounterClockwise_Stroke2_Corner0_Rounded as RetryIcon} from '#/components/icons/ArrowRotate'
import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfoIcon} from '#/components/icons/CircleInfo' import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfoIcon} from '#/components/icons/CircleInfo'
import {Message_Stroke2_Corner0_Rounded as MessageIcon} from '#/components/icons/Message' import {
import {PlusLarge_Stroke2_Corner0_Rounded as PlusIcon} from '#/components/icons/Plus' Message_Stroke2_Corner0_Rounded as MessageIcon,
MessagePlus_Stroke2_Corner0_Rounded as NewChatIcon,
} from '#/components/icons/Message'
import {SettingsGear2_Stroke2_Corner0_Rounded as SettingsIcon} from '#/components/icons/SettingsGear2' import {SettingsGear2_Stroke2_Corner0_Rounded as SettingsIcon} from '#/components/icons/SettingsGear2'
import * as Layout from '#/components/Layout' import * as Layout from '#/components/Layout'
import {Link} from '#/components/Link' import {Link} from '#/components/Link'
@@ -346,12 +348,14 @@ export function Header({newChatControl}: {newChatControl: DialogControlProps}) {
const requireEmailVerification = useRequireEmailVerification() const requireEmailVerification = useRequireEmailVerification()
const leftConvos = useLeftConvos() const leftConvos = useLeftConvos()
const {data: inboxData, hasNextPage: hasMoreRequests} = useListConvosQuery({ const {data: unreadInboxData, hasNextPage: hasMoreRequests} =
status: 'request', useListConvosQuery({
}) status: 'request',
readState: 'unread',
})
const inboxAllConvos = const inboxAllConvos =
inboxData?.pages unreadInboxData?.pages
.flatMap(page => page.convos) .flatMap(page => page.convos)
.filter( .filter(
convo => convo =>
@@ -371,48 +375,38 @@ export function Header({newChatControl}: {newChatControl: DialogControlProps}) {
], ],
}) })
const requestsLink = (
<InboxRequests
count={inboxAllConvos.length}
more={hasMoreRequests ?? false}
/>
)
const settingsLink = (
<Link
to="/messages/settings"
label={l`Chat settings`}
size="small"
variant="ghost"
color="secondary"
shape="round"
style={[a.justify_center]}>
<ButtonIcon icon={SettingsIcon} size="lg" />
</Link>
)
return ( return (
<Layout.Header.Outer> <Layout.Header.Outer>
{gtMobile ? ( {gtMobile ? (
<> <>
<Layout.Header.Content> <Layout.Header.Content align="left">
<Layout.Header.TitleText> <Layout.Header.TitleText>
<Trans>Chats</Trans> <Trans>Chats</Trans>
</Layout.Header.TitleText> </Layout.Header.TitleText>
</Layout.Header.Content> </Layout.Header.Content>
<View style={[a.flex_row, a.align_center, a.gap_sm]}> <View style={[a.flex_row, a.align_center, a.gap_sm]}>
{requestsLink} <InboxRequests
{settingsLink} count={inboxAllConvos.length}
more={hasMoreRequests}
variant="solid"
/>
<Link
to="/messages/settings"
label={l`Chat settings`}
size="small"
color="secondary"
shape="round"
style={[a.justify_center]}>
<ButtonIcon icon={SettingsIcon} />
</Link>
<Button <Button
label={l`New chat`} label={l`New chat`}
color="primary" color="primary"
size="small" size="small"
shape="round"
onPress={wrappedOpenChatControl}> onPress={wrappedOpenChatControl}>
<ButtonIcon icon={PlusIcon} /> <ButtonIcon icon={NewChatIcon} />
<ButtonText>
<Trans>New chat</Trans>
</ButtonText>
</Button> </Button>
</View> </View>
</> </>
@@ -424,8 +418,23 @@ export function Header({newChatControl}: {newChatControl: DialogControlProps}) {
<Trans>Chats</Trans> <Trans>Chats</Trans>
</Layout.Header.TitleText> </Layout.Header.TitleText>
</Layout.Header.Content> </Layout.Header.Content>
{requestsLink} <InboxRequests
<Layout.Header.Slot>{settingsLink}</Layout.Header.Slot> count={inboxAllConvos.length}
more={hasMoreRequests}
variant="ghost"
/>
<Layout.Header.Slot>
<Link
to="/messages/settings"
label={l`Chat settings`}
size="small"
variant="ghost"
color="secondary"
shape="round"
style={[a.justify_center]}>
<ButtonIcon icon={SettingsIcon} size="lg" />
</Link>
</Layout.Header.Slot>
</> </>
)} )}
</Layout.Header.Outer> </Layout.Header.Outer>
@@ -3,15 +3,29 @@ import {useLingui} from '@lingui/react/macro'
import {UNREAD_LIMIT} from '#/state/queries/messages/list-conversations' import {UNREAD_LIMIT} from '#/state/queries/messages/list-conversations'
import {atoms as a} from '#/alf' import {atoms as a} from '#/alf'
import {InlineLinkText} from '#/components/Link' import {ButtonIcon, ButtonText} from '#/components/Button'
import {Inbox_Stroke2_Corner2_Rounded as InboxIcon} from '#/components/icons/Inbox'
import {Link} from '#/components/Link'
export function InboxRequests({count, more}: {count: number; more: boolean}) { export function InboxRequests({
count,
more,
variant,
}: {
count: number
more: boolean
variant?: 'ghost' | 'solid'
}) {
const {t: l} = useLingui() const {t: l} = useLingui()
if (count < 1) return null const unread = count > 0
const label = const label = !unread
count >= UNREAD_LIMIT && more ? l({
message: `Requests`,
comment: 'Incoming message requests',
})
: count >= UNREAD_LIMIT && more
? l({ ? l({
message: `${count}+ requests`, message: `${count}+ requests`,
comment: 'Displayed when the number of requests is greater than 20', comment: 'Displayed when the number of requests is greater than 20',
@@ -21,12 +35,43 @@ export function InboxRequests({count, more}: {count: number; more: boolean}) {
other: '# requests', other: '# requests',
}) })
return ( switch (variant) {
<InlineLinkText case 'ghost': {
label={label} return (
to="/messages/inbox" <Link
style={[a.text_md, a.font_medium]}> label={label}
{label} to="/messages/inbox"
</InlineLinkText> size="small"
) variant={unread ? 'solid' : 'ghost'}
color={unread ? 'primary_subtle' : 'secondary'}
shape={unread ? 'default' : 'round'}
style={[a.justify_center, unread && [a.gap_sm, a.pl_lg, a.pr_md]]}>
<ButtonIcon icon={InboxIcon} size="lg" />
{unread && (
<ButtonText style={[a.text_md, a.font_bold]}>
{count >= UNREAD_LIMIT && more
? l({
message: `${count}+`,
comment:
'Displayed when the number of requests is greater than 20',
})
: count}
</ButtonText>
)}
</Link>
)
}
case 'solid': {
return (
<Link
label={label}
to="/messages/inbox"
color={unread ? 'primary_subtle' : 'secondary'}
size="small">
<ButtonIcon icon={InboxIcon} />
<ButtonText>{label}</ButtonText>
</Link>
)
}
}
} }