Skip to content

fix(interface): add Add Storage button to explorer top bar - #3077

Open
gprot42 wants to merge 1 commit into
spacedriveapp:mainfrom
gprot42:fix/explorer-add-storage-entry
Open

gprot42 wants to merge 1 commit into
spacedriveapp:mainfrom
gprot42:fix/explorer-add-storage-entry

Conversation

@gprot42

@gprot42 gprot42 commented Jul 8, 2026

Copy link
Copy Markdown

Summary

  • Cloud storage connection was only exposed from Overview Add Storage
  • Add the same Add Storage entry point to the explorer top bar

Test plan

  • Explorer shows blue + Add Storage button in top bar
  • Clicking it opens Add Storage modal with Cloud Storage option
  • Connecting cloud storage navigates to the new volume path

@coderabbitai

coderabbitai Bot commented Jul 8, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@gprot42, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 7 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 200078b9-f5ff-4ba1-8a51-3a7b3357c7f3

📥 Commits

Reviewing files that changed from the base of the PR and between 2801014 and f32267a.

📒 Files selected for processing (1)
  • packages/interface/src/routes/explorer/ExplorerView.tsx

Walkthrough

Adds explicit explorer sort-order state and query propagation across backend and UI, introduces an Add Storage top-bar action, and updates Tauri resolution, stub modules, and transparent-window CSS handling.

Changes

Explorer sort direction flow

