|
|
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
|
|
Eye, EyeOff,
|
|
|
|
|
Flag, FlagOff, FileX, Fingerprint,
|
|
|
|
|
Globe, Group,
|
|
|
|
|
History,
|
|
|
|
|
LockKeyhole, LockKeyholeOpen,
|
|
|
|
|
MessageSquareWarning, Minus,
|
|
|
|
|
NotebookPen, NotebookText, NotepadTextDashed,
|
|
|
|
|
@@ -145,6 +146,8 @@ async function update_journal_entry() {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log_lvl = 1;
|
|
|
|
|
|
|
|
|
|
let data_kv: key_val = {
|
|
|
|
|
alert: tmp_entry_obj?.alert,
|
|
|
|
|
personal: tmp_entry_obj?.personal,
|
|
|
|
|
@@ -162,25 +165,107 @@ async function update_journal_entry() {
|
|
|
|
|
category_code: tmp_entry_obj?.category_code,
|
|
|
|
|
content: tmp_entry_obj?.content,
|
|
|
|
|
content_encrypted: null, // This should only be generated below.
|
|
|
|
|
history: tmp_entry_obj?.history,
|
|
|
|
|
history_encrypted: null, // This should only be generated below.
|
|
|
|
|
|
|
|
|
|
group: tmp_entry_obj?.group,
|
|
|
|
|
archive_on: tmp_entry_obj?.archive_on,
|
|
|
|
|
name: tmp_entry_obj?.name,
|
|
|
|
|
tags: tmp_entry_obj?.tags,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (tmp_entry_obj?.content) {
|
|
|
|
|
|
|
|
|
|
let { left_over_string, cut_out_string } = handle_cut_string(tmp_entry_obj?.content);
|
|
|
|
|
if (!tmp_entry_obj?.private) {
|
|
|
|
|
// let new_content_string = '';
|
|
|
|
|
// let cut_content_string = '';
|
|
|
|
|
// {new_content_string, cut_content_string}
|
|
|
|
|
|
|
|
|
|
data_kv.content = left_over_string;
|
|
|
|
|
data_kv.history = data_kv.history + '\n\n' + cut_out_string;
|
|
|
|
|
} else if (tmp_entry_obj?.private) {
|
|
|
|
|
// Need to decrypt the current content and current history. Assume the history has not been decrypted yet.
|
|
|
|
|
|
|
|
|
|
if (log_lvl) {
|
|
|
|
|
console.log('TEST: Decrypting the history before saving it...');
|
|
|
|
|
}
|
|
|
|
|
decrypted_history = await handle_decrypt_string(tmp_entry_obj?.history_encrypted, journal_key);
|
|
|
|
|
data_kv.history = decrypted_history + '\n\n' + cut_out_string;
|
|
|
|
|
|
|
|
|
|
if (log_lvl) {
|
|
|
|
|
console.log('TEST: Encrypting the history before saving it...');
|
|
|
|
|
}
|
|
|
|
|
let encrypted_combined_data = await handle_encrypt_string(data_kv.history, journal_key);
|
|
|
|
|
data_kv.history_encrypted = encrypted_combined_data;
|
|
|
|
|
data_kv.history = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// // Check if the content contains a set of special "cut" XML tags. Anything inside the tags will be moved (appended) to the history field. Anything outside the tags should stay. The content may need to be merged back together if something was cut out of the middle. If no closing tag is found, then cut everything to the end of the content. Be sure to prefix the new history content with a timestamp header in Markdown.
|
|
|
|
|
// // Example: Hello <cut>Old</cut> World!
|
|
|
|
|
// // Example header: # Cut on 2024-11-06T12:34:56Z
|
|
|
|
|
// if (tmp_entry_obj?.content) {
|
|
|
|
|
// const cutTag = '<cut>';
|
|
|
|
|
// const cutEndTag = '</cut>';
|
|
|
|
|
// const cutIndex = tmp_entry_obj.content.indexOf(cutTag);
|
|
|
|
|
// const cutEndIndex = tmp_entry_obj.content.indexOf(cutEndTag);
|
|
|
|
|
|
|
|
|
|
// if (cutIndex !== -1) {
|
|
|
|
|
// let current_timestamp = new Date().toISOString();
|
|
|
|
|
// if (cutEndIndex !== -1) {
|
|
|
|
|
// // Cut everything between the cut tags
|
|
|
|
|
// const cutContent = tmp_entry_obj.content.substring(cutIndex + cutTag.length, cutEndIndex);
|
|
|
|
|
// data_kv.history = data_kv.history + '\n\n' + `# Cut on ${current_timestamp}\n` + cutContent;
|
|
|
|
|
// data_kv.content = tmp_entry_obj.content.replace(cutTag + cutContent + cutEndTag, '');
|
|
|
|
|
// } else {
|
|
|
|
|
// // Cut everything after the cut tag
|
|
|
|
|
// const cutContent = tmp_entry_obj.content.substring(cutIndex + cutTag.length);
|
|
|
|
|
// data_kv.history = data_kv.history + '\n\n' + `# Cut on ${current_timestamp}\n` + cutContent;
|
|
|
|
|
// data_kv.content = tmp_entry_obj.content.substring(0, cutIndex);
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// // We also need to support a Markdown variant of the cut tag: ~~cut cut~~.
|
|
|
|
|
// // Example: Hello ~~CUT: Old :CUT~~ World!
|
|
|
|
|
// // Example: Hello ~~:: Old ::~~ World!
|
|
|
|
|
// if (tmp_entry_obj?.content) {
|
|
|
|
|
// const cutTag = '~~::';
|
|
|
|
|
// const cutEndTag = '::~~';
|
|
|
|
|
// const cutIndex = tmp_entry_obj.content.indexOf(cutTag);
|
|
|
|
|
// const cutEndIndex = tmp_entry_obj.content.indexOf(cutEndTag);
|
|
|
|
|
|
|
|
|
|
// if (cutIndex !== -1) {
|
|
|
|
|
// let current_timestamp = new Date().toISOString();
|
|
|
|
|
// if (cutEndIndex !== -1) {
|
|
|
|
|
// // Cut everything between the cut tags
|
|
|
|
|
// const cutContent = tmp_entry_obj.content.substring(cutIndex + cutTag.length, cutEndIndex);
|
|
|
|
|
// data_kv.history = data_kv.history + '\n\n' + `# Cut on ${current_timestamp}\n` + cutContent;
|
|
|
|
|
// data_kv.content = tmp_entry_obj.content.replace(cutTag + cutContent + cutEndTag, '');
|
|
|
|
|
// } else {
|
|
|
|
|
// // Cut everything after the cut tag
|
|
|
|
|
// const cutContent = tmp_entry_obj.content.substring(cutIndex + cutTag.length);
|
|
|
|
|
// data_kv.history = data_kv.history + '\n\n' + `# Cut on ${current_timestamp}\n` + cutContent;
|
|
|
|
|
// data_kv.content = tmp_entry_obj.content.substring(0, cutIndex);
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
if (tmp_entry_obj?.content && tmp_entry_obj?.private) {
|
|
|
|
|
// console.log('TEST: Saving encrypted content', tmp_entry_obj?.content);
|
|
|
|
|
content = tmp_entry_obj?.content;
|
|
|
|
|
// console.log('TEST: journal_key', journal_key);
|
|
|
|
|
|
|
|
|
|
// Encrypt the content
|
|
|
|
|
let encrypted_base64 = await ae_util.encrypt_content(content, journal_key);
|
|
|
|
|
encrypted_base64_content = encrypted_base64.base64;
|
|
|
|
|
encryption_iv = encrypted_base64.iv;
|
|
|
|
|
console.log(`IV: ${encryption_iv}; Encrypted: ${encrypted_base64_content}`);
|
|
|
|
|
// // Encrypt the content
|
|
|
|
|
// let encrypted_base64 = await ae_util.encrypt_content(content, journal_key);
|
|
|
|
|
// encrypted_base64_content = encrypted_base64.base64;
|
|
|
|
|
// encryption_iv = encrypted_base64.iv;
|
|
|
|
|
// console.log(`IV: ${encryption_iv}; Encrypted: ${encrypted_base64_content}`);
|
|
|
|
|
|
|
|
|
|
// Combine the IV and encrypted content
|
|
|
|
|
const combined_data = Array.from(encryption_iv).map(byte => byte.toString(16).padStart(2, '0')).join('') + ':' + encrypted_base64_content;
|
|
|
|
|
// // Combine the IV and encrypted content
|
|
|
|
|
// const combined_data = Array.from(encryption_iv).map(byte => byte.toString(16).padStart(2, '0')).join('') + ':' + encrypted_base64_content;
|
|
|
|
|
|
|
|
|
|
let combined_data = await handle_encrypt_string(content, journal_key);
|
|
|
|
|
|
|
|
|
|
data_kv.content_encrypted = combined_data;
|
|
|
|
|
data_kv.content = null;
|
|
|
|
|
@@ -193,7 +278,7 @@ async function update_journal_entry() {
|
|
|
|
|
decrypted_content = '';
|
|
|
|
|
} else if (tmp_entry_obj?.content_encrypted && !tmp_entry_obj?.private) {
|
|
|
|
|
console.log('TEST: Decrypting the content before saving it...');
|
|
|
|
|
await handle_decrypt_content();
|
|
|
|
|
decrypted_content = await handle_decrypt_string(tmp_entry_obj?.content_encrypted, journal_key);
|
|
|
|
|
data_kv.content = decrypted_content; // tmp_entry_obj.content
|
|
|
|
|
decrypted_content = '';
|
|
|
|
|
// return false;
|
|
|
|
|
@@ -298,6 +383,7 @@ let encrypted_base64_content: string = $state('');
|
|
|
|
|
let encryption_iv: null|Uint8Array<ArrayBuffer> = $state(null);
|
|
|
|
|
let decrypted_content: string = $state('');
|
|
|
|
|
let trigger_decrypt: boolean = $state(false);
|
|
|
|
|
let decrypted_history: string = $state('');
|
|
|
|
|
|
|
|
|
|
$effect(() => {
|
|
|
|
|
if ($lq__journal_obj?.passcode) {
|
|
|
|
|
@@ -306,76 +392,194 @@ $effect(() => {
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$effect(async () => {
|
|
|
|
|
if (tmp_entry_obj?.content_encrypted && trigger_decrypt) {
|
|
|
|
|
trigger_decrypt = false;
|
|
|
|
|
// $effect(async () => {
|
|
|
|
|
// if (tmp_entry_obj?.content_encrypted && trigger_decrypt) {
|
|
|
|
|
// trigger_decrypt = false;
|
|
|
|
|
|
|
|
|
|
handle_decrypt_content();
|
|
|
|
|
// handle_decrypt_content();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// if (tmp_entry_obj?.content) {
|
|
|
|
|
// content = tmp_entry_obj?.content;
|
|
|
|
|
// // if (tmp_entry_obj?.content) {
|
|
|
|
|
// // content = tmp_entry_obj?.content;
|
|
|
|
|
|
|
|
|
|
// let encrypted_base64 = await ae_util.encrypt_content(content, journal_key);
|
|
|
|
|
// encrypted_base64_content = encrypted_base64.base64;
|
|
|
|
|
// encryption_iv = encrypted_base64.iv;
|
|
|
|
|
// // let encrypted_base64 = await ae_util.encrypt_content(content, journal_key);
|
|
|
|
|
// // encrypted_base64_content = encrypted_base64.base64;
|
|
|
|
|
// // encryption_iv = encrypted_base64.iv;
|
|
|
|
|
|
|
|
|
|
// let decrypted = await ae_util.decrypt_content(encrypted_base64_content, encryption_iv, journal_key);
|
|
|
|
|
// decrypted_content = decrypted;
|
|
|
|
|
// if (log_lvl) {
|
|
|
|
|
// console.log('Decrypted content:', decrypted_content);
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// console.log('Encrypted content:', base64);
|
|
|
|
|
// console.log('IV:', iv);
|
|
|
|
|
});
|
|
|
|
|
// // let decrypted = await ae_util.decrypt_content(encrypted_base64_content, encryption_iv, journal_key);
|
|
|
|
|
// // decrypted_content = decrypted;
|
|
|
|
|
// // if (log_lvl) {
|
|
|
|
|
// // console.log('Decrypted content:', decrypted_content);
|
|
|
|
|
// // }
|
|
|
|
|
// // }
|
|
|
|
|
// // console.log('Encrypted content:', base64);
|
|
|
|
|
// // console.log('IV:', iv);
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
async function handle_decrypt_content() {
|
|
|
|
|
// async function handle_decrypt_content() {
|
|
|
|
|
// log_lvl = 1;
|
|
|
|
|
// if (log_lvl) {
|
|
|
|
|
// console.log('TEST: handle_decrypt_content');
|
|
|
|
|
// }
|
|
|
|
|
// let combined_data = tmp_entry_obj?.content_encrypted;
|
|
|
|
|
// let [encryption_iv_hex, encrypted_base64_content] = combined_data.split(':');
|
|
|
|
|
// encryption_iv = new Uint8Array(encryption_iv_hex.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));
|
|
|
|
|
// if (log_lvl) {
|
|
|
|
|
// console.log(`IV: ${encryption_iv}; Encrypted: ${encrypted_base64_content}`);
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// let decrypted: string|null = null;
|
|
|
|
|
// try {
|
|
|
|
|
// decrypted = await ae_util.decrypt_content(encrypted_base64_content, encryption_iv, journal_key);
|
|
|
|
|
// } catch (error) {
|
|
|
|
|
// console.error('Error decrypting content:', error);
|
|
|
|
|
// alert('Failed to decrypt content. Please check the passcode.');
|
|
|
|
|
// return;
|
|
|
|
|
// }
|
|
|
|
|
// // let decrypted = await ae_util.decrypt_content(encrypted_base64_content, encryption_iv, journal_key);
|
|
|
|
|
// // decrypted_content = 'XXX '+decrypted+' XXX';
|
|
|
|
|
|
|
|
|
|
// if (!decrypted) {
|
|
|
|
|
// alert('Failed to decrypt content. Please check the passcode.');
|
|
|
|
|
// return;
|
|
|
|
|
// }
|
|
|
|
|
// decrypted_content = decrypted;
|
|
|
|
|
// if (log_lvl) {
|
|
|
|
|
// console.log('Decrypted content:', decrypted_content);
|
|
|
|
|
// }
|
|
|
|
|
// tmp_entry_obj.content = decrypted_content;
|
|
|
|
|
// // orig_entry_obj.content = decrypted_content;
|
|
|
|
|
// // tmp_entry_obj_changed = false;
|
|
|
|
|
|
|
|
|
|
// // tmp_entry_obj.content_encrypted = null;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
async function handle_decrypt_string(encrypted_string: string, passcode: string) {
|
|
|
|
|
log_lvl = 1;
|
|
|
|
|
if (log_lvl) {
|
|
|
|
|
console.log('TEST: handle_decrypt_content');
|
|
|
|
|
console.log(`TEST: handle_decrypt_string: ${passcode}`, encrypted_string);
|
|
|
|
|
}
|
|
|
|
|
let combined_data = tmp_entry_obj?.content_encrypted;
|
|
|
|
|
if (!encrypted_string) {
|
|
|
|
|
console.log('TEST: No encrypted string provided');
|
|
|
|
|
return '';
|
|
|
|
|
}
|
|
|
|
|
if (!passcode) {
|
|
|
|
|
console.log('TEST: No journal key provided');
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let combined_data = encrypted_string;
|
|
|
|
|
let [encryption_iv_hex, encrypted_base64_content] = combined_data.split(':');
|
|
|
|
|
encryption_iv = new Uint8Array(encryption_iv_hex.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));
|
|
|
|
|
if (log_lvl) {
|
|
|
|
|
console.log(`IV: ${encryption_iv}; Encrypted: ${encrypted_base64_content}`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let decrypted: string|null = null;
|
|
|
|
|
// Decrypt the string using the journal key
|
|
|
|
|
let decrypted_string = '';
|
|
|
|
|
try {
|
|
|
|
|
decrypted = await ae_util.decrypt_content(encrypted_base64_content, encryption_iv, journal_key);
|
|
|
|
|
decrypted_string = await ae_util.decrypt_content(encrypted_base64_content, encryption_iv, passcode);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Error decrypting content:', error);
|
|
|
|
|
alert('Failed to decrypt content. Please check the passcode.');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// let decrypted = await ae_util.decrypt_content(encrypted_base64_content, encryption_iv, journal_key);
|
|
|
|
|
// decrypted_content = 'XXX '+decrypted+' XXX';
|
|
|
|
|
|
|
|
|
|
if (!decrypted) {
|
|
|
|
|
alert('Failed to decrypt content. Please check the passcode.');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
decrypted_content = decrypted;
|
|
|
|
|
if (log_lvl) {
|
|
|
|
|
console.log('Decrypted content:', decrypted_content);
|
|
|
|
|
}
|
|
|
|
|
tmp_entry_obj.content = decrypted_content;
|
|
|
|
|
// orig_entry_obj.content = decrypted_content;
|
|
|
|
|
// tmp_entry_obj_changed = false;
|
|
|
|
|
|
|
|
|
|
// tmp_entry_obj.content_encrypted = null;
|
|
|
|
|
return decrypted_string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function handle_encrypt_string(text_string: string, passcode: string) {
|
|
|
|
|
log_lvl = 1;
|
|
|
|
|
if (log_lvl) {
|
|
|
|
|
console.log('TEST: handle_encrypt_string');
|
|
|
|
|
}
|
|
|
|
|
if (!text_string) {
|
|
|
|
|
console.log('TEST: No text string provided');
|
|
|
|
|
return '';
|
|
|
|
|
}
|
|
|
|
|
if (!passcode) {
|
|
|
|
|
console.log('TEST: No journal key provided');
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Encrypt the string using the journal key
|
|
|
|
|
let encrypted_base64 = await ae_util.encrypt_content(text_string, passcode);
|
|
|
|
|
let encrypted_base64_content = encrypted_base64.base64;
|
|
|
|
|
let encryption_iv = encrypted_base64.iv;
|
|
|
|
|
console.log(`IV: ${encryption_iv}; Encrypted: ${encrypted_base64_content}`);
|
|
|
|
|
|
|
|
|
|
// Combine the IV and encrypted content
|
|
|
|
|
const combined_data = Array.from(encryption_iv).map(byte => byte.toString(16).padStart(2, '0')).join('') + ':' + encrypted_base64_content;
|
|
|
|
|
|
|
|
|
|
return combined_data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// return new_string and cut_string
|
|
|
|
|
function handle_cut_string(old_string: string) {
|
|
|
|
|
// Check if the string contains a set of special "cut" XML tags or Markdown. Anything inside the tags or Markdown will be moved (appended) to the history field. Anything outside the tags should stay. The string may need to be merged back together if something was cut out of the middle. If no closing tag is found, then cut everything to the end of the string. Be sure to prefix the new history sting with a timestamp header in Markdown.
|
|
|
|
|
// Example: Hello <cut>Old</cut> World!
|
|
|
|
|
// Example header: # Cut on 2024-11-06T12:34:56Z
|
|
|
|
|
// We also need to support a Markdown variant of the cut tag: ~~cut cut~~.
|
|
|
|
|
// Example: Hello ~~CUT: Old :CUT~~ World!
|
|
|
|
|
// Example: Hello ~~:: Old ::~~ World!
|
|
|
|
|
|
|
|
|
|
let left_over_string = old_string; // Will be for the updated content field
|
|
|
|
|
let cut_out_string = ''; // Will be for the history field
|
|
|
|
|
|
|
|
|
|
if (old_string) {
|
|
|
|
|
let cut_tag = '<cut>';
|
|
|
|
|
let cut_end_tag = '</cut>';
|
|
|
|
|
let cut_index = old_string.indexOf(cut_tag);
|
|
|
|
|
let cut_end_index = old_string.indexOf(cut_end_tag);
|
|
|
|
|
let cut_prefix = `# Cut on ${new Date().toISOString()}\n`;
|
|
|
|
|
|
|
|
|
|
if (cut_index !== -1) {
|
|
|
|
|
if (cut_end_index !== -1) {
|
|
|
|
|
// Cut everything between the cut tags
|
|
|
|
|
const cut_content = old_string.substring(cut_index + cut_tag.length, cut_end_index);
|
|
|
|
|
cut_out_string = cut_prefix + cut_content;
|
|
|
|
|
left_over_string = old_string.replace(cut_tag + cut_content + cut_end_tag, '');
|
|
|
|
|
} else {
|
|
|
|
|
// Cut everything after the cut tag
|
|
|
|
|
const cut_content = old_string.substring(cut_index + cut_tag.length);
|
|
|
|
|
cut_out_string = cut_prefix + cut_content;
|
|
|
|
|
left_over_string = old_string.substring(0, cut_index);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cut_tag = '~~::';
|
|
|
|
|
cut_end_tag = '::~~';
|
|
|
|
|
cut_index = old_string.indexOf(cut_tag);
|
|
|
|
|
cut_end_index = old_string.indexOf(cut_end_tag);
|
|
|
|
|
cut_prefix = `# Cut on ${new Date().toISOString()}\n`;
|
|
|
|
|
if (cut_index !== -1) {
|
|
|
|
|
if (cut_end_index !== -1) {
|
|
|
|
|
// Cut everything between the cut tags
|
|
|
|
|
const cut_content = old_string.substring(cut_index + cut_tag.length, cut_end_index);
|
|
|
|
|
cut_out_string = cut_prefix + cut_content;
|
|
|
|
|
left_over_string = old_string.replace(cut_tag + cut_content + cut_end_tag, '');
|
|
|
|
|
} else {
|
|
|
|
|
// Cut everything after the cut tag
|
|
|
|
|
const cut_content = old_string.substring(cut_index + cut_tag.length);
|
|
|
|
|
cut_out_string = cut_prefix + cut_content;
|
|
|
|
|
left_over_string = old_string.substring(0, cut_index);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
return { left_over_string, cut_out_string };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<section class="svelte_component ae_section ae_view journal_entry_obj view__journal_entry_obj bg-white flex flex-col flex-grow items-center justify-center rounded-lg w-full h-full p-2 m-2 space-y-2" bind:clientHeight={$ae_loc.iframe_height_modal_body}>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{#if $lq__journal_entry_obj}
|
|
|
|
|
|
|
|
|
|
<header class="ae_header journal_entry__header flex flex-row flex-wrap gap-2 items-center justify-between w-full">
|
|
|
|
|
|
|
|
|
|
<div class="flex flex-row flex-wrap gap-2 items-center justify-start">
|
|
|
|
|
@@ -421,7 +625,7 @@ async function handle_decrypt_content() {
|
|
|
|
|
<input
|
|
|
|
|
type="text"
|
|
|
|
|
bind:value={tmp_entry_obj.name}
|
|
|
|
|
class="input input-bordered"
|
|
|
|
|
class="input input-bordered w-96"
|
|
|
|
|
placeholder="Journal Entry Name"
|
|
|
|
|
title="Edit the name of this journal entry"
|
|
|
|
|
/>
|
|
|
|
|
@@ -670,7 +874,8 @@ async function handle_decrypt_content() {
|
|
|
|
|
|
|
|
|
|
</header>
|
|
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
|
|
|
|
|
<section
|
|
|
|
|
class="flex flex-row flex-wrap gap-1 items-center justify-evenly w-full max-w-sm "
|
|
|
|
|
>
|
|
|
|
|
<!-- Entry alert status -->
|
|
|
|
|
@@ -762,7 +967,8 @@ async function handle_decrypt_content() {
|
|
|
|
|
// tmp_entry_obj.content = null;
|
|
|
|
|
} else if (tmp_entry_obj?.private && tmp_entry_obj?.content_encrypted) {
|
|
|
|
|
if (confirm('Are you sure you want to decrypt the content to view/edit?')) {
|
|
|
|
|
trigger_decrypt = true;
|
|
|
|
|
// trigger_decrypt = true;
|
|
|
|
|
handle_decrypt_content();
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
@@ -885,38 +1091,41 @@ async function handle_decrypt_content() {
|
|
|
|
|
{/if}
|
|
|
|
|
</button> -->
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{#if (!$journals_loc.entry.edit_kv[$lq__journal_entry_obj?.journal_entry_id])}
|
|
|
|
|
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
|
|
|
|
|
<div
|
|
|
|
|
ondblclick={() => {
|
|
|
|
|
<!-- ondblclick={() => {
|
|
|
|
|
if ($ae_loc.trusted_access && $ae_loc.edit_mode) {
|
|
|
|
|
// Toggle edit mode
|
|
|
|
|
$journals_loc.entry.edit = !$journals_loc.entry.edit;
|
|
|
|
|
$journals_loc.entry.edit_kv[$lq__journal_entry_obj?.journal_entry_id] = $journals_loc.entry.edit;
|
|
|
|
|
}
|
|
|
|
|
}}
|
|
|
|
|
role={$ae_loc.edit_mode ? 'button' : 'article'}
|
|
|
|
|
tabindex={$ae_loc.edit_mode ? 0 : -1}
|
|
|
|
|
|
|
|
|
|
}}
|
|
|
|
|
role={$ae_loc.edit_mode ? 'button' : 'article'}
|
|
|
|
|
tabindex={$ae_loc.edit_mode ? 0 : -1} -->
|
|
|
|
|
<section
|
|
|
|
|
class="
|
|
|
|
|
flex-grow
|
|
|
|
|
flex flex-col items-center justify-center
|
|
|
|
|
basis-full
|
|
|
|
|
flex flex-col flex-wrap items-center justify-center
|
|
|
|
|
h-full min-h-max max-h-full
|
|
|
|
|
w-full max-w-6xl
|
|
|
|
|
"
|
|
|
|
|
|
|
|
|
|
>
|
|
|
|
|
{#if (!$journals_loc.entry.edit_kv[$lq__journal_entry_obj?.journal_entry_id])}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<article
|
|
|
|
|
class:border-orange-200={$ae_loc.edit_mode}
|
|
|
|
|
class:hover:border-orange-500={$ae_loc.edit_mode}
|
|
|
|
|
class="
|
|
|
|
|
space-y-1
|
|
|
|
|
prose
|
|
|
|
|
flex-grow
|
|
|
|
|
h-full min-h-48 w-full min-w-full max-w-6xl
|
|
|
|
|
basis-full
|
|
|
|
|
h-full min-h-max max-h-full
|
|
|
|
|
w-full min-w-full max-w-6xl
|
|
|
|
|
p-2
|
|
|
|
|
space-y-1
|
|
|
|
|
font-mono
|
|
|
|
|
!bg-slate-100 !text-gray-900
|
|
|
|
|
dark:!bg-slate-900 dark:!text-gray-100
|
|
|
|
|
@@ -924,6 +1133,7 @@ async function handle_decrypt_content() {
|
|
|
|
|
shadow-md rounded-lg
|
|
|
|
|
border border-gray-200 dark:border-gray-700
|
|
|
|
|
hover:border-gray-500 dark:hover:border-gray-500
|
|
|
|
|
prose
|
|
|
|
|
prose-h1:underline prose-h1:decoration-double
|
|
|
|
|
prose-h2:underline
|
|
|
|
|
prose-h1:text-2xl prose-h2:text-xl prose-h3:text-lg
|
|
|
|
|
@@ -954,15 +1164,19 @@ async function handle_decrypt_content() {
|
|
|
|
|
<!-- {@html encrypt_content($lq__journal_entry_obj?.content, journal_key)} -->
|
|
|
|
|
<!-- --{@html encrypted_base64_content}-- -->
|
|
|
|
|
<!-- {@html marked.parse($lq__journal_entry_obj?.content)} -->
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{:else if ($journals_loc.entry.edit_kv[$lq__journal_entry_obj?.journal_entry_id])}
|
|
|
|
|
<!-- && !($lq__journal_entry_obj?.content_encrypted && decrypted_content)) -->
|
|
|
|
|
<!-- class="flex flex-row flex-wrap gap-1 items-center justify-center w-full max-w-sm" -->
|
|
|
|
|
{#if ($lq__journal_entry_obj?.content_encrypted && !decrypted_content)}
|
|
|
|
|
<div
|
|
|
|
|
class="
|
|
|
|
|
flex-grow min-h-48 h-full w-full
|
|
|
|
|
flex-grow
|
|
|
|
|
basis-full
|
|
|
|
|
h-full min-h-max max-h-full
|
|
|
|
|
w-full min-w-full max-w-6xl
|
|
|
|
|
p-2
|
|
|
|
|
space-y-1
|
|
|
|
|
bg-red-100 text-gray-900
|
|
|
|
|
dark:bg-red-900 dark:text-gray-100
|
|
|
|
|
shadow-lg rounded-lg
|
|
|
|
|
@@ -991,31 +1205,33 @@ async function handle_decrypt_content() {
|
|
|
|
|
</button> -->
|
|
|
|
|
</div>
|
|
|
|
|
{:else}
|
|
|
|
|
<div
|
|
|
|
|
|
|
|
|
|
<!-- <div
|
|
|
|
|
class="
|
|
|
|
|
flex-grow
|
|
|
|
|
flex flex-col items-center justify-center
|
|
|
|
|
w-full max-w-6xl
|
|
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
|
|
|
|
|
h-full max-h-full
|
|
|
|
|
w-full min-w-full max-w-6xl"
|
|
|
|
|
> -->
|
|
|
|
|
<textarea
|
|
|
|
|
bind:value={tmp_entry_obj.content}
|
|
|
|
|
ondblclick={() => {
|
|
|
|
|
if ($ae_loc.trusted_access && $ae_loc.edit_mode) {
|
|
|
|
|
// Toggle edit mode
|
|
|
|
|
$journals_loc.entry.edit = !$journals_loc.entry.edit;
|
|
|
|
|
$journals_loc.entry.edit_kv[$lq__journal_entry_obj?.journal_entry_id] = $journals_loc.entry.edit;
|
|
|
|
|
}
|
|
|
|
|
// if ($ae_loc.trusted_access && $ae_loc.edit_mode) {
|
|
|
|
|
// // Toggle edit mode
|
|
|
|
|
// $journals_loc.entry.edit = !$journals_loc.entry.edit;
|
|
|
|
|
// $journals_loc.entry.edit_kv[$lq__journal_entry_obj?.journal_entry_id] = $journals_loc.entry.edit;
|
|
|
|
|
// }
|
|
|
|
|
}}
|
|
|
|
|
disabled={tmp_entry_obj.content_encrypted && !decrypted_content}
|
|
|
|
|
class:border-orange-200={$ae_loc.edit_mode}
|
|
|
|
|
class:hover:border-orange-500={$ae_loc.edit_mode}
|
|
|
|
|
class="
|
|
|
|
|
space-y-1
|
|
|
|
|
flex-grow
|
|
|
|
|
h-full min-h-max max-h-full w-full min-w-full max-w-6xl
|
|
|
|
|
flex-shrink-0
|
|
|
|
|
basis-full
|
|
|
|
|
h-max min-h-max max-h-full
|
|
|
|
|
w-full min-w-full max-w-6xl
|
|
|
|
|
p-2
|
|
|
|
|
space-y-1
|
|
|
|
|
font-mono
|
|
|
|
|
bg-slate-100 text-gray-900
|
|
|
|
|
dark:bg-slate-900 dark:text-gray-100
|
|
|
|
|
@@ -1055,16 +1271,149 @@ async function handle_decrypt_content() {
|
|
|
|
|
Updated obj? {updated_obj} -->
|
|
|
|
|
|
|
|
|
|
<!-- && $lq__journal_entry_obj?.updated_on !== orig_entry_obj?.updated_on -->
|
|
|
|
|
<!-- </div> -->
|
|
|
|
|
|
|
|
|
|
{/if}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{/if}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- If there is history, then we want a toggle button to show and hide the history. -->
|
|
|
|
|
{#if ($lq__journal_entry_obj?.history || $lq__journal_entry_obj?.history_encrypted)}
|
|
|
|
|
<div
|
|
|
|
|
class="
|
|
|
|
|
flex flex-col flex-wrap gap-1 items-center justify-center h-full w-full
|
|
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
<div>
|
|
|
|
|
<button
|
|
|
|
|
type="button"
|
|
|
|
|
onclick={async () => {
|
|
|
|
|
if ($journals_sess.show__content__journal_entry_history == 'view') {
|
|
|
|
|
$journals_sess.show__content__journal_entry_history = 'hide';
|
|
|
|
|
} else if ($journals_sess.show__content__journal_entry_history == 'edit') {
|
|
|
|
|
$journals_sess.show__content__journal_entry_history = 'hide';
|
|
|
|
|
} else if ($journals_sess.show__content__journal_entry_history == 'hide') {
|
|
|
|
|
$journals_sess.show__content__journal_entry_history = 'view';
|
|
|
|
|
} else if (!$journals_sess.show__content__journal_entry_history) {
|
|
|
|
|
$journals_sess.show__content__journal_entry_history = 'view';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!tmp_entry_obj?.history && tmp_entry_obj?.history_encrypted) {
|
|
|
|
|
decrypted_history = await handle_decrypt_string(tmp_entry_obj.history_encrypted, journal_key);
|
|
|
|
|
console.log('Decrypted history:', decrypted_history);
|
|
|
|
|
tmp_entry_obj.history = decrypted_history;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}}
|
|
|
|
|
class="btn btn-sm variant-soft-secondary hover:variant-filled-secondary *:hover:inline lg:text-xs"
|
|
|
|
|
title="Toggle history of this journal entry"
|
|
|
|
|
>
|
|
|
|
|
<History strokeWidth="2.5" color="blue" />
|
|
|
|
|
<span class="hidden sm:inline">History</span>
|
|
|
|
|
</button>
|
|
|
|
|
|
|
|
|
|
<button
|
|
|
|
|
type="button"
|
|
|
|
|
class:hidden={!$journals_sess.show__content__journal_entry_history}
|
|
|
|
|
onclick={() => {
|
|
|
|
|
if ($journals_sess.show__content__journal_entry_history == 'view') {
|
|
|
|
|
$journals_sess.show__content__journal_entry_history = 'edit';
|
|
|
|
|
} else if ($journals_sess.show__content__journal_entry_history == 'edit') {
|
|
|
|
|
$journals_sess.show__content__journal_entry_history = 'view';
|
|
|
|
|
}
|
|
|
|
|
}}
|
|
|
|
|
class="btn btn-sm variant-soft-secondary hover:variant-filled-secondary *:hover:inline lg:text-xs"
|
|
|
|
|
title="Toggle edit mode for history of this journal entry"
|
|
|
|
|
>
|
|
|
|
|
{#if $journals_sess.show__content__journal_entry_history == 'view'}
|
|
|
|
|
<PenLine strokeWidth="2.5" color="blue" class="inline-block" />
|
|
|
|
|
{:else if $journals_sess.show__content__journal_entry_history == 'edit'}
|
|
|
|
|
<Pencil strokeWidth="2.5" color="blue" class="inline-block" />
|
|
|
|
|
{/if}
|
|
|
|
|
<span class="hidden sm:inline">
|
|
|
|
|
{#if $journals_sess.show__content__journal_entry_history == 'view'}
|
|
|
|
|
Edit
|
|
|
|
|
{:else if $journals_sess.show__content__journal_entry_history == 'edit'}
|
|
|
|
|
View
|
|
|
|
|
{/if}
|
|
|
|
|
</span>
|
|
|
|
|
</button>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
class="
|
|
|
|
|
flex-grow
|
|
|
|
|
basis-full
|
|
|
|
|
flex flex-col items-center justify-center
|
|
|
|
|
h-full
|
|
|
|
|
w-full max-w-6xl
|
|
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
{#if $journals_sess?.show__content__journal_entry_history == 'view'}
|
|
|
|
|
<article
|
|
|
|
|
class:border-orange-200={$ae_loc.edit_mode}
|
|
|
|
|
class:hover:border-orange-500={$ae_loc.edit_mode}
|
|
|
|
|
class="
|
|
|
|
|
space-y-1
|
|
|
|
|
h-full min-h-max max-h-full
|
|
|
|
|
w-full min-w-full max-w-6xl
|
|
|
|
|
p-2
|
|
|
|
|
font-mono
|
|
|
|
|
!bg-slate-100 !text-gray-900
|
|
|
|
|
dark:!bg-slate-900 dark:!text-gray-100
|
|
|
|
|
dark:prose-invert
|
|
|
|
|
shadow-md rounded-lg
|
|
|
|
|
border border-gray-200 dark:border-gray-700
|
|
|
|
|
hover:border-gray-500 dark:hover:border-gray-500
|
|
|
|
|
prose
|
|
|
|
|
prose-h1:underline prose-h1:decoration-double
|
|
|
|
|
prose-h2:underline
|
|
|
|
|
prose-h1:text-2xl prose-h2:text-xl prose-h3:text-lg
|
|
|
|
|
prose-h1:m-0 prose-h2:m-0 prose-h3:m-0 prose-h4:m-0 prose-h5:m-0 prose-h6:m-0
|
|
|
|
|
prose-li:m-0 prose-li:p-0 prose-li:line-height-none
|
|
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
{@html $lq__journal_entry_obj?.history_md_html}
|
|
|
|
|
</article>
|
|
|
|
|
{:else if $journals_sess?.show__content__journal_entry_history == 'edit'}
|
|
|
|
|
<textarea
|
|
|
|
|
bind:value={tmp_entry_obj.history}
|
|
|
|
|
class:border-orange-200={$ae_loc.edit_mode}
|
|
|
|
|
class:hover:border-orange-500={$ae_loc.edit_mode}
|
|
|
|
|
class="
|
|
|
|
|
space-y-1
|
|
|
|
|
flex-grow
|
|
|
|
|
basis-full
|
|
|
|
|
h-full min-h-max max-h-full
|
|
|
|
|
w-full min-w-full max-w-6xl
|
|
|
|
|
p-2
|
|
|
|
|
font-mono
|
|
|
|
|
bg-slate-100 text-gray-900
|
|
|
|
|
dark:bg-slate-900 dark:text-gray-100
|
|
|
|
|
shadow-lg rounded-lg
|
|
|
|
|
border border-gray-200 dark:border-gray-700
|
|
|
|
|
hover:border-gray-500 dark:hover:border-gray-500
|
|
|
|
|
"
|
|
|
|
|
placeholder="Edit journal entry content here..."
|
|
|
|
|
></textarea>
|
|
|
|
|
{/if}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
{/if}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
<!-- <div>
|
|
|
|
|
{@html test_html}
|
|
|
|
|
</div> -->
|
|
|
|
|
|
|
|
|
|
<div class="ae_meta flex flex-row flex-wrap gap-1 items-center justify-between w-full">
|
|
|
|
|
<section class="ae_meta flex flex-row flex-wrap gap-1 items-center justify-between w-full">
|
|
|
|
|
<!-- {$lq__journal_entry_obj?.priority}
|
|
|
|
|
{$lq__journal_entry_obj?.sort}
|
|
|
|
|
{$lq__journal_entry_obj?.group}
|
|
|
|
|
@@ -1333,7 +1682,7 @@ async function handle_decrypt_content() {
|
|
|
|
|
{/if}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
{/if}
|
|
|
|
|
|
|
|
|
|
|