mirror of
https://github.com/spacedriveapp/spacedrive
synced 2024-07-07 02:03:28 +00:00
Mobile Actions & File Info Modal (#573)
* better drawer * fix build? * style changes * fix subfolder navigation * bigger icons and drawer style tweaks * Disable Menu animation * more subfolder navigation & title stuff * move tag dialogs to modal * cleanup * Fix text input sizing * Improve modal component * Hide modal close button & fix position * update packages * style create tag / update tag modals. * move dialogs to modal & new modal component * move IsPath and isObject to client + small fixes * fix FileModal * move kind to client * move everything to components + cleanup * move format bytes, info pills, work on fileinfo and actions modal, update packages, rename xcode build step * Update Device.tsx remove placeholder data * small fixes * actions modal header and some styling * fav button * actions item, divider and container components * file actions * file info modal * remove bg-green from Inspector * Add more info to fileinfo modal * Delete unused Device component * fix merge stuff * linting + changed how we export tw + rename tw.style to twStyle
This commit is contained in:
parent
fd39dc3a3d
commit
e9e8d2286c
|
@ -19,6 +19,7 @@ fontsource
|
|||
fontttf
|
||||
fontwoff
|
||||
gopackage
|
||||
gorhom
|
||||
haml
|
||||
headlessui
|
||||
heroicons
|
||||
|
@ -74,11 +75,13 @@ titlebar
|
|||
tmpl
|
||||
tryghost
|
||||
tsparticles
|
||||
twrnc
|
||||
typescriptdef
|
||||
unlisten
|
||||
Waitlist
|
||||
webp
|
||||
windi
|
||||
wunsub
|
||||
xcworkspace
|
||||
yarnerror
|
||||
zustand
|
||||
|
|
|
@ -52,6 +52,7 @@ specta
|
|||
storedkey
|
||||
stringly
|
||||
tobiaslutke
|
||||
typecheck
|
||||
vdfs
|
||||
vijay
|
||||
zacharysmith
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
|
||||
[android]
|
||||
target = Google Inc.:Google APIs:23
|
||||
|
||||
[maven_repositories]
|
||||
central = https://repo1.maven.org/maven2
|
|
@ -14,12 +14,9 @@
|
|||
},
|
||||
"assetBundlePatterns": ["**/*"],
|
||||
"ios": {
|
||||
"supportsTablet": false,
|
||||
"bundleIdentifier": "com.spacedrive.app"
|
||||
},
|
||||
"android": {
|
||||
"package": "com.spacedrive.app"
|
||||
"supportsTablet": false
|
||||
},
|
||||
"android": {},
|
||||
"privacy": "hidden",
|
||||
"extra": {
|
||||
"eas": {
|
||||
|
|
|
@ -1,9 +1,19 @@
|
|||
{
|
||||
"cli": {
|
||||
"version": ">= 0.56.0"
|
||||
"version": ">= 0.56.0",
|
||||
"promptToConfigurePushNotifications": false
|
||||
},
|
||||
"build": {
|
||||
"production": {
|
||||
"node": "18.12.1"
|
||||
},
|
||||
"preview": {
|
||||
"extends": "production",
|
||||
"distribution": "internal"
|
||||
},
|
||||
"development": {
|
||||
"extends": "production",
|
||||
"developmentClient": true,
|
||||
"distribution": "internal",
|
||||
"android": {
|
||||
"gradleCommand": ":app:assembleDebug"
|
||||
|
@ -11,11 +21,7 @@
|
|||
"ios": {
|
||||
"buildConfiguration": "Debug"
|
||||
}
|
||||
},
|
||||
"preview": {
|
||||
"distribution": "internal"
|
||||
},
|
||||
"production": {}
|
||||
}
|
||||
},
|
||||
"submit": {
|
||||
"production": {}
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
import { registerRootComponent } from 'expo';
|
||||
import { AppWrapper } from './src/main';
|
||||
|
||||
// registerRootComponent calls AppRegistry.registerComponent('main', () => App);
|
||||
// It also ensures that whether you load the app in Expo Go or in a native build,
|
||||
// the environment is set up appropriately
|
||||
registerRootComponent(AppWrapper);
|
||||
|
|
|
@ -20,21 +20,23 @@ target 'Spacedrive' do
|
|||
|
||||
use_react_native!(
|
||||
:path => config[:reactNativePath],
|
||||
:hermes_enabled => flags[:hermes_enabled] || podfile_properties['expo.jsEngine'] == 'hermes',
|
||||
:hermes_enabled => podfile_properties['expo.jsEngine'] == 'hermes',
|
||||
:fabric_enabled => flags[:fabric_enabled],
|
||||
# An absolute path to your application root.
|
||||
:app_path => "#{Dir.pwd}/.."
|
||||
)
|
||||
|
||||
:app_path => "#{Pod::Config.instance.installation_root}/..",
|
||||
#
|
||||
# Uncomment to opt-in to using Flipper
|
||||
# Note that if you have use_frameworks! enabled, Flipper will not work
|
||||
#
|
||||
# if !ENV['CI']
|
||||
# use_flipper!()
|
||||
# end
|
||||
# :flipper_configuration => !ENV['CI'] ? FlipperConfiguration.enabled : FlipperConfiguration.disabled,
|
||||
)
|
||||
|
||||
post_install do |installer|
|
||||
react_native_post_install(installer)
|
||||
react_native_post_install(
|
||||
installer,
|
||||
# Set `mac_catalyst_enabled` to `true` in order to apply patches
|
||||
# necessary for Mac Catalyst builds
|
||||
:mac_catalyst_enabled => false
|
||||
)
|
||||
__apply_Xcode_12_5_M1_post_install_workaround(installer)
|
||||
|
||||
# This is necessary for Xcode 14, because it signs resource bundles by default
|
||||
|
@ -56,5 +58,4 @@ target 'Spacedrive' do
|
|||
Pod::UI.warn e
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -266,7 +266,7 @@ PODS:
|
|||
- glog
|
||||
- react-native-document-picker (8.1.3):
|
||||
- React-Core
|
||||
- react-native-safe-area-context (4.4.1):
|
||||
- react-native-safe-area-context (4.5.0):
|
||||
- RCT-Folly
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
|
@ -342,13 +342,13 @@ PODS:
|
|||
- React-Core
|
||||
- RNCMaskedView (0.2.8):
|
||||
- React-Core
|
||||
- RNFlashList (1.4.0):
|
||||
- RNFlashList (1.4.1):
|
||||
- React-Core
|
||||
- RNFS (2.20.0):
|
||||
- React-Core
|
||||
- RNGestureHandler (2.8.0):
|
||||
- RNGestureHandler (2.9.0):
|
||||
- React-Core
|
||||
- RNReanimated (2.13.0):
|
||||
- RNReanimated (2.14.4):
|
||||
- DoubleConversion
|
||||
- FBLazyVector
|
||||
- FBReactNativeSpec
|
||||
|
@ -375,10 +375,10 @@ PODS:
|
|||
- React-RCTText
|
||||
- ReactCommon/turbomodule/core
|
||||
- Yoga
|
||||
- RNScreens (3.18.2):
|
||||
- RNScreens (3.19.0):
|
||||
- React-Core
|
||||
- React-RCTImage
|
||||
- RNSVG (13.6.0):
|
||||
- RNSVG (13.8.0):
|
||||
- React-Core
|
||||
- Yoga (1.14.0)
|
||||
|
||||
|
@ -592,7 +592,7 @@ SPEC CHECKSUMS:
|
|||
React-jsinspector: badd81696361249893a80477983e697aab3c1a34
|
||||
React-logger: fdda34dd285bdb0232e059b19d9606fa0ec3bb9c
|
||||
react-native-document-picker: 958e2bc82e128be69055be261aeac8d872c8d34c
|
||||
react-native-safe-area-context: 99b24a0c5acd0d5dcac2b1a7f18c49ea317be99a
|
||||
react-native-safe-area-context: 39c2d8be3328df5d437ac1700f4f3a4f75716acc
|
||||
React-perflogger: e68d3795cf5d247a0379735cbac7309adf2fb931
|
||||
React-RCTActionSheet: 05452c3b281edb27850253db13ecd4c5a65bc247
|
||||
React-RCTAnimation: 578eebac706428e68466118e84aeacf3a282b4da
|
||||
|
@ -607,14 +607,14 @@ SPEC CHECKSUMS:
|
|||
ReactCommon: c9246996e73bf75a2c6c3ff15f1e16707cdc2da9
|
||||
RNCAsyncStorage: 8616bd5a58af409453ea4e1b246521bb76578d60
|
||||
RNCMaskedView: bc0170f389056201c82a55e242e5d90070e18e5a
|
||||
RNFlashList: 399bf6a0db68f594ad2c86aaff3ea39564f39f8a
|
||||
RNFlashList: 8ec7f7454721145fe84566bb9e88bcf58981c9fe
|
||||
RNFS: 4ac0f0ea233904cb798630b3c077808c06931688
|
||||
RNGestureHandler: 62232ba8f562f7dea5ba1b3383494eb5bf97a4d3
|
||||
RNReanimated: ce445c233a6ff5600223484a88ad5704945d972a
|
||||
RNScreens: 34cc502acf1b916c582c60003dc3089fa01dc66d
|
||||
RNSVG: 3a79c0c4992213e4f06c08e62730c5e7b9e4dc17
|
||||
RNGestureHandler: 071d7a9ad81e8b83fe7663b303d132406a7d8f39
|
||||
RNReanimated: 6668b0587bebd4b15dd849b99e5a9c70fc12ed95
|
||||
RNScreens: ea4cd3a853063cda19a4e3c28d2e52180c80f4eb
|
||||
RNSVG: c1e76b81c76cdcd34b4e1188852892dc280eb902
|
||||
Yoga: eca980a5771bf114c41a754098cd85e6e0d90ed7
|
||||
|
||||
PODFILE CHECKSUM: 144e94249445b1054f55a9e9533c8e6e80450047
|
||||
PODFILE CHECKSUM: 4065c8b949a453403939de6e852185dbd374d972
|
||||
|
||||
COCOAPODS: 1.11.3
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; };
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
|
||||
28422E8DCA8CF99CD27EE152 /* libPods-Spacedrive.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B51EE3BD2C384416ED4B40AC /* libPods-Spacedrive.a */; };
|
||||
3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */; };
|
||||
5574975428A2496C00851D5A /* SDCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 5574975328A2496C00851D5A /* SDCore.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
|
||||
B77FB5363D45EA26C44D71AF /* libPods-Spacedrive.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F6BAE3F0EF420529C3ABCFEB /* libPods-Spacedrive.a */; };
|
||||
BB2F792D24A3F905000567C9 /* Expo.plist in Resources */ = {isa = PBXBuildFile; fileRef = BB2F792C24A3F905000567C9 /* Expo.plist */; };
|
||||
C95AE27BB525EFF3F02CEC11 /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56E71A6EFA9EA8F4C11F42FA /* ExpoModulesProvider.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
@ -25,16 +25,16 @@
|
|||
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
|
||||
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
38392C44BCEE00E37027EE7F /* Pods-Spacedrive.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Spacedrive.debug.xcconfig"; path = "Target Support Files/Pods-Spacedrive/Pods-Spacedrive.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
5574975328A2496C00851D5A /* SDCore.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDCore.m; sourceTree = "<group>"; };
|
||||
5574975528A2498000851D5A /* SDCore.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDCore.h; sourceTree = "<group>"; };
|
||||
5574975628A24E0D00851D5A /* sdcore-universal-ios.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "sdcore-universal-ios.a"; path = "../../../target/sdcore-universal-ios.a"; sourceTree = "<group>"; };
|
||||
561FA870378F3C6C8C923B82 /* Pods-Spacedrive.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Spacedrive.debug.xcconfig"; path = "Target Support Files/Pods-Spacedrive/Pods-Spacedrive.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
56E71A6EFA9EA8F4C11F42FA /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-Spacedrive/ExpoModulesProvider.swift"; sourceTree = "<group>"; };
|
||||
AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = SplashScreen.storyboard; sourceTree = "<group>"; };
|
||||
B51EE3BD2C384416ED4B40AC /* libPods-Spacedrive.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Spacedrive.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
BB2F792C24A3F905000567C9 /* Expo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Expo.plist; path = Supporting/Expo.plist; sourceTree = "<group>"; };
|
||||
D31F33B310E620CF1C91A764 /* Pods-Spacedrive.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Spacedrive.release.xcconfig"; path = "Target Support Files/Pods-Spacedrive/Pods-Spacedrive.release.xcconfig"; sourceTree = "<group>"; };
|
||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
|
||||
F6BAE3F0EF420529C3ABCFEB /* libPods-Spacedrive.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Spacedrive.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
FEA54987FCCB6972B471EA9D /* Pods-Spacedrive.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Spacedrive.release.xcconfig"; path = "Target Support Files/Pods-Spacedrive/Pods-Spacedrive.release.xcconfig"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
@ -42,7 +42,7 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
B77FB5363D45EA26C44D71AF /* libPods-Spacedrive.a in Frameworks */,
|
||||
28422E8DCA8CF99CD27EE152 /* libPods-Spacedrive.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -79,7 +79,7 @@
|
|||
children = (
|
||||
5574975628A24E0D00851D5A /* sdcore-universal-ios.a */,
|
||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
|
||||
F6BAE3F0EF420529C3ABCFEB /* libPods-Spacedrive.a */,
|
||||
B51EE3BD2C384416ED4B40AC /* libPods-Spacedrive.a */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
|
@ -125,8 +125,8 @@
|
|||
D65327D7A22EEC0BE12398D9 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
561FA870378F3C6C8C923B82 /* Pods-Spacedrive.debug.xcconfig */,
|
||||
FEA54987FCCB6972B471EA9D /* Pods-Spacedrive.release.xcconfig */,
|
||||
38392C44BCEE00E37027EE7F /* Pods-Spacedrive.debug.xcconfig */,
|
||||
D31F33B310E620CF1C91A764 /* Pods-Spacedrive.release.xcconfig */,
|
||||
);
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
|
@ -146,15 +146,15 @@
|
|||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "Spacedrive" */;
|
||||
buildPhases = (
|
||||
EE23FABC21723647AF9773BD /* [CP] Check Pods Manifest.lock */,
|
||||
BC1F37E21575379C81F561DC /* [CP] Check Pods Manifest.lock */,
|
||||
FD10A7F022414F080027D42C /* Start Packager */,
|
||||
350DC403297BF2B8009CD6A1 /* Build sd-core-ios */,
|
||||
350DC403297BF2B8009CD6A1 /* Build Spacedrive Core */,
|
||||
13B07F871A680F5B00A75B9A /* Sources */,
|
||||
13B07F8C1A680F5B00A75B9A /* Frameworks */,
|
||||
13B07F8E1A680F5B00A75B9A /* Resources */,
|
||||
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
|
||||
F34AD9F4411557890BECFB5B /* [CP] Embed Pods Frameworks */,
|
||||
37F7445AEFB5A9FBEDBB3916 /* [CP] Copy Pods Resources */,
|
||||
65CB42BC732A49C59CCA544A /* [CP] Embed Pods Frameworks */,
|
||||
FFF29AD1ADC998E2209017DB /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
|
@ -224,7 +224,7 @@
|
|||
shellPath = /bin/sh;
|
||||
shellScript = "export NODE_BINARY=node\n\n# The project root by default is one level up from the ios directory\nexport PROJECT_ROOT=\"$PROJECT_DIR\"/..\n\n`node --print \"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'\"`\n";
|
||||
};
|
||||
350DC403297BF2B8009CD6A1 /* Build sd-core-ios */ = {
|
||||
350DC403297BF2B8009CD6A1 /* Build Spacedrive Core */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
buildActionMask = 2147483647;
|
||||
|
@ -234,7 +234,7 @@
|
|||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Build sd-core-ios";
|
||||
name = "Build Spacedrive Core";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
|
@ -243,27 +243,25 @@
|
|||
shellPath = /bin/zsh;
|
||||
shellScript = "env -i CONFIGURATION=$CONFIGURATION PLATFORM_NAME=$PLATFORM_NAME ./build-rust.sh\n";
|
||||
};
|
||||
37F7445AEFB5A9FBEDBB3916 /* [CP] Copy Pods Resources */ = {
|
||||
65CB42BC732A49C59CCA544A /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Spacedrive/Pods-Spacedrive-resources.sh",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/AccessibilityResources.bundle",
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Spacedrive/Pods-Spacedrive-frameworks.sh",
|
||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/hermes.framework/hermes",
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXConstants.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AccessibilityResources.bundle",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Spacedrive/Pods-Spacedrive-resources.sh\"\n";
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Spacedrive/Pods-Spacedrive-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
EE23FABC21723647AF9773BD /* [CP] Check Pods Manifest.lock */ = {
|
||||
BC1F37E21575379C81F561DC /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
|
@ -285,24 +283,6 @@
|
|||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
F34AD9F4411557890BECFB5B /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Spacedrive/Pods-Spacedrive-frameworks.sh",
|
||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/hermes.framework/hermes",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Spacedrive/Pods-Spacedrive-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
FD10A7F022414F080027D42C /* Start Packager */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
@ -322,6 +302,26 @@
|
|||
shellScript = "export RCT_METRO_PORT=\"${RCT_METRO_PORT:=8081}\"\necho \"export RCT_METRO_PORT=${RCT_METRO_PORT}\" > `node --print \"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/.packager.env'\"`\nif [ -z \"${RCT_NO_LAUNCH_PACKAGER+xxx}\" ] ; then\n if nc -w 5 -z localhost ${RCT_METRO_PORT} ; then\n if ! curl -s \"http://localhost:${RCT_METRO_PORT}/status\" | grep -q \"packager-status:running\" ; then\n echo \"Port ${RCT_METRO_PORT} already in use, packager is either not running or not running correctly\"\n exit 2\n fi\n else\n open `node --print \"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/launchPackager.command'\"` || echo \"Can't start packager automatically\"\n fi\nfi\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
FFF29AD1ADC998E2209017DB /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Spacedrive/Pods-Spacedrive-resources.sh",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/AccessibilityResources.bundle",
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXConstants.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AccessibilityResources.bundle",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Spacedrive/Pods-Spacedrive-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
|
@ -341,7 +341,7 @@
|
|||
/* Begin XCBuildConfiguration section */
|
||||
13B07F941A680F5B00A75B9A /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 561FA870378F3C6C8C923B82 /* Pods-Spacedrive.debug.xcconfig */;
|
||||
baseConfigurationReference = 38392C44BCEE00E37027EE7F /* Pods-Spacedrive.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
|
||||
|
@ -441,7 +441,7 @@
|
|||
};
|
||||
13B07F951A680F5B00A75B9A /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = FEA54987FCCB6972B471EA9D /* Pods-Spacedrive.release.xcconfig */;
|
||||
baseConfigurationReference = D31F33B310E620CF1C91A764 /* Pods-Spacedrive.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
|
||||
|
|
|
@ -12,45 +12,46 @@
|
|||
"android-studio": "open -a '/Applications/Android Studio.app' ./android",
|
||||
"lint": "eslint src",
|
||||
"postinstall": "node scripts/postinstall.js",
|
||||
"typecheck": "tsc -b"
|
||||
"typecheck": "tsc -b",
|
||||
"eas-build-pre-install": "npm i -g pnpm@7.18.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@gorhom/bottom-sheet": "^4.4.5",
|
||||
"@react-native-async-storage/async-storage": "~1.17.11",
|
||||
"@react-native-masked-view/masked-view": "0.2.8",
|
||||
"@react-navigation/bottom-tabs": "^6.5.2",
|
||||
"@react-navigation/drawer": "^6.5.6",
|
||||
"@react-navigation/native": "^6.0.13",
|
||||
"@react-navigation/stack": "^6.3.10",
|
||||
"@react-navigation/bottom-tabs": "^6.5.4",
|
||||
"@react-navigation/drawer": "^6.5.8",
|
||||
"@react-navigation/native": "^6.1.3",
|
||||
"@react-navigation/stack": "^6.3.12",
|
||||
"@rspc/client": "^0.0.0-main-7c0a67c1",
|
||||
"@rspc/react": "^0.0.0-main-7c0a67c1",
|
||||
"@sd/assets": "workspace:*",
|
||||
"@sd/client": "workspace:*",
|
||||
"@shopify/flash-list": "1.4.0",
|
||||
"@tanstack/react-query": "^4.20.9",
|
||||
"@shopify/flash-list": "1.4.1",
|
||||
"@tanstack/react-query": "^4.24.4",
|
||||
"byte-size": "^8.1.0",
|
||||
"class-variance-authority": "^0.4.0",
|
||||
"dayjs": "^1.11.6",
|
||||
"expo": "^47.0.10",
|
||||
"dayjs": "^1.11.5",
|
||||
"expo": "^47.0.13",
|
||||
"expo-linking": "~3.3.0",
|
||||
"expo-media-library": "~15.0.0",
|
||||
"expo-splash-screen": "~0.17.5",
|
||||
"expo-status-bar": "~1.4.2",
|
||||
"intl": "^1.2.5",
|
||||
"lottie-react-native": "5.1.4",
|
||||
"moti": "^0.21.0",
|
||||
"moti": "^0.22.0",
|
||||
"phosphor-react-native": "^1.1.2",
|
||||
"react": "18.1.0",
|
||||
"react-hook-form": "^7.41.5",
|
||||
"react-hook-form": "^7.43.0",
|
||||
"react-native": "0.70.5",
|
||||
"react-native-document-picker": "^8.1.1",
|
||||
"react-native-fs": "^2.20.0",
|
||||
"react-native-gesture-handler": "~2.8.0",
|
||||
"react-native-gesture-handler": "~2.9.0",
|
||||
"react-native-popup-menu": "^0.16.1",
|
||||
"react-native-reanimated": "~2.13.0",
|
||||
"react-native-safe-area-context": "4.4.1",
|
||||
"react-native-screens": "~3.18.2",
|
||||
"react-native-svg": "13.6.0",
|
||||
"react-native-reanimated": "~2.14.4",
|
||||
"react-native-safe-area-context": "4.5.0",
|
||||
"react-native-screens": "~3.19.0",
|
||||
"react-native-svg": "13.8.0",
|
||||
"react-native-wheel-color-picker": "^1.2.0",
|
||||
"twrnc": "^3.5.0",
|
||||
"use-count-up": "^3.0.1",
|
||||
|
@ -58,13 +59,13 @@
|
|||
"valtio": "^1.8.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rnx-kit/metro-config": "^1.3.2",
|
||||
"@rnx-kit/metro-config": "^1.3.5",
|
||||
"@sd/config": "workspace:*",
|
||||
"@types/react": "~18.0.26",
|
||||
"@types/react-native": "~0.70.8",
|
||||
"babel-plugin-module-resolver": "^4.1.0",
|
||||
"babel-plugin-module-resolver": "^5.0.0",
|
||||
"eslint-plugin-react-native": "^4.0.0",
|
||||
"metro-minify-terser": "^0.73.6",
|
||||
"metro-minify-terser": "^0.74.1",
|
||||
"react-native-svg-transformer": "^1.0.0",
|
||||
"typescript": "^4.9.4"
|
||||
}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
import { BottomSheetModalProvider } from '@gorhom/bottom-sheet';
|
||||
import { DefaultTheme, NavigationContainer, Theme } from '@react-navigation/native';
|
||||
import { loggerLink } from '@rspc/client';
|
||||
import dayjs from 'dayjs';
|
||||
import advancedFormat from 'dayjs/plugin/advancedFormat';
|
||||
import duration from 'dayjs/plugin/duration';
|
||||
import relativeTime from 'dayjs/plugin/relativeTime';
|
||||
import * as SplashScreen from 'expo-splash-screen';
|
||||
import { StatusBar } from 'expo-status-bar';
|
||||
import { useEffect } from 'react';
|
||||
|
@ -16,12 +20,16 @@ import {
|
|||
useCurrentLibrary,
|
||||
useInvalidateQuery
|
||||
} from '@sd/client';
|
||||
import { GlobalModals } from './containers/modal/GlobalModals';
|
||||
import { GlobalModals } from './components/modal/GlobalModals';
|
||||
import { reactNativeLink } from './lib/rspcReactNativeTransport';
|
||||
import tw from './lib/tailwind';
|
||||
import { tw } from './lib/tailwind';
|
||||
import RootNavigator from './navigation';
|
||||
import OnboardingNavigator from './navigation/OnboardingNavigator';
|
||||
|
||||
dayjs.extend(advancedFormat);
|
||||
dayjs.extend(relativeTime);
|
||||
dayjs.extend(duration);
|
||||
|
||||
const NavigatorTheme: Theme = {
|
||||
...DefaultTheme,
|
||||
colors: {
|
||||
|
@ -45,9 +53,15 @@ function AppContainer() {
|
|||
<BottomSheetModalProvider>
|
||||
<StatusBar style="light" />
|
||||
<NavigationContainer theme={NavigatorTheme}>
|
||||
{!library ? <OnboardingNavigator /> : <RootNavigator />}
|
||||
</NavigationContainer>
|
||||
{!library ? (
|
||||
<OnboardingNavigator />
|
||||
) : (
|
||||
<>
|
||||
<RootNavigator />
|
||||
<GlobalModals />
|
||||
</>
|
||||
)}
|
||||
</NavigationContainer>
|
||||
</BottomSheetModalProvider>
|
||||
</MenuProvider>
|
||||
</GestureHandlerRootView>
|
||||
|
|
|
@ -3,7 +3,7 @@ import { PropsWithChildren, ReactNode } 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 { tw } from '~/lib/tailwind';
|
||||
|
||||
// Anything wrapped with FadeIn will fade in on mount.
|
||||
export const FadeInAnimation = ({ children, delay }: PropsWithChildren<{ delay?: number }>) => (
|
||||
|
|
|
@ -1,143 +0,0 @@
|
|||
import { Cloud, Desktop, DeviceMobileCamera, Laptop, Lock } from 'phosphor-react-native';
|
||||
import { FlatList, Text, View } from 'react-native';
|
||||
import { ExplorerItem } from '@sd/client';
|
||||
import tw from '~/lib/tailwind';
|
||||
import FileItem from '../explorer/FileItem';
|
||||
|
||||
const placeholderFileItems: ExplorerItem[] = [
|
||||
{
|
||||
type: 'Path',
|
||||
item: {
|
||||
date_created: '2020-01-01T00:00:00.000Z',
|
||||
date_indexed: '2020-01-01T00:00:00.000Z',
|
||||
date_modified: '2020-01-01T00:00:00.000Z',
|
||||
extension: '',
|
||||
cas_id: '3',
|
||||
integrity_checksum: '',
|
||||
id: 2,
|
||||
name: 'Documents',
|
||||
key_id: null,
|
||||
is_dir: true,
|
||||
location_id: 1,
|
||||
materialized_path: '/Documents',
|
||||
object_id: 5,
|
||||
parent_id: 1,
|
||||
object: {
|
||||
extension: 'tsx',
|
||||
id: 3,
|
||||
pub_id: [3],
|
||||
name: 'App.tsx',
|
||||
key_id: null,
|
||||
date_created: '2020-01-01T00:00:00.000Z',
|
||||
date_indexed: '2020-01-01T00:00:00.000Z',
|
||||
date_modified: '2020-01-01T00:00:00.000Z',
|
||||
favorite: false,
|
||||
has_thumbnail: false,
|
||||
has_thumbstrip: false,
|
||||
has_video_preview: false,
|
||||
hidden: false,
|
||||
important: false,
|
||||
ipfs_id: '',
|
||||
kind: 2,
|
||||
note: '',
|
||||
size_in_bytes: '0'
|
||||
}
|
||||
},
|
||||
has_thumbnail: false
|
||||
},
|
||||
{
|
||||
type: 'Object',
|
||||
has_thumbnail: false,
|
||||
item: {
|
||||
date_created: '2020-01-01T00:00:00.000Z',
|
||||
date_indexed: '2020-01-01T00:00:00.000Z',
|
||||
date_modified: '2020-01-01T00:00:00.000Z',
|
||||
extension: '',
|
||||
id: 1,
|
||||
pub_id: [1],
|
||||
name: 'Minecraft',
|
||||
key_id: null,
|
||||
favorite: false,
|
||||
file_paths: [],
|
||||
has_thumbnail: false,
|
||||
has_thumbstrip: false,
|
||||
has_video_preview: false,
|
||||
hidden: false,
|
||||
important: false,
|
||||
ipfs_id: '',
|
||||
kind: 4,
|
||||
note: '',
|
||||
size_in_bytes: '0'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'Object',
|
||||
has_thumbnail: false,
|
||||
item: {
|
||||
date_created: '2020-01-01T00:00:00.000Z',
|
||||
date_indexed: '2020-01-01T00:00:00.000Z',
|
||||
date_modified: '2020-01-01T00:00:00.000Z',
|
||||
extension: '',
|
||||
id: 5,
|
||||
pub_id: [5],
|
||||
name: 'Minecraft',
|
||||
key_id: null,
|
||||
favorite: false,
|
||||
file_paths: [],
|
||||
has_thumbnail: false,
|
||||
has_thumbstrip: false,
|
||||
has_video_preview: false,
|
||||
hidden: false,
|
||||
important: false,
|
||||
ipfs_id: '',
|
||||
kind: 5,
|
||||
note: '',
|
||||
size_in_bytes: '0'
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
type DeviceProps = {
|
||||
name: string;
|
||||
size: string;
|
||||
type: keyof typeof DeviceIcon;
|
||||
locations: { name: string; folder?: boolean; format?: string; icon?: string }[];
|
||||
runningJob?: { amount: number; task: string };
|
||||
};
|
||||
|
||||
const DeviceIcon = {
|
||||
phone: <DeviceMobileCamera color="white" weight="fill" size={18} style={tw`mr-2`} />,
|
||||
laptop: <Laptop color="white" weight="fill" size={18} style={tw`mr-2`} />,
|
||||
desktop: <Desktop color="white" weight="fill" size={18} style={tw`mr-2`} />,
|
||||
server: <Cloud color="white" weight="fill" size={18} style={tw`mr-2`} />
|
||||
};
|
||||
|
||||
const Device = ({ name, size, type }: DeviceProps) => {
|
||||
return (
|
||||
<View style={tw`bg-app-overlay border-app-line my-2 rounded-md border`}>
|
||||
<View style={tw`flex flex-row items-center px-3.5 pt-3 pb-2`}>
|
||||
<View style={tw`flex flex-row items-center`}>
|
||||
{DeviceIcon[type]}
|
||||
<Text style={tw`text-ink text-base font-semibold`}>{name || 'Unnamed Device'}</Text>
|
||||
{/* P2P Lock */}
|
||||
<View style={tw`bg-app-box ml-2 flex flex-row items-center rounded py-[1px] px-[4px]`}>
|
||||
<Lock weight="bold" size={12} color={tw.color('ink-dull')} />
|
||||
<Text style={tw`text-ink-dull ml-0.5 text-xs font-semibold`}>P2P</Text>
|
||||
</View>
|
||||
</View>
|
||||
{/* Size */}
|
||||
<Text style={tw`text-ink-dull ml-2 text-sm font-semibold`}>{size}</Text>
|
||||
</View>
|
||||
<FlatList
|
||||
data={placeholderFileItems}
|
||||
renderItem={({ item }) => <FileItem data={item} />}
|
||||
keyExtractor={(item) => item.item.id.toString()}
|
||||
horizontal
|
||||
contentContainerStyle={tw`mt-3 mb-5`}
|
||||
showsHorizontalScrollIndicator={false}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default Device;
|
|
@ -9,6 +9,7 @@ type Props = {
|
|||
children: React.ReactNode;
|
||||
};
|
||||
|
||||
// TODO: Move to a Modal component
|
||||
const CreateLibraryDialog = ({ children, onSubmit, disableBackdropClose }: Props) => {
|
||||
const [libName, setLibName] = useState('');
|
||||
const [isOpen, setIsOpen] = useState(false);
|
|
@ -3,9 +3,8 @@ import { DrawerContentComponentProps } from '@react-navigation/drawer/lib/typesc
|
|||
import { Gear } from 'phosphor-react-native';
|
||||
import { Image, Platform, Pressable, Text, View } from 'react-native';
|
||||
import Layout from '~/constants/Layout';
|
||||
import tw, { twStyle } from '~/lib/tailwind';
|
||||
import { tw, twStyle } from '~/lib/tailwind';
|
||||
import { getStackNameFromState } from '~/utils/nav';
|
||||
import Divider from '../../components/primitive/Divider';
|
||||
import DrawerLibraryManager from './DrawerLibraryManager';
|
||||
import DrawerLocations from './DrawerLocations';
|
||||
import DrawerTags from './DrawerTags';
|
||||
|
@ -19,14 +18,14 @@ const DrawerContent = ({ navigation, state }: DrawerContentComponentProps) => {
|
|||
const stackName = getStackNameFromState(state);
|
||||
|
||||
return (
|
||||
<DrawerContentScrollView style={tw`flex-1 px-4 py-2`} scrollEnabled={false}>
|
||||
<DrawerContentScrollView style={tw`flex-1 px-3 py-2`} scrollEnabled={false}>
|
||||
<View style={twStyle('justify-between', { height: drawerHeight })}>
|
||||
<View>
|
||||
<View style={tw`flex flex-row items-center`}>
|
||||
<Image source={require('@sd/assets/images/logo.png')} style={tw`h-[35px] w-[35px]`} />
|
||||
<Text style={tw`text-ink ml-2 text-base font-bold`}>Spacedrive</Text>
|
||||
<Image source={require('@sd/assets/images/logo.png')} style={tw`h-[40px] w-[40px]`} />
|
||||
<Text style={tw`text-ink ml-2 text-lg font-bold`}>Spacedrive</Text>
|
||||
</View>
|
||||
<Divider style={tw`my-4`} />
|
||||
<View style={tw`mt-6`} />
|
||||
{/* Library Manager */}
|
||||
<DrawerLibraryManager />
|
||||
{/* Locations */}
|
|
@ -1,14 +1,14 @@
|
|||
import { useDrawerStatus } from '@react-navigation/drawer';
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
import { MotiView } from 'moti';
|
||||
import { CaretRight, Gear, Lock, Plus } from 'phosphor-react-native';
|
||||
import { CaretDown, Gear, Lock, Plus } from 'phosphor-react-native';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Pressable, Text, View } from 'react-native';
|
||||
import { Alert, Pressable, Text, View } from 'react-native';
|
||||
import { useCurrentLibrary } from '~/../../../packages/client/src';
|
||||
import tw, { twStyle } from '~/lib/tailwind';
|
||||
import { AnimatedHeight } from '../../components/animation/layout';
|
||||
import Divider from '../../components/primitive/Divider';
|
||||
import { tw, twStyle } from '~/lib/tailwind';
|
||||
import { AnimatedHeight } from '../animation/layout';
|
||||
import CreateLibraryDialog from '../dialog/CreateLibraryDialog';
|
||||
import Divider from '../primitive/Divider';
|
||||
|
||||
const DrawerLibraryManager = () => {
|
||||
const [dropdownClosed, setDropdownClosed] = useState(true);
|
||||
|
@ -28,23 +28,26 @@ const DrawerLibraryManager = () => {
|
|||
<Pressable onPress={() => setDropdownClosed((v) => !v)}>
|
||||
<View
|
||||
style={twStyle(
|
||||
'border-app-darkLine bg-app-box flex h-10 w-full flex-row items-center justify-between border px-3 shadow-sm',
|
||||
dropdownClosed ? 'rounded' : 'border-b-app-box rounded-t'
|
||||
'bg-sidebar-box flex h-10 w-full flex-row items-center justify-between border px-3 shadow-sm',
|
||||
dropdownClosed
|
||||
? 'border-sidebar-line/50 rounded-md'
|
||||
: 'border-b-app-box border-sidebar-line bg-sidebar-button rounded-t-md'
|
||||
)}
|
||||
>
|
||||
<Text style={tw`text-ink text-sm font-semibold`}>{currentLibrary?.config.name}</Text>
|
||||
<MotiView
|
||||
animate={{
|
||||
rotateZ: dropdownClosed ? '0deg' : '90deg'
|
||||
rotate: dropdownClosed ? '0deg' : '180deg',
|
||||
translateX: dropdownClosed ? 0 : -9
|
||||
}}
|
||||
transition={{ type: 'timing' }}
|
||||
transition={{ type: 'timing', duration: 100 }}
|
||||
>
|
||||
<CaretRight color={tw.color('text-ink')} size={16} style={tw`ml-2`} />
|
||||
<CaretDown color="white" size={18} weight="bold" style={tw`ml-2`} />
|
||||
</MotiView>
|
||||
</View>
|
||||
</Pressable>
|
||||
<AnimatedHeight hide={dropdownClosed}>
|
||||
<View style={tw`border-app-darkLine bg-app-box rounded-b border-x border-b p-2`}>
|
||||
<View style={tw`bg-sidebar-button border-sidebar-line rounded-b-md border-x border-b p-2`}>
|
||||
{/* Libraries */}
|
||||
{libraries?.map((library) => (
|
||||
<Pressable key={library.uuid} onPress={() => switchLibrary(library.uuid)}>
|
||||
|
@ -67,25 +70,27 @@ const DrawerLibraryManager = () => {
|
|||
))}
|
||||
<Divider style={tw`my-2`} />
|
||||
{/* Menu */}
|
||||
{/* Create Library */}
|
||||
<CreateLibraryDialog>
|
||||
<View style={tw`flex flex-row items-center px-1.5 py-[8px]`}>
|
||||
<Plus size={18} weight="bold" color="white" style={tw`mr-2`} />
|
||||
<Text style={tw`text-sm font-semibold text-white`}>New Library</Text>
|
||||
</View>
|
||||
</CreateLibraryDialog>
|
||||
{/* Manage Library */}
|
||||
<Pressable
|
||||
onPress={() => navigation.navigate('Settings', { screen: 'LibraryGeneralSettings' })}
|
||||
>
|
||||
<View style={tw`flex flex-row items-center px-1.5 py-[8px]`}>
|
||||
<Gear size={16} color={tw.color('ink-dull')} style={tw`mr-2`} />
|
||||
<Text style={tw`text-ink text-sm font-semibold`}>Library Settings</Text>
|
||||
<Gear size={18} weight="bold" color="white" style={tw`mr-2`} />
|
||||
<Text style={tw`text-sm font-semibold text-white`}>Manage Library</Text>
|
||||
</View>
|
||||
</Pressable>
|
||||
{/* Create Library */}
|
||||
<CreateLibraryDialog>
|
||||
{/* Lock */}
|
||||
<Pressable onPress={() => Alert.alert('TODO')}>
|
||||
<View style={tw`flex flex-row items-center px-1.5 py-[8px]`}>
|
||||
<Plus size={16} weight="bold" color={tw.color('ink-dull')} style={tw`mr-2`} />
|
||||
<Text style={tw`text-ink text-sm font-semibold`}>Add Library</Text>
|
||||
</View>
|
||||
</CreateLibraryDialog>
|
||||
<Pressable onPress={() => console.log('TODO: lock')}>
|
||||
<View style={tw`flex flex-row items-center px-1.5 py-[8px]`}>
|
||||
<Lock size={16} weight="bold" color={tw.color('ink-dull')} style={tw`mr-2`} />
|
||||
<Text style={tw`text-ink text-sm font-semibold`}>Lock</Text>
|
||||
<Lock size={18} weight="bold" color="white" style={tw`mr-2`} />
|
||||
<Text style={tw`text-sm font-semibold text-white`}>Lock</Text>
|
||||
</View>
|
||||
</Pressable>
|
||||
</View>
|
|
@ -1,12 +1,12 @@
|
|||
import { BottomSheetModal } from '@gorhom/bottom-sheet';
|
||||
import { DrawerNavigationHelpers } from '@react-navigation/drawer/lib/typescript/src/types';
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
import { useRef } from 'react';
|
||||
import { Pressable, Text, View } from 'react-native';
|
||||
import { useLibraryQuery } from '@sd/client';
|
||||
import tw, { twStyle } from '~/lib/tailwind';
|
||||
import FolderIcon from '../../components/icons/FolderIcon';
|
||||
import CollapsibleView from '../../components/layout/CollapsibleView';
|
||||
import { ModalRef } from '~/components/layout/Modal';
|
||||
import { tw, twStyle } from '~/lib/tailwind';
|
||||
import FolderIcon from '../icons/FolderIcon';
|
||||
import CollapsibleView from '../layout/CollapsibleView';
|
||||
import ImportModal from '../modal/ImportModal';
|
||||
|
||||
type DrawerLocationItemProps = {
|
||||
|
@ -20,8 +20,8 @@ const DrawerLocationItem: React.FC<DrawerLocationItemProps> = (props) => {
|
|||
return (
|
||||
<Pressable onPress={onPress}>
|
||||
<View style={twStyle('mb-[4px] flex flex-row items-center rounded py-2 px-1')}>
|
||||
<FolderIcon size={18} />
|
||||
<Text style={twStyle('ml-2 text-sm font-medium text-gray-300')} numberOfLines={1}>
|
||||
<FolderIcon size={20} />
|
||||
<Text style={twStyle('ml-1.5 font-medium text-gray-300')} numberOfLines={1}>
|
||||
{folderName}
|
||||
</Text>
|
||||
</View>
|
||||
|
@ -36,7 +36,7 @@ type DrawerLocationsProp = {
|
|||
const DrawerLocations = ({ stackName }: DrawerLocationsProp) => {
|
||||
const navigation = useNavigation<DrawerNavigationHelpers>();
|
||||
|
||||
const importModalRef = useRef<BottomSheetModal>();
|
||||
const importModalRef = useRef<ModalRef>();
|
||||
|
||||
const { data: locations } = useLibraryQuery(['locations.list'], { keepPreviousData: true });
|
||||
|
||||
|
@ -45,7 +45,7 @@ const DrawerLocations = ({ stackName }: DrawerLocationsProp) => {
|
|||
<CollapsibleView
|
||||
title="Locations"
|
||||
titleStyle={tw`text-sm font-semibold text-gray-300`}
|
||||
containerStyle={tw`mt-6 mb-3`}
|
||||
containerStyle={tw`mt-6 mb-3 ml-1`}
|
||||
>
|
||||
<View style={tw`mt-2`}>
|
||||
{locations?.map((location) => (
|
|
@ -1,10 +1,12 @@
|
|||
import { DrawerNavigationHelpers } from '@react-navigation/drawer/lib/typescript/src/types';
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
import { useRef } from 'react';
|
||||
import { ColorValue, Pressable, Text, View } from 'react-native';
|
||||
import { useLibraryQuery } from '@sd/client';
|
||||
import tw, { twStyle } from '~/lib/tailwind';
|
||||
import CollapsibleView from '../../components/layout/CollapsibleView';
|
||||
import CreateTagDialog from '../dialog/tag/CreateTagDialog';
|
||||
import { ModalRef } from '~/components/layout/Modal';
|
||||
import { tw, twStyle } from '~/lib/tailwind';
|
||||
import CollapsibleView from '../layout/CollapsibleView';
|
||||
import CreateTagModal from '../modal/tag/CreateTagModal';
|
||||
|
||||
type DrawerTagItemProps = {
|
||||
tagName: string;
|
||||
|
@ -17,7 +19,7 @@ const DrawerTagItem: React.FC<DrawerTagItemProps> = (props) => {
|
|||
return (
|
||||
<Pressable onPress={onPress}>
|
||||
<View style={twStyle('mb-[4px] flex flex-row items-center rounded py-2 px-1')}>
|
||||
<View style={twStyle('h-3 w-3 rounded-full', { backgroundColor: tagColor })} />
|
||||
<View style={twStyle('h-3.5 w-3.5 rounded-full', { backgroundColor: tagColor })} />
|
||||
<Text style={twStyle('ml-2 text-sm font-medium text-gray-300')} numberOfLines={1}>
|
||||
{tagName}
|
||||
</Text>
|
||||
|
@ -35,11 +37,13 @@ const DrawerTags = ({ stackName }: DrawerTagsProp) => {
|
|||
|
||||
const { data: tags } = useLibraryQuery(['tags.list'], { keepPreviousData: true });
|
||||
|
||||
const createTagModalRef = useRef<ModalRef>();
|
||||
|
||||
return (
|
||||
<CollapsibleView
|
||||
title="Tags"
|
||||
titleStyle={tw`text-sm font-semibold text-gray-300`}
|
||||
containerStyle={tw`mt-6 mb-3`}
|
||||
containerStyle={tw`mt-6 mb-3 ml-1`}
|
||||
>
|
||||
<View style={tw`mt-2`}>
|
||||
{tags?.map((tag) => (
|
||||
|
@ -57,11 +61,12 @@ const DrawerTags = ({ stackName }: DrawerTagsProp) => {
|
|||
))}
|
||||
</View>
|
||||
{/* Add Tag */}
|
||||
<CreateTagDialog>
|
||||
<View style={tw`border-opacity/80 border-app-line mt-1 rounded border border-dashed`}>
|
||||
<Pressable onPress={() => createTagModalRef.current.present()}>
|
||||
<View style={tw`border-app-line/80 mt-1 rounded border border-dashed`}>
|
||||
<Text style={tw`p-2 text-center text-xs font-bold text-gray-400`}>Add Tag</Text>
|
||||
</View>
|
||||
</CreateTagDialog>
|
||||
</Pressable>
|
||||
<CreateTagModal ref={createTagModalRef} />
|
||||
</CollapsibleView>
|
||||
);
|
||||
};
|
|
@ -1,16 +1,15 @@
|
|||
import { FlashList } from '@shopify/flash-list';
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
import { Rows, SquaresFour } from 'phosphor-react-native';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useState } from 'react';
|
||||
import { Pressable, View } from 'react-native';
|
||||
import { ExplorerData, ExplorerItem } from '@sd/client';
|
||||
import { ExplorerData, ExplorerItem, isPath } from '@sd/client';
|
||||
import SortByMenu from '~/components/menu/SortByMenu';
|
||||
import Layout from '~/constants/Layout';
|
||||
import SortByMenu from '~/containers/menu/SortByMenu';
|
||||
import tw from '~/lib/tailwind';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
import { SharedScreenProps } from '~/navigation/SharedScreens';
|
||||
import { getExplorerStore } from '~/stores/explorerStore';
|
||||
import { useFileModalStore } from '~/stores/modalStore';
|
||||
import { isPath } from '~/types/helper';
|
||||
import { useActionsModalStore } from '~/stores/modalStore';
|
||||
import FileItem from './FileItem';
|
||||
import FileRow from './FileRow';
|
||||
|
||||
|
@ -29,21 +28,14 @@ const Explorer = ({ data }: ExplorerProps) => {
|
|||
getExplorerStore().layoutMode = kind;
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
// Set screen title to location name.
|
||||
navigation.setOptions({
|
||||
title: data?.context.name
|
||||
});
|
||||
}, [data, navigation]);
|
||||
const { modalRef, setData } = useActionsModalStore();
|
||||
|
||||
const { fileRef, setData } = useFileModalStore();
|
||||
|
||||
function handlePress(item: ExplorerItem) {
|
||||
if (isPath(item) && item.item.is_dir) {
|
||||
navigation.navigate('Location', { id: item.item.location_id });
|
||||
function handlePress(data: ExplorerItem) {
|
||||
if (isPath(data) && data.item.is_dir) {
|
||||
navigation.push('Location', { id: data.item.location_id, path: data.item.materialized_path });
|
||||
} else {
|
||||
setData(item);
|
||||
fileRef.current.present();
|
||||
setData(data);
|
||||
modalRef.current.present();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import { Text, View } from 'react-native';
|
||||
import { ExplorerItem, ObjectKind } from '@sd/client';
|
||||
import { ExplorerItem, ObjectKind, isObject } from '@sd/client';
|
||||
import Layout from '~/constants/Layout';
|
||||
import tw, { twStyle } from '~/lib/tailwind';
|
||||
import { tw, twStyle } from '~/lib/tailwind';
|
||||
import { getExplorerStore } from '~/stores/explorerStore';
|
||||
import { isObject } from '~/types/helper';
|
||||
import FileThumb from './FileThumb';
|
||||
|
||||
type FileItemProps = {
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import React from 'react';
|
||||
import { Text, View } from 'react-native';
|
||||
import { ExplorerItem, ObjectKind } from '@sd/client';
|
||||
import tw, { twStyle } from '~/lib/tailwind';
|
||||
import { ExplorerItem, ObjectKind, isObject } from '@sd/client';
|
||||
import { tw, twStyle } from '~/lib/tailwind';
|
||||
import { getExplorerStore } from '~/stores/explorerStore';
|
||||
import { isObject } from '~/types/helper';
|
||||
import FileThumb from './FileThumb';
|
||||
|
||||
type FileRowProps = {
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import { Image, View } from 'react-native';
|
||||
import { DocumentDirectoryPath } from 'react-native-fs';
|
||||
import { ExplorerItem } from '@sd/client';
|
||||
import { isObject, isPath } from '~/types/helper';
|
||||
import { ExplorerItem, isObject, isPath } from '@sd/client';
|
||||
// import icons from '../../assets/icons/file';
|
||||
import tw from '../../lib/tailwind';
|
||||
import { tw } from '../../lib/tailwind';
|
||||
import FolderIcon from '../icons/FolderIcon';
|
||||
|
||||
type FileThumbProps = {
|
||||
|
@ -38,8 +37,8 @@ export default function FileThumb({ data, size = 1, kind }: FileThumbProps) {
|
|||
</FileThumbWrapper>
|
||||
);
|
||||
|
||||
const cas_id = isObject(data) ? data.item.file_paths[0].cas_id : data.item.cas_id;
|
||||
if (!cas_id) return undefined;
|
||||
const casId = isObject(data) ? data.item.file_paths[0]?.cas_id : data.item.cas_id;
|
||||
if (!casId) return undefined;
|
||||
|
||||
// Icon
|
||||
let icon = undefined;
|
||||
|
@ -57,9 +56,8 @@ export default function FileThumb({ data, size = 1, kind }: FileThumbProps) {
|
|||
);
|
||||
}
|
||||
|
||||
const url = getThumbnailUrlById(cas_id);
|
||||
const url = getThumbnailUrlById(casId);
|
||||
|
||||
// TODO: Not styled yet
|
||||
if (data.has_thumbnail && url) {
|
||||
return (
|
||||
<FileThumbWrapper size={size}>
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
import { Heart } from 'phosphor-react-native';
|
||||
import { useState } from 'react';
|
||||
import { Pressable, PressableProps } from 'react-native';
|
||||
import { Object as SDObject, queryClient, useLibraryMutation } from '@sd/client';
|
||||
|
||||
type Props = {
|
||||
data: SDObject;
|
||||
style: PressableProps['style'];
|
||||
};
|
||||
|
||||
const FavoriteButton = (props: Props) => {
|
||||
const [favorite, setFavorite] = useState(props.data.favorite);
|
||||
|
||||
const { mutate: toggleFavorite, isLoading } = useLibraryMutation('files.setFavorite', {
|
||||
onSuccess: () => {
|
||||
// TODO: Not sure why rust isn't invalidating these...
|
||||
queryClient.invalidateQueries(['locations.getExplorerData']);
|
||||
queryClient.invalidateQueries(['tags.getExplorerData']);
|
||||
setFavorite(!favorite);
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
disabled={isLoading}
|
||||
onPress={() => toggleFavorite({ id: props.data.id, favorite: !favorite })}
|
||||
style={props.style}
|
||||
>
|
||||
<Heart color="white" size={22} weight={favorite ? 'fill' : 'regular'} />
|
||||
</Pressable>
|
||||
);
|
||||
};
|
||||
|
||||
export default FavoriteButton;
|
|
@ -0,0 +1,48 @@
|
|||
import React from 'react';
|
||||
import { Alert, Pressable, View, ViewStyle } from 'react-native';
|
||||
import { ExplorerItem, ObjectKind, isObject, isPath, useLibraryQuery } from '@sd/client';
|
||||
import { InfoPill, PlaceholderPill } from '~/components/primitive/InfoPill';
|
||||
import { tw, twStyle } from '~/lib/tailwind';
|
||||
|
||||
type Props = {
|
||||
data: ExplorerItem;
|
||||
style?: ViewStyle;
|
||||
};
|
||||
|
||||
const InfoTagPills = ({ data, style }: Props) => {
|
||||
const objectData = data ? (isObject(data) ? data.item : data.item.object) : null;
|
||||
|
||||
const tagsQuery = useLibraryQuery(['tags.getForObject', objectData?.id], {
|
||||
enabled: Boolean(objectData)
|
||||
});
|
||||
|
||||
const isDir = data && isPath(data) ? data.item.is_dir : false;
|
||||
|
||||
const item = data?.item;
|
||||
|
||||
return (
|
||||
<View style={twStyle('mt-1 flex flex-row flex-wrap', style)}>
|
||||
{/* Kind */}
|
||||
<InfoPill
|
||||
containerStyle={tw`mr-1`}
|
||||
text={isDir ? 'Folder' : ObjectKind[objectData?.kind || 0]}
|
||||
/>
|
||||
{/* Extension */}
|
||||
{item.extension && <InfoPill text={item.extension} containerStyle={tw`mr-1`} />}
|
||||
{/* TODO: What happens if I have too many? */}
|
||||
{tagsQuery.data?.map((tag) => (
|
||||
<InfoPill
|
||||
key={tag.id}
|
||||
text={tag.name}
|
||||
containerStyle={twStyle('mr-1', { backgroundColor: tag.color + 'CC' })}
|
||||
textStyle={tw`text-white`}
|
||||
/>
|
||||
))}
|
||||
<Pressable onPress={() => Alert.alert('TODO')}>
|
||||
<PlaceholderPill text={'Add Tag'} />
|
||||
</Pressable>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default InfoTagPills;
|
34
apps/mobile/src/components/explorer/sections/Note.tsx
Normal file
34
apps/mobile/src/components/explorer/sections/Note.tsx
Normal file
|
@ -0,0 +1,34 @@
|
|||
import { useCallback, useState } from 'react';
|
||||
import { Text, View } from 'react-native';
|
||||
import { useDebouncedCallback } from 'use-debounce';
|
||||
import { useLibraryMutation } from '@sd/client';
|
||||
import { Object as SDObject } from '@sd/client';
|
||||
|
||||
type Props = {
|
||||
data: SDObject;
|
||||
};
|
||||
|
||||
const Note = (props: Props) => {
|
||||
const [note, setNote] = useState(props.data.note || '');
|
||||
|
||||
const { mutate: fileSetNote } = useLibraryMutation('files.setNote');
|
||||
|
||||
const debounce = useDebouncedCallback(
|
||||
(note: string) =>
|
||||
fileSetNote({
|
||||
id: props.data.id,
|
||||
note
|
||||
}),
|
||||
2000
|
||||
);
|
||||
|
||||
const debouncedNote = useCallback((note: string) => debounce(note), [props.data.id, fileSetNote]);
|
||||
|
||||
return (
|
||||
<View>
|
||||
<Text>Note</Text>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default Note;
|
|
@ -5,7 +5,7 @@ import { MotiView } from 'moti';
|
|||
import { List } from 'phosphor-react-native';
|
||||
import { Pressable, Text, View } from 'react-native';
|
||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
import tw, { twStyle } from '~/lib/tailwind';
|
||||
import { tw, twStyle } from '~/lib/tailwind';
|
||||
|
||||
// Default header with search bar and button to open drawer
|
||||
export default function Header() {
|
||||
|
|
|
@ -2,7 +2,7 @@ import { MotiView } from 'moti';
|
|||
import { CaretRight } from 'phosphor-react-native';
|
||||
import { PropsWithChildren, useReducer } from 'react';
|
||||
import { Pressable, StyleProp, Text, TextStyle, View, ViewStyle } from 'react-native';
|
||||
import tw from '~/lib/tailwind';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
import { AnimatedHeight } from '../animation/layout';
|
||||
|
||||
type CollapsibleViewProps = PropsWithChildren<{
|
||||
|
@ -26,9 +26,9 @@ const CollapsibleView = ({ title, titleStyle, containerStyle, children }: Collap
|
|||
translateX: hide ? 0 : 5,
|
||||
translateY: hide ? 0 : 5
|
||||
}}
|
||||
transition={{ type: 'timing' }}
|
||||
transition={{ type: 'timing', duration: 150 }}
|
||||
>
|
||||
<CaretRight color={tw.color('ink-dull')} size={16} style={tw`mr-3`} />
|
||||
<CaretRight color="white" weight="bold" size={16} style={tw`mr-3`} />
|
||||
</MotiView>
|
||||
</Pressable>
|
||||
<AnimatedHeight hide={hide}>{children}</AnimatedHeight>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { MotiView } from 'moti';
|
||||
import { ReactNode, useState } from 'react';
|
||||
import { KeyboardAvoidingView, Modal, Platform, Pressable, Text, View } from 'react-native';
|
||||
import tw from '~/lib/tailwind';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
import { PulseAnimation } from '../animation/lottie';
|
||||
import { Button } from '../primitive/Button';
|
||||
|
||||
|
|
|
@ -4,30 +4,146 @@ import {
|
|||
BottomSheetHandle,
|
||||
BottomSheetHandleProps,
|
||||
BottomSheetModal,
|
||||
BottomSheetModalProps
|
||||
BottomSheetModalProps,
|
||||
BottomSheetScrollView
|
||||
} from '@gorhom/bottom-sheet';
|
||||
import { BottomSheetModalMethods } from '@gorhom/bottom-sheet/lib/typescript/types';
|
||||
import { forwardRef } from 'react';
|
||||
import tw from '~/lib/tailwind';
|
||||
import { X } from 'phosphor-react-native';
|
||||
import { ReactNode, forwardRef } from 'react';
|
||||
import { Pressable, Text, View } from 'react-native';
|
||||
import useForwardedRef from '~/hooks/useForwardedRef';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
import { Button } from '../primitive/Button';
|
||||
|
||||
const ModalBackdrop = (props: BottomSheetBackdropProps) => (
|
||||
<BottomSheetBackdrop {...props} appearsOnIndex={0} disappearsOnIndex={-1} opacity={0.75} />
|
||||
);
|
||||
|
||||
const ModalHandle = (props: BottomSheetHandleProps) => (
|
||||
interface ModalHandle extends BottomSheetHandleProps {
|
||||
showCloseButton: boolean;
|
||||
modalRef: React.RefObject<BottomSheetModal>;
|
||||
}
|
||||
|
||||
const ModalHandle = (props: ModalHandle) => (
|
||||
<BottomSheetHandle
|
||||
{...props}
|
||||
style={tw`bg-app rounded-t-xl`}
|
||||
indicatorStyle={tw`bg-app-highlight`}
|
||||
/>
|
||||
style={tw`bg-app items-end rounded-t-2xl`}
|
||||
indicatorStyle={tw`bg-app-highlight/60`}
|
||||
>
|
||||
{props.showCloseButton && (
|
||||
<Pressable
|
||||
onPress={() => props.modalRef.current.close()}
|
||||
style={tw`bg-app-button absolute top-5 right-4 h-7 w-7 items-center justify-center rounded-full`}
|
||||
>
|
||||
<X size={16} color="white" weight="bold" />
|
||||
</Pressable>
|
||||
)}
|
||||
</BottomSheetHandle>
|
||||
);
|
||||
|
||||
export const Modal = forwardRef<BottomSheetModalMethods, BottomSheetModalProps>((props, ref) => (
|
||||
export type ModalRef = BottomSheetModal;
|
||||
|
||||
interface ModalProps extends BottomSheetModalProps {
|
||||
children: React.ReactNode;
|
||||
title?: string;
|
||||
showCloseButton?: boolean;
|
||||
}
|
||||
|
||||
export const Modal = forwardRef<ModalRef, ModalProps>((props, ref) => {
|
||||
const { children, title, showCloseButton = false, ...otherProps } = props;
|
||||
|
||||
const modalRef = useForwardedRef(ref);
|
||||
|
||||
return (
|
||||
<BottomSheetModal
|
||||
ref={ref}
|
||||
backdropComponent={ModalBackdrop}
|
||||
handleComponent={ModalHandle}
|
||||
ref={modalRef}
|
||||
backgroundStyle={tw`bg-app`}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
backdropComponent={ModalBackdrop}
|
||||
handleComponent={(props) => ModalHandle({ modalRef, showCloseButton, ...props })}
|
||||
{...otherProps}
|
||||
>
|
||||
{title && <Text style={tw`text-ink text-center text-base font-medium`}>{title}</Text>}
|
||||
{children}
|
||||
</BottomSheetModal>
|
||||
);
|
||||
});
|
||||
|
||||
export const ModalScrollView = BottomSheetScrollView;
|
||||
|
||||
type ConfirmModalProps = {
|
||||
title: string;
|
||||
description?: string;
|
||||
ctaAction?: () => void;
|
||||
ctaLabel: string;
|
||||
ctaDanger?: boolean;
|
||||
ctaDisabled?: boolean;
|
||||
loading?: boolean;
|
||||
/**
|
||||
* Disables backdrop press to close the modal.
|
||||
*/
|
||||
disableBackdropClose?: boolean;
|
||||
/**
|
||||
* Children will be rendered below the description and above the CTA button.
|
||||
*/
|
||||
children?: React.ReactNode;
|
||||
snapPoints?: (string | number)[];
|
||||
/**
|
||||
* Trigger to open the modal.
|
||||
* You can also use ref to open the modal
|
||||
*/
|
||||
trigger?: ReactNode;
|
||||
};
|
||||
|
||||
// TODO: Add loading state
|
||||
// Drop-in replacement for Dialog, can be used to get confirmation from the user, e.g. deleting a library
|
||||
export const ConfirmModal = forwardRef<ModalRef, ConfirmModalProps>((props, ref) => {
|
||||
const modalRef = useForwardedRef(ref);
|
||||
|
||||
return (
|
||||
<>
|
||||
{props.trigger && (
|
||||
<Pressable onPress={() => modalRef.current.present()}>{props.trigger}</Pressable>
|
||||
)}
|
||||
<BottomSheetModal
|
||||
ref={modalRef}
|
||||
backgroundStyle={tw`bg-app`}
|
||||
backdropComponent={ModalBackdrop}
|
||||
handleComponent={(props) => ModalHandle({ modalRef, showCloseButton: false, ...props })}
|
||||
snapPoints={props.snapPoints ?? ['25%']}
|
||||
>
|
||||
{/* Title */}
|
||||
{props.title && (
|
||||
<Text style={tw`text-ink text-center text-base font-medium`}>{props.title}</Text>
|
||||
)}
|
||||
<View style={tw`mt-4 px-6`}>
|
||||
{/* Description */}
|
||||
{props.description && <Text style={tw`text-ink-dull text-sm`}>{props.description}</Text>}
|
||||
{/* Children */}
|
||||
{props.children && props.children}
|
||||
{/* Buttons */}
|
||||
<View style={tw`flex flex-row pt-5`}>
|
||||
<Button
|
||||
variant="gray"
|
||||
style={tw`flex-1`}
|
||||
size="lg"
|
||||
disabled={props.loading} // Disables Close button if loading
|
||||
onPress={() => modalRef.current.close()}
|
||||
>
|
||||
<Text style={tw`text-ink text-sm font-medium`}>Close</Text>
|
||||
</Button>
|
||||
{props.ctaAction && (
|
||||
<Button
|
||||
style={tw`ml-4 flex-1`}
|
||||
variant={props.ctaDanger ? 'danger' : 'accent'}
|
||||
size="lg"
|
||||
onPress={props.ctaAction}
|
||||
disabled={props.ctaDisabled || props.loading}
|
||||
>
|
||||
<Text style={tw`text-ink text-sm font-medium`}>{props.ctaLabel}</Text>
|
||||
</Button>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</BottomSheetModal>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
|
|
@ -2,7 +2,7 @@ import { ArrowDown, ArrowUp } from 'phosphor-react-native';
|
|||
import { useState } from 'react';
|
||||
import { Text, View } from 'react-native';
|
||||
import { Menu, MenuItem } from '~/components/primitive/Menu';
|
||||
import tw from '~/lib/tailwind';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
|
||||
const sortOptions = {
|
||||
name: 'Name',
|
|
@ -1,4 +1,4 @@
|
|||
import { FileModal } from './FileModal';
|
||||
import { ActionsModal } from './inspector/ActionsModal';
|
||||
|
||||
/*
|
||||
* Global Modals
|
||||
|
@ -7,7 +7,7 @@ import { FileModal } from './FileModal';
|
|||
export function GlobalModals() {
|
||||
return (
|
||||
<>
|
||||
<FileModal />
|
||||
<ActionsModal />
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -1,17 +1,16 @@
|
|||
import { BottomSheetModal } from '@gorhom/bottom-sheet';
|
||||
import * as ML from 'expo-media-library';
|
||||
import { forwardRef, useCallback } from 'react';
|
||||
import { Alert, Platform, Text, View } from 'react-native';
|
||||
import DocumentPicker from 'react-native-document-picker';
|
||||
import { useLibraryMutation } from '@sd/client';
|
||||
// import RFS from 'react-native-fs';
|
||||
import { Modal } from '~/components/layout/Modal';
|
||||
import { Modal, ModalRef } from '~/components/layout/Modal';
|
||||
import { Button } from '~/components/primitive/Button';
|
||||
import useForwardedRef from '~/hooks/useForwardedRef';
|
||||
import tw from '~/lib/tailwind';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
|
||||
// WIP component
|
||||
const ImportModal = forwardRef<BottomSheetModal, unknown>((_, ref) => {
|
||||
const ImportModal = forwardRef<ModalRef, unknown>((_, ref) => {
|
||||
const modalRef = useForwardedRef(ref);
|
||||
|
||||
const { mutate: createLocation } = useLibraryMutation('locations.create', {
|
||||
|
@ -41,6 +40,9 @@ const ImportModal = forwardRef<BottomSheetModal, unknown>((_, ref) => {
|
|||
|
||||
// Temporary until we decide on the user flow
|
||||
const handlePhotosButton = useCallback(async () => {
|
||||
Alert.alert('TODO');
|
||||
return;
|
||||
|
||||
// Check if we have full access to the photos library
|
||||
let permission = await ML.getPermissionsAsync();
|
||||
// {"accessPrivileges": "none", "canAskAgain": true, "expires": "never", "granted": false, "status": "undetermined"}
|
||||
|
@ -125,8 +127,8 @@ const ImportModal = forwardRef<BottomSheetModal, unknown>((_, ref) => {
|
|||
// }, []);
|
||||
|
||||
return (
|
||||
<Modal ref={modalRef} snapPoints={['20%']}>
|
||||
<View style={tw`bg-app-box flex-1 px-6 pt-1 pb-2`}>
|
||||
<Modal ref={modalRef} snapPoints={['25%']}>
|
||||
<View style={tw`flex-1 px-8 pt-8 pb-2`}>
|
||||
{/* <Button size="md" variant="accent" style={tw`my-2`} onPress={testFN}>
|
||||
<Text>TEST</Text>
|
||||
</Button> */}
|
||||
|
@ -136,6 +138,7 @@ const ImportModal = forwardRef<BottomSheetModal, unknown>((_, ref) => {
|
|||
<Button size="md" variant="accent" onPress={handlePhotosButton}>
|
||||
<Text>Import from Photos</Text>
|
||||
</Button>
|
||||
<Text style={tw`mt-4 text-center text-white`}>TODO</Text>
|
||||
</View>
|
||||
</Modal>
|
||||
);
|
|
@ -1,15 +1,15 @@
|
|||
import { useState } from 'react';
|
||||
import { useRef } from 'react';
|
||||
import { queryClient, useBridgeMutation } from '@sd/client';
|
||||
import Dialog from '~/components/layout/Dialog';
|
||||
import { ConfirmModal, ModalRef } from '~/components/layout/Modal';
|
||||
|
||||
type Props = {
|
||||
libraryUuid: string;
|
||||
onSubmit?: () => void;
|
||||
children: React.ReactNode;
|
||||
trigger: React.ReactNode;
|
||||
};
|
||||
|
||||
const DeleteLibraryDialog = ({ children, onSubmit, libraryUuid }: Props) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const DeleteLibraryModal = ({ trigger, onSubmit, libraryUuid }: Props) => {
|
||||
const modalRef = useRef<ModalRef>();
|
||||
|
||||
const { mutate: deleteLibrary, isLoading: deleteLibLoading } = useBridgeMutation(
|
||||
'library.delete',
|
||||
|
@ -19,24 +19,21 @@ const DeleteLibraryDialog = ({ children, onSubmit, libraryUuid }: Props) => {
|
|||
onSubmit?.();
|
||||
},
|
||||
onSettled: () => {
|
||||
// Close dialog
|
||||
setIsOpen(false);
|
||||
modalRef.current.close();
|
||||
}
|
||||
}
|
||||
);
|
||||
return (
|
||||
<Dialog
|
||||
isVisible={isOpen}
|
||||
setIsVisible={setIsOpen}
|
||||
<ConfirmModal
|
||||
title="Delete Library"
|
||||
description="Deleting a library will permanently the database, the files themselves will not be deleted."
|
||||
ctaLabel="Delete"
|
||||
ctaAction={() => deleteLibrary(libraryUuid)}
|
||||
loading={deleteLibLoading}
|
||||
trigger={children}
|
||||
trigger={trigger}
|
||||
ctaDanger
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeleteLibraryDialog;
|
||||
export default DeleteLibraryModal;
|
|
@ -1,15 +1,15 @@
|
|||
import { useState } from 'react';
|
||||
import { useRef } from 'react';
|
||||
import { useLibraryMutation } from '@sd/client';
|
||||
import Dialog from '~/components/layout/Dialog';
|
||||
import { ConfirmModal, ModalRef } from '~/components/layout/Modal';
|
||||
|
||||
type Props = {
|
||||
locationId: number;
|
||||
onSubmit?: () => void;
|
||||
children: React.ReactNode;
|
||||
trigger: React.ReactNode;
|
||||
};
|
||||
|
||||
const DeleteLocationDialog = ({ children, onSubmit, locationId }: Props) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const DeleteLocationModal = ({ trigger, onSubmit, locationId }: Props) => {
|
||||
const modalRef = useRef<ModalRef>();
|
||||
|
||||
const { mutate: deleteLoc, isLoading: deleteLocLoading } = useLibraryMutation(
|
||||
'locations.delete',
|
||||
|
@ -18,24 +18,22 @@ const DeleteLocationDialog = ({ children, onSubmit, locationId }: Props) => {
|
|||
onSubmit?.();
|
||||
},
|
||||
onSettled: () => {
|
||||
// Close dialog
|
||||
setIsOpen(false);
|
||||
modalRef.current.close();
|
||||
}
|
||||
}
|
||||
);
|
||||
return (
|
||||
<Dialog
|
||||
isVisible={isOpen}
|
||||
setIsVisible={setIsOpen}
|
||||
<ConfirmModal
|
||||
ref={modalRef}
|
||||
title="Delete Location"
|
||||
description="Deleting a location will also remove all files associated with it from the Spacedrive database, the files themselves will not be deleted."
|
||||
ctaLabel="Delete"
|
||||
ctaAction={() => deleteLoc(locationId)}
|
||||
loading={deleteLocLoading}
|
||||
trigger={children}
|
||||
trigger={trigger}
|
||||
ctaDanger
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeleteLocationDialog;
|
||||
export default DeleteLocationModal;
|
|
@ -1,38 +1,36 @@
|
|||
import { useState } from 'react';
|
||||
import { useRef } from 'react';
|
||||
import { useLibraryMutation } from '@sd/client';
|
||||
import Dialog from '~/components/layout/Dialog';
|
||||
import { ConfirmModal, ModalRef } from '~/components/layout/Modal';
|
||||
|
||||
type Props = {
|
||||
tagId: number;
|
||||
onSubmit?: () => void;
|
||||
children: React.ReactNode;
|
||||
trigger: React.ReactNode;
|
||||
};
|
||||
|
||||
const DeleteTagDialog = ({ children, onSubmit, tagId }: Props) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const DeleteTagModal = ({ trigger, onSubmit, tagId }: Props) => {
|
||||
const modalRef = useRef<ModalRef>();
|
||||
|
||||
const { mutate: deleteTag, isLoading: deleteTagLoading } = useLibraryMutation('tags.delete', {
|
||||
onSuccess: () => {
|
||||
onSubmit?.();
|
||||
},
|
||||
onSettled: () => {
|
||||
// Close dialog
|
||||
setIsOpen(false);
|
||||
modalRef.current.close();
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
isVisible={isOpen}
|
||||
setIsVisible={setIsOpen}
|
||||
<ConfirmModal
|
||||
title="Delete Tag"
|
||||
description="Are you sure you want to delete this tag? This cannot be undone and tagged files will be unlinked."
|
||||
ctaLabel="Delete"
|
||||
ctaAction={() => deleteTag(tagId)}
|
||||
loading={deleteTagLoading}
|
||||
trigger={children}
|
||||
trigger={trigger}
|
||||
ctaDanger
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeleteTagDialog;
|
||||
export default DeleteTagModal;
|
127
apps/mobile/src/components/modal/inspector/ActionsModal.tsx
Normal file
127
apps/mobile/src/components/modal/inspector/ActionsModal.tsx
Normal file
|
@ -0,0 +1,127 @@
|
|||
import dayjs from 'dayjs';
|
||||
import {
|
||||
Copy,
|
||||
Icon,
|
||||
Info,
|
||||
LockSimple,
|
||||
LockSimpleOpen,
|
||||
Package,
|
||||
Pencil,
|
||||
Share,
|
||||
TrashSimple
|
||||
} from 'phosphor-react-native';
|
||||
import { PropsWithChildren, useRef } from 'react';
|
||||
import { Pressable, Text, View, ViewStyle } from 'react-native';
|
||||
import { formatBytes, isObject } from '@sd/client';
|
||||
import FileThumb from '~/components/explorer/FileThumb';
|
||||
import FavoriteButton from '~/components/explorer/sections/FavoriteButton';
|
||||
import InfoTagPills from '~/components/explorer/sections/InfoTagPills';
|
||||
import { Modal, ModalRef } from '~/components/layout/Modal';
|
||||
import { tw, twStyle } from '~/lib/tailwind';
|
||||
import { useActionsModalStore } from '~/stores/modalStore';
|
||||
import FileInfoModal from './FileInfoModal';
|
||||
|
||||
type ActionsContainerProps = PropsWithChildren<{
|
||||
style?: ViewStyle;
|
||||
}>;
|
||||
|
||||
const ActionsContainer = ({ children, style }: ActionsContainerProps) => (
|
||||
<View style={twStyle('bg-app-box rounded-lg py-3.5', style)}>{children}</View>
|
||||
);
|
||||
|
||||
type ActionsItemProps = {
|
||||
title: string;
|
||||
icon: Icon;
|
||||
onPress?: () => void;
|
||||
isDanger?: boolean;
|
||||
};
|
||||
|
||||
const ActionsItem = ({ icon, onPress, title, isDanger = false }: ActionsItemProps) => {
|
||||
const Icon = icon;
|
||||
return (
|
||||
<Pressable onPress={onPress} style={tw`flex flex-row items-center justify-between px-4`}>
|
||||
<Text
|
||||
style={twStyle(
|
||||
'text-base font-medium leading-none',
|
||||
isDanger ? 'text-red-600' : 'text-ink'
|
||||
)}
|
||||
>
|
||||
{title}
|
||||
</Text>
|
||||
<Icon color={isDanger ? 'red' : 'white'} size={22} />
|
||||
</Pressable>
|
||||
);
|
||||
};
|
||||
|
||||
const ActionDivider = () => <View style={tw`bg-app-line/80 my-3.5 h-[0.5px]`} />;
|
||||
|
||||
export const ActionsModal = () => {
|
||||
const fileInfoRef = useRef<ModalRef>(null);
|
||||
|
||||
const { modalRef, data } = useActionsModalStore();
|
||||
|
||||
const item = data?.item;
|
||||
|
||||
const objectData = data ? (isObject(data) ? data.item : data.item.object) : null;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal ref={modalRef} snapPoints={['60%', '90%']}>
|
||||
{data && (
|
||||
<View style={tw`flex-1 px-4`}>
|
||||
<View style={tw`flex flex-row items-center`}>
|
||||
{/* Thumbnail/Icon */}
|
||||
<Pressable onPress={() => fileInfoRef.current.present()}>
|
||||
<FileThumb data={data} size={1} />
|
||||
</Pressable>
|
||||
<View style={tw`ml-2 flex-1`}>
|
||||
{/* Name + Extension */}
|
||||
<Text style={tw`text-base font-bold text-gray-200`} numberOfLines={1}>
|
||||
{item.name}
|
||||
{item.extension && `.${item.extension}`}
|
||||
</Text>
|
||||
<View style={tw`flex flex-row`}>
|
||||
<Text style={tw`text-ink-faint text-xs`}>
|
||||
{formatBytes(Number(objectData?.size_in_bytes || 0))},
|
||||
</Text>
|
||||
<Text style={tw`text-ink-faint text-xs`}>
|
||||
{' '}
|
||||
{dayjs(item.date_created).format('MMM Do YYYY')}
|
||||
</Text>
|
||||
</View>
|
||||
<InfoTagPills data={data} />
|
||||
</View>
|
||||
<FavoriteButton style={tw`mr-4`} data={objectData} />
|
||||
</View>
|
||||
<View style={tw`my-3`} />
|
||||
{/* Actions */}
|
||||
<ActionsContainer>
|
||||
<ActionsItem
|
||||
icon={Info}
|
||||
title="Show Info"
|
||||
onPress={() => fileInfoRef.current.present()}
|
||||
/>
|
||||
</ActionsContainer>
|
||||
<ActionsContainer style={tw`mt-2`}>
|
||||
<ActionsItem icon={Pencil} title="Rename" />
|
||||
<ActionDivider />
|
||||
<ActionsItem icon={Copy} title="Duplicate" />
|
||||
<ActionDivider />
|
||||
<ActionsItem icon={Share} title="Share" />
|
||||
</ActionsContainer>
|
||||
<ActionsContainer style={tw`mt-2`}>
|
||||
<ActionsItem icon={LockSimple} title="Encrypt" />
|
||||
<ActionDivider />
|
||||
<ActionsItem icon={LockSimpleOpen} title="Decrypt" />
|
||||
<ActionDivider />
|
||||
<ActionsItem icon={Package} title="Compress" />
|
||||
<ActionDivider />
|
||||
<ActionsItem icon={TrashSimple} title="Delete" isDanger />
|
||||
</ActionsContainer>
|
||||
</View>
|
||||
)}
|
||||
</Modal>
|
||||
<FileInfoModal ref={fileInfoRef} data={data} />
|
||||
</>
|
||||
);
|
||||
};
|
132
apps/mobile/src/components/modal/inspector/FileInfoModal.tsx
Normal file
132
apps/mobile/src/components/modal/inspector/FileInfoModal.tsx
Normal file
|
@ -0,0 +1,132 @@
|
|||
import dayjs from 'dayjs';
|
||||
import {
|
||||
Barcode,
|
||||
CaretLeft,
|
||||
CircleWavyCheck,
|
||||
Clock,
|
||||
Cube,
|
||||
Icon,
|
||||
Snowflake
|
||||
} from 'phosphor-react-native';
|
||||
import { forwardRef } from 'react';
|
||||
import { Pressable, Text, View } from 'react-native';
|
||||
import { ExplorerItem, formatBytes, isObject, useLibraryQuery } from '@sd/client';
|
||||
import FileThumb from '~/components/explorer/FileThumb';
|
||||
import InfoTagPills from '~/components/explorer/sections/InfoTagPills';
|
||||
import { Modal, ModalRef, ModalScrollView } from '~/components/layout/Modal';
|
||||
import Divider from '~/components/primitive/Divider';
|
||||
import useForwardedRef from '~/hooks/useForwardedRef';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
|
||||
type MetaItemProps = {
|
||||
title: string;
|
||||
value: string | number;
|
||||
icon?: Icon;
|
||||
};
|
||||
|
||||
function MetaItem({ title, value, icon }: MetaItemProps) {
|
||||
const Icon = icon;
|
||||
|
||||
return (
|
||||
<>
|
||||
<View style={tw`flex flex-row items-center`}>
|
||||
<View style={tw`w-30 flex flex-row items-center`}>
|
||||
{icon && <Icon color="white" size={18} style={tw`mr-1`} />}
|
||||
<Text style={tw`text-sm font-medium text-white`}>{title}</Text>
|
||||
</View>
|
||||
<Text style={tw`text-sm text-gray-400`}>{value}</Text>
|
||||
</View>
|
||||
<Divider style={tw`my-3.5`} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
type FileInfoModalProps = {
|
||||
data: ExplorerItem;
|
||||
};
|
||||
|
||||
const FileInfoModal = forwardRef<ModalRef, FileInfoModalProps>((props, ref) => {
|
||||
const { data } = props;
|
||||
|
||||
const modalRef = useForwardedRef(ref);
|
||||
|
||||
const item = data?.item;
|
||||
|
||||
const objectData = data ? (isObject(data) ? data.item : data.item.object) : null;
|
||||
const filePathData = data ? (isObject(data) ? data.item.file_paths[0] : data.item) : null;
|
||||
|
||||
const fullObjectData = useLibraryQuery(['files.get', { id: objectData?.id || -1 }], {
|
||||
enabled: objectData?.id !== undefined
|
||||
});
|
||||
|
||||
return (
|
||||
<Modal
|
||||
ref={modalRef}
|
||||
enableContentPanningGesture={false}
|
||||
enablePanDownToClose={false}
|
||||
snapPoints={['70%']}
|
||||
>
|
||||
{data && (
|
||||
<ModalScrollView style={tw`flex-1 p-4`}>
|
||||
{/* Back Button */}
|
||||
<Pressable onPress={() => modalRef.current.close()} style={tw`absolute z-10 ml-4`}>
|
||||
<CaretLeft color={tw.color('accent')} size={20} weight="bold" />
|
||||
</Pressable>
|
||||
{/* File Icon / Name */}
|
||||
<View style={tw`items-center`}>
|
||||
<FileThumb data={data} size={1.6} />
|
||||
<Text style={tw`mt-2 text-base font-bold text-gray-200`}>{item.name}</Text>
|
||||
<InfoTagPills data={data} style={tw`mt-3`} />
|
||||
</View>
|
||||
{/* Details */}
|
||||
<Divider style={tw`mt-6 mb-4`} />
|
||||
<>
|
||||
{/* Size */}
|
||||
<MetaItem
|
||||
title="Size"
|
||||
icon={Cube}
|
||||
value={formatBytes(Number(objectData?.size_in_bytes || 0))}
|
||||
/>
|
||||
{/* Duration */}
|
||||
{fullObjectData.data?.media_data?.duration_seconds && (
|
||||
<MetaItem
|
||||
title="Duration"
|
||||
value={fullObjectData.data.media_data.duration_seconds}
|
||||
icon={Clock}
|
||||
/>
|
||||
)}
|
||||
{/* Created */}
|
||||
<MetaItem
|
||||
icon={Clock}
|
||||
title="Created"
|
||||
value={dayjs(item.date_created).format('MMM Do YYYY')}
|
||||
/>
|
||||
{/* Indexed */}
|
||||
<MetaItem
|
||||
icon={Barcode}
|
||||
title="Indexed"
|
||||
value={dayjs(item.date_indexed).format('MMM Do YYYY')}
|
||||
/>
|
||||
|
||||
{filePathData && (
|
||||
<>
|
||||
{/* TODO: Note */}
|
||||
<MetaItem icon={Snowflake} title="Content ID" value={filePathData.cas_id} />
|
||||
{/* Checksum */}
|
||||
{filePathData?.integrity_checksum && (
|
||||
<MetaItem
|
||||
icon={CircleWavyCheck}
|
||||
title="Checksum"
|
||||
value={filePathData?.integrity_checksum}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
</ModalScrollView>
|
||||
)}
|
||||
</Modal>
|
||||
);
|
||||
});
|
||||
|
||||
export default FileInfoModal;
|
111
apps/mobile/src/components/modal/tag/CreateTagModal.tsx
Normal file
111
apps/mobile/src/components/modal/tag/CreateTagModal.tsx
Normal file
|
@ -0,0 +1,111 @@
|
|||
import { forwardRef, useEffect, useState } from 'react';
|
||||
import { Pressable, Text, View } from 'react-native';
|
||||
import ColorPicker from 'react-native-wheel-color-picker';
|
||||
import { queryClient, useLibraryMutation } from '@sd/client';
|
||||
import { FadeInAnimation } from '~/components/animation/layout';
|
||||
import { Modal, ModalRef } from '~/components/layout/Modal';
|
||||
import { Button } from '~/components/primitive/Button';
|
||||
import { Input } from '~/components/primitive/Input';
|
||||
import useForwardedRef from '~/hooks/useForwardedRef';
|
||||
import { tw, twStyle } from '~/lib/tailwind';
|
||||
|
||||
const CreateTagModal = forwardRef<ModalRef, unknown>((_, ref) => {
|
||||
const modalRef = useForwardedRef(ref);
|
||||
|
||||
const [tagName, setTagName] = useState('');
|
||||
const [tagColor, setTagColor] = useState('#A717D9');
|
||||
const [showPicker, setShowPicker] = useState(false);
|
||||
|
||||
// TODO: Use react-hook-form?
|
||||
|
||||
const { mutate: createTag } = useLibraryMutation('tags.create', {
|
||||
onSuccess: () => {
|
||||
// Reset form
|
||||
setTagName('');
|
||||
setTagColor('#A717D9');
|
||||
setShowPicker(false);
|
||||
|
||||
queryClient.invalidateQueries(['tags.list']);
|
||||
},
|
||||
onSettled: () => {
|
||||
// Close modal
|
||||
modalRef.current.dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
modalRef.current.snapToIndex(showPicker ? 1 : 0);
|
||||
}, [modalRef, showPicker]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
ref={modalRef}
|
||||
snapPoints={['30%', '60%']}
|
||||
title="Create Tag"
|
||||
onDismiss={() => {
|
||||
// Resets form onDismiss
|
||||
setTagName('');
|
||||
setTagColor('#A717D9');
|
||||
setShowPicker(false);
|
||||
}}
|
||||
// Disable panning gestures
|
||||
enableHandlePanningGesture={false}
|
||||
enableContentPanningGesture={false}
|
||||
showCloseButton
|
||||
>
|
||||
<View style={tw`p-4`}>
|
||||
<View style={tw`mt-4 flex flex-row items-center`}>
|
||||
<Pressable
|
||||
onPress={() => setShowPicker((v) => !v)}
|
||||
style={twStyle({ backgroundColor: tagColor }, 'h-6 w-6 rounded-full')}
|
||||
/>
|
||||
<Input
|
||||
style={tw`ml-2 flex-1`}
|
||||
value={tagName}
|
||||
onChangeText={(text) => setTagName(text)}
|
||||
placeholder="Name"
|
||||
/>
|
||||
</View>
|
||||
{/* Color Picker */}
|
||||
{showPicker && (
|
||||
<FadeInAnimation>
|
||||
<View style={tw`mt-4 h-64`}>
|
||||
<ColorPicker
|
||||
autoResetSlider
|
||||
gapSize={0}
|
||||
thumbSize={40}
|
||||
sliderSize={24}
|
||||
shadeSliderThumb
|
||||
color={tagColor}
|
||||
onColorChangeComplete={(color) => setTagColor(color)}
|
||||
swatchesLast={false}
|
||||
palette={[
|
||||
tw.color('blue-500'),
|
||||
tw.color('red-500'),
|
||||
tw.color('green-500'),
|
||||
tw.color('yellow-500'),
|
||||
tw.color('purple-500'),
|
||||
tw.color('pink-500'),
|
||||
tw.color('gray-500'),
|
||||
tw.color('black'),
|
||||
tw.color('white')
|
||||
]}
|
||||
/>
|
||||
</View>
|
||||
</FadeInAnimation>
|
||||
)}
|
||||
<Button
|
||||
variant="accent"
|
||||
size="md"
|
||||
onPress={() => createTag({ color: tagColor, name: tagName })}
|
||||
style={tw`mt-6`}
|
||||
disabled={tagName.length === 0}
|
||||
>
|
||||
<Text style={tw`text-sm font-medium text-white`}>Create</Text>
|
||||
</Button>
|
||||
</View>
|
||||
</Modal>
|
||||
);
|
||||
});
|
||||
|
||||
export default CreateTagModal;
|
110
apps/mobile/src/components/modal/tag/UpdateTagModal.tsx
Normal file
110
apps/mobile/src/components/modal/tag/UpdateTagModal.tsx
Normal file
|
@ -0,0 +1,110 @@
|
|||
import { forwardRef, useEffect, useState } from 'react';
|
||||
import { Pressable, Text, View } from 'react-native';
|
||||
import ColorPicker from 'react-native-wheel-color-picker';
|
||||
import { Tag, queryClient, useLibraryMutation } from '@sd/client';
|
||||
import { FadeInAnimation } from '~/components/animation/layout';
|
||||
import { Modal, ModalRef } from '~/components/layout/Modal';
|
||||
import { Button } from '~/components/primitive/Button';
|
||||
import { Input } from '~/components/primitive/Input';
|
||||
import useForwardedRef from '~/hooks/useForwardedRef';
|
||||
import { tw, twStyle } from '~/lib/tailwind';
|
||||
|
||||
type Props = {
|
||||
tag: Tag;
|
||||
onSubmit?: () => void;
|
||||
};
|
||||
|
||||
const UpdateTagModal = forwardRef<ModalRef, Props>((props, ref) => {
|
||||
const modalRef = useForwardedRef(ref);
|
||||
|
||||
const [tagName, setTagName] = useState(props.tag.name);
|
||||
const [tagColor, setTagColor] = useState(props.tag.color);
|
||||
const [showPicker, setShowPicker] = useState(false);
|
||||
|
||||
const { mutate: updateTag, isLoading } = useLibraryMutation('tags.update', {
|
||||
onSuccess: () => {
|
||||
// Reset form
|
||||
setShowPicker(false);
|
||||
|
||||
queryClient.invalidateQueries(['tags.list']);
|
||||
|
||||
props.onSubmit?.();
|
||||
},
|
||||
onSettled: () => {
|
||||
modalRef.current.dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
modalRef.current.snapToIndex(showPicker ? 1 : 0);
|
||||
}, [modalRef, showPicker]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
ref={modalRef}
|
||||
snapPoints={['35%', '65%']}
|
||||
onDismiss={() => {
|
||||
// Resets form onDismiss
|
||||
setShowPicker(false);
|
||||
}}
|
||||
title="Update Tag"
|
||||
// Disable panning gestures
|
||||
enableHandlePanningGesture={false}
|
||||
enableContentPanningGesture={false}
|
||||
showCloseButton
|
||||
>
|
||||
<View style={tw`p-4`}>
|
||||
<Text style={tw`text-ink-dull mb-1 ml-1 text-xs font-medium`}>Name</Text>
|
||||
<Input value={tagName} onChangeText={(t) => setTagName(t)} />
|
||||
<Text style={tw`text-ink-dull mb-1 ml-1 mt-3 text-xs font-medium`}>Color</Text>
|
||||
<View style={tw`ml-2 flex flex-row items-center`}>
|
||||
<Pressable
|
||||
onPress={() => setShowPicker((v) => !v)}
|
||||
style={twStyle({ backgroundColor: tagColor }, 'h-5 w-5 rounded-full')}
|
||||
/>
|
||||
{/* TODO: Make this editable. Need to make sure color is a valid hexcode and update the color on picker etc. etc. */}
|
||||
<Input editable={false} value={tagColor} style={tw`ml-2 flex-1`} />
|
||||
</View>
|
||||
{showPicker && (
|
||||
<FadeInAnimation>
|
||||
<View style={tw`mt-4 h-64`}>
|
||||
<ColorPicker
|
||||
autoResetSlider
|
||||
gapSize={0}
|
||||
thumbSize={40}
|
||||
sliderSize={24}
|
||||
shadeSliderThumb
|
||||
color={tagColor}
|
||||
onColorChangeComplete={(color) => setTagColor(color)}
|
||||
swatchesLast={false}
|
||||
palette={[
|
||||
tw.color('blue-500'),
|
||||
tw.color('red-500'),
|
||||
tw.color('green-500'),
|
||||
tw.color('yellow-500'),
|
||||
tw.color('purple-500'),
|
||||
tw.color('pink-500'),
|
||||
tw.color('gray-500'),
|
||||
tw.color('black'),
|
||||
tw.color('white')
|
||||
]}
|
||||
/>
|
||||
</View>
|
||||
</FadeInAnimation>
|
||||
)}
|
||||
{/* TODO: Add loading to button */}
|
||||
<Button
|
||||
variant="accent"
|
||||
size="md"
|
||||
onPress={() => updateTag({ id: props.tag.id, color: tagColor, name: tagName })}
|
||||
style={tw`mt-6`}
|
||||
disabled={tagName.length === 0}
|
||||
>
|
||||
<Text style={tw`text-sm font-medium text-white`}>Save</Text>
|
||||
</Button>
|
||||
</View>
|
||||
</Modal>
|
||||
);
|
||||
});
|
||||
|
||||
export default UpdateTagModal;
|
|
@ -3,8 +3,8 @@ import { FC, useEffect, useState } from 'react';
|
|||
import { ScrollView, Text, View } from 'react-native';
|
||||
import RNFS from 'react-native-fs';
|
||||
import { Statistics, useLibraryQuery } from '@sd/client';
|
||||
import useCounter from '../hooks/useCounter';
|
||||
import tw, { twStyle } from '../lib/tailwind';
|
||||
import useCounter from '~/hooks/useCounter';
|
||||
import { tw, twStyle } from '~/lib/tailwind';
|
||||
|
||||
const StatItemNames: Partial<Record<keyof Statistics, string>> = {
|
||||
total_bytes_capacity: 'Total capacity',
|
|
@ -2,7 +2,7 @@ import { VariantProps, cva } from 'class-variance-authority';
|
|||
import { MotiPressable, MotiPressableProps } from 'moti/interactions';
|
||||
import { FC, useMemo } from 'react';
|
||||
import { Pressable, PressableProps } from 'react-native';
|
||||
import tw, { twStyle } from '~/lib/tailwind';
|
||||
import { tw, twStyle } from '~/lib/tailwind';
|
||||
|
||||
const button = cva(['items-center justify-center rounded-md border shadow-sm'], {
|
||||
variants: {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { StyleProp, Text, View, ViewStyle } from 'react-native';
|
||||
import tw from '~/lib/tailwind';
|
||||
import { StyleProp, View, ViewStyle } from 'react-native';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
|
||||
type DividerProps = {
|
||||
style?: StyleProp<ViewStyle>;
|
||||
|
|
39
apps/mobile/src/components/primitive/InfoPill.tsx
Normal file
39
apps/mobile/src/components/primitive/InfoPill.tsx
Normal file
|
@ -0,0 +1,39 @@
|
|||
import React from 'react';
|
||||
import { Text, TextStyle, View, ViewStyle } from 'react-native';
|
||||
import { tw, twStyle } from '~/lib/tailwind';
|
||||
|
||||
type Props = {
|
||||
text: string;
|
||||
containerStyle?: ViewStyle;
|
||||
textStyle?: TextStyle;
|
||||
};
|
||||
|
||||
export const InfoPill = (props: Props) => {
|
||||
return (
|
||||
<View
|
||||
style={twStyle(
|
||||
'shadow-app-shade/5 bg-app-highlight rounded-md border border-transparent px-[6px] py-[1px] shadow',
|
||||
props.containerStyle
|
||||
)}
|
||||
>
|
||||
<Text style={twStyle('text-ink-dull text-xs font-medium', props.textStyle)}>
|
||||
{props.text}
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export function PlaceholderPill(props: Props) {
|
||||
return (
|
||||
<View
|
||||
style={twStyle(
|
||||
'shadow-app-shade/10 border-app-highlight rounded-md border border-dashed bg-transparent px-[6px] py-[1px] shadow',
|
||||
props.containerStyle
|
||||
)}
|
||||
>
|
||||
<Text style={twStyle('text-ink-faint/70 text-xs font-medium', props.textStyle)}>
|
||||
{props.text}
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
import { VariantProps, cva } from 'class-variance-authority';
|
||||
import { FC } from 'react';
|
||||
import { TextInputProps as RNTextInputProps, TextInput } from 'react-native';
|
||||
import tw, { twStyle } from '~/lib/tailwind';
|
||||
import { tw, twStyle } from '~/lib/tailwind';
|
||||
|
||||
const input = cva(['rounded-md border text-sm shadow-sm'], {
|
||||
const input = cva(['rounded-md border text-sm leading-tight shadow-sm'], {
|
||||
variants: {
|
||||
variant: {
|
||||
default: 'border-app-line bg-app text-ink'
|
||||
|
|
|
@ -5,9 +5,10 @@ import {
|
|||
MenuOptionProps,
|
||||
MenuOptions,
|
||||
MenuTrigger,
|
||||
Menu as PMenu
|
||||
Menu as PMenu,
|
||||
renderers
|
||||
} from 'react-native-popup-menu';
|
||||
import tw from '~/lib/tailwind';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
|
||||
type MenuProps = {
|
||||
trigger: React.ReactNode;
|
||||
|
@ -17,7 +18,7 @@ type MenuProps = {
|
|||
// TODO: Still looks a bit off...
|
||||
export const Menu = (props: MenuProps) => (
|
||||
<View>
|
||||
<PMenu>
|
||||
<PMenu renderer={renderers.NotAnimatedContextMenu}>
|
||||
<MenuTrigger>{props.trigger}</MenuTrigger>
|
||||
<MenuOptions optionsContainerStyle={tw`bg-app-menu rounded p-1`}>
|
||||
{props.children}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { FC } from 'react';
|
||||
import { Switch as RNSwitch, SwitchProps, Text, View } from 'react-native';
|
||||
import tw from '~/lib/tailwind';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
|
||||
export const Switch: FC<SwitchProps> = ({ ...props }) => {
|
||||
return (
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { PropsWithChildren } from 'react';
|
||||
import { Text, View } from 'react-native';
|
||||
import tw from '~/lib/tailwind';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
|
||||
type SettingsContainerProps = PropsWithChildren<{
|
||||
title?: string;
|
||||
|
@ -9,7 +9,7 @@ type SettingsContainerProps = PropsWithChildren<{
|
|||
|
||||
export function SettingsContainer({ children, title, description }: SettingsContainerProps) {
|
||||
return (
|
||||
<View style={tw``}>
|
||||
<View>
|
||||
{title && <Text style={tw`text-ink-dull pb-2 pl-3 text-sm font-semibold`}>{title}</Text>}
|
||||
{children}
|
||||
{description && <Text style={tw`text-ink-dull px-3 pt-2 text-sm`}>{description}</Text>}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { CaretRight, Icon } from 'phosphor-react-native';
|
||||
import { Pressable, Text, View } from 'react-native';
|
||||
import tw from '~/lib/tailwind';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
|
||||
type SettingsItemProps = {
|
||||
title: string;
|
||||
|
@ -12,12 +12,12 @@ type SettingsItemProps = {
|
|||
export function SettingsItem(props: SettingsItemProps) {
|
||||
return (
|
||||
<Pressable onPress={props.onPress}>
|
||||
<View style={tw`bg-app-overlay flex flex-row items-center justify-between px-3`}>
|
||||
<View style={tw`bg-app-overlay flex flex-row items-center justify-between px-4`}>
|
||||
<View style={tw`flex flex-row items-center py-4`}>
|
||||
{props.leftIcon && props.leftIcon({ size: 18, color: tw.color('ink'), style: tw`mr-2` })}
|
||||
<Text style={tw`text-ink text-sm`}>{props.title}</Text>
|
||||
{props.leftIcon && props.leftIcon({ size: 20, color: tw.color('ink'), style: tw`mr-3` })}
|
||||
<Text style={tw`text-ink text-[14px]`}>{props.title}</Text>
|
||||
</View>
|
||||
{props.rightArea ? props.rightArea : <CaretRight size={20} color={tw.color('ink-faint')} />}
|
||||
{props.rightArea ? props.rightArea : <CaretRight size={20} color={tw.color('ink-dull')} />}
|
||||
</View>
|
||||
</Pressable>
|
||||
);
|
||||
|
|
|
@ -1,98 +0,0 @@
|
|||
import React, { useState } from 'react';
|
||||
import { Pressable, View } from 'react-native';
|
||||
import ColorPicker from 'react-native-wheel-color-picker';
|
||||
import { queryClient, useLibraryMutation } from '@sd/client';
|
||||
import Dialog from '~/components/layout/Dialog';
|
||||
import { Input } from '~/components/primitive/Input';
|
||||
import tw, { twStyle } from '~/lib/tailwind';
|
||||
|
||||
type Props = {
|
||||
onSubmit?: () => void;
|
||||
disableBackdropClose?: boolean;
|
||||
children: React.ReactNode;
|
||||
};
|
||||
|
||||
const CreateTagDialog = ({ children, onSubmit, disableBackdropClose }: Props) => {
|
||||
const [tagName, setTagName] = useState('');
|
||||
const [tagColor, setTagColor] = useState('#A717D9');
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
const { mutate: createTag, isLoading } = useLibraryMutation('tags.create', {
|
||||
onSuccess: () => {
|
||||
// Reset form
|
||||
setTagName('');
|
||||
setTagColor('#A717D9');
|
||||
setShowPicker(false);
|
||||
|
||||
queryClient.invalidateQueries(['tags.list']);
|
||||
|
||||
onSubmit?.();
|
||||
},
|
||||
onSettled: () => {
|
||||
// Close dialog
|
||||
setIsOpen(false);
|
||||
}
|
||||
});
|
||||
|
||||
const [showPicker, setShowPicker] = useState(false);
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
isVisible={isOpen}
|
||||
setIsVisible={setIsOpen}
|
||||
title="Create New Tag"
|
||||
description="Choose a name and color."
|
||||
ctaLabel="Create"
|
||||
ctaAction={() => createTag({ color: tagColor, name: tagName })}
|
||||
loading={isLoading}
|
||||
ctaDisabled={tagName.length === 0}
|
||||
trigger={children}
|
||||
disableBackdropClose={disableBackdropClose}
|
||||
onClose={() => {
|
||||
setTagName('');
|
||||
setTagColor('#A717D9');
|
||||
setShowPicker(false);
|
||||
}} // Resets form onClose
|
||||
>
|
||||
<View style={tw`flex flex-row items-center`}>
|
||||
<Pressable
|
||||
onPress={() => setShowPicker((v) => !v)}
|
||||
style={twStyle({ backgroundColor: tagColor }, 'h-5 w-5 rounded-full')}
|
||||
/>
|
||||
<Input
|
||||
style={tw`ml-2 flex-1`}
|
||||
value={tagName}
|
||||
onChangeText={(text) => setTagName(text)}
|
||||
placeholder="Name"
|
||||
/>
|
||||
</View>
|
||||
{showPicker && (
|
||||
<View style={tw`my-4 h-64`}>
|
||||
<ColorPicker
|
||||
autoResetSlider
|
||||
gapSize={0}
|
||||
thumbSize={40}
|
||||
sliderSize={24}
|
||||
shadeSliderThumb
|
||||
color={tagColor}
|
||||
onColorChangeComplete={(color) => setTagColor(color)}
|
||||
swatchesLast={false}
|
||||
palette={[
|
||||
tw.color('blue-500'),
|
||||
tw.color('red-500'),
|
||||
tw.color('green-500'),
|
||||
tw.color('yellow-500'),
|
||||
tw.color('purple-500'),
|
||||
tw.color('pink-500'),
|
||||
tw.color('gray-500'),
|
||||
tw.color('black'),
|
||||
tw.color('white')
|
||||
]}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
export default CreateTagDialog;
|
|
@ -1,92 +0,0 @@
|
|||
import React, { useState } from 'react';
|
||||
import { Pressable, Text, View } from 'react-native';
|
||||
import ColorPicker from 'react-native-wheel-color-picker';
|
||||
import { Tag, queryClient, useLibraryMutation } from '@sd/client';
|
||||
import Dialog from '~/components/layout/Dialog';
|
||||
import { Input } from '~/components/primitive/Input';
|
||||
import tw, { twStyle } from '~/lib/tailwind';
|
||||
|
||||
type Props = {
|
||||
tag: Tag;
|
||||
onSubmit?: () => void;
|
||||
children: React.ReactNode;
|
||||
};
|
||||
|
||||
const UpdateTagDialog = ({ children, onSubmit, tag }: Props) => {
|
||||
const [tagName, setTagName] = useState(tag.name);
|
||||
const [tagColor, setTagColor] = useState(tag.color);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
const { mutate: updateTag, isLoading } = useLibraryMutation('tags.update', {
|
||||
onSuccess: () => {
|
||||
// Reset form
|
||||
setShowPicker(false);
|
||||
|
||||
queryClient.invalidateQueries(['tags.list']);
|
||||
|
||||
onSubmit?.();
|
||||
},
|
||||
onSettled: () => {
|
||||
// Close dialog
|
||||
setIsOpen(false);
|
||||
}
|
||||
});
|
||||
|
||||
const [showPicker, setShowPicker] = useState(false);
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
isVisible={isOpen}
|
||||
setIsVisible={setIsOpen}
|
||||
title="Update Tag"
|
||||
ctaLabel="Save"
|
||||
ctaAction={() => updateTag({ id: tag.id, color: tagColor, name: tagName })}
|
||||
loading={isLoading}
|
||||
ctaDisabled={tagName.length === 0}
|
||||
trigger={children}
|
||||
onClose={() => {
|
||||
setShowPicker(false); // Reset form
|
||||
}}
|
||||
>
|
||||
<Text style={tw`text-ink-dull mb-1 ml-1 mt-3 text-xs font-medium`}>Name</Text>
|
||||
<Input value={tagName} onChangeText={(t) => setTagName(t)} />
|
||||
<Text style={tw`text-ink-dull mb-1 ml-1 mt-3 text-xs font-medium`}>Color</Text>
|
||||
<View style={tw`ml-2 flex flex-row items-center`}>
|
||||
<Pressable
|
||||
onPress={() => setShowPicker((v) => !v)}
|
||||
style={twStyle({ backgroundColor: tagColor }, 'h-5 w-5 rounded-full')}
|
||||
/>
|
||||
{/* TODO: Make this editable. Need to make sure color is a valid hexcode and update the color on picker etc. etc. */}
|
||||
<Input editable={false} value={tagColor} style={tw`ml-2 flex-1`} />
|
||||
</View>
|
||||
|
||||
{showPicker && (
|
||||
<View style={tw`mt-4 h-64`}>
|
||||
<ColorPicker
|
||||
autoResetSlider
|
||||
gapSize={0}
|
||||
thumbSize={40}
|
||||
sliderSize={24}
|
||||
shadeSliderThumb
|
||||
color={tagColor}
|
||||
onColorChangeComplete={(color) => setTagColor(color)}
|
||||
swatchesLast={false}
|
||||
palette={[
|
||||
tw.color('blue-500'),
|
||||
tw.color('red-500'),
|
||||
tw.color('green-500'),
|
||||
tw.color('yellow-500'),
|
||||
tw.color('purple-500'),
|
||||
tw.color('pink-500'),
|
||||
tw.color('gray-500'),
|
||||
tw.color('black'),
|
||||
tw.color('white')
|
||||
]}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
export default UpdateTagDialog;
|
|
@ -1,107 +0,0 @@
|
|||
import { BottomSheetModal, BottomSheetScrollView } from '@gorhom/bottom-sheet';
|
||||
import dayjs from 'dayjs';
|
||||
import { CaretLeft } from 'phosphor-react-native';
|
||||
import { useRef } from 'react';
|
||||
import { Button, Pressable, Text, View } from 'react-native';
|
||||
import { default as FileIcon, default as FileThumb } from '../../components/explorer/FileThumb';
|
||||
import { Modal } from '../../components/layout/Modal';
|
||||
import Divider from '../../components/primitive/Divider';
|
||||
import tw from '../../lib/tailwind';
|
||||
import { useFileModalStore } from '../../stores/modalStore';
|
||||
|
||||
type MetaItemProps = {
|
||||
title: string;
|
||||
value: string;
|
||||
};
|
||||
|
||||
function MetaItem({ title, value }: MetaItemProps) {
|
||||
return (
|
||||
<View>
|
||||
<Text style={tw`text-sm font-bold text-white`}>{title}</Text>
|
||||
<Text style={tw`mt-1 text-sm text-gray-400`}>{value}</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
export const FileModal = () => {
|
||||
const { fileRef, data } = useFileModalStore();
|
||||
|
||||
const fileDetailsRef = useRef<BottomSheetModal>(null);
|
||||
|
||||
const item = data.item;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal ref={fileRef} snapPoints={['60%', '90%']}>
|
||||
{data && (
|
||||
<View style={tw`bg-app flex-1 p-4`}>
|
||||
{/* File Icon / Name */}
|
||||
<View style={tw`flex flex-row items-center`}>
|
||||
<FileIcon data={data} size={1.6} />
|
||||
{/* File Name, Details etc. */}
|
||||
<View style={tw`ml-2`}>
|
||||
<Text style={tw`text-base font-bold text-gray-200`}>{item.name}</Text>
|
||||
<View style={tw`mt-2 flex flex-row`}>
|
||||
<Text style={tw`text-xs text-gray-400`}>5 MB,</Text>
|
||||
<Text style={tw`ml-1 text-xs text-gray-400`}>
|
||||
{item.extension.toUpperCase()},
|
||||
</Text>
|
||||
<Text style={tw`ml-1 text-xs text-gray-400`}>15 Aug</Text>
|
||||
</View>
|
||||
<Pressable style={tw`mt-2`} onPress={() => fileDetailsRef.current.present()}>
|
||||
<Text style={tw`text-accent text-sm`}>More</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
</View>
|
||||
{/* Divider */}
|
||||
<Divider style={tw`my-6`} />
|
||||
{/* Buttons */}
|
||||
<Button onPress={() => fileRef.current.close()} title="Copy" color="white" />
|
||||
<Button onPress={() => fileRef.current.close()} title="Move" color="white" />
|
||||
<Button onPress={() => fileRef.current.close()} title="Share" color="white" />
|
||||
<Button onPress={() => fileRef.current.close()} title="Delete" color="white" />
|
||||
</View>
|
||||
)}
|
||||
</Modal>
|
||||
{/* Details Modal */}
|
||||
<Modal
|
||||
ref={fileDetailsRef}
|
||||
enableContentPanningGesture={false}
|
||||
enablePanDownToClose={false}
|
||||
snapPoints={['70%']}
|
||||
>
|
||||
{data && (
|
||||
<BottomSheetScrollView style={tw`bg-app flex-1 p-4`}>
|
||||
{/* Back Button */}
|
||||
<Pressable style={tw`ml-4 w-full`} onPress={() => fileDetailsRef.current.close()}>
|
||||
<CaretLeft color={tw.color('accent')} size={20} />
|
||||
</Pressable>
|
||||
{/* File Icon / Name */}
|
||||
<View style={tw`items-center`}>
|
||||
<FileThumb data={data} size={1.8} />
|
||||
<Text style={tw`mt-3 text-base font-bold text-gray-200`}>{item.name}</Text>
|
||||
</View>
|
||||
{/* Details */}
|
||||
<Divider style={tw`mt-6 mb-4`} />
|
||||
<>
|
||||
{/* Temp, we need cas id */}
|
||||
{item.id && <MetaItem title="Unique Content ID" value={'555555555'} />}
|
||||
<Divider style={tw`my-4`} />
|
||||
<MetaItem title="URI" value={`/Users/utku/Somewhere/vite.config.js`} />
|
||||
<Divider style={tw`my-4`} />
|
||||
<MetaItem
|
||||
title="Date Created"
|
||||
value={dayjs(item.date_created).format('MMMM Do yyyy, h:mm:ss aaa')}
|
||||
/>
|
||||
<Divider style={tw`my-4`} />
|
||||
<MetaItem
|
||||
title="Date Indexed"
|
||||
value={dayjs(item.date_indexed).format('MMMM Do yyyy, h:mm:ss aaa')}
|
||||
/>
|
||||
</>
|
||||
</BottomSheetScrollView>
|
||||
)}
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -7,7 +7,7 @@ export function useAutoForm<TFieldValues extends FieldValues = FieldValues, TCon
|
|||
form: UseFormReturn<TFieldValues, TContext>,
|
||||
callback: (data: any) => void,
|
||||
/**
|
||||
*Wait time in miliseconds
|
||||
*Wait time in milliseconds
|
||||
*/
|
||||
waitTime = 500
|
||||
) {
|
||||
|
|
|
@ -2,5 +2,6 @@ import { create } from 'twrnc';
|
|||
|
||||
const tw = create(require(`../../tailwind.config.js`));
|
||||
|
||||
export default tw;
|
||||
export const twStyle = tw.style;
|
||||
const twStyle = tw.style;
|
||||
|
||||
export { tw, twStyle };
|
||||
|
|
|
@ -43,9 +43,9 @@ globalThis.localStorage = {
|
|||
https://github.com/facebook/hermes/issues/23
|
||||
|
||||
We are using "Hermes" on Android & IOS, which for the current version (0.11),
|
||||
IOS does not support the Intl fully so we need pollyfill it.
|
||||
IOS does not support the Intl fully so we need polyfill it.
|
||||
|
||||
NOTE: We can be picky about what we "pollyfill" to optimize but for now this works.
|
||||
NOTE: We can be picky about what we "polyfill" to optimize but for now this works.
|
||||
*/
|
||||
|
||||
if (Platform.OS === 'ios') {
|
||||
|
@ -54,7 +54,7 @@ if (Platform.OS === 'ios') {
|
|||
}
|
||||
|
||||
// This is insane. We load all data from `AsyncStorage` into the `_localStorage` global and then once complete we import the app.
|
||||
// This way the polyfilled `localStorage` implementation has its data populated before the global stores within `@sd/client` are initialised (as they are initialised on import).
|
||||
// This way the polyfilled `localStorage` implementation has its data populated before the global stores within `@sd/client` are initialized (as they are initialized on import).
|
||||
const App = lazy(async () => {
|
||||
const keys = await AsyncStorage.getAllKeys();
|
||||
const values = await AsyncStorage.multiGet(keys);
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { DrawerScreenProps, createDrawerNavigator } from '@react-navigation/drawer';
|
||||
import { CompositeScreenProps, NavigatorScreenParams } from '@react-navigation/native';
|
||||
import { StackScreenProps } from '@react-navigation/stack';
|
||||
import DrawerContent from '~/containers/drawer/DrawerContent';
|
||||
import tw from '~/lib/tailwind';
|
||||
import DrawerContent from '~/components/drawer/DrawerContent';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
import type { RootStackParamList } from '.';
|
||||
import type { TabParamList } from './TabNavigator';
|
||||
import TabNavigator from './TabNavigator';
|
||||
|
@ -17,7 +17,7 @@ export default function DrawerNavigator() {
|
|||
headerShown: false,
|
||||
drawerStyle: {
|
||||
backgroundColor: tw.color('app-darkBox'),
|
||||
width: '75%'
|
||||
width: '70%'
|
||||
},
|
||||
overlayColor: 'transparent',
|
||||
drawerType: 'slide',
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { StackScreenProps, createStackNavigator } from '@react-navigation/stack';
|
||||
import tw from '~/lib/tailwind';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
import SettingsScreen from '~/screens/settings/Settings';
|
||||
import AppearanceSettingsScreen from '~/screens/settings/client/AppearanceSettings';
|
||||
import ExtensionsSettingsScreen from '~/screens/settings/client/ExtensionsSettings';
|
||||
|
|
|
@ -2,7 +2,7 @@ import { BottomTabScreenProps, createBottomTabNavigator } from '@react-navigatio
|
|||
import { CompositeScreenProps, NavigatorScreenParams } from '@react-navigation/native';
|
||||
import { CirclesFour, Planet, ShareNetwork } from 'phosphor-react-native';
|
||||
import React from 'react';
|
||||
import tw from '~/lib/tailwind';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
import type { HomeDrawerScreenProps } from './DrawerNavigator';
|
||||
import NodesStack, { NodesStackParamList } from './tabs/NodesStack';
|
||||
import OverviewStack, { OverviewStackParamList } from './tabs/OverviewStack';
|
||||
|
@ -36,7 +36,7 @@ export default function TabNavigator() {
|
|||
/>
|
||||
),
|
||||
tabBarLabel: 'Overview',
|
||||
tabBarLabelStyle: tw`text-tiny font-semibold`
|
||||
tabBarLabelStyle: tw`text-[10px] font-semibold`
|
||||
}}
|
||||
/>
|
||||
<Tab.Screen
|
||||
|
@ -51,7 +51,7 @@ export default function TabNavigator() {
|
|||
/>
|
||||
),
|
||||
tabBarLabel: 'Nodes',
|
||||
tabBarLabelStyle: tw`text-tiny font-semibold`
|
||||
tabBarLabelStyle: tw`text-[10px] font-semibold`
|
||||
}}
|
||||
/>
|
||||
<Tab.Screen
|
||||
|
@ -66,7 +66,7 @@ export default function TabNavigator() {
|
|||
/>
|
||||
),
|
||||
tabBarLabel: 'Spaces',
|
||||
tabBarLabelStyle: tw`text-tiny font-semibold`
|
||||
tabBarLabelStyle: tw`text-[10px] font-semibold`
|
||||
}}
|
||||
/>
|
||||
</Tab.Navigator>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { NavigatorScreenParams } from '@react-navigation/native';
|
||||
import { StackScreenProps, createStackNavigator } from '@react-navigation/stack';
|
||||
import tw from '~/lib/tailwind';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
import NotFoundScreen from '~/screens/NotFound';
|
||||
import SearchScreen from '~/screens/Search';
|
||||
import type { DrawerNavParamList } from './DrawerNavigator';
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { CompositeScreenProps } from '@react-navigation/native';
|
||||
import { StackScreenProps, createStackNavigator } from '@react-navigation/stack';
|
||||
import Header from '~/components/header/Header';
|
||||
import tw from '~/lib/tailwind';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
import NodesScreen from '~/screens/Nodes';
|
||||
import { SharedScreens, SharedScreensParamList } from '../SharedScreens';
|
||||
import { TabScreenProps } from '../TabNavigator';
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { CompositeScreenProps } from '@react-navigation/native';
|
||||
import { StackScreenProps, TransitionPresets, createStackNavigator } from '@react-navigation/stack';
|
||||
import tw from '~/lib/tailwind';
|
||||
import Header from '../../components/header/Header';
|
||||
import { StackScreenProps, createStackNavigator } from '@react-navigation/stack';
|
||||
import Header from '~/components/header/Header';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
import OverviewScreen from '../../screens/Overview';
|
||||
import { SharedScreens, SharedScreensParamList } from '../SharedScreens';
|
||||
import { TabScreenProps } from '../TabNavigator';
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { CompositeScreenProps } from '@react-navigation/native';
|
||||
import { StackScreenProps, TransitionPresets, createStackNavigator } from '@react-navigation/stack';
|
||||
import tw from '~/lib/tailwind';
|
||||
import Header from '../../components/header/Header';
|
||||
import { StackScreenProps, createStackNavigator } from '@react-navigation/stack';
|
||||
import Header from '~/components/header/Header';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
import SpacesScreen from '../../screens/Spaces';
|
||||
import { SharedScreens, SharedScreensParamList } from '../SharedScreens';
|
||||
import { TabScreenProps } from '../TabNavigator';
|
||||
|
|
|
@ -18,9 +18,23 @@ export default function LocationScreen({ navigation, route }: SharedScreenProps<
|
|||
]);
|
||||
|
||||
useEffect(() => {
|
||||
// Not sure why we do this.
|
||||
// Set screen title to location.
|
||||
if (path && path !== '') {
|
||||
// Nested location.
|
||||
navigation.setOptions({
|
||||
title: path.split('/')[0]
|
||||
});
|
||||
} else {
|
||||
navigation.setOptions({
|
||||
title: data?.context.name
|
||||
});
|
||||
}
|
||||
}, [data, navigation, path]);
|
||||
|
||||
useEffect(() => {
|
||||
getExplorerStore().locationId = id;
|
||||
}, [id]);
|
||||
getExplorerStore().path = path;
|
||||
}, [id, path]);
|
||||
|
||||
return <Explorer data={data} />;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Text, View } from 'react-native';
|
||||
import tw from '~/lib/tailwind';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
import { NodesStackScreenProps } from '~/navigation/tabs/NodesStack';
|
||||
|
||||
export default function NodesScreen({ navigation }: NodesStackScreenProps<'Nodes'>) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Text, TouchableOpacity, View } from 'react-native';
|
||||
import tw from '~/lib/tailwind';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
import { RootStackScreenProps } from '~/navigation';
|
||||
|
||||
export default function NotFoundScreen({ navigation }: RootStackScreenProps<'NotFound'>) {
|
||||
|
|
|
@ -1,50 +1,15 @@
|
|||
import { View } from 'react-native';
|
||||
import VirtualizedListWrapper from '~/components/layout/VirtualizedListWrapper';
|
||||
import OverviewStats from '~/containers/OverviewStats';
|
||||
import tw from '~/lib/tailwind';
|
||||
import OverviewStats from '~/components/overview/OverviewStats';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
import { OverviewStackScreenProps } from '~/navigation/tabs/OverviewStack';
|
||||
|
||||
// const placeholderDevices: any = [
|
||||
// {
|
||||
// name: "James' iPhone 12",
|
||||
// size: '47.9GB',
|
||||
// locations: [],
|
||||
// type: 'phone'
|
||||
// },
|
||||
// {
|
||||
// name: "James' MacBook Pro",
|
||||
// size: '1TB',
|
||||
// locations: [],
|
||||
// type: 'laptop'
|
||||
// },
|
||||
// {
|
||||
// name: "James' Toaster",
|
||||
// size: '1PB',
|
||||
// locations: [],
|
||||
// type: 'desktop'
|
||||
// },
|
||||
// {
|
||||
// name: 'Spacedrive Server',
|
||||
// size: '5GB',
|
||||
// locations: [],
|
||||
// type: 'server'
|
||||
// }
|
||||
// ];
|
||||
|
||||
export default function OverviewScreen({ navigation }: OverviewStackScreenProps<'Overview'>) {
|
||||
return (
|
||||
<VirtualizedListWrapper>
|
||||
<View style={tw`mt-4 px-4`}>
|
||||
{/* Stats */}
|
||||
<OverviewStats />
|
||||
{/* Devices */}
|
||||
{/* <FlatList
|
||||
data={placeholderDevices}
|
||||
keyExtractor={(item, index) => index.toString()}
|
||||
renderItem={({ item }) => (
|
||||
<Device locations={[]} name={item.name} size={item.size} type={item.type} />
|
||||
)}
|
||||
/> */}
|
||||
</View>
|
||||
</VirtualizedListWrapper>
|
||||
);
|
||||
|
|
|
@ -3,7 +3,7 @@ import { useState } from 'react';
|
|||
import { ActivityIndicator, Pressable, Text, TextInput, View } from 'react-native';
|
||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
import { Button } from '~/components/primitive/Button';
|
||||
import tw, { twStyle } from '~/lib/tailwind';
|
||||
import { tw, twStyle } from '~/lib/tailwind';
|
||||
import { RootStackScreenProps } from '~/navigation';
|
||||
|
||||
const SearchScreen = ({ navigation }: RootStackScreenProps<'Search'>) => {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Text, View } from 'react-native';
|
||||
import tw from '~/lib/tailwind';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
import { SpacesStackScreenProps } from '~/navigation/tabs/SpacesStack';
|
||||
|
||||
export default function SpacesScreen({ navigation }: SpacesStackScreenProps<'Spaces'>) {
|
||||
|
|
|
@ -1,18 +1,25 @@
|
|||
import { Text, View } from 'react-native';
|
||||
import { useEffect } from 'react';
|
||||
import { useLibraryQuery } from '@sd/client';
|
||||
import Explorer from '~/components/explorer/Explorer';
|
||||
import tw from '~/lib/tailwind';
|
||||
import { SharedScreenProps } from '~/navigation/SharedScreens';
|
||||
import { getExplorerStore } from '~/stores/explorerStore';
|
||||
|
||||
export default function TagScreen({ navigation, route }: SharedScreenProps<'Tag'>) {
|
||||
const { id } = route.params;
|
||||
|
||||
const { data } = useLibraryQuery(['tags.getExplorerData', id]);
|
||||
|
||||
return (
|
||||
<View style={tw`flex-1 items-center justify-center`}>
|
||||
<Text style={tw`text-ink text-xl font-bold`}>Tag {id}</Text>
|
||||
<Explorer data={data} />
|
||||
</View>
|
||||
);
|
||||
useEffect(() => {
|
||||
// Set screen title to tag name.
|
||||
navigation.setOptions({
|
||||
title: data?.context.name
|
||||
});
|
||||
}, [data?.context.name, navigation]);
|
||||
|
||||
useEffect(() => {
|
||||
getExplorerStore().locationId = id;
|
||||
// getExplorerStore().path = path;
|
||||
}, [id]);
|
||||
|
||||
return <Explorer data={data} />;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Text, View } from 'react-native';
|
||||
import CreateLibraryDialog from '~/components/dialog/CreateLibraryDialog';
|
||||
import { AnimatedButton } from '~/components/primitive/Button';
|
||||
import CreateLibraryDialog from '~/containers/dialog/CreateLibraryDialog';
|
||||
import tw from '~/lib/tailwind';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
import { OnboardingStackScreenProps } from '~/navigation/OnboardingNavigator';
|
||||
|
||||
const CreateLibraryScreen = ({ navigation }: OnboardingStackScreenProps<'CreateLibrary'>) => {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Image, Text, View } from 'react-native';
|
||||
import { FadeInUpAnimation, LogoAnimation } from '~/components/animation/layout';
|
||||
import { AnimatedButton } from '~/components/primitive/Button';
|
||||
import tw from '~/lib/tailwind';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
import { OnboardingStackScreenProps } from '~/navigation/OnboardingNavigator';
|
||||
|
||||
const OnboardingScreen = ({ navigation }: OnboardingStackScreenProps<'Onboarding'>) => {
|
||||
|
|
|
@ -15,7 +15,7 @@ import {
|
|||
import React from 'react';
|
||||
import { SectionList, Text, View } from 'react-native';
|
||||
import { SettingsItem, SettingsItemDivider } from '~/components/settings/SettingsItem';
|
||||
import tw, { twStyle } from '~/lib/tailwind';
|
||||
import { tw, twStyle } from '~/lib/tailwind';
|
||||
import { SettingsStackParamList, SettingsStackScreenProps } from '~/navigation/SettingsNavigator';
|
||||
|
||||
type SectionType = {
|
||||
|
@ -109,7 +109,7 @@ function renderSectionHeader({ section }: { section: { title: string } }) {
|
|||
return (
|
||||
<Text
|
||||
style={twStyle(
|
||||
'text-ink-dull mb-2 ml-2 text-sm font-semibold',
|
||||
'text-ink-dull mb-2 ml-3 text-sm font-semibold',
|
||||
section.title === 'Client' ? 'mt-2' : 'mt-5'
|
||||
)}
|
||||
>
|
||||
|
@ -136,7 +136,7 @@ export default function SettingsScreen({ navigation }: SettingsStackScreenProps<
|
|||
ListFooterComponent={
|
||||
<View style={tw`mt-6 mb-4 items-center`}>
|
||||
<Text style={tw`text-ink text-sm font-bold`}>Spacedrive</Text>
|
||||
<Text style={tw`text-ink-dull mt-0.5 text-xs`}>v0.1.0</Text>
|
||||
<Text style={tw`text-ink-faint mt-0.5 text-xs`}>v0.1.0</Text>
|
||||
</View>
|
||||
}
|
||||
showsVerticalScrollIndicator={false}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import { Text, View } from 'react-native';
|
||||
import tw from '~/lib/tailwind';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
import { SettingsStackScreenProps } from '~/navigation/SettingsNavigator';
|
||||
|
||||
const AppearanceSettingsScreen = ({
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import { Text, View } from 'react-native';
|
||||
import tw from '~/lib/tailwind';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
import { SettingsStackScreenProps } from '~/navigation/SettingsNavigator';
|
||||
|
||||
const ExtensionsSettingsScreen = ({
|
||||
|
|
|
@ -4,7 +4,7 @@ import { useBridgeQuery } from '@sd/client';
|
|||
import Card from '~/components/layout/Card';
|
||||
import Divider from '~/components/primitive/Divider';
|
||||
import { Input } from '~/components/primitive/Input';
|
||||
import tw from '~/lib/tailwind';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
import { SettingsStackScreenProps } from '~/navigation/SettingsNavigator';
|
||||
|
||||
const GeneralSettingsScreen = ({ navigation }: SettingsStackScreenProps<'GeneralSettings'>) => {
|
||||
|
|
|
@ -3,9 +3,9 @@ import React from 'react';
|
|||
import { Animated, FlatList, Text, View } from 'react-native';
|
||||
import { Swipeable } from 'react-native-gesture-handler';
|
||||
import { LibraryConfigWrapped, useBridgeQuery } from '@sd/client';
|
||||
import DeleteLibraryModal from '~/components/modal/confirm-modals/DeleteLibraryModal';
|
||||
import { AnimatedButton } from '~/components/primitive/Button';
|
||||
import DeleteLibraryDialog from '~/containers/dialog/DeleteLibraryDialog';
|
||||
import tw, { twStyle } from '~/lib/tailwind';
|
||||
import { tw, twStyle } from '~/lib/tailwind';
|
||||
import { SettingsStackScreenProps } from '~/navigation/SettingsNavigator';
|
||||
|
||||
function LibraryItem({
|
||||
|
@ -34,11 +34,14 @@ function LibraryItem({
|
|||
<AnimatedButton size="md" onPress={() => navigation.replace('LibraryGeneralSettings')}>
|
||||
<Pen size={18} color="white" />
|
||||
</AnimatedButton>
|
||||
<DeleteLibraryDialog libraryUuid={library.uuid}>
|
||||
<DeleteLibraryModal
|
||||
libraryUuid={library.uuid}
|
||||
trigger={
|
||||
<AnimatedButton size="md" style={tw`mx-2`}>
|
||||
<Trash size={18} color="white" />
|
||||
</AnimatedButton>
|
||||
</DeleteLibraryDialog>
|
||||
}
|
||||
/>
|
||||
</Animated.View>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import { Text, View } from 'react-native';
|
||||
import tw from '~/lib/tailwind';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
import { SettingsStackScreenProps } from '~/navigation/SettingsNavigator';
|
||||
|
||||
const PrivacySettingsScreen = ({ navigation }: SettingsStackScreenProps<'PrivacySettings'>) => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import { Text, View } from 'react-native';
|
||||
import tw from '~/lib/tailwind';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
import { SettingsStackScreenProps } from '~/navigation/SettingsNavigator';
|
||||
|
||||
const AboutScreen = ({ navigation }: SettingsStackScreenProps<'About'>) => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import { Text, View } from 'react-native';
|
||||
import tw from '~/lib/tailwind';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
import { SettingsStackScreenProps } from '~/navigation/SettingsNavigator';
|
||||
|
||||
const SupportScreen = ({ navigation }: SettingsStackScreenProps<'Support'>) => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import { Text, View } from 'react-native';
|
||||
import tw from '~/lib/tailwind';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
import { SettingsStackScreenProps } from '~/navigation/SettingsNavigator';
|
||||
|
||||
const KeysSettingsScreen = ({ navigation }: SettingsStackScreenProps<'KeysSettings'>) => {
|
||||
|
|
|
@ -9,7 +9,7 @@ import { Switch } from '~/components/primitive/Switch';
|
|||
import { SettingsContainer } from '~/components/settings/SettingsContainer';
|
||||
import { SettingsItem } from '~/components/settings/SettingsItem';
|
||||
import { useAutoForm } from '~/hooks/useAutoForm';
|
||||
import tw from '~/lib/tailwind';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
import { SettingsStackScreenProps } from '~/navigation/SettingsNavigator';
|
||||
|
||||
const LibraryGeneralSettingsScreen = ({
|
||||
|
@ -60,9 +60,8 @@ const LibraryGeneralSettingsScreen = ({
|
|||
{/* Export */}
|
||||
<SettingsItem title="Export Library" onPress={() => Alert.alert('TODO')} />
|
||||
<View style={tw`mt-4`} />
|
||||
{/* Delete Library
|
||||
TODO: Open delete library dialog here, but do handle library switching
|
||||
And what happens if there is no library set ? */}
|
||||
{/* Delete Library */}
|
||||
{/* TODO: Open delete library dialog here, but do handle library switching and what happens if there is no library set ? */}
|
||||
<SettingsContainer description="This is permanent, your files will not be deleted, only the Spacedrive library.">
|
||||
<SettingsItem
|
||||
title="Delete Library"
|
||||
|
|
|
@ -10,8 +10,8 @@ import {
|
|||
useOnlineLocations
|
||||
} from '@sd/client';
|
||||
import FolderIcon from '~/components/icons/FolderIcon';
|
||||
import DeleteLocationDialog from '~/containers/dialog/DeleteLocationDialog';
|
||||
import tw, { twStyle } from '~/lib/tailwind';
|
||||
import DeleteLocationModal from '~/components/modal/confirm-modals/DeleteLocationModal';
|
||||
import { tw, twStyle } from '~/lib/tailwind';
|
||||
import { SettingsStackScreenProps } from '~/navigation/SettingsNavigator';
|
||||
|
||||
function LocationItem({ location, index }: { location: Location & { node: Node }; index: number }) {
|
||||
|
@ -34,13 +34,16 @@ function LocationItem({ location, index }: { location: Location & { node: Node }
|
|||
<Animated.View
|
||||
style={[tw`flex flex-row items-center`, { transform: [{ translateX: translate }] }]}
|
||||
>
|
||||
<DeleteLocationDialog locationId={location.id}>
|
||||
<DeleteLocationModal
|
||||
locationId={location.id}
|
||||
trigger={
|
||||
<View
|
||||
style={tw`border-app-line bg-app-button items-center justify-center rounded-md border py-1.5 px-3 shadow-sm`}
|
||||
style={tw`bg-app-button border-app-line items-center justify-center rounded-md border py-1.5 px-3 shadow-sm`}
|
||||
>
|
||||
<Trash size={18} color="white" />
|
||||
</View>
|
||||
</DeleteLocationDialog>
|
||||
}
|
||||
/>
|
||||
{/* Full Re-scan IS too much here */}
|
||||
<Pressable
|
||||
style={tw`border-app-line bg-app-button mx-2 items-center justify-center rounded-md border py-1.5 px-3 shadow-sm`}
|
||||
|
@ -68,7 +71,7 @@ function LocationItem({ location, index }: { location: Location & { node: Node }
|
|||
<View
|
||||
style={twStyle(
|
||||
'absolute right-0 bottom-0.5 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'
|
||||
)}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import { Text, View } from 'react-native';
|
||||
import tw from '~/lib/tailwind';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
import { SettingsStackScreenProps } from '~/navigation/SettingsNavigator';
|
||||
|
||||
const NodesSettingsScreen = ({ navigation }: SettingsStackScreenProps<'NodesSettings'>) => {
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
import { CaretRight, Pen, Trash } from 'phosphor-react-native';
|
||||
import { useRef } from 'react';
|
||||
import { Animated, FlatList, Text, View } from 'react-native';
|
||||
import { Swipeable } from 'react-native-gesture-handler';
|
||||
import { Tag, useLibraryQuery } from '@sd/client';
|
||||
import { ModalRef } from '~/components/layout/Modal';
|
||||
import DeleteTagModal from '~/components/modal/confirm-modals/DeleteTagModal';
|
||||
import UpdateTagModal from '~/components/modal/tag/UpdateTagModal';
|
||||
import { AnimatedButton } from '~/components/primitive/Button';
|
||||
import DeleteTagDialog from '~/containers/dialog/tag/DeleteTagDialog';
|
||||
import UpdateTagDialog from '~/containers/dialog/tag/UpdateTagDialog';
|
||||
import tw, { twStyle } from '~/lib/tailwind';
|
||||
import { tw, twStyle } from '~/lib/tailwind';
|
||||
import { SettingsStackScreenProps } from '~/navigation/SettingsNavigator';
|
||||
|
||||
function TagItem({ tag, index }: { tag: Tag; index: number }) {
|
||||
const updateTagModalRef = useRef<ModalRef>();
|
||||
|
||||
const renderRightActions = (
|
||||
progress: Animated.AnimatedInterpolation<number>,
|
||||
_dragX: Animated.AnimatedInterpolation<number>,
|
||||
|
@ -24,16 +28,18 @@ function TagItem({ tag, index }: { tag: Tag; index: number }) {
|
|||
<Animated.View
|
||||
style={[tw`flex flex-row items-center`, { transform: [{ translateX: translate }] }]}
|
||||
>
|
||||
<UpdateTagDialog tag={tag} onSubmit={() => swipeable.close()}>
|
||||
<AnimatedButton size="md">
|
||||
<UpdateTagModal tag={tag} ref={updateTagModalRef} onSubmit={() => swipeable.close()} />
|
||||
<AnimatedButton size="md" onPress={() => updateTagModalRef.current.present()}>
|
||||
<Pen size={18} color="white" />
|
||||
</AnimatedButton>
|
||||
</UpdateTagDialog>
|
||||
<DeleteTagDialog tagId={tag.id}>
|
||||
<DeleteTagModal
|
||||
tagId={tag.id}
|
||||
trigger={
|
||||
<AnimatedButton size="md" style={tw`mx-2`}>
|
||||
<Trash size={18} color="white" />
|
||||
</AnimatedButton>
|
||||
</DeleteTagDialog>
|
||||
}
|
||||
/>
|
||||
</Animated.View>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -8,6 +8,7 @@ export type ExplorerKind = 'Location' | 'Tag' | 'Space';
|
|||
|
||||
const state = {
|
||||
locationId: null as number | null,
|
||||
path: '',
|
||||
layoutMode: 'grid' as ExplorerLayoutMode,
|
||||
// Using gridNumColumns instead of fixed size. We dynamically calculate the item size.
|
||||
gridNumColumns: 3,
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
import { BottomSheetModal } from '@gorhom/bottom-sheet';
|
||||
import { createRef } from 'react';
|
||||
import { proxy, ref, useSnapshot } from 'valtio';
|
||||
import { ExplorerItem } from '@sd/client';
|
||||
import { ModalRef } from '~/components/layout/Modal';
|
||||
|
||||
export const fileModalStore = proxy({
|
||||
fileRef: ref(createRef<BottomSheetModal>()),
|
||||
export const actionsModalStore = proxy({
|
||||
modalRef: ref(createRef<ModalRef>()),
|
||||
data: null as ExplorerItem | null,
|
||||
setData: (data: ExplorerItem) => {
|
||||
fileModalStore.data = data;
|
||||
actionsModalStore.data = data;
|
||||
}
|
||||
});
|
||||
|
||||
export function useFileModalStore() {
|
||||
return useSnapshot(fileModalStore);
|
||||
export function useActionsModalStore() {
|
||||
return useSnapshot(actionsModalStore);
|
||||
}
|
||||
|
|
|
@ -1,11 +1 @@
|
|||
import { ExplorerItem } from '@sd/client';
|
||||
|
||||
export type valueof<T> = T[keyof T];
|
||||
|
||||
export function isPath(item: ExplorerItem): item is Extract<ExplorerItem, { type: 'Path' }> {
|
||||
return item.type === 'Path';
|
||||
}
|
||||
|
||||
export function isObject(item: ExplorerItem): item is Extract<ExplorerItem, { type: 'Object' }> {
|
||||
return item.type === 'Object';
|
||||
}
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
// Extented colors are copied from packages/ui/style/colors.scss
|
||||
// Extended colors are copied from packages/ui/style/colors.scss
|
||||
|
||||
module.exports = {
|
||||
content: ['./screens/**/*.{js,ts,jsx}', './components/**/*.{js,ts,jsx}', 'App.tsx'],
|
||||
theme: {
|
||||
extend: {
|
||||
fontSize: {
|
||||
tiny: '.65rem',
|
||||
// Default: '0.875rem'
|
||||
sm: '.85rem'
|
||||
},
|
||||
colors: {
|
||||
// Brand blue
|
||||
accent: {
|
||||
|
@ -61,6 +56,11 @@ module.exports = {
|
|||
950: 'hsla(230, 15%, 95%, 1)',
|
||||
1000: 'hsla(230, 15%, 100%, 1)'
|
||||
},
|
||||
sidebar: {
|
||||
box: 'hsla(230, 15%, 16%, 1)',
|
||||
line: 'hsla(230, 15%, 23%, 1)',
|
||||
button: 'hsla(230, 15%, 18%, 1)'
|
||||
},
|
||||
gray: {
|
||||
DEFAULT: '#505468',
|
||||
50: '#F1F1F4',
|
||||
|
|
|
@ -60,10 +60,8 @@ To run mobile app
|
|||
2. `./.github/scripts/setup-system.sh mobile`
|
||||
_The should setup most of the dependencies for the mobile app to build._
|
||||
3. You must also ensure you have [NDK 24.0.8215888 and CMake](https://developer.android.com/studio/projects/install-ndk#default-version) in Android Studio
|
||||
4. `cd apps/mobile && pnpm i` - This is a separate workspace, you need to do this!
|
||||
5. `pnpm android` - runs on Android Emulator
|
||||
6. `pnpm ios` - runs on iOS Emulator
|
||||
7. `pnpm dev` - For already bundled app - This is only temporarily supported. The final app will require the Spacedrive Rust code which isn't included in Expo Go.
|
||||
4. `pnpm mobile android` - runs on Android Emulator
|
||||
5. `pnpm mobile ios` - runs on iOS Emulator
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
|
|
|
@ -13,9 +13,6 @@ const currentLibraryUuidStore = valtioPersist('sdActiveLibrary', {
|
|||
id: null as string | null
|
||||
});
|
||||
|
||||
// Cringe method to get rspc working on mobile.
|
||||
export const mobileSync = currentLibraryUuidStore;
|
||||
|
||||
const CringeContext = createContext<{
|
||||
onNoLibrary: OnNoLibraryFunc;
|
||||
}>(undefined!);
|
||||
|
|
11
packages/client/src/utils/formatBytes.ts
Normal file
11
packages/client/src/utils/formatBytes.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
export function formatBytes(bytes: number, decimals = 2) {
|
||||
if (bytes === 0) return '0 Bytes';
|
||||
|
||||
const k = 1024;
|
||||
const dm = decimals < 0 ? 0 : decimals;
|
||||
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
||||
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
|
||||
}
|
|
@ -1,3 +1,16 @@
|
|||
import { ExplorerItem } from '../core';
|
||||
|
||||
export * from './objectKind';
|
||||
export * from './formatBytes';
|
||||
|
||||
export function isPath(item: ExplorerItem): item is Extract<ExplorerItem, { type: 'Path' }> {
|
||||
return item.type === 'Path';
|
||||
}
|
||||
|
||||
export function isObject(item: ExplorerItem): item is Extract<ExplorerItem, { type: 'Object' }> {
|
||||
return item.type === 'Object';
|
||||
}
|
||||
|
||||
export function arraysEqual<T>(a: T[], b: T[]) {
|
||||
if (a === b) return true;
|
||||
if (a == null || b == null) return false;
|
||||
|
@ -5,5 +18,3 @@ export function arraysEqual<T>(a: T[], b: T[]) {
|
|||
|
||||
return a.every((n, i) => b[i] === n);
|
||||
}
|
||||
|
||||
export * from './objectKind';
|
||||
|
|
|
@ -17,7 +17,13 @@ import {
|
|||
TrashSimple
|
||||
} from 'phosphor-react';
|
||||
import { PropsWithChildren, useMemo } from 'react';
|
||||
import { ExplorerItem, getLibraryIdRaw, useLibraryMutation, useLibraryQuery } from '@sd/client';
|
||||
import {
|
||||
ExplorerItem,
|
||||
getLibraryIdRaw,
|
||||
isObject,
|
||||
useLibraryMutation,
|
||||
useLibraryQuery
|
||||
} from '@sd/client';
|
||||
import { ContextMenu as CM, dialogManager } from '@sd/ui';
|
||||
import { getExplorerStore, useExplorerStore } from '~/hooks/useExplorerStore';
|
||||
import { useOperatingSystem } from '~/hooks/useOperatingSystem';
|
||||
|
@ -28,7 +34,6 @@ import { DecryptFileDialog } from '../dialog/DecryptFileDialog';
|
|||
import { DeleteFileDialog } from '../dialog/DeleteFileDialog';
|
||||
import { EncryptFileDialog } from '../dialog/EncryptFileDialog';
|
||||
import { EraseFileDialog } from '../dialog/EraseFileDialog';
|
||||
import { isObject } from './utils';
|
||||
|
||||
const AssignTagMenuItems = (props: { objectId: number }) => {
|
||||
const tags = useLibraryQuery(['tags.list'], { suspense: true });
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
import clsx from 'clsx';
|
||||
import { HTMLAttributes } from 'react';
|
||||
import { ExplorerItem, ObjectKind } from '@sd/client';
|
||||
import { ExplorerItem, ObjectKind, isObject } from '@sd/client';
|
||||
import { cva, tw } from '@sd/ui';
|
||||
import { getExplorerStore } from '~/hooks/useExplorerStore';
|
||||
import { FileItemContextMenu } from './ExplorerContextMenu';
|
||||
import FileThumb from './FileThumb';
|
||||
import { isObject } from './utils';
|
||||
|
||||
const NameArea = tw.div`flex justify-center`;
|
||||
|
||||
|
|
|
@ -4,12 +4,10 @@ import executable from '@sd/assets/images/Executable.png';
|
|||
import file from '@sd/assets/images/File.png';
|
||||
import video from '@sd/assets/images/Video.png';
|
||||
import clsx from 'clsx';
|
||||
import { Suspense, lazy, useMemo } from 'react';
|
||||
import { ExplorerItem } from '@sd/client';
|
||||
import { ExplorerItem, isObject, isPath } from '@sd/client';
|
||||
import { useExplorerStore } from '~/hooks/useExplorerStore';
|
||||
import { usePlatform } from '~/util/Platform';
|
||||
import { Folder } from '../icons/Folder';
|
||||
import { isObject, isPath } from './utils';
|
||||
|
||||
interface Props {
|
||||
data: ExplorerItem;
|
||||
|
@ -20,22 +18,20 @@ interface Props {
|
|||
kind?: string;
|
||||
}
|
||||
|
||||
const icons = import.meta.glob('../../../../assets/icons/*.svg');
|
||||
// const icons = import.meta.glob('../../../../assets/icons/*.svg');
|
||||
|
||||
export default function FileThumb({ data, ...props }: Props) {
|
||||
const platform = usePlatform();
|
||||
const store = useExplorerStore();
|
||||
|
||||
const item = data.item;
|
||||
// const Icon = useMemo(() => {
|
||||
// const icon = icons[`../../../../assets/icons/${item.extension}.svg`];
|
||||
|
||||
const Icon = useMemo(() => {
|
||||
const icon = icons[`../../../../assets/icons/${item.extension}.svg`];
|
||||
|
||||
const Icon = icon
|
||||
? lazy(() => icon().then((v) => ({ default: (v as any).ReactComponent })))
|
||||
: undefined;
|
||||
return Icon;
|
||||
}, [item.extension]);
|
||||
// const Icon = icon
|
||||
// ? lazy(() => icon().then((v) => ({ default: (v as any).ReactComponent })))
|
||||
// : undefined;
|
||||
// return Icon;
|
||||
// }, [item.extension]);
|
||||
|
||||
if (isPath(data) && data.item.is_dir) return <Folder size={props.size * 0.7} />;
|
||||
|
||||
|
|
|
@ -3,7 +3,14 @@ import clsx from 'clsx';
|
|||
import dayjs from 'dayjs';
|
||||
import { Barcode, CircleWavyCheck, Clock, Cube, Link, Lock, Snowflake } from 'phosphor-react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { ExplorerContext, ExplorerItem, ObjectKind, useLibraryQuery } from '@sd/client';
|
||||
import {
|
||||
ExplorerContext,
|
||||
ExplorerItem,
|
||||
ObjectKind,
|
||||
formatBytes,
|
||||
isObject,
|
||||
useLibraryQuery
|
||||
} from '@sd/client';
|
||||
import { Button, tw } from '@sd/ui';
|
||||
import { DefaultProps } from '../primitive/types';
|
||||
import { Tooltip } from '../tooltip/Tooltip';
|
||||
|
@ -11,7 +18,6 @@ import FileThumb from './FileThumb';
|
|||
import { Divider } from './inspector/Divider';
|
||||
import FavoriteButton from './inspector/FavoriteButton';
|
||||
import Note from './inspector/Note';
|
||||
import { isObject } from './utils';
|
||||
|
||||
export const InfoPill = tw.span`inline border border-transparent px-1 text-[11px] font-medium shadow shadow-app-shade/5 bg-app-selected rounded-md text-ink-dull`;
|
||||
|
||||
|
@ -77,7 +83,7 @@ export const Inspector = ({ data, context, ...elementProps }: Props) => {
|
|||
iconClassNames="my-3 max-h-[150px]"
|
||||
size={230}
|
||||
kind={ObjectKind[objectData?.kind || 0]}
|
||||
className="flex shrink grow-0 bg-green-500"
|
||||
className="flex shrink grow-0"
|
||||
data={data}
|
||||
/>
|
||||
</div>
|
||||
|
@ -112,7 +118,6 @@ export const Inspector = ({ data, context, ...elementProps }: Props) => {
|
|||
</MetaContainer>
|
||||
)}
|
||||
<Divider />
|
||||
{
|
||||
<MetaContainer>
|
||||
<div className="flex flex-wrap gap-1">
|
||||
<InfoPill>{isDir ? 'Folder' : ObjectKind[objectData?.kind || 0]}</InfoPill>
|
||||
|
@ -129,7 +134,6 @@ export const Inspector = ({ data, context, ...elementProps }: Props) => {
|
|||
<PlaceholderPill>Add Tag</PlaceholderPill>
|
||||
</div>
|
||||
</MetaContainer>
|
||||
}
|
||||
<Divider />
|
||||
<MetaContainer className="!flex-row space-x-2">
|
||||
<MetaTextLine>
|
||||
|
@ -193,15 +197,3 @@ export const Inspector = ({ data, context, ...elementProps }: Props) => {
|
|||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
function formatBytes(bytes: number, decimals = 2) {
|
||||
if (bytes === 0) return '0 Bytes';
|
||||
|
||||
const k = 1024;
|
||||
const dm = decimals < 0 ? 0 : decimals;
|
||||
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
||||
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
|
||||
}
|
||||
|
|
|
@ -2,11 +2,10 @@ import { useVirtualizer } from '@tanstack/react-virtual';
|
|||
import { memo, useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { useKey, useOnWindowResize } from 'rooks';
|
||||
import { ExplorerContext, ExplorerItem } from '@sd/client';
|
||||
import { ExplorerContext, ExplorerItem, isPath } from '@sd/client';
|
||||
import { ExplorerLayoutMode, getExplorerStore, useExplorerStore } from '~/hooks/useExplorerStore';
|
||||
import FileItem from './FileItem';
|
||||
import FileRow from './FileRow';
|
||||
import { isPath } from './utils';
|
||||
|
||||
const TOP_BAR_HEIGHT = 46;
|
||||
const GRID_TEXT_AREA_HEIGHT = 25;
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
import { ExplorerItem, FilePath } from '@sd/client';
|
||||
|
||||
export function isPath(item: ExplorerItem): item is Extract<ExplorerItem, { type: 'Path' }> {
|
||||
return item.type === 'Path';
|
||||
}
|
||||
|
||||
export function isObject(item: ExplorerItem): item is Extract<ExplorerItem, { type: 'Object' }> {
|
||||
return item.type === 'Object';
|
||||
}
|
325
pnpm-lock.yaml
325
pnpm-lock.yaml
|
@ -186,46 +186,46 @@ importers:
|
|||
'@gorhom/bottom-sheet': ^4.4.5
|
||||
'@react-native-async-storage/async-storage': ~1.17.11
|
||||
'@react-native-masked-view/masked-view': 0.2.8
|
||||
'@react-navigation/bottom-tabs': ^6.5.2
|
||||
'@react-navigation/drawer': ^6.5.6
|
||||
'@react-navigation/native': ^6.0.13
|
||||
'@react-navigation/stack': ^6.3.10
|
||||
'@rnx-kit/metro-config': ^1.3.2
|
||||
'@react-navigation/bottom-tabs': ^6.5.4
|
||||
'@react-navigation/drawer': ^6.5.8
|
||||
'@react-navigation/native': ^6.1.3
|
||||
'@react-navigation/stack': ^6.3.12
|
||||
'@rnx-kit/metro-config': ^1.3.5
|
||||
'@rspc/client': ^0.0.0-main-7c0a67c1
|
||||
'@rspc/react': ^0.0.0-main-7c0a67c1
|
||||
'@sd/assets': workspace:*
|
||||
'@sd/client': workspace:*
|
||||
'@sd/config': workspace:*
|
||||
'@shopify/flash-list': 1.4.0
|
||||
'@tanstack/react-query': ^4.20.9
|
||||
'@shopify/flash-list': 1.4.1
|
||||
'@tanstack/react-query': ^4.24.4
|
||||
'@types/react': ~18.0.26
|
||||
'@types/react-native': ~0.70.8
|
||||
babel-plugin-module-resolver: ^4.1.0
|
||||
babel-plugin-module-resolver: ^5.0.0
|
||||
byte-size: ^8.1.0
|
||||
class-variance-authority: ^0.4.0
|
||||
dayjs: ^1.11.6
|
||||
dayjs: ^1.11.5
|
||||
eslint-plugin-react-native: ^4.0.0
|
||||
expo: ^47.0.10
|
||||
expo: ^47.0.13
|
||||
expo-linking: ~3.3.0
|
||||
expo-media-library: ~15.0.0
|
||||
expo-splash-screen: ~0.17.5
|
||||
expo-status-bar: ~1.4.2
|
||||
intl: ^1.2.5
|
||||
lottie-react-native: 5.1.4
|
||||
metro-minify-terser: ^0.73.6
|
||||
moti: ^0.21.0
|
||||
metro-minify-terser: ^0.74.1
|
||||
moti: ^0.22.0
|
||||
phosphor-react-native: ^1.1.2
|
||||
react: 18.1.0
|
||||
react-hook-form: ^7.41.5
|
||||
react-hook-form: ^7.43.0
|
||||
react-native: 0.70.5
|
||||
react-native-document-picker: ^8.1.1
|
||||
react-native-fs: ^2.20.0
|
||||
react-native-gesture-handler: ~2.8.0
|
||||
react-native-gesture-handler: ~2.9.0
|
||||
react-native-popup-menu: ^0.16.1
|
||||
react-native-reanimated: ~2.13.0
|
||||
react-native-safe-area-context: 4.4.1
|
||||
react-native-screens: ~3.18.2
|
||||
react-native-svg: 13.6.0
|
||||
react-native-reanimated: ~2.14.4
|
||||
react-native-safe-area-context: 4.5.0
|
||||
react-native-screens: ~3.19.0
|
||||
react-native-svg: 13.8.0
|
||||
react-native-svg-transformer: ^1.0.0
|
||||
react-native-wheel-color-picker: ^1.2.0
|
||||
twrnc: ^3.5.0
|
||||
|
@ -234,19 +234,19 @@ importers:
|
|||
use-debounce: ^9.0.2
|
||||
valtio: ^1.8.0
|
||||
dependencies:
|
||||
'@gorhom/bottom-sheet': 4.4.5_cuwuttpow3vlkihawr5ojezmtm
|
||||
'@gorhom/bottom-sheet': 4.4.5_w366bumyfs4uyicayprrehskae
|
||||
'@react-native-async-storage/async-storage': 1.17.11_react-native@0.70.5
|
||||
'@react-native-masked-view/masked-view': 0.2.8_tj3nonr5gneraukzjkxpsiy7yu
|
||||
'@react-navigation/bottom-tabs': 6.5.3_4yxn5o6hbqm4eqjpnbll7jojyu
|
||||
'@react-navigation/drawer': 6.5.7_yrgdxcwem6xwiw4ihiusk6rm7m
|
||||
'@react-navigation/native': 6.1.2_tj3nonr5gneraukzjkxpsiy7yu
|
||||
'@react-navigation/stack': 6.3.11_omkqc3xm6hu7gsihfbjfmuohle
|
||||
'@react-navigation/bottom-tabs': 6.5.4_tzhjy2gc5kvqqitykreeetpfsq
|
||||
'@react-navigation/drawer': 6.5.8_5pbm2y6oxn4wiaxvhnj4nykkku
|
||||
'@react-navigation/native': 6.1.3_tj3nonr5gneraukzjkxpsiy7yu
|
||||
'@react-navigation/stack': 6.3.12_tvuqzzu4d6qsmbauwbo7nuei7e
|
||||
'@rspc/client': 0.0.0-main-7c0a67c1
|
||||
'@rspc/react': 0.0.0-main-7c0a67c1_7aie4jek34mpa466duyggl5x24
|
||||
'@rspc/react': 0.0.0-main-7c0a67c1_6niuqkvdadibsmemv5phcmgdcq
|
||||
'@sd/assets': link:../../packages/assets
|
||||
'@sd/client': link:../../packages/client
|
||||
'@shopify/flash-list': 1.4.0_tj3nonr5gneraukzjkxpsiy7yu
|
||||
'@tanstack/react-query': 4.22.0_tj3nonr5gneraukzjkxpsiy7yu
|
||||
'@shopify/flash-list': 1.4.1_tj3nonr5gneraukzjkxpsiy7yu
|
||||
'@tanstack/react-query': 4.24.4_tj3nonr5gneraukzjkxpsiy7yu
|
||||
byte-size: 8.1.0
|
||||
class-variance-authority: 0.4.0_typescript@4.9.4
|
||||
dayjs: 1.11.7
|
||||
|
@ -257,33 +257,33 @@ importers:
|
|||
expo-status-bar: 1.4.2
|
||||
intl: 1.2.5
|
||||
lottie-react-native: 5.1.4_tj3nonr5gneraukzjkxpsiy7yu
|
||||
moti: 0.21.0_xxoigs3lrtexqhfttsykzq4gba
|
||||
phosphor-react-native: 1.1.2_6rmyt7g6mjmjm44v4kwwqzmzjy
|
||||
moti: 0.22.0_wwrhtnmkhk6ixblrbdwhxojxqi
|
||||
phosphor-react-native: 1.1.2_tdhmirddlb52bzkqlwgrsfpe6m
|
||||
react: 18.1.0
|
||||
react-hook-form: 7.42.1_react@18.1.0
|
||||
react-hook-form: 7.43.0_react@18.1.0
|
||||
react-native: 0.70.5_react@18.1.0
|
||||
react-native-document-picker: 8.1.3_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react-native-fs: 2.20.0_react-native@0.70.5
|
||||
react-native-gesture-handler: 2.8.0_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react-native-gesture-handler: 2.9.0_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react-native-popup-menu: 0.16.1
|
||||
react-native-reanimated: 2.13.0_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react-native-safe-area-context: 4.4.1_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react-native-screens: 3.18.2_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react-native-svg: 13.6.0_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react-native-reanimated: 2.14.4_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react-native-safe-area-context: 4.5.0_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react-native-screens: 3.19.0_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react-native-svg: 13.8.0_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react-native-wheel-color-picker: 1.2.0
|
||||
twrnc: 3.6.0_react-native@0.70.5
|
||||
use-count-up: 3.0.1_react@18.1.0
|
||||
use-debounce: 9.0.3_react@18.1.0
|
||||
valtio: 1.9.0_react@18.1.0
|
||||
devDependencies:
|
||||
'@rnx-kit/metro-config': 1.3.3_tj3nonr5gneraukzjkxpsiy7yu
|
||||
'@rnx-kit/metro-config': 1.3.5_tj3nonr5gneraukzjkxpsiy7yu
|
||||
'@sd/config': link:../../packages/config
|
||||
'@types/react': 18.0.27
|
||||
'@types/react-native': 0.70.9
|
||||
babel-plugin-module-resolver: 4.1.0
|
||||
babel-plugin-module-resolver: 5.0.0
|
||||
eslint-plugin-react-native: 4.0.0
|
||||
metro-minify-terser: 0.73.7
|
||||
react-native-svg-transformer: 1.0.0_t622mrclk7o6j6mwz34ema6fve
|
||||
metro-minify-terser: 0.74.1
|
||||
react-native-svg-transformer: 1.0.0_kqpsw65h73u7hvgblav6crprhi
|
||||
typescript: 4.9.4
|
||||
|
||||
apps/server:
|
||||
|
@ -735,6 +735,15 @@ packages:
|
|||
source-map: 0.5.7
|
||||
dev: true
|
||||
|
||||
/@babel/generator/7.20.14:
|
||||
resolution: {integrity: sha512-AEmuXHdcD3A52HHXxaTmYlb8q/xMEhoRP67B3T4Oq7lbmSoqroMZzjnGj3+i1io3pdnF8iBYVu4Ilj+c4hBxYg==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/types': 7.20.7
|
||||
'@jridgewell/gen-mapping': 0.3.2
|
||||
jsesc: 2.5.2
|
||||
dev: true
|
||||
|
||||
/@babel/generator/7.20.7:
|
||||
resolution: {integrity: sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
@ -1072,6 +1081,14 @@ packages:
|
|||
'@babel/types': 7.17.0
|
||||
dev: true
|
||||
|
||||
/@babel/parser/7.20.13:
|
||||
resolution: {integrity: sha512-gFDLKMfpiXCsjt4za2JA9oTMn70CeseCehb11kRZgvd7+F67Hih3OHOK24cRrWECJ/ljfPGac6ygXAs/C8kIvw==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
'@babel/types': 7.20.7
|
||||
dev: true
|
||||
|
||||
/@babel/parser/7.20.7:
|
||||
resolution: {integrity: sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
|
@ -1372,7 +1389,7 @@ packages:
|
|||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.12.9
|
||||
'@babel/helper-plugin-utils': 7.10.4
|
||||
'@babel/helper-plugin-utils': 7.20.2
|
||||
'@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.12.9
|
||||
'@babel/plugin-transform-parameters': 7.20.7_@babel+core@7.12.9
|
||||
dev: true
|
||||
|
@ -2612,8 +2629,8 @@ packages:
|
|||
'@babel/helper-plugin-utils': 7.20.2
|
||||
dev: true
|
||||
|
||||
/@babel/plugin-transform-typescript/7.20.7:
|
||||
resolution: {integrity: sha512-m3wVKEvf6SoszD8pu4NZz3PvfKRCMgk6D6d0Qi9hNnlM5M6CFS92EgF4EiHVLKbU0r/r7ty1hg7NPZwE7WRbYw==}
|
||||
/@babel/plugin-transform-typescript/7.20.13:
|
||||
resolution: {integrity: sha512-O7I/THxarGcDZxkgWKMUrk7NK1/WbHAg3Xx86gqS6x9MTrNL6AwIluuZ96ms4xeDe6AVx6rjHbWHP7x26EPQBA==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.0.0-0
|
||||
|
@ -2625,6 +2642,19 @@ packages:
|
|||
- supports-color
|
||||
dev: false
|
||||
|
||||
/@babel/plugin-transform-typescript/7.20.13_@babel+core@7.20.12:
|
||||
resolution: {integrity: sha512-O7I/THxarGcDZxkgWKMUrk7NK1/WbHAg3Xx86gqS6x9MTrNL6AwIluuZ96ms4xeDe6AVx6rjHbWHP7x26EPQBA==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.20.12
|
||||
'@babel/helper-create-class-features-plugin': 7.20.12_@babel+core@7.20.12
|
||||
'@babel/helper-plugin-utils': 7.20.2
|
||||
'@babel/plugin-syntax-typescript': 7.20.0_@babel+core@7.20.12
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
/@babel/plugin-transform-typescript/7.20.7_@babel+core@7.20.12:
|
||||
resolution: {integrity: sha512-m3wVKEvf6SoszD8pu4NZz3PvfKRCMgk6D6d0Qi9hNnlM5M6CFS92EgF4EiHVLKbU0r/r7ty1hg7NPZwE7WRbYw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
@ -2907,7 +2937,7 @@ packages:
|
|||
dependencies:
|
||||
'@babel/helper-plugin-utils': 7.20.2
|
||||
'@babel/helper-validator-option': 7.18.6
|
||||
'@babel/plugin-transform-typescript': 7.20.7
|
||||
'@babel/plugin-transform-typescript': 7.20.13
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
@ -2921,7 +2951,7 @@ packages:
|
|||
'@babel/core': 7.20.12
|
||||
'@babel/helper-plugin-utils': 7.20.2
|
||||
'@babel/helper-validator-option': 7.18.6
|
||||
'@babel/plugin-transform-typescript': 7.20.7_@babel+core@7.20.12
|
||||
'@babel/plugin-transform-typescript': 7.20.13_@babel+core@7.20.12
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
|
@ -2999,6 +3029,24 @@ packages:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
/@babel/traverse/7.20.13:
|
||||
resolution: {integrity: sha512-kMJXfF0T6DIS9E8cgdLCSAL+cuCK+YEZHWiLK0SXpTo8YRj5lpJu3CDNKiIBCne4m9hhTIqUg6SYTAI39tAiVQ==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.18.6
|
||||
'@babel/generator': 7.20.14
|
||||
'@babel/helper-environment-visitor': 7.18.9
|
||||
'@babel/helper-function-name': 7.19.0
|
||||
'@babel/helper-hoist-variables': 7.18.6
|
||||
'@babel/helper-split-export-declaration': 7.18.6
|
||||
'@babel/parser': 7.20.13
|
||||
'@babel/types': 7.20.7
|
||||
debug: 4.3.4
|
||||
globals: 11.12.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@babel/types/7.17.0:
|
||||
resolution: {integrity: sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
@ -3997,7 +4045,7 @@ packages:
|
|||
/@gar/promisify/1.1.3:
|
||||
resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==}
|
||||
|
||||
/@gorhom/bottom-sheet/4.4.5_cuwuttpow3vlkihawr5ojezmtm:
|
||||
/@gorhom/bottom-sheet/4.4.5_w366bumyfs4uyicayprrehskae:
|
||||
resolution: {integrity: sha512-Z5Z20wshLUB8lIdtMKoJaRnjd64wBR/q8EeVPThrg+skrcBwBPHfUwZJ2srB0rEszA/01ejSJy/ixyd7Ra7vUA==}
|
||||
peerDependencies:
|
||||
react: '*'
|
||||
|
@ -4009,8 +4057,8 @@ packages:
|
|||
invariant: 2.2.4
|
||||
react: 18.1.0
|
||||
react-native: 0.70.5_react@18.1.0
|
||||
react-native-gesture-handler: 2.8.0_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react-native-reanimated: 2.13.0_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react-native-gesture-handler: 2.9.0_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react-native-reanimated: 2.14.4_tj3nonr5gneraukzjkxpsiy7yu
|
||||
dev: false
|
||||
|
||||
/@gorhom/portal/1.0.14_tj3nonr5gneraukzjkxpsiy7yu:
|
||||
|
@ -5363,8 +5411,8 @@ packages:
|
|||
/@react-native/polyfills/2.0.0:
|
||||
resolution: {integrity: sha512-K0aGNn1TjalKj+65D7ycc1//H9roAQ51GJVk5ZJQFb2teECGmzd86bYDC0aYdbRf7gtovescq4Zt6FR0tgXiHQ==}
|
||||
|
||||
/@react-navigation/bottom-tabs/6.5.3_4yxn5o6hbqm4eqjpnbll7jojyu:
|
||||
resolution: {integrity: sha512-ZA2Ko9fNwNaaSNn7738KpEk8Doi+yjRfTg8Wb/WvduIaK/28qNLAYWBCUEVjBC55y/9zJOzwc4R8Av2J2MG/4g==}
|
||||
/@react-navigation/bottom-tabs/6.5.4_tzhjy2gc5kvqqitykreeetpfsq:
|
||||
resolution: {integrity: sha512-C2Tf+SsO9zc+p/MKUkILso8Dw4KTIscXPi7YhdepyZbM8ZYMGfnZKzffGjLFlLhQXtsFQQuHMelD8sIStTkgyQ==}
|
||||
peerDependencies:
|
||||
'@react-navigation/native': ^6.0.0
|
||||
react: '*'
|
||||
|
@ -5372,13 +5420,13 @@ packages:
|
|||
react-native-safe-area-context: '>= 3.0.0'
|
||||
react-native-screens: '>= 3.0.0'
|
||||
dependencies:
|
||||
'@react-navigation/elements': 1.3.13_7faqyzkwzhg3btbxjjkwqxstpy
|
||||
'@react-navigation/native': 6.1.2_tj3nonr5gneraukzjkxpsiy7yu
|
||||
'@react-navigation/elements': 1.3.14_tyo4vetelyebz5cucognw6udfm
|
||||
'@react-navigation/native': 6.1.3_tj3nonr5gneraukzjkxpsiy7yu
|
||||
color: 4.2.3
|
||||
react: 18.1.0
|
||||
react-native: 0.70.5_react@18.1.0
|
||||
react-native-safe-area-context: 4.4.1_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react-native-screens: 3.18.2_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react-native-safe-area-context: 4.5.0_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react-native-screens: 3.19.0_tj3nonr5gneraukzjkxpsiy7yu
|
||||
warn-once: 0.1.1
|
||||
dev: false
|
||||
|
||||
|
@ -5396,8 +5444,8 @@ packages:
|
|||
use-latest-callback: 0.1.5
|
||||
dev: false
|
||||
|
||||
/@react-navigation/drawer/6.5.7_yrgdxcwem6xwiw4ihiusk6rm7m:
|
||||
resolution: {integrity: sha512-k8l+G05WrP+Il8USxEcaBtZ2Jv/JFn9dS8O1IlqIoddZITrFjsyDhk3zxeE3RWDcc9u0o7HgHfgKHPXxcT8QRQ==}
|
||||
/@react-navigation/drawer/6.5.8_5pbm2y6oxn4wiaxvhnj4nykkku:
|
||||
resolution: {integrity: sha512-24okwc1gVJex+NMwau1QfxIRUDfFvdbnwFS/N0bCUXDVu8bqsMeYA00C3xwCpvdRmANbBH4rFRniNbJLAvD4Jg==}
|
||||
peerDependencies:
|
||||
'@react-navigation/native': ^6.0.0
|
||||
react: '*'
|
||||
|
@ -5407,34 +5455,34 @@ packages:
|
|||
react-native-safe-area-context: '>= 3.0.0'
|
||||
react-native-screens: '>= 3.0.0'
|
||||
dependencies:
|
||||
'@react-navigation/elements': 1.3.13_7faqyzkwzhg3btbxjjkwqxstpy
|
||||
'@react-navigation/native': 6.1.2_tj3nonr5gneraukzjkxpsiy7yu
|
||||
'@react-navigation/elements': 1.3.14_tyo4vetelyebz5cucognw6udfm
|
||||
'@react-navigation/native': 6.1.3_tj3nonr5gneraukzjkxpsiy7yu
|
||||
color: 4.2.3
|
||||
react: 18.1.0
|
||||
react-native: 0.70.5_react@18.1.0
|
||||
react-native-gesture-handler: 2.8.0_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react-native-reanimated: 2.13.0_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react-native-safe-area-context: 4.4.1_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react-native-screens: 3.18.2_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react-native-gesture-handler: 2.9.0_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react-native-reanimated: 2.14.4_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react-native-safe-area-context: 4.5.0_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react-native-screens: 3.19.0_tj3nonr5gneraukzjkxpsiy7yu
|
||||
warn-once: 0.1.1
|
||||
dev: false
|
||||
|
||||
/@react-navigation/elements/1.3.13_7faqyzkwzhg3btbxjjkwqxstpy:
|
||||
resolution: {integrity: sha512-LqqK5s2ZfYHn2cQ376jC5V9dQztLH5ixkkJj9WR7JY2g4SghDd39WJhL3Jillw1Mu3F3b9sZwvAK+QkXhnDeAA==}
|
||||
/@react-navigation/elements/1.3.14_tyo4vetelyebz5cucognw6udfm:
|
||||
resolution: {integrity: sha512-RBbPhYq+KNFPAkWPaHB9gypq0jTGp/0fkMwRLToJ8jkLtWG4LV+JoQ/erFQnVARkR3Q807n0VnES15EYP4ITMQ==}
|
||||
peerDependencies:
|
||||
'@react-navigation/native': ^6.0.0
|
||||
react: '*'
|
||||
react-native: '*'
|
||||
react-native-safe-area-context: '>= 3.0.0'
|
||||
dependencies:
|
||||
'@react-navigation/native': 6.1.2_tj3nonr5gneraukzjkxpsiy7yu
|
||||
'@react-navigation/native': 6.1.3_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react: 18.1.0
|
||||
react-native: 0.70.5_react@18.1.0
|
||||
react-native-safe-area-context: 4.4.1_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react-native-safe-area-context: 4.5.0_tj3nonr5gneraukzjkxpsiy7yu
|
||||
dev: false
|
||||
|
||||
/@react-navigation/native/6.1.2_tj3nonr5gneraukzjkxpsiy7yu:
|
||||
resolution: {integrity: sha512-qLUe0asHofr5EhxKjvUBJ9DrPPmR4535IEwmW3oU4DRb3cLbNysjajJKHL8kcYtqPvn9Bx9QZG2x0PMb2vN23A==}
|
||||
/@react-navigation/native/6.1.3_tj3nonr5gneraukzjkxpsiy7yu:
|
||||
resolution: {integrity: sha512-DB5FyG6aqGfcjjVozljF5NEkjWaSymIbQHfWwsjL0YrvC1gfc7E53QXDOjxZ/wfbCo8qZs8RIC/LAgclP2YK/w==}
|
||||
peerDependencies:
|
||||
react: '*'
|
||||
react-native: '*'
|
||||
|
@ -5453,8 +5501,8 @@ packages:
|
|||
nanoid: 3.3.4
|
||||
dev: false
|
||||
|
||||
/@react-navigation/stack/6.3.11_omkqc3xm6hu7gsihfbjfmuohle:
|
||||
resolution: {integrity: sha512-GWOAyJfPEsjVwDWec1ERwWL5LvManJucCRUZetJqCBs4/mV7HXEt2x6l3SMitHxH1+K+9XuYXI+wBTbK1WDYOA==}
|
||||
/@react-navigation/stack/6.3.12_tvuqzzu4d6qsmbauwbo7nuei7e:
|
||||
resolution: {integrity: sha512-sDclO/EflZUbfxZZlz5fk3A0wfegeCOEKGznP9n53s+JrDJL2Dc24Gufg56ENLNRX3CiE1KzsaM4SQLJYf/zsA==}
|
||||
peerDependencies:
|
||||
'@react-navigation/native': ^6.0.0
|
||||
react: '*'
|
||||
|
@ -5463,14 +5511,14 @@ packages:
|
|||
react-native-safe-area-context: '>= 3.0.0'
|
||||
react-native-screens: '>= 3.0.0'
|
||||
dependencies:
|
||||
'@react-navigation/elements': 1.3.13_7faqyzkwzhg3btbxjjkwqxstpy
|
||||
'@react-navigation/native': 6.1.2_tj3nonr5gneraukzjkxpsiy7yu
|
||||
'@react-navigation/elements': 1.3.14_tyo4vetelyebz5cucognw6udfm
|
||||
'@react-navigation/native': 6.1.3_tj3nonr5gneraukzjkxpsiy7yu
|
||||
color: 4.2.3
|
||||
react: 18.1.0
|
||||
react-native: 0.70.5_react@18.1.0
|
||||
react-native-gesture-handler: 2.8.0_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react-native-safe-area-context: 4.4.1_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react-native-screens: 3.18.2_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react-native-gesture-handler: 2.9.0_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react-native-safe-area-context: 4.5.0_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react-native-screens: 3.19.0_tj3nonr5gneraukzjkxpsiy7yu
|
||||
warn-once: 0.1.1
|
||||
dev: false
|
||||
|
||||
|
@ -5590,9 +5638,10 @@ packages:
|
|||
engines: {node: '>=14'}
|
||||
dev: false
|
||||
|
||||
/@rnx-kit/babel-preset-metro-react-native/1.1.3:
|
||||
resolution: {integrity: sha512-D5ifPbKKDkpQfumu7iELo1HNaRxy38yGx7rys50ulENAIytCrtOOLwkxdpSKDa+rAXsKoqlcEBCpszdAI3fZxQ==}
|
||||
/@rnx-kit/babel-preset-metro-react-native/1.1.4:
|
||||
resolution: {integrity: sha512-ev82sa8Q5Z4a7kQ9pfCKYvpPpPesn0bgOFX8mNx5Gb3uZENb1i1oqySsmw1Qrrf/1KCMi4DKXOI7KezUl8Kf4g==}
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.0.0
|
||||
'@babel/plugin-transform-typescript': ^7.0.0
|
||||
metro-react-native-babel-preset: '*'
|
||||
peerDependenciesMeta:
|
||||
|
@ -5601,7 +5650,6 @@ packages:
|
|||
dependencies:
|
||||
babel-plugin-const-enum: 1.2.0
|
||||
transitivePeerDependencies:
|
||||
- '@babel/core'
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
|
@ -5611,14 +5659,15 @@ packages:
|
|||
chalk: 4.1.2
|
||||
dev: true
|
||||
|
||||
/@rnx-kit/metro-config/1.3.3_tj3nonr5gneraukzjkxpsiy7yu:
|
||||
resolution: {integrity: sha512-s6UXYbGNRGzoOfkwiPYlBFnMJyAGmac1gNnIgdO+7XVyX/gein/IzD/lhGvg8H3H7vKSl0R1N2mX6bNzAlpGcw==}
|
||||
/@rnx-kit/metro-config/1.3.5_tj3nonr5gneraukzjkxpsiy7yu:
|
||||
resolution: {integrity: sha512-8KI7sIaj1ExpH2Et37CXwy+ajdqRqXloGbHYSE4RYvda+PSJ/guU9+moY5NXaRujJtwOFA8qk3/nDvx2suMDeA==}
|
||||
peerDependencies:
|
||||
metro-config: '>=0.58.0'
|
||||
metro-react-native-babel-preset: '*'
|
||||
react: '*'
|
||||
react-native: '*'
|
||||
dependencies:
|
||||
'@rnx-kit/babel-preset-metro-react-native': 1.1.3
|
||||
'@rnx-kit/babel-preset-metro-react-native': 1.1.4
|
||||
'@rnx-kit/console': 1.0.11
|
||||
'@rnx-kit/tools-node': 1.3.1
|
||||
'@rnx-kit/tools-workspaces': 0.1.3
|
||||
|
@ -5627,7 +5676,6 @@ packages:
|
|||
transitivePeerDependencies:
|
||||
- '@babel/core'
|
||||
- '@babel/plugin-transform-typescript'
|
||||
- metro-react-native-babel-preset
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
|
@ -5679,14 +5727,14 @@ packages:
|
|||
/@rspc/client/0.0.0-main-7c0a67c1:
|
||||
resolution: {integrity: sha512-PpFkqhp8KlfdFSa8f/Ff5nOg8jhHNq12q8p0ZLYU/1K68JVPQRIk432zpXg48QT/MQbMrogx/PF5E7refhEtvw==}
|
||||
|
||||
/@rspc/react/0.0.0-main-7c0a67c1_7aie4jek34mpa466duyggl5x24:
|
||||
/@rspc/react/0.0.0-main-7c0a67c1_6niuqkvdadibsmemv5phcmgdcq:
|
||||
resolution: {integrity: sha512-SpsYJ+k/wXUCBDwVuu0WYOVRnrYzQaXyjHGIy/bSVphtYkMhJuZ3UlP2/YxMX4hj4wlDpsTZECzvez5D1vX+pw==}
|
||||
peerDependencies:
|
||||
'@tanstack/react-query': ^4.8.0
|
||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||
dependencies:
|
||||
'@rspc/client': 0.0.0-main-7c0a67c1
|
||||
'@tanstack/react-query': 4.22.0_tj3nonr5gneraukzjkxpsiy7yu
|
||||
'@tanstack/react-query': 4.24.4_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react: 18.1.0
|
||||
dev: false
|
||||
|
||||
|
@ -5769,8 +5817,8 @@ packages:
|
|||
tslib: 1.14.1
|
||||
dev: false
|
||||
|
||||
/@shopify/flash-list/1.4.0_tj3nonr5gneraukzjkxpsiy7yu:
|
||||
resolution: {integrity: sha512-PvPOyk353LuETFnNA038+QaJsAFlCQ2TYC7DHP3YnYqTX72g2BM6qLoLsPaptXKuoXX+dinOo0MbEm7HDjTy1g==}
|
||||
/@shopify/flash-list/1.4.1_tj3nonr5gneraukzjkxpsiy7yu:
|
||||
resolution: {integrity: sha512-yM5dlhqolO/R8FKomqCrSYz0Cc82vJDikxhbu1CXXGp3rPvo/ceP9jJyKueW96SXHsn/87fcSq2BjztWjlp74Q==}
|
||||
peerDependencies:
|
||||
'@babel/runtime': '*'
|
||||
react: '*'
|
||||
|
@ -7539,6 +7587,10 @@ packages:
|
|||
/@tanstack/query-core/4.22.0:
|
||||
resolution: {integrity: sha512-OeLyBKBQoT265f5G9biReijeP8mBxNFwY7ZUu1dKL+YzqpG5q5z7J/N1eT8aWyKuhyDTiUHuKm5l+oIVzbtrjw==}
|
||||
|
||||
/@tanstack/query-core/4.24.4:
|
||||
resolution: {integrity: sha512-9dqjv9eeB6VHN7lD3cLo16ZAjfjCsdXetSAD5+VyKqLUvcKTL0CklGQRJu+bWzdrS69R6Ea4UZo8obHYZnG6aA==}
|
||||
dev: false
|
||||
|
||||
/@tanstack/react-query-devtools/4.22.0_gp275tdwez2a4eujt75dnnp754:
|
||||
resolution: {integrity: sha512-YeYFBnfqvb+ZlA0IiJqiHNNSzepNhI1p2o9i8NlhQli9+Zrn230M47OBaBUs8qr3DD1dC2zGB1Dis50Ktz8gAA==}
|
||||
peerDependencies:
|
||||
|
@ -7587,8 +7639,8 @@ packages:
|
|||
react-dom: 18.2.0_react@18.2.0
|
||||
use-sync-external-store: 1.2.0_react@18.2.0
|
||||
|
||||
/@tanstack/react-query/4.22.0_tj3nonr5gneraukzjkxpsiy7yu:
|
||||
resolution: {integrity: sha512-P9o+HjG42uB/xHR6dMsJaPhtZydSe4v0xdG5G/cEj1oHZAXelMlm67/rYJNQGKgBamKElKogj+HYGF+NY2yHYg==}
|
||||
/@tanstack/react-query/4.24.4_tj3nonr5gneraukzjkxpsiy7yu:
|
||||
resolution: {integrity: sha512-RpaS/3T/a3pHuZJbIAzAYRu+1nkp+/enr9hfRXDS/mojwx567UiMksoqW4wUFWlwIvWTXyhot2nbIipTKEg55Q==}
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||
|
@ -7599,7 +7651,7 @@ packages:
|
|||
react-native:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@tanstack/query-core': 4.22.0
|
||||
'@tanstack/query-core': 4.24.4
|
||||
react: 18.1.0
|
||||
react-native: 0.70.5_react@18.1.0
|
||||
use-sync-external-store: 1.2.0_react@18.1.0
|
||||
|
@ -7940,10 +7992,6 @@ packages:
|
|||
resolution: {integrity: sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==}
|
||||
dev: true
|
||||
|
||||
/@types/invariant/2.2.35:
|
||||
resolution: {integrity: sha512-DxX1V9P8zdJPYQat1gHyY0xj3efl8gnMVjiM9iCY6y27lj+PoQWkgjt8jDqmovPqULkKVpKRg8J36iQiA+EtEg==}
|
||||
dev: false
|
||||
|
||||
/@types/is-function/1.0.1:
|
||||
resolution: {integrity: sha512-A79HEEiwXTFtfY+Bcbo58M2GRYzCr9itHWzbzHVFNEYCcoU/MMGwYYf721gBrnhpj1s6RGVVha/IgNFnR0Iw/Q==}
|
||||
dev: true
|
||||
|
@ -9311,7 +9359,7 @@ packages:
|
|||
dependencies:
|
||||
'@babel/helper-plugin-utils': 7.20.2
|
||||
'@babel/plugin-syntax-typescript': 7.20.0
|
||||
'@babel/traverse': 7.20.12
|
||||
'@babel/traverse': 7.20.13
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
@ -9353,6 +9401,18 @@ packages:
|
|||
pkg-up: 3.1.0
|
||||
reselect: 4.1.7
|
||||
resolve: 1.22.1
|
||||
dev: false
|
||||
|
||||
/babel-plugin-module-resolver/5.0.0:
|
||||
resolution: {integrity: sha512-g0u+/ChLSJ5+PzYwLwP8Rp8Rcfowz58TJNCe+L/ui4rpzE/mg//JVX0EWBUYoxaextqnwuGHzfGp2hh0PPV25Q==}
|
||||
engines: {node: '>= 16'}
|
||||
dependencies:
|
||||
find-babel-config: 2.0.0
|
||||
glob: 8.1.0
|
||||
pkg-up: 3.1.0
|
||||
reselect: 4.1.7
|
||||
resolve: 1.22.1
|
||||
dev: true
|
||||
|
||||
/babel-plugin-named-exports-order/0.0.2:
|
||||
resolution: {integrity: sha512-OgOYHOLoRK+/mvXU9imKHlG6GkPLYrUCvFXG/CM93R/aNNO8pOOF4aS+S8CCHMDQoNSeiOYEZb/G6RwL95Jktw==}
|
||||
|
@ -12457,6 +12517,15 @@ packages:
|
|||
dependencies:
|
||||
json5: 0.5.1
|
||||
path-exists: 3.0.0
|
||||
dev: false
|
||||
|
||||
/find-babel-config/2.0.0:
|
||||
resolution: {integrity: sha512-dOKT7jvF3hGzlW60Gc3ONox/0rRZ/tz7WCil0bqA1In/3I8f1BctpXahRnEKDySZqci7u+dqq93sZST9fOJpFw==}
|
||||
engines: {node: '>=16.0.0'}
|
||||
dependencies:
|
||||
json5: 2.2.3
|
||||
path-exists: 4.0.0
|
||||
dev: true
|
||||
|
||||
/find-cache-dir/2.1.0:
|
||||
resolution: {integrity: sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==}
|
||||
|
@ -13043,6 +13112,17 @@ packages:
|
|||
once: 1.4.0
|
||||
path-is-absolute: 1.0.1
|
||||
|
||||
/glob/8.1.0:
|
||||
resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==}
|
||||
engines: {node: '>=12'}
|
||||
dependencies:
|
||||
fs.realpath: 1.0.0
|
||||
inflight: 1.0.6
|
||||
inherits: 2.0.4
|
||||
minimatch: 5.1.6
|
||||
once: 1.4.0
|
||||
dev: true
|
||||
|
||||
/global-dirs/0.1.1:
|
||||
resolution: {integrity: sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==}
|
||||
engines: {node: '>=4'}
|
||||
|
@ -14522,6 +14602,7 @@ packages:
|
|||
/json5/0.5.1:
|
||||
resolution: {integrity: sha512-4xrs1aW+6N5DalkqSVA8fxh458CXvR99WU8WLKmq4v8eWAL86Xo3BVqyd3SkA9wEVjCMqyvvRRkshAdOnBp5rw==}
|
||||
hasBin: true
|
||||
dev: false
|
||||
|
||||
/json5/1.0.2:
|
||||
resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==}
|
||||
|
@ -15250,8 +15331,8 @@ packages:
|
|||
- supports-color
|
||||
- utf-8-validate
|
||||
|
||||
/metro-minify-terser/0.73.7:
|
||||
resolution: {integrity: sha512-gbv1fmMOZm6gJ6dQoD+QktlCi2wk6nlTR8j8lQCjeeXGbs6O9e5XLWNPOexHqo7S69bdbohEnfZnLJFcxgHeNw==}
|
||||
/metro-minify-terser/0.74.1:
|
||||
resolution: {integrity: sha512-R8l2KbYm1ct9benFSXBjeBDJ48BIyyQo3ECG0TSDX5efLSAS9z0scOCTUC9mcAJ9CO1tjc9ZrjHMNWAOoHO6XA==}
|
||||
dependencies:
|
||||
terser: 5.16.1
|
||||
dev: true
|
||||
|
@ -15644,13 +15725,13 @@ packages:
|
|||
engines: {node: '>=10'}
|
||||
hasBin: true
|
||||
|
||||
/moti/0.21.0_xxoigs3lrtexqhfttsykzq4gba:
|
||||
resolution: {integrity: sha512-b4UJux4sbHeTDWLU7IfJ1ct3p2N/v6fabQTjeXTXrBcna/Ha3QFJ5TKq3F7hOGeHzt5b8vLanfLdPbJRC/v3jg==}
|
||||
/moti/0.22.0_wwrhtnmkhk6ixblrbdwhxojxqi:
|
||||
resolution: {integrity: sha512-KK3fhK8igrqE+mqac4JGajvpwM9WX2QCVn1HmwgXrzUC2dA6jyA2sybmV9Fke0Ahe7/dITKXRZNcd73OTqxdOA==}
|
||||
peerDependencies:
|
||||
react-native-reanimated: '*'
|
||||
dependencies:
|
||||
framer-motion: 6.5.1_react@18.1.0
|
||||
react-native-reanimated: 2.13.0_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react-native-reanimated: 2.14.4_tj3nonr5gneraukzjkxpsiy7yu
|
||||
transitivePeerDependencies:
|
||||
- react
|
||||
- react-dom
|
||||
|
@ -16509,7 +16590,7 @@ packages:
|
|||
resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==}
|
||||
dev: false
|
||||
|
||||
/phosphor-react-native/1.1.2_6rmyt7g6mjmjm44v4kwwqzmzjy:
|
||||
/phosphor-react-native/1.1.2_tdhmirddlb52bzkqlwgrsfpe6m:
|
||||
resolution: {integrity: sha512-uWYDG4S70JP89jmXljCA0K6/0mjQDHH8GVHFwF+dmbdYkALIE84jMMSemkFtjdsazB1j+xDBJcGaKN3PdEC8uQ==}
|
||||
peerDependencies:
|
||||
react: '*'
|
||||
|
@ -16519,7 +16600,7 @@ packages:
|
|||
caniuse-lite: 1.0.30001446
|
||||
react: 18.1.0
|
||||
react-native: 0.70.5_react@18.1.0
|
||||
react-native-svg: 13.6.0_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react-native-svg: 13.8.0_tj3nonr5gneraukzjkxpsiy7yu
|
||||
dev: false
|
||||
|
||||
/phosphor-react/1.4.1_react@18.2.0:
|
||||
|
@ -17395,15 +17476,6 @@ packages:
|
|||
react-side-effect: 2.1.2_react@18.2.0
|
||||
dev: false
|
||||
|
||||
/react-hook-form/7.42.1_react@18.1.0:
|
||||
resolution: {integrity: sha512-2UIGqwMZksd5HS55crTT1ATLTr0rAI4jS7yVuqTaoRVDhY2Qc4IyjskCmpnmdYqUNOYFy04vW253tb2JRVh+IQ==}
|
||||
engines: {node: '>=12.22.0'}
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17 || ^18
|
||||
dependencies:
|
||||
react: 18.1.0
|
||||
dev: false
|
||||
|
||||
/react-hook-form/7.42.1_react@18.2.0:
|
||||
resolution: {integrity: sha512-2UIGqwMZksd5HS55crTT1ATLTr0rAI4jS7yVuqTaoRVDhY2Qc4IyjskCmpnmdYqUNOYFy04vW253tb2JRVh+IQ==}
|
||||
engines: {node: '>=12.22.0'}
|
||||
|
@ -17413,6 +17485,15 @@ packages:
|
|||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/react-hook-form/7.43.0_react@18.1.0:
|
||||
resolution: {integrity: sha512-/rVEz7T0gLdSFwPqutJ1kn2e0sQNyb9ci/hmwEYr2YG0KF/LSuRLvNrf9QWJM+gj88CjDpDW5Bh/1AD7B2+z9Q==}
|
||||
engines: {node: '>=12.22.0'}
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17 || ^18
|
||||
dependencies:
|
||||
react: 18.1.0
|
||||
dev: false
|
||||
|
||||
/react-inspector/5.1.1_react@18.2.0:
|
||||
resolution: {integrity: sha512-GURDaYzoLbW8pMGXwYPDBIv6nqei4kK7LPRZ9q9HCZF54wqXz/dnylBp/kfE9XmekBhHvLDdcYeyIwSrvtOiWg==}
|
||||
peerDependencies:
|
||||
|
@ -17514,8 +17595,8 @@ packages:
|
|||
utf8: 3.0.0
|
||||
dev: false
|
||||
|
||||
/react-native-gesture-handler/2.8.0_tj3nonr5gneraukzjkxpsiy7yu:
|
||||
resolution: {integrity: sha512-poOSfz/w0IyD6Qwq7aaIRRfEaVTl1ecQFoyiIbpOpfNTjm2B1niY2FLrdVQIOtIOe+K9nH55Qal04nr4jGkHdQ==}
|
||||
/react-native-gesture-handler/2.9.0_tj3nonr5gneraukzjkxpsiy7yu:
|
||||
resolution: {integrity: sha512-a0BcH3Qb1tgVqUutc6d3VuWQkI1AM3+fJx8dkxzZs9t06qA27QgURYFoklpabuWpsUTzuKRpxleykp25E8m7tg==}
|
||||
peerDependencies:
|
||||
react: '*'
|
||||
react-native: '*'
|
||||
|
@ -17536,8 +17617,8 @@ packages:
|
|||
resolution: {integrity: sha512-xRS7mRh0exwu7Iw8PPVHdM11d13A/KzYjy0/fZx3zVtxISxPkNaDGayau6oa7HqO3Nj0oS9ulFCYjcQfG6vahA==}
|
||||
dev: false
|
||||
|
||||
/react-native-reanimated/2.13.0_tj3nonr5gneraukzjkxpsiy7yu:
|
||||
resolution: {integrity: sha512-yUHyYVIegWWIza4+nVyS3CSmI/Mc8kLFVHw2c6gnSHaYhYA4LeEjH/jBkoMzHk9Xd0Ra3cwtjYKAMG8OTp6JVg==}
|
||||
/react-native-reanimated/2.14.4_tj3nonr5gneraukzjkxpsiy7yu:
|
||||
resolution: {integrity: sha512-DquSbl7P8j4SAmc+kRdd75Ianm8G+IYQ9T4AQ6lrpLVeDkhZmjWI0wkutKWnp6L7c5XNVUrFDUf69dwETLCItQ==}
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.0.0-0
|
||||
react: '*'
|
||||
|
@ -17545,7 +17626,7 @@ packages:
|
|||
dependencies:
|
||||
'@babel/plugin-transform-object-assign': 7.18.6
|
||||
'@babel/preset-typescript': 7.18.6
|
||||
'@types/invariant': 2.2.35
|
||||
convert-source-map: 1.9.0
|
||||
invariant: 2.2.4
|
||||
lodash.isequal: 4.5.0
|
||||
react: 18.1.0
|
||||
|
@ -17556,8 +17637,8 @@ packages:
|
|||
- supports-color
|
||||
dev: false
|
||||
|
||||
/react-native-safe-area-context/4.4.1_tj3nonr5gneraukzjkxpsiy7yu:
|
||||
resolution: {integrity: sha512-N9XTjiuD73ZpVlejHrUWIFZc+6Z14co1K/p1IFMkImU7+avD69F3y+lhkqA2hN/+vljdZrBSiOwXPkuo43nFQA==}
|
||||
/react-native-safe-area-context/4.5.0_tj3nonr5gneraukzjkxpsiy7yu:
|
||||
resolution: {integrity: sha512-0WORnk9SkREGUg2V7jHZbuN5x4vcxj/1B0QOcXJjdYWrzZHgLcUzYWWIUecUPJh747Mwjt/42RZDOaFn3L8kPQ==}
|
||||
peerDependencies:
|
||||
react: '*'
|
||||
react-native: '*'
|
||||
|
@ -17575,8 +17656,8 @@ packages:
|
|||
react-native: 0.70.5_react@18.1.0
|
||||
dev: false
|
||||
|
||||
/react-native-screens/3.18.2_tj3nonr5gneraukzjkxpsiy7yu:
|
||||
resolution: {integrity: sha512-ANUEuvMUlsYJ1QKukEhzhfrvOUO9BVH9Nzg+6eWxpn3cfD/O83yPBOF8Mx6x5H/2+sMy+VS5x/chWOOo/U7QJw==}
|
||||
/react-native-screens/3.19.0_tj3nonr5gneraukzjkxpsiy7yu:
|
||||
resolution: {integrity: sha512-Ehsmy7jr3H3j5pmN+/FqsAaIAD+k+xkcdePfLcg4rYRbN5X7fJPgaqhcmiCcZ0YxsU8ttsstP9IvRLNQuIkRRA==}
|
||||
peerDependencies:
|
||||
react: '*'
|
||||
react-native: '*'
|
||||
|
@ -17587,7 +17668,7 @@ packages:
|
|||
warn-once: 0.1.1
|
||||
dev: false
|
||||
|
||||
/react-native-svg-transformer/1.0.0_t622mrclk7o6j6mwz34ema6fve:
|
||||
/react-native-svg-transformer/1.0.0_kqpsw65h73u7hvgblav6crprhi:
|
||||
resolution: {integrity: sha512-ALHU5VvLLyKM/BvyEG7VYJmqglvaXtU7mGRCxrEwwpJO/GBf1ZMUzc4AeJAjSodj7yYtlDYRxNSt9ySWpaa6JQ==}
|
||||
peerDependencies:
|
||||
react-native: '>=0.59.0'
|
||||
|
@ -17597,13 +17678,13 @@ packages:
|
|||
'@svgr/plugin-svgo': 6.5.1_@svgr+core@6.5.1
|
||||
path-dirname: 1.0.2
|
||||
react-native: 0.70.5_react@18.1.0
|
||||
react-native-svg: 13.6.0_tj3nonr5gneraukzjkxpsiy7yu
|
||||
react-native-svg: 13.8.0_tj3nonr5gneraukzjkxpsiy7yu
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/react-native-svg/13.6.0_tj3nonr5gneraukzjkxpsiy7yu:
|
||||
resolution: {integrity: sha512-1wjHCMJ8siyZbDZ0MX5wM+Jr7YOkb6GADn4/Z+/u1UwJX8WfjarypxDF3UO1ugMHa+7qor39oY+URMcrgPpiww==}
|
||||
/react-native-svg/13.8.0_tj3nonr5gneraukzjkxpsiy7yu:
|
||||
resolution: {integrity: sha512-G8Mx6W86da+vFimZBJvA93POw8yz0fgDS5biy6oIjMWVJVQSDzCyzwO/zY0yuZmCDhKSZzogl5m0wXXvW2OcTA==}
|
||||
peerDependencies:
|
||||
react: '*'
|
||||
react-native: '*'
|
||||
|
@ -19598,7 +19679,7 @@ packages:
|
|||
hasBin: true
|
||||
dependencies:
|
||||
'@jridgewell/source-map': 0.3.2
|
||||
acorn: 8.8.1
|
||||
acorn: 8.8.2
|
||||
commander: 2.20.3
|
||||
source-map-support: 0.5.21
|
||||
dev: true
|
||||
|
|
Loading…
Reference in a new issue