local-operator-ui 0.42.0 → 0.42.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.
Files changed (119) hide show
  1. package/out/main/index.js +552 -20
  2. package/out/preload/index.js +1 -1
  3. package/out/renderer/assets/{_basePickBy-KfApUmWE.js → _basePickBy-BA9uepHv.js} +1 -1
  4. package/out/renderer/assets/{_baseUniq-DXd1h_x3.js → _baseUniq-CVACH15m.js} +1 -1
  5. package/out/renderer/assets/{agent-details-page-D-oKoyjm.js → agent-details-page-xNTNJ7kP.js} +2 -2
  6. package/out/renderer/assets/{agent-hub-page-CMbCN_Bg.js → agent-hub-page-B-zE3Ln0.js} +2 -2
  7. package/out/renderer/assets/{agents-page-COpZu9CS.js → agents-page-BeZQ1S7f.js} +3 -3
  8. package/out/renderer/assets/approvalsOverlay-BBr6f98F.css +1 -0
  9. package/out/renderer/assets/approvalsOverlay-BmSmF8Ga.js +1 -0
  10. package/out/renderer/assets/{arc-Dim07OWx.js → arc-DYIy54Kn.js} +1 -1
  11. package/out/renderer/assets/architectureDiagram-IEHRJDOE-CmfaKw-J.js +36 -0
  12. package/out/renderer/assets/{blockDiagram-JOT3LUYC-BcLFfkMT.js → blockDiagram-JOT3LUYC-bQf90tJr.js} +2 -2
  13. package/out/renderer/assets/{book-open-C2DZijqP.js → book-open-iGajLTwQ.js} +1 -1
  14. package/out/renderer/assets/browser-page-B63Z8oE2.js +1 -0
  15. package/out/renderer/assets/browser-webauthn-prompt-DX5l4JNA.js +1 -0
  16. package/out/renderer/assets/{building-2-DfFTqKaJ.js → building-2-bjja6JTC.js} +1 -1
  17. package/out/renderer/assets/{c4Diagram-VJAJSXHY-Dm38eTOl.js → c4Diagram-VJAJSXHY-BxIFIYVW.js} +2 -2
  18. package/out/renderer/assets/channel-Blax8LQd.js +1 -0
  19. package/out/renderer/assets/{chunk-4BMEZGHF-94enK1_-.js → chunk-4BMEZGHF-C2LQ_mlD.js} +1 -1
  20. package/out/renderer/assets/{chunk-A2AXSNBT-YiigwCRa.js → chunk-A2AXSNBT-BKH53MbC.js} +1 -1
  21. package/out/renderer/assets/{chunk-AEK57VVT-Bo9PQDfg.js → chunk-AEK57VVT-CuB5dlAL.js} +1 -1
  22. package/out/renderer/assets/{chunk-D6G4REZN-vwOZoeTn.js → chunk-D6G4REZN-CECeg3Wn.js} +1 -1
  23. package/out/renderer/assets/{chunk-RZ5BOZE2-BY9NQkOq.js → chunk-RZ5BOZE2-D-zkJWYc.js} +1 -1
  24. package/out/renderer/assets/{chunk-XZIHB7SX-D31wKKrQ.js → chunk-XZIHB7SX-DstteBuH.js} +1 -1
  25. package/out/renderer/assets/classDiagram-GIVACNV2-DA1IQG_V.js +1 -0
  26. package/out/renderer/assets/classDiagram-v2-COTLJTTW-DA1IQG_V.js +1 -0
  27. package/out/renderer/assets/clone-mVVuLCMS.js +1 -0
  28. package/out/renderer/assets/{console-mirror-ClsQ7RUr.js → console-mirror-gqAdwBWl.js} +13 -13
  29. package/out/renderer/assets/consoleCapture-BQQVRcXT.js +1 -0
  30. package/out/renderer/assets/{conversation-input-sync-CxT2etWK.js → conversation-input-sync-grry80zS.js} +234 -234
  31. package/out/renderer/assets/dagre-OKDRZEBW-D6RBxeJd.js +4 -0
  32. package/out/renderer/assets/diagram-SSKATNLV--xUREIPn.js +43 -0
  33. package/out/renderer/assets/diagram-VNBRO52H-BYjZ86BM.js +24 -0
  34. package/out/renderer/assets/{erDiagram-Q7BY3M3F-B17XYgVW.js → erDiagram-Q7BY3M3F-CmajcoOO.js} +2 -2
  35. package/out/renderer/assets/error-boundary-DfTTKe65.js +126 -0
  36. package/out/renderer/assets/{flowDiagram-4HSFHLVR-BuuUG-g9.js → flowDiagram-4HSFHLVR-CtQab7ap.js} +2 -2
  37. package/out/renderer/assets/{ganttDiagram-APWFNJXF-D8R9R-AO.js → ganttDiagram-APWFNJXF-CuKez3d0.js} +2 -2
  38. package/out/renderer/assets/gitGraphDiagram-7IBYFJ6S-D9QOaWwN.js +65 -0
  39. package/out/renderer/assets/{graph-nV36Izm2.js → graph-Ccifoj7G.js} +1 -1
  40. package/out/renderer/assets/{hash-0qLX32ng.js → hash-EZ0d40pW.js} +1 -1
  41. package/out/renderer/assets/{heart-DFAcW-lm.js → heart-Bo3ZudoI.js} +1 -1
  42. package/out/renderer/assets/index-ByZv232u.css +1 -0
  43. package/out/renderer/assets/index-CLJ4-1jd.js +1 -0
  44. package/out/renderer/assets/index-DXk6NfLu.js +55 -0
  45. package/out/renderer/assets/index-Dw4hyitu.js +7 -0
  46. package/out/renderer/assets/index-LBzSehKd.js +830 -0
  47. package/out/renderer/assets/infoDiagram-PH2N3AL5-DrTRSok5.js +2 -0
  48. package/out/renderer/assets/installer-B7DhTrnG.js +1 -0
  49. package/out/renderer/assets/{journeyDiagram-U35MCT3I-BwwXu0up.js → journeyDiagram-U35MCT3I-YTjOSo-b.js} +2 -2
  50. package/out/renderer/assets/{kanban-definition-NDS4AKOZ-CDbDK3QO.js → kanban-definition-NDS4AKOZ-C1UmNEaT.js} +4 -4
  51. package/out/renderer/assets/{layout-B7RIhnQw.js → layout-CWPZ7noV.js} +1 -1
  52. package/out/renderer/assets/{legacy-agents-page-DFGXD5LW.js → legacy-agents-page-ikCownYN.js} +2 -2
  53. package/out/renderer/assets/library-page-DBSSkZvn.js +157 -0
  54. package/out/renderer/assets/{mermaid.core-DcMJPeY9.js → mermaid.core-B_nZt27J.js} +5 -5
  55. package/out/renderer/assets/mesh-page-CgjL4HIw.js +1 -0
  56. package/out/renderer/assets/messages-Bswe4yCX.js +3 -0
  57. package/out/renderer/assets/mindmap-definition-ALO5MXBD-D-Y3n0RT.js +95 -0
  58. package/out/renderer/assets/mini-BdCfujvn.js +1 -0
  59. package/out/renderer/assets/{notebook-pen-ClukfLau.js → notebook-pen-BvZPJ7Yv.js} +1 -1
  60. package/out/renderer/assets/org-access-C1u_2VVY.js +1 -0
  61. package/out/renderer/assets/{org-surface-gate-B66nUFl-.js → org-surface-gate-CyIC6H59.js} +1 -1
  62. package/out/renderer/assets/{page-header-C8bsR5wI.js → page-header-C9IFgiIB.js} +1 -1
  63. package/out/renderer/assets/{path-utils-DbnynqGJ.js → path-utils-DC6z9Ymz.js} +17 -17
  64. package/out/renderer/assets/pieDiagram-IB7DONF6-BJ2PZoWa.js +30 -0
  65. package/out/renderer/assets/{projects-page-4Cv9HMNh.js → projects-page-CwwrR-j7.js} +2 -2
  66. package/out/renderer/assets/{publication-validation-BlKeNjlY.js → publication-validation-DAffiuLy.js} +1 -1
  67. package/out/renderer/assets/{quadrantDiagram-7GDLP6J5-DFsFogdr.js → quadrantDiagram-7GDLP6J5-Dpr0N86G.js} +2 -2
  68. package/out/renderer/assets/{radar-MK3ICKWK-YGPF88zl.js → radar-MK3ICKWK-CwLLK6fK.js} +1 -1
  69. package/out/renderer/assets/radient-auth-buttons-DN7K_uGZ.js +1 -0
  70. package/out/renderer/assets/{requirementDiagram-KVF5MWMF-x2D5VXdu.js → requirementDiagram-KVF5MWMF-LI2fP6nJ.js} +2 -2
  71. package/out/renderer/assets/sankeyDiagram-QLVOVGJD-uUOWgFO1.js +10 -0
  72. package/out/renderer/assets/{schedules-page-CLrwsPcv.js → schedules-page-Cf1PQGDR.js} +2 -2
  73. package/out/renderer/assets/{sequenceDiagram-X6HHIX6F-BUX2Yk2J.js → sequenceDiagram-X6HHIX6F-DperbqVG.js} +2 -2
  74. package/out/renderer/assets/{settings-page-BAVKJQXi.js → settings-page-CrnST8YF.js} +3 -3
  75. package/out/renderer/assets/smartart-qEAWtDlk.js +1 -0
  76. package/out/renderer/assets/stateDiagram-DGXRK772-RvRbNkSX.js +1 -0
  77. package/out/renderer/assets/stateDiagram-v2-YXO3MK2T-fK1yLl-v.js +1 -0
  78. package/out/renderer/assets/{team-bridge-page-DU_d4Yfc.js → team-bridge-page-BgcLwc5M.js} +2 -2
  79. package/out/renderer/assets/{timeline-definition-BDJGKUSR-Doja7siy.js → timeline-definition-BDJGKUSR-CeQ3AsWj.js} +2 -2
  80. package/out/renderer/assets/{use-download-agent-mutation-CH4V_o78.js → use-download-agent-mutation-C_zDZ6-1.js} +2 -2
  81. package/out/renderer/assets/{use-session-snapshot-7A4rQnOH.js → use-session-snapshot-BMDB4uZ0.js} +1 -1
  82. package/out/renderer/assets/{xychartDiagram-VJFVF3MP-D2e6wZz8.js → xychartDiagram-VJFVF3MP-C6-d6maF.js} +5 -5
  83. package/out/renderer/browser-approvals-overlay.html +40 -0
  84. package/out/renderer/console-capture.html +6 -5
  85. package/out/renderer/index.html +8 -7
  86. package/out/renderer/installer.html +5 -4
  87. package/out/renderer/mini.html +8 -7
  88. package/package.json +6 -4
  89. package/out/renderer/assets/architectureDiagram-IEHRJDOE-BdwEpGi5.js +0 -36
  90. package/out/renderer/assets/browser-page-DzwNid1n.js +0 -1
  91. package/out/renderer/assets/browser-webauthn-prompt-C4aaSeT0.js +0 -1
  92. package/out/renderer/assets/channel-CefUnWw7.js +0 -1
  93. package/out/renderer/assets/classDiagram-GIVACNV2-BKByQj4B.js +0 -1
  94. package/out/renderer/assets/classDiagram-v2-COTLJTTW-BKByQj4B.js +0 -1
  95. package/out/renderer/assets/clone-DpeVXG90.js +0 -1
  96. package/out/renderer/assets/consoleCapture-DHR2J1Z2.js +0 -1
  97. package/out/renderer/assets/dagre-OKDRZEBW-DV8UoEV8.js +0 -4
  98. package/out/renderer/assets/diagram-SSKATNLV-KF8nQEWd.js +0 -43
  99. package/out/renderer/assets/diagram-VNBRO52H-P7VEv-Kl.js +0 -24
  100. package/out/renderer/assets/error-boundary-DBgLhXDJ.js +0 -126
  101. package/out/renderer/assets/gitGraphDiagram-7IBYFJ6S-fr4ArrNz.js +0 -65
  102. package/out/renderer/assets/index-BKg4FYjW.js +0 -7
  103. package/out/renderer/assets/index-BlshO0D3.css +0 -1
  104. package/out/renderer/assets/index-BmixXvR4.js +0 -1
  105. package/out/renderer/assets/index-D6Di-Q2H.js +0 -57
  106. package/out/renderer/assets/index-DQKtrmMo.js +0 -830
  107. package/out/renderer/assets/infoDiagram-PH2N3AL5-DmrijSS0.js +0 -2
  108. package/out/renderer/assets/installer-4TSvERLS.js +0 -1
  109. package/out/renderer/assets/library-page-DPid0cmw.js +0 -157
  110. package/out/renderer/assets/mesh-page-CIV9irJF.js +0 -1
  111. package/out/renderer/assets/mindmap-definition-ALO5MXBD-aLvI45Tt.js +0 -95
  112. package/out/renderer/assets/mini-leTyoKhc.js +0 -1
  113. package/out/renderer/assets/org-access-BmjQJdOO.js +0 -1
  114. package/out/renderer/assets/pieDiagram-IB7DONF6-DvzUPikw.js +0 -30
  115. package/out/renderer/assets/radient-auth-buttons-syGP58Ed.js +0 -1
  116. package/out/renderer/assets/sankeyDiagram-QLVOVGJD-DA4pKMXD.js +0 -10
  117. package/out/renderer/assets/smartart-ipuU9VIr.js +0 -1
  118. package/out/renderer/assets/stateDiagram-DGXRK772-BsVvaiaW.js +0 -1
  119. package/out/renderer/assets/stateDiagram-v2-YXO3MK2T-BvVuptXT.js +0 -1
