From 33ebb4f335324a0fa33004d9cf5edbc7b081459e Mon Sep 17 00:00:00 2001 From: Almar Klein Date: Thu, 29 Jan 2026 11:03:33 +0100 Subject: [PATCH 1/2] Avoid premature submit when entering text through composition (e.g. Japanese) --- timetagger/app/dialogs.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/timetagger/app/dialogs.py b/timetagger/app/dialogs.py index 6a69dd8..114205b 100644 --- a/timetagger/app/dialogs.py +++ b/timetagger/app/dialogs.py @@ -1687,11 +1687,19 @@ def open(self, mode, record, callback=None): el.innerText = x self.maindiv.appendChild(el) + # Keep track of composing state (e.g. entering JCK characters) to avoid prematurely submitting on enter (#594) + self._is_composing = False + self._ds_input.addEventListener('compositionstart', lambda:self._set_compose_state(True)) + self._ds_input.addEventListener('compositionend', lambda:self._set_compose_state(False)) + # Almost done. Focus on ds if this looks like desktop; it's anoying on mobile super().open(callback) if utils.looks_like_desktop(): self._ds_input.focus() + def _set_compose_state(self, value): + self._is_composing = value + def _autocomp_finished(self): self._show_tags_from_ds() self._mark_as_edited() @@ -1854,6 +1862,8 @@ def _on_key(self, e): if self._autocompleter.on_key(e): e.stopPropagation() return + elif self._is_composing: + pass elif key == "enter" or key == "return": self.submit_soon() else: From 20d99372828ee0cb6d8a46fa85efffbbebec5504 Mon Sep 17 00:00:00 2001 From: Almar Klein Date: Thu, 29 Jan 2026 11:10:32 +0100 Subject: [PATCH 2/2] Also add compose-check for two other text fields --- timetagger/app/dialogs.py | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/timetagger/app/dialogs.py b/timetagger/app/dialogs.py index 114205b..147189e 100644 --- a/timetagger/app/dialogs.py +++ b/timetagger/app/dialogs.py @@ -1689,8 +1689,12 @@ def open(self, mode, record, callback=None): # Keep track of composing state (e.g. entering JCK characters) to avoid prematurely submitting on enter (#594) self._is_composing = False - self._ds_input.addEventListener('compositionstart', lambda:self._set_compose_state(True)) - self._ds_input.addEventListener('compositionend', lambda:self._set_compose_state(False)) + self._ds_input.addEventListener( + "compositionstart", lambda: self._set_compose_state(True) + ) + self._ds_input.addEventListener( + "compositionend", lambda: self._set_compose_state(False) + ) # Almost done. Focus on ds if this looks like desktop; it's anoying on mobile super().open(callback) @@ -2416,10 +2420,22 @@ def open(self, tags, callback=None): self._records = [] + # Keep track of composing state (e.g. entering JCK characters) + self._is_composing = False + self._tagname2.addEventListener( + "compositionstart", lambda: self._set_compose_state(True) + ) + self._tagname2.addEventListener( + "compositionend", lambda: self._set_compose_state(False) + ) + super().open(callback) if utils.looks_like_desktop(): self._tagname2.focus() + def _set_compose_state(self, value): + self._is_composing = value + def close(self): self._records = [] super().close() @@ -2438,6 +2454,8 @@ def _on_name2_done(self): def _on_key2(self, e): key = e.key.lower() + if self._is_composing: + pass if key == "enter" or key == "return": e.stopPropagation() e.preventDefault() @@ -2588,6 +2606,18 @@ def open(self): if utils.looks_like_desktop(): self._search_input.focus() + # Keep track of composing state (e.g. entering JCK characters) + self._is_composing = False + self._search_input.addEventListener( + "compositionstart", lambda: self._set_compose_state(True) + ) + self._search_input.addEventListener( + "compositionend", lambda: self._set_compose_state(False) + ) + + def _set_compose_state(self, value): + self._is_composing = value + def close(self): self._autocompleter.close() self._records = [] @@ -2664,6 +2694,8 @@ def _on_key(self, e): if self._autocompleter.on_key(e): e.stopPropagation() return + elif self._is_composing: + pass elif key == "enter" or key == "return": e.stopPropagation() e.preventDefault()