Skip to content

WIP: right click -> open with macos file support #64

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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: 3 additions & 1 deletion docs/release.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ $ npm run package

## TL;DR

```
```bash
# on macOS
$ npm run release
# a draft github release will be created
```

// TODO: Then, some more work needs to be done -- upload to Flathub, snap, dnf copr, aur, and homebrew. Update the URLs in the [Homebrew taps repo](https://www.github.com/alichtman/homebrew-taps).
Expand Down
10 changes: 10 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,16 @@
"arm64"
]
},
"fileAssociations": [
{
"ext": [
"dbolt",
"deadbolt"
],
"description": "Encrypted files",
"role": "Viewer"
}
],
"type": "distribution",
"hardenedRuntime": true,
"entitlements": "assets/entitlements.mac.plist",
Expand Down
8 changes: 8 additions & 0 deletions src/main/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,14 @@ const createWindow = async () => {
* Add event listeners...
*/

app.on('open-file', (event, fileOpenedWithDeadbolt) => {
event.preventDefault();
console.log('open-file', fileOpenedWithDeadbolt);
if (mainWindow) {
mainWindow.webContents.send('file-opened', fileOpenedWithDeadbolt);
}
});

app.on('window-all-closed', () => {
// Respect the OSX convention of having the application in memory even
// after all windows have been closed
Expand Down
3 changes: 3 additions & 0 deletions src/main/preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,7 @@ contextBridge.exposeInMainWorld('electronAPI', {
ipcRenderer.invoke('prettyPrintFilePath', [filePath]),
revealFileInFinder: (filePath: string) =>
ipcRenderer.invoke('revealFileInFinder', [filePath]),
handleFileOpen: (callback: (filePath: string) => void) => {
ipcRenderer.on('file-opened', (_event, filePath) => callback(filePath));
},
});
35 changes: 21 additions & 14 deletions src/renderer/App.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable no-alert */
/* eslint-disable no-else-return */
/* eslint-disable no-console */
import { useState } from 'react';
import { useState, useEffect } from 'react';
import './App.css';
import CircularProgress from '@mui/material/CircularProgress';
import FileUpload from './FileUpload';
Expand Down Expand Up @@ -45,10 +45,10 @@ export function isDeadboltFile(filePath: string | undefined): boolean {
}

export default function App() {
// This is just a handle on the file for the path -- you can't actually read or write to it in the renderer process.
const [fileToWorkWith, setFileToWorkWith] = useState<File | undefined>(
undefined,
);
// This is just a handle on the file path
const [filePathToWorkWith, setFilePathToWorkWith] = useState<
string | undefined
>(undefined);
const [pathToEncryptedOrDecryptedFile, setPathToEncryptedOrDecryptedFile] =
useState<string | undefined>(undefined);
const [viewState, setViewState] = useState<ViewState>(ViewState.FILE_UPLOAD);
Expand All @@ -61,7 +61,7 @@ export default function App() {

const resetToFileUpload = () => {
setViewState(ViewState.FILE_UPLOAD);
setFileToWorkWith(undefined);
setFilePathToWorkWith(undefined);
};

const revealInFinder = () => {
Expand Down Expand Up @@ -129,15 +129,22 @@ export default function App() {
});
};

const handleFileSelection = (file: File) => {
const isEncrypted = isDeadboltFile(file.name);
const handleFileSelection = (filePath: string) => {
const isEncrypted = isDeadboltFile(filePath);
console.log('File is encrypted?', isEncrypted);
console.log('File path:', file.name);
setFileToWorkWith(file);
console.log('File path:', filePath);
setFilePathToWorkWith(filePath);
setFileIsEncrypted(isEncrypted);
setViewState(ViewState.ENCRYPT_OR_DECRYPT);
};

useEffect(() => {
window.electronAPI.handleFileOpen((filePath) => {
console.log('handleFileOpen', filePath);
handleFileSelection(filePath);
});
}, []);

if (loading) {
return (
<div
Expand All @@ -154,12 +161,12 @@ export default function App() {
);
}

if (viewState === ViewState.FILE_UPLOAD || !fileToWorkWith) {
return <FileUpload setFileToWorkWith={handleFileSelection} />;
if (viewState === ViewState.FILE_UPLOAD || !filePathToWorkWith) {
return <FileUpload setFilePathToWorkWith={handleFileSelection} />;
} else if (viewState === ViewState.ENCRYPT_OR_DECRYPT && !fileIsEncrypted) {
return (
<EncryptOrDecryptForm
file={fileToWorkWith}
filePath={filePathToWorkWith}
onSubmit={encryptFile}
onCancel={() => {
resetToFileUpload();
Expand All @@ -170,7 +177,7 @@ export default function App() {
} else if (viewState === ViewState.ENCRYPT_OR_DECRYPT && fileIsEncrypted) {
return (
<EncryptOrDecryptForm
file={fileToWorkWith}
filePath={filePathToWorkWith}
onSubmit={decryptFile}
onCancel={() => {
resetToFileUpload();
Expand Down
14 changes: 7 additions & 7 deletions src/renderer/EncryptOrDecryptForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ import EncryptOrDecryptFileHeader from './EncryptOrDecryptFileHeader';

export default function EncryptOrDecryptForm({
isDecryption,
file,
filePath,
onSubmit,
onCancel,
}: {
isDecryption: boolean;
file: File;
filePath: string;
onSubmit: (filePath: string, password: string) => void;
onCancel: () => void;
}): React.ReactNode | null {
Expand Down Expand Up @@ -44,9 +44,9 @@ export default function EncryptOrDecryptForm({
const onKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
if (event.key === 'Enter') {
if (isDecryption) {
onSubmit(file.path, password);
onSubmit(filePath, password);
} else if (validatePassword()) {
onSubmit(file.path, password);
onSubmit(filePath, password);
} else {
// Encryption, passwords don't match
setDisplayError(true);
Expand All @@ -59,7 +59,7 @@ export default function EncryptOrDecryptForm({

return (
<>
<EncryptOrDecryptFileHeader fileName={file.path} />
<EncryptOrDecryptFileHeader fileName={filePath} />

<div
className="formBody"
Expand Down Expand Up @@ -105,9 +105,9 @@ export default function EncryptOrDecryptForm({
buttonType="primary"
onClick={() => {
if (!isDecryption && validatePassword()) {
onSubmit(file.path, password);
onSubmit(filePath, password);
} else if (isDecryption) {
onSubmit(file.path, password);
onSubmit(filePath, password);
}
}}
>
Expand Down
8 changes: 4 additions & 4 deletions src/renderer/FileUpload.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ function DeadboltVersionTagAndGithubLink() {
}

export default function FileUpload({
setFileToWorkWith,
setFilePathToWorkWith,
}: {
setFileToWorkWith: (file: File) => void;
setFilePathToWorkWith: (filepath: string) => void;
}) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const onSelectFromFileBrowser = (files: File[], _event: DropEvent) => {
console.log('File dropped:', files);
setFileToWorkWith(files[0]);
setFilePathToWorkWith(files[0].path);
};

// Drag-and-drop doesn't give us the file path, so we need to use this super hacky workaround: https://github.com/react-dropzone/file-selector/issues/10#issuecomment-2482649010
Expand All @@ -44,7 +44,7 @@ export default function FileUpload({
event.preventDefault();
const file = event.dataTransfer?.files[0];
if (file != null) {
setFileToWorkWith(file);
setFilePathToWorkWith(file.path);
}
};

Expand Down
1 change: 1 addition & 0 deletions src/renderer/preload.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ declare global {
password: string,
) => Promise<string>;
prettyPrintFilePath: (filePath: string) => Promise<string>;
handleFileOpen: (callback: (filePath: string) => void) => void;
};
}
}
Expand Down
Loading