package/out/main/index.js CHANGED
@@ -32054,6 +32054,408 @@ class ApprovalStore {
32054
32054
  );
32055
32055
  }
32056
32056
  }
32057
+ const APPROVALS_CARD_MAX_WIDTH = 352;
32058
+ const APPROVALS_CARD_MAX_HEIGHT = 480;
32059
+ const APPROVALS_CARD_MIN_HEIGHT = 96;
32060
+ const APPROVALS_CARD_INSET = 8;
32061
+ const APPROVALS_CARD_PAD = 8;
32062
+ function integer(value) {
32063
+ return Math.round(value);
32064
+ }
32065
+ function approvalsCardBoundsFor(input) {
32066
+ const pad = input.opaque === true ? 0 : APPROVALS_CARD_PAD;
32067
+ const inset = input.opaque === true ? 0 : APPROVALS_CARD_INSET;
32068
+ const content = input.contentRect;
32069
+ if (!Number.isFinite(content.x) || !Number.isFinite(content.y) || !Number.isFinite(content.width) || !Number.isFinite(content.height) || content.width <= 0 || content.height <= 0) {
32070
+ return null;
32071
+ }
32072
+ const width = Math.min(
32073
+ APPROVALS_CARD_MAX_WIDTH,
32074
+ Math.floor(content.width - 2 * pad)
32075
+ );
32076
+ if (width <= 0) return null;
32077
+ const ceiling = Math.min(
32078
+ APPROVALS_CARD_MAX_HEIGHT,
32079
+ Math.floor(content.height - 2 * pad)
32080
+ );
32081
+ if (ceiling < APPROVALS_CARD_MIN_HEIGHT) return null;
32082
+ const natural = Number.isFinite(input.naturalHeight) ? input.naturalHeight : APPROVALS_CARD_MIN_HEIGHT;
32083
+ const height = Math.min(
32084
+ ceiling,
32085
+ Math.max(APPROVALS_CARD_MIN_HEIGHT, Math.ceil(natural))
32086
+ );
32087
+ const viewWidth = width + 2 * pad;
32088
+ const viewHeight = height + 2 * pad;
32089
+ const viewX = integer(content.x + content.width - inset - width - pad);
32090
+ const viewY = integer(content.y + content.height - inset - height - pad);
32091
+ const view = {
32092
+ x: viewX,
32093
+ y: viewY,
32094
+ width: viewWidth,
32095
+ height: viewHeight
32096
+ };
32097
+ if (view.x < content.x || view.y < content.y || view.x + view.width > content.x + content.width || view.y + view.height > content.y + content.height) {
32098
+ return null;
32099
+ }
32100
+ return {
32101
+ view,
32102
+ card: {
32103
+ x: view.x + pad,
32104
+ y: view.y + pad,
32105
+ width,
32106
+ height
32107
+ },
32108
+ width,
32109
+ height,
32110
+ pad
32111
+ };
32112
+ }
32113
+ const APPROVALS_OVERLAY_S6A_ENV = "LOCAL_OPERATOR_UI_BROWSER_APPROVALS_OVERLAY_S6A";
32114
+ const TRANSPARENT = "#00000000";
32115
+ const OPAQUE = "#1b1f24";
32116
+ function approvalsOverlayEnabled(env) {
32117
+ return env[APPROVALS_OVERLAY_S6A_ENV] === "1";
32118
+ }
32119
+ function approvalsExpiryDelay(entries, now = Date.now()) {
32120
+ if (entries.length === 0) return null;
32121
+ return Math.max(
32122
+ 0,
32123
+ Math.min(...entries.map((entry) => entry.expiresAt)) - now
32124
+ );
32125
+ }
32126
+ function approvalsDocumentUrl(documentUrl, count, theme, opaque) {
32127
+ try {
32128
+ const url = new URL(documentUrl);
32129
+ if (count > 0) url.searchParams.set("count", String(count));
32130
+ url.searchParams.set("theme", theme);
32131
+ if (opaque) url.searchParams.set("opaque", "1");
32132
+ return url.toString();
32133
+ } catch {
32134
+ return documentUrl;
32135
+ }
32136
+ }
32137
+ class ApprovalsOverlayController {
32138
+ window;
32139
+ documentUrl;
32140
+ opaque;
32141
+ theme;
32142
+ log;
32143
+ view;
32144
+ childListeners;
32145
+ pending;
32146
+ ready;
32147
+ visible;
32148
+ failedReason;
32149
+ disposed;
32150
+ naturalHeight;
32151
+ layout;
32152
+ bounds;
32153
+ constructor(deps) {
32154
+ this.window = deps.window;
32155
+ this.documentUrl = deps.documentUrl;
32156
+ this.opaque = deps.opaque === true;
32157
+ this.theme = deps.theme ?? "dark";
32158
+ this.log = deps.log ?? (() => {
32159
+ });
32160
+ this.view = null;
32161
+ this.childListeners = [];
32162
+ this.pending = 0;
32163
+ this.ready = false;
32164
+ this.visible = false;
32165
+ this.failedReason = null;
32166
+ this.disposed = false;
32167
+ this.naturalHeight = APPROVALS_CARD_MIN_HEIGHT;
32168
+ this.layout = {
32169
+ presented: false,
32170
+ contentRect: null,
32171
+ revision: 0
32172
+ };
32173
+ this.bounds = null;
32174
+ this.ensureChild();
32175
+ }
32176
+ /** The live queue's count. Zero hides; a positive count auto-presents. */
32177
+ setPending(count) {
32178
+ if (this.disposed) return;
32179
+ this.pending = Math.max(0, Math.floor(Number.isFinite(count) ? count : 0));
32180
+ if (this.pending === 0) {
32181
+ this.hide();
32182
+ return;
32183
+ }
32184
+ this.updateCount();
32185
+ this.maybeShow();
32186
+ }
32187
+ /** The registry's copied layout snapshot, after every page layout pass. */
32188
+ onLayout(snapshot2) {
32189
+ if (this.disposed) return;
32190
+ this.layout = {
32191
+ presented: snapshot2.presented,
32192
+ contentRect: snapshot2.contentRect ? { ...snapshot2.contentRect } : null,
32193
+ revision: snapshot2.revision
32194
+ };
32195
+ if (!snapshot2.presented || !snapshot2.contentRect) {
32196
+ this.hide();
32197
+ return;
32198
+ }
32199
+ if (this.pending > 0) this.maybeShow();
32200
+ }
32201
+ facts() {
32202
+ const view = this.view;
32203
+ const children = this.window.isDestroyed() ? [] : this.window.contentView.children;
32204
+ const index = view ? children.indexOf(view) : -1;
32205
+ let focused = null;
32206
+ try {
32207
+ focused = electron.webContents.getFocusedWebContents()?.id ?? null;
32208
+ } catch {
32209
+ focused = null;
32210
+ }
32211
+ return {
32212
+ pending: this.pending,
32213
+ presented: this.layout.presented,
32214
+ contentRect: this.layout.contentRect,
32215
+ ready: this.ready,
32216
+ visible: this.visible,
32217
+ failedReason: this.failedReason,
32218
+ bounds: this.bounds,
32219
+ childIndex: index,
32220
+ childCount: children.length,
32221
+ childWebContentsId: view ? view.webContents.id : null,
32222
+ focusedWebContentsId: focused,
32223
+ documentUrl: this.documentUrl,
32224
+ opaque: this.opaque
32225
+ };
32226
+ }
32227
+ dispose(reason = "dispose") {
32228
+ if (this.disposed) return;
32229
+ this.disposed = true;
32230
+ this.visible = false;
32231
+ this.ready = false;
32232
+ this.releaseView(reason);
32233
+ }
32234
+ ensureChild() {
32235
+ if (this.view || this.failedReason !== null || this.disposed) return;
32236
+ this.createChild();
32237
+ }
32238
+ maybeShow() {
32239
+ if (this.disposed || this.failedReason !== null || this.pending <= 0 || !this.layout.presented || !this.layout.contentRect) {
32240
+ this.hide();
32241
+ return;
32242
+ }
32243
+ this.ensureChild();
32244
+ if (!this.view || !this.ready) return;
32245
+ this.applyBounds();
32246
+ }
32247
+ applyBounds() {
32248
+ const view = this.view;
32249
+ if (!view || !this.layout.contentRect) return;
32250
+ const bounds = approvalsCardBoundsFor({
32251
+ contentRect: this.layout.contentRect,
32252
+ naturalHeight: this.naturalHeight,
32253
+ opaque: this.opaque
32254
+ });
32255
+ this.bounds = bounds;
32256
+ if (!bounds) {
32257
+ this.hide();
32258
+ return;
32259
+ }
32260
+ try {
32261
+ const current = view.getBounds();
32262
+ if (current.width !== bounds.view.width || current.height !== bounds.view.height) {
32263
+ this.rebuildAt(bounds);
32264
+ return;
32265
+ }
32266
+ view.setBounds(bounds.view);
32267
+ const children = this.window.contentView.children;
32268
+ if (children[children.length - 1] !== view) {
32269
+ this.window.contentView.addChildView(view);
32270
+ }
32271
+ view.setVisible(true);
32272
+ this.visible = true;
32273
+ } catch (error) {
32274
+ this.fail(`bounds_apply_failed:${String(error)}`);
32275
+ }
32276
+ }
32277
+ rebuildAt(bounds) {
32278
+ this.releaseView("resize");
32279
+ this.visible = false;
32280
+ this.ready = false;
32281
+ this.bounds = bounds;
32282
+ this.createChild();
32283
+ const view = this.view;
32284
+ if (!view) return;
32285
+ view.setBounds(bounds.view);
32286
+ view.setVisible(true);
32287
+ this.visible = true;
32288
+ }
32289
+ releaseView(reason) {
32290
+ const view = this.view;
32291
+ this.view = null;
32292
+ for (const remove of this.childListeners.splice(0)) remove();
32293
+ if (!view) return;
32294
+ try {
32295
+ if (!view.webContents.isDestroyed()) view.webContents.close();
32296
+ } catch {
32297
+ }
32298
+ try {
32299
+ this.window.contentView.removeChildView(view);
32300
+ } catch {
32301
+ }
32302
+ this.log(`[browser] approvals overlay child released: ${reason}`);
32303
+ }
32304
+ createChild() {
32305
+ let view;
32306
+ try {
32307
+ const partition = `approvals-overlay-${node_crypto.randomUUID()}`;
32308
+ const childSession = electron.session.fromPartition(partition);
32309
+ childSession.setPermissionRequestHandler(
32310
+ (_contents, _permission, callback) => callback(false)
32311
+ );
32312
+ childSession.setPermissionCheckHandler(() => false);
32313
+ childSession.on("will-download", (event) => {
32314
+ event.preventDefault();
32315
+ });
32316
+ view = new electron.WebContentsView({
32317
+ webPreferences: {
32318
+ partition,
32319
+ sandbox: true,
32320
+ contextIsolation: true,
32321
+ nodeIntegration: false,
32322
+ webSecurity: true,
32323
+ allowRunningInsecureContent: false,
32324
+ // The document's own module measures itself and paints the count;
32325
+ // there is still no preload, no exposed IPC and no focus path.
32326
+ javascript: true,
32327
+ backgroundThrottling: false
32328
+ }
32329
+ });
32330
+ view.webContents.setWindowOpenHandler(() => ({ action: "deny" }));
32331
+ const allow = approvalsDocumentUrl(
32332
+ this.documentUrl,
32333
+ this.pending,
32334
+ this.theme,
32335
+ this.opaque
32336
+ );
32337
+ const base = (() => {
32338
+ try {
32339
+ const url = new URL(allow);
32340
+ url.search = "";
32341
+ return url.toString();
32342
+ } catch {
32343
+ return allow;
32344
+ }
32345
+ })();
32346
+ view.webContents.on("will-navigate", (event, url) => {
32347
+ const target2 = url.split("?")[0];
32348
+ if (target2 !== base) event.preventDefault();
32349
+ });
32350
+ view.webContents.on("will-redirect", (event, url) => {
32351
+ const target2 = url.split("?")[0];
32352
+ if (target2 !== base) event.preventDefault();
32353
+ });
32354
+ view.setBackgroundColor(this.opaque ? OPAQUE : TRANSPARENT);
32355
+ this.window.contentView.addChildView(view);
32356
+ const initial = this.bounds?.view ?? {
32357
+ x: 0,
32358
+ y: 0,
32359
+ width: 0,
32360
+ height: 0
32361
+ };
32362
+ view.setBounds(initial);
32363
+ view.setVisible(this.bounds !== null);
32364
+ this.view = view;
32365
+ this.ready = false;
32366
+ const onFinish = () => {
32367
+ this.ready = true;
32368
+ this.measureAndShow();
32369
+ };
32370
+ const onFail = (_event, code, description) => {
32371
+ this.fail(`load_failed:${code}:${description}`);
32372
+ };
32373
+ view.webContents.on("did-finish-load", onFinish);
32374
+ view.webContents.on("did-fail-load", onFail);
32375
+ this.childListeners.push(
32376
+ () => view.webContents.removeListener("did-finish-load", onFinish)
32377
+ );
32378
+ this.childListeners.push(
32379
+ () => view.webContents.removeListener("did-fail-load", onFail)
32380
+ );
32381
+ void view.webContents.loadURL(allow).catch((error) => {
32382
+ this.fail(`load_rejected:${String(error)}`);
32383
+ });
32384
+ } catch (error) {
32385
+ this.fail(`child_create_failed:${String(error)}`);
32386
+ return;
32387
+ }
32388
+ }
32389
+ measureAndShow() {
32390
+ const view = this.view;
32391
+ if (!view || view.webContents.isDestroyed()) return;
32392
+ if (view.getBounds().width <= 0) {
32393
+ this.updateCount();
32394
+ this.maybeShow();
32395
+ return;
32396
+ }
32397
+ const measured = view.webContents.executeJavaScript(
32398
+ `new Promise((resolve) => {
32399
+ const read = () => {
32400
+ const el = document.getElementById('approvals-card');
32401
+ if (!el) { resolve(0); return; }
32402
+ /*
32403
+ * Read the UNCLAMPED height. The card's own max-height is the
32404
+ * viewport minus its insets, so measuring the clamped box would
32405
+ * return the provisional 96 DIP view's ceiling forever: a
32406
+ * circular size that never reaches the card's real height.
32407
+ */
32408
+ const previous = el.style.maxHeight;
32409
+ el.style.maxHeight = 'none';
32410
+ const height = el.getBoundingClientRect().height;
32411
+ el.style.maxHeight = previous;
32412
+ resolve(height);
32413
+ };
32414
+ if (document.readyState === 'complete') read();
32415
+ else addEventListener('load', read, { once: true });
32416
+ })`
32417
+ );
32418
+ const timer = new Promise((resolve) => {
32419
+ setTimeout(() => resolve(0), 1500);
32420
+ });
32421
+ void Promise.race([measured, timer]).then((height) => {
32422
+ if (this.view !== view) return;
32423
+ if (typeof height === "number" && Number.isFinite(height) && height > 0) {
32424
+ this.naturalHeight = height;
32425
+ }
32426
+ this.maybeShow();
32427
+ }).catch((error) => {
32428
+ if (this.view !== view) return;
32429
+ this.fail(`measure_failed:${String(error)}`);
32430
+ });
32431
+ this.updateCount();
32432
+ this.maybeShow();
32433
+ }
32434
+ updateCount() {
32435
+ const view = this.view;
32436
+ if (!view || view.webContents.isDestroyed()) return;
32437
+ void view.webContents.executeJavaScript(
32438
+ `(() => { window.__approvalsCard?.setCount(${this.pending}); })()`
32439
+ ).catch(() => {
32440
+ });
32441
+ }
32442
+ hide() {
32443
+ if (this.view) {
32444
+ try {
32445
+ this.view.setVisible(false);
32446
+ } catch {
32447
+ }
32448
+ }
32449
+ this.visible = false;
32450
+ }
32451
+ fail(reason) {
32452
+ if (this.failedReason !== null) return;
32453
+ this.failedReason = reason;
32454
+ this.hide();
32455
+ this.dispose("failed");
32456
+ this.log(`[browser] approvals overlay latched off: ${reason}`);
32457
+ }
32458
+ }
32057
32459
  function browserWindowForeground(window) {
32058
32460
  return !window.isDestroyed() && window.isVisible() && window.isFocused();
32059
32461
  }
