@ottttto/dsh-scheduled-send 0.3.0 → 0.3.2

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/lib/client.js CHANGED
@@ -315,6 +315,9 @@ function createClientPluginBody(React) {
315
315
  try {
316
316
  const payload = { content, sendAt: at, conversationId: props.sessionId };
317
317
  await core.scheduleMessage(payload);
318
+ // sidebar panel has its own state: refresh it NOW (its 8s poll would
319
+ // otherwise lag ~10s behind a fresh task)
320
+ if (props.onTaskCreated) void props.onTaskCreated();
318
321
  // spec: 内容转为定时任务并清空输入框 — 绝不立即发送(不调 submit)
319
322
  if (props.inputActions && typeof props.inputActions.setDraft === "function") props.inputActions.setDraft("");
320
323
  setOpen(false);
@@ -496,6 +499,7 @@ function createClientPluginBody(React) {
496
499
  const core = props.panelCore;
497
500
  const [open, setOpen] = React.useState(false);
498
501
  const [tick, setTick] = React.useState(0);
502
+ const [hover, setHover] = React.useState(false);
499
503
  const mobile = isMobile();
500
504
 
501
505
  // keep the badge alive even while the panel is closed: poll the FULL
@@ -521,11 +525,13 @@ function createClientPluginBody(React) {
521
525
 
522
526
  const isDark = typeof window !== "undefined" && window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches;
523
527
  const entryBtn = {
524
- cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 6,
525
- border: "none", background: "transparent", color: "inherit",
526
- fontSize: 12, fontWeight: 600, padding: "4px 8px", borderRadius: 8, whiteSpace: "nowrap",
528
+ cursor: "pointer", display: "flex", alignItems: "center", gap: 8,
529
+ width: "100%", boxSizing: "border-box", textAlign: "left",
530
+ border: "none", background: hover ? "rgba(128,128,128,.16)" : "transparent", color: "inherit",
531
+ fontSize: 12, fontWeight: 600, padding: "6px 10px", borderRadius: 8, whiteSpace: "nowrap",
527
532
  ...(mobile ? { minHeight: TOUCH_MIN } : {}),
528
533
  };
534
+ const iconBox = { display: "inline-flex", width: 16, justifyContent: "center", flexShrink: 0 };
529
535
  const badge = (n) => h("span", {
530
536
  key: "b", "data-badge": n,
531
537
  style: {
@@ -620,14 +626,18 @@ function createClientPluginBody(React) {
620
626
  ])
621
627
  : null;
622
628
 
623
- return h("div", { "data-plugin": "dsh-scheduled-send-sidebar", style: { display: "inline-flex", alignItems: "center" } }, [
629
+ return h("div", { "data-plugin": "dsh-scheduled-send-sidebar", style: { width: "100%" } }, [
630
+ null,
624
631
  h("button", {
625
632
  key: "btn", type: "button",
633
+ onMouseEnter: () => setHover(true),
634
+ onMouseLeave: () => setHover(false),
626
635
  onClick: () => { setOpen(!open); setTick((n) => n + 1); },
627
636
  title: "定时任务", "aria-label": "定时任务", style: entryBtn,
628
637
  }, [
629
- h("span", { key: "l" }, "⏰ 定时任务"),
630
- all.length ? badge(all.length) : null,
638
+ h("span", { key: "i", style: iconBox }, "⏰"),
639
+ h("span", { key: "l" }, "定时任务"),
640
+ all.length ? h("span", { key: "bs", style: { marginLeft: "auto", display: "inline-flex" } }, badge(all.length)) : null,
631
641
  ]),
632
642
  footer,
633
643
  ]);
@@ -687,6 +697,9 @@ function createClientPluginBody(React) {
687
697
 
688
698
  const inject = ["slots", "sessions"]; // sessions: sidebar panel jump (0.3.0)
689
699
  function apply(ctx) {
700
+ // due-time delivery: refresh the sidebar panel the moment a task fires
701
+ ctx.on?.('guard/scheduled-due', () => { void panelCore.refresh(); });
702
+ ctx.on?.('guard/scheduled-dropped', () => { void panelCore.refresh(); });
690
703
  ctx.inject(inject, (scope) => {
691
704
  // 0.3.0 session navigation, sourced from the sessions service:
692
705
  // - open(id) selects a session as current (unknown ids throw → false)
@@ -714,7 +727,7 @@ function createClientPluginBody(React) {
714
727
  inject: (sessionId) => {
715
728
  currentSessionId = sessionId;
716
729
  core.setSession(sessionId); // dock/button are conversation-scoped
717
- return { sessionId, core };
730
+ return { sessionId, core, onTaskCreated: () => panelCore.refresh() };
718
731
  },
719
732
  }, ScheduleButton));
720
733
  scope.slots.inject("conversation.input.dock", () => scope.slots.register({
@@ -724,7 +737,7 @@ function createClientPluginBody(React) {
724
737
  inject: (sessionId) => {
725
738
  currentSessionId = sessionId;
726
739
  core.setSession(sessionId);
727
- return { sessionId, core };
740
+ return { sessionId, core, onTaskCreated: () => panelCore.refresh() };
728
741
  },
729
742
  }, ScheduledDock));
730
743
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ottttto/dsh-scheduled-send",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "DSH plugin: scheduled sending (⏰ composer button, dock list of pending tasks, sidebar 定时任务 panel with cross-session cancel, due-time delivery as a normal user bubble)",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
@@ -52,4 +52,4 @@
52
52
  "engines": {
53
53
  "node": ">=18"
54
54
  }
55
- }
55
+ }
@@ -51,6 +51,9 @@ function createClientPluginBody(React) {
51
51
  try {
52
52
  const payload = { content, sendAt: at, conversationId: props.sessionId };
53
53
  await core.scheduleMessage(payload);
54
+ // sidebar panel has its own state: refresh it NOW (its 8s poll would
55
+ // otherwise lag ~10s behind a fresh task)
56
+ if (props.onTaskCreated) void props.onTaskCreated();
54
57
  // spec: 内容转为定时任务并清空输入框 — 绝不立即发送(不调 submit)
55
58
  if (props.inputActions && typeof props.inputActions.setDraft === "function") props.inputActions.setDraft("");
56
59
  setOpen(false);
@@ -232,6 +235,7 @@ function createClientPluginBody(React) {
232
235
  const core = props.panelCore;
233
236
  const [open, setOpen] = React.useState(false);
234
237
  const [tick, setTick] = React.useState(0);
238
+ const [hover, setHover] = React.useState(false);
235
239
  const mobile = isMobile();
236
240
 
237
241
  // keep the badge alive even while the panel is closed: poll the FULL
@@ -257,11 +261,13 @@ function createClientPluginBody(React) {
257
261
 
258
262
  const isDark = typeof window !== "undefined" && window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches;
259
263
  const entryBtn = {
260
- cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 6,
261
- border: "none", background: "transparent", color: "inherit",
262
- fontSize: 12, fontWeight: 600, padding: "4px 8px", borderRadius: 8, whiteSpace: "nowrap",
264
+ cursor: "pointer", display: "flex", alignItems: "center", gap: 8,
265
+ width: "100%", boxSizing: "border-box", textAlign: "left",
266
+ border: "none", background: hover ? "rgba(128,128,128,.16)" : "transparent", color: "inherit",
267
+ fontSize: 12, fontWeight: 600, padding: "6px 10px", borderRadius: 8, whiteSpace: "nowrap",
263
268
  ...(mobile ? { minHeight: TOUCH_MIN } : {}),
264
269
  };
270
+ const iconBox = { display: "inline-flex", width: 16, justifyContent: "center", flexShrink: 0 };
265
271
  const badge = (n) => h("span", {
266
272
  key: "b", "data-badge": n,
267
273
  style: {
@@ -356,14 +362,18 @@ function createClientPluginBody(React) {
356
362
  ])
357
363
  : null;
358
364
 
359
- return h("div", { "data-plugin": "dsh-scheduled-send-sidebar", style: { display: "inline-flex", alignItems: "center" } }, [
365
+ return h("div", { "data-plugin": "dsh-scheduled-send-sidebar", style: { width: "100%" } }, [
366
+ null,
360
367
  h("button", {
361
368
  key: "btn", type: "button",
369
+ onMouseEnter: () => setHover(true),
370
+ onMouseLeave: () => setHover(false),
362
371
  onClick: () => { setOpen(!open); setTick((n) => n + 1); },
363
372
  title: "定时任务", "aria-label": "定时任务", style: entryBtn,
364
373
  }, [
365
- h("span", { key: "l" }, "⏰ 定时任务"),
366
- all.length ? badge(all.length) : null,
374
+ h("span", { key: "i", style: iconBox }, "⏰"),
375
+ h("span", { key: "l" }, "定时任务"),
376
+ all.length ? h("span", { key: "bs", style: { marginLeft: "auto", display: "inline-flex" } }, badge(all.length)) : null,
367
377
  ]),
368
378
  footer,
369
379
  ]);
@@ -423,6 +433,9 @@ function createClientPluginBody(React) {
423
433
 
424
434
  const inject = ["slots", "sessions"]; // sessions: sidebar panel jump (0.3.0)
425
435
  function apply(ctx) {
436
+ // due-time delivery: refresh the sidebar panel the moment a task fires
437
+ ctx.on?.('guard/scheduled-due', () => { void panelCore.refresh(); });
438
+ ctx.on?.('guard/scheduled-dropped', () => { void panelCore.refresh(); });
426
439
  ctx.inject(inject, (scope) => {
427
440
  // 0.3.0 session navigation, sourced from the sessions service:
428
441
  // - open(id) selects a session as current (unknown ids throw → false)
@@ -450,7 +463,7 @@ function createClientPluginBody(React) {
450
463
  inject: (sessionId) => {
451
464
  currentSessionId = sessionId;
452
465
  core.setSession(sessionId); // dock/button are conversation-scoped
453
- return { sessionId, core };
466
+ return { sessionId, core, onTaskCreated: () => panelCore.refresh() };
454
467
  },
455
468
  }, ScheduleButton));
456
469
  scope.slots.inject("conversation.input.dock", () => scope.slots.register({
@@ -460,7 +473,7 @@ function createClientPluginBody(React) {
460
473
  inject: (sessionId) => {
461
474
  currentSessionId = sessionId;
462
475
  core.setSession(sessionId);
463
- return { sessionId, core };
476
+ return { sessionId, core, onTaskCreated: () => panelCore.refresh() };
464
477
  },
465
478
  }, ScheduledDock));
466
479
  });