dsh-scheduled-message 0.1.1
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/LICENSE +21 -0
- package/README.md +113 -0
- package/client.js +1739 -0
- package/cordis.patch.yml +3 -0
- package/docs/DETAIL.md +440 -0
- package/docs/preview.png +0 -0
- package/icon.svg +13 -0
- package/index.js +694 -0
- package/lib/core.js +466 -0
- package/locale/en.json +91 -0
- package/locale/zh.json +91 -0
- package/package.json +65 -0
- package/scripts/build-client.mjs +99 -0
- package/scripts/check.mjs +101 -0
- package/scripts/host-smoke.mjs +433 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 intelfabs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# dsh-scheduled-message
|
|
2
|
+
|
|
3
|
+
Schedule the message you are already writing in the DSH composer — text, images and files — to be
|
|
4
|
+
delivered later by the **Host**. Because the timer and the store live in the Host, closing the tab or
|
|
5
|
+
the window does not cancel anything, and a message whose time passed while DSH was closed is sent at
|
|
6
|
+
the next start and marked **sent late**.
|
|
7
|
+
|
|
8
|
+
Normal sending is untouched: Enter, Shift+Enter, Ctrl/Cmd+Enter and the Send button keep exactly
|
|
9
|
+
their current meaning.
|
|
10
|
+
|
|
11
|
+

