dsh-mobile 0.5.2 → 0.5.4
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/CHANGELOG.md +22 -0
- package/CONTRIBUTORS.md +10 -6
- package/README.en.md +22 -6
- package/README.md +22 -6
- package/SECURITY.md +1 -1
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/cordis.patch.yml +6 -0
- package/docs/README.md +1 -0
- package/docs/SLOW_CONNECTIONS.en.md +77 -0
- package/docs/SLOW_CONNECTIONS.md +77 -0
- package/lib/client.js +129 -7
- package/lib/client.js.map +1 -1
- package/lib/index.d.mts +147 -122
- package/lib/index.mjs +529 -215
- package/lib/index.mjs.map +1 -1
- package/lib/mobile-layout.js +134 -2
- package/lib/mobile-layout.js.map +1 -1
- package/node_modules/dsh-mobile-question-fixes/lib/client.js +78 -0
- package/node_modules/dsh-mobile-question-fixes/lib/client.js.map +1 -0
- package/node_modules/dsh-mobile-question-fixes/lib/index.mjs +14 -0
- package/node_modules/dsh-mobile-question-fixes/lib/index.mjs.map +1 -0
- package/node_modules/dsh-mobile-question-fixes/package.json +25 -0
- package/package.json +19 -4
- package/packages/question-fixes/lib/client.js +78 -0
- package/packages/question-fixes/lib/client.js.map +1 -0
- package/packages/question-fixes/lib/index.mjs +14 -0
- package/packages/question-fixes/lib/index.mjs.map +1 -0
- package/packages/question-fixes/package.json +25 -0
package/lib/client.js
CHANGED
|
@@ -2631,6 +2631,8 @@ window.__ModuleLoader__.load({
|
|
|
2631
2631
|
the query restores the fixed scrim, and its more specific [hidden] rule
|
|
2632
2632
|
keeps winning there. */
|
|
2633
2633
|
.dsh-native-mobile-backdrop,.dsh-mobile-branch-toast,.dsh-mobile-media-toast { display:none; }
|
|
2634
|
+
/* The content-font preference may exceed Safari's focused-editable minimum. */
|
|
2635
|
+
[data-dsh-mobile-center] :is(input,textarea,[contenteditable="true"],[contenteditable="plaintext-only"],[contenteditable=""]) { font-size:max(16px,1em,var(--dsh-content-font-size,1em)) !important; }
|
|
2634
2636
|
.dsh-mobile-settings_row { display:flex; align-items:center; gap:8px; padding:16px 0; border-bottom:0.5px solid var(--dsw-alias-border-l2); }
|
|
2635
2637
|
.dsh-mobile-settings_rowText { flex:1; min-width:0; display:flex; flex-direction:column; gap:4px; padding-right:48px; }
|
|
2636
2638
|
.dsh-mobile-settings_title { color:var(--dsw-alias-label-primary); font-size:14px; font-weight:400; line-height:22px; }
|
|
@@ -2723,7 +2725,6 @@ window.__ModuleLoader__.load({
|
|
|
2723
2725
|
[data-dsh-mobile-settings-options] [class*="_rowActions"] button { flex:none !important; width:auto !important; min-width:44px !important; max-width:none !important; min-height:44px !important; padding-inline:10px !important; white-space:nowrap !important; word-break:keep-all !important; writing-mode:horizontal-tb !important; }
|
|
2724
2726
|
[data-dsh-mobile-settings-content][data-dsh-mobile-view-transition="true"],
|
|
2725
2727
|
[data-dsh-mobile-view][data-dsh-mobile-view-transition="true"] { animation:dsh-mobile-view-in var(--dsh-mobile-motion-duration) var(--dsh-mobile-motion-ease); }
|
|
2726
|
-
[data-dsh-mobile-center] textarea { font-size:16px !important; }
|
|
2727
2728
|
/* Markdown tables use content-sized columns. Small tables fill the phone;
|
|
2728
2729
|
wider tables keep readable cells and scroll inside their own region. */
|
|
2729
2730
|
[data-dsh-mobile-table-scroll] { box-sizing:border-box; width:100%; max-width:100%; overflow-x:auto; overscroll-behavior-x:contain; -webkit-overflow-scrolling:touch; }
|
|
@@ -2735,7 +2736,9 @@ window.__ModuleLoader__.load({
|
|
|
2735
2736
|
[data-dsh-mobile-history-loader] { position:relative !important; min-height:1px !important; }
|
|
2736
2737
|
[data-dsh-mobile-history-loader] button:not(:disabled) { position:absolute !important; width:1px !important; height:1px !important; margin:-1px !important; padding:0 !important; clip-path:inset(50%) !important; opacity:0 !important; overflow:hidden !important; pointer-events:none !important; }
|
|
2737
2738
|
[data-dsh-mobile-history-loader] button:disabled { min-height:28px !important; padding:4px 12px !important; }
|
|
2738
|
-
|
|
2739
|
+
/* DSH's sibling margins exclude hidden and empty Chat Node Seats. Keep that
|
|
2740
|
+
spacing rule so searchable hidden seats contribute no folded-turn gaps. */
|
|
2741
|
+
[data-dsh-mobile-message-column] { box-sizing:border-box !important; width:100% !important; max-width:none !important; margin:0 !important; padding:0 !important; gap:0 !important; --dsh-chat-flow-gap:10px; }
|
|
2739
2742
|
[data-dsh-mobile-message-column] > * { width:100% !important; max-width:100% !important; }
|
|
2740
2743
|
[data-dsh-mobile-message-column] [data-disclosure-row] { box-sizing:border-box !important; display:grid !important; grid-template-columns:16px minmax(0,1fr) !important; grid-auto-rows:auto !important; align-items:center !important; column-gap:6px !important; width:100% !important; height:auto !important; min-height:40px !important; padding:4px 0 !important; }
|
|
2741
2744
|
[data-dsh-mobile-message-column] [data-disclosure-row] > [class*="_leading"] { grid-column:1 !important; grid-row:1 !important; margin-right:0 !important; }
|
|
@@ -2757,12 +2760,27 @@ window.__ModuleLoader__.load({
|
|
|
2757
2760
|
/* The context ring is a composer-metadata _root too, so the metadata rule
|
|
2758
2761
|
above stretched it across the whole dock. It cannot shrink, which left the
|
|
2759
2762
|
session statistics beside it a few pixels wide, every number clipped to an
|
|
2760
|
-
ellipsis.
|
|
2761
|
-
|
|
2762
|
-
a wide screen keeps the ring beside them on one line. */
|
|
2763
|
+
ellipsis. Keep the ring at its own size and let it hold the row the numbers
|
|
2764
|
+
are on. */
|
|
2763
2765
|
[data-dsh-mobile-center] [data-composer-card] ~ * [class*="_root"]:has(> [class*="_trigger"][aria-haspopup="dialog"]) { width:auto !important; max-width:none !important; flex:0 0 auto !important; }
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
+
/* Slot entries participate in this flex layout through display:contents.
|
|
2767
|
+
Keep core statistics and the meter together; extra entries use their own
|
|
2768
|
+
rows instead of taking the statistics' remaining width on phones. */
|
|
2769
|
+
[data-dsh-mobile-center] [class*="_dock"]:has([data-composer-stats]) { display:flex !important; flex-wrap:wrap !important; justify-content:flex-start !important; align-items:center !important; column-gap:12px !important; row-gap:2px !important; width:100% !important; max-width:100% !important; }
|
|
2770
|
+
/* Dock row gaps replace the single-row metadata's negative margin. */
|
|
2771
|
+
[data-dsh-mobile-center] [class*="_dock"]:has([data-composer-stats]) > *,
|
|
2772
|
+
[data-dsh-mobile-center] [class*="_dock"]:has([data-composer-stats]) [data-slot="conversation.composer.dock"] > * { margin-bottom:0 !important; }
|
|
2773
|
+
[data-dsh-mobile-center] [class*="_dock"]:has([data-composer-stats]) [data-slot="conversation.composer.dock"] > :not([data-composer-stats]) { flex:0 1 100% !important; min-width:0 !important; max-width:100% !important; }
|
|
2774
|
+
[data-dsh-mobile-center] [class*="_dock"]:has([data-composer-stats]) [data-composer-stats] { order:-2 !important; }
|
|
2775
|
+
[data-dsh-mobile-center] [class*="_dock"]:has([data-composer-stats]) > [class*="_root"]:has(> [class*="_trigger"][aria-haspopup="dialog"]) { order:-1 !important; }
|
|
2776
|
+
/* Interactive pills expose complete values in their labels and dialogs.
|
|
2777
|
+
Static compact or untimed pills have no disclosure, so they may wrap. */
|
|
2778
|
+
[data-dsh-mobile-center] [data-composer-card] ~ * [class*="_root"][data-composer-stats] { box-sizing:border-box !important; width:auto !important; max-width:none !important; flex:1 1 0 !important; flex-wrap:nowrap !important; justify-content:flex-start !important; overflow:hidden !important; row-gap:2px !important; }
|
|
2779
|
+
[data-dsh-mobile-center] [data-composer-stats] > * { min-width:0 !important; }
|
|
2780
|
+
[data-dsh-mobile-center] [data-composer-stats] [class*="_pill"] { display:block !important; min-width:0 !important; white-space:nowrap !important; overflow:hidden !important; text-overflow:ellipsis !important; }
|
|
2781
|
+
[data-dsh-mobile-center] [data-composer-stats] [class*="_pill"] svg { display:inline-block !important; vertical-align:-2px !important; margin-right:6px !important; }
|
|
2782
|
+
[data-dsh-mobile-center] [data-composer-stats]:has(span[class*="_pill"]) { flex-wrap:wrap !important; overflow:visible !important; }
|
|
2783
|
+
[data-dsh-mobile-center] [data-composer-stats] span[class*="_pill"] { flex:0 1 auto !important; max-width:100% !important; white-space:normal !important; overflow:visible !important; overflow-wrap:anywhere !important; text-overflow:clip !important; }
|
|
2766
2784
|
/* Message runtime details are inline on desktop. Give the clock/runtime
|
|
2767
2785
|
label its own wrapping row on narrow screens so TTFT and throughput do
|
|
2768
2786
|
not push the action buttons or clip at the viewport edge. */
|
|
@@ -3797,6 +3815,107 @@ window.__ModuleLoader__.load({
|
|
|
3797
3815
|
};
|
|
3798
3816
|
}
|
|
3799
3817
|
//#endregion
|
|
3818
|
+
//#region src/voice-session.ts
|
|
3819
|
+
/** Screen wake-lock ownership and mobile composer focus during DSH dictation. */
|
|
3820
|
+
/** Voice phases during which the user is dictating. */
|
|
3821
|
+
const DICTATING_PHASES = [
|
|
3822
|
+
"requesting",
|
|
3823
|
+
"recording",
|
|
3824
|
+
"transcribing"
|
|
3825
|
+
];
|
|
3826
|
+
/** Whether DSH's published voice phase requires an active dictation surface. */
|
|
3827
|
+
function phaseIsDictating(phase) {
|
|
3828
|
+
return typeof phase === "string" && DICTATING_PHASES.includes(phase);
|
|
3829
|
+
}
|
|
3830
|
+
/** The wake lock API, or undefined where the browser does not offer it. */
|
|
3831
|
+
function wakeLockApi() {
|
|
3832
|
+
const api = navigator.wakeLock;
|
|
3833
|
+
return api === void 0 ? void 0 : api;
|
|
3834
|
+
}
|
|
3835
|
+
/**
|
|
3836
|
+
* Hold an available screen wake lock while DSH dictation is active and visible.
|
|
3837
|
+
* @param allowKeyboardDismissal Whether a mobile composer may lose text focus when capture starts.
|
|
3838
|
+
* @returns A disposer that releases held and subsequently returned wake locks.
|
|
3839
|
+
*/
|
|
3840
|
+
function installVoiceSession(allowKeyboardDismissal = true) {
|
|
3841
|
+
const api = wakeLockApi();
|
|
3842
|
+
if (api === void 0 && !allowKeyboardDismissal) return () => {};
|
|
3843
|
+
let sentinel = null;
|
|
3844
|
+
let pending = false;
|
|
3845
|
+
let disposed = false;
|
|
3846
|
+
let generation = 0;
|
|
3847
|
+
let lastRow = null;
|
|
3848
|
+
let lastVisible = !document.hidden;
|
|
3849
|
+
const currentRow = () => Array.from(document.querySelectorAll("[data-voice-activity]")).find((row) => phaseIsDictating(row.getAttribute("data-voice-activity"))) ?? null;
|
|
3850
|
+
const releaseLock = (lock) => {
|
|
3851
|
+
if (!lock.released) lock.release().catch((_error) => {});
|
|
3852
|
+
};
|
|
3853
|
+
const release = () => {
|
|
3854
|
+
const held = sentinel;
|
|
3855
|
+
sentinel = null;
|
|
3856
|
+
if (held !== null) releaseLock(held);
|
|
3857
|
+
};
|
|
3858
|
+
const acquireIfWanted = () => {
|
|
3859
|
+
if (api === void 0 || disposed || pending || sentinel !== null || document.hidden) return;
|
|
3860
|
+
const row = currentRow();
|
|
3861
|
+
if (row === null) return;
|
|
3862
|
+
const requestedGeneration = generation;
|
|
3863
|
+
pending = true;
|
|
3864
|
+
api.request("screen").then((lock) => {
|
|
3865
|
+
lock.addEventListener("release", () => {
|
|
3866
|
+
if (sentinel === lock) sentinel = null;
|
|
3867
|
+
});
|
|
3868
|
+
if (disposed || document.hidden || requestedGeneration !== generation || currentRow() !== row) releaseLock(lock);
|
|
3869
|
+
else if (!lock.released) sentinel = lock;
|
|
3870
|
+
}, (_error) => {}).finally(() => {
|
|
3871
|
+
pending = false;
|
|
3872
|
+
if (!disposed && requestedGeneration !== generation) acquireIfWanted();
|
|
3873
|
+
});
|
|
3874
|
+
};
|
|
3875
|
+
const dismissKeyboard = (row) => {
|
|
3876
|
+
if (!allowKeyboardDismissal) return;
|
|
3877
|
+
if (!(window.__DSH_MOBILE_NATIVE__ !== void 0 ? window.__DSH_MOBILE_KEYBOARD_STATE__?.noHardwareKeyboard === true : window.matchMedia("(pointer:coarse) and (hover:none)").matches)) return;
|
|
3878
|
+
const active = document.activeElement;
|
|
3879
|
+
const composer = row.closest("[data-composer-card]");
|
|
3880
|
+
if (active instanceof HTMLElement && composer?.contains(active) && active.closest("[data-composer-input]") !== null && (active.isContentEditable || active instanceof HTMLTextAreaElement || active instanceof HTMLInputElement)) active.blur();
|
|
3881
|
+
};
|
|
3882
|
+
const apply = () => {
|
|
3883
|
+
const row = currentRow();
|
|
3884
|
+
const visible = !document.hidden;
|
|
3885
|
+
const changed = row !== lastRow || visible !== lastVisible;
|
|
3886
|
+
if (changed) {
|
|
3887
|
+
generation++;
|
|
3888
|
+
release();
|
|
3889
|
+
if (row !== null && row !== lastRow && visible) dismissKeyboard(row);
|
|
3890
|
+
}
|
|
3891
|
+
lastRow = row;
|
|
3892
|
+
lastVisible = visible;
|
|
3893
|
+
if (changed) acquireIfWanted();
|
|
3894
|
+
};
|
|
3895
|
+
const containsVoiceRow = (node) => node instanceof Element && (node.matches("[data-voice-activity]") || node.querySelector("[data-voice-activity]") !== null);
|
|
3896
|
+
const observer = new MutationObserver((records) => {
|
|
3897
|
+
if (records.some((record) => record.type === "attributes" || [...record.addedNodes, ...record.removedNodes].some(containsVoiceRow))) apply();
|
|
3898
|
+
});
|
|
3899
|
+
observer.observe(document.documentElement, {
|
|
3900
|
+
subtree: true,
|
|
3901
|
+
childList: true,
|
|
3902
|
+
attributes: true,
|
|
3903
|
+
attributeFilter: ["data-voice-activity"]
|
|
3904
|
+
});
|
|
3905
|
+
const onVisibility = () => {
|
|
3906
|
+
apply();
|
|
3907
|
+
};
|
|
3908
|
+
document.addEventListener("visibilitychange", onVisibility);
|
|
3909
|
+
apply();
|
|
3910
|
+
return () => {
|
|
3911
|
+
disposed = true;
|
|
3912
|
+
generation++;
|
|
3913
|
+
observer.disconnect();
|
|
3914
|
+
document.removeEventListener("visibilitychange", onVisibility);
|
|
3915
|
+
release();
|
|
3916
|
+
};
|
|
3917
|
+
}
|
|
3918
|
+
//#endregion
|
|
3800
3919
|
//#region src/local-admin-host.ts
|
|
3801
3920
|
/** Browser-safe desktop-admin Host checks. Do not import Node APIs here. */
|
|
3802
3921
|
const DESKTOP_ADMIN_HEADER = "x-dsh-mobile-desktop-admin";
|
|
@@ -8769,6 +8888,7 @@ window.__ModuleLoader__.load({
|
|
|
8769
8888
|
style.dataset.plugin = "dsh-mobile";
|
|
8770
8889
|
style.textContent = desktopAdmin ? CONTROL_STYLES : NATIVE_MOBILE_STYLES;
|
|
8771
8890
|
document.head.append(style);
|
|
8891
|
+
const removeVoiceSession = installVoiceSession(!desktopAdmin);
|
|
8772
8892
|
if (!desktopAdmin) {
|
|
8773
8893
|
const removeSettingsAction = ctx.slots.inject("settings.general.item", () => {
|
|
8774
8894
|
const removeSwitchComputer = ctx.slots.register({
|
|
@@ -8795,6 +8915,7 @@ window.__ModuleLoader__.load({
|
|
|
8795
8915
|
removeSettingsAction();
|
|
8796
8916
|
removeCustom();
|
|
8797
8917
|
removeSurface();
|
|
8918
|
+
removeVoiceSession();
|
|
8798
8919
|
style.remove();
|
|
8799
8920
|
};
|
|
8800
8921
|
}
|
|
@@ -8840,6 +8961,7 @@ window.__ModuleLoader__.load({
|
|
|
8840
8961
|
});
|
|
8841
8962
|
return () => {
|
|
8842
8963
|
removeControl();
|
|
8964
|
+
removeVoiceSession();
|
|
8843
8965
|
style.remove();
|
|
8844
8966
|
};
|
|
8845
8967
|
}, "dsh-mobile: stock mobile adaptation and local control");
|