Layer / File(s) Summary
Sort contracts and tab state
packages/interface/src/routes/explorer/sortUtils.ts, packages/interface/src/routes/explorer/context.tsx, packages/interface/src/components/TabManager/TabManagerContext.tsx
Adds shared sort order helpers and a SortOrder type, stores sort order in tab explorer state, and re-exports the sort-order type from explorer context.
Directory listing sort direction
core/src/ops/files/query/directory_listing.rs, apps/cli/src/domains/file/mod.rs, core/tests/normalized_cache_fixtures_test.rs
Extends directory listing inputs with optional sort direction, applies it in SQL and in-memory sorting, and updates callers/tests to pass the new field explicitly.
Explorer sort actions and state updates
packages/interface/src/routes/explorer/context.tsx, packages/interface/src/routes/explorer/ExplorerView.tsx
Adds sort-order state and handlers to explorer context, updates sort menu wiring, and adds the Add Storage top-bar action.
Explorer query and UI consumers
packages/interface/src/routes/explorer/hooks/useExplorerFiles.ts, packages/interface/src/routes/explorer/hooks/useExplorerKeyboard.ts, packages/interface/src/routes/explorer/views/*
Passes sort direction into explorer queries, sorts directory results on the client, and updates list/column/size/knowledge views to use the current sort order and toggle behavior.

Tauri build and runtime compatibility

Layer / File(s) Summary
Vite aliases and stubs
apps/tauri/vite.config.ts, apps/tauri/src/stubs/debug.ts, apps/tauri/src/stubs/spacebot-api-client.ts
Adds Bun-aware CJS resolution, aliases packages to resolved entries or local stubs, and defines browser no-op/client placeholder modules.
Tauri CSS sources and overlays
apps/tauri/src/index.css
Adds Tailwind source paths and Tauri-specific overlay, backdrop, and solid-surface styling rules for transparent window rendering.

Estimated code review effort: 4 (Complex) | ~60 minutes

Poem

I hop through sort order, neat and clear,
With plus-button paths now landing here.
The Tauri panes glow without a blur,
And stubby little helpers quietly purr.
🐇✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding an Add Storage button to the explorer top bar.
Description check ✅ Passed The description matches the implemented explorer top-bar Add Storage entry point and related navigation flow.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/interface/src/routes/explorer/ExplorerView.tsx`:
- Around line 97-102: The storage-added callback is still typed too loosely,
letting invalid values through to navigation. Update the callback type in
useAddStorageDialog and AddStorageModal so the parameter is SdPath instead of
any, and keep the ExplorerView handleAddStorage flow aligned with that contract
when calling navigateToPath.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: b91ce94d-2b05-4b37-a630-4490927df0f0

📥 Commits

Reviewing files that changed from the base of the PR and between 60369e9 and 1dcfbf6.

📒 Files selected for processing (1)
  • packages/interface/src/routes/explorer/ExplorerView.tsx

Comment on lines +97 to +102
const handleAddStorage = useCallback(() => {
useAddStorageDialog((sdPath) => {
navigateToPath(sdPath);
});
}, [navigateToPath]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the dialog hook and SdPath definition/usages
git ls-files 'packages/interface/src/routes/explorer/**' 'packages/**' | rg 'AddStorageModal\.tsx|ExplorerView\.tsx|SdPath'
rg -n "useAddStorageDialog|SdPath|any" packages/interface/src/routes/explorer packages -g '*.ts' -g '*.tsx'

Repository: spacedriveapp/spacedrive

Length of output: 50380


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '350,390p' packages/interface/src/routes/explorer/components/AddStorageModal.tsx

Repository: spacedriveapp/spacedrive

Length of output: 1056


Type onStorageAdded as SdPath in packages/interface/src/routes/explorer/components/AddStorageModal.tsx
useAddStorageDialog still accepts (sdPath: any), which bypasses the SdPath contract and lets invalid values reach navigateToPath. Replace any with SdPath.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/interface/src/routes/explorer/ExplorerView.tsx` around lines 97 -
102, The storage-added callback is still typed too loosely, letting invalid
values through to navigation. Update the callback type in useAddStorageDialog
and AddStorageModal so the parameter is SdPath instead of any, and keep the
ExplorerView handleAddStorage flow aligned with that contract when calling
navigateToPath.

Source: Coding guidelines

Cloud storage was only reachable from Overview. Expose the same Add Storage
entry point in the explorer so users can connect S3, Google Drive, and
other providers while browsing files.
@gprot42
gprot42 force-pushed the fix/explorer-add-storage-entry branch from 2801014 to f32267a Compare July 8, 2026 17:40

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/interface/src/routes/explorer/hooks/useExplorerKeyboard.ts (1)

49-56: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Add folders_first to the keyboard navigation directory query.

Every other directory listing query in this PR includes folders_first: viewSettings.foldersFirst, but this query omits it. When folders_first is enabled in view settings, the server returns files in a different order than what the user sees, causing arrow-key navigation, typeahead, and select-all to operate on a misaligned file list.

🐛 Proposed fix
 		input: currentPath
 			? {
 					path: currentPath,
 					limit: null,
 					include_hidden: false,
 					sort_by: sortBy as DirectorySortBy,
 					sort_direction: toSortDirection(sortOrder),
+					folders_first: viewSettings.foldersFirst,
 				}
 			: null!,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/interface/src/routes/explorer/hooks/useExplorerKeyboard.ts` around
lines 49 - 56, The directory query in useExplorerKeyboard is missing
folders_first, so keyboard navigation can get out of sync with the displayed
order. Update the query built from currentPath to include folders_first using
the existing viewSettings.foldersFirst value, matching the other directory
listing queries in this hook so arrow-key navigation, typeahead, and select-all
operate on the same ordering.
🧹 Nitpick comments (2)
packages/interface/src/components/SpacesSidebar/SpaceSettingsModal.tsx (1)

19-19: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use an explicit interface for SpaceSettingsDialog props.

As per coding guidelines, "Use explicit TypeScript interfaces for component props instead of implicit types." The inline type { id: number; space: Space } should be a named interface.

♻️ Proposed refactor
+interface SpaceSettingsDialogProps {
+	id: number;
+	space: Space;
+}
+
-function SpaceSettingsDialog(props: { id: number; space: Space }) {
+function SpaceSettingsDialog(props: SpaceSettingsDialogProps) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/interface/src/components/SpacesSidebar/SpaceSettingsModal.tsx` at
line 19, `SpaceSettingsDialog` is using an inline props type instead of a named
interface. Introduce an explicit TypeScript interface for the component props
and update `SpaceSettingsDialog` to use that interface rather than `{ id:
number; space: Space }`. Keep the interface close to the component so it’s easy
to find and reuse if needed.

Source: Coding guidelines

core/src/ops/files/query/directory_listing.rs (1)

231-239: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate direction-resolution logic across SQL and in-memory sort paths.

The same self.input.sort_direction.clone().unwrap_or_else(|| Self::default_sort_direction(&self.input.sort_by)) pattern is repeated in query_indexed_directory_impl and sort_files. Extracting a small helper avoids the two paths silently diverging later.

♻️ Suggested refactor
+	fn effective_sort_direction(&self) -> SortDirection {
+		self.input
+			.sort_direction
+			.clone()
+			.unwrap_or_else(|| Self::default_sort_direction(&self.input.sort_by))
+	}
+
 	fn default_sort_direction(sort_by: &DirectorySortBy) -> SortDirection {

Then replace both call sites with self.effective_sort_direction().

Also applies to: 820-837

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/src/ops/files/query/directory_listing.rs` around lines 231 - 239,
Duplicate sort-direction resolution is repeated in both
query_indexed_directory_impl and sort_files, which risks the SQL and in-memory
paths diverging. Extract the shared logic into a helper on the directory listing
type, such as effective_sort_direction, using the existing
self.input.sort_direction and Self::default_sort_direction(&self.input.sort_by)
behavior. Then replace both call sites with the new helper and keep the SQL
dir_sql mapping and file sorting path consuming the same resolved SortDirection.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/interface/src/components/SpacesSidebar/SpaceSettingsModal.tsx`:
- Around line 63-76: The color picker buttons in SpaceSettingsModal are missing
accessible labels, so screen readers cannot identify each swatch. Update the
button rendered inside PRESET_COLORS.map in SpaceSettingsModal to include a
meaningful aria-label for each color (for example, based on the color value or a
friendly name) while keeping the existing onClick, selectedColor, and styling
behavior unchanged.

In `@packages/interface/src/components/SpacesSidebar/SpaceSwitcher.tsx`:
- Around line 20-28: The `openDialogAfterMenuCloses` flow in `SpaceSwitcher`
schedules a `requestAnimationFrame` that can still fire after the component
unmounts, leading to stale dialog opens; store the returned raf id in a
`useRef`, cancel it in a cleanup effect on unmount, and ensure the callback only
calls `openDialog` if the component is still mounted.

In `@packages/interface/src/routes/explorer/sortUtils.ts`:
- Around line 6-11: The default sort fallback does not account for the
MediaSortBy key datetaken, so media views get the wrong direction and no
effective fallback sort. Update defaultSortOrder() in sortUtils to return "desc"
for datetaken alongside modified and size, and ensure the fallback sorter that
consumes SortBy also handles datetaken using the same media date field logic as
the other media sort keys.

---

Outside diff comments:
In `@packages/interface/src/routes/explorer/hooks/useExplorerKeyboard.ts`:
- Around line 49-56: The directory query in useExplorerKeyboard is missing
folders_first, so keyboard navigation can get out of sync with the displayed
order. Update the query built from currentPath to include folders_first using
the existing viewSettings.foldersFirst value, matching the other directory
listing queries in this hook so arrow-key navigation, typeahead, and select-all
operate on the same ordering.

---

Nitpick comments:
In `@core/src/ops/files/query/directory_listing.rs`:
- Around line 231-239: Duplicate sort-direction resolution is repeated in both
query_indexed_directory_impl and sort_files, which risks the SQL and in-memory
paths diverging. Extract the shared logic into a helper on the directory listing
type, such as effective_sort_direction, using the existing
self.input.sort_direction and Self::default_sort_direction(&self.input.sort_by)
behavior. Then replace both call sites with the new helper and keep the SQL
dir_sql mapping and file sorting path consuming the same resolved SortDirection.

In `@packages/interface/src/components/SpacesSidebar/SpaceSettingsModal.tsx`:
- Line 19: `SpaceSettingsDialog` is using an inline props type instead of a
named interface. Introduce an explicit TypeScript interface for the component
props and update `SpaceSettingsDialog` to use that interface rather than `{ id:
number; space: Space }`. Keep the interface close to the component so it’s easy
to find and reuse if needed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 200078b9-f5ff-4ba1-8a51-3a7b3357c7f3

📥 Commits

Reviewing files that changed from the base of the PR and between 1dcfbf6 and 2801014.

⛔ Files ignored due to path filters (1)
  • packages/ts-client/src/generated/types.ts is excluded by !**/generated/**, !**/generated/**
📒 Files selected for processing (22)
  • apps/cli/src/domains/file/mod.rs
  • apps/tauri/src/index.css
  • apps/tauri/src/stubs/debug.ts
  • apps/tauri/src/stubs/spacebot-api-client.ts
  • apps/tauri/vite.config.ts
  • core/src/ops/files/query/directory_listing.rs
  • core/tests/normalized_cache_fixtures_test.rs
  • packages/interface/src/components/SpacesSidebar/CreateSpaceModal.tsx
  • packages/interface/src/components/SpacesSidebar/SpaceSettingsModal.tsx
  • packages/interface/src/components/SpacesSidebar/SpaceSwitcher.tsx
  • packages/interface/src/components/SpacesSidebar/spacePresets.ts
  • packages/interface/src/components/TabManager/TabManagerContext.tsx
  • packages/interface/src/routes/explorer/ExplorerView.tsx
  • packages/interface/src/routes/explorer/context.tsx
  • packages/interface/src/routes/explorer/hooks/useExplorerFiles.ts
  • packages/interface/src/routes/explorer/hooks/useExplorerKeyboard.ts
  • packages/interface/src/routes/explorer/sortUtils.ts
  • packages/interface/src/routes/explorer/views/ColumnView/Column.tsx
  • packages/interface/src/routes/explorer/views/ColumnView/ColumnView.tsx
  • packages/interface/src/routes/explorer/views/KnowledgeView.tsx
  • packages/interface/src/routes/explorer/views/ListView/ListView.tsx
  • packages/interface/src/routes/explorer/views/SizeView/SizeView.tsx
✅ Files skipped from review due to trivial changes (2)
  • apps/tauri/src/stubs/debug.ts
  • apps/tauri/src/stubs/spacebot-api-client.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/interface/src/routes/explorer/ExplorerView.tsx

Comment on lines +63 to +76
{PRESET_COLORS.map((color) => (
<button
key={color}
type="button"
onClick={() => setSelectedColor(color)}
className={clsx(
'h-8 w-8 rounded-full border-2 transition-all',
selectedColor === color
? 'scale-110 border-white'
: 'border-transparent',
)}
style={{ backgroundColor: color }}
/>
))}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Add aria-labels to color picker buttons for screen reader accessibility.

The color buttons have no text content or aria-label, so screen readers announce them as generic "button" elements with no identifying context.

♿ Proposed fix
 						<button
 							key={color}
 							type="button"
+							aria-label={`Color ${color}`}
 							onClick={() => setSelectedColor(color)}
 							className={clsx(
 								'h-8 w-8 rounded-full border-2 transition-all',
 								selectedColor === color
 									? 'scale-110 border-white'
 									: 'border-transparent',
 							)}
 							style={{ backgroundColor: color }}
 						/>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{PRESET_COLORS.map((color) => (
<button
key={color}
type="button"
onClick={() => setSelectedColor(color)}
className={clsx(
'h-8 w-8 rounded-full border-2 transition-all',
selectedColor === color
? 'scale-110 border-white'
: 'border-transparent',
)}
style={{ backgroundColor: color }}
/>
))}
{PRESET_COLORS.map((color) => (
<button
key={color}
type="button"
aria-label={`Color ${color}`}
onClick={() => setSelectedColor(color)}
className={clsx(
'h-8 w-8 rounded-full border-2 transition-all',
selectedColor === color
? 'scale-110 border-white'
: 'border-transparent',
)}
style={{ backgroundColor: color }}
/>
))}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/interface/src/components/SpacesSidebar/SpaceSettingsModal.tsx`
around lines 63 - 76, The color picker buttons in SpaceSettingsModal are missing
accessible labels, so screen readers cannot identify each swatch. Update the
button rendered inside PRESET_COLORS.map in SpaceSettingsModal to include a
meaningful aria-label for each color (for example, based on the color value or a
friendly name) while keeping the existing onClick, selectedColor, and styling
behavior unchanged.

Comment on lines +20 to +28
const [menuOpen, setMenuOpen] = useState(false);

const openDialogAfterMenuCloses = (openDialog: () => void) => {
setMenuOpen(false);
// Let the dropdown fully unmount before opening a modal overlay.
requestAnimationFrame(() => {
openDialog();
});
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Cancel pending requestAnimationFrame on component unmount to avoid stale dialog opens.

If the component unmounts between setMenuOpen(false) and the requestAnimationFrame callback (e.g., space switch causes re-render/remount), the callback still fires and attempts to open a dialog, which can cause a stale state update or unexpected dialog appearance.

🔒 Proposed fix
 	const [menuOpen, setMenuOpen] = useState(false);
 
+	useEffect(() => {
+		return () => cancelAnimationFrame(rafId);
+	}, []);
+
+	let rafId = 0;
+
 	const openDialogAfterMenuCloses = (openDialog: () => void) => {
 		setMenuOpen(false);
 		// Let the dropdown fully unmount before opening a modal overlay.
-		requestAnimationFrame(() => {
+		rafId = requestAnimationFrame(() => {
 			openDialog();
 		});
 	};

Alternatively, store the rafId in a useRef for cleaner handling:

+	const rafRef = useRef<number>(0);
+
+	useEffect(() => {
+		return () => {
+			if (rafRef.current) cancelAnimationFrame(rafRef.current);
+		};
+	}, []);
+
 	const openDialogAfterMenuCloses = (openDialog: () => void) => {
 		setMenuOpen(false);
 		// Let the dropdown fully unmount before opening a modal overlay.
-		requestAnimationFrame(() => {
+		rafRef.current = requestAnimationFrame(() => {
 			openDialog();
 		});
 	};
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const [menuOpen, setMenuOpen] = useState(false);
const openDialogAfterMenuCloses = (openDialog: () => void) => {
setMenuOpen(false);
// Let the dropdown fully unmount before opening a modal overlay.
requestAnimationFrame(() => {
openDialog();
});
};
const [menuOpen, setMenuOpen] = useState(false);
useEffect(() => {
return () => cancelAnimationFrame(rafId);
}, []);
let rafId = 0;
const openDialogAfterMenuCloses = (openDialog: () => void) => {
setMenuOpen(false);
// Let the dropdown fully unmount before opening a modal overlay.
rafId = requestAnimationFrame(() => {
openDialog();
});
};
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/interface/src/components/SpacesSidebar/SpaceSwitcher.tsx` around
lines 20 - 28, The `openDialogAfterMenuCloses` flow in `SpaceSwitcher` schedules
a `requestAnimationFrame` that can still fire after the component unmounts,
leading to stale dialog opens; store the returned raf id in a `useRef`, cancel
it in a cleanup effect on unmount, and ensure the callback only calls
`openDialog` if the component is still mounted.

Comment on lines +6 to +11
export function defaultSortOrder(sortBy: SortBy): SortOrder {
if (sortBy === "modified" || sortBy === "size") {
return "desc";
}
return "asc";
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

What fields does @sd/ts-client's generated MediaSortBy TypeScript type include?

💡 Result:

The MediaSortBy TypeScript type (or enum), exported by the @sd/ts-client package used in the Spacedrive project, defines the available fields for sorting media files within the application. Based on the project's codebase, the MediaSortBy enum is used to control sorting behavior in the explorer. While specific fields may evolve with version updates, they typically include: - Name - Size - DateCreated - DateModified - DateAccessed - DateTaken These fields are commonly used in the Spacedrive explorer to order media items, such as images and videos, when utilizing the Media View or other indexed file views [1][2][3]. Please note that as an auto-generated client, the exact structure is maintained within the generated code of @sd/ts-client and may correspond to internal sorting keys like name, sizeInBytes, dateModified, dateIndexed, dateCreated, and object.mediaData.epochTime (for Date Taken) [1][3].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== sortUtils outline ==\n'
ast-grep outline packages/interface/src/routes/explorer/sortUtils.ts --view expanded || true

printf '\n== relevant files ==\n'
git ls-files 'packages/interface/src/routes/explorer/*' 'packages/ts-client/*' | sed -n '1,120p'

printf '\n== search for SortBy / datetaken ==\n'
rg -n --hidden --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' \
  'datetaken|type SortBy|interface SortBy|enum SortBy|MediaSortBy|DirectorySortBy|defaultSortOrder|sortFiles' \
  packages/interface packages/ts-client | sed -n '1,240p'

Repository: spacedriveapp/spacedrive

Length of output: 1971


🌐 Web query:

site:github.com/spacedriveapp/spacedrive "sortUtils.ts" datetaken MediaSortBy SortBy

💡 Result:

In the Spacedrive codebase, "datetaken" is a specific sort value associated with MediaSortBy, which is used to organize media files within the file explorer interface [1][2]. The codebase defines sorting types as follows: - MediaSortBy: A type that includes "datetaken" as a valid sorting option, specifically intended for media-focused views [1][2]. - SortBy: A union type defined as SortBy = DirectorySortBy | MediaSortBy, which centralizes the sorting options used across the explorer's various views and components [3]. Technical usage context: - The explorer components, such as MediaView, often set the default sort order to "datetaken" when the user switches to media-specific views [4][5]. - Logic in the codebase handles the transitions between these sort types. For instance, code may automatically update the sort preference from "modified" to "datetaken" when switching into a media view, and vice versa when exiting [1]. - While "sortUtils.ts" is not explicitly detailed in the provided search highlights as a singular file, the sorting logic is consistently managed via the Explorer context and hooks that utilize the MediaSortBy and DirectorySortBy types imported from the @sd/ts-client package [1][6][3].

Citations:


Handle datetaken in the sort fallback.

MediaSortBy includes datetaken, but defaultSortOrder() still falls back to "asc" for it, and the fallback sorter doesn’t handle it either. That leaves media views with the wrong default direction and a no-op sort for this key.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/interface/src/routes/explorer/sortUtils.ts` around lines 6 - 11, The
default sort fallback does not account for the MediaSortBy key datetaken, so
media views get the wrong direction and no effective fallback sort. Update
defaultSortOrder() in sortUtils to return "desc" for datetaken alongside
modified and size, and ensure the fallback sorter that consumes SortBy also
handles datetaken using the same media date field logic as the other media sort
keys.

@contributor

Copy link
Copy Markdown

cr-chapters .cr/spacedriveapp_spacedrive/3077/chapters.json --header https://github.com/spacedriveapp/spacedrive/pull/3077 60369e9f0..f32267ae5 --hubSha 9bc23ed1792ab1aff32fa9ed3cfec7adab08313d

opencode -s ses_f4ffe04cfffeCaJujYODupoaOW #openrouter/nex-agi/nex-n2.5-pro:free

Motivation:
Cloud storage setup was only available from Overview, forcing users to leave Explorer to add it.
Outcome:
Explorer now opens the existing Add Storage flow directly and navigates to the connected volume.

Chapters:

  1. Expose Add Storage in Explorer — Explorer can now launch the existing Add Storage flow directly from its top bar. This integration reuses the shared dialog and routes a successful connection back into Explorer, completing the previously Overview-only entry point.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants