diff --git a/src/App.global.css b/src/App.global.css index c88f0bb..83b5483 100644 --- a/src/App.global.css +++ b/src/App.global.css @@ -11,8 +11,8 @@ @apply outline-none hover:opacity-80 active:text-gray-300 active:outline-none focus:outline-none; } - input[type='text'] { - @apply rounded focus:ring-blue-500 focus:outline-none focus:ring-2 focus:ring-inset; + input[type='number'] { + @apply px-1 py-0.5 rounded focus:ring-blue-500 focus:outline-none focus:ring-2 focus:ring-inset; } input[type='radio'] { diff --git a/src/App.tsx b/src/App.tsx index bd5b239..ce8141b 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -16,7 +16,11 @@ export default function App() { render={(props) => { const { search } = props.location; const so = qs.parse(search.slice(search.lastIndexOf('?') + 1)); - return so.page === 'screen' ? :
; + return so.page === 'screen' ? ( + + ) : ( +
+ ); }} /> diff --git a/src/components/printer/Main.tsx b/src/components/printer/Main.tsx index 9ad6164..93a6aa8 100644 --- a/src/components/printer/Main.tsx +++ b/src/components/printer/Main.tsx @@ -1,16 +1,107 @@ -import React from 'react'; +import React, { useState } from 'react'; import { ipcRenderer } from 'electron'; +interface Coord { + select: string; + x0: number; + y0: number; + x1: number; + y1: number; +} + const Main = () => { - const handleScreenSelect = async () => { - await ipcRenderer.invoke('open-screen'); + const [frameCoord, setFrameCoord] = useState(); + const [nextCoord, setNextCoord] = useState(); + const [pages, setPages] = useState(0); + + const handleCloseScreen = (c: Coord) => { + if (c.select === 'frame') { + setFrameCoord({ ...c }); + } else if (c.select === 'next') { + setNextCoord({ ...c }); + } + }; + + const handleOpenScreen = (select: string) => { + if (select === 'frame') { + setFrameCoord(undefined); + } else { + setNextCoord(undefined); + } + + ipcRenderer.invoke('open-screen', { select }); }; + const handlePrint = () => { + ipcRenderer.invoke('start-printing', { frameCoord, nextCoord, pages }); + }; + + ipcRenderer.on('close-screen', (_, c: Coord) => { + handleCloseScreen(c); + }); + return ( -
- +
+
+
+ + {frameCoord ? ( +

+ Rect: ({frameCoord.x0}, {frameCoord.y0}) and ({frameCoord.x1},{' '} + {frameCoord.y1}) +

+ ) : ( +

+ )} +

+ +
+ + {nextCoord ? ( +

+ Point: ({(nextCoord.x0 + nextCoord.x1) / 2},{' '} + {(nextCoord.y0 + nextCoord.y1) / 2}) +

+ ) : ( +

+ )} +

+ +
+

Total pages:

+ setPages(parseInt(e.target.value, 10))} + type="number" + /> +
+
+ +
+ +

+ You can stop printing anytime by pressing the "ESC" button +

+
); }; diff --git a/src/components/printer/Screen.tsx b/src/components/printer/Screen.tsx index 5e1e037..96eb5c5 100644 --- a/src/components/printer/Screen.tsx +++ b/src/components/printer/Screen.tsx @@ -1,10 +1,104 @@ -import React from 'react'; +import { ipcRenderer } from 'electron'; +import React, { MouseEvent, useRef, useState, useEffect } from 'react'; + +const Screen = ({ select }: { select: string }) => { + const parentRef = useRef(null); + const canvasRef = useRef(null); + + const [mouse, setMouse] = useState({ + select, + startX: 0, + startY: 0, + x0: 0, + y0: 0, + x1: 0, + y1: 0, + }); + const [draging, setDraging] = useState(false); + + const closeScreen = () => { + ipcRenderer.invoke('close-screen', { ...mouse }); + }; + + const setCanvasSize = () => { + const ctx = canvasRef.current; + if (ctx) { + ctx.width = window.innerWidth || 1000; + ctx.height = window.innerHeight || 1000; + } + }; + + const handleMouseDown = (ev: MouseEvent) => { + setMouse({ + ...mouse, + startX: ev.pageX - (canvasRef.current?.getBoundingClientRect().left || 0), + startY: ev.pageY - (canvasRef.current?.getBoundingClientRect().top || 0), + x0: ev.screenX, + y0: ev.screenY, + }); + + setCanvasSize(); + setDraging(true); + }; + + const handleMouseMove = (ev: MouseEvent) => { + if (!draging) { + return; + } + + const ctx = canvasRef.current?.getContext('2d'); + + if (ctx) { + const width = + ev.pageX - + (canvasRef.current?.getBoundingClientRect().left || 0) - + mouse.startX; + const height = + ev.pageY - + (canvasRef.current?.getBoundingClientRect().top || 0) - + mouse.startY; + + setMouse({ + ...mouse, + x1: ev.screenX, + y1: ev.screenY, + }); + + ctx.clearRect( + 0, + 0, + parentRef.current?.clientWidth || 1000, + parentRef.current?.clientHeight || 1000 + ); + ctx.fillStyle = 'rgba(0, 0, 0, 0.5)'; + ctx.fillRect(mouse.startX, mouse.startY, width, height); + } + }; + + const handleMouseUp = () => { + setDraging(false); + closeScreen(); + }; + + useEffect(() => { + window.onblur = closeScreen; + window.onresize = setCanvasSize; + }, []); -const Screen = () => { return ( -
-

Hello!

-
+
+ +
); }; diff --git a/src/main.dev.ts b/src/main.dev.ts index 48ba3a4..e714fde 100644 --- a/src/main.dev.ts +++ b/src/main.dev.ts @@ -71,6 +71,8 @@ const installExtensions = async () => { .catch(console.log); }; +let stopPrinting = false; + const createWindow = async () => { if ( process.env.NODE_ENV === 'development' || @@ -89,8 +91,8 @@ const createWindow = async () => { mainWindow = new BrowserWindow({ show: false, - width: 1024, - height: 728, + width: 512, + height: 364, icon: getAssetPath('icon.png'), webPreferences: { nodeIntegration: true, @@ -113,6 +115,12 @@ const createWindow = async () => { } }); + mainWindow.webContents.on('before-input-event', (event, ipnut) => { + if (ipnut.key === 'Escape') { + stopPrinting = true; + } + }); + mainWindow.on('closed', () => { mainWindow = null; }); @@ -177,21 +185,25 @@ ipcMain.handle( } ); -const createScreenWindow = () => { +const createScreenWindow = (select: string) => { if (screenWindow == null) { screenWindow = new BrowserWindow({ frame: false, transparent: true, webPreferences: { nodeIntegration: true, + contextIsolation: false, }, + parent: mainWindow || undefined, }); } - screenWindow.loadURL(`file://${__dirname}/index.html?page=screen`); + screenWindow.loadURL( + `file://${__dirname}/index.html?page=screen&select=${select}` + ); screenWindow.webContents.on('did-finish-load', () => { - screenWindow?.show(); screenWindow?.maximize(); + screenWindow?.show(); }); screenWindow.webContents.on('before-input-event', (event, ipnut) => { @@ -207,14 +219,23 @@ const createScreenWindow = () => { screenWindow.webContents.openDevTools({ mode: 'undocked' }); }; -ipcMain.handle('open-screen', async () => { - createScreenWindow(); +ipcMain.handle('open-screen', async (_, { select }) => { + createScreenWindow(select); }); ipcMain.handle('get-store', (_event, { key }) => { return store.get(key); }); +ipcMain.handle('close-screen', (_, coord) => { + mainWindow?.webContents.send('close-screen', coord); + screenWindow?.close(); +}); + +ipcMain.handle('start-printing', (_, { frameCoord, nextCoord, pages }) => { + console.log('Print with params', frameCoord, nextCoord, pages); +}); + /** * Add event listeners... */ diff --git a/src/package.json b/src/package.json index 8aa05de..74848c8 100644 --- a/src/package.json +++ b/src/package.json @@ -1,7 +1,7 @@ { "name": "plainprinter", "productName": "PlainPrinter", - "version": "0.0.7", + "version": "0.0.1", "description": "Plain screen printer", "main": "./main.prod.js", "author": { diff --git a/yarn.lock b/yarn.lock index e9caabc..6e0f5a6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1586,11 +1586,6 @@ resolved "https://registry.npmjs.org/@types/debug/-/debug-4.1.5.tgz" integrity sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ== -"@types/diff@^5.0.1": - version "5.0.1" - resolved "https://registry.npmjs.org/@types/diff/-/diff-5.0.1.tgz" - integrity sha512-XIpxU6Qdvp1ZE6Kr3yrkv1qgUab0fyf4mHYvW8N3Bx3PCsbN6or1q9/q72cv5jIFWolaGH08U9XyYoLLIykyKQ== - "@types/enzyme-adapter-react-16@^1.0.6": version "1.0.6" resolved "https://registry.npmjs.org/@types/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.0.6.tgz"