added file dropping support through `withDrop` hoc

addresses #2
pull/2/head
Michael Ochmann 3 years ago
parent 5022bdf318
commit ca9754cd10
  1. 3
      contextAPI.js
  2. 11
      src/Ation.js
  3. 1
      src/WindowManager.js
  4. 11
      src/ui/src/components/Ation.js
  5. 42
      src/ui/src/higherOrderComponents/withDrop.js
  6. 5
      src/ui/src/index.js

@ -4,5 +4,6 @@ const {contextBridge, ipcRenderer} = require("electron");
contextBridge.exposeInMainWorld("api", { contextBridge.exposeInMainWorld("api", {
openFileDialog : () => ipcRenderer.send("WindowManager::openFileDialog"), openFileDialog : () => ipcRenderer.send("WindowManager::openFileDialog"),
openFile : callback => ipcRenderer.on("Ation::openFile", (_, presentation) => callback(presentation)) onFileOpen : callback => ipcRenderer.on("Ation::openFile", (_, presentation) => callback(presentation)),
openFile : filePath => ipcRenderer.send("WindowManager::openFile", filePath)
}); });

@ -36,10 +36,11 @@ class Ation {
}); });
} }
async openFile() { async openFile(filePath = null) {
if (!this.windowManager.mainWindow) if (!this.windowManager.mainWindow)
return null; return null;
if (!filePath) {
const result = await dialog.showOpenDialog(this.windowManager.mainWindow, { const result = await dialog.showOpenDialog(this.windowManager.mainWindow, {
title : "open file", title : "open file",
filters : [ filters : [
@ -51,10 +52,12 @@ class Ation {
}); });
if (result.canceled || result.filePaths.length < 1) if (result.canceled || result.filePaths.length < 1)
return null; return;
filePath = result.filePaths[0];
}
const fileContents = await fs.readFile(result.filePaths[0], {encoding : "utf-8"}); const fileContents = await fs.readFile(filePath, {encoding : "utf-8"});
const basePath = path.dirname(result.filePaths[0]); const basePath = path.dirname(filePath);
const data = parser(fileContents); const data = parser(fileContents);

@ -18,6 +18,7 @@ class WindowManager {
app.whenReady().then(() => this.init()); app.whenReady().then(() => this.init());
ipcMain.on("WindowManager::openFileDialog", () => this.app.openFile()); ipcMain.on("WindowManager::openFileDialog", () => this.app.openFile());
ipcMain.on("WindowManager::openFile", (_, path) => this.app.openFile(path));
} }
init() { init() {

@ -19,7 +19,7 @@ const Ation = () => {
const [showTips, setShowTips] = useState(false); const [showTips, setShowTips] = useState(false);
useEffect(() => { useEffect(() => {
window.api.openFile(presentation => { window.api.onFileOpen(presentation => {
const [basePath, slideDeck] = presentation; const [basePath, slideDeck] = presentation;
if (!slideDeck) if (!slideDeck)
return; return;
@ -32,10 +32,11 @@ const Ation = () => {
window.api.openFileDialog(); window.api.openFileDialog();
} }
if (deck.length < 1)
return <NoFile openFile={openFile} />;
return ( return (
<>
{deck.length < 1 ?
<NoFile openFile={openFile} />
: (
<SlideContext.Provider value={{slide, setSlide, mode, setMode, basePath}}> <SlideContext.Provider value={{slide, setSlide, mode, setMode, basePath}}>
<section className={`window${mode === Mode.PRESENT ? " fullscreen" : ""}`}> <section className={`window${mode === Mode.PRESENT ? " fullscreen" : ""}`}>
<Toolbar openFile={openFile} setShowTips={setShowTips} /> <Toolbar openFile={openFile} setShowTips={setShowTips} />
@ -48,6 +49,8 @@ const Ation = () => {
<Blackout show={mode === Mode.BLACKOUT} /> <Blackout show={mode === Mode.BLACKOUT} />
<KeyboardControl mode={mode} setMode={setMode} deck={deck} openFile={openFile} setShowTips={setShowTips} /> <KeyboardControl mode={mode} setMode={setMode} deck={deck} openFile={openFile} setShowTips={setShowTips} />
</SlideContext.Provider> </SlideContext.Provider>
)}
</>
); );
}; };

@ -0,0 +1,42 @@
import React, {useState} from "react";
const extension = filename => {
const parts = filename.split('.');
return parts[parts.length - 1];
};
const withDrop = Component => () => {
const [drag, setDrag] = useState(false);
const handleDragOver = event => {
event.preventDefault();
event.stopPropagation();
setDrag(true);
};
const handleDragLeave = event => {
event.preventDefault();
event.stopPropagation();
setDrag(false);
}
const handleDrop = event => {
event.preventDefault();
event.stopPropagation();
const file = event.dataTransfer?.items[0].getAsFile();
if (extension(file.name.toLowerCase()) === "md") {
window.api.openFile(file.path);
}
setDrag(false);
};
return (
<section onDragLeave={handleDragLeave} onDragOver={handleDragOver} onDrop={handleDrop} style={{opacity : drag ? 0.2 : 1}}>
<Component />
</section>
);
};
export default withDrop;

@ -2,12 +2,15 @@ import React from "react";
import ReactDOM from "react-dom/client"; import ReactDOM from "react-dom/client";
import Ation from "./components/Ation"; import Ation from "./components/Ation";
import withDrop from "./higherOrderComponents/withDrop";
import "./assets/css/ation.scss"; import "./assets/css/ation.scss";
const App = withDrop(Ation);
const root = ReactDOM.createRoot(document.getElementById("root")); const root = ReactDOM.createRoot(document.getElementById("root"));
root.render( root.render(
<React.StrictMode> <React.StrictMode>
<Ation /> <App />
</React.StrictMode> </React.StrictMode>
); );
Loading…
Cancel
Save