From 09f92c853d9483add3c0e6a9e796b033a6c65df7 Mon Sep 17 00:00:00 2001 From: Aria Moradi Date: Thu, 9 Sep 2021 05:14:17 +0430 Subject: [PATCH] implement the install external apk api --- src/components/Toast.tsx | 20 +++++++++++- src/screens/manga/MangaExtensions.tsx | 44 +++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/src/components/Toast.tsx b/src/components/Toast.tsx index ba0fa56a..dd70e232 100644 --- a/src/components/Toast.tsx +++ b/src/components/Toast.tsx @@ -10,6 +10,7 @@ import React from 'react'; import Slide, { SlideProps } from '@material-ui/core/Slide'; import Snackbar from '@material-ui/core/Snackbar'; import MuiAlert, { Color as Severity } from '@material-ui/lab/Alert'; +import cloneObject from 'util/cloneObject'; function removeToast(id: string) { const container = document.querySelector(`#${id}`)!!; @@ -27,7 +28,7 @@ interface IToastProps{ severity: Severity } -function Toast(props: IToastProps) { +export function Toast(props: IToastProps) { const { message, severity } = props; const [open, setOpen] = React.useState(true); @@ -61,3 +62,20 @@ export default function makeToast(message: string, severity: Severity) { setTimeout(() => removeToast(container.id), 3500); } + +export function makeToaster( + [toasts, setToasts] : [React.ReactElement[], + (arg0: React.ReactElement[]) => void], +): [React.ReactElement[], ((message: string, severity: Severity) => void)] { + return [toasts, (message: string, severity: Severity) => { + const curToasts = cloneObject(toasts); + curToasts.push( + , + ); + setToasts(curToasts); + }]; +} diff --git a/src/screens/manga/MangaExtensions.tsx b/src/screens/manga/MangaExtensions.tsx index e74d4f60..c5dbc13a 100644 --- a/src/screens/manga/MangaExtensions.tsx +++ b/src/screens/manga/MangaExtensions.tsx @@ -6,12 +6,14 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ import React, { useContext, useEffect, useState } from 'react'; +import { fromEvent } from 'file-selector'; import ExtensionCard from 'components/manga/ExtensionCard'; import NavbarContext from 'context/NavbarContext'; import client from 'util/client'; import useLocalStorage from 'util/useLocalStorage'; import ExtensionLangSelect from 'components/manga/ExtensionLangSelect'; import { defualtLangs, langCodeToName, langSortCmp } from 'util/language'; +import { makeToaster } from 'components/Toast'; const allLangs: string[] = []; @@ -81,12 +83,54 @@ export default function MangaExtensions() { } }, [extensionsRaw]); + const [toasts, makeToast] = makeToaster(useState([])); + + const submitExtension = (file: File) => { + if (file.name.toLowerCase().endsWith('apk')) { + const formData = new FormData(); + formData.append('file', file); + + makeToast('Installing Extension File....', 'info'); + client.post('/api/v1/extension/install', + formData, { headers: { 'Content-Type': 'multipart/form-data' } }) + .then(() => { + makeToast('Installed extension successfully!', 'success'); + triggerUpdate(); + }) + .catch(() => makeToast('Extension installion failed!', 'error')); + } else { + makeToast('invalid file type!', 'error'); + } + }; + + const dropHandler = async (e: Event) => { + e.preventDefault(); + const files = await fromEvent(e); + + submitExtension(files[0] as File); + }; + + const dragOverHandler = (e: Event) => { + e.preventDefault(); + }; + + useEffect(() => { + document.addEventListener('drop', dropHandler); + document.addEventListener('dragover', dragOverHandler); + + return () => { + document.removeEventListener('drop', dropHandler); + document.removeEventListener('dragover', dragOverHandler); + }; + }, []); + if (Object.entries(extensions).length === 0) { return

loading...

; } const groupsToShow = ['updates pending', 'installed', ...shownLangs]; return ( <> + {toasts} { Object.entries(extensions).map(([lang, list]) => ( ((groupsToShow.indexOf(lang) !== -1 && (list as []).length > 0)