diff --git a/CLAUDE.md b/CLAUDE.md index da012e53..e75e12cf 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -2649,9 +2649,28 @@ Filesmith's conventions. **PROJECT SETTINGS IS ITS OWN PAGE, AND THE TREE ALWAYS FOLLOWS THE OPEN FILE** (#296; owner, 2026-10-06: "project specific settings should be in a tab called project settings not in explorer. and remove the setting for scroll to open file, it should just be on by default, no - setting"). `ProjectPage.tsx` holds Sidebar position and First view of a new project; Folder for + setting"). `ProjectPage.tsx` holds Sidebar position (the tree's) and First view of a new project; Folder for new tabs stays on Explorer, since the + and Ctrl+T open an Explorer tab. Scroll to the open file is gone and a stored `prism.tree.autoscroll` is ignored. +- **SIDEBAR POSITION IS TWO SETTINGS: THE EXPLORER'S PLACES AND THE PROJECT TREE, AND THE PREVIEW + TAKES THE OTHER SIDE** (#304; owner, 2026-10-07: "fix the setting in Explorer for the sidebar where + you can put it on the right side or the left side? I think that's just an empty setting for now, + but actually implement it. And remember that when the sidebar goes on the right, the preview menu + and button to open it would have to go on the left"; then, the same day, after testing one shared + row: "No, it should be two settings, one on the project tab and one on the explorer tab"). + Explorer > Layout opens with `explorer-side` (key `prism.explorer.side`, `lib/explorerSidePrefs.ts`, + default Left): the Explorer tab's places panel, and nothing else. Project settings keeps + `tree-side` (key `prism.tree.side`, unchanged): the project tree, and nothing else. Neither moves + the other; App reads the Explorer's for an Explorer tab and the tree's for a project tab + (`workspaceSide`), and each panel peeks from its own. On the Explorer's Right: + `.folder-browser[data-side='right']` is a three-column grid (preview, list, places; + the preview column 0px while shut, so its slide still tweens one column), the places come after + the list in the DOM (Tab walks left to right), the preview toggle LEADS the address row (before + Back, the end nearest the pane), the viewer laid over the slot sits at `left: 0` + (`.browse-workspace[data-sidebar-side='right']`), each grip is its left twin turned round + (`ExplorerResize`'s `edge`: a drag toward the middle widens), and the places peek from the right + edge. Left is the window as it was, box for box. The `explorerSide` e2e holds it (it fails on + main), one coat of a see-through ground included, and that each row moves only its own panel. - **The viewer lives here for now.** The plan is a shared package, **`prism-core`**, which diff --git a/package-lock.json b/package-lock.json index 4f6150d3..c5797b71 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "prism", - "version": "0.92.1", + "version": "0.93.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "prism", - "version": "0.92.1", + "version": "0.93.0", "license": "MIT", "dependencies": { "@codemirror/commands": "^6.11.0", diff --git a/package.json b/package.json index be068b68..af0b71d2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prism", - "version": "0.92.1", + "version": "0.93.0", "description": "A fast, universal media viewer for Windows.", "author": "Max", "license": "MIT", diff --git a/src/renderer/src/App.tsx b/src/renderer/src/App.tsx index 4a28afee..be5322bb 100644 --- a/src/renderer/src/App.tsx +++ b/src/renderer/src/App.tsx @@ -104,6 +104,7 @@ import { PropertiesDialog } from './components/PropertiesDialog' import './components/browse/workspace.css' import { focusTermSession } from 'prism-term-core/renderer/components/TerminalPanel' import { sortFiles, useSort } from './lib/sortPrefs' +import { useExplorerSide } from './lib/explorerSidePrefs' import { useTreeSide } from './lib/treePrefs' import { VideoView } from './components/VideoView' import { AudioView } from './components/AudioView' @@ -996,7 +997,12 @@ export default function App(): JSX.Element { ) // The file tree. Off on a fresh install: the media is the point. const [sidebar, setSidebar] = useState(() => localStorage.getItem(SIDEBAR_KEY) === '1') + // TWO SIDEBAR POSITIONS (#304; owner, 2026-10-07: "No, it should be two + // settings, one on the project tab and one on the explorer tab"): the + // project tree's (Project settings) and the Explorer's places (Explorer > + // Layout). Neither moves the other. const treeSide = useTreeSide() + const explorerSide = useExplorerSide() // A PANEL SLIDES WHEN IT IS OPENED OR CLOSED, AND ONLY THEN (owner, // 2026-09-23: "when you collapse the explorer sidebar its not animated, it // should be", and "when you switch between a project and explorer with @@ -2608,7 +2614,8 @@ export default function App(): JSX.Element { const peekPlaces = !!peekTarget?.startsWith('places:') const { phase: peekPhase, end: endPeek } = useSidebarPeek({ target: peekTarget, - side: peekPlaces ? 'left' : treeSide, + // Each panel peeks from its own Sidebar position (#304). + side: peekPlaces ? explorerSide : treeSide, zone: () => document.querySelector('.browse-workspace'), panel: () => document.querySelector( @@ -2616,6 +2623,9 @@ export default function App(): JSX.Element { ) }) peekingRef.current = peekPhase === 'in' + // The side the open tab's sidebar sits on: an Explorer tab's places, else + // the project tree (#304). + const workspaceSide = active && isExplorerTab(active) ? explorerSide : treeSide // The peeking panel's own toggle pins it; so does Ctrl+B (togglePanel). const pinFromPeek = useCallback(() => { endPeek() @@ -4034,7 +4044,8 @@ export default function App(): JSX.Element { : undefined } data-preview-sliding={previewSlide.sliding || undefined} - className={`browse-workspace relative flex min-h-0 flex-1 ${browsing.folder ? 'is-browsing' : ''} ${treeSide === 'right' ? 'flex-row-reverse' : ''} ${ + data-sidebar-side={workspaceSide === 'right' ? 'right' : undefined} + className={`browse-workspace relative flex min-h-0 flex-1 ${browsing.folder ? 'is-browsing' : ''} ${workspaceSide === 'right' ? 'flex-row-reverse' : ''} ${ settingsOpen || setup ? 'invisible' : '' }`} > @@ -4046,7 +4057,7 @@ export default function App(): JSX.Element { section="places" bounds={explorerWidths.bounds.places} onResize={(width) => explorerWidths.resize('places', width)} - right={!browsing.folder && treeSide === 'right'} + edge={explorerSide} /> )} {active && active.kind !== 'settings' && !fullscreen && ( @@ -4140,6 +4151,7 @@ export default function App(): JSX.Element { placesVisible={isExplorerTab(active) ? placesVisible : false} placesSliding={isExplorerTab(active) && panelSliding} placesPeek={peekPlaces ? peekPhase : null} + side={explorerSide} onPinPlaces={pinFromPeek} onPlacePicked={endPeek} onOpenProject={isExplorerTab(active) ? openAsProject : undefined} @@ -4239,6 +4251,7 @@ export default function App(): JSX.Element { section="preview" bounds={explorerWidths.bounds.preview} onResize={(width) => explorerWidths.resize('preview', width)} + edge={explorerSide === 'right' ? 'left' : 'right'} /> )} {!browsing.folder && diff --git a/src/renderer/src/components/browse/BrowseToolbar.tsx b/src/renderer/src/components/browse/BrowseToolbar.tsx index 883d3644..0b44730c 100644 --- a/src/renderer/src/components/browse/BrowseToolbar.tsx +++ b/src/renderer/src/components/browse/BrowseToolbar.tsx @@ -30,6 +30,10 @@ type Props = Pick< /** What sits after the address field: the Explorer's preview toggle and * search button (#267). The file viewer's toolbar has none. */ trailing?: ReactNode + /** What sits BEFORE the history buttons: the preview toggle, when the + * sidebar is on the right and the preview pane on the left (#304), so the + * toggle is at the end nearest the pane it opens. */ + leading?: ReactNode /** The archives along the path (#300, `ArchiveMeta.chain`): those crumbs * wear the archive icon. Before main has answered, a crumb named like an * archive with more path after it is taken to be one. */ @@ -71,6 +75,7 @@ export function BrowseToolbar(props: Props): JSX.Element { } return (
+ {props.leading}
+ ) + const places = (props.placesVisible !== false || sliding || !!props.placesPeek) && ( + { + props.onPlacePicked?.() + props.onQuickAccessFile?.(path, full) + } + : props.onQuickAccessFile + } + onPin={props.placesPeek === 'in' ? props.onPinPlaces : undefined} + onUnpinQuickAccess={props.onUnpinQuickAccess} + onMoveQuickAccess={props.onMoveQuickAccess} + onPinQuickAccessPaths={props.onPinQuickAccessPaths} + directory={props.directory} + chosenPlace={chosenPlace} + onChoosePlace={setChosenPlace} + onNavigate={ + props.placesPeek + ? (path) => { + props.onPlacePicked?.() + props.onNavigate(path) + } + : props.onNavigate + } + onNewTerminal={props.onNewTerminal} + onOpenProject={props.onOpenProject} + onOpenNewTab={props.onOpenNewTab} + /> + ) + return (
{props.terminalControls && (
{props.terminalControls}
)} - + {!right && previewToggle}