fix: ipad web view ui improvements (#1664)
This commit is contained in:
@@ -41,6 +41,13 @@ const getKey = () => {
|
||||
return keyCount++
|
||||
}
|
||||
|
||||
const setViewportHeight = () => {
|
||||
document.documentElement.style.setProperty(
|
||||
'--viewport-height',
|
||||
`${visualViewport ? visualViewport.height : window.innerHeight}px`,
|
||||
)
|
||||
}
|
||||
|
||||
const startApplication: StartApplication = async function startApplication(
|
||||
defaultSyncServerHost: string,
|
||||
device: WebOrDesktopDevice,
|
||||
@@ -53,6 +60,7 @@ const startApplication: StartApplication = async function startApplication(
|
||||
let root: Root
|
||||
|
||||
const onDestroy = () => {
|
||||
window.removeEventListener('orientationchange', setViewportHeight)
|
||||
const rootElement = document.getElementById(ElementIds.RootId) as HTMLElement
|
||||
root.unmount()
|
||||
rootElement.remove()
|
||||
@@ -66,10 +74,8 @@ const startApplication: StartApplication = async function startApplication(
|
||||
root = createRoot(appendedRootNode)
|
||||
|
||||
disableIosTextFieldZoom()
|
||||
document.documentElement.style.setProperty(
|
||||
'--viewport-height',
|
||||
`${visualViewport ? visualViewport.height : window.innerHeight}px`,
|
||||
)
|
||||
setViewportHeight()
|
||||
window.addEventListener('orientationchange', setViewportHeight)
|
||||
|
||||
root.render(
|
||||
<ApplicationGroupView
|
||||
|
||||
@@ -69,7 +69,7 @@ const ContentList: FunctionComponent<Props> = ({
|
||||
<div
|
||||
className={classNames(
|
||||
'infinite-scroll overflow-y-auto overflow-x-hidden focus:shadow-none focus:outline-none',
|
||||
'md:max-h-full md:overflow-y-hidden md:hover:overflow-y-auto',
|
||||
'md:max-h-full md:overflow-y-hidden md:hover:overflow-y-auto pointer-coarse:md:overflow-y-auto',
|
||||
'md:hover:[overflow-y:_overlay]',
|
||||
)}
|
||||
id={ElementIds.ContentList}
|
||||
|
||||
@@ -24,6 +24,7 @@ import { StreamingFileReader } from '@standardnotes/filepicker'
|
||||
import SearchBar from '../SearchBar/SearchBar'
|
||||
import { SearchOptionsController } from '@/Controllers/SearchOptionsController'
|
||||
import { classNames } from '@/Utils/ConcatenateClassNames'
|
||||
import { MediaQueryBreakpoints, useMediaQuery } from '@/Hooks/useMediaQuery'
|
||||
|
||||
type Props = {
|
||||
accountMenuController: AccountMenuController
|
||||
@@ -50,7 +51,7 @@ const ContentListView: FunctionComponent<Props> = ({
|
||||
selectionController,
|
||||
searchOptionsController,
|
||||
}) => {
|
||||
const { toggleAppPane } = useResponsiveAppPane()
|
||||
const { isNotesListVisibleOnTablets, toggleAppPane } = useResponsiveAppPane()
|
||||
|
||||
const fileInputRef = useRef<HTMLInputElement>(null)
|
||||
const itemsViewPanelRef = useRef<HTMLDivElement>(null)
|
||||
@@ -181,12 +182,19 @@ const ContentListView: FunctionComponent<Props> = ({
|
||||
[isFilesSmartView],
|
||||
)
|
||||
|
||||
const matchesMediumBreakpoint = useMediaQuery(MediaQueryBreakpoints.md)
|
||||
const matchesXLBreakpoint = useMediaQuery(MediaQueryBreakpoints.xl)
|
||||
const isTabletScreenSize = matchesMediumBreakpoint && !matchesXLBreakpoint
|
||||
|
||||
return (
|
||||
<div
|
||||
id="items-column"
|
||||
className={classNames(
|
||||
'sn-component section app-column flex h-screen flex-col pt-safe-top md:h-full',
|
||||
'xl:w-87.5 xsm-only:!w-full sm-only:!w-full pointer-coarse:md-only:!w-52 pointer-coarse:lg-only:!w-52',
|
||||
'xl:w-87.5 xsm-only:!w-full sm-only:!w-full',
|
||||
isTabletScreenSize && !isNotesListVisibleOnTablets
|
||||
? 'pointer-coarse:md-only:!w-0 pointer-coarse:lg-only:!w-0'
|
||||
: 'pointer-coarse:md-only:!w-60 pointer-coarse:lg-only:!w-60',
|
||||
)}
|
||||
aria-label={'Notes & Files'}
|
||||
ref={itemsViewPanelRef}
|
||||
|
||||
@@ -22,7 +22,7 @@ const Navigation: FunctionComponent<Props> = ({ application }) => {
|
||||
const viewControllerManager = useMemo(() => application.getViewControllerManager(), [application])
|
||||
const ref = useRef<HTMLDivElement>(null)
|
||||
const [panelWidth, setPanelWidth] = useState<number>(0)
|
||||
const { toggleAppPane } = useResponsiveAppPane()
|
||||
const { selectedPane, toggleAppPane } = useResponsiveAppPane()
|
||||
|
||||
const [hasPasscode, setHasPasscode] = useState(() => application.hasPasscode())
|
||||
useEffect(() => {
|
||||
@@ -63,7 +63,11 @@ const Navigation: FunctionComponent<Props> = ({ application }) => {
|
||||
<div
|
||||
id="navigation"
|
||||
className={classNames(
|
||||
'sn-component section app-column h-screen max-h-screen w-[220px] overflow-hidden pt-safe-top md:h-full md:max-h-full md:min-h-0 md:py-0 xsm-only:!w-full sm-only:!w-full',
|
||||
'sn-component section app-column h-screen max-h-screen overflow-hidden pt-safe-top md:h-full md:max-h-full md:min-h-0 md:pb-0',
|
||||
'w-[220px] xl:w-87.5 xsm-only:!w-full sm-only:!w-full',
|
||||
selectedPane === AppPaneId.Navigation
|
||||
? 'pointer-coarse:md-only:!w-48 pointer-coarse:lg-only:!w-48'
|
||||
: 'pointer-coarse:md-only:!w-0 pointer-coarse:lg-only:!w-0',
|
||||
isIOS() ? 'pb-safe-bottom' : 'pb-2.5',
|
||||
)}
|
||||
ref={ref}
|
||||
@@ -71,7 +75,7 @@ const Navigation: FunctionComponent<Props> = ({ application }) => {
|
||||
<ResponsivePaneContent paneId={AppPaneId.Navigation} contentElementId="navigation-content">
|
||||
<div
|
||||
className={classNames(
|
||||
'flex-grow overflow-y-auto overflow-x-hidden md:overflow-y-hidden md:hover:overflow-y-auto',
|
||||
'flex-grow overflow-y-auto overflow-x-hidden md:overflow-y-hidden md:hover:overflow-y-auto pointer-coarse:md:overflow-y-auto',
|
||||
'md:hover:[overflow-y:_overlay]',
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -3,13 +3,17 @@ import { AppPaneId } from '../ResponsivePane/AppPaneMetadata'
|
||||
import { useResponsiveAppPane } from '../ResponsivePane/ResponsivePaneProvider'
|
||||
|
||||
export const NavigationMenuButton = () => {
|
||||
const { toggleAppPane } = useResponsiveAppPane()
|
||||
const { selectedPane, toggleAppPane } = useResponsiveAppPane()
|
||||
|
||||
return (
|
||||
<button
|
||||
className="bg-text-padding mr-3 inline-flex h-8 min-w-8 cursor-pointer items-center justify-center rounded-full border border-solid border-border align-middle text-neutral hover:bg-contrast focus:bg-contrast md:hidden"
|
||||
className="bg-text-padding mr-3 inline-flex h-8 min-w-8 cursor-pointer items-center justify-center rounded-full border border-solid border-border align-middle text-neutral hover:bg-contrast focus:bg-contrast md:hidden pointer-coarse:md-only:inline-flex pointer-coarse:lg-only:inline-flex"
|
||||
onClick={() => {
|
||||
toggleAppPane(AppPaneId.Navigation)
|
||||
if (selectedPane === AppPaneId.Items || selectedPane === AppPaneId.Editor) {
|
||||
toggleAppPane(AppPaneId.Navigation)
|
||||
} else {
|
||||
toggleAppPane(AppPaneId.Items)
|
||||
}
|
||||
}}
|
||||
title="Navigation menu"
|
||||
aria-label="Navigation menu"
|
||||
|
||||
@@ -1,20 +1,36 @@
|
||||
import { AppPaneId } from '../ResponsivePane/AppPaneMetadata'
|
||||
import Icon from '../Icon/Icon'
|
||||
import { useResponsiveAppPane } from '../ResponsivePane/ResponsivePaneProvider'
|
||||
import { useMediaQuery, MediaQueryBreakpoints } from '@/Hooks/useMediaQuery'
|
||||
import { IconType } from '@standardnotes/snjs'
|
||||
|
||||
const MobileItemsListButton = () => {
|
||||
const { toggleAppPane } = useResponsiveAppPane()
|
||||
const { toggleAppPane, isNotesListVisibleOnTablets, toggleNotesListOnTablets } = useResponsiveAppPane()
|
||||
const matchesMediumBreakpoint = useMediaQuery(MediaQueryBreakpoints.md)
|
||||
const matchesXLBreakpoint = useMediaQuery(MediaQueryBreakpoints.xl)
|
||||
const isTabletScreenSize = matchesMediumBreakpoint && !matchesXLBreakpoint
|
||||
|
||||
const iconType: IconType = isTabletScreenSize && !isNotesListVisibleOnTablets ? 'chevron-right' : 'chevron-left'
|
||||
const label = isTabletScreenSize
|
||||
? isNotesListVisibleOnTablets
|
||||
? 'Hide items list'
|
||||
: 'Show items list'
|
||||
: 'Go to items list'
|
||||
|
||||
return (
|
||||
<button
|
||||
className="bg-text-padding mr-3 flex h-8 min-w-8 cursor-pointer items-center justify-center rounded-full border border-solid border-border text-neutral hover:bg-contrast focus:bg-contrast md:hidden"
|
||||
className="bg-text-padding mr-3 flex h-8 min-w-8 cursor-pointer items-center justify-center rounded-full border border-solid border-border text-neutral hover:bg-contrast focus:bg-contrast md:hidden pointer-coarse:md-only:flex pointer-coarse:lg-only:flex"
|
||||
onClick={() => {
|
||||
toggleAppPane(AppPaneId.Items)
|
||||
if (isTabletScreenSize) {
|
||||
toggleNotesListOnTablets()
|
||||
} else {
|
||||
toggleAppPane(AppPaneId.Items)
|
||||
}
|
||||
}}
|
||||
title="Go to items list"
|
||||
aria-label="Go to items list"
|
||||
title={label}
|
||||
aria-label={label}
|
||||
>
|
||||
<Icon type="chevron-left" />
|
||||
<Icon type={iconType} />
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -58,8 +58,9 @@ const PositionedPopoverContent = ({
|
||||
<Portal>
|
||||
<div
|
||||
className={classNames(
|
||||
'safe-area-padding absolute top-0 left-0 flex h-full w-full min-w-80 cursor-auto flex-col overflow-y-auto rounded bg-default shadow-main md:h-auto md:max-w-xs',
|
||||
'absolute top-0 left-0 flex h-full w-full min-w-80 cursor-auto flex-col overflow-y-auto rounded bg-default shadow-main md:h-auto md:max-w-xs',
|
||||
overrideZIndex ? overrideZIndex : 'z-dropdown-menu',
|
||||
!isDesktopScreen ? 'pt-safe-top pb-safe-bottom' : '',
|
||||
)}
|
||||
style={{
|
||||
...styles,
|
||||
|
||||
@@ -53,7 +53,7 @@ const PanelSettingsSection = ({ application }: Props) => {
|
||||
}, [application])
|
||||
|
||||
return (
|
||||
<div className="hidden text-sm md:block">
|
||||
<div className="hidden text-sm md:block pointer-coarse:md-only:hidden pointer-coarse:lg-only:hidden">
|
||||
<HorizontalSeparator classes="my-2" />
|
||||
<div className="my-1 px-3 text-sm font-semibold uppercase text-text">Panel Settings</div>
|
||||
<MenuItem
|
||||
|
||||
@@ -19,6 +19,8 @@ import { AppPaneId } from './AppPaneMetadata'
|
||||
type ResponsivePaneData = {
|
||||
selectedPane: AppPaneId
|
||||
toggleAppPane: (paneId: AppPaneId) => void
|
||||
isNotesListVisibleOnTablets: boolean
|
||||
toggleNotesListOnTablets: () => void
|
||||
}
|
||||
|
||||
const ResponsivePaneContext = createContext<ResponsivePaneData | undefined>(undefined)
|
||||
@@ -60,15 +62,10 @@ const ResponsivePaneProvider = ({ children }: ChildrenProps) => {
|
||||
|
||||
const toggleAppPane = useCallback(
|
||||
(paneId: AppPaneId) => {
|
||||
if (paneId === currentSelectedPane) {
|
||||
setCurrentSelectedPane(previousSelectedPane ? previousSelectedPane : AppPaneId.Editor)
|
||||
setPreviousSelectedPane(paneId)
|
||||
} else {
|
||||
setPreviousSelectedPane(currentSelectedPane)
|
||||
setCurrentSelectedPane(paneId)
|
||||
}
|
||||
setPreviousSelectedPane(currentSelectedPane)
|
||||
setCurrentSelectedPane(paneId)
|
||||
},
|
||||
[currentSelectedPane, previousSelectedPane],
|
||||
[currentSelectedPane],
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
@@ -102,12 +99,20 @@ const ResponsivePaneProvider = ({ children }: ChildrenProps) => {
|
||||
}
|
||||
}, [addAndroidBackHandler, currentSelectedPaneRef, toggleAppPane])
|
||||
|
||||
const [isNotesListVisibleOnTablets, setNotesListVisibleOnTablets] = useState(true)
|
||||
|
||||
const toggleNotesListOnTablets = useCallback(() => {
|
||||
setNotesListVisibleOnTablets((visible) => !visible)
|
||||
}, [])
|
||||
|
||||
const contextValue = useMemo(
|
||||
() => ({
|
||||
selectedPane: currentSelectedPane,
|
||||
toggleAppPane,
|
||||
isNotesListVisibleOnTablets,
|
||||
toggleNotesListOnTablets,
|
||||
}),
|
||||
[currentSelectedPane, toggleAppPane],
|
||||
[currentSelectedPane, isNotesListVisibleOnTablets, toggleAppPane, toggleNotesListOnTablets],
|
||||
)
|
||||
|
||||
return (
|
||||
|
||||
@@ -40,11 +40,6 @@ body {
|
||||
color: var(--sn-stylekit-foreground-color);
|
||||
}
|
||||
|
||||
.safe-area-padding {
|
||||
padding: var(--safe-area-inset-top) var(--safe-area-inset-right) var(--safe-area-inset-bottom)
|
||||
var(--safe-area-inset-left);
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans',
|
||||
@@ -154,12 +149,16 @@ $footer-height: 2rem;
|
||||
}
|
||||
|
||||
.app {
|
||||
height: calc(100% - #{$footer-height});
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
vertical-align: top;
|
||||
width: 100%;
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
height: calc(var(--viewport-height) - #{$footer-height});
|
||||
}
|
||||
|
||||
.section {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
Reference in New Issue
Block a user