Skip to content

Commit

Permalink
feat: save as functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
sitarass committed Dec 22, 2023
1 parent 2b1d1dd commit 9c3a7a7
Show file tree
Hide file tree
Showing 9 changed files with 102 additions and 48 deletions.
65 changes: 40 additions & 25 deletions public/electron.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ const path = require("path");
const fs = require("fs");
const Store = require("electron-store");
var QRCode = require("qrcode");

const { app, BrowserWindow, ipcMain } = require("electron");
const { app, BrowserWindow, ipcMain, dialog } = require("electron");

let mainWindow;
const store = new Store();
Expand All @@ -30,7 +29,7 @@ function createWindow() {
mainWindow.on("closed", () => (mainWindow = null));
}

const historyDirName = "QRsHistory";
const historyDirName = `${app.getPath("appData")}/QRsHistory`;

app.whenReady().then(() => {
ipcMain.handle("storage", () => store.get("unicorn"));
Expand Down Expand Up @@ -61,32 +60,48 @@ ipcMain.on("convertUrlsToQRs", (event, urlsArray) => {

const extension = "svg";

const qrData = urlsArray?.map((url) => {
const urlFilename = url?.replace(/^https?:\/\//, "")?.replaceAll("/", "_");
const savedPath = `${storagePath}/${urlFilename}.${extension}`;
const qrData = urlsArray
?.filter((url) => !!url)
?.map((url) => {
const urlFilename = url
?.replace(/^https?:\/\//, "")
?.replaceAll("/", "_");
const savedPath = `${storagePath}/${urlFilename}.${extension}`;

QRCode.toString(url, { type: extension }, function (err, urlData) {
fs.writeFile(savedPath, urlData, function (err) {
if (err) {
return console.log(err);
}
QRCode.toFile(savedPath, url, { type: extension }, function (err) {
if (err) throw err;
});
});

return {
id: url,
file: "file://" + path.resolve(savedPath),
fileName: urlFilename,
extension: extension,
};
});

// console.log(qrData);
return {
id: `${url}${Date.now()}`,
file: path.resolve(savedPath),
fileName: urlFilename,
extension: extension,
};
});

mainWindow.webContents.send("qrData", qrData);
// fs.readFile("path/to/file", (error, data) => {
// // Do something with file contents
});

// // Send result back to renderer process
// });
ipcMain.on("saveQRfile", (event, fileData) => {
const options = {
title: "Save QR",
defaultPath: app.getPath("documents"),
filters: [
{
name: fileData?.fileName,
extensions: [fileData?.extension],
},
],
};

dialog
.showSaveDialog(mainWindow, options)
.then(({ filePath }) => {
if (!filePath) return;
const origin = fs.createReadStream(fileData?.file, { flags: "r" });
const destination = fs.createWriteStream(filePath, { flags: "w+" });
origin.pipe(destination);
})
.catch((err) => {});
});
5 changes: 2 additions & 3 deletions public/preload.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ const { contextBridge, ipcRenderer } = require("electron");
contextBridge.exposeInMainWorld("api", {
send: (channel, data) => {
// whitelist channels
let validChannels = ["convertUrlsToQRs"];
const validChannels = ["convertUrlsToQRs", "saveQRfile"];
if (validChannels.includes(channel)) {
ipcRenderer.send(channel, data);
}
},
receive: (channel, func) => {
let validChannels = ["qrData"];
const validChannels = ["qrData", "saveQRfile"];
if (validChannels.includes(channel)) {
// Deliberately strip event as it includes `sender`
ipcRenderer.on(channel, (event, ...args) => func(...args));
Expand All @@ -22,4 +22,3 @@ contextBridge.exposeInMainWorld("api", {
return result;
}),
});

2 changes: 0 additions & 2 deletions src/components/DialogOverlay/DialogOverlay.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@
height: rem(32);

position: absolute;
top: 50%;
transform: translateY(-50%);
right: 0;
}

Expand Down
23 changes: 17 additions & 6 deletions src/components/Table/QRContentTable.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ import DialogOverlay from "components/DialogOverlay/DialogOverlay";
import useDialog from "hooks/useDialog";
import { StandardDropDown } from "components/DropDown/DropDowns";

const QRContentTable = ({ rows, handleRows, tableStyles }) => {
import styles from "./QRContentTable.module.scss";

const QRContentTable = ({ rows, handleRows }) => {
const qrViewDialog = useDialog();
const [qrView, setQrView] = useState("");

Expand Down Expand Up @@ -46,7 +48,8 @@ const QRContentTable = ({ rows, handleRows, tableStyles }) => {

const newRows = rows.map((row) => {
if (row.id === id) {
return { ...row, [name]: value, canBeReverted: true };
const hasChanged = previous[row.id]?.[name] !== value;
return { ...row, [name]: value, canBeReverted: hasChanged };
}
return row;
});
Expand All @@ -57,14 +60,18 @@ const QRContentTable = ({ rows, handleRows, tableStyles }) => {
const handleChangeCell = (row) => (e) => handleChangeRow(e, row);

const handleQrPreview = (row) => (e) => {
console.log(row?.file);
setQrView(row?.file);
setQrView(`file://${row?.file}`);
qrViewDialog.show();
};

const handleSaveAs = (row) => (e) => {
console.log("save as");
window.api.send("saveQRfile", row);
};

return (
<>
<TableContainer className={tableStyles}>
<TableContainer>
<Table aria-label="caption table" stickyHeader>
<TableHead>
<TableRow>
Expand All @@ -79,6 +86,7 @@ const QRContentTable = ({ rows, handleRows, tableStyles }) => {
<TableRow key={row.id}>
<TableCell>
<IconButton
className={!row.canBeReverted ? styles["gray-fill"] : ""}
aria-label="undo"
onClick={() => onRevert(row.id)}
disabled={!row.canBeReverted}
Expand Down Expand Up @@ -111,7 +119,10 @@ const QRContentTable = ({ rows, handleRows, tableStyles }) => {
{/* add drop down at the above one */}
<TableCell align="left">
<IconButton aria-label="saveAs" onClick={() => {}}>
<SaveAsIcon />
<SaveAsIcon
aria-label="saveAs"
onClick={handleSaveAs(row)}
/>
</IconButton>
<IconButton
aria-label="preview"
Expand Down
17 changes: 17 additions & 0 deletions src/components/Table/QRContentTable.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
@use "../../styles/utils" as *;

.container {
display: flex;
flex-direction: column;
gap: rem(32);
width: 100%;
flex: 1;
}

.gray-fill {
svg {
path {
fill: $gray-medium;
}
}
}
2 changes: 0 additions & 2 deletions src/containers/QRGeneratorLayout.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@
display: flex;
flex-direction: column;
gap: rem(32);
align-items: center;

@include desktop-up {
flex-direction: row;

}
}
1 change: 0 additions & 1 deletion src/utils/materialTheme.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ const theme = createTheme({
MuiTableContainer: {
styleOverrides: {
root: {
height: "100%",
color: colors.action,
},
},
Expand Down
16 changes: 11 additions & 5 deletions src/views/QRGenerator.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { PrimaryButton } from "components/Buttons/Buttons";
import { useForm } from "react-hook-form";
import { tableDataTransformer } from "utils/stringUtils";
import QRContentTable from "components/Table/QRContentTable";
import { SecondaryButton } from "components/Buttons/Buttons";

import styles from "./QRGenerator.module.scss";

Expand Down Expand Up @@ -42,11 +43,16 @@ const QRGenerator = () => {
>
Generate
</PrimaryButton>
<QRContentTable
rows={qrData}
handleRows={setQrData}
tableStyles={styles.tableContainer}
/>
<div className={styles.container}>
<QRContentTable
rows={qrData}
handleRows={setQrData}
tableStyles={styles.tableInnerContainer}
/>
<SecondaryButton className={styles.saveAsButton} onClick={() => {}}>
Save as all
</SecondaryButton>
</div>
</QRGeneratorLayout>
);
};
Expand Down
19 changes: 15 additions & 4 deletions src/views/QRGenerator.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,21 @@
width: 100%;
}

.tableContainer{
.submitButton {
max-width: rem(256);
align-self: center;
}

.container {
flex: 1;
overflow: auto;

display: flex;
flex-direction: column;
gap: rem(16);
}

.submitButton{
max-width: rem(256);
}
.saveAsButton {
max-width: rem(212);
align-self: flex-end;
}

0 comments on commit 9c3a7a7

Please sign in to comment.