mirror of
https://github.com/spacedriveapp/spacedrive
synced 2024-07-02 10:03:28 +00:00
[MOB-37, MOB-38, MOB-39] Preview for PDF, Text and Media files (#2098)
* version & microphonePermission text & eslint * remove polyfill as hermes supports intl now * why do we have solid on mobile? * cleanup * add solid back =_= * pnpm lock * we hate relative paths here * android config * open file logic * visual tweaks --------- Co-authored-by: ameer2468 <33054370+ameer2468@users.noreply.github.com>
This commit is contained in:
parent
c533d12df0
commit
b638fc2177
|
@ -3,7 +3,7 @@
|
|||
"name": "Spacedrive",
|
||||
"slug": "spacedrive",
|
||||
"owner": "spacedrive",
|
||||
"version": "0.0.1",
|
||||
"version": "0.1.0",
|
||||
"orientation": "portrait",
|
||||
"jsEngine": "hermes",
|
||||
"scheme": "spacedrive",
|
||||
|
@ -58,7 +58,14 @@
|
|||
}
|
||||
}
|
||||
],
|
||||
["./withRiveAssets.js"]
|
||||
[
|
||||
"expo-av",
|
||||
{
|
||||
"microphonePermission": "Allow Spacedrive to access your microphone."
|
||||
}
|
||||
],
|
||||
["./scripts/withRiveAssets.js"],
|
||||
["./scripts/withAndroidIntent.js"]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ apply plugin: 'maven-publish'
|
|||
|
||||
|
||||
group = 'com.spacedrive.core'
|
||||
version = '0.0.1'
|
||||
version = '0.1.0'
|
||||
|
||||
buildscript {
|
||||
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
|
||||
|
@ -72,7 +72,7 @@ android {
|
|||
minSdkVersion safeExtGet("minSdkVersion", 28)
|
||||
targetSdkVersion safeExtGet("targetSdkVersion", 34)
|
||||
versionCode 1
|
||||
versionName "0.2.0"
|
||||
versionName "0.1.0"
|
||||
}
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
|
|
|
@ -1,83 +1,84 @@
|
|||
{
|
||||
"name": "@sd/mobile",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"license": "GPL-3.0-only",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "expo start --dev-client",
|
||||
"android": "expo run:android",
|
||||
"ios": "expo run:ios",
|
||||
"prebuild": "expo prebuild",
|
||||
"xcode": "open ios/Spacedrive.xcworkspace",
|
||||
"android-studio": "open -a '/Applications/Android Studio.app' ./android",
|
||||
"lint": "eslint src --cache",
|
||||
"test": "cd ../.. && ./apps/mobile/scripts/run-maestro-tests ios",
|
||||
"export": "expo export",
|
||||
"typecheck": "tsc -b"
|
||||
},
|
||||
"dependencies": {
|
||||
"@gorhom/bottom-sheet": "^4.4.7",
|
||||
"@hookform/resolvers": "^3.1.0",
|
||||
"@oscartbeaumont-sd/rspc-client": "=0.0.0-main-dc31e5b2",
|
||||
"@oscartbeaumont-sd/rspc-react": "=0.0.0-main-dc31e5b2",
|
||||
"@react-native-async-storage/async-storage": "~1.21.0",
|
||||
"@react-native-masked-view/masked-view": "^0.3.0",
|
||||
"@react-navigation/bottom-tabs": "^6.5.8",
|
||||
"@react-navigation/drawer": "^6.6.3",
|
||||
"@react-navigation/native": "^6.1.7",
|
||||
"@react-navigation/stack": "^6.3.17",
|
||||
"@sd/assets": "workspace:*",
|
||||
"@sd/client": "workspace:*",
|
||||
"@shopify/flash-list": "1.6.3",
|
||||
"@tanstack/react-query": "^4.36.1",
|
||||
"babel-preset-solid": "^1.8.9",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"dayjs": "^1.11.10",
|
||||
"event-target-polyfill": "^0.0.3",
|
||||
"expo": "~50.0.6",
|
||||
"expo-av": "^13.10.5",
|
||||
"expo-blur": "^12.9.1",
|
||||
"expo-build-properties": "~0.11.1",
|
||||
"expo-linking": "~6.2.2",
|
||||
"expo-media-library": "~15.9.1",
|
||||
"expo-splash-screen": "~0.26.4",
|
||||
"expo-status-bar": "~1.11.1",
|
||||
"intl": "^1.2.5",
|
||||
"lottie-react-native": "6.5.1",
|
||||
"metro-react-native-babel-transformer": "^0.77.0",
|
||||
"moti": "^0.26.0",
|
||||
"phosphor-react-native": "^2.0.0",
|
||||
"react": "^18.2.0",
|
||||
"react-hook-form": "^7.47.0",
|
||||
"react-native": "0.73.4",
|
||||
"react-native-circular-progress": "^1.3.9",
|
||||
"react-native-document-picker": "^9.0.1",
|
||||
"react-native-fs": "^2.20.0",
|
||||
"react-native-gesture-handler": "~2.14.1",
|
||||
"react-native-linear-gradient": "^2.8.3",
|
||||
"react-native-popup-menu": "^0.16.1",
|
||||
"react-native-reanimated": "~3.6.2",
|
||||
"react-native-safe-area-context": "4.8.2",
|
||||
"react-native-screens": "~3.29.0",
|
||||
"react-native-svg": "14.1.0",
|
||||
"react-native-wheel-color-picker": "^1.2.0",
|
||||
"rive-react-native": "^6.2.3",
|
||||
"solid-js": "^1.8.8",
|
||||
"twrnc": "^3.6.4",
|
||||
"use-count-up": "^3.0.1",
|
||||
"use-debounce": "^9.0.4",
|
||||
"valtio": "^1.11.2",
|
||||
"zod": "~3.22.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.23.2",
|
||||
"@rnx-kit/metro-config": "^1.3.12",
|
||||
"@sd/config": "workspace:*",
|
||||
"@types/react": "^18.2.52",
|
||||
"babel-plugin-module-resolver": "^5.0.0",
|
||||
"eslint-plugin-react-native": "^4.1.0",
|
||||
"react-native-svg-transformer": "^1.1.0",
|
||||
"typescript": "^5.3.3"
|
||||
}
|
||||
"name": "@sd/mobile",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"license": "GPL-3.0-only",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "expo start --dev-client",
|
||||
"android": "expo run:android",
|
||||
"ios": "expo run:ios",
|
||||
"prebuild": "expo prebuild",
|
||||
"xcode": "open ios/Spacedrive.xcworkspace",
|
||||
"android-studio": "open -a '/Applications/Android Studio.app' ./android",
|
||||
"lint": "eslint src --cache",
|
||||
"test": "cd ../.. && ./apps/mobile/scripts/run-maestro-tests ios",
|
||||
"export": "expo export",
|
||||
"typecheck": "tsc -b",
|
||||
"format": "prettier --write ."
|
||||
},
|
||||
"dependencies": {
|
||||
"@gorhom/bottom-sheet": "^4.4.7",
|
||||
"@hookform/resolvers": "^3.1.0",
|
||||
"@oscartbeaumont-sd/rspc-client": "=0.0.0-main-dc31e5b2",
|
||||
"@oscartbeaumont-sd/rspc-react": "=0.0.0-main-dc31e5b2",
|
||||
"@react-native-async-storage/async-storage": "~1.21.0",
|
||||
"@react-native-masked-view/masked-view": "^0.3.0",
|
||||
"@react-navigation/bottom-tabs": "^6.5.8",
|
||||
"@react-navigation/drawer": "^6.6.3",
|
||||
"@react-navigation/native": "^6.1.7",
|
||||
"@react-navigation/stack": "^6.3.17",
|
||||
"@sd/assets": "workspace:*",
|
||||
"@sd/client": "workspace:*",
|
||||
"@shopify/flash-list": "1.6.3",
|
||||
"@tanstack/react-query": "^4.36.1",
|
||||
"babel-preset-solid": "^1.8.9",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"dayjs": "^1.11.10",
|
||||
"event-target-polyfill": "^0.0.3",
|
||||
"expo": "~50.0.6",
|
||||
"expo-av": "^13.10.5",
|
||||
"expo-blur": "^12.9.1",
|
||||
"expo-build-properties": "~0.11.1",
|
||||
"expo-linking": "~6.2.2",
|
||||
"expo-media-library": "~15.9.1",
|
||||
"expo-splash-screen": "~0.26.4",
|
||||
"expo-status-bar": "~1.11.1",
|
||||
"lottie-react-native": "6.5.1",
|
||||
"metro-react-native-babel-transformer": "^0.77.0",
|
||||
"moti": "^0.26.0",
|
||||
"phosphor-react-native": "^2.0.0",
|
||||
"react": "^18.2.0",
|
||||
"react-hook-form": "^7.47.0",
|
||||
"react-native": "0.73.4",
|
||||
"react-native-circular-progress": "^1.3.9",
|
||||
"react-native-document-picker": "^9.0.1",
|
||||
"react-native-file-viewer": "^2.1.5",
|
||||
"react-native-fs": "^2.20.0",
|
||||
"react-native-gesture-handler": "~2.14.1",
|
||||
"react-native-linear-gradient": "^2.8.3",
|
||||
"react-native-popup-menu": "^0.16.1",
|
||||
"react-native-reanimated": "~3.6.2",
|
||||
"react-native-safe-area-context": "4.8.2",
|
||||
"react-native-screens": "~3.29.0",
|
||||
"react-native-svg": "14.1.0",
|
||||
"react-native-wheel-color-picker": "^1.2.0",
|
||||
"rive-react-native": "^6.2.3",
|
||||
"solid-js": "^1.8.8",
|
||||
"twrnc": "^3.6.4",
|
||||
"use-count-up": "^3.0.1",
|
||||
"use-debounce": "^9.0.4",
|
||||
"valtio": "^1.11.2",
|
||||
"zod": "~3.22.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.23.2",
|
||||
"@rnx-kit/metro-config": "^1.3.12",
|
||||
"@sd/config": "workspace:*",
|
||||
"@types/react": "^18.2.52",
|
||||
"babel-plugin-module-resolver": "^5.0.0",
|
||||
"eslint-plugin-react-native": "^4.1.0",
|
||||
"react-native-svg-transformer": "^1.1.0",
|
||||
"typescript": "^5.3.3"
|
||||
}
|
||||
}
|
||||
|
|
26
apps/mobile/scripts/withAndroidIntent.js
Normal file
26
apps/mobile/scripts/withAndroidIntent.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
const { withAndroidManifest } = require('@expo/config-plugins');
|
||||
|
||||
// NOTE: Can be extended if needed (https://forums.expo.dev/t/how-to-edit-android-manifest-was-build/65663/4)
|
||||
function modifyAndroidManifest(androidManifest) {
|
||||
const { manifest } = androidManifest;
|
||||
|
||||
const intent = manifest['queries'][0]['intent'][0];
|
||||
|
||||
if (intent) {
|
||||
// Adds <data android:mimeType="*/*" /> to the intents
|
||||
intent['data'].push({
|
||||
$: {
|
||||
'android:mimeType': '*/*'
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return androidManifest;
|
||||
}
|
||||
|
||||
module.exports = function withAndroidIntent(config) {
|
||||
return withAndroidManifest(config, (config) => {
|
||||
config.modResults = modifyAndroidManifest(config.modResults);
|
||||
return config;
|
||||
});
|
||||
};
|
|
@ -68,11 +68,7 @@ function AppNavigation() {
|
|||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
plausibleEvent({
|
||||
event: {
|
||||
type: 'ping'
|
||||
}
|
||||
});
|
||||
plausibleEvent({ event: { type: 'ping' } });
|
||||
}, 270 * 1000);
|
||||
|
||||
return () => clearInterval(interval);
|
||||
|
|
|
@ -13,6 +13,7 @@ import { useActionsModalStore } from '~/stores/modalStore';
|
|||
|
||||
import FileItem from './FileItem';
|
||||
import FileRow from './FileRow';
|
||||
import ScreenContainer from '../layout/ScreenContainer';
|
||||
|
||||
type ExplorerProps = {
|
||||
items?: ExplorerItem[];
|
||||
|
@ -44,7 +45,7 @@ const Explorer = ({ items }: ExplorerProps) => {
|
|||
}
|
||||
|
||||
return (
|
||||
<View style={tw`flex-1 bg-mobile-screen`}>
|
||||
<ScreenContainer style={'gap-0 py-0'} scrollview={false}>
|
||||
{/* Header */}
|
||||
<View style={tw`flex flex-row items-center justify-between`}>
|
||||
{/* Sort By */}
|
||||
|
@ -99,6 +100,7 @@ const Explorer = ({ items }: ExplorerProps) => {
|
|||
)}
|
||||
</Pressable>
|
||||
)}
|
||||
contentContainerStyle={tw`p-2`}
|
||||
extraData={layoutMode}
|
||||
estimatedItemSize={
|
||||
layoutMode === 'grid'
|
||||
|
@ -107,7 +109,7 @@ const Explorer = ({ items }: ExplorerProps) => {
|
|||
}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
</ScreenContainer>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -2,7 +2,8 @@ import { useNavigation } from '@react-navigation/native';
|
|||
import { StackHeaderProps } from '@react-navigation/stack';
|
||||
import { ArrowLeft, DotsThreeOutline, MagnifyingGlass } from 'phosphor-react-native';
|
||||
import { lazy } from 'react';
|
||||
import { Platform, Pressable, Text, View } from 'react-native';
|
||||
import { Pressable, Text, View } from 'react-native';
|
||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
import { tw, twStyle } from '~/lib/tailwind';
|
||||
import { getExplorerStore, useExplorerStore } from '~/stores/explorerStore';
|
||||
|
||||
|
@ -44,16 +45,18 @@ export default function Header({
|
|||
const explorerStore = useExplorerStore();
|
||||
const routeParams = route?.route.params as any;
|
||||
|
||||
const headerHeight = useSafeAreaInsets().top;
|
||||
|
||||
return (
|
||||
<View
|
||||
style={twStyle(
|
||||
'relative h-auto w-full border-b border-app-line/50 bg-mobile-header',
|
||||
Platform.OS === 'android' ? 'pt-5' : 'pt-10'
|
||||
{ paddingTop: headerHeight }
|
||||
)}
|
||||
>
|
||||
<View style={tw`mx-auto mt-5 h-auto w-full justify-center px-7 pb-5`}>
|
||||
<View style={tw`mx-auto h-auto w-full justify-center px-7 pb-5`}>
|
||||
<View style={tw`w-full flex-row items-center justify-between`}>
|
||||
<View style={tw`flex-row items-center gap-5`}>
|
||||
<View style={tw`flex-row items-center gap-3`}>
|
||||
{navBack && (
|
||||
<Pressable
|
||||
onPress={() => {
|
||||
|
@ -67,7 +70,7 @@ export default function Header({
|
|||
<HeaderIconKind headerKind={headerKind} routeParams={routeParams} />
|
||||
<Text
|
||||
numberOfLines={1}
|
||||
style={tw`max-w-[190px] text-[22px] font-bold text-white`}
|
||||
style={tw`max-w-[200px] text-xl font-bold text-white`}
|
||||
>
|
||||
{title || (routeTitle && route?.options.title)}
|
||||
</Text>
|
||||
|
@ -128,11 +131,11 @@ interface HeaderIconKindProps {
|
|||
const HeaderIconKind = ({ headerKind, routeParams }: HeaderIconKindProps) => {
|
||||
switch (headerKind) {
|
||||
case 'location':
|
||||
return <Icon size={32} name="Folder" />;
|
||||
return <Icon size={30} name="Folder" />;
|
||||
case 'tag':
|
||||
return (
|
||||
<View
|
||||
style={twStyle('h-6 w-6 rounded-full', {
|
||||
style={twStyle('h-[30px] w-[30px] rounded-full', {
|
||||
backgroundColor: routeParams.color
|
||||
})}
|
||||
/>
|
||||
|
|
|
@ -12,7 +12,14 @@ import {
|
|||
} from 'phosphor-react-native';
|
||||
import { PropsWithChildren, useRef } from 'react';
|
||||
import { Pressable, Text, View, ViewStyle } from 'react-native';
|
||||
import { byteSize, getItemFilePath, getItemObject } from '@sd/client';
|
||||
import FileViewer from 'react-native-file-viewer';
|
||||
import {
|
||||
byteSize,
|
||||
getIndexedItemFilePath,
|
||||
getItemObject,
|
||||
useLibraryMutation,
|
||||
useLibraryQuery
|
||||
} from '@sd/client';
|
||||
import FileThumb from '~/components/explorer/FileThumb';
|
||||
import FavoriteButton from '~/components/explorer/sections/FavoriteButton';
|
||||
import InfoTagPills from '~/components/explorer/sections/InfoTagPills';
|
||||
|
@ -32,7 +39,7 @@ const ActionsContainer = ({ children, style }: ActionsContainerProps) => (
|
|||
|
||||
type ActionsItemProps = {
|
||||
title: string;
|
||||
icon: Icon;
|
||||
icon?: Icon;
|
||||
onPress?: () => void;
|
||||
isDanger?: boolean;
|
||||
};
|
||||
|
@ -49,7 +56,7 @@ const ActionsItem = ({ icon, onPress, title, isDanger = false }: ActionsItemProp
|
|||
>
|
||||
{title}
|
||||
</Text>
|
||||
<Icon color={isDanger ? 'red' : 'white'} size={22} />
|
||||
{Icon && <Icon color={isDanger ? 'red' : 'white'} size={22} />}
|
||||
</Pressable>
|
||||
);
|
||||
};
|
||||
|
@ -62,7 +69,31 @@ export const ActionsModal = () => {
|
|||
const { modalRef, data } = useActionsModalStore();
|
||||
|
||||
const objectData = data && getItemObject(data);
|
||||
const filePath = data && getItemFilePath(data);
|
||||
const filePath = data && getIndexedItemFilePath(data);
|
||||
|
||||
// Open
|
||||
|
||||
const updateAccessTime = useLibraryMutation('files.updateAccessTime');
|
||||
const queriedFullPath = useLibraryQuery(['files.getPath', filePath?.id ?? -1], {
|
||||
enabled: filePath != null
|
||||
});
|
||||
|
||||
async function handleOpen() {
|
||||
const absolutePath = queriedFullPath.data;
|
||||
if (!absolutePath) return;
|
||||
try {
|
||||
await FileViewer.open(absolutePath, {
|
||||
// Android only
|
||||
showAppsSuggestions: false, // If there is not an installed app that can open the file, open the Play Store with suggested apps
|
||||
showOpenWithDialog: true // if there is more than one app that can open the file, show an Open With dialogue box
|
||||
});
|
||||
filePath &&
|
||||
filePath.object_id &&
|
||||
updateAccessTime.mutateAsync([filePath.object_id]).catch(console.error);
|
||||
} catch (error) {
|
||||
// TODO: Handle Error & toast message
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -99,6 +130,8 @@ export const ActionsModal = () => {
|
|||
<View style={tw`my-3`} />
|
||||
{/* Actions */}
|
||||
<ActionsContainer>
|
||||
<ActionsItem title="Open" onPress={handleOpen} />
|
||||
<ActionDivider />
|
||||
<ActionsItem
|
||||
icon={Info}
|
||||
title="Show Info"
|
||||
|
|
|
@ -7,26 +7,19 @@ import OverviewSection from './OverviewSection';
|
|||
|
||||
const Cloud = () => {
|
||||
return (
|
||||
<View>
|
||||
<OverviewSection title="Cloud Drives" count={0}>
|
||||
<View style={tw`px-7`}>
|
||||
<NewCard
|
||||
icons={[
|
||||
'DriveAmazonS3',
|
||||
'DriveDropbox',
|
||||
'DriveGoogleDrive',
|
||||
'DriveOneDrive'
|
||||
]}
|
||||
text="Connect your cloud accounts to Spacedrive."
|
||||
button={() => (
|
||||
<Button variant="transparent">
|
||||
<Text style={tw`font-bold text-ink-dull`}>Coming soon</Text>
|
||||
</Button>
|
||||
)}
|
||||
/>
|
||||
</View>
|
||||
</OverviewSection>
|
||||
</View>
|
||||
<OverviewSection title="Cloud Drives" count={0}>
|
||||
<View style={tw`px-7`}>
|
||||
<NewCard
|
||||
icons={['DriveAmazonS3', 'DriveDropbox', 'DriveGoogleDrive', 'DriveOneDrive']}
|
||||
text="Connect your cloud accounts to Spacedrive."
|
||||
button={() => (
|
||||
<Button variant="transparent">
|
||||
<Text style={tw`font-bold text-ink-dull`}>Coming soon</Text>
|
||||
</Button>
|
||||
)}
|
||||
/>
|
||||
</View>
|
||||
</OverviewSection>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ const Locations = ({ locations }: Props) => {
|
|||
const modalRef = useRef<ModalRef>(null);
|
||||
|
||||
return (
|
||||
<View>
|
||||
<>
|
||||
<OverviewSection title="Locations" count={locations?.length}>
|
||||
<View style={tw`flex-row items-center`}>
|
||||
<Fade height={'100%'} width={30} color="mobile-screen">
|
||||
|
@ -80,7 +80,7 @@ const Locations = ({ locations }: Props) => {
|
|||
</View>
|
||||
</OverviewSection>
|
||||
<ImportModal ref={modalRef} />
|
||||
</View>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -94,20 +94,6 @@ window.screen = {
|
|||
height
|
||||
};
|
||||
|
||||
/*
|
||||
https://github.com/facebook/hermes/issues/23
|
||||
|
||||
We are using "Hermes" on Android & IOS, which for the current version (0.11),
|
||||
IOS does not support the Intl fully so we need polyfill it.
|
||||
|
||||
NOTE: We can be picky about what we "polyfill" to optimize but for now this works.
|
||||
*/
|
||||
|
||||
if (Platform.OS === 'ios') {
|
||||
require('intl'); // import intl object
|
||||
require('intl/locale-data/jsonp/en');
|
||||
}
|
||||
|
||||
// This is insane. We load all data from `AsyncStorage` into the `_localStorage` global and then once complete we import the app.
|
||||
// This way the polyfilled `localStorage` implementation has its data populated before the global stores within `@sd/client` are initialized (as they are initialized on import).
|
||||
const App = lazy(async () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useEffect, useMemo } from 'react';
|
||||
import { useEffect, useMemo } from 'react';
|
||||
import { useCache, useLibraryQuery, useNodes } from '@sd/client';
|
||||
import Explorer from '~/components/explorer/Explorer';
|
||||
import { BrowseStackScreenProps } from '~/navigation/tabs/BrowseStack';
|
||||
|
@ -11,21 +11,23 @@ export default function LocationScreen({ navigation, route }: BrowseStackScreenP
|
|||
useNodes(location.data?.nodes);
|
||||
const locationData = useCache(location.data?.item);
|
||||
|
||||
const { data } = useLibraryQuery([
|
||||
const paths = useLibraryQuery([
|
||||
'search.paths',
|
||||
{
|
||||
filters: [
|
||||
{
|
||||
filePath: {
|
||||
locations: { in: [id] },
|
||||
path: { path: path ?? '', location_id: id, include_descendants: false }
|
||||
locations: { in: [id] }
|
||||
// path: {location_id: id, path: path ?? '', include_descendants: true} // FIXME: This is the correct query, but it doesn't work and then provides a deserialization error.
|
||||
}
|
||||
}
|
||||
],
|
||||
take: 100
|
||||
}
|
||||
]);
|
||||
const pathsItemsReferences = useMemo(() => data?.items ?? [], [data]);
|
||||
|
||||
const pathsItemsReferences = useMemo(() => paths.data?.items ?? [], [paths.data]);
|
||||
useNodes(paths.data?.nodes);
|
||||
const pathsItems = useCache(pathsItemsReferences);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -2,10 +2,13 @@ import { proxy, useSnapshot } from 'valtio';
|
|||
import { proxySet } from 'valtio/utils';
|
||||
import { resetStore } from '@sd/client';
|
||||
|
||||
// TODO: Add "media"
|
||||
export type ExplorerLayoutMode = 'list' | 'grid' | 'media';
|
||||
|
||||
export type ExplorerKind = 'Location' | 'Tag' | 'Space';
|
||||
export enum ExplorerKind {
|
||||
Location,
|
||||
Tag,
|
||||
Space
|
||||
}
|
||||
|
||||
const state = {
|
||||
locationId: null as number | null,
|
||||
|
|
|
@ -251,9 +251,7 @@ function Options({
|
|||
<Tooltip label={t('pause')}>
|
||||
<Button
|
||||
className="cursor-pointer"
|
||||
onClick={() => {
|
||||
pauseJob.mutate(group.id);
|
||||
}}
|
||||
onClick={() => pauseJob.mutate(group.id)}
|
||||
size="icon"
|
||||
variant="outline"
|
||||
>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { byteSize } from '.';
|
||||
import { getItemFilePath, getItemLocation, getItemObject, type ObjectKindKey } from '..';
|
||||
import type { ExplorerItem } from '../core';
|
||||
import { ObjectKind } from './objectKind';
|
||||
import { getItemFilePath, getItemLocation, getItemObject } from '../utils';
|
||||
import { byteSize } from './byte-size';
|
||||
import { ObjectKind, ObjectKindKey } from './objectKind';
|
||||
|
||||
// ItemData is a single data structure understood by the Explorer, we map all ExplorerItems to this structure in this file
|
||||
// we use `null` instead of `?` optional values intentionally
|
||||
|
|
|
@ -397,9 +397,6 @@ importers:
|
|||
expo-status-bar:
|
||||
specifier: ~1.11.1
|
||||
version: 1.11.1
|
||||
intl:
|
||||
specifier: ^1.2.5
|
||||
version: 1.2.5
|
||||
lottie-react-native:
|
||||
specifier: 6.5.1
|
||||
version: 6.5.1(react-native@0.73.4)(react@18.2.0)
|
||||
|
@ -427,6 +424,9 @@ importers:
|
|||
react-native-document-picker:
|
||||
specifier: ^9.0.1
|
||||
version: 9.0.1(react-native@0.73.4)(react@18.2.0)
|
||||
react-native-file-viewer:
|
||||
specifier: ^2.1.5
|
||||
version: 2.1.5(react-native@0.73.4)
|
||||
react-native-fs:
|
||||
specifier: ^2.20.0
|
||||
version: 2.20.0(react-native@0.73.4)
|
||||
|
@ -6565,7 +6565,7 @@ packages:
|
|||
magic-string: 0.27.0
|
||||
react-docgen-typescript: 2.2.2(typescript@5.3.3)
|
||||
typescript: 5.3.3
|
||||
vite: 5.0.10(less@4.2.0)
|
||||
vite: 5.0.10(@types/node@18.17.19)
|
||||
|
||||
/@jridgewell/gen-mapping@0.3.3:
|
||||
resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==}
|
||||
|
@ -10043,7 +10043,7 @@ packages:
|
|||
magic-string: 0.30.5
|
||||
rollup: 3.29.4
|
||||
typescript: 5.3.3
|
||||
vite: 5.0.10(less@4.2.0)
|
||||
vite: 5.0.10(@types/node@18.17.19)
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
- supports-color
|
||||
|
@ -10396,7 +10396,7 @@ packages:
|
|||
react: 18.2.0
|
||||
react-docgen: 6.0.4
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
vite: 5.0.10(less@4.2.0)
|
||||
vite: 5.0.10(@types/node@18.17.19)
|
||||
transitivePeerDependencies:
|
||||
- '@preact/preset-vite'
|
||||
- encoding
|
||||
|
@ -10636,7 +10636,7 @@ packages:
|
|||
dependencies:
|
||||
'@babel/core': 7.23.2
|
||||
'@svgr/babel-preset': 8.1.0(@babel/core@7.23.2)
|
||||
'@svgr/core': 8.1.0(typescript@5.2.2)
|
||||
'@svgr/core': 8.1.0(typescript@5.3.3)
|
||||
'@svgr/hast-util-to-babel-ast': 8.0.0
|
||||
svg-parser: 2.0.4
|
||||
transitivePeerDependencies:
|
||||
|
@ -11841,7 +11841,7 @@ packages:
|
|||
'@babel/plugin-transform-react-jsx-source': 7.22.5(@babel/core@7.23.7)
|
||||
magic-string: 0.27.0
|
||||
react-refresh: 0.14.0
|
||||
vite: 5.0.10(less@4.2.0)
|
||||
vite: 5.0.10(@types/node@18.17.19)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
|
@ -12489,21 +12489,8 @@ packages:
|
|||
- supports-color
|
||||
dev: false
|
||||
|
||||
/babel-plugin-jsx-dom-expressions@0.37.11(@babel/core@7.23.7):
|
||||
resolution: {integrity: sha512-0NaWy4sFsE0AWlucvL/myEiZ851BgjeLwhtctOFmyVCK6fPXqQHQUBB5SrrrmvOiw/BZCmMe8dOy7JL3FSyTtQ==}
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.20.12
|
||||
dependencies:
|
||||
'@babel/core': 7.23.7
|
||||
'@babel/helper-module-imports': 7.18.6
|
||||
'@babel/plugin-syntax-jsx': 7.23.3(@babel/core@7.23.7)
|
||||
'@babel/types': 7.23.6
|
||||
html-entities: 2.3.3
|
||||
validate-html-nesting: 1.2.2
|
||||
dev: true
|
||||
|
||||
/babel-plugin-jsx-dom-expressions@0.37.13(@babel/core@7.23.2):
|
||||
resolution: {integrity: sha512-oAEMMIgU0h1DmHn4ZDaBBFc08nsVJciLq9pF7g0ZdpeIDKfY4zXjXr8+/oBjKhXG8nyomhnTodPjeG+/ZXcWXQ==}
|
||||
/babel-plugin-jsx-dom-expressions@0.37.17(@babel/core@7.23.2):
|
||||
resolution: {integrity: sha512-1bv8rOTzs6TR3DVyVZ7ElxyPEhnS556FMWRIsB3gBPfkn/cSKaLvXLGk+X1lvI+SzcUo4G+UcmJrn3vr1ig8mQ==}
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.20.12
|
||||
dependencies:
|
||||
|
@ -12515,6 +12502,19 @@ packages:
|
|||
validate-html-nesting: 1.2.2
|
||||
dev: false
|
||||
|
||||
/babel-plugin-jsx-dom-expressions@0.37.17(@babel/core@7.23.7):
|
||||
resolution: {integrity: sha512-1bv8rOTzs6TR3DVyVZ7ElxyPEhnS556FMWRIsB3gBPfkn/cSKaLvXLGk+X1lvI+SzcUo4G+UcmJrn3vr1ig8mQ==}
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.20.12
|
||||
dependencies:
|
||||
'@babel/core': 7.23.7
|
||||
'@babel/helper-module-imports': 7.18.6
|
||||
'@babel/plugin-syntax-jsx': 7.23.3(@babel/core@7.23.7)
|
||||
'@babel/types': 7.23.6
|
||||
html-entities: 2.3.3
|
||||
validate-html-nesting: 1.2.2
|
||||
dev: true
|
||||
|
||||
/babel-plugin-module-resolver@5.0.0:
|
||||
resolution: {integrity: sha512-g0u+/ChLSJ5+PzYwLwP8Rp8Rcfowz58TJNCe+L/ui4rpzE/mg//JVX0EWBUYoxaextqnwuGHzfGp2hh0PPV25Q==}
|
||||
engines: {node: '>= 16'}
|
||||
|
@ -12730,13 +12730,13 @@ packages:
|
|||
babel-plugin-syntax-trailing-function-commas: 7.0.0-beta.0
|
||||
dev: false
|
||||
|
||||
/babel-preset-solid@1.8.8(@babel/core@7.23.7):
|
||||
resolution: {integrity: sha512-m+sFxzriUgMiyUPz/oWxU+N6PwY2bVsZVlc4Jxx+5XhDt5lGE/meg+ZL/kLgSAZ75YuU9AJZr444Un1bO0vhJQ==}
|
||||
/babel-preset-solid@1.8.15(@babel/core@7.23.7):
|
||||
resolution: {integrity: sha512-P2yOQbB7Hn/m4YvpXV6ExHIMcgNWXWXcvY4kJzG3yqAB3hKS58OZRsvJ7RObsZWqXRvZTITBIwnpK0BMGu+ZIQ==}
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.0.0
|
||||
dependencies:
|
||||
'@babel/core': 7.23.7
|
||||
babel-plugin-jsx-dom-expressions: 0.37.11(@babel/core@7.23.7)
|
||||
babel-plugin-jsx-dom-expressions: 0.37.17(@babel/core@7.23.7)
|
||||
dev: true
|
||||
|
||||
/babel-preset-solid@1.8.9(@babel/core@7.23.2):
|
||||
|
@ -12745,7 +12745,7 @@ packages:
|
|||
'@babel/core': ^7.0.0
|
||||
dependencies:
|
||||
'@babel/core': 7.23.2
|
||||
babel-plugin-jsx-dom-expressions: 0.37.13(@babel/core@7.23.2)
|
||||
babel-plugin-jsx-dom-expressions: 0.37.17(@babel/core@7.23.2)
|
||||
dev: false
|
||||
|
||||
/bail@2.0.2:
|
||||
|
@ -16953,10 +16953,6 @@ packages:
|
|||
hasown: 2.0.0
|
||||
side-channel: 1.0.4
|
||||
|
||||
/intl@1.2.5:
|
||||
resolution: {integrity: sha512-rK0KcPHeBFBcqsErKSpvZnrOmWOj+EmDkyJ57e90YWaQNqbcivcqmKDlHEeNprDWOsKzPsh1BfSpPQdDvclHVw==}
|
||||
dev: false
|
||||
|
||||
/invariant@2.2.4:
|
||||
resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==}
|
||||
dependencies:
|
||||
|
@ -21190,6 +21186,14 @@ packages:
|
|||
resolution: {integrity: sha512-BWIKcEYtzjRV6GpkX0Km5/w2E7fgIcywiQOT7JZTc5NSbv/YI9kpFinB9lRFsOoRVGmiqq/O3VfP/oH2clIiBA==}
|
||||
dev: false
|
||||
|
||||
/react-native-file-viewer@2.1.5(react-native@0.73.4):
|
||||
resolution: {integrity: sha512-MGC6sx9jsqHdefhVQ6o0akdsPGpkXgiIbpygb2Sg4g4bh7v6K1cardLV1NwGB9A6u1yICOSDT/MOC//9Ez6EUg==}
|
||||
peerDependencies:
|
||||
react-native: '>=0.47'
|
||||
dependencies:
|
||||
react-native: 0.73.4(@babel/core@7.23.2)(@babel/preset-env@7.23.8)(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/react-native-fs@2.20.0(react-native@0.73.4):
|
||||
resolution: {integrity: sha512-VkTBzs7fIDUiy/XajOSNk0XazFE9l+QlMAce7lGuebZcag5CnjszB+u4BdqzwaQOdcYb5wsJIsqq4kxInIRpJQ==}
|
||||
peerDependencies:
|
||||
|
@ -22371,15 +22375,9 @@ packages:
|
|||
seroval: 1.0.4
|
||||
dev: true
|
||||
|
||||
/seroval@1.0.3:
|
||||
resolution: {integrity: sha512-v5Psun3O2OdehTS/BpTC9EezHxyQRM4lqtvOdbngEq8qOZUECqG5XaoFNZgBQrJKXZFgcyZtMH6Dv7G96pKSSQ==}
|
||||
engines: {node: '>=10'}
|
||||
dev: false
|
||||
|
||||
/seroval@1.0.4:
|
||||
resolution: {integrity: sha512-qQs/N+KfJu83rmszFQaTxcoJoPn6KNUruX4KmnmyD0oZkUoiNvJ1rpdYKDf4YHM05k+HOgCxa3yvf15QbVijGg==}
|
||||
engines: {node: '>=10'}
|
||||
dev: true
|
||||
|
||||
/serve-static@1.15.0:
|
||||
resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==}
|
||||
|
@ -22582,8 +22580,8 @@ packages:
|
|||
/solid-js@1.8.8:
|
||||
resolution: {integrity: sha512-9CtL5xWTYX1WWjQKqht3Tl0AJzgz4YWVQk8hoscO9TzRCgzlpAauEOexXa6bPG30W+fWLnFVE7XUiAzQFNeUKw==}
|
||||
dependencies:
|
||||
csstype: 3.1.2
|
||||
seroval: 1.0.3
|
||||
csstype: 3.1.3
|
||||
seroval: 1.0.4
|
||||
dev: false
|
||||
|
||||
/solid-refresh@0.5.3(solid-js@1.8.11):
|
||||
|
@ -24701,7 +24699,7 @@ packages:
|
|||
'@babel/core': 7.23.7
|
||||
'@babel/preset-typescript': 7.23.3(@babel/core@7.23.7)
|
||||
'@types/babel__core': 7.20.5
|
||||
babel-preset-solid: 1.8.8(@babel/core@7.23.7)
|
||||
babel-preset-solid: 1.8.15(@babel/core@7.23.7)
|
||||
merge-anything: 5.1.7
|
||||
solid-js: 1.8.11
|
||||
solid-refresh: 0.5.3(solid-js@1.8.11)
|
||||
|
@ -24827,7 +24825,6 @@ packages:
|
|||
rollup: 4.9.2
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
dev: true
|
||||
|
||||
/vite@5.0.10(less@4.2.0):
|
||||
resolution: {integrity: sha512-2P8J7WWgmc355HUMlFrwofacvr98DAjoE52BfdbwQtyLH06XKwaL/FMnmKM2crF0iX4MpmMKoDlNCB1ok7zHCw==}
|
||||
|
@ -24863,6 +24860,7 @@ packages:
|
|||
rollup: 4.9.2
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
dev: true
|
||||
|
||||
/vite@5.0.10(sass@1.69.5):
|
||||
resolution: {integrity: sha512-2P8J7WWgmc355HUMlFrwofacvr98DAjoE52BfdbwQtyLH06XKwaL/FMnmKM2crF0iX4MpmMKoDlNCB1ok7zHCw==}
|
||||
|
|
Loading…
Reference in a new issue