@qzsy/dsh-workspace-combobox 0.2.0 → 0.2.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/README.md CHANGED
@@ -5,7 +5,7 @@ Workspace combobox plus a Git branch picker for DeepSeek Harness.
5
5
  ## Install
6
6
 
7
7
  ~~~bash
8
- dsh plugin add @qzsy/dsh-workspace-combobox@0.2.0
8
+ dsh plugin add @qzsy/dsh-workspace-combobox@0.2.2
9
9
  ~~~
10
10
 
11
11
  ## Features
package/dist/client.js CHANGED
@@ -546,7 +546,7 @@ window.__ModuleLoader__.load({
546
546
  * trigger chip and hands over open/close state, the anchor, and the
547
547
  * selection; this panel adds pinyin-aware search over names and paths.
548
548
  */
549
- function HeroWorkspaceCombobox({ open, anchorRef, selectedId, onPick, onClose, actions, getHome, shortcutLabel, selection, useWorkspaces, useSessions, t }) {
549
+ function HeroWorkspaceCombobox({ open, anchorRef, selectedId, onPick, onClose, actions, getHome, shortcutLabel, useWorkspaces, useSessions, t }) {
550
550
  const home = typeof getHome === 'function' ? getHome() : '';
551
551
  const rows = useWorkspaceRows(useWorkspaces, useSessions, home, false);
552
552
  const [query, setQuery] = useState('');
@@ -559,9 +559,7 @@ window.__ModuleLoader__.load({
559
559
  const items = useWorkspaceSearch(rows, query);
560
560
  const selectedRow = selectedId === undefined || selectedId === null ? undefined : rows.find((row) => String(row.id) === String(selectedId));
561
561
  const selectedPath = selectedRow === undefined ? '' : String(selectedRow.path ?? '');
562
- useEffect(() => {
563
- if (selection !== undefined && typeof selection.set === 'function') selection.set(selectedPath);
564
- }, [selection, selectedPath]);
562
+ const branch = selectedPath.length === 0 ? null : h(BranchSelector, { path: selectedPath, t });
565
563
 
566
564
  useEffect(() => {
567
565
  if (!open) return undefined;
@@ -646,7 +644,7 @@ window.__ModuleLoader__.load({
646
644
  .finally(() => setAdding(false));
647
645
  };
648
646
 
649
- if (!open || position === null) return null;
647
+ if (!open || position === null) return branch;
650
648
  const activeOption = items.length === 0 ? undefined : Math.min(Math.max(activeIndex, 0), items.length - 1);
651
649
  const panel = h('div', {
652
650
  className: 'wsc-card wsc-heroCard',
@@ -698,13 +696,14 @@ window.__ModuleLoader__.load({
698
696
  );
699
697
  // The shipped picker portals its menu out of the Hero tree; mirror that so
700
698
  // no transformed or clipped ancestor can displace the panel.
701
- if (createPortal !== null && typeof document !== 'undefined') return createPortal(panel, document.body);
702
- return panel;
699
+ if (createPortal !== null && typeof document !== 'undefined') return h(React.Fragment, null, branch, createPortal(panel, document.body));
700
+ return h(React.Fragment, null, branch, panel);
703
701
  }
704
702
 
705
703
  //#region git branch
706
704
  const BRANCH_STATUS_ENDPOINT = 'api/workspace-git';
707
705
  const BRANCH_SWITCH_ENDPOINT = 'api/workspace-git/switch';
706
+ const MIN_SWITCH_FEEDBACK_MS = 700;
708
707
 
709
708
  function branchEndpoint(route) {
710
709
  if (typeof document !== 'undefined' && typeof document.baseURI === 'string') {
@@ -717,6 +716,10 @@ window.__ModuleLoader__.load({
717
716
  return route;
718
717
  }
719
718
 
719
+ function wait(ms) {
720
+ return new Promise((resolve) => setTimeout(resolve, ms));
721
+ }
722
+
720
723
  async function branchRequest(route, payload, signal) {
721
724
  const response = await fetch(branchEndpoint(route), {
722
725
  method: 'POST',
@@ -742,8 +745,8 @@ window.__ModuleLoader__.load({
742
745
  return body.value === null || typeof body.value !== 'object' ? {} : body.value;
743
746
  }
744
747
 
745
- function BranchSelector({ selection, t }) {
746
- const path = usePathValue(selection);
748
+ function BranchSelector({ path: activePath, t }) {
749
+ const path = typeof activePath === 'string' ? activePath : '';
747
750
  const [status, setStatus] = useState(null);
748
751
  const [loading, setLoading] = useState(false);
749
752
  const [open, setOpen] = useState(false);
@@ -871,14 +874,19 @@ window.__ModuleLoader__.load({
871
874
  const choose = async (name, isRemote) => {
872
875
  if (busy) return;
873
876
  const targetPath = path;
877
+ const startedAt = Date.now();
874
878
  setSwitching(name);
875
879
  setError('');
876
880
  try {
877
881
  const next = await branchRequest(BRANCH_SWITCH_ENDPOINT, { path: targetPath, branch: name, remote: isRemote });
882
+ const remaining = MIN_SWITCH_FEEDBACK_MS - (Date.now() - startedAt);
883
+ if (remaining > 0) await wait(remaining);
878
884
  if (selection !== undefined && typeof selection.get === 'function' && selection.get() !== targetPath) return;
879
885
  setStatus(next);
880
886
  setOpen(false);
881
887
  } catch (failure) {
888
+ const remaining = MIN_SWITCH_FEEDBACK_MS - (Date.now() - startedAt);
889
+ if (remaining > 0) await wait(remaining);
882
890
  setError(failure instanceof Error && failure.message.length > 0 ? failure.message : t('branch.failed'));
883
891
  } finally {
884
892
  setSwitching(null);
@@ -1159,7 +1167,6 @@ window.__ModuleLoader__.load({
1159
1167
  ctx.effect(() => installStyles(), 'workspace-combobox: styles');
1160
1168
  const t = ctx.locale.bind(NS);
1161
1169
  const store = createStore({ open: false });
1162
- const selectedPathStore = createPathStore();
1163
1170
  const workspaces = ctx.get('workspaces');
1164
1171
  const uiWorkspace = ctx.get('uiWorkspace');
1165
1172
  const remote = ctx.get('remote');
@@ -1221,7 +1228,6 @@ window.__ModuleLoader__.load({
1221
1228
  createWorkspace: actions.createWorkspace
1222
1229
  },
1223
1230
  getHome,
1224
- selection: selectedPathStore,
1225
1231
  shortcutLabel
1226
1232
  })
1227
1233
  }, HeroWorkspaceCombobox);
@@ -1230,20 +1236,6 @@ window.__ModuleLoader__.load({
1230
1236
  return () => {};
1231
1237
  }
1232
1238
  });
1233
- ctx.slots.inject('conversation.hero.options', () => {
1234
- try {
1235
- return ctx.slots.register({
1236
- name: 'conversation.hero.options',
1237
- id: 'workspace-combobox.branch',
1238
- order: 20,
1239
- locale: NS,
1240
- inject: () => ({ selection: selectedPathStore })
1241
- }, BranchSelector);
1242
- } catch (error) {
1243
- console.warn('workspace combobox: branch selector registration failed', error);
1244
- return () => {};
1245
- }
1246
- });
1247
1239
  }
1248
1240
  //#endregion
1249
1241
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qzsy/dsh-workspace-combobox",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Pinyin-aware workspace combobox for the New Session picker, plus a Git branch picker with local/remote branch switching and a Ctrl+. frame-wide workspace switcher.",
5
5
  "type": "module",
6
6
  "license": "MIT",