mirror of
https://github.com/spacedriveapp/spacedrive.git
synced 2026-04-21 15:07:54 -04:00
* `createSolid` + `createPersistedMutable` * Move all Valtio stores to SolidJS * Remove Valtio from `@sd/client` * Missed auth store * wip * `useSolidStore` allow mutable setting * Restructure `@sd/client` a bit * Add `WithSolid` + custom `useObserver` * Parse props both ways * Universal Context * Solid to React context working * Working universal context * context inheritance * whoops * Make it clearer how the demo works * wip: `useUniversalQuery`
222 lines
6.1 KiB
TypeScript
222 lines
6.1 KiB
TypeScript
import { RadixCheckbox, Select, SelectOption, Slider, tw, z } from '@sd/ui';
|
|
import { explorerLayout, useExplorerLayoutStore } from '~/../packages/client/src';
|
|
import i18n from '~/app/I18n';
|
|
import { SortOrderSchema } from '~/app/route-schemas';
|
|
import { useLocale } from '~/hooks';
|
|
|
|
import { useExplorerContext } from './Context';
|
|
import { createOrdering, getOrderingDirection, orderingKey } from './store';
|
|
|
|
const Subheading = tw.div`text-ink-dull mb-1 text-xs font-medium`;
|
|
|
|
export default () => {
|
|
const { t } = useLocale();
|
|
|
|
const explorer = useExplorerContext();
|
|
const layoutStore = useExplorerLayoutStore();
|
|
const settings = explorer.useSettingsSnapshot();
|
|
|
|
return (
|
|
<div className="flex w-80 flex-col gap-4 p-4">
|
|
{(settings.layoutMode === 'grid' || settings.layoutMode === 'media') && (
|
|
<div>
|
|
<Subheading>{t('item_size')}</Subheading>
|
|
{settings.layoutMode === 'grid' ? (
|
|
<Slider
|
|
onValueChange={(value) => {
|
|
explorer.settingsStore.gridItemSize = value[0] || 100;
|
|
}}
|
|
defaultValue={[settings.gridItemSize]}
|
|
max={200}
|
|
step={10}
|
|
min={60}
|
|
/>
|
|
) : (
|
|
<Slider
|
|
defaultValue={[10 - settings.mediaColumns]}
|
|
min={0}
|
|
max={6}
|
|
step={1}
|
|
onValueChange={([val]) => {
|
|
if (val !== undefined)
|
|
explorer.settingsStore.mediaColumns = 10 - val;
|
|
}}
|
|
/>
|
|
)}
|
|
</div>
|
|
)}
|
|
|
|
{settings.layoutMode === 'grid' && (
|
|
<div>
|
|
<Subheading>{t('grid_gap')}</Subheading>
|
|
<Slider
|
|
onValueChange={([val]) => {
|
|
if (val) explorer.settingsStore.gridGap = val;
|
|
}}
|
|
defaultValue={[settings.gridGap]}
|
|
max={16}
|
|
min={4}
|
|
step={4}
|
|
/>
|
|
</div>
|
|
)}
|
|
|
|
{(settings.layoutMode === 'grid' || settings.layoutMode === 'media') && (
|
|
<div className="grid grid-cols-2 gap-2">
|
|
<div className="flex flex-col">
|
|
<Subheading>{t('sort_by')}</Subheading>
|
|
<Select
|
|
value={settings.order ? orderingKey(settings.order) : 'none'}
|
|
size="sm"
|
|
className="w-full"
|
|
onChange={(key) => {
|
|
if (key === 'none') explorer.settingsStore.order = null;
|
|
else
|
|
explorer.settingsStore.order = createOrdering(
|
|
key,
|
|
explorer.settingsStore.order
|
|
? getOrderingDirection(explorer.settingsStore.order)
|
|
: 'Asc'
|
|
);
|
|
}}
|
|
>
|
|
<SelectOption value="none">{t('none')}</SelectOption>
|
|
{explorer.orderingKeys?.options.map((option) => (
|
|
<SelectOption key={option.value} value={option.value}>
|
|
{option.description}
|
|
</SelectOption>
|
|
))}
|
|
</Select>
|
|
</div>
|
|
|
|
<div className="flex flex-col">
|
|
<Subheading>{t('direction')}</Subheading>
|
|
<Select
|
|
value={settings.order ? getOrderingDirection(settings.order) : 'Asc'}
|
|
size="sm"
|
|
className="w-full"
|
|
disabled={explorer.settingsStore.order === null}
|
|
onChange={(order) => {
|
|
if (explorer.settingsStore.order === null) return;
|
|
|
|
explorer.settingsStore.order = createOrdering(
|
|
orderingKey(explorer.settingsStore.order),
|
|
order
|
|
);
|
|
}}
|
|
>
|
|
{SortOrderSchema.options.map((o) => (
|
|
<SelectOption key={o.value} value={o.value}>
|
|
{o.value}
|
|
</SelectOption>
|
|
))}
|
|
</Select>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
<div>
|
|
<Subheading>{t('explorer')}</Subheading>
|
|
<div className="grid grid-cols-2 gap-y-1">
|
|
<RadixCheckbox
|
|
checked={layoutStore.showPathBar}
|
|
label={t('show_path_bar')}
|
|
name="showPathBar"
|
|
onCheckedChange={(value) => {
|
|
if (typeof value !== 'boolean') return;
|
|
explorerLayout.showPathBar = value;
|
|
}}
|
|
/>
|
|
|
|
{settings.layoutMode === 'grid' && (
|
|
<RadixCheckbox
|
|
checked={settings.showBytesInGridView}
|
|
label={t('show_object_size')}
|
|
name="showBytesInGridView"
|
|
onCheckedChange={(value) => {
|
|
if (typeof value !== 'boolean') return;
|
|
|
|
explorer.settingsStore.showBytesInGridView = value;
|
|
}}
|
|
/>
|
|
)}
|
|
|
|
<RadixCheckbox
|
|
checked={settings.showHiddenFiles}
|
|
label={t('show_hidden_files')}
|
|
name="showHiddenFiles"
|
|
onCheckedChange={(value) => {
|
|
if (typeof value !== 'boolean') return;
|
|
explorer.settingsStore.showHiddenFiles = value;
|
|
}}
|
|
/>
|
|
|
|
{settings.layoutMode === 'media' && (
|
|
<RadixCheckbox
|
|
checked={settings.mediaAspectSquare}
|
|
label={t('square_thumbnails')}
|
|
name="mediaAspectSquare"
|
|
onCheckedChange={(value) => {
|
|
if (typeof value !== 'boolean') return;
|
|
|
|
explorer.settingsStore.mediaAspectSquare = value;
|
|
}}
|
|
/>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
{settings.layoutMode === 'media' && (
|
|
<div>
|
|
<Subheading>{t('media_view_context')}</Subheading>
|
|
<Select
|
|
className="w-full"
|
|
value={
|
|
explorer.settingsStore.mediaViewWithDescendants
|
|
? 'withDescendants'
|
|
: 'withoutDescendants'
|
|
}
|
|
onChange={(value) => {
|
|
explorer.settingsStore.mediaViewWithDescendants =
|
|
value === 'withDescendants';
|
|
}}
|
|
>
|
|
{mediaViewContextActions.options.map((option) => (
|
|
<SelectOption key={option.value} value={option.value}>
|
|
{option.description}
|
|
</SelectOption>
|
|
))}
|
|
</Select>
|
|
</div>
|
|
)}
|
|
|
|
<div>
|
|
<Subheading>{t('double_click_action')}</Subheading>
|
|
<Select
|
|
className="w-full"
|
|
value={settings.openOnDoubleClick}
|
|
onChange={(value) => {
|
|
explorer.settingsStore.openOnDoubleClick = value;
|
|
}}
|
|
>
|
|
{doubleClickActions.options.map((option) => (
|
|
<SelectOption key={option.value} value={option.value}>
|
|
{option.description}
|
|
</SelectOption>
|
|
))}
|
|
</Select>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
const doubleClickActions = z.union([
|
|
z.literal('openFile').describe(i18n.t('open_file')),
|
|
z.literal('quickPreview').describe(i18n.t('quick_preview'))
|
|
]);
|
|
|
|
const mediaViewContextActions = z.union([
|
|
z.literal('withDescendants').describe(i18n.t('current_directory_with_descendants')),
|
|
z.literal('withoutDescendants').describe(i18n.t('current_directory'))
|
|
]);
|