Skip to content

Commit ff19576

Browse files
committed
Fixed entry modal issues, removed redundant comments
1 parent d86e1db commit ff19576

File tree

6 files changed

+66
-57
lines changed

6 files changed

+66
-57
lines changed

manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"id": "hledger-notes",
33
"name": "Hledger Notes",
4-
"version": "1.0.3",
4+
"version": "1.0.4",
55
"minAppVersion": "1.0.0",
66
"description": "Create and manage hledger entries directly in your vault.",
77
"author": "Boburmirzo Khamrakulov",

src/handlers/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// Re-export functions from handler files
21
export * from './entry-handler';
32
export * from './export-handler';
43
export * from './import-handler';

src/settings.ts

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { App, PluginSettingTab, Setting, TFolder, SearchComponent } from 'obsidian';
22
import HledgerPlugin from './main';
33

4-
// Extend the SearchComponent interface to include the properties we need
54
interface ExtendedSearchComponent extends SearchComponent {
65
containerEl: HTMLElement;
76
inputEl: HTMLInputElement;
@@ -211,10 +210,8 @@ export class HledgerSettingTab extends PluginSettingTab {
211210
const searchEl = search.containerEl;
212211
searchEl.addClass('hledger-settings-search');
213212

214-
// Track if suggestions are currently shown
215213
let suggestionsShown = false;
216214

217-
// Function to remove suggestions
218215
const removeSuggestions = () => {
219216
const suggestionsContainer = searchEl.querySelector('.hledger-folder-suggestions');
220217
if (suggestionsContainer) {
@@ -224,71 +221,53 @@ export class HledgerSettingTab extends PluginSettingTab {
224221
}
225222
};
226223

227-
// Document click handler
228224
const documentClickHandler = (e: MouseEvent) => {
229225
if (!searchEl.contains(e.target as Node)) {
230226
removeSuggestions();
231227
}
232228
};
233229

234-
// Show suggestions
235230
const showSuggestions = () => {
236231
const currentValue = search.inputEl.value;
237232
const suggestions = folders.filter(f =>
238233
f.toLowerCase().contains(currentValue.toLowerCase()));
239234

240-
// Remove any existing suggestions container
241235
removeSuggestions();
242236

243237
if (suggestions.length === 0) {
244238
return;
245239
}
246240

247-
// Create a new suggestions container
248241
const suggestionsContainer = createDiv('hledger-folder-suggestions');
249242
searchEl.appendChild(suggestionsContainer);
250243
suggestionsShown = true;
251244

252-
// Add suggestions
253245
suggestions.forEach(suggestion => {
254246
const suggestionEl = suggestionsContainer.createDiv('hledger-suggestion-item');
255247
suggestionEl.setText(suggestion);
256248

257-
// Use mousedown instead of click to handle the event before blur
258249
suggestionEl.addEventListener('mousedown', (e: MouseEvent) => {
259-
// Prevent default to avoid losing focus
260250
e.preventDefault();
261251

262-
// Update the input value
263252
search.inputEl.value = suggestion;
264253
search.inputEl.dispatchEvent(new Event('input', { bubbles: true }));
265254

266-
// Remove suggestions
267255
removeSuggestions();
268256

269-
// Return focus to the input
270257
setTimeout(() => {
271258
search.inputEl.focus();
272259
search.inputEl.blur();
273260
}, 10);
274261
});
275262
});
276263

277-
// Add the document click handler
278264
document.addEventListener('click', documentClickHandler);
279265
};
280266

281-
// Focus handler
282-
search.inputEl.addEventListener('focus', showSuggestions);
283-
284-
// Input handler
267+
search.inputEl.addEventListener('focus', showSuggestions);
285268
search.inputEl.addEventListener('input', showSuggestions);
286-
287-
// Blur handler - delay to allow click events on suggestions
288269
search.inputEl.addEventListener('blur', (e: FocusEvent) => {
289-
// Small delay to allow click events on suggestions to fire first
290270
setTimeout(() => {
291-
// Only remove if the click wasn't on a suggestion
292271
if (suggestionsShown && !(e.relatedTarget as Element)?.closest('.hledger-folder-suggestions')) {
293272
removeSuggestions();
294273
}

src/ui/entry-modal.ts

Lines changed: 64 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { App, Modal, TFile, FuzzySuggestModal, Notice } from 'obsidian';
22
import { HledgerSettings } from '../settings';
33
import moment from 'moment';
44

5-
// Type definitions
65
interface Entry {
76
account: string;
87
amount: number;
@@ -301,15 +300,29 @@ export class HledgerEntryModal extends Modal {
301300
return;
302301
}
303302

304-
const zeroAmounts = this.entries.filter(entry => entry.amount === 0);
305-
if (zeroAmounts.length > 0) {
306-
new Notice('Amounts cannot be zero');
307-
return;
308-
}
309-
310-
if (!this.isExchange) {
303+
const emptyAmounts = this.entries.filter(entry => {
304+
const amountInput = entry.amount !== undefined ? entry.amount.toString() : '';
305+
return amountInput === '0' || amountInput === '' || amountInput.trim() === '' || isNaN(entry.amount);
306+
});
307+
308+
if (this.isExchange) {
309+
if (emptyAmounts.length > 0) {
310+
new Notice('Please fill in all amount fields');
311+
return;
312+
}
313+
314+
if (this.entries.every(entry => entry.amount === 0)) {
315+
new Notice('At least one amount must be non-zero in exchange mode');
316+
return;
317+
}
318+
} else {
319+
if (emptyAmounts.length > 0) {
320+
new Notice('Please fill in all amount fields with valid numbers');
321+
return;
322+
}
323+
311324
const totalAmount = this.entries.reduce((sum, entry) => sum + entry.amount, 0);
312-
const epsilon = 0.0001; // Small tolerance for floating point comparison
325+
const epsilon = 0.0001;
313326
if (Math.abs(totalAmount) > epsilon) {
314327
new Notice(`Transaction does not balance. Total is ${totalAmount.toFixed(2)}`);
315328
return;
@@ -322,7 +335,6 @@ export class HledgerEntryModal extends Modal {
322335

323336
private async loadAccounts() {
324337
if (!this.settings.accountsFile || !this.settings.hledgerFolder) {
325-
console.log('No accounts file or Hledger folder specified');
326338
return;
327339
}
328340

@@ -341,9 +353,6 @@ export class HledgerEntryModal extends Modal {
341353
return match ? match[1].trim() : null;
342354
})
343355
.filter((account): account is string => account !== null);
344-
345-
} else {
346-
console.log('Accounts file not found:', accountsPath);
347356
}
348357
} catch (error) {
349358
console.error('Error loading accounts file:', error);
@@ -596,23 +605,29 @@ export class HledgerEntryModal extends Modal {
596605
cls: 'text-input hledger-amount-input'
597606
});
598607

599-
amountInput.addEventListener('change', (e) => {
600-
this.handleAmountChange(e, entry, index, container);
608+
amountInput.addEventListener('input', (e) => {
609+
const target = e.target as HTMLInputElement;
610+
let value = target.value.trim();
611+
value = this.processAmountValue(value, entry, target);
601612
});
602-
}
603-
604-
private handleAmountChange(e: Event, entry: Entry, index: number, container: HTMLElement): void {
605-
const target = e.target as HTMLInputElement;
606-
let value = target.value.trim();
607-
608-
value = this.processAmountValue(value, entry, target);
609613

610-
if (index === 0 && this.entries.length === 2 && !this.isExchange) {
611-
this.updateSecondRowAmount(entry.amount, container);
612-
}
614+
amountInput.addEventListener('change', (e) => {
615+
const target = e.target as HTMLInputElement;
616+
let value = target.value.trim();
617+
value = this.processAmountValue(value, entry, target);
618+
619+
if (index === 0 && this.entries.length === 2 && !this.isExchange) {
620+
this.updateSecondRowAmount(entry.amount, container);
621+
}
622+
});
613623
}
614624

615625
private processAmountValue(value: string, entry: Entry, inputElement: HTMLInputElement): string {
626+
if (!value.trim()) {
627+
entry.amount = NaN;
628+
return '';
629+
}
630+
616631
let suffix = '';
617632
if (value.toLowerCase().endsWith('k')) {
618633
suffix = 'k';
@@ -622,20 +637,39 @@ export class HledgerEntryModal extends Modal {
622637
value = value.slice(0, -1);
623638
}
624639

640+
if (value.includes('.')) {
641+
value = value.replace(/,/g, '');
642+
}
643+
else if ((value.match(/,/g) || []).length === 1 && !value.includes('.')) {
644+
value = value.replace(',', '.');
645+
}
646+
else {
647+
value = value.replace(/,/g, '');
648+
}
649+
625650
value = value.replace(/[^\d.-]/g, '');
651+
652+
const decimalPoints = (value.match(/\./g) || []).length;
653+
if (decimalPoints > 1) {
654+
const parts = value.split('.');
655+
value = parts[0] + '.' + parts.slice(1).join('');
656+
}
657+
626658
value = value + suffix;
627659

628660
if (value.toLowerCase().endsWith('k')) {
629661
value = value.slice(0, -1);
630-
entry.amount = (parseFloat(value) || 0) * 1000;
662+
entry.amount = Math.round((parseFloat(value) || 0) * 1000);
631663
inputElement.value = entry.amount.toString();
632664
} else if (value.toLowerCase().endsWith('m')) {
633665
value = value.slice(0, -1);
634-
entry.amount = (parseFloat(value) || 0) * 1000000;
666+
entry.amount = Math.round((parseFloat(value) || 0) * 1000000);
635667
inputElement.value = entry.amount.toString();
636668
} else {
637669
entry.amount = parseFloat(value) || 0;
638-
inputElement.value = entry.amount.toString();
670+
if (value !== inputElement.value) {
671+
inputElement.value = value;
672+
}
639673
}
640674

641675
return value;
@@ -645,9 +679,9 @@ export class HledgerEntryModal extends Modal {
645679
const secondRow = this.entries[1];
646680
const secondAmountInput = container.querySelectorAll('.hledger-amount-input')[1] as HTMLInputElement;
647681

648-
if (!secondRow.amount && secondAmountInput && (secondAmountInput.value === '' || secondAmountInput.value === '0')) {
682+
if (secondAmountInput && !Number.isNaN(firstRowAmount) && (secondAmountInput.value === '' || secondAmountInput.value === '0')) {
649683
secondRow.amount = -firstRowAmount;
650-
secondAmountInput.value = secondRow.amount.toString();
684+
secondAmountInput.value = (-firstRowAmount).toString();
651685
}
652686
}
653687

src/ui/export-modal.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ export class HledgerExportModal extends Modal {
4949
this.createFileOptions(contentEl);
5050
this.createExportButton(contentEl);
5151

52-
// Add keyboard shortcut for quick export
5352
contentEl.addEventListener('keydown', (e) => {
5453
if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {
5554
e.preventDefault();
@@ -155,7 +154,6 @@ export class HledgerExportModal extends Modal {
155154
return false;
156155
}
157156

158-
// Check if file extension is valid
159157
if (!trimmedJournalFile.endsWith('.journal') &&
160158
!trimmedJournalFile.endsWith('.hledger') &&
161159
!trimmedJournalFile.endsWith('.ledger')) {

src/utils.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,6 @@ export function getParentDirectory(path: string): string {
153153
return pathWithoutTrailingSlash.substring(0, lastSlashIndex);
154154
}
155155

156-
// Format types and interfaces used across multiple handlers
157156
export type NumberFormat = 'comma-dot' | 'space-comma' | 'dot-comma';
158157

159158
export interface FormatConfig {

0 commit comments

Comments
 (0)