diff --git a/app/(app)/(files)/files.tsx b/app/(app)/(files)/files.tsx index f90b0ea..eee69e5 100644 --- a/app/(app)/(files)/files.tsx +++ b/app/(app)/(files)/files.tsx @@ -15,6 +15,7 @@ import React from "react"; import { createTag, deleteTag, editTag, getTags } from "@/functions/zipline/tags"; import Popup from "@/components/Popup"; import { isLightColor } from "@/functions/color"; +import { colorHash } from "@/functions/util"; export default function Files() { const router = useRouter(); @@ -63,7 +64,7 @@ export default function Files() { (async () => { const tags = await getTags() - setTags(typeof tags === "string" ? tags : null) + setTags(typeof tags === "string" ? null : tags) if (searchParams.folderId) { const folder = await getFolder(searchParams.folderId) @@ -103,7 +104,7 @@ export default function Files() { const files = await getFiles(fetchPage, fetchOptions); - if ((files?.pages || 1) > 1) setAllPageDisabled(false); + if (typeof files !== "string" && (files?.pages || 1) > 1) setAllPageDisabled(false); setFiles(typeof files === "string" ? null : files); })(); @@ -183,7 +184,7 @@ export default function Files() { const success = await deleteTag(tagId) - if (typeof success === string) return ToastAndroid.show( + if (typeof success === "string") return ToastAndroid.show( `Failed to delete the tag "${tag.name}"`, ToastAndroid.SHORT ) @@ -243,34 +244,52 @@ export default function Files() { placeholderTextColor="#222c47" /> - { - setNewTagError(null); - - if (!newTagName) return setNewTagError("Please insert a name"); - if (!hexRegex.test(newTagColor)) return setNewTagError("Please insert a valid HEX color"); - - - - const newTagData = await createTag(newTagName, newTagColor) - - if (typeof newTagData === "string") - return setNewTagError(newTagData); - - setNewTagName(null); - setNewTagColor("#ffffff"); + + { + const guess = colorHash(newTagName || "") - const newTags = await getTags() + setNewTagColor(guess) + }} + > + Guess Color + - setTags(typeof newTags === "string" ? null : newTags) + { + setNewTagError(null); + + if (!newTagName) return setNewTagError("Please insert a name"); + if (!hexRegex.test(newTagColor)) return setNewTagError("Please insert a valid HEX color"); - setCreateNewTag(false); - setTagsMenuOpen(true) - }} - > - Create - + const newTagData = await createTag(newTagName, newTagColor) + + if (typeof newTagData === "string") + return setNewTagError(newTagData); + + setNewTagName(null); + setNewTagColor("#ffffff"); + + const newTags = await getTags() + + setTags(typeof newTags === "string" ? null : newTags) + + setCreateNewTag(false); + setTagsMenuOpen(true) + }} + > + Create + + - { - setEditTagError(null); + + { + const guess = colorHash(editTagName || "") - if (!editTagName) return setEditTagError("Please insert a name"); - if (!hexRegex.test(editTagColor)) return setEditTagError("Please insert a valid HEX color"); + setEditTagColor(guess) + }} + > + Guess Color + - + { + setEditTagError(null); - const editedTagData = await editTag(tagToEdit.id, { - name: editTagName, - color: editTagColor - }) + if (!editTagName) return setEditTagError("Please insert a name"); + if (!hexRegex.test(editTagColor)) return setEditTagError("Please insert a valid HEX color"); - if (typeof editedTagData === "string") - return setEditTagError(editedTagData); + - setEditTagName(null); - setEditTagColor("#ffffff"); + const editedTagData = await editTag(tagToEdit.id, { + name: editTagName === tagToEdit.name ? undefined : editTagName, + color: editTagColor + }) - const newTags = await getTags() + if (typeof editedTagData === "string") + return setEditTagError(editedTagData); - setTags(typeof newTags === "string" ? null : newTags) + setEditTagName(null); + setEditTagColor("#ffffff"); - setTagToEdit(null); - setTagsMenuOpen(true) - }} - > - Edit - + const newTags = await getTags() + + setTags(typeof newTags === "string" ? null : newTags) + + setTagToEdit(null); + setTagsMenuOpen(true) + }} + > + Edit + + {folders.map((folder, index) => { - const name = folder.public ? ( + const name = folder.public ? ( folder.id === fold.id) const newFolders = [...folders]; diff --git a/components/Header.tsx b/components/Header.tsx index 0b8ea94..793b0b4 100644 --- a/components/Header.tsx +++ b/components/Header.tsx @@ -6,7 +6,7 @@ import { View, Text, Pressable, Image } from "react-native"; import type { APISelfUser } from "@/types/zipline"; import { styles } from "@/styles/components/header"; import type React from "react"; -import Sidebar from "@/components/Sidebar.tsx" +import Sidebar from "@/components/Sidebar" export default function Header({ children }: PropsWithChildren) { const [avatar, setAvatar] = useState(null); diff --git a/components/LargeFileDisplay.tsx b/components/LargeFileDisplay.tsx index 372e1d5..7fcd2a3 100644 --- a/components/LargeFileDisplay.tsx +++ b/components/LargeFileDisplay.tsx @@ -14,8 +14,6 @@ interface Props { export default function LargeFileDisplay({ file, hidden, onClose }: Props) { const dashUrl = db.get("url") as DashURL | null; - console.log("aagdrgf") - return ( >({}) const screenWidth = Dimensions.get("window").width; const translateX = useRef(new Animated.Value(-screenWidth)).current; @@ -28,13 +30,14 @@ export default function Sidebar({ open = false, paddingTop = 0, setOpen }: Props const settings = await getSettings() const user = await getCurrentUser() - if (user && ["ADMIN", "SUPERADMIN"].includes(user.role)) setIsAdmin(true) - if (settings && settings.invitesEnabled) setInvitesEnabled(true) + if (typeof user !== "string" && ["ADMIN", "SUPERADMIN"].includes(user.role)) setIsAdmin(true) + if (typeof settings !== "string" && settings.invitesEnabled) setInvitesEnabled(true) })() }) const pathname = usePathname() + // biome-ignore lint/correctness/useExhaustiveDependencies:. useEffect(() => { Animated.timing(translateX, { toValue: open ? 0 : -screenWidth, @@ -44,29 +47,77 @@ export default function Sidebar({ open = false, paddingTop = 0, setOpen }: Props }, [open, screenWidth]); return ( - - {/* Your sidebar content goes here */} - - {sidebarOptions.map((option) => { - const isActive = pathname === option.route; - - if (option.type === "button") return ( - { - setOpen(false) - router.replace(option.route) - }} href={option.route} style={{ - ...styles.sidebarOption, - ...(isActive && styles.sidebarOptionActive) - }}> - - {option.name} - - ) - })} + + + {sidebarOptions.map(renderSidebarOptions)} ); + + function renderSidebarOptions(option: SidebarOption) { + if (option.adminOnly && !isAdmin) return ( + + ) + + if (option.invitesRoute && !invitesEnabled) return ( + + ) + + if (option.type === "button") { + const isActive = pathname === option.route; + + const route = option.route as RelativePathString + + return ( + { + setOpen(false) + + if (isActive) return; + + router.replace(route) + }} style={{ + ...styles.sidebarOption, + ...(isActive && styles.sidebarOptionActive) + }}> + + {option.name} + + ) + } + + if (option.type === "select") { + const open = openStates[option.name] ?? false + + return ( + + setOpenStates((prev) => { + return { + ...prev, + [option.name]: !prev[option.name] + } + })} style={styles.sidebarOption}> + + {option.name} + + + {open && ( + + {option.subMenus.map(renderSidebarOptions)} + + )} + + ); + } + } } \ No newline at end of file diff --git a/components/tmp.tsx b/components/tmp.tsx new file mode 100644 index 0000000..e69de29 diff --git a/constants/sidebar.ts b/constants/sidebar.ts index d401e68..d4da1fd 100644 --- a/constants/sidebar.ts +++ b/constants/sidebar.ts @@ -1,7 +1,10 @@ +import type { IconProps } from "@react-native-material/core"; +import type MaterialIcons from "@expo/vector-icons/MaterialIcons"; + interface SidebarOptionButton { route: string; name: string; - icon: string; + icon: keyof typeof MaterialIcons.glyphMap; adminOnly: boolean; invitesRoute: boolean; subMenus: []; @@ -11,14 +14,14 @@ interface SidebarOptionButton { interface SidebarOptionSelect { route: null; name: string; - icon: string; + icon: keyof typeof MaterialIcons.glyphMap; adminOnly: boolean; invitesRoute: boolean; subMenus: Array; type: "select"; } -type SidebarOption = SidebarOptionButton | SidebarOptionSelect; +export type SidebarOption = SidebarOptionButton | SidebarOptionSelect; export const sidebarOptions: Array = [ { @@ -102,7 +105,7 @@ export const sidebarOptions: Array = [ invitesRoute: false, subMenus: [ { - route: "/administrator/settings", + route: "/settings", name: "Settings", icon: "settings", adminOnly: true, @@ -111,7 +114,7 @@ export const sidebarOptions: Array = [ type: "button" }, { - route: "/administrator/users", + route: "/users", name: "Users", icon: "people", adminOnly: true, @@ -120,7 +123,7 @@ export const sidebarOptions: Array = [ type: "button" }, { - route: "/administrator/invites", + route: "/invites", name: "Invites", icon: "mail-outline", adminOnly: true, diff --git a/functions/zipline/exports.ts b/functions/zipline/exports.ts index 9ae06e1..a0ea5ae 100644 --- a/functions/zipline/exports.ts +++ b/functions/zipline/exports.ts @@ -20,7 +20,14 @@ export async function getUserExports(): Promise { } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } @@ -42,7 +49,14 @@ export async function createUserExport(): Promise<{ running: boolean } | string> } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } @@ -66,6 +80,13 @@ export async function deleteUserExport( } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } diff --git a/functions/zipline/files.ts b/functions/zipline/files.ts index f7778c3..1225390 100644 --- a/functions/zipline/files.ts +++ b/functions/zipline/files.ts @@ -37,7 +37,14 @@ export async function getFiles(page: string, options: GetFilesOptions = {}): Pro } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } @@ -59,7 +66,14 @@ export async function getFile(id: string): Promise { } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } @@ -81,7 +95,14 @@ export async function deleteFile(id: string): Promise { } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } @@ -102,6 +123,8 @@ export async function updateFileTags( try { const file = await getFile(id); + if (typeof file === "string") return file; + let newTags = (file?.tags || []).map((tag) => tag.id); if (options.remove) @@ -124,7 +147,14 @@ export async function updateFileTags( } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } @@ -156,7 +186,14 @@ export async function editFile( } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } @@ -220,6 +257,13 @@ export async function uploadFiles( } catch(e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } \ No newline at end of file diff --git a/functions/zipline/folders.ts b/functions/zipline/folders.ts index 2766b96..19c3dd9 100644 --- a/functions/zipline/folders.ts +++ b/functions/zipline/folders.ts @@ -5,7 +5,7 @@ import axios, { type AxiosError } from "axios"; // GET /api/user/folders export async function getFolders( noIncl?: T, -): Promise { +): Promise { const token = db.get("token"); const url = db.get("url"); @@ -26,7 +26,14 @@ export async function getFolders( } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } @@ -48,7 +55,14 @@ export async function getFolder(id: string): Promise { } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } @@ -80,7 +94,14 @@ export async function createFolder( } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } @@ -111,7 +132,14 @@ export async function editFolder( } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } @@ -136,7 +164,14 @@ export async function deleteFolder(id: string): Promise { } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } @@ -165,7 +200,14 @@ export async function removeFileFromFolder( } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } @@ -196,6 +238,13 @@ export async function addFileToFolder( } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } diff --git a/functions/zipline/invites.ts b/functions/zipline/invites.ts index 8b2196f..4fa48ae 100644 --- a/functions/zipline/invites.ts +++ b/functions/zipline/invites.ts @@ -20,7 +20,14 @@ export async function getInvites(): Promise { } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } @@ -48,7 +55,14 @@ export async function createInvite(expiresAt?: string, maxUses?: number): Promis } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } @@ -72,6 +86,13 @@ export async function deleteInvite(code: string): Promise { } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } \ No newline at end of file diff --git a/functions/zipline/settings.ts b/functions/zipline/settings.ts index d3abb04..cec90d0 100644 --- a/functions/zipline/settings.ts +++ b/functions/zipline/settings.ts @@ -20,7 +20,14 @@ export async function getSettings(): Promise { } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } @@ -44,6 +51,13 @@ export async function updateSettings( } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } diff --git a/functions/zipline/stats.ts b/functions/zipline/stats.ts index 08493fb..e5b2a18 100644 --- a/functions/zipline/stats.ts +++ b/functions/zipline/stats.ts @@ -28,7 +28,14 @@ export async function getStats( } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } @@ -50,6 +57,13 @@ export async function getUserStats(): Promise { } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } diff --git a/functions/zipline/tags.ts b/functions/zipline/tags.ts index f91b244..f79bdb5 100644 --- a/functions/zipline/tags.ts +++ b/functions/zipline/tags.ts @@ -20,7 +20,14 @@ export async function getTags(): Promise { } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } @@ -52,7 +59,14 @@ export async function createTag( } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } @@ -74,7 +88,14 @@ export async function deleteTag(id: string): Promise { } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } @@ -106,6 +127,13 @@ export async function editTag(id: string, options: EditTagOptions = {}) { } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } diff --git a/functions/zipline/urls.ts b/functions/zipline/urls.ts index 255c90f..dcf751d 100644 --- a/functions/zipline/urls.ts +++ b/functions/zipline/urls.ts @@ -20,7 +20,14 @@ export async function getURLs(): Promise { } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } @@ -42,7 +49,14 @@ export async function getURL(id: string): Promise { } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } @@ -90,7 +104,14 @@ export async function createURL({ } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } @@ -112,7 +133,14 @@ export async function deleteURL(id: string): Promise { } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } @@ -143,6 +171,13 @@ export async function editURL( } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } diff --git a/functions/zipline/user.ts b/functions/zipline/user.ts index 2e233e6..f042a91 100644 --- a/functions/zipline/user.ts +++ b/functions/zipline/user.ts @@ -20,7 +20,14 @@ export async function getCurrentUser(): Promise { } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } @@ -42,7 +49,14 @@ export async function getRecentFiles(): Promise { } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } diff --git a/functions/zipline/users.ts b/functions/zipline/users.ts index c8d9c7c..3900d9e 100644 --- a/functions/zipline/users.ts +++ b/functions/zipline/users.ts @@ -10,7 +10,7 @@ import type { // GET /api/users(?noincl=true) export async function getUsers( noIncl?: T, -): Promise { +): Promise { const token = db.get("token"); const url = db.get("url"); @@ -31,7 +31,14 @@ export async function getUsers( } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } @@ -52,7 +59,14 @@ export async function getUser(id: string): Promise { } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } @@ -88,7 +102,14 @@ export async function createUser( } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } @@ -116,7 +137,14 @@ export async function deleteUser( } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } @@ -167,6 +195,13 @@ export async function editUser( } catch (e) { const error = e as AxiosError; - return error.response.error; + const data = error.response?.data as { + error: string; + statusCode: number; + } | undefined; + + if (data) return data.error + + return "Something went wrong..." } } diff --git a/styles/files/files.ts b/styles/files/files.ts index 65cde3c..7690f4b 100644 --- a/styles/files/files.ts +++ b/styles/files/files.ts @@ -187,5 +187,16 @@ export const styles = StyleSheet.create({ tagFilesText: { color: "gray", marginLeft: 10 + }, + manageTagButton: { + width: "45%", + marginHorizontal: "2.5%", + }, + manageTagButtonsContainer: { + flexDirection: "row", + justifyContent: "space-between", + }, + guessButton: { + backgroundColor: "#616060" } });