Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/App.global.css
Original file line number Diff line number Diff line change
Expand Up @@ -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'] {
Expand Down
6 changes: 5 additions & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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' ? <Screen /> : <Main />;
return so.page === 'screen' ? (
<Screen select={so.select?.toString() || 'frame'} />
) : (
<Main />
);
}}
/>
</Switch>
Expand Down
105 changes: 98 additions & 7 deletions src/components/printer/Main.tsx
Original file line number Diff line number Diff line change
@@ -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<Coord>();
const [nextCoord, setNextCoord] = useState<Coord>();
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 (
<section className="flex flex-1">
<button type="button" onClick={handleScreenSelect}>
Open
</button>
<section className="absolute inset-0 flex flex-col items-stretch justify-center p-8 space-y-8 bg-gray-100">
<section className="flex flex-col items-stretch flex-1 p-4 border rounded space-y-7">
<section className="flex items-center justify-start space-x-4">
<button
type="button"
onClick={() => handleOpenScreen('frame')}
className="btn"
>
Select screenshot frame...
</button>
{frameCoord ? (
<p>
Rect: ({frameCoord.x0}, {frameCoord.y0}) and ({frameCoord.x1},{' '}
{frameCoord.y1})
</p>
) : (
<p />
)}
</section>

<section className="flex items-center justify-start space-x-4">
<button
type="button"
onClick={() => handleOpenScreen('next')}
className="btn"
>
Select next button...
</button>
{nextCoord ? (
<p>
Point: ({(nextCoord.x0 + nextCoord.x1) / 2},{' '}
{(nextCoord.y0 + nextCoord.y1) / 2})
</p>
) : (
<p />
)}
</section>

<section className="flex items-center justify-start ml-1 space-x-4">
<p>Total pages:</p>
<input
value={pages}
onChange={(e) => setPages(parseInt(e.target.value, 10))}
type="number"
/>
</section>
</section>

<section className="flex flex-col items-center space-y-4">
<button
type="button"
onClick={handlePrint}
className="w-full py-2 text-base btn"
disabled={!frameCoord || !nextCoord || !pages}
>
Start printing
</button>
<p className="opacity-50">
You can stop printing anytime by pressing the &quot;ESC&quot; button
</p>
</section>
</section>
);
};
Expand Down
104 changes: 99 additions & 5 deletions src/components/printer/Screen.tsx
Original file line number Diff line number Diff line change
@@ -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<HTMLDivElement>(null);
const canvasRef = useRef<HTMLCanvasElement>(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 (
<section className="flex flex-1">
<p>Hello!</p>
</section>
<div
style={{ cursor: draging ? 'crosshair' : 'default' }}
className="w-full h-full"
ref={parentRef}
>
<canvas
ref={canvasRef}
className="bg-gray-50 opacity-20"
onMouseDown={handleMouseDown}
onMouseMove={handleMouseMove}
onMouseUp={handleMouseUp}
/>
</div>
);
};

Expand Down
35 changes: 28 additions & 7 deletions src/main.dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ const installExtensions = async () => {
.catch(console.log);
};

let stopPrinting = false;

const createWindow = async () => {
if (
process.env.NODE_ENV === 'development' ||
Expand All @@ -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,
Expand All @@ -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;
});
Expand Down Expand Up @@ -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) => {
Expand All @@ -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...
*/
Expand Down
2 changes: 1 addition & 1 deletion src/package.json
Original file line number Diff line number Diff line change
@@ -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": {
Expand Down
5 changes: 0 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down