mirror of
https://github.com/spacedriveapp/spacedrive
synced 2024-07-04 12:13:27 +00:00
Mobile - Settings & Tags (#479)
* Sync tailwind configs * Switch to new colors part 1 * new colors part 2 * switched to new colors * settings screens template * settings progress * Setting header titles * Refactor settings icon * Fix tsconfig relative path issue * Move mobile eslint config to @sd/config * Add no-restricted-imports rule to eslint * rename TextInput to Input & tailwind font sizing * General Settings screen + Card component * Library settings screen & delete lib dialog * autoform hook * Mini tweaks and new packages * Exclude android & ios from search * Add Switch (Input) * Library General settings screen * Refactor settings + Switch and Switch Container * Locations screen & delete and rescan locations * Rename folder + small tweaks * Make things Swipeable * Create Tag Dialog with color picker * Upgrade to Expo 47 * More tag stuff * fix pnpm lock * regen pnpm-lock * Change CI node version to 16 * Move `isVideo` into shared package Co-authored-by: Oscar Beaumont <oscar@otbeaumont.me>
This commit is contained in:
parent
78a5754f4e
commit
42f09b0918
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
|
@ -28,7 +28,7 @@ jobs:
|
||||||
- name: Install Node.js
|
- name: Install Node.js
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 17
|
node-version: 16
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
||||||
- name: Install pnpm dependencies
|
- name: Install pnpm dependencies
|
||||||
|
@ -80,7 +80,7 @@ jobs:
|
||||||
- name: Install Node.js
|
- name: Install Node.js
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 17
|
node-version: 16
|
||||||
|
|
||||||
- name: Install pnpm
|
- name: Install pnpm
|
||||||
uses: pnpm/action-setup@v2.0.1
|
uses: pnpm/action-setup@v2.0.1
|
||||||
|
@ -138,7 +138,7 @@ jobs:
|
||||||
- name: Install Node.js
|
- name: Install Node.js
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 17
|
node-version: 16
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
||||||
- name: Install pnpm dependencies
|
- name: Install pnpm dependencies
|
||||||
|
|
17
.vscode/settings.json
vendored
17
.vscode/settings.json
vendored
|
@ -37,9 +37,18 @@
|
||||||
"rust-analyzer.procMacro.enable": true,
|
"rust-analyzer.procMacro.enable": true,
|
||||||
"rust-analyzer.diagnostics.experimental.enable": false,
|
"rust-analyzer.diagnostics.experimental.enable": false,
|
||||||
"tailwindCSS.experimental.classRegex": [
|
"tailwindCSS.experimental.classRegex": [
|
||||||
["cva\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"],
|
["cva\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"],
|
||||||
"tw`([^`]*)",
|
"tw`([^`]*)",
|
||||||
"tw\\.[^`]+`([^`]*)`",
|
"tw\\.[^`]+`([^`]*)`",
|
||||||
"tw\\(.*?\\).*?`([^`]*)"
|
"tw\\(.*?\\).*?`([^`]*)",
|
||||||
],
|
"tw\\.style\\(([^)]*)\\)"
|
||||||
|
],
|
||||||
|
"search.exclude": {
|
||||||
|
"**/node_modules": true,
|
||||||
|
"**/bower_components": true,
|
||||||
|
"**/*.code-search": true,
|
||||||
|
// Hiding these folders bcs they create a lot of noise in the search results
|
||||||
|
"apps/mobile/android": true,
|
||||||
|
"apps/mobile/ios": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,42 +1,7 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
env: {
|
...require('@sd/config/eslint-react-native.js'),
|
||||||
'react-native/react-native': true
|
|
||||||
},
|
|
||||||
parser: '@typescript-eslint/parser',
|
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
ecmaFeatures: {
|
tsconfigRootDir: __dirname,
|
||||||
jsx: true
|
project: './tsconfig.json'
|
||||||
},
|
|
||||||
ecmaVersion: 12,
|
|
||||||
sourceType: 'module'
|
|
||||||
},
|
|
||||||
extends: [
|
|
||||||
'eslint:recommended',
|
|
||||||
'plugin:react/recommended',
|
|
||||||
'plugin:react-hooks/recommended',
|
|
||||||
'plugin:@typescript-eslint/recommended'
|
|
||||||
],
|
|
||||||
plugins: ['react', 'react-native'],
|
|
||||||
rules: {
|
|
||||||
'react/display-name': 'off',
|
|
||||||
'react/prop-types': 'off',
|
|
||||||
'react/no-unescaped-entities': 'off',
|
|
||||||
'react/react-in-jsx-scope': 'off',
|
|
||||||
'react-hooks/rules-of-hooks': 'error',
|
|
||||||
'react-hooks/exhaustive-deps': 'warn',
|
|
||||||
'@typescript-eslint/no-unused-vars': 'off',
|
|
||||||
'@typescript-eslint/ban-ts-comment': 'off',
|
|
||||||
'@typescript-eslint/no-explicit-any': 'off',
|
|
||||||
'@typescript-eslint/no-var-requires': 'off',
|
|
||||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
|
||||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
|
||||||
'no-control-regex': 'off',
|
|
||||||
'no-mixed-spaces-and-tabs': ['warn', 'smart-tabs']
|
|
||||||
},
|
|
||||||
ignorePatterns: ['**/*.js', '**/*.json', 'node_modules', 'android', 'ios', '.expo'],
|
|
||||||
settings: {
|
|
||||||
react: {
|
|
||||||
version: 'detect'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,3 +1,2 @@
|
||||||
Make sure to run `pnpm i` in this folder after making changes to the `packages`.
|
- Make sure to run `pnpm i` if you make any change to the `package` mobile uses like `assets`.
|
||||||
|
- If iOS build fails with `node not found` error, run `echo "export NODE_BINARY=$(command -v node)" >> .xcode.env.local` on `mobile/ios/` directory.
|
||||||
- Note: If you add/remove something from `packages/assets` folder, you need to delete node_modules and run `pnpm i` again to link it.
|
|
||||||
|
|
|
@ -36,6 +36,17 @@ target 'Spacedrive' do
|
||||||
post_install do |installer|
|
post_install do |installer|
|
||||||
react_native_post_install(installer)
|
react_native_post_install(installer)
|
||||||
__apply_Xcode_12_5_M1_post_install_workaround(installer)
|
__apply_Xcode_12_5_M1_post_install_workaround(installer)
|
||||||
|
|
||||||
|
# This is necessary for Xcode 14, because it signs resource bundles by default
|
||||||
|
# when building for devices.
|
||||||
|
installer.target_installation_results.pod_target_installation_results
|
||||||
|
.each do |pod_name, target_installation_result|
|
||||||
|
target_installation_result.resource_bundle_targets.each do |resource_bundle_target|
|
||||||
|
resource_bundle_target.build_configurations.each do |config|
|
||||||
|
config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
post_integrate do |installer|
|
post_integrate do |installer|
|
||||||
|
|
|
@ -1,343 +1,343 @@
|
||||||
PODS:
|
PODS:
|
||||||
- boost (1.76.0)
|
- boost (1.76.0)
|
||||||
- DoubleConversion (1.1.6)
|
- DoubleConversion (1.1.6)
|
||||||
- EXApplication (4.2.2):
|
- EXApplication (5.0.1):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- EXConstants (13.2.4):
|
- EXConstants (14.0.2):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- EXFileSystem (14.1.0):
|
- EXFileSystem (15.1.1):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- EXFont (10.2.1):
|
- EXFont (11.0.1):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- EXMediaLibrary (14.2.0):
|
- EXMediaLibrary (15.0.0):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- React-Core
|
- React-Core
|
||||||
- Expo (46.0.16):
|
- Expo (47.0.8):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- ExpoKeepAwake (10.2.0):
|
- ExpoKeepAwake (11.0.1):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- ExpoModulesCore (0.11.8):
|
- ExpoModulesCore (1.0.3):
|
||||||
- React-Core
|
- React-Core
|
||||||
- ReactCommon/turbomodule/core
|
- ReactCommon/turbomodule/core
|
||||||
- EXSplashScreen (0.16.2):
|
- EXSplashScreen (0.17.5):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- React-Core
|
- React-Core
|
||||||
- FBLazyVector (0.69.6)
|
- FBLazyVector (0.70.5)
|
||||||
- FBReactNativeSpec (0.69.6):
|
- FBReactNativeSpec (0.70.5):
|
||||||
- RCT-Folly (= 2021.06.28.00-v2)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- RCTRequired (= 0.69.6)
|
- RCTRequired (= 0.70.5)
|
||||||
- RCTTypeSafety (= 0.69.6)
|
- RCTTypeSafety (= 0.70.5)
|
||||||
- React-Core (= 0.69.6)
|
- React-Core (= 0.70.5)
|
||||||
- React-jsi (= 0.69.6)
|
- React-jsi (= 0.70.5)
|
||||||
- ReactCommon/turbomodule/core (= 0.69.6)
|
- ReactCommon/turbomodule/core (= 0.70.5)
|
||||||
- fmt (6.2.1)
|
- fmt (6.2.1)
|
||||||
- glog (0.3.5)
|
- glog (0.3.5)
|
||||||
- hermes-engine (0.69.6)
|
- hermes-engine (0.70.5)
|
||||||
- libevent (2.1.12)
|
- libevent (2.1.12)
|
||||||
- lottie-ios (3.4.4)
|
- lottie-ios (3.4.4)
|
||||||
- lottie-react-native (5.1.4):
|
- lottie-react-native (5.1.4):
|
||||||
- lottie-ios (~> 3.4.0)
|
- lottie-ios (~> 3.4.0)
|
||||||
- React-Core
|
- React-Core
|
||||||
- RCT-Folly (2021.06.28.00-v2):
|
- RCT-Folly (2021.07.22.00):
|
||||||
- boost
|
- boost
|
||||||
- DoubleConversion
|
- DoubleConversion
|
||||||
- fmt (~> 6.2.1)
|
- fmt (~> 6.2.1)
|
||||||
- glog
|
- glog
|
||||||
- RCT-Folly/Default (= 2021.06.28.00-v2)
|
- RCT-Folly/Default (= 2021.07.22.00)
|
||||||
- RCT-Folly/Default (2021.06.28.00-v2):
|
- RCT-Folly/Default (2021.07.22.00):
|
||||||
- boost
|
- boost
|
||||||
- DoubleConversion
|
- DoubleConversion
|
||||||
- fmt (~> 6.2.1)
|
- fmt (~> 6.2.1)
|
||||||
- glog
|
- glog
|
||||||
- RCT-Folly/Futures (2021.06.28.00-v2):
|
- RCT-Folly/Futures (2021.07.22.00):
|
||||||
- boost
|
- boost
|
||||||
- DoubleConversion
|
- DoubleConversion
|
||||||
- fmt (~> 6.2.1)
|
- fmt (~> 6.2.1)
|
||||||
- glog
|
- glog
|
||||||
- libevent
|
- libevent
|
||||||
- RCTRequired (0.69.6)
|
- RCTRequired (0.70.5)
|
||||||
- RCTTypeSafety (0.69.6):
|
- RCTTypeSafety (0.70.5):
|
||||||
- FBLazyVector (= 0.69.6)
|
- FBLazyVector (= 0.70.5)
|
||||||
- RCTRequired (= 0.69.6)
|
- RCTRequired (= 0.70.5)
|
||||||
- React-Core (= 0.69.6)
|
- React-Core (= 0.70.5)
|
||||||
- React (0.69.6):
|
- React (0.70.5):
|
||||||
- React-Core (= 0.69.6)
|
- React-Core (= 0.70.5)
|
||||||
- React-Core/DevSupport (= 0.69.6)
|
- React-Core/DevSupport (= 0.70.5)
|
||||||
- React-Core/RCTWebSocket (= 0.69.6)
|
- React-Core/RCTWebSocket (= 0.70.5)
|
||||||
- React-RCTActionSheet (= 0.69.6)
|
- React-RCTActionSheet (= 0.70.5)
|
||||||
- React-RCTAnimation (= 0.69.6)
|
- React-RCTAnimation (= 0.70.5)
|
||||||
- React-RCTBlob (= 0.69.6)
|
- React-RCTBlob (= 0.70.5)
|
||||||
- React-RCTImage (= 0.69.6)
|
- React-RCTImage (= 0.70.5)
|
||||||
- React-RCTLinking (= 0.69.6)
|
- React-RCTLinking (= 0.70.5)
|
||||||
- React-RCTNetwork (= 0.69.6)
|
- React-RCTNetwork (= 0.70.5)
|
||||||
- React-RCTSettings (= 0.69.6)
|
- React-RCTSettings (= 0.70.5)
|
||||||
- React-RCTText (= 0.69.6)
|
- React-RCTText (= 0.70.5)
|
||||||
- React-RCTVibration (= 0.69.6)
|
- React-RCTVibration (= 0.70.5)
|
||||||
- React-bridging (0.69.6):
|
- React-bridging (0.70.5):
|
||||||
- RCT-Folly (= 2021.06.28.00-v2)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-jsi (= 0.69.6)
|
- React-jsi (= 0.70.5)
|
||||||
- React-callinvoker (0.69.6)
|
- React-callinvoker (0.70.5)
|
||||||
- React-Codegen (0.69.6):
|
- React-Codegen (0.70.5):
|
||||||
- FBReactNativeSpec (= 0.69.6)
|
- FBReactNativeSpec (= 0.70.5)
|
||||||
- RCT-Folly (= 2021.06.28.00-v2)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- RCTRequired (= 0.69.6)
|
- RCTRequired (= 0.70.5)
|
||||||
- RCTTypeSafety (= 0.69.6)
|
- RCTTypeSafety (= 0.70.5)
|
||||||
- React-Core (= 0.69.6)
|
- React-Core (= 0.70.5)
|
||||||
- React-jsi (= 0.69.6)
|
- React-jsi (= 0.70.5)
|
||||||
- React-jsiexecutor (= 0.69.6)
|
- React-jsiexecutor (= 0.70.5)
|
||||||
- ReactCommon/turbomodule/core (= 0.69.6)
|
- ReactCommon/turbomodule/core (= 0.70.5)
|
||||||
- React-Core (0.69.6):
|
- React-Core (0.70.5):
|
||||||
- glog
|
- glog
|
||||||
- RCT-Folly (= 2021.06.28.00-v2)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Core/Default (= 0.69.6)
|
- React-Core/Default (= 0.70.5)
|
||||||
- React-cxxreact (= 0.69.6)
|
- React-cxxreact (= 0.70.5)
|
||||||
- React-jsi (= 0.69.6)
|
- React-jsi (= 0.70.5)
|
||||||
- React-jsiexecutor (= 0.69.6)
|
- React-jsiexecutor (= 0.70.5)
|
||||||
- React-perflogger (= 0.69.6)
|
- React-perflogger (= 0.70.5)
|
||||||
- Yoga
|
- Yoga
|
||||||
- React-Core/CoreModulesHeaders (0.69.6):
|
- React-Core/CoreModulesHeaders (0.70.5):
|
||||||
- glog
|
- glog
|
||||||
- RCT-Folly (= 2021.06.28.00-v2)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Core/Default
|
- React-Core/Default
|
||||||
- React-cxxreact (= 0.69.6)
|
- React-cxxreact (= 0.70.5)
|
||||||
- React-jsi (= 0.69.6)
|
- React-jsi (= 0.70.5)
|
||||||
- React-jsiexecutor (= 0.69.6)
|
- React-jsiexecutor (= 0.70.5)
|
||||||
- React-perflogger (= 0.69.6)
|
- React-perflogger (= 0.70.5)
|
||||||
- Yoga
|
- Yoga
|
||||||
- React-Core/Default (0.69.6):
|
- React-Core/Default (0.70.5):
|
||||||
- glog
|
- glog
|
||||||
- RCT-Folly (= 2021.06.28.00-v2)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-cxxreact (= 0.69.6)
|
- React-cxxreact (= 0.70.5)
|
||||||
- React-jsi (= 0.69.6)
|
- React-jsi (= 0.70.5)
|
||||||
- React-jsiexecutor (= 0.69.6)
|
- React-jsiexecutor (= 0.70.5)
|
||||||
- React-perflogger (= 0.69.6)
|
- React-perflogger (= 0.70.5)
|
||||||
- Yoga
|
- Yoga
|
||||||
- React-Core/DevSupport (0.69.6):
|
- React-Core/DevSupport (0.70.5):
|
||||||
- glog
|
- glog
|
||||||
- RCT-Folly (= 2021.06.28.00-v2)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Core/Default (= 0.69.6)
|
- React-Core/Default (= 0.70.5)
|
||||||
- React-Core/RCTWebSocket (= 0.69.6)
|
- React-Core/RCTWebSocket (= 0.70.5)
|
||||||
- React-cxxreact (= 0.69.6)
|
- React-cxxreact (= 0.70.5)
|
||||||
- React-jsi (= 0.69.6)
|
- React-jsi (= 0.70.5)
|
||||||
- React-jsiexecutor (= 0.69.6)
|
- React-jsiexecutor (= 0.70.5)
|
||||||
- React-jsinspector (= 0.69.6)
|
- React-jsinspector (= 0.70.5)
|
||||||
- React-perflogger (= 0.69.6)
|
- React-perflogger (= 0.70.5)
|
||||||
- Yoga
|
- Yoga
|
||||||
- React-Core/RCTActionSheetHeaders (0.69.6):
|
- React-Core/RCTActionSheetHeaders (0.70.5):
|
||||||
- glog
|
- glog
|
||||||
- RCT-Folly (= 2021.06.28.00-v2)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Core/Default
|
- React-Core/Default
|
||||||
- React-cxxreact (= 0.69.6)
|
- React-cxxreact (= 0.70.5)
|
||||||
- React-jsi (= 0.69.6)
|
- React-jsi (= 0.70.5)
|
||||||
- React-jsiexecutor (= 0.69.6)
|
- React-jsiexecutor (= 0.70.5)
|
||||||
- React-perflogger (= 0.69.6)
|
- React-perflogger (= 0.70.5)
|
||||||
- Yoga
|
- Yoga
|
||||||
- React-Core/RCTAnimationHeaders (0.69.6):
|
- React-Core/RCTAnimationHeaders (0.70.5):
|
||||||
- glog
|
- glog
|
||||||
- RCT-Folly (= 2021.06.28.00-v2)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Core/Default
|
- React-Core/Default
|
||||||
- React-cxxreact (= 0.69.6)
|
- React-cxxreact (= 0.70.5)
|
||||||
- React-jsi (= 0.69.6)
|
- React-jsi (= 0.70.5)
|
||||||
- React-jsiexecutor (= 0.69.6)
|
- React-jsiexecutor (= 0.70.5)
|
||||||
- React-perflogger (= 0.69.6)
|
- React-perflogger (= 0.70.5)
|
||||||
- Yoga
|
- Yoga
|
||||||
- React-Core/RCTBlobHeaders (0.69.6):
|
- React-Core/RCTBlobHeaders (0.70.5):
|
||||||
- glog
|
- glog
|
||||||
- RCT-Folly (= 2021.06.28.00-v2)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Core/Default
|
- React-Core/Default
|
||||||
- React-cxxreact (= 0.69.6)
|
- React-cxxreact (= 0.70.5)
|
||||||
- React-jsi (= 0.69.6)
|
- React-jsi (= 0.70.5)
|
||||||
- React-jsiexecutor (= 0.69.6)
|
- React-jsiexecutor (= 0.70.5)
|
||||||
- React-perflogger (= 0.69.6)
|
- React-perflogger (= 0.70.5)
|
||||||
- Yoga
|
- Yoga
|
||||||
- React-Core/RCTImageHeaders (0.69.6):
|
- React-Core/RCTImageHeaders (0.70.5):
|
||||||
- glog
|
- glog
|
||||||
- RCT-Folly (= 2021.06.28.00-v2)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Core/Default
|
- React-Core/Default
|
||||||
- React-cxxreact (= 0.69.6)
|
- React-cxxreact (= 0.70.5)
|
||||||
- React-jsi (= 0.69.6)
|
- React-jsi (= 0.70.5)
|
||||||
- React-jsiexecutor (= 0.69.6)
|
- React-jsiexecutor (= 0.70.5)
|
||||||
- React-perflogger (= 0.69.6)
|
- React-perflogger (= 0.70.5)
|
||||||
- Yoga
|
- Yoga
|
||||||
- React-Core/RCTLinkingHeaders (0.69.6):
|
- React-Core/RCTLinkingHeaders (0.70.5):
|
||||||
- glog
|
- glog
|
||||||
- RCT-Folly (= 2021.06.28.00-v2)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Core/Default
|
- React-Core/Default
|
||||||
- React-cxxreact (= 0.69.6)
|
- React-cxxreact (= 0.70.5)
|
||||||
- React-jsi (= 0.69.6)
|
- React-jsi (= 0.70.5)
|
||||||
- React-jsiexecutor (= 0.69.6)
|
- React-jsiexecutor (= 0.70.5)
|
||||||
- React-perflogger (= 0.69.6)
|
- React-perflogger (= 0.70.5)
|
||||||
- Yoga
|
- Yoga
|
||||||
- React-Core/RCTNetworkHeaders (0.69.6):
|
- React-Core/RCTNetworkHeaders (0.70.5):
|
||||||
- glog
|
- glog
|
||||||
- RCT-Folly (= 2021.06.28.00-v2)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Core/Default
|
- React-Core/Default
|
||||||
- React-cxxreact (= 0.69.6)
|
- React-cxxreact (= 0.70.5)
|
||||||
- React-jsi (= 0.69.6)
|
- React-jsi (= 0.70.5)
|
||||||
- React-jsiexecutor (= 0.69.6)
|
- React-jsiexecutor (= 0.70.5)
|
||||||
- React-perflogger (= 0.69.6)
|
- React-perflogger (= 0.70.5)
|
||||||
- Yoga
|
- Yoga
|
||||||
- React-Core/RCTSettingsHeaders (0.69.6):
|
- React-Core/RCTSettingsHeaders (0.70.5):
|
||||||
- glog
|
- glog
|
||||||
- RCT-Folly (= 2021.06.28.00-v2)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Core/Default
|
- React-Core/Default
|
||||||
- React-cxxreact (= 0.69.6)
|
- React-cxxreact (= 0.70.5)
|
||||||
- React-jsi (= 0.69.6)
|
- React-jsi (= 0.70.5)
|
||||||
- React-jsiexecutor (= 0.69.6)
|
- React-jsiexecutor (= 0.70.5)
|
||||||
- React-perflogger (= 0.69.6)
|
- React-perflogger (= 0.70.5)
|
||||||
- Yoga
|
- Yoga
|
||||||
- React-Core/RCTTextHeaders (0.69.6):
|
- React-Core/RCTTextHeaders (0.70.5):
|
||||||
- glog
|
- glog
|
||||||
- RCT-Folly (= 2021.06.28.00-v2)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Core/Default
|
- React-Core/Default
|
||||||
- React-cxxreact (= 0.69.6)
|
- React-cxxreact (= 0.70.5)
|
||||||
- React-jsi (= 0.69.6)
|
- React-jsi (= 0.70.5)
|
||||||
- React-jsiexecutor (= 0.69.6)
|
- React-jsiexecutor (= 0.70.5)
|
||||||
- React-perflogger (= 0.69.6)
|
- React-perflogger (= 0.70.5)
|
||||||
- Yoga
|
- Yoga
|
||||||
- React-Core/RCTVibrationHeaders (0.69.6):
|
- React-Core/RCTVibrationHeaders (0.70.5):
|
||||||
- glog
|
- glog
|
||||||
- RCT-Folly (= 2021.06.28.00-v2)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Core/Default
|
- React-Core/Default
|
||||||
- React-cxxreact (= 0.69.6)
|
- React-cxxreact (= 0.70.5)
|
||||||
- React-jsi (= 0.69.6)
|
- React-jsi (= 0.70.5)
|
||||||
- React-jsiexecutor (= 0.69.6)
|
- React-jsiexecutor (= 0.70.5)
|
||||||
- React-perflogger (= 0.69.6)
|
- React-perflogger (= 0.70.5)
|
||||||
- Yoga
|
- Yoga
|
||||||
- React-Core/RCTWebSocket (0.69.6):
|
- React-Core/RCTWebSocket (0.70.5):
|
||||||
- glog
|
- glog
|
||||||
- RCT-Folly (= 2021.06.28.00-v2)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Core/Default (= 0.69.6)
|
- React-Core/Default (= 0.70.5)
|
||||||
- React-cxxreact (= 0.69.6)
|
- React-cxxreact (= 0.70.5)
|
||||||
- React-jsi (= 0.69.6)
|
- React-jsi (= 0.70.5)
|
||||||
- React-jsiexecutor (= 0.69.6)
|
- React-jsiexecutor (= 0.70.5)
|
||||||
- React-perflogger (= 0.69.6)
|
- React-perflogger (= 0.70.5)
|
||||||
- Yoga
|
- Yoga
|
||||||
- React-CoreModules (0.69.6):
|
- React-CoreModules (0.70.5):
|
||||||
- RCT-Folly (= 2021.06.28.00-v2)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- RCTTypeSafety (= 0.69.6)
|
- RCTTypeSafety (= 0.70.5)
|
||||||
- React-Codegen (= 0.69.6)
|
- React-Codegen (= 0.70.5)
|
||||||
- React-Core/CoreModulesHeaders (= 0.69.6)
|
- React-Core/CoreModulesHeaders (= 0.70.5)
|
||||||
- React-jsi (= 0.69.6)
|
- React-jsi (= 0.70.5)
|
||||||
- React-RCTImage (= 0.69.6)
|
- React-RCTImage (= 0.70.5)
|
||||||
- ReactCommon/turbomodule/core (= 0.69.6)
|
- ReactCommon/turbomodule/core (= 0.70.5)
|
||||||
- React-cxxreact (0.69.6):
|
- React-cxxreact (0.70.5):
|
||||||
- boost (= 1.76.0)
|
- boost (= 1.76.0)
|
||||||
- DoubleConversion
|
- DoubleConversion
|
||||||
- glog
|
- glog
|
||||||
- RCT-Folly (= 2021.06.28.00-v2)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-callinvoker (= 0.69.6)
|
- React-callinvoker (= 0.70.5)
|
||||||
- React-jsi (= 0.69.6)
|
- React-jsi (= 0.70.5)
|
||||||
- React-jsinspector (= 0.69.6)
|
- React-jsinspector (= 0.70.5)
|
||||||
- React-logger (= 0.69.6)
|
- React-logger (= 0.70.5)
|
||||||
- React-perflogger (= 0.69.6)
|
- React-perflogger (= 0.70.5)
|
||||||
- React-runtimeexecutor (= 0.69.6)
|
- React-runtimeexecutor (= 0.70.5)
|
||||||
- React-hermes (0.69.6):
|
- React-hermes (0.70.5):
|
||||||
- DoubleConversion
|
- DoubleConversion
|
||||||
- glog
|
- glog
|
||||||
- hermes-engine
|
- hermes-engine
|
||||||
- RCT-Folly (= 2021.06.28.00-v2)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- RCT-Folly/Futures (= 2021.06.28.00-v2)
|
- RCT-Folly/Futures (= 2021.07.22.00)
|
||||||
- React-cxxreact (= 0.69.6)
|
- React-cxxreact (= 0.70.5)
|
||||||
- React-jsi (= 0.69.6)
|
- React-jsi (= 0.70.5)
|
||||||
- React-jsiexecutor (= 0.69.6)
|
- React-jsiexecutor (= 0.70.5)
|
||||||
- React-jsinspector (= 0.69.6)
|
- React-jsinspector (= 0.70.5)
|
||||||
- React-perflogger (= 0.69.6)
|
- React-perflogger (= 0.70.5)
|
||||||
- React-jsi (0.69.6):
|
- React-jsi (0.70.5):
|
||||||
- boost (= 1.76.0)
|
- boost (= 1.76.0)
|
||||||
- DoubleConversion
|
- DoubleConversion
|
||||||
- glog
|
- glog
|
||||||
- RCT-Folly (= 2021.06.28.00-v2)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-jsi/Default (= 0.69.6)
|
- React-jsi/Default (= 0.70.5)
|
||||||
- React-jsi/Default (0.69.6):
|
- React-jsi/Default (0.70.5):
|
||||||
- boost (= 1.76.0)
|
- boost (= 1.76.0)
|
||||||
- DoubleConversion
|
- DoubleConversion
|
||||||
- glog
|
- glog
|
||||||
- RCT-Folly (= 2021.06.28.00-v2)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-jsiexecutor (0.69.6):
|
- React-jsiexecutor (0.70.5):
|
||||||
- DoubleConversion
|
- DoubleConversion
|
||||||
- glog
|
- glog
|
||||||
- RCT-Folly (= 2021.06.28.00-v2)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-cxxreact (= 0.69.6)
|
- React-cxxreact (= 0.70.5)
|
||||||
- React-jsi (= 0.69.6)
|
- React-jsi (= 0.70.5)
|
||||||
- React-perflogger (= 0.69.6)
|
- React-perflogger (= 0.70.5)
|
||||||
- React-jsinspector (0.69.6)
|
- React-jsinspector (0.70.5)
|
||||||
- React-logger (0.69.6):
|
- React-logger (0.70.5):
|
||||||
- glog
|
- glog
|
||||||
- react-native-document-picker (8.1.2):
|
- react-native-document-picker (8.1.2):
|
||||||
- React-Core
|
- React-Core
|
||||||
- react-native-safe-area-context (4.3.1):
|
- react-native-safe-area-context (4.4.1):
|
||||||
- RCT-Folly
|
- RCT-Folly
|
||||||
- RCTRequired
|
- RCTRequired
|
||||||
- RCTTypeSafety
|
- RCTTypeSafety
|
||||||
- React
|
- React-Core
|
||||||
- ReactCommon/turbomodule/core
|
- ReactCommon/turbomodule/core
|
||||||
- React-perflogger (0.69.6)
|
- React-perflogger (0.70.5)
|
||||||
- React-RCTActionSheet (0.69.6):
|
- React-RCTActionSheet (0.70.5):
|
||||||
- React-Core/RCTActionSheetHeaders (= 0.69.6)
|
- React-Core/RCTActionSheetHeaders (= 0.70.5)
|
||||||
- React-RCTAnimation (0.69.6):
|
- React-RCTAnimation (0.70.5):
|
||||||
- RCT-Folly (= 2021.06.28.00-v2)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- RCTTypeSafety (= 0.69.6)
|
- RCTTypeSafety (= 0.70.5)
|
||||||
- React-Codegen (= 0.69.6)
|
- React-Codegen (= 0.70.5)
|
||||||
- React-Core/RCTAnimationHeaders (= 0.69.6)
|
- React-Core/RCTAnimationHeaders (= 0.70.5)
|
||||||
- React-jsi (= 0.69.6)
|
- React-jsi (= 0.70.5)
|
||||||
- ReactCommon/turbomodule/core (= 0.69.6)
|
- ReactCommon/turbomodule/core (= 0.70.5)
|
||||||
- React-RCTBlob (0.69.6):
|
- React-RCTBlob (0.70.5):
|
||||||
- RCT-Folly (= 2021.06.28.00-v2)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Codegen (= 0.69.6)
|
- React-Codegen (= 0.70.5)
|
||||||
- React-Core/RCTBlobHeaders (= 0.69.6)
|
- React-Core/RCTBlobHeaders (= 0.70.5)
|
||||||
- React-Core/RCTWebSocket (= 0.69.6)
|
- React-Core/RCTWebSocket (= 0.70.5)
|
||||||
- React-jsi (= 0.69.6)
|
- React-jsi (= 0.70.5)
|
||||||
- React-RCTNetwork (= 0.69.6)
|
- React-RCTNetwork (= 0.70.5)
|
||||||
- ReactCommon/turbomodule/core (= 0.69.6)
|
- ReactCommon/turbomodule/core (= 0.70.5)
|
||||||
- React-RCTImage (0.69.6):
|
- React-RCTImage (0.70.5):
|
||||||
- RCT-Folly (= 2021.06.28.00-v2)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- RCTTypeSafety (= 0.69.6)
|
- RCTTypeSafety (= 0.70.5)
|
||||||
- React-Codegen (= 0.69.6)
|
- React-Codegen (= 0.70.5)
|
||||||
- React-Core/RCTImageHeaders (= 0.69.6)
|
- React-Core/RCTImageHeaders (= 0.70.5)
|
||||||
- React-jsi (= 0.69.6)
|
- React-jsi (= 0.70.5)
|
||||||
- React-RCTNetwork (= 0.69.6)
|
- React-RCTNetwork (= 0.70.5)
|
||||||
- ReactCommon/turbomodule/core (= 0.69.6)
|
- ReactCommon/turbomodule/core (= 0.70.5)
|
||||||
- React-RCTLinking (0.69.6):
|
- React-RCTLinking (0.70.5):
|
||||||
- React-Codegen (= 0.69.6)
|
- React-Codegen (= 0.70.5)
|
||||||
- React-Core/RCTLinkingHeaders (= 0.69.6)
|
- React-Core/RCTLinkingHeaders (= 0.70.5)
|
||||||
- React-jsi (= 0.69.6)
|
- React-jsi (= 0.70.5)
|
||||||
- ReactCommon/turbomodule/core (= 0.69.6)
|
- ReactCommon/turbomodule/core (= 0.70.5)
|
||||||
- React-RCTNetwork (0.69.6):
|
- React-RCTNetwork (0.70.5):
|
||||||
- RCT-Folly (= 2021.06.28.00-v2)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- RCTTypeSafety (= 0.69.6)
|
- RCTTypeSafety (= 0.70.5)
|
||||||
- React-Codegen (= 0.69.6)
|
- React-Codegen (= 0.70.5)
|
||||||
- React-Core/RCTNetworkHeaders (= 0.69.6)
|
- React-Core/RCTNetworkHeaders (= 0.70.5)
|
||||||
- React-jsi (= 0.69.6)
|
- React-jsi (= 0.70.5)
|
||||||
- ReactCommon/turbomodule/core (= 0.69.6)
|
- ReactCommon/turbomodule/core (= 0.70.5)
|
||||||
- React-RCTSettings (0.69.6):
|
- React-RCTSettings (0.70.5):
|
||||||
- RCT-Folly (= 2021.06.28.00-v2)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- RCTTypeSafety (= 0.69.6)
|
- RCTTypeSafety (= 0.70.5)
|
||||||
- React-Codegen (= 0.69.6)
|
- React-Codegen (= 0.70.5)
|
||||||
- React-Core/RCTSettingsHeaders (= 0.69.6)
|
- React-Core/RCTSettingsHeaders (= 0.70.5)
|
||||||
- React-jsi (= 0.69.6)
|
- React-jsi (= 0.70.5)
|
||||||
- ReactCommon/turbomodule/core (= 0.69.6)
|
- ReactCommon/turbomodule/core (= 0.70.5)
|
||||||
- React-RCTText (0.69.6):
|
- React-RCTText (0.70.5):
|
||||||
- React-Core/RCTTextHeaders (= 0.69.6)
|
- React-Core/RCTTextHeaders (= 0.70.5)
|
||||||
- React-RCTVibration (0.69.6):
|
- React-RCTVibration (0.70.5):
|
||||||
- RCT-Folly (= 2021.06.28.00-v2)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Codegen (= 0.69.6)
|
- React-Codegen (= 0.70.5)
|
||||||
- React-Core/RCTVibrationHeaders (= 0.69.6)
|
- React-Core/RCTVibrationHeaders (= 0.70.5)
|
||||||
- React-jsi (= 0.69.6)
|
- React-jsi (= 0.70.5)
|
||||||
- ReactCommon/turbomodule/core (= 0.69.6)
|
- ReactCommon/turbomodule/core (= 0.70.5)
|
||||||
- React-runtimeexecutor (0.69.6):
|
- React-runtimeexecutor (0.70.5):
|
||||||
- React-jsi (= 0.69.6)
|
- React-jsi (= 0.70.5)
|
||||||
- ReactCommon/turbomodule/core (0.69.6):
|
- ReactCommon/turbomodule/core (0.70.5):
|
||||||
- DoubleConversion
|
- DoubleConversion
|
||||||
- glog
|
- glog
|
||||||
- RCT-Folly (= 2021.06.28.00-v2)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-bridging (= 0.69.6)
|
- React-bridging (= 0.70.5)
|
||||||
- React-callinvoker (= 0.69.6)
|
- React-callinvoker (= 0.70.5)
|
||||||
- React-Core (= 0.69.6)
|
- React-Core (= 0.70.5)
|
||||||
- React-cxxreact (= 0.69.6)
|
- React-cxxreact (= 0.70.5)
|
||||||
- React-jsi (= 0.69.6)
|
- React-jsi (= 0.70.5)
|
||||||
- React-logger (= 0.69.6)
|
- React-logger (= 0.70.5)
|
||||||
- React-perflogger (= 0.69.6)
|
- React-perflogger (= 0.70.5)
|
||||||
- RNCAsyncStorage (1.17.10):
|
- RNCAsyncStorage (1.17.10):
|
||||||
- React-Core
|
- React-Core
|
||||||
- RNCMaskedView (0.2.8):
|
- RNCMaskedView (0.2.8):
|
||||||
|
@ -346,9 +346,9 @@ PODS:
|
||||||
- React-Core
|
- React-Core
|
||||||
- RNFS (2.20.0):
|
- RNFS (2.20.0):
|
||||||
- React-Core
|
- React-Core
|
||||||
- RNGestureHandler (2.5.0):
|
- RNGestureHandler (2.8.0):
|
||||||
- React-Core
|
- React-Core
|
||||||
- RNReanimated (2.10.0):
|
- RNReanimated (2.12.0):
|
||||||
- DoubleConversion
|
- DoubleConversion
|
||||||
- FBLazyVector
|
- FBLazyVector
|
||||||
- FBReactNativeSpec
|
- FBReactNativeSpec
|
||||||
|
@ -375,10 +375,10 @@ PODS:
|
||||||
- React-RCTText
|
- React-RCTText
|
||||||
- ReactCommon/turbomodule/core
|
- ReactCommon/turbomodule/core
|
||||||
- Yoga
|
- Yoga
|
||||||
- RNScreens (3.15.0):
|
- RNScreens (3.18.2):
|
||||||
- React-Core
|
- React-Core
|
||||||
- React-RCTImage
|
- React-RCTImage
|
||||||
- RNSVG (13.0.0):
|
- RNSVG (13.4.0):
|
||||||
- React-Core
|
- React-Core
|
||||||
- Yoga (1.14.0)
|
- Yoga (1.14.0)
|
||||||
|
|
||||||
|
@ -392,7 +392,7 @@ DEPENDENCIES:
|
||||||
- EXMediaLibrary (from `../../../node_modules/expo-media-library/ios`)
|
- EXMediaLibrary (from `../../../node_modules/expo-media-library/ios`)
|
||||||
- Expo (from `../../../node_modules/expo`)
|
- Expo (from `../../../node_modules/expo`)
|
||||||
- ExpoKeepAwake (from `../../../node_modules/expo-keep-awake/ios`)
|
- ExpoKeepAwake (from `../../../node_modules/expo-keep-awake/ios`)
|
||||||
- ExpoModulesCore (from `../../../node_modules/expo-modules-core/ios`)
|
- ExpoModulesCore (from `../../../node_modules/expo-modules-core`)
|
||||||
- EXSplashScreen (from `../../../node_modules/expo-splash-screen/ios`)
|
- EXSplashScreen (from `../../../node_modules/expo-splash-screen/ios`)
|
||||||
- FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`)
|
- FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`)
|
||||||
- FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`)
|
- FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`)
|
||||||
|
@ -466,7 +466,7 @@ EXTERNAL SOURCES:
|
||||||
ExpoKeepAwake:
|
ExpoKeepAwake:
|
||||||
:path: "../../../node_modules/expo-keep-awake/ios"
|
:path: "../../../node_modules/expo-keep-awake/ios"
|
||||||
ExpoModulesCore:
|
ExpoModulesCore:
|
||||||
:path: "../../../node_modules/expo-modules-core/ios"
|
:path: "../../../node_modules/expo-modules-core"
|
||||||
EXSplashScreen:
|
EXSplashScreen:
|
||||||
:path: "../../../node_modules/expo-splash-screen/ios"
|
:path: "../../../node_modules/expo-splash-screen/ios"
|
||||||
FBLazyVector:
|
FBLazyVector:
|
||||||
|
@ -559,62 +559,62 @@ EXTERNAL SOURCES:
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
boost: a7c83b31436843459a1961bfd74b96033dc77234
|
boost: a7c83b31436843459a1961bfd74b96033dc77234
|
||||||
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
|
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
|
||||||
EXApplication: e418d737a036e788510f2c4ad6c10a7d54d18586
|
EXApplication: 034b1c40a8e9fe1bff76a1e511ee90dff64ad834
|
||||||
EXConstants: 7c44785d41d8e959d527d23d29444277a4d1ee73
|
EXConstants: 3c86653c422dd77e40d10cbbabb3025003977415
|
||||||
EXFileSystem: 927e0a8885aa9c49e50fc38eaba2c2389f2f1019
|
EXFileSystem: 60602b6eefa6873f97172c684b7537c9760b50d6
|
||||||
EXFont: 06df627203afcb8a3b3152ec06eb2f11f46f0cff
|
EXFont: 319606bfe48c33b5b5063fb0994afdc496befe80
|
||||||
EXMediaLibrary: e8c8a365701629b7b21dd29769b86e8320610f18
|
EXMediaLibrary: b1c4f78878e45f6a359aff3a059e1660c41b73ab
|
||||||
Expo: 7ac824960a6059d6c68e73f432c8e6bf6d92a0ef
|
Expo: 36b5f625d36728adbdd1934d4d57182f319ab832
|
||||||
ExpoKeepAwake: 0e8f18142e71bbf2c7f6aa66ebed249ba1420320
|
ExpoKeepAwake: 69b59d0a8d2b24de9f82759c39b3821fec030318
|
||||||
ExpoModulesCore: 39ec590ce622289c060183aba57f77b1e73b4e11
|
ExpoModulesCore: b5d21c8880afda6fb6ee95469f9ac2ec9b98e995
|
||||||
EXSplashScreen: 799bece80089219b2c989c1082d70f3b00995cda
|
EXSplashScreen: 3e989924f61a8dd07ee4ea584c6ba14be9b51949
|
||||||
FBLazyVector: 739d2f9719faecb463c7aa191591af31c8c94182
|
FBLazyVector: affa4ba1bfdaac110a789192f4d452b053a86624
|
||||||
FBReactNativeSpec: 957de82f66e31f2f14bbec34e37242282fdd26de
|
FBReactNativeSpec: fe8b5f1429cfe83a8d72dc8ed61dc7704cac8745
|
||||||
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
|
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
|
||||||
glog: 3d02b25ca00c2d456734d0bcff864cbc62f6ae1a
|
glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b
|
||||||
hermes-engine: c2c873a670bc435451449f918c2b3ab3c39255fc
|
hermes-engine: 7fe5fc6ef707b7fdcb161b63898ec500e285653d
|
||||||
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
|
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
|
||||||
lottie-ios: 8f97d3271e155c2d688875c29cd3c74908aef5f8
|
lottie-ios: 8f97d3271e155c2d688875c29cd3c74908aef5f8
|
||||||
lottie-react-native: b702fab740cdb952a8e2354713d3beda63ff97b0
|
lottie-react-native: b702fab740cdb952a8e2354713d3beda63ff97b0
|
||||||
RCT-Folly: b9d9fe1fc70114b751c076104e52f3b1b5e5a95a
|
RCT-Folly: 0080d0a6ebf2577475bda044aa59e2ca1f909cda
|
||||||
RCTRequired: c8c080849a3670601d5c7056023a2176067a69d8
|
RCTRequired: 21229f84411088e5d8538f21212de49e46cc83e2
|
||||||
RCTTypeSafety: 710aef40f5ae246bc5fff7e873855b17ed11c180
|
RCTTypeSafety: 62eed57a32924b09edaaf170a548d1fc96223086
|
||||||
React: b6bb382534be4de9d367ef3d04f92108c1768160
|
React: f0254ccddeeef1defe66c6b1bb9133a4f040792b
|
||||||
React-bridging: 0fca0337cef9305026814907dd29254a833a2db7
|
React-bridging: e46911666b7ec19538a620a221d6396cd293d687
|
||||||
React-callinvoker: 700e6eb96b5f7f2fdd96d7263cd4627d2fa080ed
|
React-callinvoker: 66b62e2c34546546b2f21ab0b7670346410a2b53
|
||||||
React-Codegen: fd21633c4b9f47d0681bbb54b173a203963a5e4d
|
React-Codegen: b6999435966df3bdf82afa3f319ba0d6f9a8532a
|
||||||
React-Core: 8ec15c9727c8c01b1e4f14cad5bd21f7c1d56d49
|
React-Core: dabbc9d1fe0a11d884e6ee1599789cf8eb1058a5
|
||||||
React-CoreModules: 79486447bf901292a83df52d4f7acbecda296723
|
React-CoreModules: 5b6b7668f156f73a56420df9ec68ca2ec8f2e818
|
||||||
React-cxxreact: 9022135650dd9960a60a1361e9add424c6c37ab9
|
React-cxxreact: c7ca2baee46db22a30fce9e639277add3c3f6ad1
|
||||||
React-hermes: b5ce7fb460ff6d39e7bb9bbe1f523272c4b85c0b
|
React-hermes: c93e1d759ad5560dfea54d233013d7d2c725c286
|
||||||
React-jsi: 4ccb3599c422ad071e3895c5feab9b0afc40505d
|
React-jsi: a565dcb49130ed20877a9bb1105ffeecbb93d02d
|
||||||
React-jsiexecutor: c61b60de03b3474e5749b8a8fd8e6507630d62c4
|
React-jsiexecutor: 31564fa6912459921568e8b0e49024285a4d584b
|
||||||
React-jsinspector: eaacb698c5af7a99131bc1933806372c20222dfd
|
React-jsinspector: badd81696361249893a80477983e697aab3c1a34
|
||||||
React-logger: ebb4d31bbbe4f1a8a1a9b658d7429210b8f68160
|
React-logger: fdda34dd285bdb0232e059b19d9606fa0ec3bb9c
|
||||||
react-native-document-picker: f5ec1a712ca2a975c233117f044817bb8393cad4
|
react-native-document-picker: f5ec1a712ca2a975c233117f044817bb8393cad4
|
||||||
react-native-safe-area-context: 6c12e3859b6f27b25de4fee8201cfb858432d8de
|
react-native-safe-area-context: 99b24a0c5acd0d5dcac2b1a7f18c49ea317be99a
|
||||||
React-perflogger: 1fb1ad5333b43a5137afd7608695f7a42c5efd27
|
React-perflogger: e68d3795cf5d247a0379735cbac7309adf2fb931
|
||||||
React-RCTActionSheet: a435bd67689433575a1e5d7614b021d2c17f0726
|
React-RCTActionSheet: 05452c3b281edb27850253db13ecd4c5a65bc247
|
||||||
React-RCTAnimation: d097c5ed2d00735958508617555abd85183b94e2
|
React-RCTAnimation: 578eebac706428e68466118e84aeacf3a282b4da
|
||||||
React-RCTBlob: f43a0fceb328e1a40aa52701a4eba955635444ab
|
React-RCTBlob: f47a0aa61e7d1fb1a0e13da832b0da934939d71a
|
||||||
React-RCTImage: 08f4428e931efe0eefb94443c8ca08cfb250a556
|
React-RCTImage: 60f54b66eed65d86b6dffaf4733d09161d44929d
|
||||||
React-RCTLinking: 3a8851e818652582f87e5a7577302e6ad7e1de3e
|
React-RCTLinking: 91073205aeec4b29450ca79b709277319368ac9e
|
||||||
React-RCTNetwork: 19f7c66b612e2336eefdfbc7ab3a9bd8ca4e21cf
|
React-RCTNetwork: ca91f2c9465a7e335c8a5fae731fd7f10572213b
|
||||||
React-RCTSettings: 9324e718a865ff01e4a96be4c65923581b2d5170
|
React-RCTSettings: 1a9a5d01337d55c18168c1abe0f4a589167d134a
|
||||||
React-RCTText: 9cadcd5d982c1d25f7439f47354b1c1b75e60105
|
React-RCTText: c591e8bd9347a294d8416357ca12d779afec01d5
|
||||||
React-RCTVibration: 285f8538386c660e6b9497e204636acd93bf7fcc
|
React-RCTVibration: 8e5c8c5d17af641f306d7380d8d0fe9b3c142c48
|
||||||
React-runtimeexecutor: 0af71c94f968fa10015bf0119951bccd2e4d8865
|
React-runtimeexecutor: 7401c4a40f8728fd89df4a56104541b760876117
|
||||||
ReactCommon: fe7580b9d10f00249facf25659e0ec051320cc8a
|
ReactCommon: c9246996e73bf75a2c6c3ff15f1e16707cdc2da9
|
||||||
RNCAsyncStorage: 0c357f3156fcb16c8589ede67cc036330b6698ca
|
RNCAsyncStorage: 0c357f3156fcb16c8589ede67cc036330b6698ca
|
||||||
RNCMaskedView: bc0170f389056201c82a55e242e5d90070e18e5a
|
RNCMaskedView: bc0170f389056201c82a55e242e5d90070e18e5a
|
||||||
RNFlashList: 18d906a373da5ff16776e5013df9495d826edc7e
|
RNFlashList: 18d906a373da5ff16776e5013df9495d826edc7e
|
||||||
RNFS: 4ac0f0ea233904cb798630b3c077808c06931688
|
RNFS: 4ac0f0ea233904cb798630b3c077808c06931688
|
||||||
RNGestureHandler: bad495418bcbd3ab47017a38d93d290ebd406f50
|
RNGestureHandler: 62232ba8f562f7dea5ba1b3383494eb5bf97a4d3
|
||||||
RNReanimated: 7faa787e8d4493fbc95fab2ad331fa7625828cfa
|
RNReanimated: 2a91e85fcd343f8af3c58d3425b99fdd285590a5
|
||||||
RNScreens: 4a1af06327774490d97342c00aee0c2bafb497b7
|
RNScreens: 34cc502acf1b916c582c60003dc3089fa01dc66d
|
||||||
RNSVG: 42a0c731b11179ebbd27a3eeeafa7201ebb476ff
|
RNSVG: 07dbd870b0dcdecc99b3a202fa37c8ca163caec2
|
||||||
Yoga: 75bf4b0131cfb46a659cd0c13309b79a6fcff66d
|
Yoga: eca980a5771bf114c41a754098cd85e6e0d90ed7
|
||||||
|
|
||||||
PODFILE CHECKSUM: b77befb1871220c1a94408eeae0857d78b685698
|
PODFILE CHECKSUM: 144e94249445b1054f55a9e9533c8e6e80450047
|
||||||
|
|
||||||
COCOAPODS: 1.11.3
|
COCOAPODS: 1.11.3
|
||||||
|
|
|
@ -361,7 +361,9 @@
|
||||||
"FB_SONARKIT_ENABLED=1",
|
"FB_SONARKIT_ENABLED=1",
|
||||||
);
|
);
|
||||||
INFOPLIST_FILE = Spacedrive/Info.plist;
|
INFOPLIST_FILE = Spacedrive/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
INFOPLIST_KEY_CFBundleDisplayName = Spacedrive;
|
||||||
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.productivity";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
|
@ -454,7 +456,9 @@
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEVELOPMENT_TEAM = H7MGS2DHHJ;
|
DEVELOPMENT_TEAM = H7MGS2DHHJ;
|
||||||
INFOPLIST_FILE = Spacedrive/Info.plist;
|
INFOPLIST_FILE = Spacedrive/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
INFOPLIST_KEY_CFBundleDisplayName = Spacedrive;
|
||||||
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.productivity";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
|
@ -581,7 +585,7 @@
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
/usr/lib/swift,
|
/usr/lib/swift,
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
|
@ -635,7 +639,7 @@
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
/usr/lib/swift,
|
/usr/lib/swift,
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@gorhom/bottom-sheet": "^4.4.5",
|
"@gorhom/bottom-sheet": "^4.4.5",
|
||||||
"@react-native-async-storage/async-storage": "~1.17.10",
|
"@react-native-async-storage/async-storage": "~1.17.3",
|
||||||
"@react-native-masked-view/masked-view": "0.2.8",
|
"@react-native-masked-view/masked-view": "0.2.8",
|
||||||
"@react-navigation/bottom-tabs": "^6.4.0",
|
"@react-navigation/bottom-tabs": "^6.4.0",
|
||||||
"@react-navigation/drawer": "^6.5.0",
|
"@react-navigation/drawer": "^6.5.0",
|
||||||
|
@ -25,41 +25,45 @@
|
||||||
"@rspc/react": "^0.0.0-main-7c0a67c1",
|
"@rspc/react": "^0.0.0-main-7c0a67c1",
|
||||||
"@sd/assets": "workspace:*",
|
"@sd/assets": "workspace:*",
|
||||||
"@sd/client": "workspace:*",
|
"@sd/client": "workspace:*",
|
||||||
"@shopify/flash-list": "^1.3.1",
|
"@shopify/flash-list": "1.3.1",
|
||||||
"@tanstack/react-query": "^4.12.0",
|
"@tanstack/react-query": "^4.12.0",
|
||||||
"byte-size": "^8.1.0",
|
"byte-size": "^8.1.0",
|
||||||
"class-variance-authority": "^0.2.3",
|
"class-variance-authority": "^0.2.3",
|
||||||
"dayjs": "^1.11.6",
|
"dayjs": "^1.11.6",
|
||||||
"expo": "~46.0.15",
|
"expo": "^47.0.0",
|
||||||
"expo-linking": "~3.2.2",
|
"expo-linking": "~3.2.3",
|
||||||
"expo-media-library": "~14.2.0",
|
"expo-media-library": "~15.0.0",
|
||||||
"expo-splash-screen": "~0.16.2",
|
"expo-splash-screen": "~0.17.5",
|
||||||
"expo-status-bar": "~1.4.0",
|
"expo-status-bar": "~1.4.2",
|
||||||
"intl": "^1.2.5",
|
"intl": "^1.2.5",
|
||||||
"lottie-react-native": "^5.1.4",
|
"lottie-react-native": "5.1.4",
|
||||||
"moti": "^0.20.0",
|
"moti": "^0.20.0",
|
||||||
"phosphor-react-native": "^1.1.2",
|
"phosphor-react-native": "^1.1.2",
|
||||||
"react": "18.0.0",
|
"react": "18.1.0",
|
||||||
"react-native": "0.69.6",
|
"react-hook-form": "^7.36.1",
|
||||||
|
"react-native": "0.70.5",
|
||||||
"react-native-document-picker": "^8.1.1",
|
"react-native-document-picker": "^8.1.1",
|
||||||
"react-native-fs": "^2.20.0",
|
"react-native-fs": "^2.20.0",
|
||||||
"react-native-gesture-handler": "~2.5.0",
|
"react-native-gesture-handler": "~2.8.0",
|
||||||
"react-native-reanimated": "~2.10.0",
|
"react-native-reanimated": "~2.12.0",
|
||||||
"react-native-safe-area-context": "4.3.1",
|
"react-native-safe-area-context": "4.4.1",
|
||||||
"react-native-screens": "~3.15.0",
|
"react-native-screens": "~3.18.0",
|
||||||
"react-native-svg": "13.0.0",
|
"react-native-svg": "13.4.0",
|
||||||
|
"react-native-wheel-color-picker": "^1.2.0",
|
||||||
"twrnc": "^3.4.1",
|
"twrnc": "^3.4.1",
|
||||||
"use-count-up": "^3.0.1",
|
"use-count-up": "^3.0.1",
|
||||||
|
"use-debounce": "^8.0.4",
|
||||||
"valtio": "^1.7.1"
|
"valtio": "^1.7.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rnx-kit/metro-config": "^1.3.2",
|
"@rnx-kit/metro-config": "^1.3.2",
|
||||||
"@types/react": "~18.0.0",
|
"@sd/config": "workspace:*",
|
||||||
"@types/react-native": "~0.69.5",
|
"@types/react": "~18.0.24",
|
||||||
|
"@types/react-native": "~0.70.6",
|
||||||
"babel-plugin-module-resolver": "^4.1.0",
|
"babel-plugin-module-resolver": "^4.1.0",
|
||||||
"eslint-plugin-react-native": "^4.0.0",
|
"eslint-plugin-react-native": "^4.0.0",
|
||||||
"metro-minify-terser": "^0.73.1",
|
"metro-minify-terser": "^0.73.1",
|
||||||
"react-native-svg-transformer": "^1.0.0",
|
"react-native-svg-transformer": "^1.0.0",
|
||||||
"typescript": "^4.8.4"
|
"typescript": "^4.6.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
||||||
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
||||||
import { useDeviceContext } from 'twrnc';
|
import { useDeviceContext } from 'twrnc';
|
||||||
|
|
||||||
import { GlobalModals } from './containers/modals/GlobalModals';
|
import { GlobalModals } from './containers/modal/GlobalModals';
|
||||||
import { reactNativeLink } from './lib/rspcReactNativeTransport';
|
import { reactNativeLink } from './lib/rspcReactNativeTransport';
|
||||||
import tw from './lib/tailwind';
|
import tw from './lib/tailwind';
|
||||||
import RootNavigator from './navigation';
|
import RootNavigator from './navigation';
|
||||||
|
@ -26,7 +26,8 @@ const NavigatorTheme: Theme = {
|
||||||
...DefaultTheme,
|
...DefaultTheme,
|
||||||
colors: {
|
colors: {
|
||||||
...DefaultTheme.colors,
|
...DefaultTheme.colors,
|
||||||
background: tw.color('gray-650')
|
// Default screen background
|
||||||
|
background: tw.color('app')
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -38,7 +39,7 @@ function AppContainer() {
|
||||||
|
|
||||||
const { library } = useCurrentLibrary();
|
const { library } = useCurrentLibrary();
|
||||||
return (
|
return (
|
||||||
<SafeAreaProvider style={tw`flex-1 bg-gray-650`}>
|
<SafeAreaProvider style={tw`flex-1 bg-app`}>
|
||||||
<GestureHandlerRootView style={tw`flex-1`}>
|
<GestureHandlerRootView style={tw`flex-1`}>
|
||||||
<BottomSheetModalProvider>
|
<BottomSheetModalProvider>
|
||||||
<StatusBar style="light" />
|
<StatusBar style="light" />
|
||||||
|
|
|
@ -90,13 +90,13 @@ const placeholderFileItems: ExplorerItem[] = [
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
export interface DeviceProps {
|
type DeviceProps = {
|
||||||
name: string;
|
name: string;
|
||||||
size: string;
|
size: string;
|
||||||
type: keyof typeof DeviceIcon;
|
type: keyof typeof DeviceIcon;
|
||||||
locations: { name: string; folder?: boolean; format?: string; icon?: string }[];
|
locations: { name: string; folder?: boolean; format?: string; icon?: string }[];
|
||||||
runningJob?: { amount: number; task: string };
|
runningJob?: { amount: number; task: string };
|
||||||
}
|
};
|
||||||
|
|
||||||
const DeviceIcon = {
|
const DeviceIcon = {
|
||||||
phone: <DeviceMobileCamera color="white" weight="fill" size={18} style={tw`mr-2`} />,
|
phone: <DeviceMobileCamera color="white" weight="fill" size={18} style={tw`mr-2`} />,
|
||||||
|
@ -107,21 +107,20 @@ const DeviceIcon = {
|
||||||
|
|
||||||
const Device = ({ name, locations, size, type }: DeviceProps) => {
|
const Device = ({ name, locations, size, type }: DeviceProps) => {
|
||||||
return (
|
return (
|
||||||
<View style={tw`my-2 bg-gray-600 border rounded-md border-gray-550`}>
|
<View style={tw`my-2 bg-app-overlay border rounded-md border-app-line`}>
|
||||||
<View style={tw`flex flex-row items-center px-3.5 pt-3 pb-2`}>
|
<View style={tw`flex flex-row items-center px-3.5 pt-3 pb-2`}>
|
||||||
<View style={tw`flex flex-row items-center`}>
|
<View style={tw`flex flex-row items-center`}>
|
||||||
{DeviceIcon[type]}
|
{DeviceIcon[type]}
|
||||||
<Text style={tw`text-base font-semibold text-white`}>{name || 'Unnamed Device'}</Text>
|
<Text style={tw`text-base font-semibold text-ink`}>{name || 'Unnamed Device'}</Text>
|
||||||
{/* P2P Lock */}
|
{/* P2P Lock */}
|
||||||
<View style={tw`flex flex-row rounded items-center ml-2 bg-gray-500 py-[1px] px-[4px]`}>
|
<View style={tw`flex flex-row rounded items-center ml-2 bg-app-box py-[1px] px-[4px]`}>
|
||||||
<Lock weight="bold" size={12} color={tw.color('gray-400')} />
|
<Lock weight="bold" size={12} color={tw.color('ink-dull')} />
|
||||||
<Text style={tw`text-gray-400 font-semibold ml-0.5 text-xs`}>P2P</Text>
|
<Text style={tw`text-ink-dull font-semibold ml-0.5 text-xs`}>P2P</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
{/* Size */}
|
{/* Size */}
|
||||||
<Text style={tw`ml-2 text-sm font-semibold text-gray-400`}>{size}</Text>
|
<Text style={tw`ml-2 text-sm font-semibold text-ink-dull`}>{size}</Text>
|
||||||
</View>
|
</View>
|
||||||
{/* Locations/Files TODO: Maybe use FlashList? */}
|
|
||||||
<FlatList
|
<FlatList
|
||||||
data={placeholderFileItems}
|
data={placeholderFileItems}
|
||||||
renderItem={({ item }) => <FileItem data={item} />}
|
renderItem={({ item }) => <FileItem data={item} />}
|
||||||
|
|
|
@ -5,12 +5,12 @@ import tw from '~/lib/tailwind';
|
||||||
|
|
||||||
import FileItem from './FileItem';
|
import FileItem from './FileItem';
|
||||||
|
|
||||||
type Props = {
|
type ExplorerProps = {
|
||||||
locationId: number;
|
locationId: number;
|
||||||
path?: string;
|
path?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Explorer = ({ locationId, path }: Props) => {
|
const Explorer = ({ locationId, path }: ExplorerProps) => {
|
||||||
const { data } = useLibraryQuery([
|
const { data } = useLibraryQuery([
|
||||||
'locations.getExplorerData',
|
'locations.getExplorerData',
|
||||||
{
|
{
|
||||||
|
@ -23,7 +23,7 @@ const Explorer = ({ locationId, path }: Props) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={tw`flex-1`}>
|
<View style={tw`flex-1`}>
|
||||||
<Text style={tw`text-xl font-bold text-white mt-4`}>Location id:{locationId}</Text>
|
<Text style={tw`text-xl font-bold text-ink mt-4`}>Location id:{locationId}</Text>
|
||||||
{data && (
|
{data && (
|
||||||
<FlashList
|
<FlashList
|
||||||
data={data.items}
|
data={data.items}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { useNavigation } from '@react-navigation/native';
|
import { useNavigation } from '@react-navigation/native';
|
||||||
import { ExplorerItem } from '@sd/client';
|
import { ExplorerItem, isVideoExt } from '@sd/client';
|
||||||
import { Pressable, Text, View } from 'react-native';
|
import { Pressable, Text, View } from 'react-native';
|
||||||
|
import { isPath } from '~/types/helper';
|
||||||
|
|
||||||
import tw from '../../lib/tailwind';
|
import tw from '../../lib/tailwind';
|
||||||
import { SharedScreenProps } from '../../navigation/SharedScreens';
|
import { SharedScreenProps } from '../../navigation/SharedScreens';
|
||||||
|
@ -17,13 +18,12 @@ const FileItem = ({ data }: FileItemProps) => {
|
||||||
const navigation = useNavigation<SharedScreenProps<'Location'>['navigation']>();
|
const navigation = useNavigation<SharedScreenProps<'Location'>['navigation']>();
|
||||||
|
|
||||||
function handlePress() {
|
function handlePress() {
|
||||||
// if (!data) return;
|
if (isPath(data) && data.is_dir) {
|
||||||
// if (data.is_dir) {
|
navigation.navigate('Location', { id: data.location_id });
|
||||||
// navigation.navigate('Location', { id: data.location_id });
|
} else {
|
||||||
// } else {
|
setData(data);
|
||||||
// setData(data);
|
fileRef.current.present();
|
||||||
// fileRef.current.present();
|
}
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -31,10 +31,10 @@ const FileItem = ({ data }: FileItemProps) => {
|
||||||
<View style={tw`w-[90px] h-[80px] items-center`}>
|
<View style={tw`w-[90px] h-[80px] items-center`}>
|
||||||
<FileThumb
|
<FileThumb
|
||||||
data={data}
|
data={data}
|
||||||
kind={data.extension === 'zip' ? 'zip' : isVideo(data.extension) ? 'video' : 'other'}
|
kind={data.extension === 'zip' ? 'zip' : isVideoExt(data.extension) ? 'video' : 'other'}
|
||||||
/>
|
/>
|
||||||
<View style={tw`px-1.5 py-[1px] mt-1`}>
|
<View style={tw`px-1.5 py-[1px] mt-1`}>
|
||||||
<Text numberOfLines={1} style={tw`text-xs font-medium text-center text-gray-300`}>
|
<Text numberOfLines={1} style={tw`text-xs font-medium text-center text-ink-dull`}>
|
||||||
{data?.name}
|
{data?.name}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
|
@ -44,36 +44,3 @@ const FileItem = ({ data }: FileItemProps) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export default FileItem;
|
export default FileItem;
|
||||||
|
|
||||||
// Copied from FileItem.tsx (interface/src/components/explorer/FileItem.tsx)
|
|
||||||
function isVideo(extension: string) {
|
|
||||||
return [
|
|
||||||
'avi',
|
|
||||||
'asf',
|
|
||||||
'mpeg',
|
|
||||||
'mts',
|
|
||||||
'mpe',
|
|
||||||
'vob',
|
|
||||||
'qt',
|
|
||||||
'mov',
|
|
||||||
'asf',
|
|
||||||
'asx',
|
|
||||||
'mjpeg',
|
|
||||||
'ts',
|
|
||||||
'mxf',
|
|
||||||
'm2ts',
|
|
||||||
'f4v',
|
|
||||||
'wm',
|
|
||||||
'3gp',
|
|
||||||
'm4v',
|
|
||||||
'wmv',
|
|
||||||
'mp4',
|
|
||||||
'webm',
|
|
||||||
'flv',
|
|
||||||
'mpg',
|
|
||||||
'hevc',
|
|
||||||
'ogv',
|
|
||||||
'swf',
|
|
||||||
'wtv'
|
|
||||||
].includes(extension);
|
|
||||||
}
|
|
||||||
|
|
|
@ -84,7 +84,7 @@ export default function FileThumb({ data, size = 1, kind }: FileThumbProps) {
|
||||||
<Svg
|
<Svg
|
||||||
// Background
|
// Background
|
||||||
style={tw`absolute top-0 left-0`}
|
style={tw`absolute top-0 left-0`}
|
||||||
fill={tw.color('gray-550')}
|
fill={tw.color('app-box')}
|
||||||
width={45 * size}
|
width={45 * size}
|
||||||
height={60 * size}
|
height={60 * size}
|
||||||
viewBox="0 0 65 81"
|
viewBox="0 0 65 81"
|
||||||
|
@ -94,7 +94,7 @@ export default function FileThumb({ data, size = 1, kind }: FileThumbProps) {
|
||||||
<Svg
|
<Svg
|
||||||
// Peel
|
// Peel
|
||||||
style={tw`absolute top-[2px] -right-[0.6px]`}
|
style={tw`absolute top-[2px] -right-[0.6px]`}
|
||||||
fill={tw.color('gray-500')}
|
fill={tw.color('app-highlight')}
|
||||||
width={15 * size}
|
width={15 * size}
|
||||||
height={15 * size}
|
height={15 * size}
|
||||||
viewBox="0 0 41 41"
|
viewBox="0 0 41 41"
|
||||||
|
|
|
@ -7,7 +7,8 @@ import { Pressable, Text, View } from 'react-native';
|
||||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||||
import tw from '~/lib/tailwind';
|
import tw from '~/lib/tailwind';
|
||||||
|
|
||||||
const Header = () => {
|
// Default header with search bar and button to open drawer
|
||||||
|
export default function Header() {
|
||||||
const navigation = useNavigation<DrawerNavigationHelpers>();
|
const navigation = useNavigation<DrawerNavigationHelpers>();
|
||||||
|
|
||||||
const { top } = useSafeAreaInsets();
|
const { top } = useSafeAreaInsets();
|
||||||
|
@ -16,7 +17,7 @@ const Header = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={tw.style('mx-4 bg-gray-500 border border-[#333949] bg-opacity-40 rounded', {
|
style={tw.style('mx-4 bg-app-overlay border border-app-line rounded', {
|
||||||
marginTop: top + 10
|
marginTop: top + 10
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
|
@ -26,18 +27,16 @@ const Header = () => {
|
||||||
animate={{ rotate: isDrawerOpen ? '90deg' : '0deg' }}
|
animate={{ rotate: isDrawerOpen ? '90deg' : '0deg' }}
|
||||||
transition={{ type: 'timing' }}
|
transition={{ type: 'timing' }}
|
||||||
>
|
>
|
||||||
<List size={20} color={tw.color('gray-300')} weight="fill" />
|
<List size={20} color={tw.color('ink-faint')} weight="fill" />
|
||||||
</MotiView>
|
</MotiView>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
<Pressable
|
<Pressable
|
||||||
style={tw`flex-1 h-full justify-center`}
|
style={tw`flex-1 h-full justify-center`}
|
||||||
onPress={() => navigation.navigate('Search')}
|
onPress={() => navigation.navigate('Search')}
|
||||||
>
|
>
|
||||||
<Text style={tw`text-gray-300 font-medium text-sm`}>Search</Text>
|
<Text style={tw`text-ink-dull font-medium text-sm`}>Search</Text>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
export default Header;
|
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { View, ViewProps } from 'react-native';
|
||||||
|
import tw from '~/lib/tailwind';
|
||||||
|
|
||||||
|
type CardProps = {
|
||||||
|
children: React.ReactNode;
|
||||||
|
} & ViewProps;
|
||||||
|
|
||||||
|
const Card = ({ children, ...props }: CardProps) => {
|
||||||
|
const { style, ...otherProps } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={tw.style(
|
||||||
|
'px-4 py-3 border border-app-line rounded-lg bg-app-overlay',
|
||||||
|
style as string
|
||||||
|
)}
|
||||||
|
{...otherProps}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Card;
|
|
@ -29,7 +29,7 @@ const CollapsibleView = ({ title, titleStyle, containerStyle, children }: Collap
|
||||||
}}
|
}}
|
||||||
transition={{ type: 'timing' }}
|
transition={{ type: 'timing' }}
|
||||||
>
|
>
|
||||||
<CaretRight color={tw.color('gray-200')} size={16} style={tw`mr-3`} />
|
<CaretRight color={tw.color('ink-dull')} size={16} style={tw`mr-3`} />
|
||||||
</MotiView>
|
</MotiView>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
<AnimatedHeight hide={hide}>{children}</AnimatedHeight>
|
<AnimatedHeight hide={hide}>{children}</AnimatedHeight>
|
||||||
|
|
|
@ -57,7 +57,7 @@ const Dialog = (props: DialogProps) => {
|
||||||
<Modal renderToHardwareTextureAndroid transparent visible={props.isVisible ?? visible}>
|
<Modal renderToHardwareTextureAndroid transparent visible={props.isVisible ?? visible}>
|
||||||
{/* Backdrop */}
|
{/* Backdrop */}
|
||||||
<Pressable
|
<Pressable
|
||||||
style={tw`bg-black bg-opacity-50 absolute inset-0`}
|
style={tw`bg-app-box/40 absolute inset-0`}
|
||||||
onPress={handleCloseDialog}
|
onPress={handleCloseDialog}
|
||||||
disabled={props.disableBackdropClose || props.loading}
|
disabled={props.disableBackdropClose || props.loading}
|
||||||
/>
|
/>
|
||||||
|
@ -73,15 +73,16 @@ const Dialog = (props: DialogProps) => {
|
||||||
animate={{ translateY: 0 }}
|
animate={{ translateY: 0 }}
|
||||||
transition={{ type: 'timing', duration: 200 }}
|
transition={{ type: 'timing', duration: 200 }}
|
||||||
>
|
>
|
||||||
|
{/* TODO: Blur may look cool here */}
|
||||||
<View
|
<View
|
||||||
style={tw`min-w-[360px] max-w-[380px] rounded-md bg-gray-650 border border-gray-550 shadow-md overflow-hidden`}
|
style={tw`min-w-[360px] max-w-[380px] rounded-md bg-app border border-app-line shadow shadow-app-shade overflow-hidden`}
|
||||||
>
|
>
|
||||||
<View style={tw`p-5`}>
|
<View style={tw`p-5`}>
|
||||||
{/* Title */}
|
{/* Title */}
|
||||||
<Text style={tw`font-bold text-white text-base`}>{props.title}</Text>
|
<Text style={tw`font-bold text-ink text-base`}>{props.title}</Text>
|
||||||
{/* Description */}
|
{/* Description */}
|
||||||
{props.description && (
|
{props.description && (
|
||||||
<Text style={tw`text-sm text-gray-300 mt-2 leading-normal`}>
|
<Text style={tw`text-sm text-ink-dull mt-2 leading-normal`}>
|
||||||
{props.description}
|
{props.description}
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
|
@ -90,7 +91,7 @@ const Dialog = (props: DialogProps) => {
|
||||||
</View>
|
</View>
|
||||||
{/* Actions */}
|
{/* Actions */}
|
||||||
<View
|
<View
|
||||||
style={tw`flex flex-row items-center px-3 py-3 bg-gray-600 border-t border-gray-550`}
|
style={tw`flex flex-row items-center px-3 py-3 bg-app-highlight border-t border-app-line`}
|
||||||
>
|
>
|
||||||
{props.loading && <PulseAnimation style={tw`h-7`} />}
|
{props.loading && <PulseAnimation style={tw`h-7`} />}
|
||||||
<View style={tw`flex-grow`} />
|
<View style={tw`flex-grow`} />
|
||||||
|
@ -100,17 +101,17 @@ const Dialog = (props: DialogProps) => {
|
||||||
disabled={props.loading} // Disables Close button if loading
|
disabled={props.loading} // Disables Close button if loading
|
||||||
onPress={handleCloseDialog}
|
onPress={handleCloseDialog}
|
||||||
>
|
>
|
||||||
<Text style={tw`text-white text-sm`}>Close</Text>
|
<Text style={tw`text-ink text-sm`}>Close</Text>
|
||||||
</Button>
|
</Button>
|
||||||
{props.ctaAction && (
|
{props.ctaAction && (
|
||||||
<Button
|
<Button
|
||||||
style={tw`ml-2`}
|
style={tw`ml-2`}
|
||||||
variant={props.ctaDanger ? 'danger' : 'primary'}
|
variant={props.ctaDanger ? 'danger' : 'accent'}
|
||||||
size="md"
|
size="md"
|
||||||
onPress={props.ctaAction}
|
onPress={props.ctaAction}
|
||||||
disabled={props.ctaDisabled || props.loading}
|
disabled={props.ctaDisabled || props.loading}
|
||||||
>
|
>
|
||||||
<Text style={tw`text-white text-sm`}>{props.ctaLabel}</Text>
|
<Text style={tw`text-ink text-sm`}>{props.ctaLabel}</Text>
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
|
|
@ -17,8 +17,8 @@ const ModalBackdrop = (props: BottomSheetBackdropProps) => (
|
||||||
const ModalHandle = (props: BottomSheetHandleProps) => (
|
const ModalHandle = (props: BottomSheetHandleProps) => (
|
||||||
<BottomSheetHandle
|
<BottomSheetHandle
|
||||||
{...props}
|
{...props}
|
||||||
style={tw`bg-gray-600 rounded-t-xl`}
|
style={tw`bg-app rounded-t-xl`}
|
||||||
indicatorStyle={tw`bg-gray-550`}
|
indicatorStyle={tw`bg-app-highlight`}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ export const Modal = forwardRef<BottomSheetModalMethods, BottomSheetModalProps>(
|
||||||
ref={ref}
|
ref={ref}
|
||||||
backdropComponent={ModalBackdrop}
|
backdropComponent={ModalBackdrop}
|
||||||
handleComponent={ModalHandle}
|
handleComponent={ModalHandle}
|
||||||
backgroundStyle={tw.style('bg-gray-600')}
|
backgroundStyle={tw`bg-app`}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
|
|
|
@ -7,11 +7,10 @@ import tw from '~/lib/tailwind';
|
||||||
const button = cva(['border rounded-md items-center justify-center shadow-sm'], {
|
const button = cva(['border rounded-md items-center justify-center shadow-sm'], {
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
default: 'bg-gray-50 border-gray-100',
|
danger: ['bg-red-600 border-red-800'],
|
||||||
primary: ['bg-primary-600'],
|
gray: ['bg-app-button border-app-line'],
|
||||||
danger: ['bg-red-600'],
|
dark_gray: ['bg-app border-app-box'],
|
||||||
gray: ['bg-gray-100 border-gray-200'],
|
accent: ['bg-accent border-accent-deep shadow-md shadow-app-shade/10']
|
||||||
dark_gray: ['bg-gray-500 border-gray-600']
|
|
||||||
},
|
},
|
||||||
size: {
|
size: {
|
||||||
default: ['py-1', 'px-3'],
|
default: ['py-1', 'px-3'],
|
||||||
|
@ -24,7 +23,7 @@ const button = cva(['border rounded-md items-center justify-center shadow-sm'],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
variant: 'default',
|
variant: 'gray',
|
||||||
size: 'default'
|
size: 'default'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,7 +6,7 @@ type DividerProps = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const Divider = ({ style }: DividerProps) => {
|
const Divider = ({ style }: DividerProps) => {
|
||||||
return <View style={[tw`w-full my-1 h-[1px] bg-gray-550`, style]} />;
|
return <View style={[tw`w-full my-1 h-[1px] bg-app-line`, style]} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Divider;
|
export default Divider;
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import { VariantProps, cva } from 'class-variance-authority';
|
import { VariantProps, cva } from 'class-variance-authority';
|
||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
import { TextInput as RNTextInput, TextInputProps as RNTextInputProps } from 'react-native';
|
import { TextInputProps as RNTextInputProps, TextInput } from 'react-native';
|
||||||
import tw from '~/lib/tailwind';
|
import tw from '~/lib/tailwind';
|
||||||
|
|
||||||
const input = cva(['text-sm rounded-md border shadow-sm'], {
|
const input = cva(['text-sm rounded-md border shadow-sm'], {
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
default: 'bg-gray-550 border-gray-500 text-white'
|
default: 'bg-app border-app-line text-ink'
|
||||||
},
|
},
|
||||||
size: {
|
size: {
|
||||||
default: ['py-2', 'px-3']
|
default: ['py-2', 'px-3']
|
||||||
|
@ -20,11 +20,11 @@ const input = cva(['text-sm rounded-md border shadow-sm'], {
|
||||||
|
|
||||||
type InputProps = VariantProps<typeof input> & RNTextInputProps;
|
type InputProps = VariantProps<typeof input> & RNTextInputProps;
|
||||||
|
|
||||||
export const TextInput: FC<InputProps> = ({ variant, ...props }) => {
|
export const Input: FC<InputProps> = ({ variant, ...props }) => {
|
||||||
const { style, ...otherProps } = props;
|
const { style, ...otherProps } = props;
|
||||||
return (
|
return (
|
||||||
<RNTextInput
|
<TextInput
|
||||||
placeholderTextColor={tw.color('gray-300')}
|
placeholderTextColor={tw.color('ink-dull')}
|
||||||
style={tw.style(input({ variant }), style as string)}
|
style={tw.style(input({ variant }), style as string)}
|
||||||
{...otherProps}
|
{...otherProps}
|
||||||
/>
|
/>
|
||||||
|
|
23
apps/mobile/src/components/primitive/Switch.tsx
Normal file
23
apps/mobile/src/components/primitive/Switch.tsx
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
import { FC } from 'react';
|
||||||
|
import { Switch as RNSwitch, SwitchProps, Text, View } from 'react-native';
|
||||||
|
import tw from '~/lib/tailwind';
|
||||||
|
|
||||||
|
export const Switch: FC<SwitchProps> = ({ ...props }) => {
|
||||||
|
return (
|
||||||
|
<RNSwitch trackColor={{ false: tw.color('app-line'), true: tw.color('accent') }} {...props} />
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
type SwitchContainerProps = { title: string; description?: string } & SwitchProps;
|
||||||
|
|
||||||
|
export const SwitchContainer: FC<SwitchContainerProps> = ({ title, description, ...props }) => {
|
||||||
|
return (
|
||||||
|
<View style={tw`flex flex-row items-center justify-between pb-6`}>
|
||||||
|
<View style={tw`w-[80%]`}>
|
||||||
|
<Text style={tw`font-medium text-ink text-sm`}>{title}</Text>
|
||||||
|
{description && <Text style={tw`text-ink-dull text-sm mt-2`}>{description}</Text>}
|
||||||
|
</View>
|
||||||
|
<Switch trackColor={{ false: tw.color('app-line'), true: tw.color('accent') }} {...props} />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
18
apps/mobile/src/components/settings/SettingsContainer.tsx
Normal file
18
apps/mobile/src/components/settings/SettingsContainer.tsx
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import { PropsWithChildren } from 'react';
|
||||||
|
import { Text, View } from 'react-native';
|
||||||
|
import tw from '~/lib/tailwind';
|
||||||
|
|
||||||
|
type SettingsContainerProps = PropsWithChildren<{
|
||||||
|
title?: string;
|
||||||
|
description?: string;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
export function SettingsContainer({ children, title, description }: SettingsContainerProps) {
|
||||||
|
return (
|
||||||
|
<View style={tw``}>
|
||||||
|
{title && <Text style={tw`pb-2 pl-3 text-sm font-semibold text-ink-dull`}>{title}</Text>}
|
||||||
|
{children}
|
||||||
|
{description && <Text style={tw`text-ink-dull text-sm px-3 pt-2`}>{description}</Text>}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
32
apps/mobile/src/components/settings/SettingsItem.tsx
Normal file
32
apps/mobile/src/components/settings/SettingsItem.tsx
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
import { CaretRight, Icon } from 'phosphor-react-native';
|
||||||
|
import { Pressable, Text, View } from 'react-native';
|
||||||
|
import tw from '~/lib/tailwind';
|
||||||
|
|
||||||
|
type SettingsItemProps = {
|
||||||
|
title: string;
|
||||||
|
onPress?: () => void;
|
||||||
|
leftIcon?: Icon;
|
||||||
|
rightArea?: React.ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function SettingsItem(props: SettingsItemProps) {
|
||||||
|
return (
|
||||||
|
<Pressable onPress={props.onPress}>
|
||||||
|
<View style={tw`flex flex-row items-center justify-between px-3 bg-app-overlay`}>
|
||||||
|
<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-sm text-ink`}>{props.title}</Text>
|
||||||
|
</View>
|
||||||
|
{props.rightArea ? props.rightArea : <CaretRight size={20} color={tw.color('ink-faint')} />}
|
||||||
|
</View>
|
||||||
|
</Pressable>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SettingsItemDivider() {
|
||||||
|
return (
|
||||||
|
<View style={tw`bg-app-overlay`}>
|
||||||
|
<View style={tw`mx-3 border-b border-b-app-line`} />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,27 +0,0 @@
|
||||||
import { FC } from 'react';
|
|
||||||
import { Pressable, Text, View } from 'react-native';
|
|
||||||
import tw from '~/lib/tailwind';
|
|
||||||
|
|
||||||
import FolderIcon from '../../components/icons/FolderIcon';
|
|
||||||
|
|
||||||
interface BrowseLocationItemProps {
|
|
||||||
folderName: string;
|
|
||||||
onPress: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const BrowseLocationItem: FC<BrowseLocationItemProps> = (props) => {
|
|
||||||
const { folderName, onPress } = props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Pressable onPress={onPress}>
|
|
||||||
<View style={tw.style('flex mb-[4px] flex-row items-center py-2 px-2 rounded')}>
|
|
||||||
<FolderIcon size={18} />
|
|
||||||
<Text style={tw.style('text-gray-300 text-sm font-medium ml-2')} numberOfLines={1}>
|
|
||||||
{folderName}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
</Pressable>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default BrowseLocationItem;
|
|
|
@ -1,25 +0,0 @@
|
||||||
import { FC } from 'react';
|
|
||||||
import { ColorValue, Pressable, Text, View } from 'react-native';
|
|
||||||
import tw from '~/lib/tailwind';
|
|
||||||
|
|
||||||
type BrowseTagItemProps = {
|
|
||||||
tagName: string;
|
|
||||||
tagColor: ColorValue;
|
|
||||||
onPress: () => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
const BrowseTagItem: FC<BrowseTagItemProps> = (props) => {
|
|
||||||
const { tagName, tagColor, onPress } = props;
|
|
||||||
return (
|
|
||||||
<Pressable onPress={onPress}>
|
|
||||||
<View style={tw.style('flex mb-[4px] flex-row items-center py-2 px-2 rounded')}>
|
|
||||||
<View style={tw.style('w-3 h-3 rounded-full', { backgroundColor: tagColor })} />
|
|
||||||
<Text style={tw.style('text-gray-300 text-sm font-medium ml-2')} numberOfLines={1}>
|
|
||||||
{tagName}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
</Pressable>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default BrowseTagItem;
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { queryClient, useBridgeMutation, useCurrentLibrary } from '@sd/client';
|
import { queryClient, useBridgeMutation, useCurrentLibrary } from '@sd/client';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import Dialog from '~/components/layout/Dialog';
|
import Dialog from '~/components/layout/Dialog';
|
||||||
import { TextInput } from '~/components/primitive/Input';
|
import { Input } from '~/components/primitive/Input';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onSubmit?: () => void;
|
onSubmit?: () => void;
|
||||||
|
@ -11,7 +11,7 @@ type Props = {
|
||||||
|
|
||||||
const CreateLibraryDialog = ({ children, onSubmit, disableBackdropClose }: Props) => {
|
const CreateLibraryDialog = ({ children, onSubmit, disableBackdropClose }: Props) => {
|
||||||
const [libName, setLibName] = useState('');
|
const [libName, setLibName] = useState('');
|
||||||
const [createLibOpen, setCreateLibOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
const { switchLibrary } = useCurrentLibrary();
|
const { switchLibrary } = useCurrentLibrary();
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ const CreateLibraryDialog = ({ children, onSubmit, disableBackdropClose }: Props
|
||||||
// Reset form
|
// Reset form
|
||||||
setLibName('');
|
setLibName('');
|
||||||
|
|
||||||
|
// We do this instead of invalidating the query because it triggers a full app re-render??
|
||||||
queryClient.setQueryData(['library.list'], (libraries: any) => [...(libraries || []), lib]);
|
queryClient.setQueryData(['library.list'], (libraries: any) => [...(libraries || []), lib]);
|
||||||
|
|
||||||
// Switch to the new library
|
// Switch to the new library
|
||||||
|
@ -31,14 +32,14 @@ const CreateLibraryDialog = ({ children, onSubmit, disableBackdropClose }: Props
|
||||||
},
|
},
|
||||||
onSettled: () => {
|
onSettled: () => {
|
||||||
// Close create lib dialog
|
// Close create lib dialog
|
||||||
setCreateLibOpen(false);
|
setIsOpen(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<Dialog
|
<Dialog
|
||||||
isVisible={createLibOpen}
|
isVisible={isOpen}
|
||||||
setIsVisible={setCreateLibOpen}
|
setIsVisible={setIsOpen}
|
||||||
title="Create New Library"
|
title="Create New Library"
|
||||||
description="Choose a name for your new library, you can configure this and more settings from the library settings later on."
|
description="Choose a name for your new library, you can configure this and more settings from the library settings later on."
|
||||||
ctaLabel="Create"
|
ctaLabel="Create"
|
||||||
|
@ -47,9 +48,9 @@ const CreateLibraryDialog = ({ children, onSubmit, disableBackdropClose }: Props
|
||||||
ctaDisabled={libName.length === 0}
|
ctaDisabled={libName.length === 0}
|
||||||
trigger={children}
|
trigger={children}
|
||||||
disableBackdropClose={disableBackdropClose}
|
disableBackdropClose={disableBackdropClose}
|
||||||
onClose={() => setLibName('')} // Reset form onClose
|
onClose={() => setLibName('')} // Resets form onClose
|
||||||
>
|
>
|
||||||
<TextInput
|
<Input
|
||||||
value={libName}
|
value={libName}
|
||||||
onChangeText={(text) => setLibName(text)}
|
onChangeText={(text) => setLibName(text)}
|
||||||
placeholder="My Cool Library"
|
placeholder="My Cool Library"
|
||||||
|
|
42
apps/mobile/src/containers/dialog/DeleteLibraryDialog.tsx
Normal file
42
apps/mobile/src/containers/dialog/DeleteLibraryDialog.tsx
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
import { queryClient, useBridgeMutation } from '@sd/client';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import Dialog from '~/components/layout/Dialog';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
libraryUuid: string;
|
||||||
|
onSubmit?: () => void;
|
||||||
|
children: React.ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
const DeleteLibraryDialog = ({ children, onSubmit, libraryUuid }: Props) => {
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
|
const { mutate: deleteLibrary, isLoading: deleteLibLoading } = useBridgeMutation(
|
||||||
|
'library.delete',
|
||||||
|
{
|
||||||
|
onSuccess: () => {
|
||||||
|
queryClient.invalidateQueries(['library.list']);
|
||||||
|
onSubmit?.();
|
||||||
|
},
|
||||||
|
onSettled: () => {
|
||||||
|
// Close dialog
|
||||||
|
setIsOpen(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<Dialog
|
||||||
|
isVisible={isOpen}
|
||||||
|
setIsVisible={setIsOpen}
|
||||||
|
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}
|
||||||
|
ctaDanger
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DeleteLibraryDialog;
|
41
apps/mobile/src/containers/dialog/DeleteLocationDialog.tsx
Normal file
41
apps/mobile/src/containers/dialog/DeleteLocationDialog.tsx
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
import { useLibraryMutation } from '@sd/client';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import Dialog from '~/components/layout/Dialog';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
locationId: number;
|
||||||
|
onSubmit?: () => void;
|
||||||
|
children: React.ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
const DeleteLocationDialog = ({ children, onSubmit, locationId }: Props) => {
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
|
const { mutate: deleteLoc, isLoading: deleteLocLoading } = useLibraryMutation(
|
||||||
|
'locations.delete',
|
||||||
|
{
|
||||||
|
onSuccess: () => {
|
||||||
|
onSubmit?.();
|
||||||
|
},
|
||||||
|
onSettled: () => {
|
||||||
|
// Close dialog
|
||||||
|
setIsOpen(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<Dialog
|
||||||
|
isVisible={isOpen}
|
||||||
|
setIsVisible={setIsOpen}
|
||||||
|
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}
|
||||||
|
ctaDanger
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DeleteLocationDialog;
|
98
apps/mobile/src/containers/dialog/tag/CreateTagDialog.tsx
Normal file
98
apps/mobile/src/containers/dialog/tag/CreateTagDialog.tsx
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
import { queryClient, useLibraryMutation } from '@sd/client';
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import { Pressable, View } from 'react-native';
|
||||||
|
import ColorPicker from 'react-native-wheel-color-picker';
|
||||||
|
import Dialog from '~/components/layout/Dialog';
|
||||||
|
import { Input } from '~/components/primitive/Input';
|
||||||
|
import tw 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={tw.style({ backgroundColor: tagColor }, 'w-5 h-5 rounded-full')}
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
style={tw`flex-1 ml-2`}
|
||||||
|
value={tagName}
|
||||||
|
onChangeText={(text) => setTagName(text)}
|
||||||
|
placeholder="Name"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
{showPicker && (
|
||||||
|
<View style={tw`h-64 mt-4`}>
|
||||||
|
<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;
|
38
apps/mobile/src/containers/dialog/tag/DeleteTagDialog.tsx
Normal file
38
apps/mobile/src/containers/dialog/tag/DeleteTagDialog.tsx
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import { useLibraryMutation } from '@sd/client';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import Dialog from '~/components/layout/Dialog';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
tagId: number;
|
||||||
|
onSubmit?: () => void;
|
||||||
|
children: React.ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
const DeleteTagDialog = ({ children, onSubmit, tagId }: Props) => {
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
|
const { mutate: deleteTag, isLoading: deleteTagLoading } = useLibraryMutation('tags.delete', {
|
||||||
|
onSuccess: () => {
|
||||||
|
onSubmit?.();
|
||||||
|
},
|
||||||
|
onSettled: () => {
|
||||||
|
// Close dialog
|
||||||
|
setIsOpen(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<Dialog
|
||||||
|
isVisible={isOpen}
|
||||||
|
setIsVisible={setIsOpen}
|
||||||
|
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}
|
||||||
|
ctaDanger
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DeleteTagDialog;
|
92
apps/mobile/src/containers/dialog/tag/UpdateTagDialog.tsx
Normal file
92
apps/mobile/src/containers/dialog/tag/UpdateTagDialog.tsx
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
import { Tag, queryClient, useLibraryMutation } from '@sd/client';
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import { Pressable, Text, View } from 'react-native';
|
||||||
|
import ColorPicker from 'react-native-wheel-color-picker';
|
||||||
|
import Dialog from '~/components/layout/Dialog';
|
||||||
|
import { Input } from '~/components/primitive/Input';
|
||||||
|
import tw 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`mb-1 text-xs font-medium text-ink-dull ml-1 mt-3`}>Name</Text>
|
||||||
|
<Input value={tagName} onChangeText={(t) => setTagName(t)} />
|
||||||
|
<Text style={tw`mb-1 text-xs font-medium text-ink-dull ml-1 mt-3`}>Color</Text>
|
||||||
|
<View style={tw`flex flex-row items-center ml-2`}>
|
||||||
|
<Pressable
|
||||||
|
onPress={() => setShowPicker((v) => !v)}
|
||||||
|
style={tw.style({ backgroundColor: tagColor }, 'w-5 h-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`flex-1 ml-2`} />
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{showPicker && (
|
||||||
|
<View style={tw`h-64 mt-4`}>
|
||||||
|
<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;
|
|
@ -25,7 +25,7 @@ const DrawerContent = ({ navigation, state }: DrawerContentComponentProps) => {
|
||||||
<View>
|
<View>
|
||||||
<View style={tw`flex flex-row items-center`}>
|
<View style={tw`flex flex-row items-center`}>
|
||||||
<Image source={require('@sd/assets/images/logo.png')} style={tw`w-[35px] h-[35px]`} />
|
<Image source={require('@sd/assets/images/logo.png')} style={tw`w-[35px] h-[35px]`} />
|
||||||
<Text style={tw`text-base font-bold text-white ml-2`}>Spacedrive</Text>
|
<Text style={tw`text-base font-bold text-ink ml-2`}>Spacedrive</Text>
|
||||||
</View>
|
</View>
|
||||||
<Divider style={tw`my-4`} />
|
<Divider style={tw`my-4`} />
|
||||||
{/* Library Manager */}
|
{/* Library Manager */}
|
||||||
|
@ -37,7 +37,7 @@ const DrawerContent = ({ navigation, state }: DrawerContentComponentProps) => {
|
||||||
</View>
|
</View>
|
||||||
{/* Settings */}
|
{/* Settings */}
|
||||||
<Pressable onPress={() => navigation.navigate('Settings')}>
|
<Pressable onPress={() => navigation.navigate('Settings')}>
|
||||||
<Gear color="white" size={24} />
|
<Gear color={tw.color('ink')} size={24} />
|
||||||
</Pressable>
|
</Pressable>
|
||||||
</View>
|
</View>
|
||||||
</DrawerContentScrollView>
|
</DrawerContentScrollView>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { useDrawerStatus } from '@react-navigation/drawer';
|
import { useDrawerStatus } from '@react-navigation/drawer';
|
||||||
|
import { useNavigation } from '@react-navigation/native';
|
||||||
import { MotiView } from 'moti';
|
import { MotiView } from 'moti';
|
||||||
import { CaretRight, Gear, Lock, Plus } from 'phosphor-react-native';
|
import { CaretRight, Gear, Lock, Plus } from 'phosphor-react-native';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
@ -21,62 +22,73 @@ const DrawerLibraryManager = () => {
|
||||||
|
|
||||||
const { library: currentLibrary, libraries, switchLibrary } = useCurrentLibrary();
|
const { library: currentLibrary, libraries, switchLibrary } = useCurrentLibrary();
|
||||||
|
|
||||||
|
const navigation = useNavigation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View>
|
<View>
|
||||||
<Pressable onPress={() => setDropdownClosed((v) => !v)}>
|
<Pressable onPress={() => setDropdownClosed((v) => !v)}>
|
||||||
<View
|
<View
|
||||||
style={tw.style(
|
style={tw.style(
|
||||||
'flex flex-row justify-between items-center px-3 h-10 w-full bg-gray-500 border border-[#333949] bg-opacity-40 shadow-sm',
|
'flex flex-row justify-between items-center px-3 h-10 w-full bg-app-box border border-app-darkLine shadow-sm',
|
||||||
dropdownClosed ? 'rounded' : 'rounded-t border-b-gray-550'
|
dropdownClosed ? 'rounded' : 'rounded-t border-b-app-box'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Text style={tw`text-gray-200 text-sm font-semibold`}>{currentLibrary?.config.name}</Text>
|
<Text style={tw`text-ink text-sm font-semibold`}>{currentLibrary?.config.name}</Text>
|
||||||
<MotiView
|
<MotiView
|
||||||
animate={{
|
animate={{
|
||||||
rotateZ: dropdownClosed ? '0deg' : '90deg'
|
rotateZ: dropdownClosed ? '0deg' : '90deg'
|
||||||
}}
|
}}
|
||||||
transition={{ type: 'timing' }}
|
transition={{ type: 'timing' }}
|
||||||
>
|
>
|
||||||
<CaretRight color={tw.color('text-gray-200')} size={16} style={tw`ml-2`} />
|
<CaretRight color={tw.color('text-ink')} size={16} style={tw`ml-2`} />
|
||||||
</MotiView>
|
</MotiView>
|
||||||
</View>
|
</View>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
<AnimatedHeight hide={dropdownClosed}>
|
<AnimatedHeight hide={dropdownClosed}>
|
||||||
<View
|
<View
|
||||||
style={tw`py-2 px-2 bg-gray-500 border-l border-b border-r border-[#333949] bg-opacity-40 rounded-b`}
|
style={tw`py-2 px-2 bg-app-box border-l border-b border-r border-app-darkLine rounded-b`}
|
||||||
>
|
>
|
||||||
{/* Libraries */}
|
{/* Libraries */}
|
||||||
{libraries?.map((library) => (
|
{libraries?.map((library) => (
|
||||||
<Pressable key={library.uuid} onPress={() => switchLibrary(library.uuid)}>
|
<Pressable key={library.uuid} onPress={() => switchLibrary(library.uuid)}>
|
||||||
<View
|
<View
|
||||||
style={tw.style(
|
style={tw.style(
|
||||||
'p-2',
|
'p-2 mt-1',
|
||||||
currentLibrary.uuid === library.uuid && 'bg-gray-500 bg-opacity-70 rounded'
|
currentLibrary.uuid === library.uuid && 'bg-accent rounded'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Text style={tw`text-sm text-gray-200 font-semibold`}>{library.config.name}</Text>
|
<Text
|
||||||
|
style={tw.style(
|
||||||
|
'text-sm text-ink font-semibold',
|
||||||
|
currentLibrary.uuid === library.uuid && 'text-white'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{library.config.name}
|
||||||
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
))}
|
))}
|
||||||
<Divider style={tw`mt-2 mb-2`} />
|
<Divider style={tw`mt-2 mb-2`} />
|
||||||
{/* Menu */}
|
{/* Menu */}
|
||||||
<Pressable onPress={() => console.log('settings')}>
|
<Pressable
|
||||||
|
onPress={() => navigation.navigate('Settings', { screen: 'LibraryGeneralSettings' })}
|
||||||
|
>
|
||||||
<View style={tw`flex flex-row items-center px-1.5 py-[8px]`}>
|
<View style={tw`flex flex-row items-center px-1.5 py-[8px]`}>
|
||||||
<Gear size={16} color={tw.color('gray-100')} style={tw`mr-2`} />
|
<Gear size={16} color={tw.color('ink-dull')} style={tw`mr-2`} />
|
||||||
<Text style={tw`text-sm text-gray-200 font-semibold`}>Library Settings</Text>
|
<Text style={tw`text-sm text-ink font-semibold`}>Library Settings</Text>
|
||||||
</View>
|
</View>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
{/* Create Library */}
|
{/* Create Library */}
|
||||||
<CreateLibraryDialog>
|
<CreateLibraryDialog>
|
||||||
<View style={tw`flex flex-row items-center px-1.5 py-[8px]`}>
|
<View style={tw`flex flex-row items-center px-1.5 py-[8px]`}>
|
||||||
<Plus size={16} weight="bold" color={tw.color('gray-100')} style={tw`mr-2`} />
|
<Plus size={16} weight="bold" color={tw.color('ink-dull')} style={tw`mr-2`} />
|
||||||
<Text style={tw`text-sm text-gray-200 font-semibold`}>Add Library</Text>
|
<Text style={tw`text-sm text-ink font-semibold`}>Add Library</Text>
|
||||||
</View>
|
</View>
|
||||||
</CreateLibraryDialog>
|
</CreateLibraryDialog>
|
||||||
<Pressable onPress={() => console.log('lock')}>
|
<Pressable onPress={() => console.log('TODO: lock')}>
|
||||||
<View style={tw`flex flex-row items-center px-1.5 py-[8px]`}>
|
<View style={tw`flex flex-row items-center px-1.5 py-[8px]`}>
|
||||||
<Lock size={16} weight="bold" color={tw.color('gray-100')} style={tw`mr-2`} />
|
<Lock size={16} weight="bold" color={tw.color('ink-dull')} style={tw`mr-2`} />
|
||||||
<Text style={tw`text-sm text-gray-200 font-semibold`}>Lock</Text>
|
<Text style={tw`text-sm text-ink font-semibold`}>Lock</Text>
|
||||||
</View>
|
</View>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
</View>
|
</View>
|
||||||
|
|
|
@ -8,12 +8,12 @@ import tw from '~/lib/tailwind';
|
||||||
|
|
||||||
import FolderIcon from '../../components/icons/FolderIcon';
|
import FolderIcon from '../../components/icons/FolderIcon';
|
||||||
import CollapsibleView from '../../components/layout/CollapsibleView';
|
import CollapsibleView from '../../components/layout/CollapsibleView';
|
||||||
import ImportModal from '../modals/ImportModal';
|
import ImportModal from '../modal/ImportModal';
|
||||||
|
|
||||||
interface DrawerLocationItemProps {
|
type DrawerLocationItemProps = {
|
||||||
folderName: string;
|
folderName: string;
|
||||||
onPress: () => void;
|
onPress: () => void;
|
||||||
}
|
};
|
||||||
|
|
||||||
const DrawerLocationItem: React.FC<DrawerLocationItemProps> = (props) => {
|
const DrawerLocationItem: React.FC<DrawerLocationItemProps> = (props) => {
|
||||||
const { folderName, onPress } = props;
|
const { folderName, onPress } = props;
|
||||||
|
@ -30,9 +30,9 @@ const DrawerLocationItem: React.FC<DrawerLocationItemProps> = (props) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
interface DrawerLocationsProp {
|
type DrawerLocationsProp = {
|
||||||
stackName: string;
|
stackName: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
const DrawerLocations = ({ stackName }: DrawerLocationsProp) => {
|
const DrawerLocations = ({ stackName }: DrawerLocationsProp) => {
|
||||||
const navigation = useNavigation<DrawerNavigationHelpers>();
|
const navigation = useNavigation<DrawerNavigationHelpers>();
|
||||||
|
@ -64,7 +64,7 @@ const DrawerLocations = ({ stackName }: DrawerLocationsProp) => {
|
||||||
</View>
|
</View>
|
||||||
{/* Add Location */}
|
{/* Add Location */}
|
||||||
<Pressable onPress={() => importModalRef.current.present()}>
|
<Pressable onPress={() => importModalRef.current.present()}>
|
||||||
<View style={tw`border border-dashed rounded border-gray-450 border-opacity-60 mt-1`}>
|
<View style={tw`border border-dashed rounded border-app-line border-opacity-80 mt-1`}>
|
||||||
<Text style={tw`text-xs font-bold text-center text-gray-400 px-2 py-2`}>
|
<Text style={tw`text-xs font-bold text-center text-gray-400 px-2 py-2`}>
|
||||||
Add Location
|
Add Location
|
||||||
</Text>
|
</Text>
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { ColorValue, Pressable, Text, View } from 'react-native';
|
||||||
import tw from '~/lib/tailwind';
|
import tw from '~/lib/tailwind';
|
||||||
|
|
||||||
import CollapsibleView from '../../components/layout/CollapsibleView';
|
import CollapsibleView from '../../components/layout/CollapsibleView';
|
||||||
|
import CreateTagDialog from '../dialog/tag/CreateTagDialog';
|
||||||
|
|
||||||
type DrawerTagItemProps = {
|
type DrawerTagItemProps = {
|
||||||
tagName: string;
|
tagName: string;
|
||||||
|
@ -56,6 +57,12 @@ const DrawerTags = ({ stackName }: DrawerTagsProp) => {
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</View>
|
</View>
|
||||||
|
{/* Add Tag */}
|
||||||
|
<CreateTagDialog>
|
||||||
|
<View style={tw`border border-dashed rounded border-app-line border-opacity-80 mt-1`}>
|
||||||
|
<Text style={tw`text-xs font-bold text-center text-gray-400 px-2 py-2`}>Add Tag</Text>
|
||||||
|
</View>
|
||||||
|
</CreateTagDialog>
|
||||||
</CollapsibleView>
|
</CollapsibleView>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,10 +10,10 @@ import Divider from '../../components/primitive/Divider';
|
||||||
import tw from '../../lib/tailwind';
|
import tw from '../../lib/tailwind';
|
||||||
import { useFileModalStore } from '../../stores/modalStore';
|
import { useFileModalStore } from '../../stores/modalStore';
|
||||||
|
|
||||||
interface MetaItemProps {
|
type MetaItemProps = {
|
||||||
title: string;
|
title: string;
|
||||||
value: string;
|
value: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
function MetaItem({ title, value }: MetaItemProps) {
|
function MetaItem({ title, value }: MetaItemProps) {
|
||||||
return (
|
return (
|
||||||
|
@ -33,7 +33,7 @@ export const FileModal = () => {
|
||||||
<>
|
<>
|
||||||
<Modal ref={fileRef} snapPoints={['60%', '90%']}>
|
<Modal ref={fileRef} snapPoints={['60%', '90%']}>
|
||||||
{data && (
|
{data && (
|
||||||
<View style={tw`flex-1 p-4 bg-gray-600`}>
|
<View style={tw`flex-1 p-4 bg-app`}>
|
||||||
{/* File Icon / Name */}
|
{/* File Icon / Name */}
|
||||||
<View style={tw`flex flex-row items-center`}>
|
<View style={tw`flex flex-row items-center`}>
|
||||||
<FileIcon data={data} size={1.6} />
|
<FileIcon data={data} size={1.6} />
|
||||||
|
@ -48,7 +48,7 @@ export const FileModal = () => {
|
||||||
<Text style={tw`ml-1 text-xs text-gray-400`}>15 Aug</Text>
|
<Text style={tw`ml-1 text-xs text-gray-400`}>15 Aug</Text>
|
||||||
</View>
|
</View>
|
||||||
<Pressable style={tw`mt-2`} onPress={() => fileDetailsRef.current.present()}>
|
<Pressable style={tw`mt-2`} onPress={() => fileDetailsRef.current.present()}>
|
||||||
<Text style={tw`text-sm text-primary-500`}>More</Text>
|
<Text style={tw`text-sm text-accent`}>More</Text>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
@ -70,10 +70,10 @@ export const FileModal = () => {
|
||||||
snapPoints={['70%']}
|
snapPoints={['70%']}
|
||||||
>
|
>
|
||||||
{data && (
|
{data && (
|
||||||
<BottomSheetScrollView style={tw`flex-1 p-4 bg-gray-600`}>
|
<BottomSheetScrollView style={tw`flex-1 p-4 bg-app`}>
|
||||||
{/* Back Button */}
|
{/* Back Button */}
|
||||||
<Pressable style={tw`w-full ml-4`} onPress={() => fileDetailsRef.current.close()}>
|
<Pressable style={tw`w-full ml-4`} onPress={() => fileDetailsRef.current.close()}>
|
||||||
<CaretLeft color={tw.color('primary-500')} size={20} />
|
<CaretLeft color={tw.color('accent')} size={20} />
|
||||||
</Pressable>
|
</Pressable>
|
||||||
{/* File Icon / Name */}
|
{/* File Icon / Name */}
|
||||||
<View style={tw`items-center`}>
|
<View style={tw`items-center`}>
|
|
@ -10,14 +10,15 @@ import { Button } from '~/components/primitive/Button';
|
||||||
import useForwardedRef from '~/hooks/useForwardedRef';
|
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<BottomSheetModal, unknown>((_, ref) => {
|
||||||
const modalRef = useForwardedRef(ref);
|
const modalRef = useForwardedRef(ref);
|
||||||
|
|
||||||
const { mutate: createLocation } = useLibraryMutation('locations.create', {
|
const { mutate: createLocation } = useLibraryMutation('locations.create', {
|
||||||
onError: (error, variables, context) => {
|
onError: (error) => {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
},
|
},
|
||||||
onSettled: (data, error, variables, context) => {
|
onSettled: () => {
|
||||||
// Close the modal
|
// Close the modal
|
||||||
modalRef.current?.close();
|
modalRef.current?.close();
|
||||||
}
|
}
|
||||||
|
@ -89,7 +90,6 @@ const ImportModal = forwardRef<BottomSheetModal, unknown>((_, ref) => {
|
||||||
// Gets Actual Path
|
// Gets Actual Path
|
||||||
const path = (await ML.getAssetInfoAsync(assetId)).localUri;
|
const path = (await ML.getAssetInfoAsync(assetId)).localUri;
|
||||||
|
|
||||||
// Permission Granted
|
|
||||||
const libraryPath = Platform.select({
|
const libraryPath = Platform.select({
|
||||||
android: '',
|
android: '',
|
||||||
ios: path.replace('file://', '').split('Media/DCIM/')[0] + 'Media/DCIM/'
|
ios: path.replace('file://', '').split('Media/DCIM/')[0] + 'Media/DCIM/'
|
||||||
|
@ -100,10 +100,10 @@ const ImportModal = forwardRef<BottomSheetModal, unknown>((_, ref) => {
|
||||||
indexer_rules_ids: []
|
indexer_rules_ids: []
|
||||||
});
|
});
|
||||||
|
|
||||||
const assets = await ML.getAssetsAsync({ mediaType: ML.MediaType.photo });
|
// const assets = await ML.getAssetsAsync({ mediaType: ML.MediaType.photo });
|
||||||
assets.assets.map(async (i) => {
|
// assets.assets.map(async (i) => {
|
||||||
console.log((await ML.getAssetInfoAsync(i)).localUri);
|
// console.log((await ML.getAssetInfoAsync(i)).localUri);
|
||||||
});
|
// });
|
||||||
}, [createLocation]);
|
}, [createLocation]);
|
||||||
|
|
||||||
// const testFN = useCallback(async () => {
|
// const testFN = useCallback(async () => {
|
||||||
|
@ -126,14 +126,14 @@ const ImportModal = forwardRef<BottomSheetModal, unknown>((_, ref) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal ref={modalRef} snapPoints={['20%']}>
|
<Modal ref={modalRef} snapPoints={['20%']}>
|
||||||
<View style={tw`flex-1 px-6 pt-1 pb-2 bg-gray-600`}>
|
<View style={tw`flex-1 px-6 pt-1 pb-2 bg-app-box`}>
|
||||||
{/* <Button size="md" variant="primary" style={tw`my-2`} onPress={testFN}>
|
{/* <Button size="md" variant="accent" style={tw`my-2`} onPress={testFN}>
|
||||||
<Text>TEST</Text>
|
<Text>TEST</Text>
|
||||||
</Button> */}
|
</Button> */}
|
||||||
<Button size="md" variant="primary" style={tw`my-2`} onPress={handleFilesButton}>
|
<Button size="md" variant="accent" style={tw`my-2`} onPress={handleFilesButton}>
|
||||||
<Text>Import from Files</Text>
|
<Text>Import from Files</Text>
|
||||||
</Button>
|
</Button>
|
||||||
<Button size="md" variant="primary" onPress={handlePhotosButton}>
|
<Button size="md" variant="accent" onPress={handlePhotosButton}>
|
||||||
<Text>Import from Photos</Text>
|
<Text>Import from Photos</Text>
|
||||||
</Button>
|
</Button>
|
||||||
</View>
|
</View>
|
21
apps/mobile/src/hooks/useAutoForm.ts
Normal file
21
apps/mobile/src/hooks/useAutoForm.ts
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
import { FieldValues, UseFormReturn } from 'react-hook-form';
|
||||||
|
import { useDebouncedCallback } from 'use-debounce';
|
||||||
|
|
||||||
|
// Same as useDebouncedForm, just a bit more general to use it with all forms.
|
||||||
|
export function useAutoForm<TFieldValues extends FieldValues = FieldValues, TContext = any>(
|
||||||
|
form: UseFormReturn<TFieldValues, TContext>,
|
||||||
|
callback: (data: any) => void,
|
||||||
|
/**
|
||||||
|
*Wait time in miliseconds
|
||||||
|
*/
|
||||||
|
waitTime = 500
|
||||||
|
) {
|
||||||
|
const debounced = useDebouncedCallback(callback, waitTime);
|
||||||
|
|
||||||
|
// listen for any form changes
|
||||||
|
form.watch(debounced);
|
||||||
|
|
||||||
|
// persist unchanged data when the component is unmounted
|
||||||
|
useEffect(() => () => debounced.flush(), [debounced]);
|
||||||
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||||
import * as SplashScreen from 'expo-splash-screen';
|
import * as SplashScreen from 'expo-splash-screen';
|
||||||
import { lazy, useEffect } from 'react';
|
import { Suspense, lazy } from 'react';
|
||||||
import { Suspense } from 'react';
|
|
||||||
import { Platform } from 'react-native';
|
import { Platform } from 'react-native';
|
||||||
|
|
||||||
// Enable the splash screen
|
// Enable the splash screen
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { DrawerScreenProps, createDrawerNavigator } from '@react-navigation/draw
|
||||||
import { CompositeScreenProps, NavigatorScreenParams } from '@react-navigation/native';
|
import { CompositeScreenProps, NavigatorScreenParams } from '@react-navigation/native';
|
||||||
import { StackScreenProps } from '@react-navigation/stack';
|
import { StackScreenProps } from '@react-navigation/stack';
|
||||||
import DrawerContent from '~/containers/drawer/DrawerContent';
|
import DrawerContent from '~/containers/drawer/DrawerContent';
|
||||||
|
import tw from '~/lib/tailwind';
|
||||||
|
|
||||||
import type { RootStackParamList } from '.';
|
import type { RootStackParamList } from '.';
|
||||||
import type { TabParamList } from './TabNavigator';
|
import type { TabParamList } from './TabNavigator';
|
||||||
|
@ -16,7 +17,7 @@ export default function DrawerNavigator() {
|
||||||
screenOptions={{
|
screenOptions={{
|
||||||
headerShown: false,
|
headerShown: false,
|
||||||
drawerStyle: {
|
drawerStyle: {
|
||||||
backgroundColor: 'rgb(10,10,12)',
|
backgroundColor: tw.color('app-darkBox'),
|
||||||
width: '75%'
|
width: '75%'
|
||||||
},
|
},
|
||||||
overlayColor: 'transparent',
|
overlayColor: 'transparent',
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
/**
|
|
||||||
* Learn more about deep linking with React Navigation
|
|
||||||
* https://reactnavigation.org/docs/deep-linking
|
|
||||||
* https://reactnavigation.org/docs/configuring-links
|
|
||||||
*/
|
|
||||||
import { LinkingOptions } from '@react-navigation/native';
|
import { LinkingOptions } from '@react-navigation/native';
|
||||||
import * as Linking from 'expo-linking';
|
import * as Linking from 'expo-linking';
|
||||||
|
|
||||||
import { RootStackParamList } from '.';
|
import { RootStackParamList } from '.';
|
||||||
|
|
||||||
// TODO: Deep linking for React Navigation. It will allow us to do spacedrive://tags/{id} etc.
|
/**
|
||||||
|
* TODO: Deep linking for React Navigation. It will allow us to do spacedrive://tags/{id} etc.
|
||||||
|
* https://reactnavigation.org/docs/deep-linking
|
||||||
|
* https://reactnavigation.org/docs/configuring-links
|
||||||
|
*/
|
||||||
const linking: LinkingOptions<RootStackParamList> = {
|
const linking: LinkingOptions<RootStackParamList> = {
|
||||||
prefixes: [Linking.createURL('/')],
|
prefixes: [Linking.createURL('/')],
|
||||||
config: {
|
config: {
|
||||||
|
|
125
apps/mobile/src/navigation/SettingsNavigator.tsx
Normal file
125
apps/mobile/src/navigation/SettingsNavigator.tsx
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
import { StackScreenProps, createStackNavigator } from '@react-navigation/stack';
|
||||||
|
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';
|
||||||
|
import GeneralSettingsScreen from '~/screens/settings/client/GeneralSettings';
|
||||||
|
import LibrarySettingsScreen from '~/screens/settings/client/LibrarySettings';
|
||||||
|
import PrivacySettingsScreen from '~/screens/settings/client/PrivacySettings';
|
||||||
|
import AboutScreen from '~/screens/settings/info/About';
|
||||||
|
import SupportScreen from '~/screens/settings/info/Support';
|
||||||
|
import KeysSettingsScreen from '~/screens/settings/library/KeysSettings';
|
||||||
|
import LibraryGeneralSettingsScreen from '~/screens/settings/library/LibraryGeneralSettings';
|
||||||
|
import LocationSettingsScreen from '~/screens/settings/library/LocationSettings';
|
||||||
|
import NodesSettingsScreen from '~/screens/settings/library/NodesSettings';
|
||||||
|
import TagsSettingsScreen from '~/screens/settings/library/TagsSettings';
|
||||||
|
|
||||||
|
const SettingsStack = createStackNavigator<SettingsStackParamList>();
|
||||||
|
|
||||||
|
export default function SettingsNavigator() {
|
||||||
|
return (
|
||||||
|
<SettingsStack.Navigator
|
||||||
|
initialRouteName="Home"
|
||||||
|
screenOptions={{
|
||||||
|
headerBackTitleVisible: false,
|
||||||
|
headerStyle: tw`bg-app`,
|
||||||
|
headerTintColor: tw.color('ink'),
|
||||||
|
headerTitleStyle: tw`text-base`,
|
||||||
|
headerBackTitleStyle: tw`text-base`
|
||||||
|
// headerShadowVisible: false // will disable the white line under
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SettingsStack.Screen
|
||||||
|
name="Home"
|
||||||
|
component={SettingsScreen}
|
||||||
|
options={{ headerTitle: 'Settings' }}
|
||||||
|
/>
|
||||||
|
{/* Client */}
|
||||||
|
<SettingsStack.Screen
|
||||||
|
name="GeneralSettings"
|
||||||
|
component={GeneralSettingsScreen}
|
||||||
|
options={{ headerTitle: 'General Settings' }}
|
||||||
|
/>
|
||||||
|
<SettingsStack.Screen
|
||||||
|
name="LibrarySettings"
|
||||||
|
component={LibrarySettingsScreen}
|
||||||
|
options={{ headerTitle: 'Libraries' }}
|
||||||
|
/>
|
||||||
|
<SettingsStack.Screen
|
||||||
|
name="AppearanceSettings"
|
||||||
|
component={AppearanceSettingsScreen}
|
||||||
|
options={{ headerTitle: 'Appearance' }}
|
||||||
|
/>
|
||||||
|
<SettingsStack.Screen
|
||||||
|
name="PrivacySettings"
|
||||||
|
component={PrivacySettingsScreen}
|
||||||
|
options={{ headerTitle: 'Privacy' }}
|
||||||
|
/>
|
||||||
|
<SettingsStack.Screen
|
||||||
|
name="ExtensionsSettings"
|
||||||
|
component={ExtensionsSettingsScreen}
|
||||||
|
options={{ headerTitle: 'Extensions' }}
|
||||||
|
/>
|
||||||
|
{/* Library */}
|
||||||
|
<SettingsStack.Screen
|
||||||
|
name="LibraryGeneralSettings"
|
||||||
|
component={LibraryGeneralSettingsScreen}
|
||||||
|
options={{ headerTitle: 'Library Settings' }}
|
||||||
|
/>
|
||||||
|
<SettingsStack.Screen
|
||||||
|
name="LocationSettings"
|
||||||
|
component={LocationSettingsScreen}
|
||||||
|
options={{ headerTitle: 'Locations' }}
|
||||||
|
/>
|
||||||
|
<SettingsStack.Screen
|
||||||
|
name="NodesSettings"
|
||||||
|
component={NodesSettingsScreen}
|
||||||
|
options={{ headerTitle: 'Nodes' }}
|
||||||
|
/>
|
||||||
|
<SettingsStack.Screen
|
||||||
|
name="TagsSettings"
|
||||||
|
component={TagsSettingsScreen}
|
||||||
|
options={{ headerTitle: 'Tags' }}
|
||||||
|
/>
|
||||||
|
<SettingsStack.Screen
|
||||||
|
name="KeysSettings"
|
||||||
|
component={KeysSettingsScreen}
|
||||||
|
options={{ headerTitle: 'Keys' }}
|
||||||
|
/>
|
||||||
|
{/* Info */}
|
||||||
|
<SettingsStack.Screen
|
||||||
|
name="About"
|
||||||
|
component={AboutScreen}
|
||||||
|
options={{ headerTitle: 'About' }}
|
||||||
|
/>
|
||||||
|
<SettingsStack.Screen
|
||||||
|
name="Support"
|
||||||
|
component={SupportScreen}
|
||||||
|
options={{ headerTitle: 'Support' }}
|
||||||
|
/>
|
||||||
|
</SettingsStack.Navigator>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SettingsStackParamList = {
|
||||||
|
// Home screen for the Settings stack.
|
||||||
|
Home: undefined;
|
||||||
|
// Client
|
||||||
|
GeneralSettings: undefined;
|
||||||
|
LibrarySettings: undefined;
|
||||||
|
AppearanceSettings: undefined;
|
||||||
|
PrivacySettings: undefined;
|
||||||
|
ExtensionsSettings: undefined;
|
||||||
|
// Library
|
||||||
|
LibraryGeneralSettings: undefined;
|
||||||
|
LocationSettings: undefined;
|
||||||
|
NodesSettings: undefined;
|
||||||
|
TagsSettings: undefined;
|
||||||
|
KeysSettings: undefined;
|
||||||
|
// Info
|
||||||
|
About: undefined;
|
||||||
|
Support: undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SettingsStackScreenProps<Screen extends keyof SettingsStackParamList> =
|
||||||
|
StackScreenProps<SettingsStackParamList, Screen>;
|
|
@ -7,6 +7,7 @@ import {
|
||||||
import LocationScreen from '~/screens/Location';
|
import LocationScreen from '~/screens/Location';
|
||||||
import TagScreen from '~/screens/Tag';
|
import TagScreen from '~/screens/Tag';
|
||||||
|
|
||||||
|
// Mounted on all the tabs, so we can navigate to it from any tab
|
||||||
export function SharedScreens(
|
export function SharedScreens(
|
||||||
Stack: TypedNavigator<
|
Stack: TypedNavigator<
|
||||||
SharedScreensParamList,
|
SharedScreensParamList,
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import { BottomTabScreenProps, createBottomTabNavigator } from '@react-navigation/bottom-tabs';
|
import { BottomTabScreenProps, createBottomTabNavigator } from '@react-navigation/bottom-tabs';
|
||||||
import { CompositeScreenProps, NavigatorScreenParams } from '@react-navigation/native';
|
import { CompositeScreenProps, NavigatorScreenParams } from '@react-navigation/native';
|
||||||
import { Camera, CirclesFour, Folder, Planet } from 'phosphor-react-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 type { HomeDrawerScreenProps } from './DrawerNavigator';
|
||||||
import BrowseStack, { BrowseStackParamList } from './tabs/BrowseStack';
|
import NodesStack, { NodesStackParamList } from './tabs/NodesStack';
|
||||||
import OverviewStack, { OverviewStackParamList } from './tabs/OverviewStack';
|
import OverviewStack, { OverviewStackParamList } from './tabs/OverviewStack';
|
||||||
import PhotosStack, { PhotosStackParamList } from './tabs/PhotosStack';
|
|
||||||
import SpacesStack, { SpacesStackParamList } from './tabs/SpacesStack';
|
import SpacesStack, { SpacesStackParamList } from './tabs/SpacesStack';
|
||||||
|
|
||||||
const Tab = createBottomTabNavigator<TabParamList>();
|
const Tab = createBottomTabNavigator<TabParamList>();
|
||||||
|
@ -17,11 +17,11 @@ export default function TabNavigator() {
|
||||||
initialRouteName="OverviewStack"
|
initialRouteName="OverviewStack"
|
||||||
screenOptions={{
|
screenOptions={{
|
||||||
headerShown: false,
|
headerShown: false,
|
||||||
tabBarActiveTintColor: tw.color('primary'),
|
tabBarActiveTintColor: tw.color('accent'),
|
||||||
tabBarInactiveTintColor: 'white',
|
tabBarInactiveTintColor: tw.color('ink'),
|
||||||
tabBarStyle: {
|
tabBarStyle: {
|
||||||
backgroundColor: tw.color('gray-650'),
|
backgroundColor: tw.color('app'),
|
||||||
borderTopColor: tw.color('gray-600')
|
borderTopColor: tw.color('app-shade')
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -30,19 +30,29 @@ export default function TabNavigator() {
|
||||||
component={OverviewStack}
|
component={OverviewStack}
|
||||||
options={{
|
options={{
|
||||||
tabBarIcon: ({ focused }) => (
|
tabBarIcon: ({ focused }) => (
|
||||||
<Planet size={22} weight="bold" color={focused ? tw.color('bg-primary') : 'white'} />
|
<Planet
|
||||||
|
size={22}
|
||||||
|
weight={focused ? 'bold' : 'regular'}
|
||||||
|
color={focused ? tw.color('accent') : tw.color('ink')}
|
||||||
|
/>
|
||||||
),
|
),
|
||||||
tabBarLabel: 'Overview'
|
tabBarLabel: 'Overview',
|
||||||
|
tabBarLabelStyle: tw`font-semibold text-tiny`
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Tab.Screen
|
<Tab.Screen
|
||||||
name="BrowseStack"
|
name="NodesStack"
|
||||||
component={BrowseStack}
|
component={NodesStack}
|
||||||
options={{
|
options={{
|
||||||
tabBarIcon: ({ focused }) => (
|
tabBarIcon: ({ focused }) => (
|
||||||
<Folder size={22} weight="bold" color={focused ? tw.color('bg-primary') : 'white'} />
|
<ShareNetwork
|
||||||
|
size={22}
|
||||||
|
weight={focused ? 'bold' : 'regular'}
|
||||||
|
color={focused ? tw.color('accent') : tw.color('ink')}
|
||||||
|
/>
|
||||||
),
|
),
|
||||||
tabBarLabel: 'Browse'
|
tabBarLabel: 'Nodes',
|
||||||
|
tabBarLabelStyle: tw`font-semibold text-tiny`
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Tab.Screen
|
<Tab.Screen
|
||||||
|
@ -52,21 +62,12 @@ export default function TabNavigator() {
|
||||||
tabBarIcon: ({ focused }) => (
|
tabBarIcon: ({ focused }) => (
|
||||||
<CirclesFour
|
<CirclesFour
|
||||||
size={22}
|
size={22}
|
||||||
weight="bold"
|
weight={focused ? 'bold' : 'regular'}
|
||||||
color={focused ? tw.color('bg-primary') : 'white'}
|
color={focused ? tw.color('accent') : tw.color('ink')}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
tabBarLabel: 'Spaces'
|
tabBarLabel: 'Spaces',
|
||||||
}}
|
tabBarLabelStyle: tw`font-semibold text-tiny`
|
||||||
/>
|
|
||||||
<Tab.Screen
|
|
||||||
name="PhotosStack"
|
|
||||||
component={PhotosStack}
|
|
||||||
options={{
|
|
||||||
tabBarIcon: ({ focused }) => (
|
|
||||||
<Camera size={22} weight="bold" color={focused ? tw.color('bg-primary') : 'white'} />
|
|
||||||
),
|
|
||||||
tabBarLabel: 'Photos'
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Tab.Navigator>
|
</Tab.Navigator>
|
||||||
|
@ -75,9 +76,8 @@ export default function TabNavigator() {
|
||||||
|
|
||||||
export type TabParamList = {
|
export type TabParamList = {
|
||||||
OverviewStack: NavigatorScreenParams<OverviewStackParamList>;
|
OverviewStack: NavigatorScreenParams<OverviewStackParamList>;
|
||||||
BrowseStack: NavigatorScreenParams<BrowseStackParamList>;
|
NodesStack: NavigatorScreenParams<NodesStackParamList>;
|
||||||
SpacesStack: NavigatorScreenParams<SpacesStackParamList>;
|
SpacesStack: NavigatorScreenParams<SpacesStackParamList>;
|
||||||
PhotosStack: NavigatorScreenParams<PhotosStackParamList>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TabScreenProps<Screen extends keyof TabParamList> = CompositeScreenProps<
|
export type TabScreenProps<Screen extends keyof TabParamList> = CompositeScreenProps<
|
||||||
|
|
|
@ -2,11 +2,11 @@ import { NavigatorScreenParams } from '@react-navigation/native';
|
||||||
import { StackScreenProps, createStackNavigator } from '@react-navigation/stack';
|
import { StackScreenProps, createStackNavigator } from '@react-navigation/stack';
|
||||||
import tw from '~/lib/tailwind';
|
import tw from '~/lib/tailwind';
|
||||||
import NotFoundScreen from '~/screens/NotFound';
|
import NotFoundScreen from '~/screens/NotFound';
|
||||||
import SearchScreen from '~/screens/modals/Search';
|
import SearchScreen from '~/screens/Search';
|
||||||
import SettingsScreen from '~/screens/modals/settings/Settings';
|
|
||||||
|
|
||||||
import type { DrawerNavParamList } from './DrawerNavigator';
|
import type { DrawerNavParamList } from './DrawerNavigator';
|
||||||
import DrawerNavigator from './DrawerNavigator';
|
import DrawerNavigator from './DrawerNavigator';
|
||||||
|
import SettingsNavigator, { SettingsStackParamList } from './SettingsNavigator';
|
||||||
|
|
||||||
const Stack = createStackNavigator<RootStackParamList>();
|
const Stack = createStackNavigator<RootStackParamList>();
|
||||||
|
|
||||||
|
@ -24,16 +24,17 @@ export default function RootNavigator() {
|
||||||
{/* Modals */}
|
{/* Modals */}
|
||||||
<Stack.Group
|
<Stack.Group
|
||||||
screenOptions={{
|
screenOptions={{
|
||||||
|
headerShown: false,
|
||||||
presentation: 'modal',
|
presentation: 'modal',
|
||||||
headerBackTitleVisible: false,
|
headerBackTitleVisible: false,
|
||||||
headerStyle: tw`bg-gray-650`,
|
headerStyle: tw`bg-app`,
|
||||||
headerTintColor: tw.color('gray-200'),
|
headerTintColor: tw.color('ink'),
|
||||||
headerTitleStyle: tw`text-base`,
|
headerTitleStyle: tw`text-base`,
|
||||||
headerBackTitleStyle: tw`text-base`
|
headerBackTitleStyle: tw`text-base`
|
||||||
// headerShadowVisible: false // will disable the white line under
|
// headerShadowVisible: false // will disable the white line under
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Stack.Screen name="Settings" component={SettingsScreen} />
|
<Stack.Screen name="Settings" component={SettingsNavigator} />
|
||||||
</Stack.Group>
|
</Stack.Group>
|
||||||
</Stack.Navigator>
|
</Stack.Navigator>
|
||||||
);
|
);
|
||||||
|
@ -44,7 +45,7 @@ export type RootStackParamList = {
|
||||||
NotFound: undefined;
|
NotFound: undefined;
|
||||||
// Modals
|
// Modals
|
||||||
Search: undefined;
|
Search: undefined;
|
||||||
Settings: undefined;
|
Settings: NavigatorScreenParams<SettingsStackParamList>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type RootStackScreenProps<Screen extends keyof RootStackParamList> = StackScreenProps<
|
export type RootStackScreenProps<Screen extends keyof RootStackParamList> = StackScreenProps<
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
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 BrowseScreen from '~/screens/Browse';
|
|
||||||
|
|
||||||
import { SharedScreens, SharedScreensParamList } from '../SharedScreens';
|
|
||||||
import { TabScreenProps } from '../TabNavigator';
|
|
||||||
|
|
||||||
const Stack = createStackNavigator<BrowseStackParamList>();
|
|
||||||
|
|
||||||
export default function BrowseStack() {
|
|
||||||
return (
|
|
||||||
<Stack.Navigator
|
|
||||||
initialRouteName="Browse"
|
|
||||||
screenOptions={{
|
|
||||||
headerStyle: { backgroundColor: tw.color('gray-650') },
|
|
||||||
headerTintColor: tw.color('gray-200'),
|
|
||||||
headerTitleStyle: tw`text-base`,
|
|
||||||
headerBackTitleStyle: tw`text-base`
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Stack.Screen name="Browse" component={BrowseScreen} options={{ header: Header }} />
|
|
||||||
{SharedScreens(Stack as any)}
|
|
||||||
</Stack.Navigator>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export type BrowseStackParamList = {
|
|
||||||
Browse: undefined;
|
|
||||||
} & SharedScreensParamList;
|
|
||||||
|
|
||||||
export type BrowseStackScreenProps<Screen extends keyof BrowseStackParamList> =
|
|
||||||
CompositeScreenProps<
|
|
||||||
StackScreenProps<BrowseStackParamList, Screen>,
|
|
||||||
TabScreenProps<'BrowseStack'>
|
|
||||||
>;
|
|
36
apps/mobile/src/navigation/tabs/NodesStack.tsx
Normal file
36
apps/mobile/src/navigation/tabs/NodesStack.tsx
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
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 NodesScreen from '~/screens/Nodes';
|
||||||
|
|
||||||
|
import { SharedScreens, SharedScreensParamList } from '../SharedScreens';
|
||||||
|
import { TabScreenProps } from '../TabNavigator';
|
||||||
|
|
||||||
|
const Stack = createStackNavigator<NodesStackParamList>();
|
||||||
|
|
||||||
|
export default function NodesStack() {
|
||||||
|
return (
|
||||||
|
<Stack.Navigator
|
||||||
|
initialRouteName="Nodes"
|
||||||
|
screenOptions={{
|
||||||
|
headerStyle: { backgroundColor: tw.color('app-box') },
|
||||||
|
headerTintColor: tw.color('ink'),
|
||||||
|
headerTitleStyle: tw`text-base`,
|
||||||
|
headerBackTitleStyle: tw`text-base`
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Stack.Screen name="Nodes" component={NodesScreen} options={{ header: Header }} />
|
||||||
|
{SharedScreens(Stack as any)}
|
||||||
|
</Stack.Navigator>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export type NodesStackParamList = {
|
||||||
|
Nodes: undefined;
|
||||||
|
} & SharedScreensParamList;
|
||||||
|
|
||||||
|
export type NodesStackScreenProps<Screen extends keyof NodesStackParamList> = CompositeScreenProps<
|
||||||
|
StackScreenProps<NodesStackParamList, Screen>,
|
||||||
|
TabScreenProps<'NodesStack'>
|
||||||
|
>;
|
|
@ -14,8 +14,8 @@ export default function OverviewStack() {
|
||||||
<Stack.Navigator
|
<Stack.Navigator
|
||||||
initialRouteName="Overview"
|
initialRouteName="Overview"
|
||||||
screenOptions={{
|
screenOptions={{
|
||||||
headerStyle: { backgroundColor: tw.color('gray-650') },
|
headerStyle: { backgroundColor: tw.color('app-box') },
|
||||||
headerTintColor: tw.color('gray-200'),
|
headerTintColor: tw.color('ink'),
|
||||||
headerTitleStyle: tw`text-base`,
|
headerTitleStyle: tw`text-base`,
|
||||||
headerBackTitleStyle: tw`text-base`
|
headerBackTitleStyle: tw`text-base`
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
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 PhotosScreen from '../../screens/Photos';
|
|
||||||
import { SharedScreens, SharedScreensParamList } from '../SharedScreens';
|
|
||||||
import { TabScreenProps } from '../TabNavigator';
|
|
||||||
|
|
||||||
const Stack = createStackNavigator<PhotosStackParamList>();
|
|
||||||
|
|
||||||
export default function PhotosStack() {
|
|
||||||
return (
|
|
||||||
<Stack.Navigator
|
|
||||||
initialRouteName="Photos"
|
|
||||||
screenOptions={{
|
|
||||||
headerStyle: { backgroundColor: tw.color('gray-650') },
|
|
||||||
headerTintColor: tw.color('gray-200'),
|
|
||||||
headerTitleStyle: tw`text-base`,
|
|
||||||
headerBackTitleStyle: tw`text-base`
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Stack.Screen name="Photos" component={PhotosScreen} options={{ header: Header }} />
|
|
||||||
{SharedScreens(Stack as any)}
|
|
||||||
</Stack.Navigator>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export type PhotosStackParamList = {
|
|
||||||
Photos: undefined;
|
|
||||||
} & SharedScreensParamList;
|
|
||||||
|
|
||||||
export type PhotosStackScreenProps<Screen extends keyof PhotosStackParamList> =
|
|
||||||
CompositeScreenProps<
|
|
||||||
StackScreenProps<PhotosStackParamList, Screen>,
|
|
||||||
TabScreenProps<'PhotosStack'>
|
|
||||||
>;
|
|
|
@ -14,8 +14,8 @@ export default function SpacesStack() {
|
||||||
<Stack.Navigator
|
<Stack.Navigator
|
||||||
initialRouteName="Spaces"
|
initialRouteName="Spaces"
|
||||||
screenOptions={{
|
screenOptions={{
|
||||||
headerStyle: { backgroundColor: tw.color('gray-650') },
|
headerStyle: { backgroundColor: tw.color('app-box') },
|
||||||
headerTintColor: tw.color('gray-200'),
|
headerTintColor: tw.color('ink'),
|
||||||
headerTitleStyle: tw`text-base`,
|
headerTitleStyle: tw`text-base`,
|
||||||
headerBackTitleStyle: tw`text-base`
|
headerBackTitleStyle: tw`text-base`
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -1,77 +0,0 @@
|
||||||
import { ColorValue, Text, View } from 'react-native';
|
|
||||||
import CollapsibleView from '~/components/layout/CollapsibleView';
|
|
||||||
import BrowseLocationItem from '~/containers/browse/BrowseLocationItem';
|
|
||||||
import BrowseTagItem from '~/containers/browse/BrowseTagItem';
|
|
||||||
import tw from '~/lib/tailwind';
|
|
||||||
import { BrowseStackScreenProps } from '~/navigation/tabs/BrowseStack';
|
|
||||||
|
|
||||||
const placeholderLocationData = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
name: 'Spacedrive'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
name: 'Classified'
|
|
||||||
}
|
|
||||||
];
|
|
||||||
const placeholderTagsData = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
name: 'Secret',
|
|
||||||
color: tw.color('blue-500')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
name: 'OBS',
|
|
||||||
color: tw.color('purple-500')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
name: 'BlackMagic',
|
|
||||||
color: tw.color('red-500')
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
// Will refactor this soon
|
|
||||||
const BrowseScreen = ({ navigation }: BrowseStackScreenProps<'Browse'>) => {
|
|
||||||
return (
|
|
||||||
<View style={tw`flex-1 p-4`}>
|
|
||||||
<CollapsibleView
|
|
||||||
title="Locations"
|
|
||||||
titleStyle={tw`mt-5 mb-3 ml-1 text-base font-semibold text-gray-300`}
|
|
||||||
>
|
|
||||||
{placeholderLocationData.map((location) => (
|
|
||||||
<BrowseLocationItem
|
|
||||||
key={location.id}
|
|
||||||
folderName={location.name}
|
|
||||||
onPress={() => navigation.navigate('Location', { id: location.id })}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
{/* Add Location */}
|
|
||||||
<View style={tw`border border-dashed rounded border-gray-450 border-opacity-60 mt-1`}>
|
|
||||||
<Text style={tw`text-xs font-bold text-center text-gray-400 px-2 py-2`}>
|
|
||||||
Add Location
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
</CollapsibleView>
|
|
||||||
{/* Tags */}
|
|
||||||
<View style={tw`mt-8`} />
|
|
||||||
<CollapsibleView
|
|
||||||
title="Tags"
|
|
||||||
titleStyle={tw`mt-5 mb-3 ml-1 text-base font-semibold text-gray-300`}
|
|
||||||
>
|
|
||||||
{placeholderTagsData.map((tag) => (
|
|
||||||
<BrowseTagItem
|
|
||||||
key={tag.id}
|
|
||||||
tagName={tag.name}
|
|
||||||
onPress={() => navigation.navigate('Tag', { id: tag.id })}
|
|
||||||
tagColor={tag.color as ColorValue}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</CollapsibleView>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default BrowseScreen;
|
|
11
apps/mobile/src/screens/Nodes.tsx
Normal file
11
apps/mobile/src/screens/Nodes.tsx
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import { Text, View } from 'react-native';
|
||||||
|
import tw from '~/lib/tailwind';
|
||||||
|
import { NodesStackScreenProps } from '~/navigation/tabs/NodesStack';
|
||||||
|
|
||||||
|
export default function NodesScreen({ navigation }: NodesStackScreenProps<'Nodes'>) {
|
||||||
|
return (
|
||||||
|
<View style={tw`flex-1 items-center justify-center`}>
|
||||||
|
<Text style={tw`font-bold text-xl text-ink`}>Nodes</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
|
@ -7,7 +7,7 @@ export default function NotFoundScreen({ navigation }: RootStackScreenProps<'Not
|
||||||
<View style={tw`flex-1 items-center justify-center p-5`}>
|
<View style={tw`flex-1 items-center justify-center p-5`}>
|
||||||
<Text style={tw`font-bold text-xl`}>This screen doesn't exist.</Text>
|
<Text style={tw`font-bold text-xl`}>This screen doesn't exist.</Text>
|
||||||
<TouchableOpacity onPress={() => navigation.replace('Root')} style={tw`mt-4 py-4`}>
|
<TouchableOpacity onPress={() => navigation.replace('Root')} style={tw`mt-4 py-4`}>
|
||||||
<Text style={tw`text-sm text-gray-250`}>Go to home screen!</Text>
|
<Text style={tw`text-sm text-ink-dull`}>Go to home screen!</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
import { Text, View } from 'react-native';
|
|
||||||
import tw from '~/lib/tailwind';
|
|
||||||
import { PhotosStackScreenProps } from '~/navigation/tabs/PhotosStack';
|
|
||||||
|
|
||||||
export default function PhotosScreen({ navigation }: PhotosStackScreenProps<'Photos'>) {
|
|
||||||
return (
|
|
||||||
<View style={tw`flex-1 items-center justify-center`}>
|
|
||||||
<Text style={tw`font-bold text-xl text-white`}>Photos</Text>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -18,23 +18,21 @@ const SearchScreen = ({ navigation }: RootStackScreenProps<'Search'>) => {
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<View style={tw`flex flex-row items-center mx-4`}>
|
<View style={tw`flex flex-row items-center mx-4`}>
|
||||||
{/* Search Input */}
|
{/* Search Input */}
|
||||||
<View
|
<View style={tw`flex-1 bg-app-overlay border border-app-line rounded h-10 mr-3`}>
|
||||||
style={tw`flex-1 bg-gray-500 border border-[#333949] bg-opacity-40 rounded h-10 mr-3`}
|
|
||||||
>
|
|
||||||
<View style={tw`flex flex-row h-full items-center px-3`}>
|
<View style={tw`flex flex-row h-full items-center px-3`}>
|
||||||
<View style={tw`mr-3`}>
|
<View style={tw`mr-3`}>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<ActivityIndicator size={'small'} color={'white'} />
|
<ActivityIndicator size={'small'} color={'white'} />
|
||||||
) : (
|
) : (
|
||||||
<MagnifyingGlass size={20} weight="light" color={tw.color('gray-300')} />
|
<MagnifyingGlass size={20} weight="light" color={tw.color('ink-faint')} />
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
<TextInput
|
<TextInput
|
||||||
placeholder={'Search'}
|
placeholder={'Search'}
|
||||||
clearButtonMode="never" // can't change the color??
|
clearButtonMode="never" // can't change the color??
|
||||||
underlineColorAndroid="transparent"
|
underlineColorAndroid="transparent"
|
||||||
placeholderTextColor={tw.color('gray-300')}
|
placeholderTextColor={tw.color('ink-dull')}
|
||||||
style={tw`flex-1 text-gray-300 font-medium text-sm`}
|
style={tw`flex-1 text-ink font-medium text-sm`}
|
||||||
textContentType={'none'}
|
textContentType={'none'}
|
||||||
autoFocus
|
autoFocus
|
||||||
autoCapitalize="none"
|
autoCapitalize="none"
|
||||||
|
@ -44,12 +42,12 @@ const SearchScreen = ({ navigation }: RootStackScreenProps<'Search'>) => {
|
||||||
</View>
|
</View>
|
||||||
{/* Cancel Button */}
|
{/* Cancel Button */}
|
||||||
<Pressable onPress={() => navigation.goBack()}>
|
<Pressable onPress={() => navigation.goBack()}>
|
||||||
<Text style={tw`text-primary-500`}>Cancel</Text>
|
<Text style={tw`text-accent`}>Cancel</Text>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
</View>
|
</View>
|
||||||
{/* Content */}
|
{/* Content */}
|
||||||
<View style={tw`flex-1 items-center mt-8`}>
|
<View style={tw`flex-1 items-center mt-8`}>
|
||||||
<Button variant="primary" onPress={() => setLoading((v) => !v)}>
|
<Button variant="accent" onPress={() => setLoading((v) => !v)}>
|
||||||
<Text>Toggle loading</Text>
|
<Text>Toggle loading</Text>
|
||||||
</Button>
|
</Button>
|
||||||
</View>
|
</View>
|
|
@ -5,7 +5,7 @@ import { SpacesStackScreenProps } from '~/navigation/tabs/SpacesStack';
|
||||||
export default function SpacesScreen({ navigation }: SpacesStackScreenProps<'Spaces'>) {
|
export default function SpacesScreen({ navigation }: SpacesStackScreenProps<'Spaces'>) {
|
||||||
return (
|
return (
|
||||||
<View style={tw`items-center justify-center flex-1`}>
|
<View style={tw`items-center justify-center flex-1`}>
|
||||||
<Text style={tw`text-xl font-bold text-white`}>Spaces</Text>
|
<Text style={tw`text-xl font-bold text-ink`}>Spaces</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ export default function TagScreen({ navigation, route }: SharedScreenProps<'Tag'
|
||||||
const { id } = route.params;
|
const { id } = route.params;
|
||||||
return (
|
return (
|
||||||
<View style={tw`flex-1 items-center justify-center`}>
|
<View style={tw`flex-1 items-center justify-center`}>
|
||||||
<Text style={tw`font-bold text-xl text-white`}>Tag {id}</Text>
|
<Text style={tw`font-bold text-xl text-ink`}>Tag {id}</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
import { Text, View } from 'react-native';
|
|
||||||
import tw from '~/lib/tailwind';
|
|
||||||
import { RootStackScreenProps } from '~/navigation';
|
|
||||||
|
|
||||||
export default function SettingsScreen({ navigation }: RootStackScreenProps<'Settings'>) {
|
|
||||||
return (
|
|
||||||
<View style={tw`flex-1 items-center justify-center`}>
|
|
||||||
<Text style={tw`font-bold text-xl text-white`}>Settings</Text>
|
|
||||||
<View style={tw`my-8 h-1 w-4/5`} />
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { Text, View } from 'react-native';
|
import { Text, View } from 'react-native';
|
||||||
import { useSnapshot } from 'valtio';
|
|
||||||
import { AnimatedButton } from '~/components/primitive/Button';
|
import { AnimatedButton } from '~/components/primitive/Button';
|
||||||
import CreateLibraryDialog from '~/containers/dialog/CreateLibraryDialog';
|
import CreateLibraryDialog from '~/containers/dialog/CreateLibraryDialog';
|
||||||
import tw from '~/lib/tailwind';
|
import tw from '~/lib/tailwind';
|
||||||
|
@ -7,13 +6,13 @@ import { OnboardingStackScreenProps } from '~/navigation/OnboardingNavigator';
|
||||||
|
|
||||||
const CreateLibraryScreen = ({ navigation }: OnboardingStackScreenProps<'CreateLibrary'>) => {
|
const CreateLibraryScreen = ({ navigation }: OnboardingStackScreenProps<'CreateLibrary'>) => {
|
||||||
return (
|
return (
|
||||||
<View style={tw`flex-1 items-center justify-center bg-gray-650 p-4`}>
|
<View style={tw`flex-1 items-center justify-center bg-app p-4`}>
|
||||||
<Text style={tw`text-gray-450 text-center px-6 my-8 text-base leading-relaxed`}>
|
<Text style={tw`text-ink-dull text-center px-6 my-8 text-base leading-relaxed`}>
|
||||||
Onboarding screen for users to create their first library
|
Onboarding screen for users to create their first library
|
||||||
</Text>
|
</Text>
|
||||||
<CreateLibraryDialog disableBackdropClose>
|
<CreateLibraryDialog disableBackdropClose>
|
||||||
<AnimatedButton disabled variant="primary">
|
<AnimatedButton variant="accent">
|
||||||
<Text style={tw`text-white text-center px-6 py-2 text-base font-medium`}>
|
<Text style={tw`text-ink text-center px-6 py-2 text-base font-medium`}>
|
||||||
Create Library
|
Create Library
|
||||||
</Text>
|
</Text>
|
||||||
</AnimatedButton>
|
</AnimatedButton>
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { OnboardingStackScreenProps } from '~/navigation/OnboardingNavigator';
|
||||||
|
|
||||||
const OnboardingScreen = ({ navigation }: OnboardingStackScreenProps<'Onboarding'>) => {
|
const OnboardingScreen = ({ navigation }: OnboardingStackScreenProps<'Onboarding'>) => {
|
||||||
return (
|
return (
|
||||||
<View style={tw`flex-1 items-center justify-around bg-gray-650 p-4 z-10`}>
|
<View style={tw`flex-1 items-center justify-around bg-app p-4 z-10`}>
|
||||||
{/* Logo */}
|
{/* Logo */}
|
||||||
<LogoAnimation>
|
<LogoAnimation>
|
||||||
<View style={tw`items-center mt-2`}>
|
<View style={tw`items-center mt-2`}>
|
||||||
|
@ -16,12 +16,12 @@ const OnboardingScreen = ({ navigation }: OnboardingStackScreenProps<'Onboarding
|
||||||
{/* Text */}
|
{/* Text */}
|
||||||
<View>
|
<View>
|
||||||
<FadeInUpAnimation delay={500}>
|
<FadeInUpAnimation delay={500}>
|
||||||
<Text style={tw`text-white text-center text-5xl font-black leading-tight`}>
|
<Text style={tw`text-ink text-center text-5xl font-black leading-tight`}>
|
||||||
A file explorer from the future.
|
A file explorer from the future.
|
||||||
</Text>
|
</Text>
|
||||||
</FadeInUpAnimation>
|
</FadeInUpAnimation>
|
||||||
<FadeInUpAnimation delay={800}>
|
<FadeInUpAnimation delay={800}>
|
||||||
<Text style={tw`text-gray-450 text-center px-6 mt-8 text-base leading-relaxed`}>
|
<Text style={tw`text-ink-dull text-center px-6 mt-8 text-base leading-relaxed`}>
|
||||||
Combine your drives and clouds into one database that you can organize and explore from
|
Combine your drives and clouds into one database that you can organize and explore from
|
||||||
any device.
|
any device.
|
||||||
</Text>
|
</Text>
|
||||||
|
@ -29,10 +29,8 @@ const OnboardingScreen = ({ navigation }: OnboardingStackScreenProps<'Onboarding
|
||||||
</View>
|
</View>
|
||||||
{/* Get Started Button */}
|
{/* Get Started Button */}
|
||||||
<FadeInUpAnimation delay={1200}>
|
<FadeInUpAnimation delay={1200}>
|
||||||
<AnimatedButton variant="primary" onPress={() => navigation.navigate('CreateLibrary')}>
|
<AnimatedButton variant="accent" onPress={() => navigation.navigate('CreateLibrary')}>
|
||||||
<Text style={tw`text-white text-center px-6 py-2 text-base font-medium`}>
|
<Text style={tw`text-ink text-center px-6 py-2 text-base font-medium`}>Get Started</Text>
|
||||||
Get Started
|
|
||||||
</Text>
|
|
||||||
</AnimatedButton>
|
</AnimatedButton>
|
||||||
</FadeInUpAnimation>
|
</FadeInUpAnimation>
|
||||||
</View>
|
</View>
|
||||||
|
|
148
apps/mobile/src/screens/settings/Settings.tsx
Normal file
148
apps/mobile/src/screens/settings/Settings.tsx
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
import {
|
||||||
|
Books,
|
||||||
|
FlyingSaucer,
|
||||||
|
GearSix,
|
||||||
|
HardDrive,
|
||||||
|
Heart,
|
||||||
|
Icon,
|
||||||
|
Key,
|
||||||
|
PaintBrush,
|
||||||
|
PuzzlePiece,
|
||||||
|
ShareNetwork,
|
||||||
|
ShieldCheck,
|
||||||
|
TagSimple
|
||||||
|
} from 'phosphor-react-native';
|
||||||
|
import React from 'react';
|
||||||
|
import { SectionList, Text, View } from 'react-native';
|
||||||
|
import { SettingsItem, SettingsItemDivider } from '~/components/settings/SettingsItem';
|
||||||
|
import tw from '~/lib/tailwind';
|
||||||
|
import { SettingsStackParamList, SettingsStackScreenProps } from '~/navigation/SettingsNavigator';
|
||||||
|
|
||||||
|
type SectionType = {
|
||||||
|
title: string;
|
||||||
|
data: {
|
||||||
|
title: string;
|
||||||
|
icon: Icon;
|
||||||
|
navigateTo: keyof SettingsStackParamList;
|
||||||
|
}[];
|
||||||
|
};
|
||||||
|
|
||||||
|
const sections: SectionType[] = [
|
||||||
|
{
|
||||||
|
title: 'Client',
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
icon: GearSix,
|
||||||
|
navigateTo: 'GeneralSettings',
|
||||||
|
title: 'General'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: Books,
|
||||||
|
navigateTo: 'LibrarySettings',
|
||||||
|
title: 'Libraries'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: PaintBrush,
|
||||||
|
navigateTo: 'AppearanceSettings',
|
||||||
|
title: 'Appearance'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: ShieldCheck,
|
||||||
|
navigateTo: 'PrivacySettings',
|
||||||
|
title: 'Privacy'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: PuzzlePiece,
|
||||||
|
navigateTo: 'ExtensionsSettings',
|
||||||
|
title: 'Extensions'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Library',
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
icon: GearSix,
|
||||||
|
navigateTo: 'LibraryGeneralSettings',
|
||||||
|
title: 'General'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: HardDrive,
|
||||||
|
navigateTo: 'LocationSettings',
|
||||||
|
title: 'Locations'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: ShareNetwork,
|
||||||
|
navigateTo: 'NodesSettings',
|
||||||
|
title: 'Nodes'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: TagSimple,
|
||||||
|
navigateTo: 'TagsSettings',
|
||||||
|
title: 'Tags'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: Key,
|
||||||
|
navigateTo: 'KeysSettings',
|
||||||
|
title: 'Keys'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Resources',
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
icon: FlyingSaucer,
|
||||||
|
navigateTo: 'About',
|
||||||
|
title: 'About'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: Heart,
|
||||||
|
navigateTo: 'Support',
|
||||||
|
title: 'Support'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
function renderSectionHeader({ section }: { section: { title: string } }) {
|
||||||
|
return (
|
||||||
|
<Text
|
||||||
|
style={tw.style(
|
||||||
|
'mb-2 ml-2 text-sm font-semibold text-ink-dull',
|
||||||
|
section.title === 'Client' ? 'mt-2' : 'mt-5'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{section.title}
|
||||||
|
</Text>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function SettingsScreen({ navigation }: SettingsStackScreenProps<'Home'>) {
|
||||||
|
return (
|
||||||
|
<View style={tw`flex-1`}>
|
||||||
|
<SectionList
|
||||||
|
sections={sections}
|
||||||
|
contentContainerStyle={tw`py-4`}
|
||||||
|
ItemSeparatorComponent={SettingsItemDivider}
|
||||||
|
renderItem={({ item }) => (
|
||||||
|
<SettingsItem
|
||||||
|
title={item.title}
|
||||||
|
leftIcon={item.icon}
|
||||||
|
onPress={() => navigation.navigate(item.navigateTo)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
renderSectionHeader={renderSectionHeader}
|
||||||
|
ListFooterComponent={
|
||||||
|
<View style={tw`items-center mt-6 mb-4`}>
|
||||||
|
<Text style={tw`text-sm font-bold text-ink`}>Spacedrive</Text>
|
||||||
|
<Text style={tw`text-ink-dull text-xs mt-0.5`}>v0.1.0</Text>
|
||||||
|
</View>
|
||||||
|
}
|
||||||
|
showsVerticalScrollIndicator={false}
|
||||||
|
stickySectionHeadersEnabled={false}
|
||||||
|
initialNumToRender={50}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Text, View } from 'react-native';
|
||||||
|
import tw from '~/lib/tailwind';
|
||||||
|
import { SettingsStackScreenProps } from '~/navigation/SettingsNavigator';
|
||||||
|
|
||||||
|
const AppearanceSettingsScreen = ({
|
||||||
|
navigation
|
||||||
|
}: SettingsStackScreenProps<'AppearanceSettings'>) => {
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<Text style={tw`text-ink`}>TODO: Theme Switch</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AppearanceSettingsScreen;
|
|
@ -0,0 +1,16 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Text, View } from 'react-native';
|
||||||
|
import tw from '~/lib/tailwind';
|
||||||
|
import { SettingsStackScreenProps } from '~/navigation/SettingsNavigator';
|
||||||
|
|
||||||
|
const ExtensionsSettingsScreen = ({
|
||||||
|
navigation
|
||||||
|
}: SettingsStackScreenProps<'ExtensionsSettings'>) => {
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<Text style={tw`text-ink`}>TODO</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ExtensionsSettingsScreen;
|
44
apps/mobile/src/screens/settings/client/GeneralSettings.tsx
Normal file
44
apps/mobile/src/screens/settings/client/GeneralSettings.tsx
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
import { useBridgeQuery } from '@sd/client';
|
||||||
|
import React from 'react';
|
||||||
|
import { Text, View } from 'react-native';
|
||||||
|
import Card from '~/components/layout/Card';
|
||||||
|
import Divider from '~/components/primitive/Divider';
|
||||||
|
import { Input } from '~/components/primitive/Input';
|
||||||
|
import tw from '~/lib/tailwind';
|
||||||
|
import { SettingsStackScreenProps } from '~/navigation/SettingsNavigator';
|
||||||
|
|
||||||
|
const GeneralSettingsScreen = ({ navigation }: SettingsStackScreenProps<'GeneralSettings'>) => {
|
||||||
|
const { data: node } = useBridgeQuery(['nodeState']);
|
||||||
|
|
||||||
|
if (!node) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={tw`flex-1 p-4`}>
|
||||||
|
<Card>
|
||||||
|
{/* Card Header */}
|
||||||
|
<View style={tw`flex flex-row justify-between`}>
|
||||||
|
<Text style={tw`font-semibold text-ink`}>Connected Node</Text>
|
||||||
|
<View style={tw`flex flex-row`}>
|
||||||
|
{/* Peers */}
|
||||||
|
<View style={tw`rounded bg-app-highlight self-start px-1.5 py-[2px] mr-2`}>
|
||||||
|
<Text style={tw`text-xs font-semibold text-ink`}>0 Peers</Text>
|
||||||
|
</View>
|
||||||
|
{/* Status */}
|
||||||
|
<View style={tw`px-1.5 py-[2px] rounded bg-accent`}>
|
||||||
|
<Text style={tw`text-xs font-semibold text-ink`}>Running</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
{/* Divider */}
|
||||||
|
<Divider style={tw`mt-2 mb-4`} />
|
||||||
|
{/* Node Name and Port */}
|
||||||
|
<Text style={tw`mb-1 text-xs font-medium text-ink-dull ml-1`}>Node Name</Text>
|
||||||
|
<Input value={node.name} />
|
||||||
|
<Text style={tw`mt-2 mb-1 text-xs font-medium text-ink-dull ml-1`}>Node Port</Text>
|
||||||
|
<Input value={node.p2p_port?.toString() ?? '5795'} keyboardType="numeric" />
|
||||||
|
</Card>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GeneralSettingsScreen;
|
82
apps/mobile/src/screens/settings/client/LibrarySettings.tsx
Normal file
82
apps/mobile/src/screens/settings/client/LibrarySettings.tsx
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
import { LibraryConfigWrapped, useBridgeQuery } from '@sd/client';
|
||||||
|
import { CaretRight, Pen, Trash } from 'phosphor-react-native';
|
||||||
|
import React from 'react';
|
||||||
|
import { Animated, FlatList, Text, View } from 'react-native';
|
||||||
|
import { Swipeable } from 'react-native-gesture-handler';
|
||||||
|
import { AnimatedButton } from '~/components/primitive/Button';
|
||||||
|
import DeleteLibraryDialog from '~/containers/dialog/DeleteLibraryDialog';
|
||||||
|
import tw from '~/lib/tailwind';
|
||||||
|
import { SettingsStackScreenProps } from '~/navigation/SettingsNavigator';
|
||||||
|
|
||||||
|
function LibraryItem({
|
||||||
|
library,
|
||||||
|
index,
|
||||||
|
navigation
|
||||||
|
}: {
|
||||||
|
library: LibraryConfigWrapped;
|
||||||
|
index: number;
|
||||||
|
navigation: SettingsStackScreenProps<'LibrarySettings'>['navigation'];
|
||||||
|
}) {
|
||||||
|
const renderRightActions = (
|
||||||
|
progress: Animated.AnimatedInterpolation<number>,
|
||||||
|
dragX: Animated.AnimatedInterpolation<number>
|
||||||
|
) => {
|
||||||
|
const translate = progress.interpolate({
|
||||||
|
inputRange: [0, 1],
|
||||||
|
outputRange: [100, 0],
|
||||||
|
extrapolate: 'clamp'
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Animated.View
|
||||||
|
style={[tw`flex flex-row items-center`, { transform: [{ translateX: translate }] }]}
|
||||||
|
>
|
||||||
|
<AnimatedButton size="md" onPress={() => navigation.replace('LibraryGeneralSettings')}>
|
||||||
|
<Pen size={18} color="white" />
|
||||||
|
</AnimatedButton>
|
||||||
|
<DeleteLibraryDialog libraryUuid={library.uuid}>
|
||||||
|
<AnimatedButton size="md" style={tw`mx-2`}>
|
||||||
|
<Trash size={18} color="white" />
|
||||||
|
</AnimatedButton>
|
||||||
|
</DeleteLibraryDialog>
|
||||||
|
</Animated.View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Swipeable
|
||||||
|
containerStyle={tw.style(
|
||||||
|
index !== 0 && 'mt-2',
|
||||||
|
'bg-app-overlay border border-app-line rounded-lg px-4 py-3'
|
||||||
|
)}
|
||||||
|
enableTrackpadTwoFingerGesture
|
||||||
|
renderRightActions={renderRightActions}
|
||||||
|
>
|
||||||
|
<View style={tw`flex flex-row items-center justify-between`}>
|
||||||
|
<View>
|
||||||
|
<Text style={tw`font-semibold text-ink`}>{library.config.name}</Text>
|
||||||
|
<Text style={tw`mt-0.5 text-xs text-ink-dull`}>{library.uuid}</Text>
|
||||||
|
</View>
|
||||||
|
<CaretRight color={tw.color('ink-dull')} size={18} />
|
||||||
|
</View>
|
||||||
|
</Swipeable>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const LibrarySettingsScreen = ({ navigation }: SettingsStackScreenProps<'LibrarySettings'>) => {
|
||||||
|
const { data: libraries } = useBridgeQuery(['library.list']);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={tw`py-4 px-3 flex-1`}>
|
||||||
|
<FlatList
|
||||||
|
data={libraries}
|
||||||
|
keyExtractor={(item) => item.uuid}
|
||||||
|
renderItem={({ item, index }) => (
|
||||||
|
<LibraryItem navigation={navigation} library={item} index={index} />
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LibrarySettingsScreen;
|
14
apps/mobile/src/screens/settings/client/PrivacySettings.tsx
Normal file
14
apps/mobile/src/screens/settings/client/PrivacySettings.tsx
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Text, View } from 'react-native';
|
||||||
|
import tw from '~/lib/tailwind';
|
||||||
|
import { SettingsStackScreenProps } from '~/navigation/SettingsNavigator';
|
||||||
|
|
||||||
|
const PrivacySettingsScreen = ({ navigation }: SettingsStackScreenProps<'PrivacySettings'>) => {
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<Text style={tw`text-ink`}>TODO</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PrivacySettingsScreen;
|
14
apps/mobile/src/screens/settings/info/About.tsx
Normal file
14
apps/mobile/src/screens/settings/info/About.tsx
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Text, View } from 'react-native';
|
||||||
|
import tw from '~/lib/tailwind';
|
||||||
|
import { SettingsStackScreenProps } from '~/navigation/SettingsNavigator';
|
||||||
|
|
||||||
|
const AboutScreen = ({ navigation }: SettingsStackScreenProps<'About'>) => {
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<Text style={tw`text-ink`}>TODO</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AboutScreen;
|
14
apps/mobile/src/screens/settings/info/Support.tsx
Normal file
14
apps/mobile/src/screens/settings/info/Support.tsx
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Text, View } from 'react-native';
|
||||||
|
import tw from '~/lib/tailwind';
|
||||||
|
import { SettingsStackScreenProps } from '~/navigation/SettingsNavigator';
|
||||||
|
|
||||||
|
const SupportScreen = ({ navigation }: SettingsStackScreenProps<'Support'>) => {
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<Text style={tw`text-ink`}>TODO</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SupportScreen;
|
14
apps/mobile/src/screens/settings/library/KeysSettings.tsx
Normal file
14
apps/mobile/src/screens/settings/library/KeysSettings.tsx
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Text, View } from 'react-native';
|
||||||
|
import tw from '~/lib/tailwind';
|
||||||
|
import { SettingsStackScreenProps } from '~/navigation/SettingsNavigator';
|
||||||
|
|
||||||
|
const KeysSettingsScreen = ({ navigation }: SettingsStackScreenProps<'KeysSettings'>) => {
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<Text style={tw`text-ink`}>TODO</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default KeysSettingsScreen;
|
|
@ -0,0 +1,85 @@
|
||||||
|
import { useBridgeMutation, useCurrentLibrary } from '@sd/client';
|
||||||
|
import { Trash } from 'phosphor-react-native';
|
||||||
|
import React from 'react';
|
||||||
|
import { Controller, useForm } from 'react-hook-form';
|
||||||
|
import { Alert, Text, View } from 'react-native';
|
||||||
|
import { Button } from '~/components/primitive/Button';
|
||||||
|
import { Input } from '~/components/primitive/Input';
|
||||||
|
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 { SettingsStackScreenProps } from '~/navigation/SettingsNavigator';
|
||||||
|
|
||||||
|
type LibraryFormData = {
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const LibraryGeneralSettingsScreen = ({
|
||||||
|
navigation
|
||||||
|
}: SettingsStackScreenProps<'LibraryGeneralSettings'>) => {
|
||||||
|
const { library } = useCurrentLibrary();
|
||||||
|
|
||||||
|
const form = useForm<LibraryFormData>({
|
||||||
|
defaultValues: { name: library.config.name, description: library.config.description }
|
||||||
|
});
|
||||||
|
|
||||||
|
const { mutate: editLibrary } = useBridgeMutation('library.edit');
|
||||||
|
|
||||||
|
useAutoForm(form, (value) => {
|
||||||
|
editLibrary({ description: value.description, name: value.name, id: library.uuid });
|
||||||
|
console.log('Updated', value);
|
||||||
|
// TODO: Show toast
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
{/* This looks bad... */}
|
||||||
|
<View style={tw`mt-4 px-2 py-4 bg-app-overlay`}>
|
||||||
|
<Text style={tw`mb-1 text-xs font-medium text-ink-dull ml-1`}>Name</Text>
|
||||||
|
<Controller
|
||||||
|
name="name"
|
||||||
|
control={form.control}
|
||||||
|
render={({ field: { onBlur, onChange, value } }) => (
|
||||||
|
<Input onBlur={onBlur} onChangeText={onChange} value={value} />
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
{/* Description */}
|
||||||
|
<Text style={tw`mb-1 text-xs font-medium text-ink-dull ml-1 mt-3`}>Description</Text>
|
||||||
|
<Controller
|
||||||
|
name="description"
|
||||||
|
control={form.control}
|
||||||
|
render={({ field: { onBlur, onChange, value } }) => (
|
||||||
|
<Input onBlur={onBlur} onChangeText={onChange} value={value} />
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
{/* Encrypt */}
|
||||||
|
<View style={tw`mt-6`} />
|
||||||
|
<SettingsContainer description="Enable encryption for this library, this will only encrypt the Spacedrive database, not the files themselves.">
|
||||||
|
<SettingsItem title="Encrypt Library" rightArea={<Switch value={true} />} />
|
||||||
|
</SettingsContainer>
|
||||||
|
<View style={tw`mt-6`} />
|
||||||
|
{/* 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 ? */}
|
||||||
|
<SettingsContainer description="This is permanent, your files will not be deleted, only the Spacedrive library.">
|
||||||
|
<SettingsItem
|
||||||
|
title="Delete Library"
|
||||||
|
rightArea={
|
||||||
|
<Button size="sm" variant="danger" onPress={() => Alert.alert('TODO')}>
|
||||||
|
<Trash color={tw.color('ink')} size={20} />
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</SettingsContainer>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LibraryGeneralSettingsScreen;
|
100
apps/mobile/src/screens/settings/library/LocationSettings.tsx
Normal file
100
apps/mobile/src/screens/settings/library/LocationSettings.tsx
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
import { Location, Node, useLibraryMutation, useLibraryQuery } from '@sd/client';
|
||||||
|
import { CaretRight, Repeat, Trash } from 'phosphor-react-native';
|
||||||
|
import { Animated, FlatList, Pressable, Text, View } from 'react-native';
|
||||||
|
import { Swipeable } from 'react-native-gesture-handler';
|
||||||
|
import FolderIcon from '~/components/icons/FolderIcon';
|
||||||
|
import DeleteLocationDialog from '~/containers/dialog/DeleteLocationDialog';
|
||||||
|
import tw from '~/lib/tailwind';
|
||||||
|
import { SettingsStackScreenProps } from '~/navigation/SettingsNavigator';
|
||||||
|
|
||||||
|
function LocationItem({ location, index }: { location: Location & { node: Node }; index: number }) {
|
||||||
|
const { mutate: fullRescan } = useLibraryMutation('locations.fullRescan', {
|
||||||
|
onMutate: () => {
|
||||||
|
// TODO: Show Toast
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const renderRightActions = (progress: Animated.AnimatedInterpolation<number>) => {
|
||||||
|
const translate = progress.interpolate({
|
||||||
|
inputRange: [0, 1],
|
||||||
|
outputRange: [100, 0],
|
||||||
|
extrapolate: 'clamp'
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Animated.View
|
||||||
|
style={[tw`flex flex-row items-center`, { transform: [{ translateX: translate }] }]}
|
||||||
|
>
|
||||||
|
<DeleteLocationDialog locationId={location.id}>
|
||||||
|
<View
|
||||||
|
style={tw`py-1.5 px-3 bg-app-button border-app-line border rounded-md items-center justify-center shadow-sm`}
|
||||||
|
>
|
||||||
|
<Trash size={18} color="white" />
|
||||||
|
</View>
|
||||||
|
</DeleteLocationDialog>
|
||||||
|
{/* Full Re-scan IS too much here */}
|
||||||
|
<Pressable
|
||||||
|
style={tw`py-1.5 px-3 bg-app-button border-app-line border rounded-md items-center justify-center shadow-sm mx-2`}
|
||||||
|
onPress={() => fullRescan(location.id)}
|
||||||
|
>
|
||||||
|
<Repeat size={18} color="white" />
|
||||||
|
</Pressable>
|
||||||
|
</Animated.View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Swipeable
|
||||||
|
containerStyle={tw`bg-app-overlay border border-app-line rounded-lg`}
|
||||||
|
enableTrackpadTwoFingerGesture
|
||||||
|
renderRightActions={renderRightActions}
|
||||||
|
>
|
||||||
|
<View style={tw.style('px-4 py-3', index !== 0 && 'mt-2')}>
|
||||||
|
<View style={tw`flex flex-row items-center`}>
|
||||||
|
<View style={tw`relative`}>
|
||||||
|
<FolderIcon size={32} />
|
||||||
|
{/* Online/Offline Indicator */}
|
||||||
|
<View
|
||||||
|
style={tw.style(
|
||||||
|
'absolute w-2 h-2 right-0 bottom-0.5 rounded-full',
|
||||||
|
location.is_online ? 'bg-green-500' : 'bg-red-500'
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<View style={tw`flex-1 mx-4`}>
|
||||||
|
<Text numberOfLines={1} style={tw`text-sm font-semibold text-ink`}>
|
||||||
|
{location.name}
|
||||||
|
</Text>
|
||||||
|
<View style={tw`self-start bg-app-highlight py-[1px] px-1 rounded mt-0.5`}>
|
||||||
|
<Text numberOfLines={1} style={tw`text-xs font-semibold text-ink-dull`}>
|
||||||
|
{location.node.name}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<Text numberOfLines={1} style={tw`mt-0.5 text-[10px] font-semibold text-ink-dull`}>
|
||||||
|
{location.local_path}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<CaretRight color={tw.color('ink-dull')} size={18} />
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</Swipeable>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Add new location from here (ImportModal)
|
||||||
|
|
||||||
|
const LocationSettingsScreen = ({ navigation }: SettingsStackScreenProps<'LocationSettings'>) => {
|
||||||
|
const { data: locations } = useLibraryQuery(['locations.list']);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={tw`flex-1 px-3 py-4`}>
|
||||||
|
<FlatList
|
||||||
|
data={locations}
|
||||||
|
keyExtractor={(item) => item.id.toString()}
|
||||||
|
renderItem={({ item, index }) => <LocationItem location={item} index={index} />}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LocationSettingsScreen;
|
14
apps/mobile/src/screens/settings/library/NodesSettings.tsx
Normal file
14
apps/mobile/src/screens/settings/library/NodesSettings.tsx
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Text, View } from 'react-native';
|
||||||
|
import tw from '~/lib/tailwind';
|
||||||
|
import { SettingsStackScreenProps } from '~/navigation/SettingsNavigator';
|
||||||
|
|
||||||
|
const NodesSettingsScreen = ({ navigation }: SettingsStackScreenProps<'NodesSettings'>) => {
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<Text style={tw`text-ink`}>TODO</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default NodesSettingsScreen;
|
76
apps/mobile/src/screens/settings/library/TagsSettings.tsx
Normal file
76
apps/mobile/src/screens/settings/library/TagsSettings.tsx
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
import { Tag, useLibraryQuery } from '@sd/client';
|
||||||
|
import { CaretRight, Pen, Trash } from 'phosphor-react-native';
|
||||||
|
import { Animated, FlatList, Text, View } from 'react-native';
|
||||||
|
import { Swipeable } from 'react-native-gesture-handler';
|
||||||
|
import { AnimatedButton } from '~/components/primitive/Button';
|
||||||
|
import DeleteTagDialog from '~/containers/dialog/tag/DeleteTagDialog';
|
||||||
|
import UpdateTagDialog from '~/containers/dialog/tag/UpdateTagDialog';
|
||||||
|
import tw from '~/lib/tailwind';
|
||||||
|
import { SettingsStackScreenProps } from '~/navigation/SettingsNavigator';
|
||||||
|
|
||||||
|
function TagItem({ tag, index }: { tag: Tag; index: number }) {
|
||||||
|
const renderRightActions = (
|
||||||
|
progress: Animated.AnimatedInterpolation<number>,
|
||||||
|
_dragX: Animated.AnimatedInterpolation<number>,
|
||||||
|
swipeable: Swipeable
|
||||||
|
) => {
|
||||||
|
const translate = progress.interpolate({
|
||||||
|
inputRange: [0, 1],
|
||||||
|
outputRange: [100, 0],
|
||||||
|
extrapolate: 'clamp'
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Animated.View
|
||||||
|
style={[tw`flex flex-row items-center`, { transform: [{ translateX: translate }] }]}
|
||||||
|
>
|
||||||
|
<UpdateTagDialog tag={tag} onSubmit={() => swipeable.close()}>
|
||||||
|
<AnimatedButton size="md">
|
||||||
|
<Pen size={18} color="white" />
|
||||||
|
</AnimatedButton>
|
||||||
|
</UpdateTagDialog>
|
||||||
|
<DeleteTagDialog tagId={tag.id}>
|
||||||
|
<AnimatedButton size="md" style={tw`mx-2`}>
|
||||||
|
<Trash size={18} color="white" />
|
||||||
|
</AnimatedButton>
|
||||||
|
</DeleteTagDialog>
|
||||||
|
</Animated.View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Swipeable
|
||||||
|
containerStyle={tw`bg-app-overlay border border-app-line rounded-lg`}
|
||||||
|
enableTrackpadTwoFingerGesture
|
||||||
|
renderRightActions={renderRightActions}
|
||||||
|
>
|
||||||
|
<View style={tw.style('px-4 py-3', index !== 0 && 'mt-2')}>
|
||||||
|
<View style={tw`flex flex-row items-center justify-between`}>
|
||||||
|
<View style={tw`flex flex-row`}>
|
||||||
|
<View style={tw.style({ backgroundColor: tag.color }, 'w-4 h-4 rounded-full')} />
|
||||||
|
<Text style={tw`ml-3 text-ink`}>{tag.name}</Text>
|
||||||
|
</View>
|
||||||
|
<CaretRight color={tw.color('ink-dull')} size={18} />
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</Swipeable>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Add "New Tag" button
|
||||||
|
|
||||||
|
const TagsSettingsScreen = ({ navigation }: SettingsStackScreenProps<'TagsSettings'>) => {
|
||||||
|
const { data: tags } = useLibraryQuery(['tags.list']);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={tw`flex-1 px-3 py-4`}>
|
||||||
|
<FlatList
|
||||||
|
data={tags}
|
||||||
|
keyExtractor={(item) => item.id.toString()}
|
||||||
|
renderItem={({ item, index }) => <TagItem tag={item} index={index} />}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TagsSettingsScreen;
|
|
@ -1,34 +1,63 @@
|
||||||
|
// Extented colors are copied from packages/ui/style/colors.scss
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
content: ['./screens/**/*.{js,ts,jsx}', './components/**/*.{js,ts,jsx}', 'App.tsx'],
|
content: ['./screens/**/*.{js,ts,jsx}', './components/**/*.{js,ts,jsx}', 'App.tsx'],
|
||||||
theme: {
|
theme: {
|
||||||
fontSize: {
|
|
||||||
'tiny': '.65rem',
|
|
||||||
'xs': '.75rem',
|
|
||||||
'sm': '.84rem',
|
|
||||||
'base': '1rem',
|
|
||||||
'lg': '1.125rem',
|
|
||||||
'xl': '1.25rem',
|
|
||||||
'2xl': '1.5rem',
|
|
||||||
'3xl': '1.875rem',
|
|
||||||
'4xl': '2.25rem',
|
|
||||||
'5xl': '3rem',
|
|
||||||
'6xl': '4rem',
|
|
||||||
'7xl': '5rem'
|
|
||||||
},
|
|
||||||
extend: {
|
extend: {
|
||||||
|
fontSize: {
|
||||||
|
tiny: '.65rem',
|
||||||
|
// Default: '0.875rem'
|
||||||
|
sm: '.85rem'
|
||||||
|
},
|
||||||
colors: {
|
colors: {
|
||||||
primary: {
|
// Brand blue
|
||||||
DEFAULT: '#2599FF',
|
accent: {
|
||||||
50: '#FFFFFF',
|
DEFAULT: 'hsla(208, 100%, 47%, 1)',
|
||||||
100: '#F1F8FF',
|
faint: 'hsla(208, 100%, 64%, 1)',
|
||||||
200: '#BEE1FF',
|
deep: 'hsla(208, 100%, 47%, 1)'
|
||||||
300: '#8BC9FF',
|
},
|
||||||
400: '#58B1FF',
|
ink: {
|
||||||
500: '#2599FF',
|
DEFAULT: 'hsla(230, 0%, 100%, 1)',
|
||||||
600: '#0081F1',
|
light: 'hsla(230, 0%, 82%, 1)',
|
||||||
700: '#0065BE',
|
dull: 'hsla(230, 10%, 70%, 1)',
|
||||||
800: '#004A8B',
|
faint: 'hsla(230, 10%, 55%, 1)'
|
||||||
900: '#002F58'
|
},
|
||||||
|
// Brand gray
|
||||||
|
app: {
|
||||||
|
DEFAULT: 'hsla(230, 15%, 13%, 1)',
|
||||||
|
// background (dark)
|
||||||
|
box: 'hsla(230, 15%, 17%, 1)',
|
||||||
|
darkBox: 'hsla(230, 15%, 7%, 1)',
|
||||||
|
// foreground (light)
|
||||||
|
overlay: 'hsla(230, 15%, 19%, 1)',
|
||||||
|
// border
|
||||||
|
line: 'hsla(230, 15%, 25%, 1)',
|
||||||
|
darkLine: 'hsla(230, 15%, 7%, 1)',
|
||||||
|
// 'selected' on desktop
|
||||||
|
highlight: 'hsla(230, 15%, 27%, 1)',
|
||||||
|
// shadow
|
||||||
|
shade: 'hsla(230, 15%, 0%, 1)',
|
||||||
|
// button
|
||||||
|
button: 'hsla(230, 15%, 23%, 1)',
|
||||||
|
50: 'hsla(230, 15%, 5%, 1)',
|
||||||
|
100: 'hsla(230, 15%, 10%, 1)',
|
||||||
|
150: 'hsla(230, 15%, 15%, 1)',
|
||||||
|
200: 'hsla(230, 15%, 20%, 1)',
|
||||||
|
250: 'hsla(230, 15%, 30%, 1)',
|
||||||
|
300: 'hsla(230, 15%, 35%, 1)',
|
||||||
|
350: 'hsla(230, 15%, 40%, 1)',
|
||||||
|
450: 'hsla(230, 15%, 45%, 1)',
|
||||||
|
500: 'hsla(230, 15%, 50%, 1)',
|
||||||
|
550: 'hsla(230, 15%, 55%, 1)',
|
||||||
|
600: 'hsla(230, 15%, 60%, 1)',
|
||||||
|
650: 'hsla(230, 15%, 65%, 1)',
|
||||||
|
700: 'hsla(230, 15%, 70%, 1)',
|
||||||
|
750: 'hsla(230, 15%, 75%, 1)',
|
||||||
|
800: 'hsla(230, 15%, 80%, 1)',
|
||||||
|
850: 'hsla(230, 15%, 85%, 1)',
|
||||||
|
900: 'hsla(230, 15%, 90%, 1)',
|
||||||
|
950: 'hsla(230, 15%, 95%, 1)',
|
||||||
|
1000: 'hsla(230, 15%, 100%, 1)'
|
||||||
},
|
},
|
||||||
gray: {
|
gray: {
|
||||||
DEFAULT: '#505468',
|
DEFAULT: '#505468',
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
{
|
{
|
||||||
"extends": "expo/tsconfig.base",
|
"extends": "expo/tsconfig.base",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": "src",
|
"baseUrl": ".",
|
||||||
"target": "ESNext",
|
"target": "ESNext",
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"paths": {
|
"paths": {
|
||||||
"~/*": ["*"]
|
"~/*": ["src/*"]
|
||||||
},
|
},
|
||||||
"jsx": "react-native"
|
"jsx": "react-native"
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,3 +9,4 @@ export * from './hooks';
|
||||||
export * from './stores';
|
export * from './stores';
|
||||||
export * from './rspc';
|
export * from './rspc';
|
||||||
export * from './core';
|
export * from './core';
|
||||||
|
export * from './utils';
|
||||||
|
|
1
packages/client/src/utils/index.ts
Normal file
1
packages/client/src/utils/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export * from './isVideoExt';
|
31
packages/client/src/utils/isVideoExt.ts
Normal file
31
packages/client/src/utils/isVideoExt.ts
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
export function isVideoExt(extension: string) {
|
||||||
|
return [
|
||||||
|
'avi',
|
||||||
|
'asf',
|
||||||
|
'mpeg',
|
||||||
|
'mts',
|
||||||
|
'mpe',
|
||||||
|
'vob',
|
||||||
|
'qt',
|
||||||
|
'mov',
|
||||||
|
'asf',
|
||||||
|
'asx',
|
||||||
|
'mjpeg',
|
||||||
|
'ts',
|
||||||
|
'mxf',
|
||||||
|
'm2ts',
|
||||||
|
'f4v',
|
||||||
|
'wm',
|
||||||
|
'3gp',
|
||||||
|
'm4v',
|
||||||
|
'wmv',
|
||||||
|
'mp4',
|
||||||
|
'webm',
|
||||||
|
'flv',
|
||||||
|
'mpg',
|
||||||
|
'hevc',
|
||||||
|
'ogv',
|
||||||
|
'swf',
|
||||||
|
'wtv'
|
||||||
|
].includes(extension);
|
||||||
|
}
|
59
packages/config/eslint-react-native.js
Normal file
59
packages/config/eslint-react-native.js
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
module.exports = {
|
||||||
|
env: {
|
||||||
|
'react-native/react-native': true
|
||||||
|
},
|
||||||
|
parser: '@typescript-eslint/parser',
|
||||||
|
parserOptions: {
|
||||||
|
ecmaFeatures: {
|
||||||
|
jsx: true
|
||||||
|
},
|
||||||
|
ecmaVersion: 12,
|
||||||
|
sourceType: 'module'
|
||||||
|
},
|
||||||
|
extends: [
|
||||||
|
'eslint:recommended',
|
||||||
|
'plugin:react/recommended',
|
||||||
|
'plugin:react-hooks/recommended',
|
||||||
|
'plugin:@typescript-eslint/recommended'
|
||||||
|
],
|
||||||
|
plugins: ['react', 'react-native'],
|
||||||
|
rules: {
|
||||||
|
'react/display-name': 'off',
|
||||||
|
'react/prop-types': 'off',
|
||||||
|
'react/no-unescaped-entities': 'off',
|
||||||
|
'react/react-in-jsx-scope': 'off',
|
||||||
|
'react-hooks/rules-of-hooks': 'error',
|
||||||
|
'react-hooks/exhaustive-deps': 'warn',
|
||||||
|
'@typescript-eslint/no-unused-vars': 'off',
|
||||||
|
'@typescript-eslint/ban-ts-comment': 'off',
|
||||||
|
'@typescript-eslint/no-explicit-any': 'off',
|
||||||
|
'@typescript-eslint/no-var-requires': 'off',
|
||||||
|
'@typescript-eslint/no-non-null-assertion': 'off',
|
||||||
|
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||||
|
'no-control-regex': 'off',
|
||||||
|
'no-mixed-spaces-and-tabs': ['warn', 'smart-tabs'],
|
||||||
|
'no-restricted-imports': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
paths: [
|
||||||
|
{
|
||||||
|
name: 'react-native',
|
||||||
|
importNames: ['SafeAreaView'],
|
||||||
|
message: 'Import SafeAreaView from react-native-safe-area-context instead'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'react-native',
|
||||||
|
importNames: ['Button'],
|
||||||
|
message: 'Import Button from ~/components instead.'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
ignorePatterns: ['**/*.js', '**/*.json', 'node_modules', 'android', 'ios', '.expo'],
|
||||||
|
settings: {
|
||||||
|
react: {
|
||||||
|
version: 'detect'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
|
@ -1,4 +1,4 @@
|
||||||
import { ExplorerItem } from '@sd/client';
|
import { ExplorerItem, isVideoExt } from '@sd/client';
|
||||||
import { cva, tw } from '@sd/ui';
|
import { cva, tw } from '@sd/ui';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { HTMLAttributes } from 'react';
|
import { HTMLAttributes } from 'react';
|
||||||
|
@ -27,7 +27,7 @@ interface Props extends HTMLAttributes<HTMLDivElement> {
|
||||||
}
|
}
|
||||||
|
|
||||||
function FileItem({ data, selected, index, ...rest }: Props) {
|
function FileItem({ data, selected, index, ...rest }: Props) {
|
||||||
const isVid = isVideo(data.extension || '');
|
const isVid = isVideoExt(data.extension || '');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
@ -86,35 +86,3 @@ function FileItem({ data, selected, index, ...rest }: Props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default FileItem;
|
export default FileItem;
|
||||||
|
|
||||||
function isVideo(extension: string) {
|
|
||||||
return [
|
|
||||||
'avi',
|
|
||||||
'asf',
|
|
||||||
'mpeg',
|
|
||||||
'mts',
|
|
||||||
'mpe',
|
|
||||||
'vob',
|
|
||||||
'qt',
|
|
||||||
'mov',
|
|
||||||
'asf',
|
|
||||||
'asx',
|
|
||||||
'mjpeg',
|
|
||||||
'ts',
|
|
||||||
'mxf',
|
|
||||||
'm2ts',
|
|
||||||
'f4v',
|
|
||||||
'wm',
|
|
||||||
'3gp',
|
|
||||||
'm4v',
|
|
||||||
'wmv',
|
|
||||||
'mp4',
|
|
||||||
'webm',
|
|
||||||
'flv',
|
|
||||||
'mpg',
|
|
||||||
'hevc',
|
|
||||||
'ogv',
|
|
||||||
'swf',
|
|
||||||
'wtv'
|
|
||||||
].includes(extension);
|
|
||||||
}
|
|
||||||
|
|
3594
pnpm-lock.yaml
3594
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue