dsh-local-board 1.5.3 → 1.5.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/client.js CHANGED
@@ -24,6 +24,13 @@ window.__ModuleLoader__.load({
24
24
  configureVault: '选择文件夹'
25
25
  };
26
26
  const PROJECT_STATUS = ['进行中', '暂停', '已结束'];
27
+ /**
28
+ * True while an IME is composing (Chinese/Japanese/Korean input). Enter and Escape
29
+ * then belong to the IME — confirming a candidate must never submit the form.
30
+ */
31
+ const composing = (event) => (event.nativeEvent && event.nativeEvent.isComposing === true)
32
+ || event.isComposing === true
33
+ || event.keyCode === 229;
27
34
  /** Card color stripe; keys match what the markdown stores. */
28
35
  const CARD_COLORS = [
29
36
  { key: 'red', hex: '#e5484d', label: '红' },
@@ -211,6 +218,7 @@ window.__ModuleLoader__.load({
211
218
  placeholder,
212
219
  onChange: (event) => setDraft({ ...draft, [key]: event.target.value }),
213
220
  onKeyDown: (event) => {
221
+ if (composing(event)) return;
214
222
  if (event.key === 'Escape') onCancel();
215
223
  if (event.key === 'Enter') onSubmit(draft);
216
224
  }
@@ -515,6 +523,7 @@ window.__ModuleLoader__.load({
515
523
  value: name,
516
524
  onChange: (event) => setName(event.target.value),
517
525
  onKeyDown: (event) => {
526
+ if (composing(event)) return;
518
527
  if (event.key === 'Enter' && name.trim() !== '') onCreate({ name: name.trim(), role });
519
528
  if (event.key === 'Escape') onCancel();
520
529
  }
@@ -548,6 +557,7 @@ window.__ModuleLoader__.load({
548
557
  if (next !== '' && next !== project.name) commit({ name: next });
549
558
  },
550
559
  onKeyDown: (event) => {
560
+ if (composing(event)) return;
551
561
  if (event.key === 'Enter') event.target.blur();
552
562
  }
553
563
  })),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-local-board",
3
- "version": "1.5.3",
3
+ "version": "1.5.6",
4
4
  "description": "本地待办看板:Todo/Doing/Done 三列,按项目组织。首次使用自己选一个文件夹,数据就是一个 Markdown 文件,随你放哪、随你备份。macOS 支持到期提醒。",
5
5
  "type": "module",
6
6
  "main": "index.js",
package/scripts/digest.py CHANGED
@@ -84,9 +84,27 @@ def build(rows, today):
84
84
  body = body[:197] + '…'
85
85
  return body
86
86
 
87
- def notify(body):
88
- script = 'display notification "' + body.replace('"', '\\"') + '" with title "' + TITLE + '" sound name "Glass"'
89
- subprocess.run(['/usr/bin/osascript', '-e', script], check=False)
87
+ APPLESCRIPT = (
88
+ 'on run argv\n'
89
+ ' display notification (item 2 of argv) with title (item 1 of argv) subtitle "DSH 看板" sound name "Glass"\n'
90
+ 'end run'
91
+ )
92
+
93
+
94
+ def notify(title, body):
95
+ """Notification text is user data: pass it as argv so AppleScript never parses it."""
96
+ try:
97
+ result = subprocess.run(
98
+ ['/usr/bin/osascript', '-e', APPLESCRIPT, str(title), str(body)],
99
+ capture_output=True, text=True, timeout=20
100
+ )
101
+ if result.returncode != 0:
102
+ print('notify failed:', (result.stderr or '').strip() or 'osascript exit ' + str(result.returncode), file=sys.stderr)
103
+ return False
104
+ return True
105
+ except (OSError, subprocess.SubprocessError) as error:
106
+ print('notify failed:', error, file=sys.stderr)
107
+ return False
90
108
 
91
109
  def main():
92
110
  today = datetime.date.today().isoformat()
@@ -106,7 +124,7 @@ def main():
106
124
  print('title:', TITLE)
107
125
  print('body :', body)
108
126
  return 0
109
- notify(body)
127
+ notify(TITLE, body)
110
128
  print('notified:', body)
111
129
  return 0
112
130
 
@@ -72,6 +72,29 @@ def save_state(state):
72
72
  STATE.parent.mkdir(parents=True, exist_ok=True)
73
73
  STATE.write_text(json.dumps(state, ensure_ascii=False), encoding='utf-8')
74
74
 
75
+ APPLESCRIPT = (
76
+ 'on run argv\n'
77
+ ' display notification (item 2 of argv) with title (item 1 of argv) subtitle "DSH 看板" sound name "Glass"\n'
78
+ 'end run'
79
+ )
80
+
81
+
82
+ def notify(title, body):
83
+ """Notification text is user data: pass it as argv so AppleScript never parses it."""
84
+ try:
85
+ result = subprocess.run(
86
+ ['/usr/bin/osascript', '-e', APPLESCRIPT, str(title), str(body)],
87
+ capture_output=True, text=True, timeout=20
88
+ )
89
+ if result.returncode != 0:
90
+ print('notify failed:', (result.stderr or '').strip() or 'osascript exit ' + str(result.returncode), file=sys.stderr)
91
+ return False
92
+ return True
93
+ except (OSError, subprocess.SubprocessError) as error:
94
+ print('notify failed:', error, file=sys.stderr)
95
+ return False
96
+
97
+
75
98
  def main():
76
99
  window = 120
77
100
  if '--window' in sys.argv:
@@ -111,7 +134,7 @@ def main():
111
134
  if '--dry-run' in sys.argv:
112
135
  print('body:', body)
113
136
  return 0
114
- subprocess.run(['/usr/bin/osascript', '-e', f'display notification "{body}" with title "{TITLE}" sound name "Glass"'], check=False)
137
+ notify(TITLE, body)
115
138
  for when, _minutes, _row, key in hits:
116
139
  state[key] = when.isoformat(timespec='minutes')
117
140
  save_state(state)
package/scripts/weekly.py CHANGED
@@ -70,17 +70,40 @@ def build(rows, today):
70
70
  body = body[:197] + '…'
71
71
  return body
72
72
 
73
+ APPLESCRIPT = (
74
+ 'on run argv\n'
75
+ ' display notification (item 2 of argv) with title (item 1 of argv) subtitle "DSH 看板" sound name "Glass"\n'
76
+ 'end run'
77
+ )
78
+
79
+
80
+ def notify(title, body):
81
+ """Notification text is user data: pass it as argv so AppleScript never parses it."""
82
+ try:
83
+ result = subprocess.run(
84
+ ['/usr/bin/osascript', '-e', APPLESCRIPT, str(title), str(body)],
85
+ capture_output=True, text=True, timeout=20
86
+ )
87
+ if result.returncode != 0:
88
+ print('notify failed:', (result.stderr or '').strip() or 'osascript exit ' + str(result.returncode), file=sys.stderr)
89
+ return False
90
+ return True
91
+ except (OSError, subprocess.SubprocessError) as error:
92
+ print('notify failed:', error, file=sys.stderr)
93
+ return False
94
+
95
+
73
96
  def main():
74
- if not BOARD.exists():
75
- print('board not found', file=sys.stderr)
76
- return 1
77
97
  today = datetime.date.today()
78
- body = build(parse(read_board()), today)
98
+ try:
99
+ body = build(parse(read_board()), today)
100
+ except OSError as error:
101
+ print('cannot read board or snapshot:', error, file=sys.stderr)
102
+ return 1
79
103
  if '--dry-run' in sys.argv:
80
104
  print('body:', body)
81
105
  return 0
82
- script = 'display notification "' + body.replace('"', '\\"') + '" with title "' + TITLE + '" sound name "Glass"'
83
- subprocess.run(['/usr/bin/osascript', '-e', script], check=False)
106
+ notify(TITLE, body)
84
107
  print('notified:', body)
85
108
  return 0
86
109