Skip to content

Commit

Permalink
Merge pull request #115 from meld-cp/dev
Browse files Browse the repository at this point in the history
Merge with dev
  • Loading branch information
meld-cp authored Aug 27, 2023
2 parents 5f49006 + 9eb1094 commit 764c6ea
Show file tree
Hide file tree
Showing 26 changed files with 924 additions and 537 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ package-lock.json
dist
*.map
test-vault

29 changes: 23 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ You can install the plugin via the Community Plugins tab within Obsidian by sear

> Please report any bugs or feature requests [here](https://github.com/meld-cp/obsidian-encrypt/issues).
### 2.3.0
- add encrypt/decrypt of `.md` or `.encrypted` notes #68 (via file context menu, ribbon icon or command palette, helps with #91, #103, #108, #114)
- fix double blank line #107
- fix offline decrypt tool #111 (found in `/tools/decrypt.html`)
- ribbon icon changes
- code refactor and clean up

### 2.2.0
- stronger encryption (thanks @brycx)
- fix #92 - Enable selection text in Reading view
Expand All @@ -51,9 +58,9 @@ https://raw.githubusercontent.com/meld-cp/obsidian-encrypt/main/
<img alt="Run the Encrypt/Decrypt command" src="https://raw.githubusercontent.com/meld-cp/obsidian-encrypt/main/docs/assets/eg_ed_cp.png" />
-->

### Standalone, always encrypted, notes (.encrypted files)
### Whole encrypted notes (.encrypted files)
#### To create a new encrypted note
1. Select 'Create encrypted note' from the command palette.
1. Select 'Create encrypted note' from the command palette (or click the ribbon icon).
2. Enter and confirm a password and optional hint to use.
3. Edit your encrypted note (it's contents will be encrypted and saved to disk).

Expand All @@ -64,9 +71,20 @@ https://raw.githubusercontent.com/meld-cp/obsidian-encrypt/main/
#### To changing an encrypted notes password and hint
1. Open the note as usual from the navigation tree.
2. Enter the password for the note.
3. Click 'Change Password' from the tab title bar or tab context menu.
3. Click the 'Change Password' icon from the tab title bar or tab context menu.
4. Enter the new password and hint.

#### To encrypt/decrypt an existing note
- Right-click the file and choose 'Encrypt note' or 'Decrypt note'.

OR

- Select the ribbon icon named 'Convert to or from an Encrypted note' to toggle the active file between encrypted and not.

OR

- Select 'Convert to or from an Encrypted note' from the command palette (or even better, bind a hot key)

### In-place Encryption

#### To encrypt selected text
Expand Down Expand Up @@ -105,15 +123,14 @@ https://raw.githubusercontent.com/meld-cp/obsidian-encrypt/main/
### Common Settings
| | |
|--|--|
| Confirm password | Confirm password when encrypting |
| Confirm password | Confirm password when encrypting (recommended) |
| Remember password | Remember the last used password for this session. |
| Remember Password Timeout | The number of minutes to remember the last used password. |
| Remember Password Using | Remember passwords by using File or Parent path |
| Remember Password Using | Remember passwords by using `File Name` or `Parent Folder` matching |

### Whole note encryption Settings
| | |
|--|--|
| Add ribbon icon to create note | Adds a ribbon icon to the left bar to create an encrypted note. |
| Default view for new tabs | The default view that a new encrypted note tab gets opened in |

### In-place encryption Settings
Expand Down
24 changes: 24 additions & 0 deletions esbuild-tool-decrypt.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import esbuild from "esbuild";
import process from "process";
import copyStaticFiles from 'esbuild-copy-static-files';

const prod = (process.argv[2] === 'production');

esbuild.build({
entryPoints: ['src/tools/offline-decrypt.ts'],
bundle: true,
format: 'iife',
watch: !prod,
target: 'es2018',
logLevel: "info",
sourcemap: prod ? false : 'inline',
treeShaking: prod,
minify: prod,
outfile: './tools/offline-decrypt.js',
plugins:[
copyStaticFiles({
src: './src/tools/decrypt.html',
dest: './tools/decrypt.html',
}),
]
}).catch(() => process.exit(1));
4 changes: 2 additions & 2 deletions manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "meld-encrypt",
"name": "Meld Encrypt",
"version": "2.2.0",
"version": "2.3.0",
"minAppVersion": "1.0.3",
"description": "Hide secrets in your vault",
"author": "meld-cp",
Expand All @@ -10,5 +10,5 @@
"fundingUrl": {
"Buy Me a Coffee": "https://www.buymeacoffee.com/cleon",
"GitHub Sponsor": "https://github.com/sponsors/meld-cp"
}
}
}
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
{
"name": "obsidian-sample-plugin",
"version": "2.2.0",
"version": "2.3.0",
"description": "Hide secrets in your vault",
"main": "main.js",
"scripts": {
"dev": "node esbuild.config.mjs",
"build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production",
"version": "node version-bump.mjs && git add manifest.json versions.json"
"version": "node version-bump.mjs && git add manifest.json versions.json",
"dev-tool-decrypt": "tsc -noEmit -skipLibCheck && node esbuild-tool-decrypt.config.mjs",
"build-tool-decrypt": "tsc -noEmit -skipLibCheck && node esbuild-tool-decrypt.config.mjs production"
},
"keywords": [],
"author": "",
Expand Down
197 changes: 197 additions & 0 deletions src/PluginPasswordModal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
import { App, Modal, Setting, TextComponent } from 'obsidian';
import { UiHelper } from 'src/services/UiHelper';
import { IPasswordAndHint } from './services/SessionPasswordService';

export default class PluginPasswordModal extends Modal {

// input
private title: string;
private defaultPassword: IPasswordAndHint | null;
//private defaultHint?: string | null = null;
private confirmPassword: boolean;
private isEncrypting: boolean;

// output
public resultConfirmed = false;
public resultPassword: IPasswordAndHint;

constructor(
app: App,
title: string,
isEncrypting:boolean,
confirmPassword: boolean,
defaultPassword: IPasswordAndHint | null,
) {
super(app);
this.title = title;
this.defaultPassword = defaultPassword;
this.confirmPassword = confirmPassword;
this.isEncrypting = isEncrypting;
}

onOpen() {
const { contentEl } = this;

contentEl.empty();

this.invalidate();

let password = this.defaultPassword?.password ?? '';
let confirmPass = '';
let hint = this.defaultPassword?.hint ?? '';

new Setting(contentEl).setHeading().setName( this.title );

/* Main password input*/

UiHelper.buildPasswordSetting({
container: contentEl,
name: 'Password:',
placeholder: this.isEncrypting ? '' : `Hint: ${hint}`,
initialValue: password,
autoFocus: password == '',
onChangeCallback: (value) => {
password = value;
this.invalidate();
},
onEnterCallback: (value) =>{
password = value;
this.invalidate();

if (password.length > 0){
if (sConfirmPassword.settingEl.isShown()){
//tcConfirmPassword.inputEl.focus();
const elInp = sConfirmPassword.components.find( (bc) => bc instanceof TextComponent );
if ( elInp instanceof TextComponent ){
elInp.inputEl.focus();
}

}else if (sHint.settingEl.isShown()){
//tcHint.inputEl.focus();
const elInp = sHint.components.find( (bc) => bc instanceof TextComponent );
if ( elInp instanceof TextComponent ){
elInp.inputEl.focus();
}
}else if( validate() ){
this.close();
}
}
}
});

/* End Main password input row */

/* Confirm password input row */
const sConfirmPassword = UiHelper.buildPasswordSetting({
container : contentEl,
name: 'Confirm Password:',
autoFocus: password != '',
onChangeCallback: (value) => {
confirmPass = value;
this.invalidate();
},
onEnterCallback: (value) =>{
confirmPass = value;
this.invalidate();
if (confirmPass.length > 0){
if ( validate() ){
if ( sHint.settingEl.isShown() ){
//tcHint.inputEl.focus();
const elInp = sHint.components.find( (bc) => bc instanceof TextComponent );
if ( elInp instanceof TextComponent ){
elInp.inputEl.focus();
}
}
}
}
}
});

if ( !this.confirmPassword ){
sConfirmPassword.settingEl.hide();
}

/* End Confirm password input row */

/* Hint input row */
const sHint = new Setting(contentEl)
.setName('Optional Password Hint')
.addText( tc=>{
//tcHint = tc;
tc.inputEl.placeholder = `Password Hint`;
tc.setValue(hint);
tc.onChange( v=> hint = v );
tc.inputEl.on('keypress', '*', (ev, target) => {
if (
ev.key == 'Enter'
&& target instanceof HTMLInputElement
&& target.value.length > 0
) {
ev.preventDefault();
if ( validate() ){
this.close();
}
}
});
})
;
if (!this.isEncrypting){
sHint.settingEl.hide();
}

/* END Hint text row */

new Setting(contentEl).addButton( cb=>{
cb
.setButtonText('Confirm')
.onClick( evt =>{
if (validate()){
this.close();
}
})
;
});

const validate = () : boolean => {
this.invalidate();

sConfirmPassword.setDesc('');

if ( this.confirmPassword ){
if (password != confirmPass){
// passwords don't match
sConfirmPassword.setDesc('Passwords don\'t match');
return false;
}
}

this.resultConfirmed = true;
this.resultPassword = { password, hint };

return true;
}

}

openAsync(): Promise<IPasswordAndHint> {
return new Promise<IPasswordAndHint>( (resolve, reject) =>{

this.onClose = () =>{
if (this.resultConfirmed == true){
resolve( this.resultPassword );
}else{
reject();
}
}

this.open();

} );
}

private invalidate(){
this.resultConfirmed = false;
this.resultPassword = { password: '', hint: '' };
}

}
Loading

0 comments on commit 764c6ea

Please sign in to comment.