saf directory
This commit is contained in:
@@ -1,16 +0,0 @@
|
|||||||
import { createContext, useCallback, useContext, useMemo, useState } from 'react';
|
|
||||||
|
|
||||||
const AuthContext = createContext(null);
|
|
||||||
|
|
||||||
export function AuthProvider({ children }) {
|
|
||||||
|
|
||||||
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useAuth() {
|
|
||||||
const ctx = useContext(AuthContext);
|
|
||||||
if (!ctx) {
|
|
||||||
throw new Error('useAuth must be used within an AuthProvider');
|
|
||||||
}
|
|
||||||
return ctx;
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { createContext, useCallback, useContext, useMemo, useState } from 'react';
|
||||||
|
import type { ReactNode } from 'react';
|
||||||
|
|
||||||
|
export type User = {
|
||||||
|
};
|
||||||
|
|
||||||
|
type AuthContextValue = {
|
||||||
|
user: User | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const AuthContext = createContext<AuthContextValue | null>(null);
|
||||||
|
|
||||||
|
export function AuthProvider({ children }: { children: ReactNode }) {
|
||||||
|
const [user, setUser] = useState<User | null>(null);
|
||||||
|
|
||||||
|
const value = useMemo(() => ({ user }), [user]);
|
||||||
|
|
||||||
|
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useAuth(): AuthContextValue {
|
||||||
|
const ctx = useContext(AuthContext);
|
||||||
|
if (!ctx) {
|
||||||
|
throw new Error('useAuth must be used within an AuthProvider');
|
||||||
|
}
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
Generated
+16
-15
@@ -10,10 +10,12 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"expo": "~57.0.8",
|
"expo": "~57.0.8",
|
||||||
"expo-constants": "~57.0.17",
|
"expo-constants": "~57.0.17",
|
||||||
|
"expo-file-system": "~57.0.6",
|
||||||
"expo-linking": "~57.0.9",
|
"expo-linking": "~57.0.9",
|
||||||
"expo-router": "~57.0.20",
|
"expo-router": "~57.0.20",
|
||||||
"expo-status-bar": "~57.0.1",
|
"expo-status-bar": "~57.0.1",
|
||||||
"react": "19.2.3",
|
"react": "19.2.3",
|
||||||
|
"react-dom": "19.2.3",
|
||||||
"react-native": "0.86.0",
|
"react-native": "0.86.0",
|
||||||
"react-native-safe-area-context": "~5.7.0",
|
"react-native-safe-area-context": "~5.7.0",
|
||||||
"react-native-screens": "~4.26.0"
|
"react-native-screens": "~4.26.0"
|
||||||
@@ -3495,6 +3497,16 @@
|
|||||||
"react-native": "*"
|
"react-native": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/expo-file-system": {
|
||||||
|
"version": "57.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-57.0.6.tgz",
|
||||||
|
"integrity": "sha512-pm8PMYEW6BnVOCBJ7df9FcDmQtE1tqImuYphlfYe1ipQRLYtdCayRczJcbKIsnB3mqEyp4gC2gWmMbsAsAOjVg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"expo": "*",
|
||||||
|
"react-native": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/expo-font": {
|
"node_modules/expo-font": {
|
||||||
"version": "57.0.3",
|
"version": "57.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/expo-font/-/expo-font-57.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/expo-font/-/expo-font-57.0.3.tgz",
|
||||||
@@ -4052,16 +4064,6 @@
|
|||||||
"react-native": "*"
|
"react-native": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/expo/node_modules/expo-file-system": {
|
|
||||||
"version": "57.0.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-57.0.6.tgz",
|
|
||||||
"integrity": "sha512-pm8PMYEW6BnVOCBJ7df9FcDmQtE1tqImuYphlfYe1ipQRLYtdCayRczJcbKIsnB3mqEyp4gC2gWmMbsAsAOjVg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peerDependencies": {
|
|
||||||
"expo": "*",
|
|
||||||
"react-native": "*"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/expo/node_modules/expo-keep-awake": {
|
"node_modules/expo/node_modules/expo-keep-awake": {
|
||||||
"version": "57.0.1",
|
"version": "57.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-57.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-57.0.1.tgz",
|
||||||
@@ -6049,16 +6051,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-dom": {
|
"node_modules/react-dom": {
|
||||||
"version": "19.2.8",
|
"version": "19.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.8.tgz",
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz",
|
||||||
"integrity": "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==",
|
"integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"scheduler": "^0.27.0"
|
"scheduler": "^0.27.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "^19.2.8"
|
"react": "^19.2.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-fast-compare": {
|
"node_modules/react-fast-compare": {
|
||||||
|
|||||||
@@ -5,10 +5,12 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"expo": "~57.0.8",
|
"expo": "~57.0.8",
|
||||||
"expo-constants": "~57.0.17",
|
"expo-constants": "~57.0.17",
|
||||||
|
"expo-file-system": "~57.0.6",
|
||||||
"expo-linking": "~57.0.9",
|
"expo-linking": "~57.0.9",
|
||||||
"expo-router": "~57.0.20",
|
"expo-router": "~57.0.20",
|
||||||
"expo-status-bar": "~57.0.1",
|
"expo-status-bar": "~57.0.1",
|
||||||
"react": "19.2.3",
|
"react": "19.2.3",
|
||||||
|
"react-dom": "19.2.3",
|
||||||
"react-native": "0.86.0",
|
"react-native": "0.86.0",
|
||||||
"react-native-safe-area-context": "~5.7.0",
|
"react-native-safe-area-context": "~5.7.0",
|
||||||
"react-native-screens": "~4.26.0"
|
"react-native-screens": "~4.26.0"
|
||||||
|
|||||||
@@ -0,0 +1,129 @@
|
|||||||
|
import { Directory, File, Paths } from 'expo-file-system';
|
||||||
|
|
||||||
|
export type Folder = {
|
||||||
|
uri: string;
|
||||||
|
name: string;
|
||||||
|
isDirectory: true;
|
||||||
|
exists?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type FileEntry = {
|
||||||
|
uri: string;
|
||||||
|
name: string;
|
||||||
|
isDirectory: false;
|
||||||
|
extension: string;
|
||||||
|
exists: boolean;
|
||||||
|
size: number;
|
||||||
|
type: string;
|
||||||
|
lastModified: number | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type DirectoryEntry = Folder | FileEntry;
|
||||||
|
|
||||||
|
export type FolderInfo = {
|
||||||
|
uri: string;
|
||||||
|
name: string;
|
||||||
|
exists: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
type PickDirectoryOptions = {
|
||||||
|
recursive?: boolean;
|
||||||
|
includeRoot?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function pickDirectory(initialUri?: string): Promise<Folder | null> {
|
||||||
|
try {
|
||||||
|
const directory = await Directory.pickDirectoryAsync(initialUri);
|
||||||
|
if (!directory || !directory.uri) return null;
|
||||||
|
return toFolder({ uri: directory.uri, name: directory.name, exists: directory.exists });
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function listDirectory(directoryUri: string): DirectoryEntry[] {
|
||||||
|
const directory = new Directory(directoryUri);
|
||||||
|
if (!directory.exists) return [];
|
||||||
|
try {
|
||||||
|
return directory.list().map(toEntry);
|
||||||
|
} catch {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function listFolders(directoryUri: string, options: PickDirectoryOptions = {}): Folder[] {
|
||||||
|
const { recursive = false, includeRoot = false } = options;
|
||||||
|
if (!recursive) {
|
||||||
|
return listDirectory(directoryUri).filter((entry): entry is Folder => entry.isDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
const result: Folder[] = [];
|
||||||
|
if (includeRoot) {
|
||||||
|
result.push({ ...getFolderInfo(directoryUri), isDirectory: true });
|
||||||
|
}
|
||||||
|
const visit = (uri: string) => {
|
||||||
|
for (const entry of listDirectory(uri)) {
|
||||||
|
if (entry.isDirectory) {
|
||||||
|
result.push(entry);
|
||||||
|
visit(entry.uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
visit(directoryUri);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getFolderInfo(directoryUri: string): FolderInfo {
|
||||||
|
const directory = new Directory(directoryUri);
|
||||||
|
return {
|
||||||
|
uri: directory.uri,
|
||||||
|
name: directory.name,
|
||||||
|
exists: directory.exists,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createDirectory(directoryUri: string, name: string): Folder {
|
||||||
|
const directory = new Directory(Paths.join(directoryUri, name));
|
||||||
|
directory.create({ idempotent: true, intermediates: true });
|
||||||
|
return toFolder({ uri: directory.uri, name: directory.name, exists: directory.exists });
|
||||||
|
}
|
||||||
|
|
||||||
|
export function fileFromUri(uri: string): FileEntry {
|
||||||
|
const file = new File(uri);
|
||||||
|
return {
|
||||||
|
uri: file.uri,
|
||||||
|
name: file.name,
|
||||||
|
isDirectory: false,
|
||||||
|
extension: file.extension,
|
||||||
|
exists: file.exists,
|
||||||
|
size: file.size,
|
||||||
|
type: file.type,
|
||||||
|
lastModified: file.lastModified,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function toEntry(item: Directory | File): DirectoryEntry {
|
||||||
|
if (item instanceof Directory) {
|
||||||
|
return toFolder({ uri: item.uri, name: item.name, exists: item.exists });
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
uri: item.uri,
|
||||||
|
name: item.name,
|
||||||
|
isDirectory: false,
|
||||||
|
extension: item.extension,
|
||||||
|
exists: item.exists,
|
||||||
|
size: item.size,
|
||||||
|
type: item.type,
|
||||||
|
lastModified: item.lastModified,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function toFolder({ uri, name, exists }: { uri: string; name?: string; exists?: boolean }): Folder {
|
||||||
|
const directory = exists === undefined ? new Directory(uri) : null;
|
||||||
|
return {
|
||||||
|
uri,
|
||||||
|
name: name ?? directory?.name ?? Paths.basename(uri),
|
||||||
|
isDirectory: true,
|
||||||
|
exists: exists ?? directory?.exists,
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user