feat(user-pref): revert view mode as user-prefs serverside
previous change is breaking playwright tests, need to check later changes
This commit is contained in:
@@ -72,23 +72,35 @@ export type Section =
|
||||
| 'photos'
|
||||
| 'music';
|
||||
|
||||
// `viewMode` used to live here (localStorage `oxi-view-mode`), but
|
||||
// moved to the server-side `ui_preferences` bag so the choice
|
||||
// follows the user across devices. Read via
|
||||
// `preferences.viewMode` and mutate via `preferences.setViewMode`
|
||||
// (`lib/stores/preferences.svelte.ts`). Kept `ViewMode` as an
|
||||
// exported type because template code still needs it for prop
|
||||
// annotations without pulling in the whole preferences module.
|
||||
const VIEW_KEY = 'oxi-view-mode';
|
||||
|
||||
function readViewMode(): ViewMode {
|
||||
if (typeof localStorage === 'undefined') return 'grid';
|
||||
return localStorage.getItem(VIEW_KEY) === 'list' ? 'list' : 'grid';
|
||||
}
|
||||
|
||||
class FilesStore {
|
||||
currentFolder = $state<string | null>(null);
|
||||
currentFolderInfo = $state<FolderItem | null>(null);
|
||||
breadcrumbPath = $state<Array<{ id: string; name: string }>>([]);
|
||||
// View mode INTENTIONALLY lives here (localStorage) rather than in
|
||||
// the server-side `preferences` bag. See the note in
|
||||
// `preferences.svelte.ts::UiPreferences` for the full rationale —
|
||||
// short version: server persistence broke Playwright test
|
||||
// isolation (favorites.spec's list-view click leaked into every
|
||||
// downstream test's context), and view mode isn't a preference
|
||||
// users have asked to sync across devices.
|
||||
viewMode = $state<ViewMode>(readViewMode());
|
||||
section = $state<Section>('files');
|
||||
isSearchMode = $state(false);
|
||||
// Reactive set: in-place mutations below drive template/$derived reads.
|
||||
selection = new SvelteSet<string>();
|
||||
|
||||
setViewMode(mode: ViewMode): void {
|
||||
this.viewMode = mode;
|
||||
if (typeof localStorage !== 'undefined') localStorage.setItem(VIEW_KEY, mode);
|
||||
}
|
||||
|
||||
clearSelection(): void {
|
||||
this.selection.clear();
|
||||
}
|
||||
|
||||
@@ -27,11 +27,13 @@ it('shows the owner as "Me" for the current user and a short id otherwise', () =
|
||||
expect(ownerLabel('abcdef123456', 'someone-else')).toBe('abcdef12');
|
||||
});
|
||||
|
||||
// View-mode assertions moved to `preferences.svelte.test.ts` — the
|
||||
// setting now lives on the server-side `ui_preferences` bag via the
|
||||
// `preferences` store, not on `FilesStore`. What remains of `FilesStore`
|
||||
// is navigation + selection state, exercised below.
|
||||
it('toggles selection', () => {
|
||||
it('persists the view mode and toggles selection', () => {
|
||||
files.setViewMode('list');
|
||||
expect(files.viewMode).toBe('list');
|
||||
expect(localStorage.getItem('oxi-view-mode')).toBe('list');
|
||||
files.setViewMode('grid');
|
||||
expect(files.viewMode).toBe('grid');
|
||||
|
||||
files.clearSelection();
|
||||
expect(files.selection.size).toBe(0);
|
||||
files.toggleSelected('a');
|
||||
|
||||
@@ -41,22 +41,23 @@ export interface UiPreferences {
|
||||
* preserved on upload, matching Nextcloud / ownCloud / Seafile.
|
||||
*/
|
||||
hide_dotfiles?: boolean;
|
||||
/**
|
||||
* App-wide file list view: grid tiles or list rows. Default
|
||||
* `'grid'`. Migrated from the localStorage `oxi-view-mode` key
|
||||
* so the choice follows the user across devices — muscle memory
|
||||
* for "I use list on my laptop, grid on my tablet" is rare;
|
||||
* consistency across devices is the common case. Public-share
|
||||
* viewers still use `oxi-share-view` (localStorage) because
|
||||
* anonymous consumers have no server preferences.
|
||||
*/
|
||||
view_mode?: 'grid' | 'list';
|
||||
// NOTE: view_mode (grid/list) DELIBERATELY stays in localStorage
|
||||
// (`oxi-view-mode` on `filesStore`). Making it server-persistent
|
||||
// caused a real Playwright regression: `favorites.spec.ts` clicks
|
||||
// the list-view toggle, and on the server-backed store that
|
||||
// preference would then leak into every downstream test's fresh
|
||||
// browser context — Playwright's default context isolation
|
||||
// relies on localStorage being fresh per test, which the server
|
||||
// bag can't provide. Result: files-extra's `Zip-*` folder fell
|
||||
// outside list view's smaller virtualisation window (~25 vs ~75
|
||||
// grid items) and `getByTestId` timed out. Google Drive / Finder
|
||||
// / Dropbox also keep view mode per-device — the sync-across-
|
||||
// devices UX isn't a strongly-requested pattern.
|
||||
}
|
||||
|
||||
/** Reasonable default for an empty bag or a missing key. */
|
||||
const DEFAULTS: Required<UiPreferences> = {
|
||||
hide_dotfiles: false,
|
||||
view_mode: 'grid'
|
||||
hide_dotfiles: false
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -84,8 +85,6 @@ class PreferencesStore {
|
||||
: DEFAULTS.hide_dotfiles
|
||||
);
|
||||
|
||||
viewMode = $derived<'grid' | 'list'>(this.bag.view_mode === 'list' ? 'list' : DEFAULTS.view_mode);
|
||||
|
||||
// ── Mutations ─────────────────────────────────────────────────
|
||||
|
||||
private patchTimer: ReturnType<typeof setTimeout> | null = null;
|
||||
@@ -158,10 +157,6 @@ class PreferencesStore {
|
||||
toggleHideDotfiles(): void {
|
||||
this.setHideDotfiles(!this.hideDotfiles);
|
||||
}
|
||||
|
||||
setViewMode(mode: 'grid' | 'list'): void {
|
||||
this.set({ view_mode: mode });
|
||||
}
|
||||
}
|
||||
|
||||
export const preferences = new PreferencesStore();
|
||||
|
||||
Reference in New Issue
Block a user