add previous and next buttons (#1096)

This commit is contained in:
Athou
2023-06-24 12:14:44 +02:00
parent 7c226f41db
commit 872247d80f
35 changed files with 215 additions and 20 deletions

View File

@@ -89,6 +89,7 @@ export const Constants = {
mobileBreakpoint: DEFAULT_THEME.breakpoints.md,
headerHeight: 60,
entryMaxWidth: 650,
buttonSpacing: 14,
isTopVisible: (div: HTMLElement) => div.getBoundingClientRect().top >= Constants.layout.headerHeight,
isBottomVisible: (div: HTMLElement) => div.getBoundingClientRect().bottom <= window.innerHeight,
},

View File

@@ -20,7 +20,7 @@ interface ActionButtonProps {
export const ActionButton = forwardRef<HTMLButtonElement, ActionButtonProps>((props: ActionButtonProps, ref) => {
const theme = useMantineTheme()
const variant = props.variant ?? "subtle"
const mobile = useMobile(theme.breakpoints.lg)
const mobile = useMobile(theme.breakpoints.xl)
const iconOnly = (mobile && !props.showLabelOnMobile) || (!mobile && props.hideLabelOnDesktop)
return iconOnly ? (
<Tooltip label={props.label} openDelay={500}>

View File

@@ -1,5 +0,0 @@
import { Group } from "@mantine/core"
export function ButtonToolbar(props: { children: React.ReactNode }) {
return <Group spacing={14}>{props.children}</Group>
}

View File

@@ -1,10 +1,10 @@
import { t, Trans } from "@lingui/macro"
import { Group, Indicator, MultiSelect, Popover } from "@mantine/core"
import { Constants } from "app/constants"
import { markEntriesUpToEntry, markEntry, starEntry, tagEntry } from "app/slices/entries"
import { useAppDispatch, useAppSelector } from "app/store"
import { Entry } from "app/types"
import { ActionButton } from "components/ActionButtton"
import { ButtonToolbar } from "components/ButtonToolbar"
import { useMobile } from "hooks/useMobile"
import { TbArrowBarToDown, TbExternalLink, TbEyeCheck, TbEyeOff, TbShare, TbStar, TbStarOff, TbTag } from "react-icons/tb"
import { ShareButtons } from "./ShareButtons"
@@ -32,7 +32,7 @@ export function FeedEntryFooter(props: FeedEntryFooterProps) {
return (
<Group position="apart">
<ButtonToolbar>
<Group spacing={Constants.layout.buttonSpacing}>
{props.entry.markable && (
<ActionButton
icon={props.entry.read ? <TbEyeOff size={18} /> : <TbEyeCheck size={18} />}
@@ -82,7 +82,7 @@ export function FeedEntryFooter(props: FeedEntryFooterProps) {
<a href={props.entry.url} target="_blank" rel="noreferrer">
<ActionButton icon={<TbExternalLink size={18} />} label={<Trans>Open link</Trans>} />
</a>
</ButtonToolbar>
</Group>
<ActionButton
icon={<TbArrowBarToDown size={18} />}

View File

@@ -1,15 +1,29 @@
import { t, Trans } from "@lingui/macro"
import { ActionIcon, Center, Divider, Indicator, Popover, TextInput } from "@mantine/core"
import { ActionIcon, Box, Center, Divider, Group, Indicator, Popover, TextInput } from "@mantine/core"
import { useForm } from "@mantine/form"
import { reloadEntries, search } from "app/slices/entries"
import { Constants } from "app/constants"
import { reloadEntries, search, selectNextEntry, selectPreviousEntry } from "app/slices/entries"
import { changeReadingMode, changeReadingOrder } from "app/slices/user"
import { useAppDispatch, useAppSelector } from "app/store"
import { ActionButton } from "components/ActionButtton"
import { ButtonToolbar } from "components/ButtonToolbar"
import { Loader } from "components/Loader"
import { useBrowserExtension } from "hooks/useBrowserExtension"
import { useMobile } from "hooks/useMobile"
import { useEffect } from "react"
import { TbArrowDown, TbArrowUp, TbExternalLink, TbEye, TbEyeOff, TbRefresh, TbSearch, TbSettings, TbUser, TbX } from "react-icons/tb"
import {
TbArrowDown,
TbArrowUp,
TbExternalLink,
TbEye,
TbEyeOff,
TbRefresh,
TbSearch,
TbSettings,
TbSortAscending,
TbSortDescending,
TbUser,
TbX,
} from "react-icons/tb"
import { MarkAllAsReadButton } from "./MarkAllAsReadButton"
import { ProfileMenu } from "./ProfileMenu"
@@ -17,6 +31,24 @@ function HeaderDivider() {
return <Divider orientation="vertical" />
}
function HeaderToolbar(props: { children: React.ReactNode }) {
const mobile = useMobile("480px")
return mobile ? (
// on mobile use all available width
<Box
sx={{
width: "100%",
display: "flex",
justifyContent: "space-between",
}}
>
{props.children}
</Box>
) : (
<Group spacing={Constants.layout.buttonSpacing}>{props.children}</Group>
)
}
const iconSize = 18
export function Header() {
@@ -42,7 +74,34 @@ export function Header() {
if (!settings) return <Loader />
return (
<Center>
<ButtonToolbar>
<HeaderToolbar>
<ActionButton
icon={<TbArrowDown size={iconSize} />}
label={<Trans>Next</Trans>}
onClick={() =>
dispatch(
selectNextEntry({
expand: true,
markAsRead: true,
scrollToEntry: true,
})
)
}
/>
<ActionButton
icon={<TbArrowUp size={iconSize} />}
label={<Trans>Previous</Trans>}
onClick={() =>
dispatch(
selectPreviousEntry({
expand: true,
markAsRead: true,
scrollToEntry: true,
})
)
}
/>
<ActionButton
icon={<TbRefresh size={iconSize} />}
label={<Trans>Refresh</Trans>}
@@ -58,7 +117,7 @@ export function Header() {
onClick={() => dispatch(changeReadingMode(settings.readingMode === "all" ? "unread" : "all"))}
/>
<ActionButton
icon={settings.readingOrder === "asc" ? <TbArrowUp size={iconSize} /> : <TbArrowDown size={iconSize} />}
icon={settings.readingOrder === "asc" ? <TbSortAscending size={iconSize} /> : <TbSortDescending size={iconSize} />}
label={settings.readingOrder === "asc" ? <Trans>Asc</Trans> : <Trans>Desc</Trans>}
onClick={() => dispatch(changeReadingOrder(settings.readingOrder === "asc" ? "desc" : "asc"))}
/>
@@ -106,7 +165,7 @@ export function Header() {
/>
</>
)}
</ButtonToolbar>
</HeaderToolbar>
</Center>
)
}

View File

@@ -530,6 +530,7 @@ msgid "Newest first"
msgstr "الأحدث أولاً"
#: src/components/content/add/Subscribe.tsx
#: src/components/header/Header.tsx
msgid "Next"
msgstr "التالي"
@@ -639,6 +640,10 @@ msgstr "كلمات المرور غير متطابقة"
msgid "Position"
msgstr "المنـصب"
#: src/components/header/Header.tsx
msgid "Previous"
msgstr ""
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "الملف الشخصي"

View File

@@ -530,6 +530,7 @@ msgid "Newest first"
msgstr "El més nou primer"
#: src/components/content/add/Subscribe.tsx
#: src/components/header/Header.tsx
msgid "Next"
msgstr "Següent"
@@ -639,6 +640,10 @@ msgstr "Les contrasenyes no coincideixen"
msgid "Position"
msgstr "Posició"
#: src/components/header/Header.tsx
msgid "Previous"
msgstr ""
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Perfil"

View File

@@ -530,6 +530,7 @@ msgid "Newest first"
msgstr "Nejnovější jako první"
#: src/components/content/add/Subscribe.tsx
#: src/components/header/Header.tsx
msgid "Next"
msgstr "Další"
@@ -639,6 +640,10 @@ msgstr "Hesla se neshodují"
msgid "Position"
msgstr "Pozice"
#: src/components/header/Header.tsx
msgid "Previous"
msgstr ""
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Profil"

View File

@@ -530,6 +530,7 @@ msgid "Newest first"
msgstr "Y diweddaraf yn gyntaf"
#: src/components/content/add/Subscribe.tsx
#: src/components/header/Header.tsx
msgid "Next"
msgstr "Nesaf"
@@ -639,6 +640,10 @@ msgstr "Nid yw cyfrineiriau yn cyfateb"
msgid "Position"
msgstr "Swydd"
#: src/components/header/Header.tsx
msgid "Previous"
msgstr ""
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Proffil"

View File

@@ -530,6 +530,7 @@ msgid "Newest first"
msgstr "Nyeste først"
#: src/components/content/add/Subscribe.tsx
#: src/components/header/Header.tsx
msgid "Next"
msgstr "Næste"
@@ -639,6 +640,10 @@ msgstr "Adgangskoder stemmer ikke overens"
msgid "Position"
msgstr ""
#: src/components/header/Header.tsx
msgid "Previous"
msgstr ""
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Profil"

View File

@@ -530,6 +530,7 @@ msgid "Newest first"
msgstr "Neueste zuerst"
#: src/components/content/add/Subscribe.tsx
#: src/components/header/Header.tsx
msgid "Next"
msgstr "Weiter"
@@ -639,6 +640,10 @@ msgstr "Passwörter stimmen nicht überein"
msgid "Position"
msgstr "Stellung"
#: src/components/header/Header.tsx
msgid "Previous"
msgstr ""
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Profil"

View File

@@ -530,6 +530,7 @@ msgid "Newest first"
msgstr "Newest first"
#: src/components/content/add/Subscribe.tsx
#: src/components/header/Header.tsx
msgid "Next"
msgstr "Next"
@@ -639,6 +640,10 @@ msgstr "Passwords do not match"
msgid "Position"
msgstr "Position"
#: src/components/header/Header.tsx
msgid "Previous"
msgstr "Previous"
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Profile"

View File

@@ -530,6 +530,7 @@ msgid "Newest first"
msgstr "más reciente primero"
#: src/components/content/add/Subscribe.tsx
#: src/components/header/Header.tsx
msgid "Next"
msgstr "Siguiente"
@@ -639,6 +640,10 @@ msgstr "Las contraseñas no coinciden"
msgid "Position"
msgstr "Posición"
#: src/components/header/Header.tsx
msgid "Previous"
msgstr ""
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Perfil"

View File

@@ -530,6 +530,7 @@ msgid "Newest first"
msgstr "ابتدا جدیدترین"
#: src/components/content/add/Subscribe.tsx
#: src/components/header/Header.tsx
msgid "Next"
msgstr "بعد"
@@ -639,6 +640,10 @@ msgstr "گذرواژه ها مطابقت ندارند"
msgid "Position"
msgstr "موقعیت"
#: src/components/header/Header.tsx
msgid "Previous"
msgstr ""
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "نمایه"

View File

@@ -530,6 +530,7 @@ msgid "Newest first"
msgstr "Uusin ensin"
#: src/components/content/add/Subscribe.tsx
#: src/components/header/Header.tsx
msgid "Next"
msgstr "Seuraava"
@@ -639,6 +640,10 @@ msgstr "Salasanat eivät täsmää"
msgid "Position"
msgstr "Sijainti"
#: src/components/header/Header.tsx
msgid "Previous"
msgstr ""
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Profiili"

View File

@@ -530,6 +530,7 @@ msgid "Newest first"
msgstr "Plus récent en premier"
#: src/components/content/add/Subscribe.tsx
#: src/components/header/Header.tsx
msgid "Next"
msgstr "Suivant"
@@ -639,6 +640,10 @@ msgstr "Les mots de passe ne correspondent pas"
msgid "Position"
msgstr "Position"
#: src/components/header/Header.tsx
msgid "Previous"
msgstr ""
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Profil"

View File

@@ -530,6 +530,7 @@ msgid "Newest first"
msgstr "o máis novo primeiro"
#: src/components/content/add/Subscribe.tsx
#: src/components/header/Header.tsx
msgid "Next"
msgstr "Seguinte"
@@ -639,6 +640,10 @@ msgstr "Os contrasinais non coinciden"
msgid "Position"
msgstr "Posición"
#: src/components/header/Header.tsx
msgid "Previous"
msgstr ""
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Perfil"

View File

@@ -530,6 +530,7 @@ msgid "Newest first"
msgstr "A legújabbak először"
#: src/components/content/add/Subscribe.tsx
#: src/components/header/Header.tsx
msgid "Next"
msgstr "Következő"
@@ -639,6 +640,10 @@ msgstr "A jelszavak nem egyeznek"
msgid "Position"
msgstr "Pozíció"
#: src/components/header/Header.tsx
msgid "Previous"
msgstr ""
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Profil"

View File

@@ -530,6 +530,7 @@ msgid "Newest first"
msgstr "Terbaru dulu"
#: src/components/content/add/Subscribe.tsx
#: src/components/header/Header.tsx
msgid "Next"
msgstr "Selanjutnya"
@@ -639,6 +640,10 @@ msgstr "Kata sandi tidak cocok"
msgid "Position"
msgstr "Posisi"
#: src/components/header/Header.tsx
msgid "Previous"
msgstr ""
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Profil"

View File

@@ -530,6 +530,7 @@ msgid "Newest first"
msgstr "Il più recente prima"
#: src/components/content/add/Subscribe.tsx
#: src/components/header/Header.tsx
msgid "Next"
msgstr "Avanti"
@@ -639,6 +640,10 @@ msgstr "Le password non corrispondono"
msgid "Position"
msgstr "Posizione"
#: src/components/header/Header.tsx
msgid "Previous"
msgstr ""
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Profilo"

View File

@@ -530,6 +530,7 @@ msgid "Newest first"
msgstr "最新順"
#: src/components/content/add/Subscribe.tsx
#: src/components/header/Header.tsx
msgid "Next"
msgstr "次へ"
@@ -639,6 +640,10 @@ msgstr "パスワードが一致しません"
msgid "Position"
msgstr "位置"
#: src/components/header/Header.tsx
msgid "Previous"
msgstr ""
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "プロフィール"

View File

@@ -530,6 +530,7 @@ msgid "Newest first"
msgstr "최신순"
#: src/components/content/add/Subscribe.tsx
#: src/components/header/Header.tsx
msgid "Next"
msgstr "다음"
@@ -639,6 +640,10 @@ msgstr "비밀번호가 일치하지 않습니다"
msgid "Position"
msgstr "위치"
#: src/components/header/Header.tsx
msgid "Previous"
msgstr ""
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "프로필"

View File

@@ -530,6 +530,7 @@ msgid "Newest first"
msgstr "Terbaharu dahulu"
#: src/components/content/add/Subscribe.tsx
#: src/components/header/Header.tsx
msgid "Next"
msgstr "Seterusnya"
@@ -639,6 +640,10 @@ msgstr "Kata laluan tidak sepadan"
msgid "Position"
msgstr "Kedudukan"
#: src/components/header/Header.tsx
msgid "Previous"
msgstr ""
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Profil"

View File

@@ -530,6 +530,7 @@ msgid "Newest first"
msgstr "Nyeste først"
#: src/components/content/add/Subscribe.tsx
#: src/components/header/Header.tsx
msgid "Next"
msgstr "Neste"
@@ -639,6 +640,10 @@ msgstr "Passordene samsvarer ikke"
msgid "Position"
msgstr "Posisjon"
#: src/components/header/Header.tsx
msgid "Previous"
msgstr ""
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Profil"

View File

@@ -530,6 +530,7 @@ msgid "Newest first"
msgstr "Nieuwste eerst"
#: src/components/content/add/Subscribe.tsx
#: src/components/header/Header.tsx
msgid "Next"
msgstr "Volgende"
@@ -639,6 +640,10 @@ msgstr "Wachtwoorden komen niet overeen"
msgid "Position"
msgstr "Positie"
#: src/components/header/Header.tsx
msgid "Previous"
msgstr ""
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Profiel"

View File

@@ -530,6 +530,7 @@ msgid "Newest first"
msgstr "Nyeste først"
#: src/components/content/add/Subscribe.tsx
#: src/components/header/Header.tsx
msgid "Next"
msgstr "Neste"
@@ -639,6 +640,10 @@ msgstr "Passordene samsvarer ikke"
msgid "Position"
msgstr "Posisjon"
#: src/components/header/Header.tsx
msgid "Previous"
msgstr ""
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Profil"

View File

@@ -530,6 +530,7 @@ msgid "Newest first"
msgstr "Najnowsze jako pierwsze"
#: src/components/content/add/Subscribe.tsx
#: src/components/header/Header.tsx
msgid "Next"
msgstr "Dalej"
@@ -639,6 +640,10 @@ msgstr "Hasła nie pasują"
msgid "Position"
msgstr "Pozycja"
#: src/components/header/Header.tsx
msgid "Previous"
msgstr ""
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Profil"

View File

@@ -530,6 +530,7 @@ msgid "Newest first"
msgstr "Mais novo primeiro"
#: src/components/content/add/Subscribe.tsx
#: src/components/header/Header.tsx
msgid "Next"
msgstr "Próximo"
@@ -639,6 +640,10 @@ msgstr "Senhas não coincidem"
msgid "Position"
msgstr "Posição"
#: src/components/header/Header.tsx
msgid "Previous"
msgstr ""
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Perfil"

View File

@@ -530,6 +530,7 @@ msgid "Newest first"
msgstr "Сначала новые"
#: src/components/content/add/Subscribe.tsx
#: src/components/header/Header.tsx
msgid "Next"
msgstr "Далее"
@@ -639,6 +640,10 @@ msgstr "Пароли не совпадают"
msgid "Position"
msgstr "Позиция"
#: src/components/header/Header.tsx
msgid "Previous"
msgstr ""
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Профиль"

View File

@@ -530,6 +530,7 @@ msgid "Newest first"
msgstr "Najnovšie ako prvé"
#: src/components/content/add/Subscribe.tsx
#: src/components/header/Header.tsx
msgid "Next"
msgstr "Ďalej"
@@ -639,6 +640,10 @@ msgstr "Heslá sa nezhodujú"
msgid "Position"
msgstr "Pozícia"
#: src/components/header/Header.tsx
msgid "Previous"
msgstr ""
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Profil"

View File

@@ -530,6 +530,7 @@ msgid "Newest first"
msgstr "Nyast först"
#: src/components/content/add/Subscribe.tsx
#: src/components/header/Header.tsx
msgid "Next"
msgstr "Nästa"
@@ -639,6 +640,10 @@ msgstr "Lösenorden matchar inte"
msgid "Position"
msgstr ""
#: src/components/header/Header.tsx
msgid "Previous"
msgstr ""
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Profil"

View File

@@ -530,6 +530,7 @@ msgid "Newest first"
msgstr "Önce en yenisi"
#: src/components/content/add/Subscribe.tsx
#: src/components/header/Header.tsx
msgid "Next"
msgstr "Sonraki"
@@ -639,6 +640,10 @@ msgstr "Parolalar eşleşmiyor"
msgid "Position"
msgstr "Konum"
#: src/components/header/Header.tsx
msgid "Previous"
msgstr ""
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Profil"

View File

@@ -530,6 +530,7 @@ msgid "Newest first"
msgstr "最新优先"
#: src/components/content/add/Subscribe.tsx
#: src/components/header/Header.tsx
msgid "Next"
msgstr "下一个"
@@ -639,6 +640,10 @@ msgstr "密码不匹配"
msgid "Position"
msgstr "位置"
#: src/components/header/Header.tsx
msgid "Previous"
msgstr ""
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "配置文件"

View File

@@ -1,12 +1,12 @@
import { Trans } from "@lingui/macro"
import { Anchor, Box, Center, Container, Divider, Group, Image, Title, useMantineColorScheme } from "@mantine/core"
import { client } from "app/client"
import { Constants } from "app/constants"
import { redirectToApiDocumentation, redirectToLogin, redirectToRegistration, redirectToRootCategory } from "app/slices/redirect"
import { useAppDispatch, useAppSelector } from "app/store"
import welcome_page_dark from "assets/welcome_page_dark.png"
import welcome_page_light from "assets/welcome_page_light.png"
import { ActionButton } from "components/ActionButtton"
import { ButtonToolbar } from "components/ButtonToolbar"
import { useBrowserExtension } from "hooks/useBrowserExtension"
import { useMobile } from "hooks/useMobile"
import { useAsyncCallback } from "react-async-hook"
@@ -73,7 +73,7 @@ function Buttons() {
})
return (
<ButtonToolbar>
<Group spacing={Constants.layout.buttonSpacing}>
{serverInfos?.demoAccountEnabled && (
<ActionButton
label={<Trans>Try the demo!</Trans>}
@@ -115,7 +115,7 @@ function Buttons() {
hideLabelOnDesktop
/>
)}
</ButtonToolbar>
</Group>
)
}

View File

@@ -178,7 +178,7 @@ export default function Layout(props: LayoutProps) {
)}
{!mobileMenuOpen && (
<Group>
<Box mr="sm">{burger}</Box>
<Box>{burger}</Box>
<Box sx={{ flexGrow: 1 }}>{props.header}</Box>
</Group>
)}