[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:
nikec 2023-07-06 00:27:38 +02:00 committed by GitHub
parent f83f29c720
commit 9d800eec31
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 54 additions and 31 deletions

4
.vscode/launch.json vendored
View file

@ -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
View file

@ -53,6 +53,7 @@
],
"env": {
"RUST_BACKTRACE": "short"
// "RUST_LOG": "sd_core::invalidate-query=trace"
},
"problemMatcher": ["$rustc"],
"group": "build",

View file

@ -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'
)}

View file

@ -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|

View file

@ -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)

View file

@ -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() {} }

View file

@ -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

View file

@ -27,7 +27,7 @@ export const Component = () => {
[
'locations.quickRescan',
{
sub_path: location.data?.path ?? '',
sub_path: path ?? '',
location_id: locationId
}
],

View file

@ -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

View file

@ -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';

View file

@ -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;
}

View 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;
}

View file

@ -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;