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)