Files
omnivore/packages/web/components/templates/NavigationLayout.tsx
Tom Rogers 4e582fb55d Improving Self-Hosting and Removing 3rd Party dependencies. (#4513)
* fix: Library Header layout shift

* Bump Github Actions versions.

* Self-Hosting Changes

* Fix Minio Environment Variable

* Just make pdfs successful, due to lack of PDFHandler

* Fix issue where flag was set wrong

* Added an NGINX Example file

* Add some documentation for self-hosting via Docker Compose

* Make some adjustments to Puppeteer due to failing sites.

* adjust timings

* Add start of Mail Service

* Fix Docker Files

* More email service stuff

* Add Guide to use Zapier for Email-Importing.

* Ensure that if no env is provided it uses the old email settings

* Add some instructions for self-hosted email

* Add SNS Endpoints for Mail Watcher

* Add steps and functionality for using SES and SNS for email

* Uncomment a few jobs.

* Added option for Firefox for parser. Was having issues with Chromium on Docker.

* Add missing space.

Co-authored-by: Russ Taylor <729694+russtaylor@users.noreply.github.com>

* Fix some wording on the Guide

* update browser extension to handle self-hosted instances

* add slight documentation to options page

* Fix MV

* Do raw handlers for Medium

* Fix images in Medium

* Update self-hosting/GUIDE.md

Co-authored-by: Mike Baker <1426795+mbaker3@users.noreply.github.com>

* Update Guide with other variables

* Add The Verge to JS-less handlers

* Update regex and image-proxy

* Update self-hosting/nginx/nginx.conf

Co-authored-by: Mike Baker <1426795+mbaker3@users.noreply.github.com>

* Update regex and image-proxy

* Update self-hosting/docker-compose/docker-compose.yml

Co-authored-by: Mike Baker <1426795+mbaker3@users.noreply.github.com>

* Fix Minio for Export

* Merge to main

* Update GUIDE with newer NGINX

* Update nginx config to include api/save route

* Enable Native PDF View for PDFS

* Enable Native PDF View for PDFS

* feat:lover packages test

* feat:working build

* feat:alpine build

* docs:api dockerfile docs

* Write a PDF.js wrapper to replace pspdfkit

* Revert changes for replication, set settings to have default mode

* build folder got removed due to gitignore on pdf

* Add Box shadow to pdf pages

* Add Toggle for Progress in PDFS, enabled native viewer toggle

* Update node version to LTS

* Update node version to LTS

* Fix Linting issues

* Fix Linting issues

* Make env variable nullable

* Add touchend listener for mobile

* Make changes to PDF for mobile

* fix(android): change serverUrl to selfhosted first

* feat:2 stage alpine content fetch

* feat:separated start script

* fix:changed to node 22

* Add back youtube functionality and add guide

* trigger build

* Fix cache issue on YouTube

* Allow empty AWS_S3_ENDPOINT

* Allow empty AWS_S3_ENDPOINT

* Add GCHR for all images

* Add GCHR For self hosting.

* Add GCHR For self hosting.

* Test prebuilt.

* Test prebuilt

* Test prebuilt...

* Fix web image

* Remove Web Image (For now)

* Move docker-compose to images

* Move docker-compose files to correct locations

* Remove the need for ARGS

* Update packages, and Typescript versions

* Fix

* Fix issues with build on Web

* Correct push

* Fix Linting issues

* Fix Trace import

* Add missing types

* Fix Tasks

* Add information into guide about self-build

* Fix issues with PDF Viewer

---------

Co-authored-by: keumky2 <keumky2@woowahan.com>
Co-authored-by: William Theaker <wtheaker@nvidia.com>
Co-authored-by: Russ Taylor <729694+russtaylor@users.noreply.github.com>
Co-authored-by: David Adams <david@dadams2.com>
Co-authored-by: Mike Baker <1426795+mbaker3@users.noreply.github.com>
Co-authored-by: m1xxos <66390094+m1xxos@users.noreply.github.com>
Co-authored-by: Adil <mr.adil777@gmail.com>
2025-01-27 13:33:16 +01:00

220 lines
6.2 KiB
TypeScript

import { PageMetaData, PageMetaDataProps } from '../patterns/PageMetaData'
import { HStack, SpanBox, VStack } from '../elements/LayoutPrimitives'
import { ReactNode, useEffect, useState, useCallback } from 'react'
import { navigationCommands } from '../../lib/keyboardShortcuts/navigationShortcuts'
import { useKeyboardShortcuts } from '../../lib/keyboardShortcuts/useKeyboardShortcuts'
import { useRouter } from 'next/router'
import { ConfirmationModal } from '../patterns/ConfirmationModal'
import { KeyboardShortcutListModal } from './KeyboardShortcutListModal'
import { setupAnalytics } from '../../lib/analytics'
import { primaryCommands } from '../../lib/keyboardShortcuts/navigationShortcuts'
import { useLogout } from '../../lib/logout'
import { useApplyLocalTheme } from '../../lib/hooks/useApplyLocalTheme'
import { useRegisterActions } from 'kbar'
import { theme } from '../tokens/stitches.config'
import { NavigationMenu } from './navMenu/NavigationMenu'
import { Button } from '../elements/Button'
import { List } from '@phosphor-icons/react'
import { LIBRARY_LEFT_MENU_WIDTH } from './navMenu/LibraryLegacyMenu'
import { AddLinkModal } from './AddLinkModal'
import useWindowDimensions from '../../lib/hooks/useGetWindowDimensions'
import { useHandleAddUrl } from '../../lib/hooks/useHandleAddUrl'
import { useGetViewer } from '../../lib/networking/viewer/useGetViewer'
import { useQueryClient } from '@tanstack/react-query'
export type NavigationSection =
| 'home'
| 'library'
| 'subscriptions'
| 'highlights'
| 'archive'
| 'trash'
type NavigationLayoutProps = {
children: ReactNode
rightPane?: ReactNode
title: string
section: NavigationSection
pageMetaDataProps?: PageMetaDataProps
showNavigationMenu: boolean
setShowNavigationMenu: (show: boolean) => void
}
export function NavigationLayout(props: NavigationLayoutProps): JSX.Element {
useApplyLocalTheme()
const router = useRouter()
const queryClient = useQueryClient()
const [showLogoutConfirmation, setShowLogoutConfirmation] = useState(false)
const [showKeyboardCommandsModal, setShowKeyboardCommandsModal] =
useState(false)
const {
data: viewerData,
isFetching,
isPending,
isError,
status,
} = useGetViewer()
useRegisterActions(navigationCommands(router))
useKeyboardShortcuts(
primaryCommands((action) => {
switch (action) {
case 'toggleShortcutHelpModalDisplay':
setShowKeyboardCommandsModal(true)
break
}
})
)
// Attempt to identify the user if they are logged in.
useEffect(() => {
if (viewerData) {
setupAnalytics(viewerData)
}
if (!viewerData && !isPending) {
console.log('viewerData: ', viewerData, isFetching, isPending, status)
// there was an error loading, so lets log out
queryClient.clear()
router.push(`/login`)
}
}, [viewerData])
const showLogout = useCallback(() => {
setShowLogoutConfirmation(true)
}, [setShowLogoutConfirmation])
const { width, previous } = useWindowDimensions()
useEffect(() => {
if (width < previous.width && width <= 768) {
props.setShowNavigationMenu(false)
}
}, [width, previous])
const [showAddLinkModal, setShowAddLinkModal] = useState(false)
const handleLinkAdded = useHandleAddUrl()
useEffect(() => {
document.addEventListener('logout', showLogout)
return () => {
document.removeEventListener('logout', showLogout)
}
}, [showLogout])
const { logout } = useLogout()
return (
<HStack
css={{ width: '100vw', height: '100vh' }}
distribution="start"
alignment="start"
>
<PageMetaData path={props.section} title={props.title} />
<Header
menuOpen={props.showNavigationMenu}
toggleMenu={() => {
props.setShowNavigationMenu(!props.showNavigationMenu)
}}
/>
{props.showNavigationMenu && (
<>
<NavigationMenu
section={props.section}
setShowAddLinkModal={setShowAddLinkModal}
showMenu={props.showNavigationMenu}
setShowMenu={props.setShowNavigationMenu}
/>
<SpanBox
css={{
width: LIBRARY_LEFT_MENU_WIDTH,
flexShrink: '0',
'@mdDown': {
display: 'none',
},
}}
></SpanBox>
<SpanBox
css={{
display: 'none',
position: 'fixed',
zIndex: '2',
backgroundColor: 'var(--colors-overlay)',
'@mdDown': {
display: 'flex',
top: '0px',
left: '0px',
width: '100vw',
height: '100vh',
pointerEvents: 'auto',
},
}}
onClick={(event) => {
props.setShowNavigationMenu(false)
event.stopPropagation()
}}
></SpanBox>
</>
)}
{props.children}
{showLogoutConfirmation && (
<ConfirmationModal
message={'Are you sure you want to log out?'}
onAccept={logout}
onOpenChange={() => setShowLogoutConfirmation(false)}
/>
)}
{showKeyboardCommandsModal && (
<KeyboardShortcutListModal
onOpenChange={() => setShowKeyboardCommandsModal(false)}
/>
)}
{showAddLinkModal && (
<AddLinkModal
onOpenChange={setShowAddLinkModal}
handleLinkSubmission={handleLinkAdded}
/>
)}
</HStack>
)
}
type HeaderProps = {
menuOpen: boolean
toggleMenu: () => void
}
const Header = (props: HeaderProps): JSX.Element => {
return (
<VStack
alignment="start"
distribution="center"
css={{
zIndex: 10,
position: props.menuOpen ? 'fixed' : 'absolute',
left: '0px',
top: '0px',
pl: '20px',
pt: '20px',
height: '58px',
}}
>
<Button
style="plainIcon"
onClick={(event) => {
props.toggleMenu()
event.preventDefault()
}}
css={{ height: 'unset', display: 'flex' }}
>
<List size="25" color={theme.colors.readerTextSubtle.toString()} />
</Button>
</VStack>
)
}