summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/web/app/reader/_components/command-palette.tsx36
-rw-r--r--apps/web/app/reader/_components/reader-layout-shell.tsx42
-rw-r--r--apps/web/app/reader/_components/reader-shell.tsx21
-rw-r--r--apps/web/lib/stores/user-interface-store.ts12
4 files changed, 74 insertions, 37 deletions
diff --git a/apps/web/app/reader/_components/command-palette.tsx b/apps/web/app/reader/_components/command-palette.tsx
index e9b7b04..cca04b6 100644
--- a/apps/web/app/reader/_components/command-palette.tsx
+++ b/apps/web/app/reader/_components/command-palette.tsx
@@ -195,39 +195,9 @@ export function CommandPalette() {
<Command.Item
onSelect={() =>
actionAndClose(() => {
- const sidebarPanel = document.querySelector('[data-panel-id="sidebar"]') as HTMLElement | null
- const mainContentPanel = document.querySelector('[data-panel-id="main-content"]') as HTMLElement | null
- if (sidebarPanel && mainContentPanel) {
- const totalPixels = sidebarPanel.offsetWidth + mainContentPanel.offsetWidth
- const minPixels = 192
- const maxPixels = parseInt(sidebarPanel.style.maxWidth, 10) || Math.round(totalPixels * 0.35)
- const midpoint = Math.round((minPixels + maxPixels) / 2)
- localStorage.setItem(
- "react-resizable-panels:asa-sidebar-layout:sidebar:main-content",
- JSON.stringify({ sidebar: midpoint, "main-content": totalPixels - midpoint })
- )
- } else {
- localStorage.removeItem(
- "react-resizable-panels:asa-sidebar-layout:sidebar:main-content"
- )
- }
-
- const entryListPanel = document.querySelector('[data-panel-id="entry-list"]') as HTMLElement | null
- const detailPanel = document.querySelector('[data-panel-id="detail-panel"]') as HTMLElement | null
- if (entryListPanel && detailPanel) {
- const totalPixels = entryListPanel.offsetWidth + detailPanel.offsetWidth
- const halfPixels = Math.round(totalPixels / 2)
- localStorage.setItem(
- "react-resizable-panels:asa-detail-layout:entry-list:detail-panel",
- JSON.stringify({ "entry-list": halfPixels, "detail-panel": totalPixels - halfPixels })
- )
- } else {
- localStorage.removeItem(
- "react-resizable-panels:asa-detail-layout:entry-list:detail-panel"
- )
- }
-
- window.location.reload()
+ const store = useUserInterfaceStore.getState()
+ store.resetSidebarLayout?.()
+ store.resetDetailLayout?.()
})
}
className="cursor-pointer px-2 py-1 text-text-secondary aria-selected:bg-background-tertiary aria-selected:text-text-primary"
diff --git a/apps/web/app/reader/_components/reader-layout-shell.tsx b/apps/web/app/reader/_components/reader-layout-shell.tsx
index 3ff2fa8..9d2eb24 100644
--- a/apps/web/app/reader/_components/reader-layout-shell.tsx
+++ b/apps/web/app/reader/_components/reader-layout-shell.tsx
@@ -1,7 +1,7 @@
"use client"
-import { Suspense, useEffect, useMemo, useState } from "react"
-import { Group, Panel, Separator, useDefaultLayout } from "react-resizable-panels"
+import { Suspense, useEffect, useMemo, useRef, useState } from "react"
+import { Group, Panel, Separator, useDefaultLayout, useGroupRef } from "react-resizable-panels"
import { useUserInterfaceStore } from "@/lib/stores/user-interface-store"
import { classNames } from "@/lib/utilities"
import { useIsMobile } from "@/lib/hooks/use-is-mobile"
@@ -60,7 +60,7 @@ export function ReaderLayoutShell({
const sidebarMaxWidth = useMemo(() => {
if (typeof window === "undefined") return "35%"
- if (!subscriptionsData && !customFeedsData) return "35%"
+ if (!subscriptionsData || !customFeedsData) return "35%"
const canvas = document.createElement("canvas")
const maybeContext = canvas.getContext("2d")
@@ -159,6 +159,41 @@ export function ReaderLayoutShell({
storage: typeof window !== "undefined" ? localStorage : { getItem: () => null, setItem: () => {} },
})
+ const sidebarGroupRef = useGroupRef()
+ const sidebarMaxWidthRef = useRef(sidebarMaxWidth)
+ sidebarMaxWidthRef.current = sidebarMaxWidth
+ const sidebarOnLayoutChangedRef = useRef(sidebarLayout.onLayoutChanged)
+ sidebarOnLayoutChangedRef.current = sidebarLayout.onLayoutChanged
+
+ useEffect(() => {
+ useUserInterfaceStore.getState().setResetSidebarLayout(() => {
+ const group = sidebarGroupRef.current
+ if (!group) return
+ const groupElement = document.querySelector("[data-group]") as HTMLElement | null
+ if (!groupElement) return
+ const totalPixels = groupElement.offsetWidth
+ if (totalPixels === 0) return
+ const minPixels = 192
+ const maxWidthValue = sidebarMaxWidthRef.current
+ let maxPixels: number
+ if (maxWidthValue.endsWith("px")) {
+ maxPixels = parseFloat(maxWidthValue)
+ } else if (maxWidthValue.endsWith("%")) {
+ maxPixels = totalPixels * parseFloat(maxWidthValue) / 100
+ } else {
+ maxPixels = totalPixels * 0.35
+ }
+ const midpointPixels = Math.round((minPixels + maxPixels) / 2)
+ const midpointPercent = (midpointPixels / totalPixels) * 100
+ const appliedLayout = group.setLayout({
+ sidebar: midpointPercent,
+ "main-content": 100 - midpointPercent,
+ })
+ sidebarOnLayoutChangedRef.current?.(appliedLayout)
+ })
+ return () => useUserInterfaceStore.getState().setResetSidebarLayout(null)
+ }, [sidebarGroupRef])
+
useKeyboardNavigation()
useEffect(() => {
@@ -308,6 +343,7 @@ export function ReaderLayoutShell({
orientation="horizontal"
defaultLayout={sidebarLayout.defaultLayout}
onLayoutChanged={isSidebarCollapsed ? undefined : sidebarLayout.onLayoutChanged}
+ groupRef={sidebarGroupRef}
>
{!isSidebarCollapsed && (
<>
diff --git a/apps/web/app/reader/_components/reader-shell.tsx b/apps/web/app/reader/_components/reader-shell.tsx
index 09278c3..247ec8d 100644
--- a/apps/web/app/reader/_components/reader-shell.tsx
+++ b/apps/web/app/reader/_components/reader-shell.tsx
@@ -1,6 +1,7 @@
"use client"
-import { Group, Panel, Separator, useDefaultLayout } from "react-resizable-panels"
+import { useEffect, useRef } from "react"
+import { Group, Panel, Separator, useDefaultLayout, useGroupRef } from "react-resizable-panels"
import { useUserInterfaceStore } from "@/lib/stores/user-interface-store"
import { useMarkAllAsRead } from "@/lib/queries/use-mark-all-as-read"
import { useSubscriptions } from "@/lib/queries/use-subscriptions"
@@ -58,6 +59,23 @@ export function ReaderShell({
storage: typeof window !== "undefined" ? localStorage : { getItem: () => null, setItem: () => {} },
})
+ const detailGroupRef = useGroupRef()
+ const detailOnLayoutChangedRef = useRef(detailLayout.onLayoutChanged)
+ detailOnLayoutChangedRef.current = detailLayout.onLayoutChanged
+
+ useEffect(() => {
+ useUserInterfaceStore.getState().setResetDetailLayout(() => {
+ const group = detailGroupRef.current
+ if (!group) return
+ const appliedLayout = group.setLayout({
+ "entry-list": 50,
+ "detail-panel": 50,
+ })
+ detailOnLayoutChangedRef.current?.(appliedLayout)
+ })
+ return () => useUserInterfaceStore.getState().setResetDetailLayout(null)
+ }, [detailGroupRef])
+
useRealtimeEntries()
let pageTitle = feedFilter === "saved" ? "saved" : "all entries"
@@ -192,6 +210,7 @@ export function ReaderShell({
className="min-h-0 flex-1"
defaultLayout={detailLayout.defaultLayout}
onLayoutChanged={detailLayout.onLayoutChanged}
+ groupRef={detailGroupRef}
>
<Panel id="entry-list" defaultSize={selectedEntryIdentifier ? "40%" : "100%"} minSize="25%">
<div data-panel-zone="entryList" className={classNames(
diff --git a/apps/web/lib/stores/user-interface-store.ts b/apps/web/lib/stores/user-interface-store.ts
index 5890167..01dceba 100644
--- a/apps/web/lib/stores/user-interface-store.ts
+++ b/apps/web/lib/stores/user-interface-store.ts
@@ -44,6 +44,8 @@ interface UserInterfaceState {
isShortcutsDialogOpen: boolean
expandedFolderIdentifiers: string[]
navigableEntryIdentifiers: string[]
+ resetSidebarLayout: (() => void) | null
+ resetDetailLayout: (() => void) | null
toggleSidebar: () => void
setSidebarCollapsed: (isCollapsed: boolean) => void
@@ -67,6 +69,8 @@ interface UserInterfaceState {
toggleShortcutsDialog: () => void
toggleFolderExpansion: (folderIdentifier: string) => void
setNavigableEntryIdentifiers: (identifiers: string[]) => void
+ setResetSidebarLayout: (callback: (() => void) | null) => void
+ setResetDetailLayout: (callback: (() => void) | null) => void
}
export const useUserInterfaceStore = create<UserInterfaceState>()(
@@ -92,6 +96,8 @@ export const useUserInterfaceStore = create<UserInterfaceState>()(
isShortcutsDialogOpen: false,
expandedFolderIdentifiers: [],
navigableEntryIdentifiers: [],
+ resetSidebarLayout: null,
+ resetDetailLayout: null,
toggleSidebar: () =>
set((state) => ({ isSidebarCollapsed: !state.isSidebarCollapsed })),
@@ -155,6 +161,12 @@ export const useUserInterfaceStore = create<UserInterfaceState>()(
setNavigableEntryIdentifiers: (identifiers) =>
set({ navigableEntryIdentifiers: identifiers }),
+
+ setResetSidebarLayout: (callback) =>
+ set({ resetSidebarLayout: callback }),
+
+ setResetDetailLayout: (callback) =>
+ set({ resetDetailLayout: callback }),
}),
{
name: "asa-news-ui-preferences",