mirror of
https://github.com/Stef-00012/Zipline-Android-App.git
synced 2025-05-11 18:35:58 +02:00
[nobuild] .
This commit is contained in:
parent
3f586399de
commit
aa36fbb91e
9 changed files with 809 additions and 718 deletions
|
@ -18,6 +18,7 @@ import { isLightColor } from "@/functions/color";
|
|||
import { colorHash } from "@/functions/util";
|
||||
import LargeFileDisplay from "@/components/LargeFileDisplay";
|
||||
import TextInput from "@/components/TextInput";
|
||||
import Button from "@/components/Button";
|
||||
|
||||
export default function Files() {
|
||||
const router = useRouter();
|
||||
|
@ -145,19 +146,20 @@ export default function Files() {
|
|||
<Text style={styles.headerText}>Tags</Text>
|
||||
|
||||
<View style={styles.headerButtons}>
|
||||
<Pressable
|
||||
style={styles.headerButton}
|
||||
<Button
|
||||
onPress={() => {
|
||||
setCreateNewTag(true)
|
||||
setTagsMenuOpen(false)
|
||||
}}
|
||||
>
|
||||
<MaterialIcons
|
||||
name="add"
|
||||
size={30}
|
||||
color={styles.headerButton.color}
|
||||
/>
|
||||
</Pressable>
|
||||
icon="add"
|
||||
color="transparent"
|
||||
iconColor="#2d3f70"
|
||||
borderColor="#222c47"
|
||||
borderWidth={2}
|
||||
iconSize={30}
|
||||
padding={4}
|
||||
rippleColor="#283557"
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
|
@ -174,47 +176,54 @@ export default function Files() {
|
|||
</View>
|
||||
|
||||
<View style={styles.tagButtonContainer}>
|
||||
<Pressable style={styles.tagButton}>
|
||||
<MaterialIcons
|
||||
name="edit"
|
||||
size={20}
|
||||
color={"white"}
|
||||
onPress={() => {
|
||||
setTagToEdit(tag)
|
||||
setTagsMenuOpen(false)
|
||||
}}
|
||||
/>
|
||||
</Pressable>
|
||||
<Button
|
||||
icon="edit"
|
||||
color="#323ea8"
|
||||
onPress={() => {
|
||||
setTagToEdit(tag)
|
||||
setTagsMenuOpen(false)
|
||||
}}
|
||||
iconSize={20}
|
||||
width={32}
|
||||
height={32}
|
||||
padding={6}
|
||||
margin={{
|
||||
left: 5,
|
||||
right: 5
|
||||
}}
|
||||
/>
|
||||
|
||||
<Pressable style={{
|
||||
...styles.tagButton,
|
||||
...styles.tagButtonDanger
|
||||
}}>
|
||||
<MaterialIcons
|
||||
name="delete"
|
||||
size={20}
|
||||
color={"white"}
|
||||
onPress={async () => {
|
||||
const tagId = tag.id
|
||||
<Button
|
||||
icon="delete"
|
||||
color="#CF4238"
|
||||
onPress={async () => {
|
||||
const tagId = tag.id
|
||||
|
||||
const success = await deleteTag(tagId)
|
||||
const success = await deleteTag(tagId)
|
||||
|
||||
if (typeof success === "string") return ToastAndroid.show(
|
||||
`Failed to delete the tag "${tag.name}"`,
|
||||
ToastAndroid.SHORT
|
||||
)
|
||||
if (typeof success === "string") return ToastAndroid.show(
|
||||
`Failed to delete the tag "${tag.name}"`,
|
||||
ToastAndroid.SHORT
|
||||
)
|
||||
|
||||
const newTags = tags.filter(tg => tag.id !== tg.id)
|
||||
const newTags = tags.filter(tg => tag.id !== tg.id)
|
||||
|
||||
setTags(newTags)
|
||||
setTags(newTags)
|
||||
|
||||
ToastAndroid.show(
|
||||
`Deleted the tag "${tag.name}"`,
|
||||
ToastAndroid.SHORT
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</Pressable>
|
||||
ToastAndroid.show(
|
||||
`Deleted the tag "${tag.name}"`,
|
||||
ToastAndroid.SHORT
|
||||
)
|
||||
}}
|
||||
iconSize={20}
|
||||
width={32}
|
||||
height={32}
|
||||
padding={6}
|
||||
margin={{
|
||||
left: 5,
|
||||
right: 5
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
))}
|
||||
|
@ -256,26 +265,25 @@ export default function Files() {
|
|||
/>
|
||||
|
||||
<View style={styles.manageTagButtonsContainer}>
|
||||
<Pressable
|
||||
style={{
|
||||
...styles.button,
|
||||
...styles.manageTagButton,
|
||||
...styles.guessButton
|
||||
}}
|
||||
<Button
|
||||
color="#616060"
|
||||
text="Guess Color"
|
||||
onPress={async () => {
|
||||
const guess = colorHash(newTagName || "")
|
||||
|
||||
setNewTagColor(guess)
|
||||
}}
|
||||
>
|
||||
<Text style={styles.buttonText}>Guess Color</Text>
|
||||
</Pressable>
|
||||
|
||||
<Pressable
|
||||
style={{
|
||||
...styles.button,
|
||||
...styles.manageTagButton
|
||||
width="45%"
|
||||
margin={{
|
||||
left: "2.5%",
|
||||
right: "2.5%",
|
||||
top: 15
|
||||
}}
|
||||
/>
|
||||
|
||||
<Button
|
||||
color="#323ea8"
|
||||
text="Create"
|
||||
onPress={async () => {
|
||||
setNewTagError(null);
|
||||
|
||||
|
@ -297,9 +305,13 @@ export default function Files() {
|
|||
setCreateNewTag(false);
|
||||
setTagsMenuOpen(true)
|
||||
}}
|
||||
>
|
||||
<Text style={styles.buttonText}>Create</Text>
|
||||
</Pressable>
|
||||
width="45%"
|
||||
margin={{
|
||||
left: "2.5%",
|
||||
right: "2.5%",
|
||||
top: 15
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<Text
|
||||
|
@ -340,26 +352,25 @@ export default function Files() {
|
|||
/>
|
||||
|
||||
<View style={styles.manageTagButtonsContainer}>
|
||||
<Pressable
|
||||
style={{
|
||||
...styles.button,
|
||||
...styles.manageTagButton,
|
||||
...styles.guessButton
|
||||
}}
|
||||
<Button
|
||||
color="#616060"
|
||||
text="Guess Color"
|
||||
onPress={async () => {
|
||||
const guess = colorHash(editTagName || "")
|
||||
|
||||
setEditTagColor(guess)
|
||||
}}
|
||||
>
|
||||
<Text style={styles.buttonText}>Guess Color</Text>
|
||||
</Pressable>
|
||||
|
||||
<Pressable
|
||||
style={{
|
||||
...styles.button,
|
||||
...styles.manageTagButton
|
||||
width="45%"
|
||||
margin={{
|
||||
left: "2.5%",
|
||||
right: "2.5%",
|
||||
top: 15
|
||||
}}
|
||||
/>
|
||||
|
||||
<Button
|
||||
color="#323ea8"
|
||||
text="Create"
|
||||
onPress={async () => {
|
||||
setEditTagError(null);
|
||||
|
||||
|
@ -386,9 +397,13 @@ export default function Files() {
|
|||
setTagToEdit(null);
|
||||
setTagsMenuOpen(true)
|
||||
}}
|
||||
>
|
||||
<Text style={styles.buttonText}>Edit</Text>
|
||||
</Pressable>
|
||||
width="45%"
|
||||
margin={{
|
||||
left: "2.5%",
|
||||
right: "2.5%",
|
||||
top: 15
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<Text
|
||||
|
@ -406,49 +421,64 @@ export default function Files() {
|
|||
|
||||
{!isFolder && (
|
||||
<View style={styles.headerButtons}>
|
||||
<Pressable
|
||||
disabled={!files}
|
||||
style={styles.headerButton}
|
||||
<Button
|
||||
onPress={() => {
|
||||
setFavorites((prev) => !prev);
|
||||
}}
|
||||
>
|
||||
<MaterialIcons
|
||||
name={favorites ? "star" : "star-border"}
|
||||
size={30}
|
||||
color={favorites ? styles.headerStarButtonActive.color : styles.headerButton.color}
|
||||
/>
|
||||
</Pressable>
|
||||
icon={favorites ? "star" : "star-border"}
|
||||
color="transparent"
|
||||
iconColor={favorites ? "#f1d01f" : "#2d3f70"}
|
||||
borderColor="#222c47"
|
||||
borderWidth={2}
|
||||
iconSize={30}
|
||||
padding={4}
|
||||
rippleColor="#283557"
|
||||
disabled={!files}
|
||||
margin={{
|
||||
left: 2,
|
||||
right: 2
|
||||
}}
|
||||
/>
|
||||
|
||||
{!name && (
|
||||
<>
|
||||
<Pressable
|
||||
disabled={!files}
|
||||
style={styles.headerButton}
|
||||
<Button
|
||||
onPress={() => {
|
||||
setTagsMenuOpen(true)
|
||||
}}
|
||||
>
|
||||
<MaterialIcons
|
||||
name="sell"
|
||||
size={30}
|
||||
color={styles.headerButton.color}
|
||||
/>
|
||||
</Pressable>
|
||||
|
||||
<Pressable
|
||||
icon="sell"
|
||||
color="transparent"
|
||||
iconColor="#2d3f70"
|
||||
borderColor="#222c47"
|
||||
borderWidth={2}
|
||||
iconSize={30}
|
||||
disabled={!files}
|
||||
style={styles.headerButton}
|
||||
padding={4}
|
||||
rippleColor="#283557"
|
||||
margin={{
|
||||
left: 2,
|
||||
right: 2
|
||||
}}
|
||||
/>
|
||||
|
||||
<Button
|
||||
onPress={() => {
|
||||
router.replace("/upload/file")
|
||||
}}
|
||||
>
|
||||
<MaterialIcons
|
||||
name="upload-file"
|
||||
size={30}
|
||||
color={styles.headerButton.color}
|
||||
/>
|
||||
</Pressable>
|
||||
icon="upload-file"
|
||||
color="transparent"
|
||||
iconColor="#2d3f70"
|
||||
borderColor="#222c47"
|
||||
borderWidth={2}
|
||||
iconSize={30}
|
||||
disabled={!files}
|
||||
padding={4}
|
||||
rippleColor="#283557"
|
||||
margin={{
|
||||
left: 2,
|
||||
right: 2
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
|
@ -486,9 +516,7 @@ export default function Files() {
|
|||
|
||||
{!isFolder && (
|
||||
<View style={styles.pagesContainer}>
|
||||
<Pressable
|
||||
style={styles.pageButton}
|
||||
disabled={prevPageDisabled || allPageDisabled}
|
||||
<Button
|
||||
onPress={() => {
|
||||
setNextPageDisabled(false);
|
||||
|
||||
|
@ -504,24 +532,21 @@ export default function Files() {
|
|||
setPage(newPage);
|
||||
setSelectedPage(newPage);
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
style={
|
||||
allPageDisabled || prevPageDisabled
|
||||
? {
|
||||
...styles.pageButtonText,
|
||||
...styles.pageButtonTextDisabled,
|
||||
}
|
||||
: styles.pageButtonText
|
||||
}
|
||||
>
|
||||
PREV
|
||||
</Text>
|
||||
</Pressable>
|
||||
|
||||
<Pressable
|
||||
style={styles.pageButton}
|
||||
text="PREV"
|
||||
color="transparent"
|
||||
textColor={(allPageDisabled || prevPageDisabled) ? "gray" : "white"}
|
||||
borderColor="#222c47"
|
||||
borderWidth={2}
|
||||
rippleColor="#283557"
|
||||
flex={1}
|
||||
disabled={allPageDisabled || prevPageDisabled}
|
||||
margin={{
|
||||
left: 5,
|
||||
right: 5
|
||||
}}
|
||||
/>
|
||||
|
||||
<Button
|
||||
onPress={() => {
|
||||
setPrevPageDisabled(true);
|
||||
setNextPageDisabled(false);
|
||||
|
@ -531,20 +556,19 @@ export default function Files() {
|
|||
setPage(newPage);
|
||||
setSelectedPage(newPage);
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
style={
|
||||
allPageDisabled || prevPageDisabled
|
||||
? {
|
||||
...styles.pageButtonText,
|
||||
...styles.pageButtonTextDisabled,
|
||||
}
|
||||
: styles.pageButtonText
|
||||
}
|
||||
>
|
||||
1
|
||||
</Text>
|
||||
</Pressable>
|
||||
text="1"
|
||||
color="transparent"
|
||||
textColor={(allPageDisabled || prevPageDisabled) ? "gray" : "white"}
|
||||
borderColor="#222c47"
|
||||
borderWidth={2}
|
||||
rippleColor="#283557"
|
||||
flex={1}
|
||||
disabled={allPageDisabled || prevPageDisabled}
|
||||
margin={{
|
||||
left: 5,
|
||||
right: 5
|
||||
}}
|
||||
/>
|
||||
|
||||
<TextInput
|
||||
inputStyle={styles.input}
|
||||
|
@ -576,9 +600,7 @@ export default function Files() {
|
|||
value={selectedPage}
|
||||
/>
|
||||
|
||||
<Pressable
|
||||
style={styles.pageButton}
|
||||
disabled={allPageDisabled || nextPageDisabled}
|
||||
<Button
|
||||
onPress={() => {
|
||||
setNextPageDisabled(true);
|
||||
setPrevPageDisabled(false);
|
||||
|
@ -588,24 +610,21 @@ export default function Files() {
|
|||
setPage(newPage);
|
||||
setSelectedPage(newPage);
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
style={
|
||||
allPageDisabled || nextPageDisabled
|
||||
? {
|
||||
...styles.pageButtonText,
|
||||
...styles.pageButtonTextDisabled,
|
||||
}
|
||||
: styles.pageButtonText
|
||||
}
|
||||
>
|
||||
{files?.pages || "..."}
|
||||
</Text>
|
||||
</Pressable>
|
||||
|
||||
<Pressable
|
||||
style={styles.pageButton}
|
||||
text={files?.pages ? String(files?.pages) : "..."}
|
||||
color="transparent"
|
||||
textColor={(nextPageDisabled || allPageDisabled) ? "gray" : "white"}
|
||||
borderColor="#222c47"
|
||||
borderWidth={2}
|
||||
rippleColor="#283557"
|
||||
flex={1}
|
||||
disabled={nextPageDisabled || allPageDisabled}
|
||||
margin={{
|
||||
left: 5,
|
||||
right: 5
|
||||
}}
|
||||
/>
|
||||
|
||||
<Button
|
||||
onPress={() => {
|
||||
setPrevPageDisabled(false);
|
||||
|
||||
|
@ -618,20 +637,19 @@ export default function Files() {
|
|||
setPage(newPage);
|
||||
setSelectedPage(newPage);
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
style={
|
||||
allPageDisabled || nextPageDisabled
|
||||
? {
|
||||
...styles.pageButtonText,
|
||||
...styles.pageButtonTextDisabled,
|
||||
}
|
||||
: styles.pageButtonText
|
||||
}
|
||||
>
|
||||
NEXT
|
||||
</Text>
|
||||
</Pressable>
|
||||
text="NEXT"
|
||||
color="transparent"
|
||||
textColor={(nextPageDisabled || allPageDisabled) ? "gray" : "white"}
|
||||
borderColor="#222c47"
|
||||
borderWidth={2}
|
||||
rippleColor="#283557"
|
||||
flex={1}
|
||||
disabled={nextPageDisabled || allPageDisabled}
|
||||
margin={{
|
||||
left: 5,
|
||||
right: 5
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
|
|
|
@ -8,23 +8,25 @@ import { styles } from "@/styles/folders";
|
|||
import { useEffect, useState } from "react";
|
||||
import * as Clipboard from "expo-clipboard";
|
||||
import * as db from "@/functions/database";
|
||||
import { type ExternalPathString, Link, useRouter } from "expo-router";
|
||||
import {
|
||||
type ExternalPathString,
|
||||
Link,
|
||||
useRouter,
|
||||
} from "expo-router";
|
||||
import { createFolder, deleteFolder, editFolder, getFolders } from "@/functions/zipline/folders";
|
||||
createFolder,
|
||||
deleteFolder,
|
||||
editFolder,
|
||||
getFolders,
|
||||
} from "@/functions/zipline/folders";
|
||||
import Popup from "@/components/Popup";
|
||||
import { useAuth } from "@/hooks/useAuth";
|
||||
import { useShareIntent } from "@/hooks/useShareIntent";
|
||||
import TextInput from "@/components/TextInput";
|
||||
import Switch from "@/components/Switch"
|
||||
import Switch from "@/components/Switch";
|
||||
import Button from "@/components/Button";
|
||||
|
||||
export default function Folders() {
|
||||
const router = useRouter();
|
||||
|
||||
useAuth()
|
||||
useShareIntent()
|
||||
useAuth();
|
||||
useShareIntent();
|
||||
|
||||
const [folders, setFolders] = useState<APIFolders | null>(null);
|
||||
|
||||
|
@ -48,14 +50,19 @@ export default function Folders() {
|
|||
return (
|
||||
<View style={styles.mainContainer}>
|
||||
<View style={styles.mainContainer}>
|
||||
<Popup hidden={!createNewFolder} onClose={() => {
|
||||
setCreateNewFolder(false)
|
||||
setNewFolderName(null)
|
||||
setNewFolderPublic(false)
|
||||
}}>
|
||||
<Popup
|
||||
hidden={!createNewFolder}
|
||||
onClose={() => {
|
||||
setCreateNewFolder(false);
|
||||
setNewFolderName(null);
|
||||
setNewFolderPublic(false);
|
||||
}}
|
||||
>
|
||||
<View style={styles.popupContent}>
|
||||
<Text style={styles.mainHeaderText}>Create Folder</Text>
|
||||
{newFolderError && <Text style={styles.errorText}>{newFolderError}</Text>}
|
||||
{newFolderError && (
|
||||
<Text style={styles.errorText}>{newFolderError}</Text>
|
||||
)}
|
||||
|
||||
<TextInput
|
||||
title="Name:"
|
||||
|
@ -65,33 +72,40 @@ export default function Folders() {
|
|||
value={newFolderName || ""}
|
||||
placeholder="myFolder"
|
||||
/>
|
||||
|
||||
<Switch onValueChange={() => setNewFolderPublic((prev) => !prev)} value={newFolderPublic} title="Public" />
|
||||
|
||||
<Pressable
|
||||
style={styles.button}
|
||||
<Switch
|
||||
onValueChange={() => setNewFolderPublic((prev) => !prev)}
|
||||
value={newFolderPublic}
|
||||
title="Public"
|
||||
/>
|
||||
|
||||
<Button
|
||||
onPress={async () => {
|
||||
setNewFolderError(null)
|
||||
setNewFolderError(null);
|
||||
|
||||
if (!newFolderName || newFolderName.length <= 0) return setNewFolderError("Please insert a folder name");
|
||||
if (!newFolderName || newFolderName.length <= 0)
|
||||
return setNewFolderError("Please insert a folder name");
|
||||
|
||||
const createdFolder = await createFolder(
|
||||
newFolderName,
|
||||
newFolderPublic,
|
||||
);
|
||||
|
||||
const createdFolder = await createFolder(newFolderName, newFolderPublic);
|
||||
|
||||
if (typeof createdFolder === "string")
|
||||
return setNewFolderError(createdFolder);
|
||||
|
||||
setNewFolderName(null);
|
||||
setNewFolderPublic(false);
|
||||
|
||||
const newFolders = await getFolders()
|
||||
const newFolders = await getFolders();
|
||||
|
||||
setFolders(typeof newFolders === "string" ? null : newFolders)
|
||||
setFolders(typeof newFolders === "string" ? null : newFolders);
|
||||
|
||||
setCreateNewFolder(false);
|
||||
}}
|
||||
>
|
||||
<Text style={styles.buttonText}>Create</Text>
|
||||
</Pressable>
|
||||
text="Create"
|
||||
color="#323ea8"
|
||||
/>
|
||||
</View>
|
||||
</Popup>
|
||||
|
||||
|
@ -100,35 +114,28 @@ export default function Folders() {
|
|||
<View style={styles.header}>
|
||||
<Text style={styles.headerText}>Folders</Text>
|
||||
<View style={styles.headerButtons}>
|
||||
<Pressable
|
||||
style={styles.headerButton}
|
||||
<Button
|
||||
onPress={() => {
|
||||
setCreateNewFolder(true)
|
||||
setCreateNewFolder(true);
|
||||
}}
|
||||
>
|
||||
<MaterialIcons
|
||||
name="create-new-folder"
|
||||
size={30}
|
||||
color={styles.headerButton.color}
|
||||
/>
|
||||
</Pressable>
|
||||
icon="create-new-folder"
|
||||
color="transparent"
|
||||
iconColor="#2d3f70"
|
||||
borderColor="#222c47"
|
||||
borderWidth={2}
|
||||
iconSize={30}
|
||||
padding={4}
|
||||
rippleColor="#283557"
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View style={{ ...styles.foldersContainer, flex: 1 }}>
|
||||
<ScrollView
|
||||
showsHorizontalScrollIndicator={false}
|
||||
horizontal
|
||||
>
|
||||
<ScrollView showsHorizontalScrollIndicator={false} horizontal>
|
||||
<View>
|
||||
<Table>
|
||||
<Row
|
||||
data={[
|
||||
"Name",
|
||||
"Public",
|
||||
"Created",
|
||||
"Actions",
|
||||
]}
|
||||
data={["Name", "Public", "Created", "Actions"]}
|
||||
widthArr={[80, 50, 130, 150]}
|
||||
style={styles.tableHeader}
|
||||
textStyle={styles.rowText}
|
||||
|
@ -154,19 +161,13 @@ export default function Folders() {
|
|||
{folder.name}
|
||||
</Link>
|
||||
) : (
|
||||
<Text
|
||||
key={folder.id}
|
||||
style={styles.rowText}
|
||||
>
|
||||
<Text key={folder.id} style={styles.rowText}>
|
||||
{folder.name}
|
||||
</Text>
|
||||
)
|
||||
);
|
||||
|
||||
const isPublic = (
|
||||
<Text
|
||||
key={folder.id}
|
||||
style={styles.rowText}
|
||||
>
|
||||
<Text key={folder.id} style={styles.rowText}>
|
||||
{folder.public ? "Yes" : "No"}
|
||||
</Text>
|
||||
);
|
||||
|
@ -182,29 +183,26 @@ export default function Folders() {
|
|||
|
||||
const actions = (
|
||||
<View style={styles.actionsContainer}>
|
||||
<Pressable
|
||||
style={styles.actionButton}
|
||||
<Button
|
||||
icon="folder-open"
|
||||
color="#323ea8"
|
||||
onPress={() => {
|
||||
const folderId = folder.id;
|
||||
|
||||
router.replace(`/files?folderId=${folderId}`)
|
||||
router.replace(`/files?folderId=${folderId}`);
|
||||
}}
|
||||
>
|
||||
<MaterialIcons
|
||||
name="folder-open"
|
||||
size={20}
|
||||
color={"white"}
|
||||
/>
|
||||
</Pressable>
|
||||
iconSize={20}
|
||||
width={32}
|
||||
height={32}
|
||||
padding={6}
|
||||
/>
|
||||
|
||||
<Pressable
|
||||
style={{
|
||||
...styles.actionButton,
|
||||
...(!folder.public && styles.actionButtonDisabled)
|
||||
}}
|
||||
disabled={!folder.public}
|
||||
<Button
|
||||
icon="content-copy"
|
||||
color={folder.public ? "#323ea8" : "#181c28"}
|
||||
iconColor={folder.public ? "white" : "#2a3952"}
|
||||
onPress={async () => {
|
||||
const urlDest = `${dashUrl}/folder/${folder.id}`
|
||||
const urlDest = `${dashUrl}/folder/${folder.id}`;
|
||||
|
||||
const saved =
|
||||
await Clipboard.setStringAsync(urlDest);
|
||||
|
@ -220,80 +218,80 @@ export default function Folders() {
|
|||
ToastAndroid.SHORT,
|
||||
);
|
||||
}}
|
||||
>
|
||||
<MaterialIcons
|
||||
name="content-copy"
|
||||
size={20}
|
||||
color={folder.public ? "white" : "#2a3952"}
|
||||
/>
|
||||
</Pressable>
|
||||
disabled={!folder.public}
|
||||
iconSize={20}
|
||||
width={32}
|
||||
height={32}
|
||||
padding={6}
|
||||
/>
|
||||
|
||||
<Pressable
|
||||
style={{
|
||||
...styles.actionButton,
|
||||
...(!folder.public && styles.actionButtonPrivate)
|
||||
}}
|
||||
<Button
|
||||
onPress={async () => {
|
||||
const folderId = folder.id;
|
||||
|
||||
const success = await editFolder(folderId, !folder.public);
|
||||
const success = await editFolder(
|
||||
folderId,
|
||||
!folder.public,
|
||||
);
|
||||
|
||||
if (typeof success === "string") return ToastAndroid.show(
|
||||
`Failed to update the folder "${folder.name}"`,
|
||||
ToastAndroid.SHORT
|
||||
)
|
||||
|
||||
ToastAndroid.show(
|
||||
`Updated the folder "${folder.name}"'s visibility`,
|
||||
ToastAndroid.SHORT
|
||||
)
|
||||
if (typeof success === "string")
|
||||
return ToastAndroid.show(
|
||||
`Failed to update the folder "${folder.name}"`,
|
||||
ToastAndroid.SHORT,
|
||||
);
|
||||
|
||||
const folderIndex = folders.findIndex((fold) => folder.id === fold.id)
|
||||
ToastAndroid.show(
|
||||
`Updated the folder "${folder.name}"'s visibility`,
|
||||
ToastAndroid.SHORT,
|
||||
);
|
||||
|
||||
const newFolders = [...folders];
|
||||
newFolders[folderIndex].public = !folder.public;
|
||||
const folderIndex = folders.findIndex(
|
||||
(fold) => folder.id === fold.id,
|
||||
);
|
||||
|
||||
setFolders(newFolders);
|
||||
const newFolders = [...folders];
|
||||
newFolders[folderIndex].public = !folder.public;
|
||||
|
||||
setFolders(newFolders);
|
||||
}}
|
||||
>
|
||||
<MaterialIcons
|
||||
name={folder.public ? "lock-open" : "lock"}
|
||||
size={20}
|
||||
color={"white"}
|
||||
/>
|
||||
</Pressable>
|
||||
color={folder.public ? "#323ea8": "#343a40"}
|
||||
icon={folder.public ? "lock-open" : "lock"}
|
||||
iconSize={20}
|
||||
width={32}
|
||||
height={32}
|
||||
padding={6}
|
||||
/>
|
||||
|
||||
<Pressable
|
||||
style={{
|
||||
...styles.actionButton,
|
||||
...styles.actionButtonDanger,
|
||||
}}
|
||||
<Button
|
||||
onPress={async () => {
|
||||
const folderId = folder.id;
|
||||
|
||||
const success = await deleteFolder(folderId);
|
||||
|
||||
if (typeof success === "string") return ToastAndroid.show(
|
||||
`Failed to delete the folder "${folder.name}"`,
|
||||
ToastAndroid.SHORT
|
||||
)
|
||||
if (typeof success === "string")
|
||||
return ToastAndroid.show(
|
||||
`Failed to delete the folder "${folder.name}"`,
|
||||
ToastAndroid.SHORT,
|
||||
);
|
||||
|
||||
const newFolders = folders.filter((fold) => fold.id !== folder.id)
|
||||
const newFolders = folders.filter(
|
||||
(fold) => fold.id !== folder.id,
|
||||
);
|
||||
|
||||
setFolders(newFolders)
|
||||
setFolders(newFolders);
|
||||
|
||||
ToastAndroid.show(
|
||||
`Deleted the folder "${folder.name}"`,
|
||||
ToastAndroid.SHORT
|
||||
)
|
||||
ToastAndroid.show(
|
||||
`Deleted the folder "${folder.name}"`,
|
||||
ToastAndroid.SHORT,
|
||||
);
|
||||
}}
|
||||
>
|
||||
<MaterialIcons
|
||||
name="delete"
|
||||
size={20}
|
||||
color={"white"}
|
||||
/>
|
||||
</Pressable>
|
||||
color="#CF4238"
|
||||
icon="delete"
|
||||
iconSize={20}
|
||||
width={32}
|
||||
height={32}
|
||||
padding={6}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
|
||||
|
@ -314,12 +312,7 @@ export default function Folders() {
|
|||
return (
|
||||
<Row
|
||||
key={folder.id}
|
||||
data={[
|
||||
name,
|
||||
isPublic,
|
||||
created,
|
||||
actions,
|
||||
]}
|
||||
data={[name, isPublic, created, actions]}
|
||||
widthArr={[80, 50, 130, 150]}
|
||||
style={rowStyle}
|
||||
textStyle={styles.rowText}
|
||||
|
|
|
@ -7,6 +7,7 @@ import { styles } from "@/styles/login";
|
|||
import { useLoginAuth } from "@/hooks/useLoginAuth";
|
||||
import React from "react";
|
||||
import TextInput from "@/components/TextInput";
|
||||
import Button from "@/components/Button";
|
||||
|
||||
export default function Login() {
|
||||
const router = useRouter();
|
||||
|
@ -83,18 +84,16 @@ export default function Login() {
|
|||
</>
|
||||
)}
|
||||
|
||||
<Pressable
|
||||
style={{
|
||||
...styles.button,
|
||||
...styles.buttonSecondary,
|
||||
}}
|
||||
<Button
|
||||
onPress={() => setTokenLogin((prev) => !prev)}
|
||||
>
|
||||
<Text style={styles.buttonText}>Use {tokenLogin ? "Password" : "Token"} Login</Text>
|
||||
</Pressable>
|
||||
color="#616060"
|
||||
text={`Use ${tokenLogin ? "Password" : "Token"} Login`}
|
||||
margin={{
|
||||
top: 5
|
||||
}}
|
||||
/>
|
||||
|
||||
<Pressable
|
||||
style={styles.button}
|
||||
<Button
|
||||
onPress={async () => {
|
||||
setError(undefined)
|
||||
|
||||
|
@ -136,9 +135,12 @@ export default function Login() {
|
|||
|
||||
return router.replace("/");
|
||||
}}
|
||||
>
|
||||
<Text style={styles.buttonText}>Login</Text>
|
||||
</Pressable>
|
||||
text="Login"
|
||||
color="#323ea8"
|
||||
margin={{
|
||||
top: 5
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
|
|
|
@ -23,6 +23,7 @@ import { clearTempFiles, clearZeroByteFiles, generateThumbnails, getZeroByteFile
|
|||
import { useRouter } from "expo-router";
|
||||
import TextInput from "@/components/TextInput"
|
||||
import Switch from "@/components/Switch";
|
||||
import Button from "@/components/Button";
|
||||
|
||||
export default function UserSettings() {
|
||||
const router = useRouter()
|
||||
|
@ -161,39 +162,43 @@ export default function UserSettings() {
|
|||
<Text style={styles.serverActionWarningText}>This will delete {zeroByteFiles} files from the database and datasource.</Text>
|
||||
|
||||
<View style={styles.manageServerActionButtonsContainer}>
|
||||
<Pressable style={{
|
||||
...styles.button,
|
||||
...styles.manageServerActionButtonCancel,
|
||||
marginRight: 10
|
||||
}} onPress={() => {
|
||||
setClearZeroByteFilesPopupOpen(false)
|
||||
}}>
|
||||
<Text style={styles.buttonText}>Cancel</Text>
|
||||
</Pressable>
|
||||
|
||||
<Pressable style={{
|
||||
...styles.button,
|
||||
...styles.manageServerActionButtonDanger,
|
||||
marginRight: 10
|
||||
}} onPress={async () => {
|
||||
const success = await clearZeroByteFiles()
|
||||
|
||||
if (typeof success === "string") {
|
||||
setSaveError(success)
|
||||
<Button
|
||||
onPress={() => {
|
||||
setClearZeroByteFilesPopupOpen(false)
|
||||
}}
|
||||
text="Cancel"
|
||||
color="#181c28"
|
||||
margin={{
|
||||
right: 10,
|
||||
top: 10,
|
||||
}}
|
||||
/>
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
setClearZeroByteFilesPopupOpen(false)
|
||||
|
||||
ToastAndroid.show(
|
||||
success.status,
|
||||
ToastAndroid.SHORT
|
||||
)
|
||||
}}>
|
||||
<Text style={styles.buttonText}>Yes, Delete</Text>
|
||||
</Pressable>
|
||||
<Button
|
||||
color="#CF4238"
|
||||
margin={{
|
||||
right: 10,
|
||||
top: 10,
|
||||
}}
|
||||
text="Yes, Delete"
|
||||
onPress={async () => {
|
||||
const success = await clearZeroByteFiles()
|
||||
|
||||
if (typeof success === "string") {
|
||||
setSaveError(success)
|
||||
setClearZeroByteFilesPopupOpen(false)
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
setClearZeroByteFilesPopupOpen(false)
|
||||
|
||||
ToastAndroid.show(
|
||||
success.status,
|
||||
ToastAndroid.SHORT
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
|
@ -213,39 +218,43 @@ export default function UserSettings() {
|
|||
<Text style={styles.serverActionWarningText}>This will delete temporary files stored within the temporary directory (defined in the configuration). This should not cause harm unless there are files that are being processed still.</Text>
|
||||
|
||||
<View style={styles.manageServerActionButtonsContainer}>
|
||||
<Pressable style={{
|
||||
...styles.button,
|
||||
...styles.manageServerActionButtonCancel,
|
||||
marginRight: 10
|
||||
}} onPress={() => {
|
||||
setClearTempFilesPopupOpen(false)
|
||||
}}>
|
||||
<Text style={styles.buttonText}>Cancel</Text>
|
||||
</Pressable>
|
||||
|
||||
<Pressable style={{
|
||||
...styles.button,
|
||||
...styles.manageServerActionButtonDanger,
|
||||
marginRight: 10
|
||||
}} onPress={async () => {
|
||||
const success = await clearTempFiles()
|
||||
|
||||
if (typeof success === "string") {
|
||||
setSaveError(success)
|
||||
<Button
|
||||
onPress={() => {
|
||||
setClearTempFilesPopupOpen(false)
|
||||
}}
|
||||
text="Cancel"
|
||||
color="#181c28"
|
||||
margin={{
|
||||
right: 10,
|
||||
top: 10,
|
||||
}}
|
||||
/>
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
setClearTempFilesPopupOpen(false)
|
||||
|
||||
ToastAndroid.show(
|
||||
success.status,
|
||||
ToastAndroid.SHORT
|
||||
)
|
||||
}}>
|
||||
<Text style={styles.buttonText}>Yes, Delete</Text>
|
||||
</Pressable>
|
||||
<Button
|
||||
color="#CF4238"
|
||||
margin={{
|
||||
right: 10,
|
||||
top: 10,
|
||||
}}
|
||||
text="Yes, Delete"
|
||||
onPress={async () => {
|
||||
const success = await clearTempFiles()
|
||||
|
||||
if (typeof success === "string") {
|
||||
setSaveError(success)
|
||||
setClearTempFilesPopupOpen(false)
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
setClearTempFilesPopupOpen(false)
|
||||
|
||||
ToastAndroid.show(
|
||||
success.status,
|
||||
ToastAndroid.SHORT
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
|
@ -281,48 +290,52 @@ export default function UserSettings() {
|
|||
/>
|
||||
|
||||
<View style={styles.manageServerActionButtonsContainer}>
|
||||
<Pressable style={{
|
||||
...styles.button,
|
||||
...styles.manageServerActionButtonCancel,
|
||||
marginRight: 10
|
||||
}} onPress={() => {
|
||||
setRequerySizeOfFilesPopupOpen(false)
|
||||
setRequerySizeForceDelete(false)
|
||||
setRequerySizeForceUpdate(false)
|
||||
}}>
|
||||
<Text style={styles.buttonText}>Cancel</Text>
|
||||
</Pressable>
|
||||
|
||||
<Pressable style={{
|
||||
...styles.button,
|
||||
...styles.manageServerActionButtonDanger,
|
||||
marginRight: 10
|
||||
}} onPress={async () => {
|
||||
const success = await requeryFileSize({
|
||||
forceDelete: requerySizeForceDelete,
|
||||
forceUpdate: requerySizeForceUpdate
|
||||
})
|
||||
|
||||
if (typeof success === "string") {
|
||||
setSaveError(success)
|
||||
<Button
|
||||
onPress={() => {
|
||||
setRequerySizeOfFilesPopupOpen(false)
|
||||
setRequerySizeForceDelete(false)
|
||||
setRequerySizeForceUpdate(false)
|
||||
}}
|
||||
text="Cancel"
|
||||
color="#181c28"
|
||||
margin={{
|
||||
right: 10,
|
||||
top: 10,
|
||||
}}
|
||||
/>
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
setRequerySizeOfFilesPopupOpen(false)
|
||||
setRequerySizeForceDelete(false)
|
||||
setRequerySizeForceUpdate(false)
|
||||
|
||||
ToastAndroid.show(
|
||||
success.status,
|
||||
ToastAndroid.SHORT
|
||||
)
|
||||
}}>
|
||||
<Text style={styles.buttonText}>Requery</Text>
|
||||
</Pressable>
|
||||
<Button
|
||||
color="#CF4238"
|
||||
margin={{
|
||||
right: 10,
|
||||
top: 10,
|
||||
}}
|
||||
text="Requery"
|
||||
onPress={async () => {
|
||||
const success = await requeryFileSize({
|
||||
forceDelete: requerySizeForceDelete,
|
||||
forceUpdate: requerySizeForceUpdate
|
||||
})
|
||||
|
||||
if (typeof success === "string") {
|
||||
setSaveError(success)
|
||||
setRequerySizeOfFilesPopupOpen(false)
|
||||
setRequerySizeForceDelete(false)
|
||||
setRequerySizeForceUpdate(false)
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
setRequerySizeOfFilesPopupOpen(false)
|
||||
setRequerySizeForceDelete(false)
|
||||
setRequerySizeForceUpdate(false)
|
||||
|
||||
ToastAndroid.show(
|
||||
success.status,
|
||||
ToastAndroid.SHORT
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
|
@ -351,42 +364,46 @@ export default function UserSettings() {
|
|||
/>
|
||||
|
||||
<View style={styles.manageServerActionButtonsContainer}>
|
||||
<Pressable style={{
|
||||
...styles.button,
|
||||
...styles.manageServerActionButtonCancel,
|
||||
marginRight: 10
|
||||
}} onPress={() => {
|
||||
setGenerateThumbnailsPopupOpen(false)
|
||||
setGenerateThumbnailsRerun(false)
|
||||
}}>
|
||||
<Text style={styles.buttonText}>Cancel</Text>
|
||||
</Pressable>
|
||||
<Button
|
||||
onPress={() => {
|
||||
setGenerateThumbnailsPopupOpen(false)
|
||||
setGenerateThumbnailsRerun(false)
|
||||
}}
|
||||
text="Cancel"
|
||||
color="#181c28"
|
||||
margin={{
|
||||
right: 10,
|
||||
top: 10,
|
||||
}}
|
||||
/>
|
||||
|
||||
<Pressable style={{
|
||||
...styles.button,
|
||||
...styles.manageServerActionButtonDanger,
|
||||
marginRight: 10
|
||||
}} onPress={async () => {
|
||||
const success = await generateThumbnails(generateThumbnailsRerun)
|
||||
<Button
|
||||
color="#CF4238"
|
||||
margin={{
|
||||
right: 10,
|
||||
top: 10,
|
||||
}}
|
||||
text="Generate"
|
||||
onPress={async () => {
|
||||
const success = await generateThumbnails(generateThumbnailsRerun)
|
||||
|
||||
if (typeof success === "string") {
|
||||
setSaveError(success)
|
||||
setGenerateThumbnailsPopupOpen(false)
|
||||
setGenerateThumbnailsRerun(false)
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof success === "string") {
|
||||
setSaveError(success)
|
||||
setGenerateThumbnailsPopupOpen(false)
|
||||
setGenerateThumbnailsRerun(false)
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
setGenerateThumbnailsPopupOpen(false)
|
||||
setGenerateThumbnailsRerun(false)
|
||||
|
||||
ToastAndroid.show(
|
||||
success.status,
|
||||
ToastAndroid.LONG
|
||||
)
|
||||
}}>
|
||||
<Text style={styles.buttonText}>Generate</Text>
|
||||
</Pressable>
|
||||
ToastAndroid.show(
|
||||
success.status,
|
||||
ToastAndroid.LONG
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
|
@ -442,49 +459,62 @@ export default function UserSettings() {
|
|||
password
|
||||
/>
|
||||
|
||||
<Pressable style={styles.button} onPress={() => handleSave("userInfo")}>
|
||||
<Text style={styles.buttonText}>Save</Text>
|
||||
</Pressable>
|
||||
<Button
|
||||
onPress={() => handleSave("userInfo")}
|
||||
color="#323ea8"
|
||||
text="Save"
|
||||
icon="save"
|
||||
margin={{
|
||||
top: 10,
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
|
||||
{/* Avatar */}
|
||||
<View style={styles.settingGroup}>
|
||||
<Text style={styles.headerText}>Avatar</Text>
|
||||
|
||||
<Text style={styles.headerText}>Avatar:</Text>
|
||||
<Pressable style={styles.avatarButton} onPress={async () => {
|
||||
const output = await DocumentPicker.getDocumentAsync({
|
||||
type: [
|
||||
"image/png",
|
||||
"image/jpeg",
|
||||
"image/jpg"
|
||||
],
|
||||
copyToCacheDirectory: true,
|
||||
});
|
||||
|
||||
if (output.canceled || !output.assets) {
|
||||
setAvatar(undefined)
|
||||
setAvatarName(null)
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
const fileURI = output.assets[0].uri
|
||||
|
||||
const fileInfo = await FileSystem.getInfoAsync(fileURI)
|
||||
|
||||
if (!fileInfo.exists) return;
|
||||
|
||||
const avatarDataURI = await getFileDataURI(fileURI)
|
||||
|
||||
setAvatar(avatarDataURI || undefined)
|
||||
|
||||
const filename = fileURI.split('/').pop() || "avatar.png"
|
||||
|
||||
setAvatarName(filename)
|
||||
}}>
|
||||
<Text style={styles.avatarButtonText}>{avatar ? avatarName : "Select an Avatar..."}</Text>
|
||||
</Pressable>
|
||||
<Button
|
||||
color="transparent"
|
||||
borderWidth={2}
|
||||
borderColor="#222c47"
|
||||
margin={{
|
||||
top: 5
|
||||
}}
|
||||
rippleColor="gray"
|
||||
text={avatar ? avatarName as string : "Select an Avatar..."}
|
||||
onPress={async () => {
|
||||
const output = await DocumentPicker.getDocumentAsync({
|
||||
type: [
|
||||
"image/png",
|
||||
"image/jpeg",
|
||||
"image/jpg"
|
||||
],
|
||||
copyToCacheDirectory: true,
|
||||
});
|
||||
|
||||
if (output.canceled || !output.assets) {
|
||||
setAvatar(undefined)
|
||||
setAvatarName(null)
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
const fileURI = output.assets[0].uri
|
||||
|
||||
const fileInfo = await FileSystem.getInfoAsync(fileURI)
|
||||
|
||||
if (!fileInfo.exists) return;
|
||||
|
||||
const avatarDataURI = await getFileDataURI(fileURI)
|
||||
|
||||
setAvatar(avatarDataURI || undefined)
|
||||
|
||||
const filename = fileURI.split('/').pop() || "avatar.png"
|
||||
|
||||
setAvatarName(filename)
|
||||
}}
|
||||
/>
|
||||
|
||||
<View style={styles.avatarPreviewContainer}>
|
||||
<Text style={styles.avatarPreviewHeader}>Avatar Preview</Text>
|
||||
|
@ -493,27 +523,38 @@ export default function UserSettings() {
|
|||
|
||||
<View style={styles.avatarButtonsContainer}>
|
||||
{avatar && (
|
||||
<Pressable
|
||||
style={{
|
||||
...styles.button,
|
||||
...styles.manageAvatarButton,
|
||||
...styles.cancelAvatarButton
|
||||
<Button
|
||||
text="Cancel"
|
||||
color="transparent"
|
||||
textColor="white"
|
||||
height="auto"
|
||||
width="28.33%"
|
||||
margin={{
|
||||
left: "2.5%",
|
||||
right: "2.5%",
|
||||
top: 10
|
||||
}}
|
||||
rippleColor="gray"
|
||||
borderWidth={2}
|
||||
borderColor="#ff8787"
|
||||
onPress={() => {
|
||||
setAvatar(undefined)
|
||||
setAvatarName(null)
|
||||
}}
|
||||
>
|
||||
<Text style={styles.buttonText}>Cancel</Text>
|
||||
</Pressable>
|
||||
/>
|
||||
)}
|
||||
|
||||
{currentAvatar && (
|
||||
<Pressable
|
||||
style={{
|
||||
...styles.button,
|
||||
...styles.manageAvatarButton,
|
||||
...styles.removeAvatarButton
|
||||
<Button
|
||||
text="Remove Avatar"
|
||||
color="#e03131"
|
||||
textColor="white"
|
||||
height="auto"
|
||||
width="28.33%"
|
||||
margin={{
|
||||
left: "2.5%",
|
||||
right: "2.5%",
|
||||
top: 10
|
||||
}}
|
||||
onPress={async () => {
|
||||
const success = await editCurrentUser({
|
||||
|
@ -533,17 +574,21 @@ export default function UserSettings() {
|
|||
ToastAndroid.SHORT
|
||||
)
|
||||
}}
|
||||
>
|
||||
<Text style={styles.buttonText}>Remove Avatar</Text>
|
||||
</Pressable>
|
||||
/>
|
||||
)}
|
||||
|
||||
<Pressable
|
||||
style={{
|
||||
...styles.button,
|
||||
...styles.manageAvatarButton,
|
||||
...(!avatar && styles.saveAvatarButtonDisabled)
|
||||
<Button
|
||||
text="Save"
|
||||
color={avatar ? "#323ea8" : "#181c28"}
|
||||
textColor={avatar ? "white" : "gray"}
|
||||
height="auto"
|
||||
width="28.33%"
|
||||
margin={{
|
||||
left: "2.5%",
|
||||
right: "2.5%",
|
||||
top: 10
|
||||
}}
|
||||
disabled={!avatar}
|
||||
onPress={async () => {
|
||||
const success = await editCurrentUser({
|
||||
avatar: avatar
|
||||
|
@ -562,12 +607,7 @@ export default function UserSettings() {
|
|||
ToastAndroid.SHORT
|
||||
)
|
||||
}}
|
||||
>
|
||||
<Text style={{
|
||||
...styles.buttonText,
|
||||
...(!avatar && styles.saveAvatarButtonTextDisabled)
|
||||
}}>Save</Text>
|
||||
</Pressable>
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
|
@ -665,31 +705,42 @@ export default function UserSettings() {
|
|||
placeholder="My Cool Color"
|
||||
/>
|
||||
|
||||
<Pressable style={styles.button} onPress={() => handleSave("viewingFiles")}>
|
||||
<Text style={styles.buttonText}>Save</Text>
|
||||
</Pressable>
|
||||
<Button
|
||||
onPress={() => handleSave("viewingFiles")}
|
||||
color="#323ea8"
|
||||
text="Save"
|
||||
icon="save"
|
||||
margin={{
|
||||
top: 10,
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
|
||||
{/* Export Files */}
|
||||
<View style={styles.settingGroup}>
|
||||
<Text style={styles.headerText}>Export Files</Text>
|
||||
|
||||
<Pressable style={styles.button} onPress={async () => {
|
||||
const success = await createUserExport()
|
||||
|
||||
if (typeof success === "string") return setSaveError(success);
|
||||
|
||||
const newExports = await getUserExports()
|
||||
|
||||
setExports(typeof newExports === "string" ? null : newExports)
|
||||
|
||||
ToastAndroid.show(
|
||||
"Successfully started creating the export",
|
||||
ToastAndroid.SHORT
|
||||
)
|
||||
}}>
|
||||
<Text style={styles.buttonText}>New Export</Text>
|
||||
</Pressable>
|
||||
<Button
|
||||
onPress={async () => {
|
||||
const success = await createUserExport()
|
||||
|
||||
if (typeof success === "string") return setSaveError(success);
|
||||
|
||||
const newExports = await getUserExports()
|
||||
|
||||
setExports(typeof newExports === "string" ? null : newExports)
|
||||
|
||||
ToastAndroid.show(
|
||||
"Successfully started creating the export",
|
||||
ToastAndroid.SHORT
|
||||
)
|
||||
}}
|
||||
color="#323ea8"
|
||||
text="New Export"
|
||||
margin={{
|
||||
top: 10,
|
||||
}}
|
||||
/>
|
||||
|
||||
<View style={styles.exportsContainer}>
|
||||
<ScrollView
|
||||
|
@ -745,11 +796,9 @@ export default function UserSettings() {
|
|||
|
||||
const actions = (
|
||||
<View style={styles.actionsContainer}>
|
||||
<Pressable
|
||||
style={{
|
||||
...styles.actionButton,
|
||||
...styles.actionButtonDanger
|
||||
}}
|
||||
<Button
|
||||
icon="delete"
|
||||
color="#CF4238"
|
||||
onPress={async () => {
|
||||
setSaveError(null)
|
||||
|
||||
|
@ -768,19 +817,16 @@ export default function UserSettings() {
|
|||
ToastAndroid.SHORT,
|
||||
);
|
||||
}}
|
||||
>
|
||||
<MaterialIcons
|
||||
name="delete"
|
||||
size={20}
|
||||
color={"white"}
|
||||
/>
|
||||
</Pressable>
|
||||
|
||||
<Pressable
|
||||
style={{
|
||||
...styles.actionButton,
|
||||
...(!zlExport.completed && styles.actionButtonDisabled)
|
||||
}}
|
||||
iconSize={20}
|
||||
width={32}
|
||||
height={32}
|
||||
padding={6}
|
||||
/>
|
||||
|
||||
<Button
|
||||
icon="download"
|
||||
color={zlExport.completed ? "#323ea8" : "#181c28"}
|
||||
iconColor={zlExport.completed ? "white" : "gray"}
|
||||
disabled={!zlExport.completed}
|
||||
onPress={async () => {
|
||||
const exportId = zlExport.id;
|
||||
|
@ -832,13 +878,11 @@ export default function UserSettings() {
|
|||
ToastAndroid.SHORT
|
||||
)
|
||||
}}
|
||||
>
|
||||
<MaterialIcons
|
||||
name="download"
|
||||
size={20}
|
||||
color={"white"}
|
||||
/>
|
||||
</Pressable>
|
||||
iconSize={20}
|
||||
width={32}
|
||||
height={32}
|
||||
padding={6}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
|
||||
|
@ -884,40 +928,60 @@ export default function UserSettings() {
|
|||
<Text style={styles.headerText}>Server Actions</Text>
|
||||
|
||||
<View style={styles.serverActionButtonRow}>
|
||||
<Pressable style={{
|
||||
...styles.button,
|
||||
...styles.serverActionButton
|
||||
}} onPress={async () => {
|
||||
setClearZeroByteFilesPopupOpen(true)
|
||||
<Button
|
||||
onPress={async () => {
|
||||
setClearZeroByteFilesPopupOpen(true)
|
||||
|
||||
const zeroByteFiles = await getZeroByteFiles()
|
||||
setZeroByteFiles(typeof zeroByteFiles === "string" ? 0 : zeroByteFiles.files.length)
|
||||
}}
|
||||
color="#323ea8"
|
||||
text="Clear Zero Byte Files"
|
||||
width="45%"
|
||||
margin={{
|
||||
left: "2.5%",
|
||||
right: "2.5%",
|
||||
top: 10,
|
||||
}}
|
||||
/>
|
||||
|
||||
const zeroByteFiles = await getZeroByteFiles()
|
||||
setZeroByteFiles(typeof zeroByteFiles === "string" ? 0 : zeroByteFiles.files.length)
|
||||
}}>
|
||||
<Text style={styles.buttonText}>Clear Zero Byte Files</Text>
|
||||
</Pressable>
|
||||
|
||||
<Pressable style={{
|
||||
...styles.button,
|
||||
...styles.serverActionButton
|
||||
}} onPress={() => setClearTempFilesPopupOpen(true)}>
|
||||
<Text style={styles.buttonText}>Clear Temp Files</Text>
|
||||
</Pressable>
|
||||
<Button
|
||||
onPress={() => setClearTempFilesPopupOpen(true)}
|
||||
color="#323ea8"
|
||||
text="Clear Temp Files"
|
||||
width="45%"
|
||||
margin={{
|
||||
left: "2.5%",
|
||||
right: "2.5%",
|
||||
top: 10,
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<View style={styles.serverActionButtonRow}>
|
||||
<Pressable style={{
|
||||
...styles.button,
|
||||
...styles.serverActionButton
|
||||
}} onPress={() => setRequerySizeOfFilesPopupOpen(true)}>
|
||||
<Text style={styles.buttonText}>Requery Size of Files</Text>
|
||||
</Pressable>
|
||||
<Button
|
||||
onPress={() => setRequerySizeOfFilesPopupOpen(true)}
|
||||
color="#323ea8"
|
||||
text="Requery Size of Files"
|
||||
width="45%"
|
||||
margin={{
|
||||
left: "2.5%",
|
||||
right: "2.5%",
|
||||
top: 10,
|
||||
}}
|
||||
/>
|
||||
|
||||
<Pressable style={{
|
||||
...styles.button,
|
||||
...styles.serverActionButton
|
||||
}} onPress={() => setGenerateThumbnailsPopupOpen(true)}>
|
||||
<Text style={styles.buttonText}>Generate Thumbnails</Text>
|
||||
</Pressable>
|
||||
<Button
|
||||
onPress={() => setGenerateThumbnailsPopupOpen(true)}
|
||||
color="#323ea8"
|
||||
text="Generate Thumbnails"
|
||||
width="45%"
|
||||
margin={{
|
||||
left: "2.5%",
|
||||
right: "2.5%",
|
||||
top: 10,
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
|
@ -925,59 +989,65 @@ export default function UserSettings() {
|
|||
<View style={styles.settingGroup}>
|
||||
<Text style={styles.headerText}>App Settings</Text>
|
||||
|
||||
<Pressable style={{
|
||||
...styles.button,
|
||||
...styles.buttonSecondary
|
||||
}} onPress={async () => {
|
||||
const permissions = await FileSystem.StorageAccessFramework.requestDirectoryPermissionsAsync();
|
||||
<Button
|
||||
onPress={async () => {
|
||||
const permissions = await FileSystem.StorageAccessFramework.requestDirectoryPermissionsAsync();
|
||||
|
||||
if (!permissions.granted) return ToastAndroid.show(
|
||||
"The permission to the folder was not granted",
|
||||
ToastAndroid.SHORT
|
||||
);
|
||||
|
||||
db.set("exportDownloadPath", permissions.directoryUri)
|
||||
|
||||
ToastAndroid.show(
|
||||
"Successfully changed the folder",
|
||||
ToastAndroid.SHORT
|
||||
)
|
||||
}}
|
||||
color="#323244"
|
||||
text="Change Export Download Folder"
|
||||
margin={{
|
||||
top: 10,
|
||||
}}
|
||||
/>
|
||||
|
||||
if (!permissions.granted) return ToastAndroid.show(
|
||||
"The permission to the folder was not granted",
|
||||
ToastAndroid.SHORT
|
||||
);
|
||||
<Button
|
||||
onPress={async () => {
|
||||
const permissions = await FileSystem.StorageAccessFramework.requestDirectoryPermissionsAsync();
|
||||
|
||||
if (!permissions.granted) return ToastAndroid.show(
|
||||
"The permission to the folder was not granted",
|
||||
ToastAndroid.SHORT
|
||||
);
|
||||
|
||||
db.set("fileDownloadPath", permissions.directoryUri)
|
||||
|
||||
ToastAndroid.show(
|
||||
"Successfully changed the folder",
|
||||
ToastAndroid.SHORT
|
||||
)
|
||||
}}
|
||||
color="#323244"
|
||||
text="Change File Download Folder"
|
||||
margin={{
|
||||
top: 10,
|
||||
}}
|
||||
/>
|
||||
|
||||
db.set("exportDownloadPath", permissions.directoryUri)
|
||||
|
||||
ToastAndroid.show(
|
||||
"Successfully changed the folder",
|
||||
ToastAndroid.SHORT
|
||||
)
|
||||
}}>
|
||||
<Text style={styles.buttonText}>Change Export Download Folder</Text>
|
||||
</Pressable>
|
||||
|
||||
<Pressable style={{
|
||||
...styles.button,
|
||||
...styles.buttonSecondary
|
||||
}} onPress={async () => {
|
||||
const permissions = await FileSystem.StorageAccessFramework.requestDirectoryPermissionsAsync();
|
||||
|
||||
if (!permissions.granted) return ToastAndroid.show(
|
||||
"The permission to the folder was not granted",
|
||||
ToastAndroid.SHORT
|
||||
);
|
||||
|
||||
db.set("fileDownloadPath", permissions.directoryUri)
|
||||
|
||||
ToastAndroid.show(
|
||||
"Successfully changed the folder",
|
||||
ToastAndroid.SHORT
|
||||
)
|
||||
}}>
|
||||
<Text style={styles.buttonText}>Change File Download Folder</Text>
|
||||
</Pressable>
|
||||
|
||||
<Pressable style={{
|
||||
...styles.button,
|
||||
...styles.buttonDanger
|
||||
}} onPress={async () => {
|
||||
await db.del("url")
|
||||
await db.del("token")
|
||||
|
||||
router.replace("/login")
|
||||
}}>
|
||||
<Text style={styles.buttonText}>Logout</Text>
|
||||
</Pressable>
|
||||
<Button
|
||||
onPress={async () => {
|
||||
await db.del("url")
|
||||
await db.del("token")
|
||||
|
||||
router.replace("/login")
|
||||
}}
|
||||
color="#CF4238"
|
||||
text="Logout"
|
||||
margin={{
|
||||
top: 10,
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
</KeyboardAwareScrollView>
|
||||
</View>
|
||||
|
|
|
@ -18,6 +18,7 @@ import { useAuth } from "@/hooks/useAuth";
|
|||
import { useShareIntent } from "@/hooks/useShareIntent";
|
||||
import TextInput from "@/components/TextInput";
|
||||
import Switch from "@/components/Switch";
|
||||
import Button from "@/components/Button";
|
||||
|
||||
export default function Urls() {
|
||||
useAuth()
|
||||
|
@ -131,9 +132,13 @@ export default function Urls() {
|
|||
value={newUrlEnabled}
|
||||
onValueChange={() => setNewUrlEnabled((prev) => !prev)}
|
||||
/>
|
||||
|
||||
<Pressable
|
||||
style={styles.button}
|
||||
|
||||
<Button
|
||||
color="#323ea8"
|
||||
text="Shorten"
|
||||
margin={{
|
||||
top: 5
|
||||
}}
|
||||
onPress={async () => {
|
||||
setNewUrlError(undefined);
|
||||
|
||||
|
@ -180,9 +185,7 @@ export default function Urls() {
|
|||
ToastAndroid.SHORT,
|
||||
);
|
||||
}}
|
||||
>
|
||||
<Text style={styles.buttonText}>Shorten</Text>
|
||||
</Pressable>
|
||||
/>
|
||||
|
||||
<Text
|
||||
style={styles.popupSubHeaderText}
|
||||
|
@ -251,9 +254,13 @@ export default function Urls() {
|
|||
value={editUrlEnabled}
|
||||
onValueChange={() => setEditUrlEnabled((prev) => !prev)}
|
||||
/>
|
||||
|
||||
<Pressable
|
||||
style={styles.button}
|
||||
|
||||
<Button
|
||||
color="#323ea8"
|
||||
text="Edit"
|
||||
margin={{
|
||||
top: 5
|
||||
}}
|
||||
onPress={async () => {
|
||||
setEditUrlError(undefined);
|
||||
|
||||
|
@ -287,9 +294,7 @@ export default function Urls() {
|
|||
|
||||
setUrlToEdit(null);
|
||||
}}
|
||||
>
|
||||
<Text style={styles.buttonText}>Edit</Text>
|
||||
</Pressable>
|
||||
/>
|
||||
|
||||
<Text
|
||||
style={styles.popupSubHeaderText}
|
||||
|
@ -306,18 +311,19 @@ export default function Urls() {
|
|||
<View style={styles.header}>
|
||||
<Text style={styles.headerText}>URLs</Text>
|
||||
<View style={styles.headerButtons}>
|
||||
<Pressable
|
||||
style={styles.headerButton}
|
||||
<Button
|
||||
onPress={() => {
|
||||
setCreateNewUrl(true);
|
||||
}}
|
||||
>
|
||||
<MaterialIcons
|
||||
name="add-link"
|
||||
size={30}
|
||||
color={styles.headerButton.color}
|
||||
/>
|
||||
</Pressable>
|
||||
icon="add-link"
|
||||
color="transparent"
|
||||
iconColor="#2d3f70"
|
||||
borderColor="#222c47"
|
||||
borderWidth={2}
|
||||
iconSize={30}
|
||||
padding={4}
|
||||
rippleColor="#283557"
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
|
@ -424,8 +430,9 @@ export default function Urls() {
|
|||
|
||||
const actions = (
|
||||
<View style={styles.actionsContainer}>
|
||||
<Pressable
|
||||
style={styles.actionButton}
|
||||
<Button
|
||||
icon="content-copy"
|
||||
color="#323ea8"
|
||||
onPress={async () => {
|
||||
const urlDest = url.vanity
|
||||
? `${dashUrl}${settings.urlsRoute === "/" ? "" : settings.urlsRoute}/${url.vanity}`
|
||||
|
@ -445,32 +452,27 @@ export default function Urls() {
|
|||
ToastAndroid.SHORT,
|
||||
);
|
||||
}}
|
||||
>
|
||||
<MaterialIcons
|
||||
name="content-copy"
|
||||
size={20}
|
||||
color={"white"}
|
||||
/>
|
||||
</Pressable>
|
||||
iconSize={20}
|
||||
width={32}
|
||||
height={32}
|
||||
padding={6}
|
||||
/>
|
||||
|
||||
<Pressable
|
||||
style={styles.actionButton}
|
||||
<Button
|
||||
icon="edit"
|
||||
color="#323ea8"
|
||||
onPress={() => {
|
||||
setUrlToEdit(url)
|
||||
}}
|
||||
>
|
||||
<MaterialIcons
|
||||
name="edit"
|
||||
size={20}
|
||||
color={"white"}
|
||||
/>
|
||||
</Pressable>
|
||||
iconSize={20}
|
||||
width={32}
|
||||
height={32}
|
||||
padding={6}
|
||||
/>
|
||||
|
||||
<Pressable
|
||||
style={{
|
||||
...styles.actionButton,
|
||||
...styles.actionButtonDanger,
|
||||
}}
|
||||
<Button
|
||||
icon="delete"
|
||||
color="#CF4238"
|
||||
onPress={async () => {
|
||||
const urlId = url.id;
|
||||
|
||||
|
@ -490,13 +492,11 @@ export default function Urls() {
|
|||
ToastAndroid.SHORT
|
||||
)
|
||||
}}
|
||||
>
|
||||
<MaterialIcons
|
||||
name="delete"
|
||||
size={20}
|
||||
color={"white"}
|
||||
/>
|
||||
</Pressable>
|
||||
iconSize={20}
|
||||
width={32}
|
||||
height={32}
|
||||
padding={6}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
|
||||
|
|
|
@ -14,23 +14,16 @@ export default function NotFoundScreen() {
|
|||
|
||||
<Text style={styles.text}>This page does not exist.</Text>
|
||||
|
||||
<Button onPress={() => {
|
||||
// router.replace({
|
||||
// pathname: "/",
|
||||
// });
|
||||
}} text="Head to the Dashboard" color="#323ea8" />
|
||||
|
||||
{/* <Pressable
|
||||
style={styles.button}
|
||||
<Button
|
||||
onPress={() => {
|
||||
router.replace({
|
||||
pathname: "/",
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Text style={styles.buttonText}>Head to the Dashboard</Text>
|
||||
</Pressable> */}
|
||||
text="Head to the Dashboard"
|
||||
color="#323ea8"
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ export default function Home() {
|
|||
// db.del("url")
|
||||
// db.del("token")
|
||||
|
||||
router.replace("/test");
|
||||
// router.replace("/login");
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -4,12 +4,10 @@ import { MaterialIcons } from "@expo/vector-icons";
|
|||
import { type ColorValue, type DimensionValue, Pressable, Text } from "react-native";
|
||||
|
||||
interface Props {
|
||||
onPress: () => void | Promise<void>;
|
||||
onPress: () => unknown | Promise<unknown>;
|
||||
disabled?: boolean;
|
||||
color: ColorValue;
|
||||
disabledColor?: ColorValue;
|
||||
textColor?: ColorValue;
|
||||
disabledTextColor?: ColorValue;
|
||||
text?: string;
|
||||
width?: DimensionValue;
|
||||
height?: DimensionValue;
|
||||
|
@ -17,15 +15,23 @@ interface Props {
|
|||
iconColor?: ColorValue;
|
||||
borderWidth?: number;
|
||||
borderColor?: ColorValue;
|
||||
iconSize?: number;
|
||||
padding?: number;
|
||||
rippleColor?: ColorValue;
|
||||
margin?: {
|
||||
top?: DimensionValue;
|
||||
bottom?: DimensionValue;
|
||||
left?: DimensionValue;
|
||||
right?: DimensionValue;
|
||||
},
|
||||
flex?: number
|
||||
}
|
||||
|
||||
export default function Button({
|
||||
onPress = () => {},
|
||||
disabled = false,
|
||||
color,
|
||||
disabledColor,
|
||||
textColor = "white",
|
||||
disabledTextColor = "gray",
|
||||
text,
|
||||
width,
|
||||
height,
|
||||
|
@ -33,37 +39,45 @@ export default function Button({
|
|||
iconColor = "white",
|
||||
borderWidth = 0,
|
||||
borderColor,
|
||||
iconSize = 20,
|
||||
padding = 10,
|
||||
margin = {},
|
||||
rippleColor,
|
||||
flex
|
||||
}: Props) {
|
||||
return (
|
||||
<Pressable
|
||||
onPress={onPress}
|
||||
disabled={disabled}
|
||||
android_ripple={{
|
||||
color: disabled
|
||||
? getRippleColor(disabledColor as string || "#323244")
|
||||
: getRippleColor(color as string),
|
||||
color: rippleColor || getRippleColor(color as string)
|
||||
}}
|
||||
style={{
|
||||
...styles.button,
|
||||
width: width,
|
||||
...(height && { height: height }),
|
||||
backgroundColor: disabled ? disabledColor : color,
|
||||
backgroundColor: color,
|
||||
borderWidth: borderWidth,
|
||||
borderColor: borderColor,
|
||||
padding: 10 - borderWidth
|
||||
padding: padding - borderWidth,
|
||||
...(margin.left && { marginLeft: margin.left }),
|
||||
...(margin.right && { marginRight: margin.right }),
|
||||
...(margin.top && { marginTop: margin.top }),
|
||||
...(margin.bottom && { marginBottom: margin.bottom }),
|
||||
...(flex && { flex })
|
||||
}}
|
||||
>
|
||||
{icon && (
|
||||
<MaterialIcons
|
||||
name={icon}
|
||||
size={20}
|
||||
size={iconSize}
|
||||
color={iconColor}
|
||||
/>
|
||||
)}
|
||||
{text && (
|
||||
<Text style={{
|
||||
...styles.buttonText,
|
||||
color: disabled ? disabledTextColor : textColor,
|
||||
color: textColor,
|
||||
...(icon && { marginLeft: 5 })
|
||||
}}>{text}</Text>
|
||||
)}
|
||||
|
|
|
@ -6,6 +6,7 @@ export const styles = StyleSheet.create({
|
|||
borderRadius: 6,
|
||||
height: 40,
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
flexDirection: "row",
|
||||
},
|
||||
buttonText: {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue