mirror of
https://github.com/spacedriveapp/spacedrive
synced 2024-07-04 12:13:27 +00:00
Revert "remove fixed filters" (#2261)
* Revert "remove fixed filters (#2257)"
This reverts commit 1959226fb9
.
* bump 0.2.10
This commit is contained in:
parent
44c2854205
commit
5b40cefe37
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -8179,7 +8179,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sd-core"
|
name = "sd-core"
|
||||||
version = "0.2.9"
|
version = "0.2.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aovec",
|
"aovec",
|
||||||
"async-channel",
|
"async-channel",
|
||||||
|
@ -8336,7 +8336,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sd-desktop"
|
name = "sd-desktop"
|
||||||
version = "0.2.9"
|
version = "0.2.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"axum",
|
"axum",
|
||||||
"directories 5.0.1",
|
"directories 5.0.1",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "sd-desktop"
|
name = "sd-desktop"
|
||||||
version = "0.2.9"
|
version = "0.2.10"
|
||||||
description = "The universal file manager."
|
description = "The universal file manager."
|
||||||
authors = ["Spacedrive Technology Inc <support@spacedrive.com>"]
|
authors = ["Spacedrive Technology Inc <support@spacedrive.com>"]
|
||||||
default-run = "sd-desktop"
|
default-run = "sd-desktop"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "sd-core"
|
name = "sd-core"
|
||||||
version = "0.2.9"
|
version = "0.2.10"
|
||||||
description = "Virtual distributed filesystem engine that powers Spacedrive."
|
description = "Virtual distributed filesystem engine that powers Spacedrive."
|
||||||
authors = ["Spacedrive Technology Inc."]
|
authors = ["Spacedrive Technology Inc."]
|
||||||
rust-version = "1.75.0"
|
rust-version = "1.75.0"
|
||||||
|
|
|
@ -25,7 +25,19 @@ export function Component() {
|
||||||
|
|
||||||
const explorerSettingsSnapshot = explorerSettings.useSettingsSnapshot();
|
const explorerSettingsSnapshot = explorerSettings.useSettingsSnapshot();
|
||||||
|
|
||||||
const search = useSearch();
|
const fixedFilters = useMemo<SearchFilterArgs[]>(
|
||||||
|
() => [
|
||||||
|
// { object: { favorite: true } },
|
||||||
|
...(explorerSettingsSnapshot.layoutMode === 'media'
|
||||||
|
? [{ object: { kind: { in: [ObjectKindEnum.Image, ObjectKindEnum.Video] } } }]
|
||||||
|
: [])
|
||||||
|
],
|
||||||
|
[explorerSettingsSnapshot.layoutMode]
|
||||||
|
);
|
||||||
|
|
||||||
|
const search = useSearch({
|
||||||
|
fixedFilters
|
||||||
|
});
|
||||||
|
|
||||||
const objects = useObjectsExplorerQuery({
|
const objects = useObjectsExplorerQuery({
|
||||||
arg: {
|
arg: {
|
||||||
|
@ -33,10 +45,7 @@ export function Component() {
|
||||||
filters: [
|
filters: [
|
||||||
...search.allFilters,
|
...search.allFilters,
|
||||||
// TODO: Add filter to search options
|
// TODO: Add filter to search options
|
||||||
{ object: { favorite: true } },
|
{ object: { favorite: true } }
|
||||||
...(explorerSettingsSnapshot.layoutMode === 'media'
|
|
||||||
? [{ object: { kind: { in: [ObjectKindEnum.Image, ObjectKindEnum.Video] } } }]
|
|
||||||
: [])
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
order: explorerSettings.useSettingsSnapshot().order
|
order: explorerSettings.useSettingsSnapshot().order
|
||||||
|
|
|
@ -27,7 +27,7 @@ export function Component() {
|
||||||
|
|
||||||
// const explorerSettingsSnapshot = explorerSettings.useSettingsSnapshot();
|
// const explorerSettingsSnapshot = explorerSettings.useSettingsSnapshot();
|
||||||
|
|
||||||
// const filters = useMemo<SearchFilterArgs[]>(
|
// const fixedFilters = useMemo<SearchFilterArgs[]>(
|
||||||
// () => [
|
// () => [
|
||||||
// ...(explorerSettingsSnapshot.layoutMode === 'media'
|
// ...(explorerSettingsSnapshot.layoutMode === 'media'
|
||||||
// ? [{ object: { kind: { in: [ObjectKindEnum.Image, ObjectKindEnum.Video] } } }]
|
// ? [{ object: { kind: { in: [ObjectKindEnum.Image, ObjectKindEnum.Video] } } }]
|
||||||
|
@ -36,7 +36,7 @@ export function Component() {
|
||||||
// [explorerSettingsSnapshot.layoutMode]
|
// [explorerSettingsSnapshot.layoutMode]
|
||||||
// );
|
// );
|
||||||
|
|
||||||
const search = useSearch();
|
const search = useSearch({});
|
||||||
|
|
||||||
// const objects = useObjectsExplorerQuery({
|
// const objects = useObjectsExplorerQuery({
|
||||||
// arg: {
|
// arg: {
|
||||||
|
|
|
@ -71,9 +71,7 @@ const LocationExplorer = ({ location }: { location: Location; path?: string }) =
|
||||||
const { layoutMode, mediaViewWithDescendants, showHiddenFiles } =
|
const { layoutMode, mediaViewWithDescendants, showHiddenFiles } =
|
||||||
explorerSettings.useSettingsSnapshot();
|
explorerSettings.useSettingsSnapshot();
|
||||||
|
|
||||||
const search = useLocationSearch(location);
|
const search = useLocationSearch(explorerSettings, location);
|
||||||
|
|
||||||
const explorerSettingsSnapshot = explorerSettings.useSettingsSnapshot();
|
|
||||||
|
|
||||||
const paths = usePathsExplorerQuery({
|
const paths = usePathsExplorerQuery({
|
||||||
arg: {
|
arg: {
|
||||||
|
@ -86,15 +84,12 @@ const LocationExplorer = ({ location }: { location: Location; path?: string }) =
|
||||||
path: path ?? '',
|
path: path ?? '',
|
||||||
include_descendants:
|
include_descendants:
|
||||||
search.search !== '' ||
|
search.search !== '' ||
|
||||||
search.filters.length > 0 ||
|
search.dynamicFilters.length > 0 ||
|
||||||
(layoutMode === 'media' && mediaViewWithDescendants)
|
(layoutMode === 'media' && mediaViewWithDescendants)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
!showHiddenFiles && { filePath: { hidden: false } },
|
!showHiddenFiles && { filePath: { hidden: false } }
|
||||||
explorerSettingsSnapshot.layoutMode === 'media' && [
|
|
||||||
{ object: { kind: { in: [ObjectKindEnum.Image, ObjectKindEnum.Video] } } }
|
|
||||||
]
|
|
||||||
].filter(Boolean) as any,
|
].filter(Boolean) as any,
|
||||||
take
|
take
|
||||||
},
|
},
|
||||||
|
@ -273,32 +268,47 @@ function useLocationExplorerSettings(location: Location) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function useLocationSearch(location: Location) {
|
function useLocationSearch(
|
||||||
|
explorerSettings: UseExplorerSettings<FilePathOrder>,
|
||||||
|
location: Location
|
||||||
|
) {
|
||||||
const [searchParams, setSearchParams] = useRawSearchParams();
|
const [searchParams, setSearchParams] = useRawSearchParams();
|
||||||
|
const explorerSettingsSnapshot = explorerSettings.useSettingsSnapshot();
|
||||||
|
|
||||||
|
const fixedFilters = useMemo(
|
||||||
|
() => [
|
||||||
|
{ filePath: { locations: { in: [location.id] } } },
|
||||||
|
...(explorerSettingsSnapshot.layoutMode === 'media'
|
||||||
|
? [{ object: { kind: { in: [ObjectKindEnum.Image, ObjectKindEnum.Video] } } }]
|
||||||
|
: [])
|
||||||
|
],
|
||||||
|
[location.id, explorerSettingsSnapshot.layoutMode]
|
||||||
|
);
|
||||||
|
|
||||||
const filtersParam = searchParams.get('filters');
|
const filtersParam = searchParams.get('filters');
|
||||||
const filters = useMemo(() => JSON.parse(filtersParam ?? '[]'), [filtersParam]);
|
const dynamicFilters = useMemo(() => JSON.parse(filtersParam ?? '[]'), [filtersParam]);
|
||||||
|
|
||||||
const searchQueryParam = searchParams.get('search');
|
const searchQueryParam = searchParams.get('search');
|
||||||
|
|
||||||
const search = useSearch({
|
const search = useSearch({
|
||||||
open: !!searchQueryParam || filters.length > 0 || undefined,
|
open: !!searchQueryParam || dynamicFilters.length > 0 || undefined,
|
||||||
search: searchParams.get('search') ?? undefined,
|
search: searchParams.get('search') ?? undefined,
|
||||||
defaultFilters: [{ filePath: { locations: { in: [location.id] } } }],
|
fixedFilters,
|
||||||
filters: filters
|
dynamicFilters
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setSearchParams(
|
setSearchParams(
|
||||||
(p) => {
|
(p) => {
|
||||||
if (search.filters.length > 0) p.set('filters', JSON.stringify(search.filters));
|
if (search.dynamicFilters.length > 0)
|
||||||
|
p.set('filters', JSON.stringify(search.dynamicFilters));
|
||||||
else p.delete('filters');
|
else p.delete('filters');
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
},
|
},
|
||||||
{ replace: true }
|
{ replace: true }
|
||||||
);
|
);
|
||||||
}, [search.filters, setSearchParams]);
|
}, [search.dynamicFilters, setSearchParams]);
|
||||||
|
|
||||||
const searchQuery = search.search;
|
const searchQuery = search.search;
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,19 @@ export function Component() {
|
||||||
|
|
||||||
const explorerSettingsSnapshot = explorerSettings.useSettingsSnapshot();
|
const explorerSettingsSnapshot = explorerSettings.useSettingsSnapshot();
|
||||||
|
|
||||||
const search = useSearch();
|
const fixedFilters = useMemo<SearchFilterArgs[]>(
|
||||||
|
() => [
|
||||||
|
// { object: { dateAccessed: { from: new Date(0).toISOString() } } },
|
||||||
|
...(explorerSettingsSnapshot.layoutMode === 'media'
|
||||||
|
? [{ object: { kind: { in: [ObjectKindEnum.Image, ObjectKindEnum.Video] } } }]
|
||||||
|
: [])
|
||||||
|
],
|
||||||
|
[explorerSettingsSnapshot.layoutMode]
|
||||||
|
);
|
||||||
|
|
||||||
|
const search = useSearch({
|
||||||
|
fixedFilters
|
||||||
|
});
|
||||||
|
|
||||||
const objects = useObjectsExplorerQuery({
|
const objects = useObjectsExplorerQuery({
|
||||||
arg: {
|
arg: {
|
||||||
|
@ -33,10 +45,7 @@ export function Component() {
|
||||||
filters: [
|
filters: [
|
||||||
...search.allFilters,
|
...search.allFilters,
|
||||||
// TODO: Add fil ter to search options
|
// TODO: Add fil ter to search options
|
||||||
{ object: { dateAccessed: { from: new Date(0).toISOString() } } },
|
{ object: { dateAccessed: { from: new Date(0).toISOString() } } }
|
||||||
...(explorerSettingsSnapshot.layoutMode === 'media'
|
|
||||||
? [{ object: { kind: { in: [ObjectKindEnum.Image, ObjectKindEnum.Video] } } }]
|
|
||||||
: [])
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
order: explorerSettings.useSettingsSnapshot().order
|
order: explorerSettings.useSettingsSnapshot().order
|
||||||
|
|
|
@ -46,14 +46,14 @@ export const Component = () => {
|
||||||
|
|
||||||
const rawFilters = savedSearch.data?.filters;
|
const rawFilters = savedSearch.data?.filters;
|
||||||
|
|
||||||
const filters = useMemo(() => {
|
const dynamicFilters = useMemo(() => {
|
||||||
if (rawFilters) return JSON.parse(rawFilters) as SearchFilterArgs[];
|
if (rawFilters) return JSON.parse(rawFilters) as SearchFilterArgs[];
|
||||||
}, [rawFilters]);
|
}, [rawFilters]);
|
||||||
|
|
||||||
const search = useSearch({
|
const search = useSearch({
|
||||||
open: true,
|
open: true,
|
||||||
search: savedSearch.data?.search ?? undefined,
|
search: savedSearch.data?.search ?? undefined,
|
||||||
filters: filters
|
dynamicFilters
|
||||||
});
|
});
|
||||||
|
|
||||||
const paths = usePathsExplorerQuery({
|
const paths = usePathsExplorerQuery({
|
||||||
|
@ -85,7 +85,7 @@ export const Component = () => {
|
||||||
>
|
>
|
||||||
<hr className="w-full border-t border-sidebar-divider bg-sidebar-divider" />
|
<hr className="w-full border-t border-sidebar-divider bg-sidebar-divider" />
|
||||||
<SearchOptions>
|
<SearchOptions>
|
||||||
{(search.filters !== filters ||
|
{(search.dynamicFilters !== dynamicFilters ||
|
||||||
search.search !== savedSearch.data?.search) && (
|
search.search !== savedSearch.data?.search) && (
|
||||||
<SaveButton searchId={id} />
|
<SaveButton searchId={id} />
|
||||||
)}
|
)}
|
||||||
|
@ -123,7 +123,7 @@ function SaveButton({ searchId }: { searchId: number }) {
|
||||||
updateSavedSearch.mutate([
|
updateSavedSearch.mutate([
|
||||||
searchId,
|
searchId,
|
||||||
{
|
{
|
||||||
filters: JSON.stringify(search.filters),
|
filters: JSON.stringify(search.dynamicFilters),
|
||||||
search: search.search
|
search: search.search
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -55,11 +55,13 @@ export const AppliedFilters = ({ allowRemove = true }: { allowRemove?: boolean }
|
||||||
onDelete={
|
onDelete={
|
||||||
removalIndex !== null && allowRemove
|
removalIndex !== null && allowRemove
|
||||||
? () => {
|
? () => {
|
||||||
search.updateFilters((dyanmicFilters) => {
|
search.updateDynamicFilters(
|
||||||
dyanmicFilters.splice(removalIndex, 1);
|
(dyanmicFilters) => {
|
||||||
|
dyanmicFilters.splice(removalIndex, 1);
|
||||||
|
|
||||||
return dyanmicFilters;
|
return dyanmicFilters;
|
||||||
});
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,25 +71,28 @@ export function useToggleOptionSelected({ search }: { search: UseSearch }) {
|
||||||
option: FilterOption;
|
option: FilterOption;
|
||||||
select: boolean;
|
select: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
search.updateFilters((filters) => {
|
search.updateDynamicFilters((dynamicFilters) => {
|
||||||
const rawArg = filters.find((arg) => filter.extract(arg));
|
const key = getKey({ ...option, type: filter.name });
|
||||||
|
if (search.fixedFiltersKeys?.has(key)) return dynamicFilters;
|
||||||
|
|
||||||
|
const rawArg = dynamicFilters.find((arg) => filter.extract(arg));
|
||||||
|
|
||||||
if (!rawArg) {
|
if (!rawArg) {
|
||||||
const arg = filter.create(option.value);
|
const arg = filter.create(option.value);
|
||||||
filters.push(arg);
|
dynamicFilters.push(arg);
|
||||||
} else {
|
} else {
|
||||||
const rawArgIndex = filters.findIndex((arg) => filter.extract(arg))!;
|
const rawArgIndex = dynamicFilters.findIndex((arg) => filter.extract(arg))!;
|
||||||
|
|
||||||
const arg = filter.extract(rawArg)!;
|
const arg = filter.extract(rawArg)!;
|
||||||
|
|
||||||
if (select) {
|
if (select) {
|
||||||
if (rawArg) filter.applyAdd(arg, option);
|
if (rawArg) filter.applyAdd(arg, option);
|
||||||
} else {
|
} else {
|
||||||
if (!filter.applyRemove(arg, option)) filters.splice(rawArgIndex, 1);
|
if (!filter.applyRemove(arg, option)) dynamicFilters.splice(rawArgIndex, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return filters;
|
return dynamicFilters;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -156,14 +159,14 @@ const FilterOptionText = ({ filter, search }: { filter: SearchFilterCRUD; search
|
||||||
className="flex gap-1.5"
|
className="flex gap-1.5"
|
||||||
onSubmit={(e) => {
|
onSubmit={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
search.updateFilters((filters) => {
|
search.updateDynamicFilters((dynamicFilters) => {
|
||||||
if (allFiltersKeys.has(key)) return filters;
|
if (allFiltersKeys.has(key)) return dynamicFilters;
|
||||||
|
|
||||||
const arg = filter.create(value);
|
const arg = filter.create(value);
|
||||||
filters.push(arg);
|
dynamicFilters.push(arg);
|
||||||
setValue('');
|
setValue('');
|
||||||
|
|
||||||
return filters;
|
return dynamicFilters;
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -188,7 +191,7 @@ const FilterOptionBoolean = ({
|
||||||
filter: SearchFilterCRUD;
|
filter: SearchFilterCRUD;
|
||||||
search: UseSearch;
|
search: UseSearch;
|
||||||
}) => {
|
}) => {
|
||||||
const { allFiltersKeys } = search;
|
const { fixedFiltersKeys, allFiltersKeys } = search;
|
||||||
|
|
||||||
const key = getKey({
|
const key = getKey({
|
||||||
type: filter.name,
|
type: filter.name,
|
||||||
|
@ -201,17 +204,19 @@ const FilterOptionBoolean = ({
|
||||||
icon={filter.icon}
|
icon={filter.icon}
|
||||||
selected={allFiltersKeys?.has(key)}
|
selected={allFiltersKeys?.has(key)}
|
||||||
setSelected={() => {
|
setSelected={() => {
|
||||||
search.updateFilters((filters) => {
|
search.updateDynamicFilters((dynamicFilters) => {
|
||||||
const index = filters.findIndex((f) => filter.extract(f) !== undefined);
|
if (fixedFiltersKeys?.has(key)) return dynamicFilters;
|
||||||
|
|
||||||
|
const index = dynamicFilters.findIndex((f) => filter.extract(f) !== undefined);
|
||||||
|
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
filters.splice(index, 1);
|
dynamicFilters.splice(index, 1);
|
||||||
} else {
|
} else {
|
||||||
const arg = filter.create(true);
|
const arg = filter.create(true);
|
||||||
filters.push(arg);
|
dynamicFilters.push(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
return filters;
|
return dynamicFilters;
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
|
@ -81,7 +81,6 @@ export default ({ redirectToSearch }: Props) => {
|
||||||
|
|
||||||
function clearValue() {
|
function clearValue() {
|
||||||
search.setSearch('');
|
search.setSearch('');
|
||||||
search.setFilters([]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -100,10 +99,7 @@ export default ({ redirectToSearch }: Props) => {
|
||||||
search.setSearchBarFocused(false);
|
search.setSearchBarFocused(false);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onFocus={() => {
|
onFocus={() => search.setSearchBarFocused(true)}
|
||||||
search.setSearchBarFocused(true);
|
|
||||||
if (search.defaultFilters) search.setFilters(search.defaultFilters);
|
|
||||||
}}
|
|
||||||
right={
|
right={
|
||||||
<div className="pointer-events-none flex h-7 items-center space-x-1 opacity-70 group-focus-within:hidden">
|
<div className="pointer-events-none flex h-7 items-center space-x-1 opacity-70 group-focus-within:hidden">
|
||||||
{
|
{
|
||||||
|
|
|
@ -124,7 +124,9 @@ export const SearchOptions = ({
|
||||||
|
|
||||||
{children ?? (
|
{children ?? (
|
||||||
<>
|
<>
|
||||||
{(search.filters.length > 0 || search.search !== '') && <SaveSearchButton />}
|
{(search.dynamicFilters.length > 0 || search.search !== '') && (
|
||||||
|
<SaveSearchButton />
|
||||||
|
)}
|
||||||
|
|
||||||
<EscapeButton />
|
<EscapeButton />
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -27,19 +27,13 @@ export function Component() {
|
||||||
}, []),
|
}, []),
|
||||||
orderingKeys: objectOrderingKeysSchema
|
orderingKeys: objectOrderingKeysSchema
|
||||||
});
|
});
|
||||||
const explorerSettingsSnapshot = explorerSettings.useSettingsSnapshot();
|
|
||||||
|
|
||||||
const search = useSearchWithFilters();
|
const search = useSearchWithFilters(explorerSettings);
|
||||||
|
|
||||||
const objects = useObjectsExplorerQuery({
|
const objects = useObjectsExplorerQuery({
|
||||||
arg: {
|
arg: {
|
||||||
take: 100,
|
take: 100,
|
||||||
filters: [
|
filters: search.allFilters
|
||||||
...search.allFilters,
|
|
||||||
...(explorerSettingsSnapshot.layoutMode === 'media'
|
|
||||||
? [{ object: { kind: { in: [ObjectKindEnum.Image, ObjectKindEnum.Video] } } }]
|
|
||||||
: [])
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
order: explorerSettings.useSettingsSnapshot().order
|
order: explorerSettings.useSettingsSnapshot().order
|
||||||
});
|
});
|
||||||
|
@ -83,31 +77,43 @@ export function Component() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function useSearchWithFilters() {
|
function useSearchWithFilters(explorerSettings: UseExplorerSettings<ObjectOrder>) {
|
||||||
const [searchParams, setSearchParams] = useRawSearchParams();
|
const [searchParams, setSearchParams] = useRawSearchParams();
|
||||||
|
const explorerSettingsSnapshot = explorerSettings.useSettingsSnapshot();
|
||||||
|
|
||||||
|
const fixedFilters = useMemo(
|
||||||
|
() => [
|
||||||
|
...(explorerSettingsSnapshot.layoutMode === 'media'
|
||||||
|
? [{ object: { kind: { in: [ObjectKindEnum.Image, ObjectKindEnum.Video] } } }]
|
||||||
|
: [])
|
||||||
|
],
|
||||||
|
[explorerSettingsSnapshot.layoutMode]
|
||||||
|
);
|
||||||
|
|
||||||
const filtersParam = searchParams.get('filters');
|
const filtersParam = searchParams.get('filters');
|
||||||
const filters = useMemo(() => JSON.parse(filtersParam ?? '[]'), [filtersParam]);
|
const dynamicFilters = useMemo(() => JSON.parse(filtersParam ?? '[]'), [filtersParam]);
|
||||||
|
|
||||||
const searchQueryParam = searchParams.get('search');
|
const searchQueryParam = searchParams.get('search');
|
||||||
|
|
||||||
const search = useSearch({
|
const search = useSearch({
|
||||||
open: !!searchQueryParam || filters.length > 0 || undefined,
|
open: !!searchQueryParam || dynamicFilters.length > 0 || undefined,
|
||||||
search: searchParams.get('search') ?? undefined,
|
search: searchParams.get('search') ?? undefined,
|
||||||
filters
|
fixedFilters,
|
||||||
|
dynamicFilters
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setSearchParams(
|
setSearchParams(
|
||||||
(p) => {
|
(p) => {
|
||||||
if (search.filters.length > 0) p.set('filters', JSON.stringify(search.filters));
|
if (search.dynamicFilters.length > 0)
|
||||||
|
p.set('filters', JSON.stringify(search.dynamicFilters));
|
||||||
else p.delete('filters');
|
else p.delete('filters');
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
},
|
},
|
||||||
{ replace: true }
|
{ replace: true }
|
||||||
);
|
);
|
||||||
}, [search.filters, setSearchParams]);
|
}, [search.dynamicFilters, setSearchParams]);
|
||||||
|
|
||||||
const searchQuery = search.search;
|
const searchQuery = search.search;
|
||||||
|
|
||||||
|
|
|
@ -9,12 +9,15 @@ import { argsToOptions, getKey, useSearchStore } from './store';
|
||||||
export interface UseSearchProps {
|
export interface UseSearchProps {
|
||||||
open?: boolean;
|
open?: boolean;
|
||||||
search?: string;
|
search?: string;
|
||||||
|
/**
|
||||||
|
* Filters that cannot be removed
|
||||||
|
*/
|
||||||
|
fixedFilters?: SearchFilterArgs[];
|
||||||
/**
|
/**
|
||||||
* Filters that can be removed.
|
* Filters that can be removed.
|
||||||
* When this value changes dynamic filters stored internally will reset.
|
* When this value changes dynamic filters stored internally will reset.
|
||||||
*/
|
*/
|
||||||
filters?: SearchFilterArgs[];
|
dynamicFilters?: SearchFilterArgs[];
|
||||||
defaultFilters?: SearchFilterArgs[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useSearch(props?: UseSearchProps) {
|
export function useSearch(props?: UseSearchProps) {
|
||||||
|
@ -22,22 +25,18 @@ export function useSearch(props?: UseSearchProps) {
|
||||||
|
|
||||||
const searchState = useSearchStore();
|
const searchState = useSearchStore();
|
||||||
|
|
||||||
const [filters, setFilters] = useState(props?.filters ?? []);
|
// Filters that can't be removed
|
||||||
const [filtersFromProps, setFiltersFromProps] = useState(props?.filters);
|
|
||||||
|
|
||||||
if (filtersFromProps !== props?.filters) {
|
const fixedFilters = useMemo(() => props?.fixedFilters ?? [], [props?.fixedFilters]);
|
||||||
setFiltersFromProps(props?.filters);
|
|
||||||
setFilters(props?.filters ?? []);
|
|
||||||
}
|
|
||||||
|
|
||||||
const filtersAsOptions = useMemo(
|
const fixedFiltersAsOptions = useMemo(
|
||||||
() => argsToOptions(filters, searchState.filterOptions),
|
() => argsToOptions(fixedFilters, searchState.filterOptions),
|
||||||
[filters, searchState.filterOptions]
|
[fixedFilters, searchState.filterOptions]
|
||||||
);
|
);
|
||||||
|
|
||||||
const filtersKeys: Set<string> = useMemo(() => {
|
const fixedFiltersKeys: Set<string> = useMemo(() => {
|
||||||
return new Set(
|
return new Set(
|
||||||
filtersAsOptions.map(({ arg, filter }) =>
|
fixedFiltersAsOptions.map(({ arg, filter }) =>
|
||||||
getKey({
|
getKey({
|
||||||
type: filter.name,
|
type: filter.name,
|
||||||
name: arg.name,
|
name: arg.name,
|
||||||
|
@ -45,31 +44,79 @@ export function useSearch(props?: UseSearchProps) {
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}, [filtersAsOptions]);
|
}, [fixedFiltersAsOptions]);
|
||||||
|
|
||||||
const updateFilters = useCallback(
|
// Filters that can be removed
|
||||||
|
|
||||||
|
const [dynamicFilters, setDynamicFilters] = useState(props?.dynamicFilters ?? []);
|
||||||
|
const [dynamicFiltersFromProps, setDynamicFiltersFromProps] = useState(props?.dynamicFilters);
|
||||||
|
|
||||||
|
if (dynamicFiltersFromProps !== props?.dynamicFilters) {
|
||||||
|
setDynamicFiltersFromProps(props?.dynamicFilters);
|
||||||
|
setDynamicFilters(props?.dynamicFilters ?? []);
|
||||||
|
}
|
||||||
|
|
||||||
|
const dynamicFiltersAsOptions = useMemo(
|
||||||
|
() => argsToOptions(dynamicFilters, searchState.filterOptions),
|
||||||
|
[dynamicFilters, searchState.filterOptions]
|
||||||
|
);
|
||||||
|
|
||||||
|
const dynamicFiltersKeys: Set<string> = useMemo(() => {
|
||||||
|
return new Set(
|
||||||
|
dynamicFiltersAsOptions.map(({ arg, filter }) =>
|
||||||
|
getKey({
|
||||||
|
type: filter.name,
|
||||||
|
name: arg.name,
|
||||||
|
value: arg.value
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}, [dynamicFiltersAsOptions]);
|
||||||
|
|
||||||
|
const updateDynamicFilters = useCallback(
|
||||||
(cb: (args: SearchFilterArgs[]) => SearchFilterArgs[]) =>
|
(cb: (args: SearchFilterArgs[]) => SearchFilterArgs[]) =>
|
||||||
setFilters((filters) => produce(filters, cb)),
|
setDynamicFilters((filters) => produce(filters, cb)),
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
// Merging of filters that should be ORed
|
// Merging of filters that should be ORed
|
||||||
|
|
||||||
const mergedFilters = useMemo(() => {
|
const mergedFilters = useMemo(() => {
|
||||||
const value: { arg: SearchFilterArgs; removalIndex: number | null }[] = [];
|
const value: { arg: SearchFilterArgs; removalIndex: number | null }[] = fixedFilters.map(
|
||||||
|
(arg) => ({
|
||||||
|
arg,
|
||||||
|
removalIndex: null
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
for (const [index, arg] of filters.entries()) {
|
for (const [index, arg] of dynamicFilters.entries()) {
|
||||||
const filter = filterRegistry.find((f) => f.extract(arg));
|
const filter = filterRegistry.find((f) => f.extract(arg));
|
||||||
if (!filter) continue;
|
if (!filter) continue;
|
||||||
|
|
||||||
value.push({
|
const fixedEquivalentIndex = fixedFilters.findIndex(
|
||||||
arg,
|
(a) => filter.extract(a) !== undefined
|
||||||
removalIndex: index
|
);
|
||||||
});
|
|
||||||
|
if (fixedEquivalentIndex !== -1) {
|
||||||
|
const merged = filter.merge(
|
||||||
|
filter.extract(fixedFilters[fixedEquivalentIndex]!)! as any,
|
||||||
|
filter.extract(arg)! as any
|
||||||
|
);
|
||||||
|
|
||||||
|
value[fixedEquivalentIndex] = {
|
||||||
|
arg: filter.create(merged),
|
||||||
|
removalIndex: fixedEquivalentIndex
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
value.push({
|
||||||
|
arg,
|
||||||
|
removalIndex: index
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}, [filters]);
|
}, [fixedFilters, dynamicFilters]);
|
||||||
|
|
||||||
// Filters generated from the search query
|
// Filters generated from the search query
|
||||||
|
|
||||||
|
@ -120,16 +167,17 @@ export function useSearch(props?: UseSearchProps) {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
open: props?.open || searchBarFocused,
|
open: props?.open || searchBarFocused,
|
||||||
|
fixedFilters,
|
||||||
|
fixedFiltersKeys,
|
||||||
search,
|
search,
|
||||||
rawSearch,
|
rawSearch,
|
||||||
setSearch: setRawSearch,
|
setSearch: setRawSearch,
|
||||||
searchBarFocused,
|
searchBarFocused,
|
||||||
setSearchBarFocused,
|
setSearchBarFocused,
|
||||||
defaultFilters: props?.defaultFilters,
|
dynamicFilters,
|
||||||
filters,
|
setDynamicFilters,
|
||||||
setFilters,
|
updateDynamicFilters,
|
||||||
updateFilters,
|
dynamicFiltersKeys,
|
||||||
filtersKeys,
|
|
||||||
mergedFilters,
|
mergedFilters,
|
||||||
allFilters,
|
allFilters,
|
||||||
allFiltersKeys
|
allFiltersKeys
|
||||||
|
|
|
@ -82,13 +82,13 @@ function EditForm({ savedSearch, onDelete }: { savedSearch: SavedSearch; onDelet
|
||||||
updateSavedSearch.mutate([savedSearch.id, { name: data.name ?? '' }]);
|
updateSavedSearch.mutate([savedSearch.id, { name: data.name ?? '' }]);
|
||||||
});
|
});
|
||||||
|
|
||||||
const filters = useMemo(() => {
|
const fixedFilters = useMemo(() => {
|
||||||
if (savedSearch.filters === null) return [];
|
if (savedSearch.filters === null) return [];
|
||||||
|
|
||||||
return JSON.parse(savedSearch.filters) as SearchFilterArgs[];
|
return JSON.parse(savedSearch.filters) as SearchFilterArgs[];
|
||||||
}, [savedSearch.filters]);
|
}, [savedSearch.filters]);
|
||||||
|
|
||||||
const search = useSearch({ search: savedSearch.search ?? undefined, filters });
|
const search = useSearch({ search: savedSearch.search ?? undefined, fixedFilters });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form form={form}>
|
<Form form={form}>
|
||||||
|
|
|
@ -38,20 +38,22 @@ export function Component() {
|
||||||
|
|
||||||
const explorerSettingsSnapshot = explorerSettings.useSettingsSnapshot();
|
const explorerSettingsSnapshot = explorerSettings.useSettingsSnapshot();
|
||||||
|
|
||||||
|
const fixedFilters = useMemo(
|
||||||
|
() => [
|
||||||
|
{ object: { tags: { in: [tag!.id] } } },
|
||||||
|
...(explorerSettingsSnapshot.layoutMode === 'media'
|
||||||
|
? [{ object: { kind: { in: [ObjectKindEnum.Image, ObjectKindEnum.Video] } } }]
|
||||||
|
: [])
|
||||||
|
],
|
||||||
|
[tag, explorerSettingsSnapshot.layoutMode]
|
||||||
|
);
|
||||||
|
|
||||||
const search = useSearch({
|
const search = useSearch({
|
||||||
defaultFilters: [{ object: { tags: { in: [tag!.id] } } }]
|
fixedFilters
|
||||||
});
|
});
|
||||||
|
|
||||||
const objects = useObjectsExplorerQuery({
|
const objects = useObjectsExplorerQuery({
|
||||||
arg: {
|
arg: { take: 100, filters: search.allFilters },
|
||||||
take: 100,
|
|
||||||
filters: [
|
|
||||||
...search.allFilters,
|
|
||||||
...(explorerSettingsSnapshot.layoutMode === 'media'
|
|
||||||
? [{ object: { kind: { in: [ObjectKindEnum.Image, ObjectKindEnum.Video] } } }]
|
|
||||||
: [])
|
|
||||||
]
|
|
||||||
},
|
|
||||||
order: explorerSettings.useSettingsSnapshot().order
|
order: explorerSettings.useSettingsSnapshot().order
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue