diff --git a/apps/desktop/package.json b/apps/desktop/package.json
index 7b6dfae6f..3e300ad93 100644
--- a/apps/desktop/package.json
+++ b/apps/desktop/package.json
@@ -11,7 +11,8 @@
"build": "tauri build"
},
"dependencies": {
- "@rspc/client": "^0.0.5",
+ "@rspc/client": "^0.0.6",
+ "@rspc/tauri": "^0.0.6",
"@sd/client": "workspace:*",
"@sd/core": "workspace:*",
"@sd/interface": "workspace:*",
diff --git a/apps/desktop/src-tauri/src/main.rs b/apps/desktop/src-tauri/src/main.rs
index b773aa813..9fb97486e 100644
--- a/apps/desktop/src-tauri/src/main.rs
+++ b/apps/desktop/src-tauri/src/main.rs
@@ -1,6 +1,6 @@
#![cfg_attr(
- all(not(debug_assertions), target_os = "windows"),
- windows_subsystem = "windows"
+ all(not(debug_assertions), target_os = "windows"),
+ windows_subsystem = "windows"
)]
use std::path::PathBuf;
diff --git a/apps/desktop/src/index.tsx b/apps/desktop/src/index.tsx
index 93a94fdf2..ad21450db 100644
--- a/apps/desktop/src/index.tsx
+++ b/apps/desktop/src/index.tsx
@@ -1,9 +1,10 @@
// import Spacedrive JS client
-import { TauriTransport, createClient } from '@rspc/client';
+import { createClient } from '@rspc/client';
+import { TauriTransport } from '@rspc/tauri';
import { Operations, queryClient, rspc } from '@sd/client';
import SpacedriveInterface, { Platform } from '@sd/interface';
import { dialog, invoke, os, shell } from '@tauri-apps/api';
-import { Event, listen } from '@tauri-apps/api/event';
+import { listen } from '@tauri-apps/api/event';
import { convertFileSrc } from '@tauri-apps/api/tauri';
import { appWindow } from '@tauri-apps/api/window';
import React, { useEffect, useState } from 'react';
diff --git a/apps/mobile/babel.config.js b/apps/mobile/babel.config.js
index 224bce79e..123f8b03f 100644
--- a/apps/mobile/babel.config.js
+++ b/apps/mobile/babel.config.js
@@ -2,6 +2,27 @@ module.exports = function (api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
- plugins: ['react-native-reanimated/plugin']
+ plugins: [
+ 'react-native-reanimated/plugin',
+ [
+ 'module-resolver',
+ {
+ extensions: [
+ '.js',
+ '.jsx',
+ '.ts',
+ '.tsx',
+ '.android.js',
+ '.android.tsx',
+ '.ios.js',
+ '.ios.tsx'
+ ],
+ root: ['src'],
+ alias: {
+ '~': './src'
+ }
+ }
+ ]
+ ]
};
};
diff --git a/apps/mobile/ios/Podfile.lock b/apps/mobile/ios/Podfile.lock
index eb04e2bc1..5825a73f1 100644
--- a/apps/mobile/ios/Podfile.lock
+++ b/apps/mobile/ios/Podfile.lock
@@ -9,11 +9,11 @@ PODS:
- ExpoModulesCore
- EXFont (10.2.0):
- ExpoModulesCore
- - Expo (46.0.9):
+ - Expo (46.0.10):
- ExpoModulesCore
- ExpoKeepAwake (10.2.0):
- ExpoModulesCore
- - ExpoModulesCore (0.11.4):
+ - ExpoModulesCore (0.11.5):
- React-Core
- ReactCommon/turbomodule/core
- EXSplashScreen (0.16.2):
@@ -31,6 +31,10 @@ PODS:
- glog (0.3.5)
- hermes-engine (0.69.4)
- libevent (2.1.12)
+ - lottie-ios (3.4.2)
+ - lottie-react-native (5.1.4):
+ - lottie-ios (~> 3.4.0)
+ - React-Core
- RCT-Folly (2021.06.28.00-v2):
- boost
- DoubleConversion
@@ -335,7 +339,7 @@ PODS:
- React-Core
- RNGestureHandler (2.5.0):
- React-Core
- - RNReanimated (2.9.1):
+ - RNReanimated (2.10.0):
- DoubleConversion
- FBLazyVector
- FBReactNativeSpec
@@ -372,19 +376,20 @@ PODS:
DEPENDENCIES:
- boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`)
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
- - "EXApplication (from `../node_modules/.pnpm/expo-application@4.2.2_expo@46.0.9/node_modules/expo-application/ios`)"
- - "EXConstants (from `../node_modules/.pnpm/expo-constants@13.2.4_expo@46.0.9/node_modules/expo-constants/ios`)"
- - "EXFileSystem (from `../node_modules/.pnpm/expo-file-system@14.1.0_expo@46.0.9/node_modules/expo-file-system/ios`)"
- - "EXFont (from `../node_modules/.pnpm/expo-font@10.2.0_expo@46.0.9/node_modules/expo-font/ios`)"
- - "Expo (from `../node_modules/.pnpm/expo@46.0.9_@babel+core@7.18.10/node_modules/expo`)"
- - "ExpoKeepAwake (from `../node_modules/.pnpm/expo-keep-awake@10.2.0_expo@46.0.9/node_modules/expo-keep-awake/ios`)"
- - "ExpoModulesCore (from `../node_modules/.pnpm/expo-modules-core@0.11.4/node_modules/expo-modules-core/ios`)"
- - "EXSplashScreen (from `../node_modules/.pnpm/expo-splash-screen@0.16.2_expo@46.0.9/node_modules/expo-splash-screen/ios`)"
+ - "EXApplication (from `../node_modules/.pnpm/expo-application@4.2.2_expo@46.0.10/node_modules/expo-application/ios`)"
+ - "EXConstants (from `../node_modules/.pnpm/expo-constants@13.2.4_expo@46.0.10/node_modules/expo-constants/ios`)"
+ - "EXFileSystem (from `../node_modules/.pnpm/expo-file-system@14.1.0_expo@46.0.10/node_modules/expo-file-system/ios`)"
+ - "EXFont (from `../node_modules/.pnpm/expo-font@10.2.0_expo@46.0.10/node_modules/expo-font/ios`)"
+ - "Expo (from `../node_modules/.pnpm/expo@46.0.10_@babel+core@7.18.10/node_modules/expo`)"
+ - "ExpoKeepAwake (from `../node_modules/.pnpm/expo-keep-awake@10.2.0_expo@46.0.10/node_modules/expo-keep-awake/ios`)"
+ - "ExpoModulesCore (from `../node_modules/.pnpm/expo-modules-core@0.11.5/node_modules/expo-modules-core/ios`)"
+ - "EXSplashScreen (from `../node_modules/.pnpm/expo-splash-screen@0.16.2_expo@46.0.10/node_modules/expo-splash-screen/ios`)"
- FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`)
- FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`)
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
- hermes-engine (from `../node_modules/react-native/sdks/hermes/hermes-engine.podspec`)
- libevent (~> 2.1.12)
+ - lottie-react-native (from `../node_modules/lottie-react-native`)
- RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`)
- RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`)
- RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`)
@@ -426,6 +431,7 @@ SPEC REPOS:
trunk:
- fmt
- libevent
+ - lottie-ios
EXTERNAL SOURCES:
boost:
@@ -433,21 +439,21 @@ EXTERNAL SOURCES:
DoubleConversion:
:podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec"
EXApplication:
- :path: "../node_modules/.pnpm/expo-application@4.2.2_expo@46.0.9/node_modules/expo-application/ios"
+ :path: "../node_modules/.pnpm/expo-application@4.2.2_expo@46.0.10/node_modules/expo-application/ios"
EXConstants:
- :path: "../node_modules/.pnpm/expo-constants@13.2.4_expo@46.0.9/node_modules/expo-constants/ios"
+ :path: "../node_modules/.pnpm/expo-constants@13.2.4_expo@46.0.10/node_modules/expo-constants/ios"
EXFileSystem:
- :path: "../node_modules/.pnpm/expo-file-system@14.1.0_expo@46.0.9/node_modules/expo-file-system/ios"
+ :path: "../node_modules/.pnpm/expo-file-system@14.1.0_expo@46.0.10/node_modules/expo-file-system/ios"
EXFont:
- :path: "../node_modules/.pnpm/expo-font@10.2.0_expo@46.0.9/node_modules/expo-font/ios"
+ :path: "../node_modules/.pnpm/expo-font@10.2.0_expo@46.0.10/node_modules/expo-font/ios"
Expo:
- :path: "../node_modules/.pnpm/expo@46.0.9_@babel+core@7.18.10/node_modules/expo"
+ :path: "../node_modules/.pnpm/expo@46.0.10_@babel+core@7.18.10/node_modules/expo"
ExpoKeepAwake:
- :path: "../node_modules/.pnpm/expo-keep-awake@10.2.0_expo@46.0.9/node_modules/expo-keep-awake/ios"
+ :path: "../node_modules/.pnpm/expo-keep-awake@10.2.0_expo@46.0.10/node_modules/expo-keep-awake/ios"
ExpoModulesCore:
- :path: "../node_modules/.pnpm/expo-modules-core@0.11.4/node_modules/expo-modules-core/ios"
+ :path: "../node_modules/.pnpm/expo-modules-core@0.11.5/node_modules/expo-modules-core/ios"
EXSplashScreen:
- :path: "../node_modules/.pnpm/expo-splash-screen@0.16.2_expo@46.0.9/node_modules/expo-splash-screen/ios"
+ :path: "../node_modules/.pnpm/expo-splash-screen@0.16.2_expo@46.0.10/node_modules/expo-splash-screen/ios"
FBLazyVector:
:path: "../node_modules/react-native/Libraries/FBLazyVector"
FBReactNativeSpec:
@@ -456,6 +462,8 @@ EXTERNAL SOURCES:
:podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec"
hermes-engine:
:podspec: "../node_modules/react-native/sdks/hermes/hermes-engine.podspec"
+ lottie-react-native:
+ :path: "../node_modules/lottie-react-native"
RCT-Folly:
:podspec: "../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec"
RCTRequired:
@@ -534,9 +542,9 @@ SPEC CHECKSUMS:
EXConstants: 7c44785d41d8e959d527d23d29444277a4d1ee73
EXFileSystem: 927e0a8885aa9c49e50fc38eaba2c2389f2f1019
EXFont: a5d80bd9b3452b2d5abbce2487da89b0150e6487
- Expo: 73412414e62f5cbc6e713def821de70b92cd3ad6
+ Expo: fcdb32274e2ca9c7638d3b21b30fb665c6869219
ExpoKeepAwake: 0e8f18142e71bbf2c7f6aa66ebed249ba1420320
- ExpoModulesCore: e281bb7b78ea47e227dd5af94d04b24d8b2e1255
+ ExpoModulesCore: 5a973701f4400d70254bc836305228731c829010
EXSplashScreen: 799bece80089219b2c989c1082d70f3b00995cda
FBLazyVector: c71b8c429a8af2aff1013934a7152e9d9d0c937d
FBReactNativeSpec: 3cc5cff7d792e74a875be91e56d6242335016f50
@@ -544,6 +552,8 @@ SPEC CHECKSUMS:
glog: 3d02b25ca00c2d456734d0bcff864cbc62f6ae1a
hermes-engine: 761a544537e62df2a37189389b9d2654dc1f75af
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
+ lottie-ios: 6bbc53eef6957e4744a50321507015fba72d8ca6
+ lottie-react-native: b702fab740cdb952a8e2354713d3beda63ff97b0
RCT-Folly: b9d9fe1fc70114b751c076104e52f3b1b5e5a95a
RCTRequired: bd9d2ab0fda10171fcbcf9ba61a7df4dc15a28f4
RCTTypeSafety: e44e139bf6ec8042db396201834fc2372f6a21cd
@@ -575,7 +585,7 @@ SPEC CHECKSUMS:
RNCAsyncStorage: d81ee5c3db1060afd49ea7045ad460eff82d2b7d
RNCMaskedView: cb9670ea9239998340eaab21df13fa12a1f9de15
RNGestureHandler: bad495418bcbd3ab47017a38d93d290ebd406f50
- RNReanimated: 2cf7451318bb9cc430abeec8d67693f9cf4e039c
+ RNReanimated: 7faa787e8d4493fbc95fab2ad331fa7625828cfa
RNScreens: 4a1af06327774490d97342c00aee0c2bafb497b7
RNSVG: 42a0c731b11179ebbd27a3eeeafa7201ebb476ff
Yoga: ff994563b2fd98c982ca58e8cd9db2cdaf4dda74
diff --git a/apps/mobile/ios/Spacedrive/Info.plist b/apps/mobile/ios/Spacedrive/Info.plist
index 544e7b24b..fd2881b25 100644
--- a/apps/mobile/ios/Spacedrive/Info.plist
+++ b/apps/mobile/ios/Spacedrive/Info.plist
@@ -1,81 +1,83 @@
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleDisplayName
- Spacedrive
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- $(PRODUCT_BUNDLE_PACKAGE_TYPE)
- CFBundleShortVersionString
- 0.0.1
- CFBundleSignature
- ????
- CFBundleURLTypes
-
-
- CFBundleURLSchemes
-
- spacedrive
- com.spacedrive.app
-
-
-
- CFBundleVersion
- 1
- LSRequiresIPhoneOS
-
- NSAppTransportSecurity
- NSAllowsArbitraryLoads
-
- NSExceptionDomains
-
- localhost
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleDisplayName
+ Spacedrive
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ $(PRODUCT_BUNDLE_PACKAGE_TYPE)
+ CFBundleShortVersionString
+ 0.0.1
+ CFBundleSignature
+ ????
+ CFBundleURLTypes
+
- NSExceptionAllowsInsecureHTTPLoads
-
+ CFBundleURLSchemes
+
+ spacedrive
+ com.spacedrive.app
+
+
+
+ CFBundleVersion
+ 1
+ LSRequiresIPhoneOS
+
+ NSAppTransportSecurity
+
+ NSAllowsArbitraryLoads
+
+ NSExceptionDomains
+
+ localhost
+
+ NSExceptionAllowsInsecureHTTPLoads
+
+
+ UIBackgroundModes
+
+ remote-notification
+
+ UIFileSharingEnabled
+
+ UILaunchStoryboardName
+ SplashScreen
+ UIRequiredDeviceCapabilities
+
+ armv7
+
+ UIRequiresFullScreen
+
+ UIStatusBarStyle
+ UIStatusBarStyleDefault
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UIUserInterfaceStyle
+ Automatic
+ UIViewControllerBasedStatusBarAppearance
+
- UIBackgroundModes
-
- remote-notification
-
- UILaunchStoryboardName
- SplashScreen
- UIRequiredDeviceCapabilities
-
- armv7
-
- UIRequiresFullScreen
-
- UIStatusBarStyle
- UIStatusBarStyleDefault
- UISupportedInterfaceOrientations
-
- UIInterfaceOrientationPortrait
- UIInterfaceOrientationPortraitUpsideDown
-
- UISupportedInterfaceOrientations~ipad
-
- UIInterfaceOrientationPortrait
- UIInterfaceOrientationPortraitUpsideDown
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
-
- UIUserInterfaceStyle
- Automatic
- UIViewControllerBasedStatusBarAppearance
-
-
-
+
\ No newline at end of file
diff --git a/apps/mobile/package.json b/apps/mobile/package.json
index 711926bd7..f1c15ee93 100644
--- a/apps/mobile/package.json
+++ b/apps/mobile/package.json
@@ -10,7 +10,6 @@
"lint": "eslint src/**/*.{ts,tsx} && tsc --noEmit"
},
"dependencies": {
- "@expo/vector-icons": "^13.0.0",
"@gorhom/bottom-sheet": "^4.4.3",
"@react-native-async-storage/async-storage": "~1.17.3",
"@react-native-masked-view/masked-view": "0.2.7",
@@ -18,41 +17,45 @@
"@react-navigation/drawer": "^6.4.4",
"@react-navigation/native": "^6.0.12",
"@react-navigation/stack": "^6.2.3",
- "@rspc/client": "^0.0.5",
+ "@rspc/client": "^0.0.6",
+ "@rspc/react": "^0.0.6",
"@sd/assets": "file:../../packages/assets",
"@tanstack/react-query": "^4.2.3",
"byte-size": "^8.1.0",
"class-variance-authority": "^0.2.3",
"date-fns": "^2.29.2",
- "expo": "~46.0.9",
- "expo-font": "~10.2.0",
+ "expo": "~46.0.10",
"expo-linking": "~3.2.2",
"expo-splash-screen": "~0.16.2",
"expo-status-bar": "~1.4.0",
+ "immer": "^9.0.15",
"intl": "^1.2.5",
+ "lottie-react-native": "^5.1.4",
"moti": "^0.18.0",
"phosphor-react-native": "^1.1.2",
"react": "18.0.0",
"react-native": "0.69.4",
"react-native-gesture-handler": "~2.5.0",
"react-native-heroicons": "^2.2.0",
- "react-native-reanimated": "~2.9.1",
+ "react-native-reanimated": "~2.10.0",
"react-native-safe-area-context": "4.3.1",
"react-native-screens": "~3.15.0",
"react-native-svg": "13.0.0",
"twrnc": "^3.4.0",
"use-count-up": "^3.0.1",
- "zustand": "^4.1.1"
+ "valtio": "^1.7.0",
+ "valtio-persist": "^1.0.2"
},
"devDependencies": {
"@babel/core": "^7.18.6",
"@babel/runtime": "^7.18.9",
- "@rnx-kit/metro-config": "^1.2.36",
+ "@rnx-kit/metro-config": "^1.2.37",
"@rnx-kit/metro-resolver-symlinks": "^0.1.21",
"@types/react": "~18.0.0",
"@types/react-native": "~0.69.1",
"@typescript-eslint/eslint-plugin": "^5.30.7",
"@typescript-eslint/parser": "^5.30.7",
+ "babel-plugin-module-resolver": "^4.1.0",
"eslint": "^8.21.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-react": "^7.30.1",
diff --git a/apps/mobile/pnpm-lock.yaml b/apps/mobile/pnpm-lock.yaml
index 75295d7a7..84ec59b3d 100644
Binary files a/apps/mobile/pnpm-lock.yaml and b/apps/mobile/pnpm-lock.yaml differ
diff --git a/apps/mobile/src/App.tsx b/apps/mobile/src/App.tsx
index 14794ffd7..2b1e45276 100644
--- a/apps/mobile/src/App.tsx
+++ b/apps/mobile/src/App.tsx
@@ -6,15 +6,22 @@ import React, { useEffect } from 'react';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import { useDeviceContext } from 'twrnc';
+import { useSnapshot } from 'valtio';
import { GlobalModals } from './components/modals/GlobalModals';
-import { ReactNativeTransport, queryClient, rspc, useInvalidateQuery } from './hooks/rspc';
+import {
+ ReactNativeTransport,
+ queryClient,
+ rspc,
+ useBridgeQuery,
+ useInvalidateQuery
+} from './hooks/rspc';
import useCachedResources from './hooks/useCachedResources';
-import { getItemFromStorage } from './lib/storage';
import tw from './lib/tailwind';
import RootNavigator from './navigation';
import OnboardingNavigator from './navigation/OnboardingNavigator';
-import { useOnboardingStore } from './stores/useOnboardingStore';
+import { libraryStore } from './stores/libraryStore';
+import { onboardingStore } from './stores/onboardingStore';
import type { Operations } from './types/bindings';
const client = createClient({
@@ -25,50 +32,69 @@ const NavigatorTheme: Theme = {
...DefaultTheme,
colors: {
...DefaultTheme.colors,
- background: '#08090D'
+ background: tw.color('gray-650')
}
};
-export default function App() {
+function AppContainer() {
// Enables dark mode, and screen size breakpoints, etc. for tailwind
useDeviceContext(tw, { withDeviceColorScheme: false });
const isLoadingComplete = useCachedResources();
- const { showOnboarding, hideOnboarding } = useOnboardingStore();
+ const { showOnboarding } = useSnapshot(onboardingStore);
+
+ const { data: libraries } = useBridgeQuery(['library.list'], {
+ onError(err) {
+ console.error(err);
+ }
+ });
+
+ const { _persist, switchLibrary } = useSnapshot(libraryStore);
+
+ console.log('persisted?', _persist.loaded);
// Runs when the app is launched
useEffect(() => {
- getItemFromStorage('@onboarding').then((value) => {
- value && hideOnboarding();
- });
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, []);
+ // Temporarly set the first library to be the current library
+ if (!showOnboarding) {
+ if (libraries && libraries.length > 0) {
+ switchLibrary(libraries[0].uuid);
+ }
+ }
+ }, [libraries, showOnboarding, switchLibrary]);
- if (!isLoadingComplete) {
+ // Might need to move _persist.loaded to useCacheResources hook.
+ if (!isLoadingComplete || !_persist.loaded) {
return null;
} else {
return (
-
- <>
-
-
-
-
-
-
- {showOnboarding ? : }
-
-
-
-
-
- >
-
+
+
+
+
+
+ {showOnboarding ? : }
+
+
+
+
+
);
}
}
+export default function App() {
+ return (
+
+ <>
+
+
+ >
+
+ );
+}
+
function InvalidateQuery() {
useInvalidateQuery();
return null;
diff --git a/apps/mobile/src/components/animation/layout.tsx b/apps/mobile/src/components/animation/layout.tsx
index 78253f6c4..f1dabe3ca 100644
--- a/apps/mobile/src/components/animation/layout.tsx
+++ b/apps/mobile/src/components/animation/layout.tsx
@@ -2,9 +2,8 @@ import { MotiView, useDynamicAnimation } from 'moti';
import React from 'react';
import { StyleSheet, View } from 'react-native';
import { useDerivedValue, useSharedValue } from 'react-native-reanimated';
-
-import Layout from '../../constants/Layout';
-import tw from '../../lib/tailwind';
+import Layout from '~/constants/Layout';
+import tw from '~/lib/tailwind';
// Anything wrapped with FadeIn will fade in on mount.
export const FadeInAnimation = ({ children, delay }: { children: any; delay?: number }) => (
diff --git a/apps/mobile/src/components/browse/BrowseLocationItem.tsx b/apps/mobile/src/components/browse/BrowseLocationItem.tsx
index 2298925c9..49c271b1d 100644
--- a/apps/mobile/src/components/browse/BrowseLocationItem.tsx
+++ b/apps/mobile/src/components/browse/BrowseLocationItem.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { Pressable, Text, View } from 'react-native';
+import tw from '~/lib/tailwind';
-import tw from '../../lib/tailwind';
import FolderIcon from '../icons/FolderIcon';
interface BrowseLocationItemProps {
diff --git a/apps/mobile/src/components/browse/BrowseTagItem.tsx b/apps/mobile/src/components/browse/BrowseTagItem.tsx
index 2f8508008..e89477f1e 100644
--- a/apps/mobile/src/components/browse/BrowseTagItem.tsx
+++ b/apps/mobile/src/components/browse/BrowseTagItem.tsx
@@ -1,7 +1,6 @@
import React from 'react';
import { ColorValue, Pressable, Text, View } from 'react-native';
-
-import tw from '../../lib/tailwind';
+import tw from '~/lib/tailwind';
type BrowseTagItemProps = {
tagName: string;
diff --git a/apps/mobile/src/components/device/Device.tsx b/apps/mobile/src/components/device/Device.tsx
index d8a24afad..bcf1e246b 100644
--- a/apps/mobile/src/components/device/Device.tsx
+++ b/apps/mobile/src/components/device/Device.tsx
@@ -2,9 +2,9 @@ import { Cloud, Desktop, DeviceMobileCamera, Laptop } from 'phosphor-react-nativ
import React from 'react';
import { FlatList, Text, View } from 'react-native';
import { LockClosedIcon } from 'react-native-heroicons/solid';
+import tw from '~/lib/tailwind';
+import { FilePath } from '~/types/bindings';
-import tw from '../../lib/tailwind';
-import { FilePath } from '../../types/bindings';
import FileItem from '../file/FileItem';
const placeholderFileItems: FilePath[] = [
@@ -16,48 +16,11 @@ const placeholderFileItems: FilePath[] = [
extension: '',
file_id: 1,
id: 1,
- key: null,
location_id: 1,
materialized_path: '',
name: 'Minecraft',
parent_id: 0,
- key_id: null,
- location: null,
- file: {
- id: 1,
- key_id: 1,
- albums: [],
- comments: [],
- key: {
- algorithm: null,
- checksum: '',
- date_created: null,
- file_paths: [],
- files: [],
- id: 1,
- name: 'Hello world'
- },
- labels: [],
- media_data: null,
- spaces: [],
- tags: [],
- cas_id: '',
- ipfs_id: '',
- has_thumbnail: false,
- favorite: false,
- has_thumbstrip: false,
- has_video_preview: false,
- hidden: false,
- important: false,
- integrity_checksum: '',
- kind: 1,
- note: '',
- paths: [],
- size_in_bytes: '555',
- date_created: '',
- date_indexed: '',
- date_modified: ''
- }
+ key_id: null
},
{
is_dir: true,
@@ -67,48 +30,11 @@ const placeholderFileItems: FilePath[] = [
extension: '',
file_id: 2,
id: 2,
- key: null,
location_id: 2,
materialized_path: '',
name: 'Documents',
parent_id: 0,
- key_id: null,
- location: null,
- file: {
- id: 2,
- key_id: 2,
- albums: [],
- comments: [],
- key: {
- algorithm: null,
- checksum: '',
- date_created: null,
- file_paths: [],
- files: [],
- id: 1,
- name: 'Hello world'
- },
- labels: [],
- media_data: null,
- spaces: [],
- tags: [],
- cas_id: '',
- ipfs_id: '',
- has_thumbnail: false,
- favorite: false,
- has_thumbstrip: false,
- has_video_preview: false,
- hidden: false,
- important: false,
- integrity_checksum: '',
- kind: 1,
- note: '',
- paths: [],
- size_in_bytes: '555',
- date_created: '',
- date_indexed: '',
- date_modified: ''
- }
+ key_id: null
},
{
is_dir: false,
@@ -118,48 +44,11 @@ const placeholderFileItems: FilePath[] = [
extension: 'tsx',
file_id: 3,
id: 3,
- key: null,
location_id: 3,
materialized_path: '',
name: 'App.tsx',
parent_id: 0,
- key_id: null,
- location: null,
- file: {
- id: 3,
- key_id: 3,
- albums: [],
- comments: [],
- key: {
- algorithm: null,
- checksum: '',
- date_created: null,
- file_paths: [],
- files: [],
- id: 1,
- name: 'Hello world'
- },
- labels: [],
- media_data: null,
- spaces: [],
- tags: [],
- cas_id: '',
- ipfs_id: '',
- has_thumbnail: false,
- favorite: false,
- has_thumbstrip: false,
- has_video_preview: false,
- hidden: false,
- important: false,
- integrity_checksum: '',
- kind: 1,
- note: '',
- paths: [],
- size_in_bytes: '555',
- date_created: '',
- date_indexed: '',
- date_modified: ''
- }
+ key_id: null
},
{
is_dir: false,
@@ -169,48 +58,11 @@ const placeholderFileItems: FilePath[] = [
extension: 'vite',
file_id: 4,
id: 4,
- key: null,
location_id: 4,
materialized_path: '',
name: 'vite.config.js',
parent_id: 0,
- key_id: null,
- location: null,
- file: {
- id: 4,
- key_id: 4,
- albums: [],
- comments: [],
- key: {
- algorithm: null,
- checksum: '',
- date_created: null,
- file_paths: [],
- files: [],
- id: 1,
- name: 'Hello world'
- },
- labels: [],
- media_data: null,
- spaces: [],
- tags: [],
- cas_id: '',
- ipfs_id: '',
- has_thumbnail: false,
- favorite: false,
- has_thumbstrip: false,
- has_video_preview: false,
- hidden: false,
- important: false,
- integrity_checksum: '',
- kind: 1,
- note: '',
- paths: [],
- size_in_bytes: '555',
- date_created: '',
- date_indexed: '',
- date_modified: ''
- }
+ key_id: null
},
{
is_dir: false,
@@ -220,48 +72,11 @@ const placeholderFileItems: FilePath[] = [
extension: 'docker',
file_id: 5,
id: 5,
- key: null,
location_id: 5,
materialized_path: '',
name: 'Dockerfile',
parent_id: 0,
- key_id: null,
- location: null,
- file: {
- id: 5,
- key_id: 5,
- albums: [],
- comments: [],
- key: {
- algorithm: null,
- checksum: '',
- date_created: null,
- file_paths: [],
- files: [],
- id: 1,
- name: 'Hello world'
- },
- labels: [],
- media_data: null,
- spaces: [],
- tags: [],
- cas_id: '',
- ipfs_id: '',
- has_thumbnail: false,
- favorite: false,
- has_thumbstrip: false,
- has_video_preview: false,
- hidden: false,
- important: false,
- integrity_checksum: '',
- kind: 1,
- note: '',
- paths: [],
- size_in_bytes: '555',
- date_created: '',
- date_indexed: '',
- date_modified: ''
- }
+ key_id: null
}
];
diff --git a/apps/mobile/src/components/drawer/DrawerContent.tsx b/apps/mobile/src/components/drawer/DrawerContent.tsx
index 2b93328ac..49c0b59c8 100644
--- a/apps/mobile/src/components/drawer/DrawerContent.tsx
+++ b/apps/mobile/src/components/drawer/DrawerContent.tsx
@@ -2,14 +2,15 @@ import { DrawerContentScrollView } from '@react-navigation/drawer';
import { DrawerContentComponentProps } from '@react-navigation/drawer/lib/typescript/src/types';
import { getFocusedRouteNameFromRoute } from '@react-navigation/native';
import React from 'react';
-import { ColorValue, Platform, Pressable, Text, View } from 'react-native';
+import { ColorValue, Image, Platform, Pressable, Text, View } from 'react-native';
import { CogIcon } from 'react-native-heroicons/solid';
+import Layout from '~/constants/Layout';
+import tw from '~/lib/tailwind';
-import Layout from '../../constants/Layout';
-import tw from '../../lib/tailwind';
import CollapsibleView from '../layout/CollapsibleView';
+import Divider from '../primitive/Divider';
+import DrawerLibraryManager from './DrawerLibraryManager';
import DrawerLocationItem from './DrawerLocationItem';
-import DrawerLogo from './DrawerLogo';
import DrawerTagItem from './DrawerTagItem';
const placeholderLocationData = [
@@ -60,28 +61,36 @@ const DrawerContent = ({ navigation, state }: DrawerContentComponentProps) => {
-
- TODO: Library Selection
+
+
+ Spacedrive
+
+
+ {/* Library Manager */}
+
{/* Locations */}
- {placeholderLocationData.map((location) => (
-
- navigation.navigate(stackName, {
- screen: 'Location',
- params: { id: location.id }
- })
- }
- />
- ))}
+
+ {placeholderLocationData.map((location) => (
+
+ navigation.navigate(stackName, {
+ screen: 'Location',
+ params: { id: location.id }
+ })
+ }
+ />
+ ))}
+
{/* Add Location */}
-
-
+
+
Add Location
@@ -89,21 +98,24 @@ const DrawerContent = ({ navigation, state }: DrawerContentComponentProps) => {
{/* Tags */}
- {placeholderTagsData.map((tag) => (
-
- navigation.navigate(stackName, {
- screen: 'Tag',
- params: { id: tag.id }
- })
- }
- tagColor={tag.color as ColorValue}
- />
- ))}
+
+ {placeholderTagsData.map((tag) => (
+
+ navigation.navigate(stackName, {
+ screen: 'Tag',
+ params: { id: tag.id }
+ })
+ }
+ tagColor={tag.color as ColorValue}
+ />
+ ))}
+
{/* Settings */}
diff --git a/apps/mobile/src/components/drawer/DrawerLibraryManager.tsx b/apps/mobile/src/components/drawer/DrawerLibraryManager.tsx
new file mode 100644
index 000000000..7fbd51daa
--- /dev/null
+++ b/apps/mobile/src/components/drawer/DrawerLibraryManager.tsx
@@ -0,0 +1,126 @@
+import { MotiView } from 'moti';
+import React, { useEffect, useState } from 'react';
+import { Pressable, Text, View } from 'react-native';
+import { LockClosedIcon } from 'react-native-heroicons/outline';
+import { ChevronRightIcon, CogIcon, PlusIcon } from 'react-native-heroicons/solid';
+import { useSnapshot } from 'valtio';
+import { useBridgeMutation } from '~/hooks/rspc';
+import tw from '~/lib/tailwind';
+import { libraryStore, useCurrentLibrary } from '~/stores/libraryStore';
+
+import { AnimatedHeight } from '../animation/layout';
+import Dialog from '../layout/Dialog';
+import Divider from '../primitive/Divider';
+import { TextInput } from '../primitive/Input';
+
+// TODO: Maybe minimize this when drawer is closed?
+const DrawerLibraryManager = () => {
+ const [dropdownClosed, setDropdownClosed] = useState(true);
+
+ // Init Libraries
+ const { initLibraries, switchLibrary } = useSnapshot(libraryStore);
+ const { currentLibrary, libraries, currentLibraryUuid } = useCurrentLibrary();
+
+ useEffect(() => {
+ if (libraries && !currentLibraryUuid) initLibraries(libraries);
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [libraries, currentLibraryUuid]);
+
+ // Create Library
+ const [libName, setLibName] = useState('');
+
+ const [createLibOpen, setCreateLibOpen] = useState(false);
+
+ const { mutate: createLibrary, isLoading: createLibLoading } = useBridgeMutation(
+ 'library.create',
+ {
+ onSuccess: () => {
+ // Reset form
+ setLibName('');
+ },
+ onSettled: () => {
+ // Close create lib dialog
+ setCreateLibOpen(false);
+ }
+ }
+ );
+
+ return (
+
+ setDropdownClosed((v) => !v)}>
+
+ {currentLibrary?.config.name}
+
+
+
+
+
+
+
+ {/* Libraries */}
+ {libraries?.map((library) => (
+ switchLibrary(library.uuid)}>
+
+ {library.config.name}
+
+
+ ))}
+
+ {/* Menu */}
+ console.log('settings')}>
+
+
+ Library Settings
+
+
+ {/* Create Library */}
+
+ console.log('lock')}>
+
+
+ Lock
+
+
+
+
+
+ );
+};
+
+export default DrawerLibraryManager;
diff --git a/apps/mobile/src/components/drawer/DrawerLocationItem.tsx b/apps/mobile/src/components/drawer/DrawerLocationItem.tsx
index a9f74ae74..c950f2e82 100644
--- a/apps/mobile/src/components/drawer/DrawerLocationItem.tsx
+++ b/apps/mobile/src/components/drawer/DrawerLocationItem.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { Pressable, Text, View } from 'react-native';
+import tw from '~/lib/tailwind';
-import tw from '../../lib/tailwind';
import FolderIcon from '../icons/FolderIcon';
interface DrawerLocationItemProps {
@@ -13,7 +13,7 @@ const DrawerLocationItem: React.FC = (props) => {
const { folderName, onPress } = props;
return (
-
+
{folderName}
diff --git a/apps/mobile/src/components/drawer/DrawerLogo.tsx b/apps/mobile/src/components/drawer/DrawerLogo.tsx
deleted file mode 100644
index afe1ce54c..000000000
--- a/apps/mobile/src/components/drawer/DrawerLogo.tsx
+++ /dev/null
@@ -1,19 +0,0 @@
-import React from 'react';
-import { Image, Text, View } from 'react-native';
-
-import tw from '../../lib/tailwind';
-import Divider from '../base/Divider';
-
-const DrawerLogo = () => {
- return (
- <>
-
-
- Spacedrive
-
-
- >
- );
-};
-
-export default DrawerLogo;
diff --git a/apps/mobile/src/components/drawer/DrawerTagItem.tsx b/apps/mobile/src/components/drawer/DrawerTagItem.tsx
index 210b04876..d364e9845 100644
--- a/apps/mobile/src/components/drawer/DrawerTagItem.tsx
+++ b/apps/mobile/src/components/drawer/DrawerTagItem.tsx
@@ -1,7 +1,6 @@
import React from 'react';
import { ColorValue, Pressable, Text, View } from 'react-native';
-
-import tw from '../../lib/tailwind';
+import tw from '~/lib/tailwind';
type DrawerTagItemProps = {
tagName: string;
@@ -13,7 +12,7 @@ const DrawerTagItem: React.FC = (props) => {
const { tagName, tagColor, onPress } = props;
return (
-
+
{tagName}
diff --git a/apps/mobile/src/components/file/FileIcon.tsx b/apps/mobile/src/components/file/FileIcon.tsx
index 101f78dc9..db646bebe 100644
--- a/apps/mobile/src/components/file/FileIcon.tsx
+++ b/apps/mobile/src/components/file/FileIcon.tsx
@@ -17,13 +17,16 @@ type FileIconProps = {
};
const FileIcon = ({ file, size = 1 }: FileIconProps) => {
+ // Temp
+ const has_thumbnail = false;
+
return (
{file?.is_dir ? (
- ) : file?.file?.has_thumbnail ? (
+ ) : has_thumbnail ? (
<>{/* TODO */}>
) : (
diff --git a/apps/mobile/src/components/file/FileItem.tsx b/apps/mobile/src/components/file/FileItem.tsx
index 5bc5d8a03..352f4e17a 100644
--- a/apps/mobile/src/components/file/FileItem.tsx
+++ b/apps/mobile/src/components/file/FileItem.tsx
@@ -1,10 +1,11 @@
import { useNavigation } from '@react-navigation/native';
import React from 'react';
import { Pressable, Text, View } from 'react-native';
+import { useSnapshot } from 'valtio';
import tw from '../../lib/tailwind';
import { SharedScreenProps } from '../../navigation/SharedScreens';
-import { useFileModalStore } from '../../stores/useModalStore';
+import { fileModalStore } from '../../stores/modalStore';
import { FilePath } from '../../types/bindings';
import FileIcon from './FileIcon';
@@ -15,8 +16,7 @@ type FileItemProps = {
// TODO: Menu for file actions (File details, Share etc.)
const FileItem = ({ file }: FileItemProps) => {
- const fileRef = useFileModalStore((state) => state.fileRef);
- const setData = useFileModalStore((state) => state.setData);
+ const { fileRef, setData } = useSnapshot(fileModalStore);
const navigation = useNavigation['navigation']>();
diff --git a/apps/mobile/src/components/header/Header.tsx b/apps/mobile/src/components/header/Header.tsx
index 8838ade88..df139c78f 100644
--- a/apps/mobile/src/components/header/Header.tsx
+++ b/apps/mobile/src/components/header/Header.tsx
@@ -6,8 +6,7 @@ import { List } from 'phosphor-react-native';
import React from 'react';
import { Pressable, Text, View } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
-
-import tw from '../../lib/tailwind';
+import tw from '~/lib/tailwind';
const Header = () => {
const navigation = useNavigation();
@@ -17,7 +16,11 @@ const Header = () => {
const isDrawerOpen = useDrawerStatus() === 'open';
return (
-
+
navigation.openDrawer()}>
{
style={tw`flex-1 h-full justify-center`}
onPress={() => navigation.navigate('Search')}
>
- Search
+ Search
diff --git a/apps/mobile/src/components/layout/CollapsibleView.tsx b/apps/mobile/src/components/layout/CollapsibleView.tsx
index abdf28a68..0d55838ae 100644
--- a/apps/mobile/src/components/layout/CollapsibleView.tsx
+++ b/apps/mobile/src/components/layout/CollapsibleView.tsx
@@ -1,9 +1,9 @@
-import { Ionicons } from '@expo/vector-icons';
import { MotiView } from 'moti';
import React, { useReducer } from 'react';
import { Pressable, StyleProp, Text, TextStyle, View, ViewStyle } from 'react-native';
+import { ChevronRightIcon } from 'react-native-heroicons/solid';
+import tw from '~/lib/tailwind';
-import tw from '../../lib/tailwind';
import { AnimatedHeight } from '../animation/layout';
type CollapsibleViewProps = {
@@ -18,7 +18,7 @@ const CollapsibleView = ({ title, titleStyle, containerStyle, children }: Collap
return (
-
+
{title}
@@ -28,14 +28,9 @@ const CollapsibleView = ({ title, titleStyle, containerStyle, children }: Collap
translateX: hide ? 0 : 5,
translateY: hide ? 0 : 5
}}
- transition={{ type: 'spring' }}
+ transition={{ type: 'timing' }}
>
-
+
{children}
diff --git a/apps/mobile/src/components/layout/Dialog.tsx b/apps/mobile/src/components/layout/Dialog.tsx
new file mode 100644
index 000000000..4b6a634d7
--- /dev/null
+++ b/apps/mobile/src/components/layout/Dialog.tsx
@@ -0,0 +1,110 @@
+import { MotiView } from 'moti';
+import React, { useState } from 'react';
+import { KeyboardAvoidingView, Modal, Platform, Pressable, Text, View } from 'react-native';
+import tw from '~/lib/tailwind';
+
+import { Button } from '../primitive/Button';
+
+type DialogProps = {
+ title: string;
+ description?: string;
+ trigger?: React.ReactNode;
+ /**
+ * if `true`, dialog will be visible when mounted.
+ * It can be used when trigger is not provided and/or you need to open the dialog programmatically
+ */
+ isVisible?: boolean;
+ /**
+ * Like above, it will override the default dialog state for opening/closing the dialog.
+ * It can be used to control dialog state from outside
+ */
+ setIsVisible?: (v: boolean) => void;
+ children?: React.ReactNode;
+ ctaAction?: () => void;
+ ctaLabel?: string;
+ ctaDanger?: boolean;
+ /**
+ * Disables backdrop press to close the modal.
+ */
+ disableBackdropClose?: boolean;
+};
+
+const Dialog = (props: DialogProps) => {
+ const [visible, setVisible] = useState(props.isVisible ?? false);
+
+ return (
+
+ {props.trigger && (
+ (props.setIsVisible ? props.setIsVisible(true) : setVisible(true))}
+ >
+ {props.trigger}
+
+ )}
+
+ {/* Backdrop */}
+ (props.setIsVisible ? props.setIsVisible(false) : setVisible(false))}
+ disabled={props.disableBackdropClose}
+ />
+ {/* Content */}
+
+
+
+
+ {/* Title */}
+ {props.title}
+ {/* Description */}
+ {props.description && (
+
+ {props.description}
+
+ )}
+ {/* Children */}
+ {props.children}
+
+ {/* Actions */}
+
+
+ {props.ctaAction && (
+
+ )}
+
+
+
+
+
+
+ );
+};
+
+export default Dialog;
diff --git a/apps/mobile/src/components/modals/FileModal.tsx b/apps/mobile/src/components/modals/FileModal.tsx
index e5658ee1d..f46017c73 100644
--- a/apps/mobile/src/components/modals/FileModal.tsx
+++ b/apps/mobile/src/components/modals/FileModal.tsx
@@ -3,23 +3,15 @@ import { format } from 'date-fns';
import React, { useRef } from 'react';
import { Button, Pressable, Text, View } from 'react-native';
import { ChevronLeftIcon } from 'react-native-heroicons/outline';
+import { useSnapshot } from 'valtio';
import tw from '../../lib/tailwind';
-import { useFileModalStore } from '../../stores/useModalStore';
-import Divider from '../base/Divider';
+import { fileModalStore } from '../../stores/modalStore';
import FileIcon from '../file/FileIcon';
+import Divider from '../primitive/Divider';
import ModalBackdrop from './layout/ModalBackdrop';
import ModalHandle from './layout/ModalHandle';
-/*
-https://github.com/software-mansion/react-native-reanimated/issues/3296
-https://github.com/gorhom/react-native-bottom-sheet/issues/925
-https://github.com/gorhom/react-native-bottom-sheet/issues/1036
-
-Reanimated has a bug where it sometimes doesn't animate on mount (IOS only?), doing a console.log() seems to do a re-render and fix the issue.
-We can't do this for production obvs but until then they might fix it so, let's not try weird hacks for now and live with the logs.
-*/
-
interface MetaItemProps {
title: string;
value: string;
@@ -35,7 +27,7 @@ function MetaItem({ title, value }: MetaItemProps) {
}
export const FileModal = () => {
- const { fileRef, data } = useFileModalStore();
+ const { fileRef, data } = useSnapshot(fileModalStore);
const fileDetailsRef = useRef(null);
@@ -46,8 +38,6 @@ export const FileModal = () => {
snapPoints={['60%', '90%']}
backdropComponent={ModalBackdrop}
handleComponent={ModalHandle}
- // Do not remove!
- onAnimate={(from, to) => console.log(from, to)}
>
{data && (
@@ -72,7 +62,6 @@ export const FileModal = () => {
{/* Divider */}
{/* Buttons */}
-