mirror of
https://github.com/spacedriveapp/spacedrive
synced 2024-07-04 13:23:28 +00:00
[ENG-885] Move online locations to lib store (#1074)
* Enable trace logging for invalidate query * Fixing quick rescan on explorer And annotating wrong quick rescan usage on top bar reload button * Move online locations to lib store * Fix topbar reload path * fix mobile * Remove unused imports + format - Adjust `arraysEqual` arguments type --------- Co-authored-by: Ericson Soares <ericson.ds999@gmail.com> Co-authored-by: Utku Bakir <74243531+utkubakir@users.noreply.github.com> Co-authored-by: Vítor Vasconcellos <vasconcellos.dev@gmail.com>
This commit is contained in:
parent
f83f29c720
commit
9d800eec31
4
.vscode/launch.json
vendored
4
.vscode/launch.json
vendored
|
@ -16,6 +16,10 @@
|
|||
],
|
||||
"problemMatcher": "$rustc"
|
||||
},
|
||||
"env": {
|
||||
"RUST_BACKTRACE": "short"
|
||||
// "RUST_LOG": "sd_core::invalidate-query=trace"
|
||||
},
|
||||
"sourceLanguages": ["rust"],
|
||||
"preLaunchTask": "ui:dev"
|
||||
},
|
||||
|
|
1
.vscode/tasks.json
vendored
1
.vscode/tasks.json
vendored
|
@ -53,6 +53,7 @@
|
|||
],
|
||||
"env": {
|
||||
"RUST_BACKTRACE": "short"
|
||||
// "RUST_LOG": "sd_core::invalidate-query=trace"
|
||||
},
|
||||
"problemMatcher": ["$rustc"],
|
||||
"group": "build",
|
||||
|
|
|
@ -73,7 +73,9 @@ function LocationItem({ location, index, navigation }: LocationItemProps) {
|
|||
{/* Full Re-scan IS too much here */}
|
||||
<Pressable
|
||||
style={tw`items-center justify-center rounded-md border border-app-line bg-app-button px-3 py-1.5 shadow-sm`}
|
||||
onPress={() => fullRescan.mutate({ location_id: location.id, reidentify_objects: true })}
|
||||
onPress={() =>
|
||||
fullRescan.mutate({ location_id: location.id, reidentify_objects: true })
|
||||
}
|
||||
>
|
||||
<Repeat size={18} color="white" />
|
||||
</Pressable>
|
||||
|
@ -97,7 +99,7 @@ function LocationItem({ location, index, navigation }: LocationItemProps) {
|
|||
<View
|
||||
style={twStyle(
|
||||
'absolute bottom-0.5 right-0 h-2 w-2 rounded-full',
|
||||
onlineLocations?.some((l) => arraysEqual(location.pub_id, l))
|
||||
onlineLocations.some((l) => arraysEqual(location.pub_id, l))
|
||||
? 'bg-green-500'
|
||||
: 'bg-red-500'
|
||||
)}
|
||||
|
|
|
@ -136,6 +136,8 @@ macro_rules! invalidate_query {
|
|||
}
|
||||
}
|
||||
|
||||
::tracing::trace!(target: "sd_core::invalidate-query", "invalidate_query!(\"{}\") at {}", $key, concat!(file!(), ":", line!()));
|
||||
|
||||
// The error are ignored here because they aren't mission critical. If they fail the UI might be outdated for a bit.
|
||||
ctx.emit(crate::api::CoreEvent::InvalidateOperation(
|
||||
crate::api::utils::InvalidateOperationEvent::dangerously_create($key, serde_json::Value::Null, None)
|
||||
|
@ -165,6 +167,8 @@ macro_rules! invalidate_query {
|
|||
}
|
||||
}
|
||||
|
||||
::tracing::trace!(target: "sd_core::invalidate-query", "invalidate_query!(\"{}\") at {}", $key, concat!(file!(), ":", line!()));
|
||||
|
||||
// The error are ignored here because they aren't mission critical. If they fail the UI might be outdated for a bit.
|
||||
let _ = serde_json::to_value($arg)
|
||||
.map(|v|
|
||||
|
@ -203,6 +207,8 @@ macro_rules! invalidate_query {
|
|||
}
|
||||
}
|
||||
|
||||
::tracing::trace!(target: "sd_core::invalidate-query", "invalidate_query!(\"{}\") at {}", $key, concat!(file!(), ":", line!()));
|
||||
|
||||
// The error are ignored here because they aren't mission critical. If they fail the UI might be outdated for a bit.
|
||||
let _ = serde_json::to_value($arg)
|
||||
.and_then(|arg|
|
||||
|
|
|
@ -119,11 +119,6 @@ impl Node {
|
|||
}
|
||||
|
||||
pub fn init_logger(data_dir: impl AsRef<Path>) -> WorkerGuard {
|
||||
let log_filter = match cfg!(debug_assertions) {
|
||||
true => tracing::Level::DEBUG,
|
||||
false => tracing::Level::INFO,
|
||||
};
|
||||
|
||||
let (logfile, guard) = NonBlocking::new(
|
||||
RollingFileAppender::builder()
|
||||
.filename_prefix("sd.log")
|
||||
|
@ -137,8 +132,8 @@ impl Node {
|
|||
.with(fmt::Subscriber::new().with_ansi(false).with_writer(logfile))
|
||||
.with(
|
||||
fmt::Subscriber::new()
|
||||
.with_writer(std::io::stdout.with_max_level(log_filter))
|
||||
.with_filter(
|
||||
.with_writer(std::io::stdout)
|
||||
.with_filter(if cfg!(debug_assertions) {
|
||||
EnvFilter::from_default_env()
|
||||
.add_directive(
|
||||
"warn".parse().expect("Error invalid tracing directive!"),
|
||||
|
@ -177,8 +172,10 @@ impl Node {
|
|||
"rspc=debug"
|
||||
.parse()
|
||||
.expect("Error invalid tracing directive!"),
|
||||
),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
EnvFilter::from("info")
|
||||
}),
|
||||
);
|
||||
|
||||
tracing::collect::set_global_default(collector)
|
||||
|
|
|
@ -16,6 +16,7 @@ import TopBarOptions, { TOP_BAR_ICON_STYLE, ToolOption } from '../TopBar/TopBarO
|
|||
import { useExplorerContext } from './Context';
|
||||
import OptionsPanel from './OptionsPanel';
|
||||
import { getExplorerStore, useExplorerStore } from './store';
|
||||
import { useExplorerSearchParams } from './util';
|
||||
|
||||
export const useExplorerTopBarOptions = () => {
|
||||
const explorerStore = useExplorerStore();
|
||||
|
@ -84,6 +85,8 @@ export const useExplorerTopBarOptions = () => {
|
|||
|
||||
const { parent } = useExplorerContext();
|
||||
|
||||
const [{ path }] = useExplorerSearchParams();
|
||||
|
||||
const toolOptions = [
|
||||
{
|
||||
toolTipLabel: 'Key Manager',
|
||||
|
@ -114,7 +117,7 @@ export const useExplorerTopBarOptions = () => {
|
|||
'locations.quickRescan',
|
||||
{
|
||||
location_id: parent.location.id,
|
||||
sub_path: ''
|
||||
sub_path: path ?? ''
|
||||
}
|
||||
],
|
||||
{ onData() {} }
|
||||
|
|
|
@ -3,10 +3,8 @@ import clsx from 'clsx';
|
|||
import { useEffect, useState } from 'react';
|
||||
import { Link, NavLink } from 'react-router-dom';
|
||||
import {
|
||||
LibraryContextProvider,
|
||||
arraysEqual,
|
||||
useBridgeQuery,
|
||||
useClientContext,
|
||||
useDebugState,
|
||||
useFeatureFlag,
|
||||
useLibraryQuery,
|
||||
|
@ -14,8 +12,7 @@ import {
|
|||
} from '@sd/client';
|
||||
import { Button, Tooltip } from '@sd/ui';
|
||||
import { AddLocationButton } from '~/app/$libraryId/settings/library/locations/AddLocationButton';
|
||||
import { Folder } from '~/components/Folder';
|
||||
import { SubtleButton } from '~/components/SubtleButton';
|
||||
import { Folder, SubtleButton } from '~/components';
|
||||
import SidebarLink from './Link';
|
||||
import LocationsContextMenu from './LocationsContextMenu';
|
||||
import Section from './Section';
|
||||
|
@ -128,10 +125,8 @@ export const LibrarySection = () => {
|
|||
}
|
||||
>
|
||||
{locations?.map((location) => {
|
||||
const online =
|
||||
onlineLocations?.some((l) => arraysEqual(location.pub_id, l)) || false;
|
||||
const online = onlineLocations.some((l) => arraysEqual(location.pub_id, l));
|
||||
|
||||
// const online = onlineLocations?.some((l) => arraysEqual(location.pub_id, l));
|
||||
return (
|
||||
<LocationsContextMenu key={location.id} locationId={location.id}>
|
||||
<SidebarLink
|
||||
|
|
|
@ -27,7 +27,7 @@ export const Component = () => {
|
|||
[
|
||||
'locations.quickRescan',
|
||||
{
|
||||
sub_path: location.data?.path ?? '',
|
||||
sub_path: path ?? '',
|
||||
location_id: locationId
|
||||
}
|
||||
],
|
||||
|
|
|
@ -4,7 +4,7 @@ import { useState } from 'react';
|
|||
import { useNavigate } from 'react-router';
|
||||
import { Location, Node, arraysEqual, useLibraryMutation, useOnlineLocations } from '@sd/client';
|
||||
import { Button, Card, Tooltip, dialogManager } from '@sd/ui';
|
||||
import { Folder } from '~/components/Folder';
|
||||
import { Folder } from '~/components';
|
||||
import { useIsDark } from '~/hooks';
|
||||
import DeleteDialog from './DeleteDialog';
|
||||
|
||||
|
@ -23,7 +23,7 @@ export default ({ location }: Props) => {
|
|||
|
||||
if (hide) return <></>;
|
||||
|
||||
const online = onlineLocations?.some((l) => arraysEqual(location.pub_id, l)) || false;
|
||||
const online = onlineLocations.some((l) => arraysEqual(location.pub_id, l));
|
||||
|
||||
return (
|
||||
<Card
|
||||
|
|
|
@ -2,6 +2,7 @@ export * from './useClientContext';
|
|||
export * from './useDebugState';
|
||||
export * from './useFeatureFlag';
|
||||
export * from './useLibraryContext';
|
||||
export * from './useLibraryStore';
|
||||
export * from './useOnboardingStore';
|
||||
export * from './useP2PEvents';
|
||||
export * from './usePlausible';
|
||||
|
|
|
@ -2,11 +2,11 @@ import { PropsWithChildren, createContext, useContext, useState } from 'react';
|
|||
import { LibraryConfigWrapped } from '../core';
|
||||
import { useBridgeSubscription } from '../rspc';
|
||||
import { ClientContext, useClientContext } from './useClientContext';
|
||||
import { getLibraryStore, useLibraryStore } from './useLibraryStore';
|
||||
|
||||
export interface LibraryContext {
|
||||
library: LibraryConfigWrapped;
|
||||
libraries: ClientContext['libraries'];
|
||||
onlineLocations: number[][] | null;
|
||||
}
|
||||
|
||||
const LibraryContext = createContext<LibraryContext>(null!);
|
||||
|
@ -17,18 +17,17 @@ interface LibraryContextProviderProps extends PropsWithChildren {
|
|||
|
||||
export const LibraryContextProvider = ({ children, library }: LibraryContextProviderProps) => {
|
||||
const { libraries } = useClientContext();
|
||||
const [onlineLocations, setOnlineLocations] = useState<number[][] | null>(null);
|
||||
|
||||
// We put this into context because each hook creates a new subscription which means we get duplicate events from the backend if we don't do this
|
||||
// TODO: This should probs be a library subscription - https://linear.app/spacedriveapp/issue/ENG-724/locationsonline-should-be-a-library-not-a-bridge-subscription
|
||||
useBridgeSubscription(['locations.online'], {
|
||||
onData: (d) => setOnlineLocations(d)
|
||||
onData: (d) => {
|
||||
getLibraryStore().onlineLocations = d;
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<LibraryContext.Provider value={{ library, libraries, onlineLocations }}>
|
||||
{children}
|
||||
</LibraryContext.Provider>
|
||||
<LibraryContext.Provider value={{ library, libraries }}>{children}</LibraryContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -41,6 +40,6 @@ export const useLibraryContext = () => {
|
|||
};
|
||||
|
||||
export function useOnlineLocations() {
|
||||
const ctx = useLibraryContext();
|
||||
return ctx?.onlineLocations || [];
|
||||
const { onlineLocations } = useLibraryStore();
|
||||
return onlineLocations;
|
||||
}
|
||||
|
|
15
packages/client/src/hooks/useLibraryStore.ts
Normal file
15
packages/client/src/hooks/useLibraryStore.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { proxy, useSnapshot } from 'valtio';
|
||||
|
||||
const state = {
|
||||
onlineLocations: [] as number[][]
|
||||
};
|
||||
|
||||
const libraryStore = proxy(state);
|
||||
|
||||
export function useLibraryStore() {
|
||||
return useSnapshot(libraryStore);
|
||||
}
|
||||
|
||||
export function getLibraryStore() {
|
||||
return libraryStore;
|
||||
}
|
|
@ -8,7 +8,7 @@ export function isPath(item: ExplorerItem): item is Extract<ExplorerItem, { type
|
|||
return item.type === 'Path';
|
||||
}
|
||||
|
||||
export function arraysEqual<T>(a: T[], b: T[]) {
|
||||
export function arraysEqual<T>(a: readonly T[], b: readonly T[]) {
|
||||
if (a === b) return true;
|
||||
if (a == null || b == null) return false;
|
||||
if (a.length !== b.length) return false;
|
||||
|
|
Loading…
Reference in a new issue