Skip to content

Commit

Permalink
feature: ability to drag and drop images into editor
Browse files Browse the repository at this point in the history
  • Loading branch information
khakimov committed Nov 12, 2023
1 parent bc60588 commit a161a57
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 62 deletions.
71 changes: 38 additions & 33 deletions src/main/ipc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,43 +165,48 @@ ipcMain.on('open-file-dialog', async (event) => {
}
});

ipcMain.handle('save-file', async (event, { fileData, fileExtension, storePath }) => {
try {
const currentDate = new Date();
const year = String(currentDate.getFullYear()).slice(-2);
const month = String(currentDate.getMonth() + 1).padStart(2, '0');
const day = String(currentDate.getDate()).padStart(2, '0');
const hours = String(currentDate.getHours()).padStart(2, '0');
const minutes = String(currentDate.getMinutes()).padStart(2, '0');
const seconds = String(currentDate.getSeconds()).padStart(2, '0');
const fileName = `${year}${month}${day}-${hours}${minutes}${seconds}.${fileExtension}`;
const fullStorePath = path.join(
storePath,
String(currentDate.getFullYear()),
currentDate.toLocaleString('default', { month: 'short' }),
'media'
);
const newFilePath = path.join(fullStorePath, fileName);

// Convert Data URL to Buffer
const dataUrlParts = fileData.split(';base64,');
const fileBuffer = Buffer.from(dataUrlParts[1], 'base64');

await fs.promises.mkdir(fullStorePath, { recursive: true });
await fs.promises.writeFile(newFilePath, fileBuffer);
return newFilePath;
ipcMain.handle(
'save-file',
async (event, { fileData, fileExtension, storePath }) => {
try {
const currentDate = new Date();
const year = String(currentDate.getFullYear()).slice(-2);
const month = String(currentDate.getMonth() + 1).padStart(2, '0');
const day = String(currentDate.getDate()).padStart(2, '0');
const hours = String(currentDate.getHours()).padStart(2, '0');
const minutes = String(currentDate.getMinutes()).padStart(2, '0');
const seconds = String(currentDate.getSeconds()).padStart(2, '0');
const milliseconds = String(currentDate.getMilliseconds()).padStart(
3,
'0'
);
const fileName = `${year}${month}${day}-${hours}${minutes}${seconds}${milliseconds}.${fileExtension}`;
const fullStorePath = path.join(
storePath,
String(currentDate.getFullYear()),
currentDate.toLocaleString('default', { month: 'short' }),
'media'
);
const newFilePath = path.join(fullStorePath, fileName);

// Convert Data URL to Buffer
const dataUrlParts = fileData.split(';base64,');
const fileBuffer = Buffer.from(dataUrlParts[1], 'base64');

} catch (error) {
console.error('Failed to save the file:', error);
await fs.promises.mkdir(fullStorePath, { recursive: true });
await fs.promises.writeFile(newFilePath, fileBuffer);
return newFilePath;
} catch (error) {
console.error('Failed to save the file:', error);
}
}
});

);

ipcMain.handle('open-file', async (event, data) => {
let attachments: string[] = [];
const storePath = data.storePath;
const selected = await dialog.showOpenDialog({
properties: ['openFile'],
properties: ['openFile', 'multiSelections'],
filters: [
{ name: 'Images', extensions: ['jpg', 'jpeg', 'png', 'gif', 'svg'] },
{ name: 'Movies', extensions: ['mp4', 'mov'] },
Expand All @@ -214,7 +219,7 @@ ipcMain.handle('open-file', async (event, data) => {
return attachments;
}

for (const filePath of selectedFiles) {
for (const [index, filePath] of selectedFiles.entries()) {
const currentDate = new Date();
const year = String(currentDate.getFullYear()).slice(-2);
const month = String(currentDate.getMonth() + 1).padStart(2, '0');
Expand All @@ -224,10 +229,10 @@ ipcMain.handle('open-file', async (event, data) => {
const seconds = String(currentDate.getSeconds()).padStart(2, '0');
const selectedFileName = filePath.split('/').pop();

if (!selectedFileName) return;
if (!selectedFileName) continue;

const extension = selectedFileName.split('.').pop();
const fileName = `${year}${month}${day}-${hours}${minutes}${seconds}.${extension}`;
const fileName = `${year}${month}${day}-${hours}${minutes}${seconds}-${index}.${extension}`;
const fullStorePath = path.join(
storePath,
String(currentDate.getFullYear()),
Expand Down
2 changes: 0 additions & 2 deletions src/renderer/hooks/usePostHelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@ export const attachToPostCreator =
storePath: storePath,
});
}


// Attachments are stored relative to the base path from the
// base directory of the pile
const correctedPaths = newAttachments.map((path) => {
Expand Down
88 changes: 61 additions & 27 deletions src/renderer/pages/Pile/Editor/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,26 +52,55 @@ export default function Editor({

addCommands() {
return {
triggerSubmit: () => ({ state, dispatch }) => {
// This will trigger a 'submit' event on the editor
const event = new CustomEvent('submit');
document.dispatchEvent(event);

return true;
},
triggerSubmit:
() =>
({ state, dispatch }) => {
// This will trigger a 'submit' event on the editor
const event = new CustomEvent('submit');
document.dispatchEvent(event);

return true;
},
};
},

addKeyboardShortcuts() {
return {
'Enter': ({ editor }) => {
Enter: ({ editor }) => {
editor.commands.triggerSubmit();
return true;
},
};
},
});

const handleFile = (fileOrItem) => {
let file;
if (fileOrItem instanceof DataTransferItem) {
file = fileOrItem.getAsFile();

if (!file) {
return;
}
} else if (fileOrItem instanceof File) {
file = fileOrItem;
} else {
throw new Error('Invalid argument: must be a File or DataTransferItem');
}

if (file && file.type.indexOf('image') === 0) {
const fileName = file.name; // Retrieve the filename
const fileExtension = fileName.split('.').pop(); // Extract the file extension
// Handle the image file here (e.g., upload, display, etc.)
const reader = new FileReader();
reader.onload = () => {
const imageData = reader.result;
attachToPost(imageData, fileExtension);
};
reader.readAsDataURL(file);
}
};

const editor = useEditor({
extensions: [
StarterKit,
Expand All @@ -86,26 +115,31 @@ export default function Editor({
EnterSubmitExtension,
],
editorProps: {
handlePaste: function(view, event, slice) {
handlePaste: function (view, event, slice) {
const items = Array.from(event.clipboardData?.items || []);
for (const item of items) {
if (item.type.indexOf("image") === 0) {
const file = item.getAsFile();
const fileName = file.name; // Retrieve the filename
const fileExtension = fileName.split('.').pop(); // Extract the file extension
// Handle the image file here (e.g., upload, display, etc.)
const reader = new FileReader();
reader.onload = () => {
const imageData = reader.result;
attachToPost(imageData, fileExtension);
};
reader.readAsDataURL(file);

return true; // handled
}
let imageHandled = false; // flag to track if an image was handled

if (items) {
items.forEach(handleFile);
imageHandled = true;
}
return false; // not handled use default behaviour
}
return imageHandled;
},
handleDrop: function (view, event, slice, moved) {
let imageHandled = false; // flag to track if an image was handled
if (
!moved &&
event.dataTransfer &&
event.dataTransfer.files &&
event.dataTransfer.files[0]
) {
// if dropping external files
const items = Array.from(event.dataTransfer.files);
items.forEach(handleFile);
return imageHandled; // handled
}
return imageHandled; // not handled use default behaviour
},
},
autofocus: true,
editable: editable,
Expand Down Expand Up @@ -251,7 +285,7 @@ export default function Editor({
if (!post) return;

return (
<div className={`${styles.frame} ${isNew && styles.isNew}`}>
<div className={`${styles.frame} ${isNew && styles.isNew}`}>
{editable ? (
<EditorContent
key={'new'}
Expand Down

0 comments on commit a161a57

Please sign in to comment.