|
|
12
|
+
|
|
13
|
+
## What you get
|
|
14
|
+
|
|
15
|
+
| Surface | Behaviour |
|
|
16
|
+
|---|---|
|
|
17
|
+
| **Schedule** button | Orange pill beside Send in the composer tool row. Disabled while the draft is empty or the composer is busy. |
|
|
18
|
+
| **Alt+Enter** (Option+Enter on macOS) | Opens the same dialog. Registered as an editable-region shortcut, editable in Settings › Shortcuts. |
|
|
19
|
+
| **Dialog** | Date, hour 1–12, minute, AM/PM, quick picks, a "Sends …" summary, and an optional **Repeat** row. Backdrop/Escape close, focus returns to the composer. |
|
|
20
|
+
| **Strip** | Above the composer: `2 scheduled · next Fri, 14 Nov, 9:00 am`, expandable to rows with **Send now**, **Change time**, **Cancel**, and **Retry** for a failed delivery. |
|
|
21
|
+
| **Repeat** | Creates a task in DSH's own Automation service and opens its task page. Blocked when the draft has images or files. |
|
|
22
|
+
| **Phone** | Bottom sheet under 640 px, 44 px targets, 16 px inputs (no zoom-on-focus), safe-area padding. |
|
|
23
|
+
| **Theme** | Host tokens for every surface and text colour; the accent orange is the only literal colour. English and Chinese dictionaries ship complete. |
|
|
24
|
+
|
|
25
|
+
## Install
|
|
26
|
+
|
|
27
|
+
The package is a normal DSH plugin bundle: a Host half (`index.js`), a browser half
|
|
28
|
+
(`client.js`), and one patch entry.
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
# 1. put the package where the profile can resolve it
|
|
32
|
+
cp -r dsh-scheduled-message ~/.dsh/profiles/desktop/node_modules/dsh-scheduled-message
|
|
33
|
+
|
|
34
|
+
# 2. add it to the profile's dependencies and bundle list (package.json)
|
|
35
|
+
# "dsh-scheduled-message": "file:./node_modules/dsh-scheduled-message"
|
|
36
|
+
# "dsh": { "profile": { "bundles": [ …, "dsh-scheduled-message" ] } }
|
|
37
|
+
|
|
38
|
+
# 3. restart DSH
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
With the plugin manager available, `install_bundle` with this directory as the target does the same
|
|
42
|
+
thing and reports `application: applied`.
|
|
43
|
+
|
|
44
|
+
Registering the row directly, without touching `dsh.profile.bundles`, also works — the bundle ships
|
|
45
|
+
`cordis.patch.yml`:
|
|
46
|
+
|
|
47
|
+
```yaml
|
|
48
|
+
- insert:
|
|
49
|
+
- id: dsh-scheduled-message
|
|
50
|
+
name: dsh-scheduled-message
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Using it
|
|
54
|
+
|
|
55
|
+
1. Type the message and attach anything you want.
|
|
56
|
+
2. Press **Alt+Enter**, or click **Schedule**.
|
|
57
|
+
3. Pick a date and a time on the 12-hour clock, or use a quick pick.
|
|
58
|
+
4. Press **Schedule**. The draft and its attachments are cleared and the message appears in the strip.
|
|
59
|
+
5. Close the tab whenever you like. Delivery is the Host's job.
|
|
60
|
+
|
|
61
|
+
Tick **Repeat** instead to create an Automation task: daily, weekdays, weekly on the chosen weekday,
|
|
62
|
+
or monthly on the chosen day. Monthly rules on the 29th–31st skip months that are too short.
|
|
63
|
+
|
|
64
|
+
## What it does not do
|
|
65
|
+
|
|
66
|
+
- **No repeating messages with attachments.** The Automation service delivers text only, so the UI
|
|
67
|
+
and the Host validator both refuse that combination.
|
|
68
|
+
- **No auto-retry.** A failed delivery is reported with its reason; **Retry** is a user action.
|
|
69
|
+
- **No polling.** The strip refreshes on mount, after an action, on window focus, and once shortly
|
|
70
|
+
after the next due time.
|
|
71
|
+
- **No cross-zone surprise.** The browser's IANA zone is captured at create time and only used for
|
|
72
|
+
display and for the 12-hour reading; the Host stores one absolute instant.
|
|
73
|
+
- **Disabling the plugin does not delete anything.** Pending records stay in storage and resume when
|
|
74
|
+
the plugin is enabled again.
|
|
75
|
+
|
|
76
|
+
## Layout
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
index.js Host half: durable store, six /api routes, timer, delivery
|
|
80
|
+
client.js browser bundle (generated — see scripts/build-client.mjs)
|
|
81
|
+
client.src.js browser half source (button, dialog, strip, shortcut, styles)
|
|
82
|
+
lib/core.js dependency-free shared logic: 12-hour clock, zone resolution,
|
|
83
|
+
validation, RRULE text, timer chunking, retention
|
|
84
|
+
locale/en.json English dictionary
|
|
85
|
+
locale/zh.json Chinese dictionary
|
|
86
|
+
scripts/build-client.mjs inlines lib/core.js + locale/*.json into client.js
|
|
87
|
+
scripts/check.mjs static gates (parse, bundle freshness, locale coverage, exports)
|
|
88
|
+
scripts/host-smoke.mjs end-to-end Host test against in-memory services
|
|
89
|
+
test/*.test.mjs node --test suites
|
|
90
|
+
docs/DETAIL.md design notes, API evidence, and what is still unverified
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Development
|
|
94
|
+
|
|
95
|
+
```sh
|
|
96
|
+
npm run build # regenerate client.js after editing client.src.js, lib/core.js or locale/*.json
|
|
97
|
+
npm test # unit + bundle + Host smoke tests
|
|
98
|
+
npm run check # static gates
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Status
|
|
102
|
+
|
|
103
|
+
`0.1.1`. 33 automated tests and the static gates pass. 0.1.1 fixes the composer button: it now reads
|
|
104
|
+
the draft through the composer slot's standard `useInput` hook, so it enables as soon as you type
|
|
105
|
+
(0.1.0 read a `props.input` that `conversation.input.right` never passes and stayed disabled).
|
|
106
|
+
|
|
107
|
+
The plugin was also booted inside an isolated DSH `0.2.2-rc.2` web instance: it loaded, its client
|
|
108
|
+
bundle was served into the page's boot graph, a real scheduled message was created, stored, delivered
|
|
109
|
+
on time and, in a second cycle with the Host stopped past the due instant, delivered at startup and
|
|
110
|
+
marked **sent late**; Repeat created a real Automation task. The dialog itself renders in a live composer —
|
|
111
|
+
the screenshot above is the real thing, not a mock — while Alt+Enter and the strip have not been
|
|
112
|
+
separately observed. See
|
|
113
|
+
[`docs/DETAIL.md`](docs/DETAIL.md#7-verification) for the exact list.
|