@@ -35925,7 +36327,9 @@ const enUiBrowser = {
35925
36327
  "ui.browser.page_context_menu.cut": "Cut",
35926
36328
  "ui.browser.page_context_menu.open_link_in_new_tab": "Open link in new tab",
35927
36329
  "ui.browser.page_context_menu.paste": "Paste",
36330
+ "ui.browser.page_context_menu.redo": "Redo",
35928
36331
  "ui.browser.page_context_menu.select_all": "Select all",
36332
+ "ui.browser.page_context_menu.undo": "Undo",
35929
36333
  "ui.browser.use_browser_chrome.downloads_folder_failed": "Could not open the downloads folder. {message}",
35930
36334
  "ui.browser.use_consent_attention_lifetime.that_request_is_no_longer_waiting": "That request is no longer waiting.",
35931
36335
  "ui.browser.webauthn_chooser.a_site": "A site",
@@ -37217,6 +37621,7 @@ const enUiLibrary = {
37217
37621
  "ui.library.page.loaded_count": "{loaded} of {total} assets",
37218
37622
  "ui.library.page.preview": "Asset preview",
37219
37623
  "ui.library.page.results": "Library results",
37624
+ "ui.library.page.resize_preview": "Resize details drawer. Double-click to reset.",
37220
37625
  "ui.library.preview.unavailable": "This asset isn't available",
37221
37626
  "ui.library.preview.unavailable_detail": "It may no longer be in the catalog.",
37222
37627
  "ui.library.preview.pptx_preparing": "Preparing presentation…",
@@ -39720,6 +40125,8 @@ const esUiBrowser = {
39720
40125
  "ui.browser.page_context_menu.copy": "Copiar",
39721
40126
  "ui.browser.page_context_menu.paste": "Pegar",
39722
40127
  "ui.browser.page_context_menu.select_all": "Seleccionar todo",
40128
+ "ui.browser.page_context_menu.redo": "Rehacer",
40129
+ "ui.browser.page_context_menu.undo": "Deshacer",
39723
40130
  "ui.browser.page_context_menu.copy_page_address": "Copiar dirección de la página",
39724
40131
  "ui.browser.browser_url_bar.home": "Inicio",
39725
40132
  "ui.browser.browser_url_bar.site_secure": "Conexión segura con {origin}",
@@ -40886,6 +41293,7 @@ const esUiLibrary = {
40886
41293
  "ui.library.page.loaded_count": "{loaded} de {total} recursos",
40887
41294
  "ui.library.page.preview": "Vista previa del recurso",
40888
41295
  "ui.library.page.results": "Resultados de la Biblioteca",
41296
+ "ui.library.page.resize_preview": "Cambiar el tamaño del panel de detalles. Doble clic para restablecer.",
40889
41297
  "ui.library.preview.unavailable": "Este recurso no está disponible",
40890
41298
  "ui.library.preview.unavailable_detail": "Puede que ya no esté en el catálogo.",
40891
41299
  "ui.library.preview.pptx_preparing": "Preparando la presentación…",
@@ -43389,6 +43797,8 @@ const frUiBrowser = {
43389
43797
  "ui.browser.page_context_menu.copy": "Copier",
43390
43798
  "ui.browser.page_context_menu.paste": "Coller",
43391
43799
  "ui.browser.page_context_menu.select_all": "Tout sélectionner",
43800
+ "ui.browser.page_context_menu.redo": "Rétablir",
43801
+ "ui.browser.page_context_menu.undo": "Annuler",
43392
43802
  "ui.browser.page_context_menu.copy_page_address": "Copier l’adresse de la page",
43393
43803
  "ui.browser.browser_url_bar.home": "Accueil",
43394
43804
  "ui.browser.browser_url_bar.site_secure": "Connexion sécurisée à {origin}",
@@ -44555,6 +44965,7 @@ const frUiLibrary = {
44555
44965
  "ui.library.page.loaded_count": "{loaded} éléments sur {total}",
44556
44966
  "ui.library.page.preview": "Aperçu de l’élément",
44557
44967
  "ui.library.page.results": "Résultats de la Bibliothèque",
44968
+ "ui.library.page.resize_preview": "Redimensionner le panneau de détails. Double-cliquer pour réinitialiser.",
44558
44969
  "ui.library.preview.unavailable": "Cet élément n’est pas disponible",
44559
44970
  "ui.library.preview.unavailable_detail": "Il n’est peut-être plus dans le catalogue.",
44560
44971
  "ui.library.preview.pptx_preparing": "Préparation de la présentation…",
@@ -47085,6 +47496,8 @@ const hiUiBrowser = {
47085
47496
  "ui.browser.page_context_menu.open_link_in_new_tab": "लिंक नए टैब में खोलें",
47086
47497
  "ui.browser.page_context_menu.paste": "पेस्ट करें",
47087
47498
  "ui.browser.page_context_menu.select_all": "सभी चुनें",
47499
+ "ui.browser.page_context_menu.redo": "फिर से करें",
47500
+ "ui.browser.page_context_menu.undo": "पूर्ववत करें",
47088
47501
  "ui.browser.use_browser_chrome.downloads_folder_failed": "डाउनलोड फ़ोल्डर नहीं खुल सका। {message}",
47089
47502
  "ui.browser.use_consent_attention_lifetime.that_request_is_no_longer_waiting": "वह अनुरोध अब इंतज़ार में नहीं है।",
47090
47503
  "ui.browser.webauthn_chooser.a_site": "एक साइट",
@@ -48193,6 +48606,7 @@ const hiUiLibrary = {
48193
48606
  "ui.library.page.loaded_count": "{loaded} एसेट कुल {total} में से",
48194
48607
  "ui.library.page.preview": "एसेट का प्रीव्यू",
48195
48608
  "ui.library.page.results": "लाइब्रेरी के नतीजे",
48609
+ "ui.library.page.resize_preview": "विवरण ड्रॉअर का आकार बदलें। रीसेट करने के लिए दो बार क्लिक करें।",
48196
48610
  "ui.library.preview.unavailable": "यह एसेट उपलब्ध नहीं है",
48197
48611
  "ui.library.preview.unavailable_detail": "हो सकता है यह अब कैटलॉग में न हो।",
48198
48612
  "ui.library.preview.pptx_preparing": "प्रस्तुति तैयार हो रही है…",
@@ -50712,6 +51126,8 @@ const ruUiBrowser = {
50712
51126
  "ui.browser.page_context_menu.open_link_in_new_tab": "Открыть ссылку в новой вкладке",
50713
51127
  "ui.browser.page_context_menu.paste": "Вставить",
50714
51128
  "ui.browser.page_context_menu.select_all": "Выделить всё",
51129
+ "ui.browser.page_context_menu.redo": "Повторить",
51130
+ "ui.browser.page_context_menu.undo": "Отменить",
50715
51131
  "ui.browser.use_browser_chrome.downloads_folder_failed": "Не удалось открыть папку загрузок. {message}",
50716
51132
  "ui.browser.use_consent_attention_lifetime.that_request_is_no_longer_waiting": "Этот запрос больше не ожидает.",
50717
51133
  "ui.browser.webauthn_chooser.a_site": "Сайт",
@@ -51840,6 +52256,7 @@ const ruUiLibrary = {
51840
52256
  "ui.library.page.loaded_count": "Файлы: {loaded} из {total}",
51841
52257
  "ui.library.page.preview": "Предпросмотр файла",
51842
52258
  "ui.library.page.results": "Результаты Библиотеки",
52259
+ "ui.library.page.resize_preview": "Изменить ширину панели сведений. Дважды щёлкните, чтобы сбросить её.",
51843
52260
  "ui.library.preview.unavailable": "Этот файл недоступен",
51844
52261
  "ui.library.preview.unavailable_detail": "Возможно, его больше нет в каталоге.",
51845
52262
  "ui.library.preview.pptx_preparing": "Подготовка презентации…",
@@ -54359,6 +54776,8 @@ const urUiBrowser = {
54359
54776
  "ui.browser.page_context_menu.open_link_in_new_tab": "لنک نئے ٹیب میں کھولیں",
54360
54777
  "ui.browser.page_context_menu.paste": "چسپاں کریں",
54361
54778
  "ui.browser.page_context_menu.select_all": "سب منتخب کریں",
54779
+ "ui.browser.page_context_menu.redo": "دوبارہ کریں",
54780
+ "ui.browser.page_context_menu.undo": "کالعدم کریں",
54362
54781
  "ui.browser.use_browser_chrome.downloads_folder_failed": "ڈاؤن لوڈ فولڈر نہیں کھل سکا۔ {message}",
54363
54782
  "ui.browser.use_consent_attention_lifetime.that_request_is_no_longer_waiting": "وہ درخواست اب منتظر نہیں ہے۔",
54364
54783
  "ui.browser.webauthn_chooser.a_site": "ایک سائٹ",
@@ -55487,6 +55906,7 @@ const urUiLibrary = {
55487
55906
  "ui.library.page.loaded_count": "{total} اثاثوں میں سے {loaded}",
55488
55907
  "ui.library.page.preview": "اثاثے کا پیش منظر",
55489
55908
  "ui.library.page.results": "لائبریری کے نتائج",
55909
+ "ui.library.page.resize_preview": "تفصیلات کے پینل کی چوڑائی بدلیں۔ ڈبل کلک کر کے ری سیٹ کریں۔",
55490
55910
  "ui.library.preview.unavailable": "یہ اثاثہ دستیاب نہیں",
55491
55911
  "ui.library.preview.unavailable_detail": "ممکن ہے اب یہ کیٹلاگ میں نہ ہو۔",
55492
55912
  "ui.library.preview.pptx_preparing": "پریزنٹیشن تیار ہو رہی ہے…",
@@ -58006,6 +58426,8 @@ const viUiBrowser = {
58006
58426
  "ui.browser.page_context_menu.open_link_in_new_tab": "Mở liên kết trong tab mới",
58007
58427
  "ui.browser.page_context_menu.paste": "Dán",
58008
58428
  "ui.browser.page_context_menu.select_all": "Chọn tất cả",
58429
+ "ui.browser.page_context_menu.redo": "Làm lại",
58430
+ "ui.browser.page_context_menu.undo": "Hoàn tác",
58009
58431
  "ui.browser.use_browser_chrome.downloads_folder_failed": "Không thể mở thư mục tải xuống. {message}",
58010
58432
  "ui.browser.use_consent_attention_lifetime.that_request_is_no_longer_waiting": "Yêu cầu đó không còn chờ xử lý.",
58011
58433
  "ui.browser.webauthn_chooser.a_site": "Một trang web",
@@ -59134,6 +59556,7 @@ const viUiLibrary = {
59134
59556
  "ui.library.page.loaded_count": "{loaded}/{total} tệp",
59135
59557
  "ui.library.page.preview": "Xem trước tệp",
59136
59558
  "ui.library.page.results": "Kết quả Thư viện",
59559
+ "ui.library.page.resize_preview": "Điều chỉnh kích thước ngăn chi tiết. Nhấp đúp để đặt lại.",
59137
59560
  "ui.library.preview.unavailable": "Tệp này không khả dụng",
59138
59561
  "ui.library.preview.unavailable_detail": "Có thể tệp không còn trong thư viện.",
59139
59562
  "ui.library.preview.pptx_preparing": "Đang chuẩn bị bản trình bày…",
@@ -61462,6 +61885,8 @@ const zhCNUiBrowser = {
61462
61885
  "ui.browser.page_context_menu.open_link_in_new_tab": "在新标签页中打开链接",
61463
61886
  "ui.browser.page_context_menu.paste": "粘贴",
61464
61887
  "ui.browser.page_context_menu.select_all": "全选",
61888
+ "ui.browser.page_context_menu.redo": "重做",
61889
+ "ui.browser.page_context_menu.undo": "撤销",
61465
61890
  "ui.browser.use_browser_chrome.downloads_folder_failed": "无法打开下载文件夹。{message}",
61466
61891
  "ui.browser.use_consent_attention_lifetime.that_request_is_no_longer_waiting": "此请求已不再等待处理。",
61467
61892
  "ui.browser.webauthn_chooser.a_site": "某个网站",
@@ -62601,6 +63026,7 @@ const zhCNUiLibrary = {
62601
63026
  "ui.library.page.loaded_count": "{loaded}/{total}个资源",
62602
63027
  "ui.library.page.preview": "资源预览",
62603
63028
  "ui.library.page.results": "资源库结果",
63029
+ "ui.library.page.resize_preview": "调整详情抽屉宽度。双击可重置。",
62604
63030
  "ui.library.preview.unavailable": "此资源不可用",
62605
63031
  "ui.library.preview.unavailable_detail": "该资源可能已不在目录中。",
62606
63032
  "ui.library.preview.pptx_preparing": "正在准备演示文稿……",
@@ -67225,7 +67651,12 @@ class TabRegistry {
67225
67651
  * reads `visible` alone, so a state page never makes a native view
67226
67652
  * "presented"; and every report overwrites it, so a reason cannot outlive the
67227
67653
  * hide it described. */
67228
- ownStatePage = false;
67654
+ /** Why the view is hidden for the KEYBOARD: true only while the browser's own
67655
+ * state page is the reason, cleared when an overlay also hides it. */
67656
+ ownPageReason = false;
67657
+ /** The browser's own content state (start page, failure), independent of any
67658
+ * overlay also hiding the view. Controls are refused on it. */
67659
+ ownStateContent = false;
67229
67660
  contentRect = null;
67230
67661
  /** Tabs with a command in flight, keyed by tabId. See `lane`. */
67231
67662
  busy = /* @__PURE__ */ new Set();
@@ -67340,7 +67771,7 @@ class TabRegistry {
67340
67771
  * `browserChromeOwnsChord` is untouched: this says whose keys they are, never
67341
67772
  * that the window is foreground. */
67342
67773
  get chromeVisible() {
67343
- return this.contentRect !== null && (this.visible || this.ownStatePage);
67774
+ return this.contentRect !== null && (this.visible || this.ownPageReason);
67344
67775
  }
67345
67776
  get activeTab() {
67346
67777
  return this.activeTabId === null ? null : this.tabs.get(this.activeTabId) ?? null;
@@ -67530,11 +67961,28 @@ class TabRegistry {
67530
67961
  * still the browser, and `chromeVisible` keeps its shortcuts. Normalised
67531
67962
  * against `visible` so the invariant held is "a reason only exists while the
67532
67963
  * view is hidden", never two facts that disagree. */
67533
- setViewVisible(visible, ownPage = false) {
67964
+ setViewVisible(visible, ownPage = false, ownStatePage = ownPage) {
67534
67965
  this.visible = visible;
67535
- this.ownStatePage = !visible && ownPage;
67966
+ this.ownPageReason = !visible && ownPage;
67967
+ this.ownStateContent = !visible && ownStatePage;
67536
67968
  this.applyLayout();
67537
67969
  }
67970
+ /**
67971
+ * Whether an APP OVERLAY (menu, dialog, picker) is what hides this tab's view.
67972
+ *
67973
+ * The page is still the active, laid-out tab - our own chrome asked the view to
67974
+ * stand down so a DOM panel could be seen - and the difference matters to
67975
+ * `controlPage`: Find/Print/Reset zoom are chrome-initiated commands on the
67976
+ * page, and "hidden so our menu is visible" must not read as "this tab is
67977
+ * gone" (QA Q2-F1). A route teardown drops `contentRect` and an own-state page
67978
+ * (start/failure) sets `ownStateContent`, so neither qualifies — and it stays
67979
+ * set while an overlay hides the same page (QA Q3-1).
67980
+ */
67981
+ hiddenByOverlay(tabId) {
67982
+ const record = this.tabs.get(tabId);
67983
+ if (!record || record.tabId !== this.activeTabId) return false;
67984
+ return this.contentRect !== null && !this.visible && !this.ownStateContent;
67985
+ }
67538
67986
  activate(tabId) {
67539
67987
  if (!this.tabs.has(tabId)) return;
67540
67988
  this.activeTabId = tabId;
@@ -68694,9 +69142,10 @@ const PAGE_ZOOM_STEPS = [
68694
69142
  ];
68695
69143
  const PRINT_CANCELLED = /cancel/i;
68696
69144
  class PageControls {
68697
- constructor(changed, resultTimeoutMs = 5e3) {
69145
+ constructor(changed, resultTimeoutMs = 5e3, hiddenByOverlay = () => false) {
68698
69146
  this.changed = changed;
68699
69147
  this.resultTimeoutMs = resultTimeoutMs;
69148
+ this.hiddenByOverlay = hiddenByOverlay;
68700
69149
  }
68701
69150
  find = null;
68702
69151
  record = null;
@@ -68706,17 +69155,21 @@ class PageControls {
68706
69155
  notice = null;
68707
69156
  noticeTabId = null;
68708
69157
  timer = null;
69158
+ /** A presented page, or the same page waiting under an app overlay. */
69159
+ shown(active) {
69160
+ return active.presented || this.hiddenByOverlay(active.tabId);
69161
+ }
68709
69162
  stopTimer() {
68710
69163
  if (this.timer) clearTimeout(this.timer);
68711
69164
  this.timer = null;
68712
69165
  }
68713
69166
  reconcile(active) {
68714
- if (this.record && (active !== this.record || !active.presented || active.documentEpoch !== this.epoch || active.view.webContents.isDestroyed()))
69167
+ if (this.record && (active !== this.record || !this.shown(active) || active.documentEpoch !== this.epoch || active.view.webContents.isDestroyed()))
68715
69168
  this.clear();
68716
69169
  }
68717
69170
  state(active) {
68718
69171
  this.reconcile(active);
68719
- if (active?.tabId !== this.noticeTabId || !active?.presented)
69172
+ if (active?.tabId !== this.noticeTabId || !active || !this.shown(active))
68720
69173
  this.notice = null;
68721
69174
  return {
68722
69175
  find: this.find ? { ...this.find } : null,
@@ -68740,7 +69193,7 @@ class PageControls {
68740
69193
  }
68741
69194
  open(active) {
68742
69195
  this.reconcile(active);
68743
- if (!active.presented) return;
69196
+ if (!this.shown(active)) return;
68744
69197
  if (this.record === active) return;
68745
69198
  this.clear();
68746
69199
  this.record = active;
@@ -68754,7 +69207,7 @@ class PageControls {
68754
69207
  unreported: false
68755
69208
  };
68756
69209
  this.listener = (_event, result) => {
68757
- if (this.record !== active || !active.presented || active.documentEpoch !== this.epoch || result.requestId !== this.requestId || !this.find)
69210
+ if (this.record !== active || !this.shown(active) || active.documentEpoch !== this.epoch || result.requestId !== this.requestId || !this.find)
68758
69211
  return;
68759
69212
  if (result.finalUpdate !== false) this.stopTimer();
68760
69213
  this.find = {
@@ -68796,7 +69249,7 @@ class PageControls {
68796
69249
  const request = this.requestId;
68797
69250
  this.timer = setTimeout(() => {
68798
69251
  this.timer = null;
68799
- if (this.record !== active || !active.presented || active.documentEpoch !== this.epoch || this.requestId !== request || !this.find)
69252
+ if (this.record !== active || !this.shown(active) || active.documentEpoch !== this.epoch || this.requestId !== request || !this.find)
68800
69253
  return;
68801
69254
  this.requestId = null;
68802
69255
  if (active.view.webContents.isDestroyed()) {
@@ -68842,7 +69295,7 @@ class PageControls {
68842
69295
  * (cancelled is the person changing their mind, not a failure) only
68843
69296
  * surfaces through `notice` when Electron names a real reason. */
68844
69297
  print(active) {
68845
- if (!active.presented) return;
69298
+ if (!this.shown(active)) return;
68846
69299
  const wc = active.view.webContents;
68847
69300
  if (wc.isDestroyed() || !wc.print) {
68848
69301
  this.notice = "Printing is not available for this page";
@@ -69018,6 +69471,10 @@ function withTimeout(work, ms) {
69018
69471
  function isReportableLoadFailure(code) {
69019
69472
  return code !== 0 && code !== -3;
69020
69473
  }
69474
+ function isSupersededRestore(error) {
69475
+ const message = error instanceof Error ? error.message : String(error);
69476
+ return message.includes("ERR_ABORTED (-3)");
69477
+ }
69021
69478
  function sessionRequesterOf(requester) {
69022
69479
  if (!requester.startsWith("session:")) return null;
69023
69480
  const id2 = requester.slice("session:".length);
@@ -69076,7 +69533,11 @@ class BrowserHost {
69076
69533
  hydration = Promise.resolve();
69077
69534
  constructor(options) {
69078
69535
  this.registry = options.registry;
69079
- this.pageControls = new PageControls(() => this.onChanged());
69536
+ this.pageControls = new PageControls(
69537
+ () => this.onChanged(),
69538
+ 5e3,
69539
+ (tabId) => this.registry.hiddenByOverlay(tabId)
69540
+ );
69080
69541
  this.cdp = options.cdp;
69081
69542
  this.approvals = options.approvals;
69082
69543
  this.ownership = options.ownership;
@@ -69611,7 +70072,7 @@ class BrowserHost {
69611
70072
  async controlPage(tabId, action, query2 = "", forward = true, next = false) {
69612
70073
  return this.registry.lane(tabId, async () => {
69613
70074
  const active = this.registry.activeTab;
69614
- if (!active || active.tabId !== tabId || !active.presented || active.view.webContents.isDestroyed())
70075
+ if (!active || active.tabId !== tabId || !active.presented && !this.registry.hiddenByOverlay(tabId) || active.view.webContents.isDestroyed())
69615
70076
  throw new Error("The browser tab is no longer presented.");
69616
70077
  if (action === "open") this.pageControls.open(active);
69617
70078
  else if (action === "print") this.pageControls.print(active);
@@ -69910,7 +70371,7 @@ class BrowserHost {
69910
70371
  if (started) await withTimeout(started, RESTORE_TAB_TIMEOUT_MS);
69911
70372
  } catch (error) {
69912
70373
  this.log(`[browser] could not restore tab ${tabId}: ${String(error)}`);
69913
- if (!committed && !this.loadFailures.has(tabId) && this.registry.get(tabId) && !contents.isDestroyed()) {
70374
+ if (!committed && !isSupersededRestore(error) && !this.loadFailures.has(tabId) && this.registry.get(tabId) && !contents.isDestroyed()) {
69914
70375
  const entry = recorded.entries[recorded.activeIndex];
69915
70376
  this.recordLoadFailure(tabId, {
69916
70377
  code: -2,
@@ -70141,8 +70602,8 @@ class BrowserHost {
70141
70602
  * main tell the browser's own state pages (start page, load failure - hidden so
70142
70603
  * their DOM can paint) from an overlay covering them. Shortcut ownership keys
70143
70604
  * on it; presentation does not. See `TabRegistry.chromeVisible`. */
70144
- setViewVisible(visible, ownPage = false) {
70145
- this.registry.setViewVisible(visible, ownPage);
70605
+ setViewVisible(visible, ownPage = false, ownStatePage = ownPage) {
70606
+ this.registry.setViewVisible(visible, ownPage, ownStatePage);
70146
70607
  if (!visible) this.clearPageFocus();
70147
70608
  return this.chromeState();
70148
70609
  }
@@ -71322,7 +71783,7 @@ function registerBrowserIpc(options) {
71322
71783
  });
71323
71784
  electron.ipcMain.handle(
71324
71785
  "browser-set-visible",
71325
- (event, visible, ownPage) => {
71786
+ (event, visible, ownPage, ownStatePage) => {
71326
71787
  const host = authorize(event);
71327
71788
  if (typeof visible !== "boolean") {
71328
71789
  throw new Error("Visibility must be a boolean.");
@@ -71330,7 +71791,14 @@ function registerBrowserIpc(options) {
71330
71791
  if (ownPage !== void 0 && typeof ownPage !== "boolean") {
71331
71792
  throw new Error("The view-hidden reason must be a boolean.");
71332
71793
  }
71333
- return host.setViewVisible(visible, ownPage === true);
71794
+ if (ownStatePage !== void 0 && typeof ownStatePage !== "boolean") {
71795
+ throw new Error("The own-state reason must be a boolean.");
71796
+ }
71797
+ return host.setViewVisible(
71798
+ visible,
71799
+ ownPage === true,
71800
+ ownStatePage === void 0 ? ownPage === true : ownStatePage
71801
+ );
71334
71802
  }
71335
71803
  );
71336
71804
  electron.ipcMain.handle(
@@ -71861,6 +72329,17 @@ function buildPageContextMenuItems(input) {
71861
72329
  if (input.isEditable) {
71862
72330
  const flags = input.editFlags ?? {};
71863
72331
  return [
72332
+ {
72333
+ id: "undo",
72334
+ label: t("ui.browser.page_context_menu.undo"),
72335
+ enabled: flags.canUndo ?? true
72336
+ },
72337
+ {
72338
+ id: "redo",
72339
+ label: t("ui.browser.page_context_menu.redo"),
72340
+ enabled: flags.canRedo ?? true
72341
+ },
72342
+ SEPARATOR,
71864
72343
  {
71865
72344
  id: "cut",
71866
72345
  label: t("ui.browser.page_context_menu.cut"),
@@ -71900,6 +72379,13 @@ function buildPageContextMenuItems(input) {
71900
72379
  enabled: true
71901
72380
  }
71902
72381
  ];
72382
+ if (input.selectionText) {
72383
+ items.push(SEPARATOR, {
72384
+ id: "copy",
72385
+ label: t("ui.browser.page_context_menu.copy"),
72386
+ enabled: true
72387
+ });
72388
+ }
71903
72389
  if (input.linkUrl) {
71904
72390
  items.push(
71905
72391
  SEPARATOR,
@@ -73648,6 +74134,7 @@ async function initializeBrowserHost(options, bindings) {
73648
74134
  canGoBack: navigation ? navigation.canGoBack() : false,
73649
74135
  canGoForward: navigation ? navigation.canGoForward() : false,
73650
74136
  isEditable: params.isEditable,
74137
+ selectionText: params.selectionText ?? "",
73651
74138
  editFlags: params.editFlags
73652
74139
  });
73653
74140
  const menu = electron.Menu.buildFromTemplate(
@@ -73664,6 +74151,8 @@ async function initializeBrowserHost(options, bindings) {
73664
74151
  electron.clipboard.writeText(params.linkURL ?? "");
73665
74152
  else if (item.id === "copy-page")
73666
74153
  electron.clipboard.writeText(contents.getURL());
74154
+ else if (item.id === "undo") contents.undo();
74155
+ else if (item.id === "redo") contents.redo();
73667
74156
  else if (item.id === "cut") contents.cut();
73668
74157
  else if (item.id === "copy") contents.copy();
73669
74158
  else if (item.id === "paste") contents.paste();
@@ -73923,6 +74412,12 @@ async function initializeBrowserHost(options, bindings) {
73923
74412
  type: metric.type
73924
74413
  }))
73925
74414
  }) : null;
74415
+ const approvalsOverlay = options.approvalsOverlay?.enabled === true && approvalsOverlayEnabled(process.env) ? new ApprovalsOverlayController({
74416
+ window: options.window,
74417
+ documentUrl: options.approvalsOverlay.documentUrl,
74418
+ opaque: process.platform !== "darwin",
74419
+ log: log2
74420
+ }) : null;
73926
74421
  const sessionStore = new BrowserSessionStore({
73927
74422
  dir: path$1.join(options.userDataDir, "browser"),
73928
74423
  log: log2
@@ -73978,7 +74473,10 @@ async function initializeBrowserHost(options, bindings) {
73978
74473
  },
73979
74474
  releaseTab,
73980
74475
  notifyChanged,
73981
- (snapshot2) => addressOverlay?.onLayout(snapshot2)
74476
+ (snapshot2) => {
74477
+ addressOverlay?.onLayout(snapshot2);
74478
+ approvalsOverlay?.onLayout(snapshot2);
74479
+ }
73982
74480
  );
73983
74481
  registryForDownloads = registry;
73984
74482
  rollback.add(async () => {
@@ -73988,6 +74486,7 @@ async function initializeBrowserHost(options, bindings) {
73988
74486
  await Promise.allSettled([...releases]);
73989
74487
  });
73990
74488
  rollback.add(() => addressOverlay?.dispose("startup-rollback"));
74489
+ rollback.add(() => approvalsOverlay?.dispose("startup-rollback"));
73991
74490
  const ownership = new OwnershipLedger({
73992
74491
  mayAdopt: (token, requester) => {
73993
74492
  const record = registry.requireSurface(token);
@@ -74011,6 +74510,9 @@ async function initializeBrowserHost(options, bindings) {
74011
74510
  }
74012
74511
  }
74013
74512
  });
74513
+ let approvalsExpiryTimer = null;
74514
+ let syncApprovalsOverlay = () => {
74515
+ };
74014
74516
  const approvals = new ApprovalStore({
74015
74517
  dir: path$1.join(options.userDataDir, "browser"),
74016
74518
  onChanged: () => {
@@ -74018,9 +74520,26 @@ async function initializeBrowserHost(options, bindings) {
74018
74520
  options.window.webContents.send("browser-consent-changed");
74019
74521
  }
74020
74522
  consentNotifier.announce(approvals.pendingEntries());
74523
+ syncApprovalsOverlay();
74021
74524
  },
74022
74525
  log: log2
74023
74526
  });
74527
+ syncApprovalsOverlay = () => {
74528
+ if (!approvalsOverlay) return;
74529
+ if (approvalsExpiryTimer) {
74530
+ clearTimeout(approvalsExpiryTimer);
74531
+ approvalsExpiryTimer = null;
74532
+ }
74533
+ const entries = approvals.pendingEntries();
74534
+ approvalsOverlay?.setPending(entries.length);
74535
+ if (entries.length === 0) return;
74536
+ const delay2 = approvalsExpiryDelay(entries);
74537
+ if (delay2 !== null) {
74538
+ approvalsExpiryTimer = setTimeout(syncApprovalsOverlay, delay2 + 25);
74539
+ approvalsExpiryTimer.unref?.();
74540
+ }
74541
+ };
74542
+ syncApprovalsOverlay();
74024
74543
  const profileDir = browserStoragePath(browserSession) ?? "";
74025
74544
  const facts = {
74026
74545
  proto: 1,
@@ -74311,6 +74830,11 @@ async function initializeBrowserHost(options, bindings) {
74311
74830
  }
74312
74831
  sessionStore.flush();
74313
74832
  addressOverlay?.dispose("host-stop");
74833
+ if (approvalsExpiryTimer) {
74834
+ clearTimeout(approvalsExpiryTimer);
74835
+ approvalsExpiryTimer = null;
74836
+ }
74837
+ approvalsOverlay?.dispose("host-stop");
74314
74838
  registry.destroyAll();
74315
74839
  await Promise.allSettled([...releases]);
74316
74840
  await cdp.close();
@@ -85725,7 +86249,7 @@ const addressOverlayGate = resolveAddressOverlayGate({
85725
86249
  const addressOverlayProduct = process.platform === "darwin" && !addressOverlayGate.enabled;
85726
86250
  if (addressOverlayProduct) {
85727
86251
  console.log(
85728
- "[address-overlay] product chrome armed (darwin): popout field over the tab strip, native list child"
86252
+ "[address-overlay] product chrome armed (darwin): permanent address row, native list child"
85729
86253
  );
85730
86254
  }
85731
86255
  if (addressOverlayGate.asked) {
@@ -86151,6 +86675,8 @@ electron.app.whenReady().then(async () => {
86151
86675
  const rendererUrl = rendererDocumentUrl();
86152
86676
  const consoleCaptureUrl = consoleCaptureUrlFor(rendererUrl);
86153
86677
  const addressOverlayDocumentUrl = addressOverlayGate.list || addressOverlayProduct ? addressListDocumentUrlFor(rendererUrl) : addressOverlayDocumentUrlFor(rendererUrl);
86678
+ const approvalsOverlayS6a = process.env[APPROVALS_OVERLAY_S6A_ENV] === "1";
86679
+ const approvalsOverlayDocumentUrl = approvalsOverlayS6a ? documentUrlFor(rendererUrl, "browser-approvals-overlay.html") : null;
86154
86680
  backendService.observeDesktopFeed(
86155
86681
  (frame) => {
86156
86682
  if (frame.type === "notification") {
@@ -87003,6 +87529,12 @@ electron.app.whenReady().then(async () => {
87003
87529
  documentUrl: addressOverlayDocumentUrl
87004
87530
  }
87005
87531
  } : {},
87532
+ ...approvalsOverlayS6a && approvalsOverlayDocumentUrl ? {
87533
+ approvalsOverlay: {
87534
+ enabled: true,
87535
+ documentUrl: approvalsOverlayDocumentUrl
87536
+ }
87537
+ } : {},
87006
87538
  preloadPath: path$1.join(__dirname, "../preload/index.js"),
87007
87539
  /*
87008
87540
  * The console's surfaces are handed the user's own PATH, from the same