@davmash/bygone 0.8.4 → 0.8.6

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.
@@ -3811,6 +3811,9 @@ var require_changeTour = __commonJS({
3811
3811
  }
3812
3812
  requireString(value.title, "title");
3813
3813
  requireString(value.generatedAt, "generatedAt");
3814
+ if (value.windowTitle !== void 0) {
3815
+ requireString(value.windowTitle, "windowTitle");
3816
+ }
3814
3817
  if (value.sourceUrl !== void 0) {
3815
3818
  requireString(value.sourceUrl, "sourceUrl");
3816
3819
  }
@@ -4103,8 +4106,9 @@ var require_changeTour = __commonJS({
4103
4106
  if (!isRecord22(value) || value.version !== CHANGE_TOUR_SOURCE_VERSION) {
4104
4107
  throw new Error("Unsupported or missing change-tour source version.");
4105
4108
  }
4106
- requireOnlyKeys(value, ["version", "title", "sourceUrl", "range", "anchors", "connections", "chapters", "coverage"], "source");
4109
+ requireOnlyKeys(value, ["version", "title", "windowTitle", "sourceUrl", "range", "anchors", "connections", "chapters", "coverage"], "source");
4107
4110
  optionalString(value.title, "title");
4111
+ optionalString(value.windowTitle, "windowTitle");
4108
4112
  optionalString(value.sourceUrl, "sourceUrl");
4109
4113
  if (value.range !== void 0) {
4110
4114
  if (!isRecord22(value.range)) throw new Error("range must be an object.");
@@ -4947,7 +4951,7 @@ var require_changeTour = __commonJS({
4947
4951
  packaging: { id: "packaging", title: "Packaging and dependencies", priority: 4 }
4948
4952
  };
4949
4953
  function buildChangeTourManifest(startPath, options = {}) {
4950
- var _a, _b, _c, _d;
4954
+ var _a, _b, _c, _d, _e;
4951
4955
  const range = resolveBranchReviewRange3(startPath, options.headRef, options.baseRef);
4952
4956
  const maxFileBytes = options.maxFileBytes ?? DEFAULT_MAX_TOUR_FILE_BYTES;
4953
4957
  const maxLineBytes = options.maxLineBytes ?? DEFAULT_MAX_TOUR_LINE_BYTES;
@@ -5019,7 +5023,8 @@ var require_changeTour = __commonJS({
5019
5023
  const manifest = {
5020
5024
  version: CHANGE_TOUR_MANIFEST_VERSION,
5021
5025
  title: ((_a = options.source) == null ? void 0 : _a.title) || ((_b = options.story) == null ? void 0 : _b.title) || options.title || `${range.headRef} against ${range.baseRef}`,
5022
- sourceUrl: ((_c = options.source) == null ? void 0 : _c.sourceUrl) || ((_d = options.story) == null ? void 0 : _d.sourceUrl) || options.sourceUrl,
5026
+ windowTitle: (_c = options.source) == null ? void 0 : _c.windowTitle,
5027
+ sourceUrl: ((_d = options.source) == null ? void 0 : _d.sourceUrl) || ((_e = options.story) == null ? void 0 : _e.sourceUrl) || options.sourceUrl,
5023
5028
  generatedAt: options.generatedAt || (/* @__PURE__ */ new Date()).toISOString(),
5024
5029
  range: {
5025
5030
  baseRef: range.baseRef,
@@ -5466,6 +5471,140 @@ var require_changeTour = __commonJS({
5466
5471
  }
5467
5472
  });
5468
5473
 
5474
+ // out/windowTitle.js
5475
+ var require_windowTitle = __commonJS({
5476
+ "out/windowTitle.js"(exports2, module2) {
5477
+ "use strict";
5478
+ var __defProp2 = Object.defineProperty;
5479
+ var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
5480
+ var __getOwnPropNames2 = Object.getOwnPropertyNames;
5481
+ var __hasOwnProp2 = Object.prototype.hasOwnProperty;
5482
+ var __export2 = (target, all) => {
5483
+ for (var name in all)
5484
+ __defProp2(target, name, { get: all[name], enumerable: true });
5485
+ };
5486
+ var __copyProps2 = (to, from, except, desc) => {
5487
+ if (from && typeof from === "object" || typeof from === "function") {
5488
+ for (let key of __getOwnPropNames2(from))
5489
+ if (!__hasOwnProp2.call(to, key) && key !== except)
5490
+ __defProp2(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc2(from, key)) || desc.enumerable });
5491
+ }
5492
+ return to;
5493
+ };
5494
+ var __toCommonJS2 = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
5495
+ var windowTitle_exports2 = {};
5496
+ __export2(windowTitle_exports2, {
5497
+ MAX_WINDOW_TITLE_LENGTH: () => MAX_WINDOW_TITLE_LENGTH2,
5498
+ buildHistoryTitle: () => buildHistoryTitle3,
5499
+ buildHistoryTitleFromViewState: () => buildHistoryTitleFromViewState2,
5500
+ buildMultiPanelTitle: () => buildMultiPanelTitle2,
5501
+ buildStandaloneSessionTitle: () => buildStandaloneSessionTitle3,
5502
+ buildTourWindowTitle: () => buildTourWindowTitle3,
5503
+ buildTwoWayComparisonTitle: () => buildTwoWayComparisonTitle2,
5504
+ formatComparisonPair: () => formatComparisonPair2,
5505
+ truncateTitle: () => truncateTitle2
5506
+ });
5507
+ module2.exports = __toCommonJS2(windowTitle_exports2);
5508
+ var MAX_WINDOW_TITLE_LENGTH2 = 120;
5509
+ function truncateTitle2(text, max = MAX_WINDOW_TITLE_LENGTH2) {
5510
+ if (text.length <= max) {
5511
+ return text;
5512
+ }
5513
+ return `${text.slice(0, max - 1)}\u2026`;
5514
+ }
5515
+ function formatComparisonPair2(left, right) {
5516
+ return `${left} \u2194 ${right}`;
5517
+ }
5518
+ function buildMultiPanelTitle2(input) {
5519
+ const { panels, activePanelId, activePairIndex, panelIds } = input;
5520
+ if (panels.length === 0) {
5521
+ return "Multi-Panel Compare";
5522
+ }
5523
+ if (panels.length === 1) {
5524
+ return truncateTitle2(panels[0].label);
5525
+ }
5526
+ if (panels.length === 2) {
5527
+ return truncateTitle2(formatComparisonPair2(panels[0].label, panels[1].label));
5528
+ }
5529
+ const ids = panelIds ?? panels.map((_panel, index) => String(index));
5530
+ const activeIndex = activePanelId ? ids.findIndex((id) => id === activePanelId) : -1;
5531
+ if (activePairIndex !== null && activePairIndex !== void 0 && activePairIndex >= 0 && activePairIndex < panels.length - 1) {
5532
+ return truncateTitle2(formatComparisonPair2(
5533
+ panels[activePairIndex].label,
5534
+ panels[activePairIndex + 1].label
5535
+ ));
5536
+ }
5537
+ if (activeIndex >= 0) {
5538
+ const derivedPairIndex = activeIndex < panels.length - 1 ? activeIndex : Math.max(0, activeIndex - 1);
5539
+ return truncateTitle2(formatComparisonPair2(
5540
+ panels[derivedPairIndex].label,
5541
+ panels[derivedPairIndex + 1].label
5542
+ ));
5543
+ }
5544
+ return truncateTitle2(formatComparisonPair2(panels[0].label, panels[panels.length - 1].label));
5545
+ }
5546
+ function buildHistoryTitle3(fileName, options) {
5547
+ const parts = [`${fileName} History`];
5548
+ if (options == null ? void 0 : options.shortCommit) {
5549
+ parts.push(options.shortCommit);
5550
+ }
5551
+ if (options == null ? void 0 : options.positionLabel) {
5552
+ parts.push(`(${options.positionLabel})`);
5553
+ }
5554
+ return truncateTitle2(parts.join(" \u2014 "));
5555
+ }
5556
+ function buildHistoryTitleFromViewState2(fileName, history) {
5557
+ const shortCommit = history.rightCommitLabel.split(/\s+/)[0] || void 0;
5558
+ return buildHistoryTitle3(fileName, {
5559
+ shortCommit,
5560
+ positionLabel: history.positionLabel
5561
+ });
5562
+ }
5563
+ function buildTwoWayComparisonTitle2(left, right) {
5564
+ return truncateTitle2(formatComparisonPair2(left, right));
5565
+ }
5566
+ function buildTourWindowTitle3(manifest, appName = "Bygone") {
5567
+ var _a, _b;
5568
+ const label = ((_a = manifest == null ? void 0 : manifest.windowTitle) == null ? void 0 : _a.trim()) || ((_b = manifest == null ? void 0 : manifest.title) == null ? void 0 : _b.trim());
5569
+ return label ? truncateTitle2(label) : `${appName} Tour`;
5570
+ }
5571
+ function buildStandaloneSessionTitle3(session2) {
5572
+ var _a, _b, _c, _d;
5573
+ if (session2.mode === "multi-diff" && session2.multi) {
5574
+ return buildMultiPanelTitle2({
5575
+ panels: session2.multi.files,
5576
+ activePanelId: session2.multi.activePanelId,
5577
+ activePairIndex: session2.multi.activePairIndex,
5578
+ panelIds: session2.multi.files.map((file) => file.id)
5579
+ });
5580
+ }
5581
+ if (session2.mode === "history" && ((_a = session2.history) == null ? void 0 : _a.filePath)) {
5582
+ const entry = (_b = session2.history.entries) == null ? void 0 : _b[session2.history.index ?? 0];
5583
+ return buildHistoryTitle3(
5584
+ session2.history.filePath.split("/").pop() || "File",
5585
+ { shortCommit: entry == null ? void 0 : entry.shortCommit }
5586
+ );
5587
+ }
5588
+ if (session2.mode === "directory-history" && session2.dirHistory) {
5589
+ const name = session2.dirHistory.displayName || session2.dirHistory.viewRelativePath || "Directory";
5590
+ return truncateTitle2(`${name} Directory History`);
5591
+ }
5592
+ if (session2.mode === "directory" && session2.directory) {
5593
+ if ((_c = session2.directory.review) == null ? void 0 : _c.headRef) {
5594
+ return truncateTitle2(`${session2.directory.review.headRef} Branch Change`);
5595
+ }
5596
+ if ((_d = session2.directory.labels) == null ? void 0 : _d.length) {
5597
+ return truncateTitle2(session2.directory.labels.join(" \u2194 "));
5598
+ }
5599
+ }
5600
+ if (session2.left && session2.right) {
5601
+ return buildTwoWayComparisonTitle2(session2.left.label, session2.right.label);
5602
+ }
5603
+ return "Compare";
5604
+ }
5605
+ }
5606
+ });
5607
+
5469
5608
  // node_modules/js-yaml/lib/common.js
5470
5609
  var require_common = __commonJS({
5471
5610
  "node_modules/js-yaml/lib/common.js"(exports2, module2) {
@@ -8594,6 +8733,7 @@ var require_present = __commonJS({
8594
8733
  var path9 = require("path");
8595
8734
  var { spawn: spawn2 } = require("child_process");
8596
8735
  var { buildChangeTourManifest, parseChangeTourStory } = require_changeTour();
8736
+ var { buildTourWindowTitle: buildTourWindowTitle3 } = require_windowTitle();
8597
8737
  var { tokenMatches: tokenMatches2 } = require_commandSpec();
8598
8738
  var { loadTourSource } = require_tourFile();
8599
8739
  var MIME_TYPES = /* @__PURE__ */ new Map([
@@ -8627,6 +8767,9 @@ var require_present = __commonJS({
8627
8767
  process.stdout.write(`Wrote change-tour manifest to ${resolvedOutput}
8628
8768
  `);
8629
8769
  }
8770
+ const tourWindowTitle = buildTourWindowTitle3(manifest, "Bygone");
8771
+ const presenterIndexPath = path9.join(packageRoot2, "web", "index.html");
8772
+ let presenterIndexTemplate;
8630
8773
  const server = createServer((request, response) => {
8631
8774
  const requestUrl = new URL(request.url || "/", "http://127.0.0.1");
8632
8775
  if (requestUrl.pathname === "/tour.json") {
@@ -8637,6 +8780,21 @@ var require_present = __commonJS({
8637
8780
  response.end(serializedManifest);
8638
8781
  return;
8639
8782
  }
8783
+ if (requestUrl.pathname === "/" || requestUrl.pathname === "/index.html") {
8784
+ if (!presenterIndexTemplate) {
8785
+ presenterIndexTemplate = readFileSync5(presenterIndexPath, "utf8");
8786
+ }
8787
+ const html = presenterIndexTemplate.replace(
8788
+ /<title>Bygone Tour<\/title>/,
8789
+ `<title>${escapeHtml(tourWindowTitle)}</title>`
8790
+ );
8791
+ response.writeHead(200, {
8792
+ "Content-Type": "text/html; charset=utf-8",
8793
+ "Cache-Control": "no-store"
8794
+ });
8795
+ response.end(html);
8796
+ return;
8797
+ }
8640
8798
  const targetPath = resolveAssetPath(packageRoot2, requestUrl.pathname);
8641
8799
  if (!targetPath) {
8642
8800
  respond(response, 404, "Not found");
@@ -8707,7 +8865,7 @@ var require_present = __commonJS({
8707
8865
  }
8708
8866
  function resolveAssetPath(packageRoot2, requestPath) {
8709
8867
  if (requestPath === "/" || requestPath === "/index.html") {
8710
- return path9.join(packageRoot2, "web", "index.html");
8868
+ return null;
8711
8869
  }
8712
8870
  if (!requestPath.startsWith("/web/") && !requestPath.startsWith("/media/")) {
8713
8871
  return null;
@@ -8739,9 +8897,13 @@ var require_present = __commonJS({
8739
8897
  }
8740
8898
  response.end(message);
8741
8899
  }
8900
+ function escapeHtml(text) {
8901
+ return text.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;");
8902
+ }
8742
8903
  module2.exports = {
8743
8904
  parsePresentArgs,
8744
- startPresentation: startPresentation2
8905
+ startPresentation: startPresentation2,
8906
+ escapeHtml
8745
8907
  };
8746
8908
  }
8747
8909
  });
@@ -8789,6 +8951,121 @@ var require_launchArgs = __commonJS({
8789
8951
  }
8790
8952
  });
8791
8953
 
8954
+ // src/windowTitle.ts
8955
+ var windowTitle_exports = {};
8956
+ __export(windowTitle_exports, {
8957
+ MAX_WINDOW_TITLE_LENGTH: () => MAX_WINDOW_TITLE_LENGTH,
8958
+ buildHistoryTitle: () => buildHistoryTitle,
8959
+ buildHistoryTitleFromViewState: () => buildHistoryTitleFromViewState,
8960
+ buildMultiPanelTitle: () => buildMultiPanelTitle,
8961
+ buildStandaloneSessionTitle: () => buildStandaloneSessionTitle,
8962
+ buildTourWindowTitle: () => buildTourWindowTitle,
8963
+ buildTwoWayComparisonTitle: () => buildTwoWayComparisonTitle,
8964
+ formatComparisonPair: () => formatComparisonPair,
8965
+ truncateTitle: () => truncateTitle
8966
+ });
8967
+ function truncateTitle(text, max = MAX_WINDOW_TITLE_LENGTH) {
8968
+ if (text.length <= max) {
8969
+ return text;
8970
+ }
8971
+ return `${text.slice(0, max - 1)}\u2026`;
8972
+ }
8973
+ function formatComparisonPair(left, right) {
8974
+ return `${left} \u2194 ${right}`;
8975
+ }
8976
+ function buildMultiPanelTitle(input) {
8977
+ const { panels, activePanelId, activePairIndex, panelIds } = input;
8978
+ if (panels.length === 0) {
8979
+ return "Multi-Panel Compare";
8980
+ }
8981
+ if (panels.length === 1) {
8982
+ return truncateTitle(panels[0].label);
8983
+ }
8984
+ if (panels.length === 2) {
8985
+ return truncateTitle(formatComparisonPair(panels[0].label, panels[1].label));
8986
+ }
8987
+ const ids = panelIds ?? panels.map((_panel, index) => String(index));
8988
+ const activeIndex = activePanelId ? ids.findIndex((id) => id === activePanelId) : -1;
8989
+ if (activePairIndex !== null && activePairIndex !== void 0 && activePairIndex >= 0 && activePairIndex < panels.length - 1) {
8990
+ return truncateTitle(formatComparisonPair(
8991
+ panels[activePairIndex].label,
8992
+ panels[activePairIndex + 1].label
8993
+ ));
8994
+ }
8995
+ if (activeIndex >= 0) {
8996
+ const derivedPairIndex = activeIndex < panels.length - 1 ? activeIndex : Math.max(0, activeIndex - 1);
8997
+ return truncateTitle(formatComparisonPair(
8998
+ panels[derivedPairIndex].label,
8999
+ panels[derivedPairIndex + 1].label
9000
+ ));
9001
+ }
9002
+ return truncateTitle(formatComparisonPair(panels[0].label, panels[panels.length - 1].label));
9003
+ }
9004
+ function buildHistoryTitle(fileName, options) {
9005
+ const parts = [`${fileName} History`];
9006
+ if (options?.shortCommit) {
9007
+ parts.push(options.shortCommit);
9008
+ }
9009
+ if (options?.positionLabel) {
9010
+ parts.push(`(${options.positionLabel})`);
9011
+ }
9012
+ return truncateTitle(parts.join(" \u2014 "));
9013
+ }
9014
+ function buildHistoryTitleFromViewState(fileName, history) {
9015
+ const shortCommit = history.rightCommitLabel.split(/\s+/)[0] || void 0;
9016
+ return buildHistoryTitle(fileName, {
9017
+ shortCommit,
9018
+ positionLabel: history.positionLabel
9019
+ });
9020
+ }
9021
+ function buildTwoWayComparisonTitle(left, right) {
9022
+ return truncateTitle(formatComparisonPair(left, right));
9023
+ }
9024
+ function buildTourWindowTitle(manifest, appName = "Bygone") {
9025
+ const label = manifest?.windowTitle?.trim() || manifest?.title?.trim();
9026
+ return label ? truncateTitle(label) : `${appName} Tour`;
9027
+ }
9028
+ function buildStandaloneSessionTitle(session2) {
9029
+ if (session2.mode === "multi-diff" && session2.multi) {
9030
+ return buildMultiPanelTitle({
9031
+ panels: session2.multi.files,
9032
+ activePanelId: session2.multi.activePanelId,
9033
+ activePairIndex: session2.multi.activePairIndex,
9034
+ panelIds: session2.multi.files.map((file) => file.id)
9035
+ });
9036
+ }
9037
+ if (session2.mode === "history" && session2.history?.filePath) {
9038
+ const entry = session2.history.entries?.[session2.history.index ?? 0];
9039
+ return buildHistoryTitle(
9040
+ session2.history.filePath.split("/").pop() || "File",
9041
+ { shortCommit: entry?.shortCommit }
9042
+ );
9043
+ }
9044
+ if (session2.mode === "directory-history" && session2.dirHistory) {
9045
+ const name = session2.dirHistory.displayName || session2.dirHistory.viewRelativePath || "Directory";
9046
+ return truncateTitle(`${name} Directory History`);
9047
+ }
9048
+ if (session2.mode === "directory" && session2.directory) {
9049
+ if (session2.directory.review?.headRef) {
9050
+ return truncateTitle(`${session2.directory.review.headRef} Branch Change`);
9051
+ }
9052
+ if (session2.directory.labels?.length) {
9053
+ return truncateTitle(session2.directory.labels.join(" \u2194 "));
9054
+ }
9055
+ }
9056
+ if (session2.left && session2.right) {
9057
+ return buildTwoWayComparisonTitle(session2.left.label, session2.right.label);
9058
+ }
9059
+ return "Compare";
9060
+ }
9061
+ var MAX_WINDOW_TITLE_LENGTH;
9062
+ var init_windowTitle = __esm({
9063
+ "src/windowTitle.ts"() {
9064
+ "use strict";
9065
+ MAX_WINDOW_TITLE_LENGTH = 120;
9066
+ }
9067
+ });
9068
+
8792
9069
  // package.json
8793
9070
  var require_package = __commonJS({
8794
9071
  "package.json"(exports2, module2) {
@@ -8798,7 +9075,7 @@ var require_package = __commonJS({
8798
9075
  displayName: "Bygone",
8799
9076
  desktopName: "com.davidmashburn.bygone.desktop",
8800
9077
  description: "See how change happened. Visual diff and file history for VS Code.",
8801
- version: "0.8.4",
9078
+ version: "0.8.6",
8802
9079
  author: "David Mashburn",
8803
9080
  license: "MIT",
8804
9081
  private: false,
@@ -8991,7 +9268,9 @@ var require_package = __commonJS({
8991
9268
  "web:start": "npm run compile && node ./scripts/web-server.mjs",
8992
9269
  "package:desktop": "npm run package:desktop:mac",
8993
9270
  "package:desktop:mac": "npm run compile && electron-builder --mac dmg --publish never",
9271
+ "package:desktop:mac:release": "npm run compile && electron-builder --mac dmg --publish never --config packaging/macos/electron-builder.signing.json",
8994
9272
  "package:desktop:mac:zip": "npm run compile && electron-builder --mac zip --publish never",
9273
+ "package:desktop:mac:zip:release": "npm run compile && electron-builder --mac zip --publish never --config packaging/macos/electron-builder.signing.json",
8995
9274
  "package:desktop:linux": "npm run compile && electron-builder --linux AppImage --publish never",
8996
9275
  "package:desktop:win": "npm run compile && electron-builder --win --publish never",
8997
9276
  "package:desktop:all": "npm run compile && electron-builder --mac --win --linux AppImage --publish never",
@@ -9007,6 +9286,7 @@ var require_package = __commonJS({
9007
9286
  "release:check": "npm run security:audit && npm test && npm run bundle:check && npm run lint && npm run package:vsix && npm run package:npm && npm run package:npm:dry-run",
9008
9287
  "release:build": "node ./scripts/release.mjs",
9009
9288
  "release:publish": "node ./scripts/release.mjs --publish",
9289
+ "release:verify-macos": "node ./scripts/verify-macos-signing.mjs --require-notarized",
9010
9290
  lint: "eslint . --max-warnings=0",
9011
9291
  "lint:fix": "eslint . --fix",
9012
9292
  watch: "tsc -watch -p ./",
@@ -9036,6 +9316,10 @@ var require_package = __commonJS({
9036
9316
  {
9037
9317
  from: "completions",
9038
9318
  to: "completions"
9319
+ },
9320
+ {
9321
+ from: "packaging/homebrew/bygone-launcher.sh",
9322
+ to: "bygone-launcher.sh"
9039
9323
  }
9040
9324
  ],
9041
9325
  extraMetadata: {
@@ -22040,6 +22324,11 @@ var { tokenMatches, tokensFor } = require_commandSpec();
22040
22324
  var { startPresentation } = require_present();
22041
22325
  var { resolveWorkingDirectory } = require_workingDirectory();
22042
22326
  var { getCliArgsFromArgv, getForwardedLaunchArgs } = require_launchArgs();
22327
+ var {
22328
+ buildHistoryTitle: buildHistoryTitle2,
22329
+ buildStandaloneSessionTitle: buildStandaloneSessionTitle2,
22330
+ buildTourWindowTitle: buildTourWindowTitle2
22331
+ } = (init_windowTitle(), __toCommonJS(windowTitle_exports));
22043
22332
  var APP_NAME = "Bygone";
22044
22333
  var APP_VERSION = require_package().version;
22045
22334
  var HELP_URL = "https://github.com/davidmashburn/bygone";
@@ -22274,7 +22563,7 @@ async function openTourPresentation(args, cwd) {
22274
22563
  });
22275
22564
  activeTourServers.add(presentation.server);
22276
22565
  try {
22277
- await showTourWindow(presentation.url, presentation.server);
22566
+ await showTourWindow(presentation.url, presentation.server, presentation.manifest);
22278
22567
  } catch (error) {
22279
22568
  closeTourServer(presentation.server);
22280
22569
  throw error;
@@ -22284,7 +22573,7 @@ async function openAuthoredTourDocument(sourcePath) {
22284
22573
  const document2 = discoverAuthoredTourDocument2(sourcePath);
22285
22574
  await openTourPresentation(["--tour", document2.documentPath], document2.repoRoot);
22286
22575
  }
22287
- async function showTourWindow(url, server) {
22576
+ async function showTourWindow(url, server, manifest) {
22288
22577
  const parsedUrl = new URL(url);
22289
22578
  if (parsedUrl.protocol !== "http:" || parsedUrl.hostname !== "127.0.0.1") {
22290
22579
  throw new Error("Tour presenter URL must use the local Bygone server.");
@@ -22296,7 +22585,7 @@ async function showTourWindow(url, server) {
22296
22585
  minWidth: 960,
22297
22586
  minHeight: 640,
22298
22587
  show: false,
22299
- title: `${APP_NAME} Tour`,
22588
+ title: buildTourWindowTitle2(manifest, APP_NAME),
22300
22589
  webPreferences: {
22301
22590
  sandbox: true,
22302
22591
  contextIsolation: true,
@@ -22334,12 +22623,24 @@ async function showTourWindow(url, server) {
22334
22623
  latestTourWindow = getLatestTourWindow();
22335
22624
  }
22336
22625
  });
22626
+ const tourWindowTitle = buildTourWindowTitle2(manifest, APP_NAME);
22627
+ const applyTourWindowTitle = () => {
22628
+ if (!tourWindow.isDestroyed()) {
22629
+ tourWindow.setTitle(tourWindowTitle);
22630
+ }
22631
+ };
22632
+ tourWindow.webContents.on("page-title-updated", (event) => {
22633
+ event.preventDefault();
22634
+ queueMicrotask(applyTourWindowTitle);
22635
+ });
22636
+ tourWindow.webContents.on("did-finish-load", applyTourWindowTitle);
22337
22637
  try {
22338
22638
  await tourWindow.loadURL(url);
22339
22639
  } catch (error) {
22340
22640
  tourWindow.destroy();
22341
22641
  throw error;
22342
22642
  }
22643
+ applyTourWindowTitle();
22343
22644
  tourWindow.show();
22344
22645
  tourWindow.focus();
22345
22646
  return tourWindow;
@@ -23428,11 +23729,15 @@ async function handleRendererMessage(message) {
23428
23729
  return;
23429
23730
  }
23430
23731
  if (message.type === "multiSetActivePanel" && typeof message.panelId === "string") {
23431
- setActiveMultiPanel(message.panelId);
23732
+ if (setActiveMultiPanel(message.panelId)) {
23733
+ refreshSessionWindowTitle();
23734
+ }
23432
23735
  return;
23433
23736
  }
23434
23737
  if (message.type === "multiSetActivePair" && Number.isInteger(message.pairIndex)) {
23435
- setActiveMultiPair(message.pairIndex);
23738
+ if (setActiveMultiPair(message.pairIndex)) {
23739
+ refreshSessionWindowTitle();
23740
+ }
23436
23741
  return;
23437
23742
  }
23438
23743
  if (message.type === "multiAddPanel" && typeof message.anchorPanelId === "string" && (message.side === "left" || message.side === "right")) {
@@ -23456,7 +23761,7 @@ async function handleRendererMessage(message) {
23456
23761
  if (panel) {
23457
23762
  panel.content = message.content;
23458
23763
  panel.dirty = panel.content !== panel.savedContent;
23459
- updateWindowTitle(session.multi.files.map((file) => file.label).join(" \u2194 ") || "Multi-Panel Compare");
23764
+ refreshSessionWindowTitle();
23460
23765
  }
23461
23766
  return;
23462
23767
  }
@@ -24110,7 +24415,7 @@ async function sendCurrentDirectoryDiff() {
24110
24415
  canMutate: !review && session.source?.kind === "directories",
24111
24416
  review: buildReviewViewState(review)
24112
24417
  });
24113
- updateWindowTitle(review ? `${review.headRef} Branch Change` : session.directory.labels.join(" \u2194 "));
24418
+ refreshSessionWindowTitle();
24114
24419
  if (launchArguments.kind === "smoke-directory" && mainWindow && !mainWindow.isDestroyed()) {
24115
24420
  setTimeout(() => {
24116
24421
  void mainWindow.webContents.executeJavaScript(`document.querySelector('.dir-entry[data-is-dir="false"]')?.click()`);
@@ -24175,7 +24480,7 @@ async function sendCurrentDirectoryHistoryEntry() {
24175
24480
  fileNavigation: buildDirectoryHistoryFileNavigationState(session.dirHistory, entry),
24176
24481
  canReturnToDirectory: true
24177
24482
  });
24178
- updateWindowTitle(`${relativePath} Directory History`);
24483
+ refreshSessionWindowTitle();
24179
24484
  scheduleCaptureIfNeeded();
24180
24485
  return;
24181
24486
  }
@@ -24199,7 +24504,7 @@ async function sendCurrentDirectoryHistoryEntry() {
24199
24504
  history,
24200
24505
  canMutate: true
24201
24506
  });
24202
- updateWindowTitle(`${session.dirHistory.displayName} Directory History`);
24507
+ refreshSessionWindowTitle();
24203
24508
  scheduleCaptureIfNeeded();
24204
24509
  }
24205
24510
  function buildDirectoryHistoryViewState(dirHistory, entry) {
@@ -25370,7 +25675,7 @@ async function sendCurrentMultiDiff() {
25370
25675
  fileNavigation: buildStandaloneFileNavigationState(),
25371
25676
  mutationEnabled: !isDirectoryDrilldown
25372
25677
  });
25373
- updateWindowTitle(panels.map((panel) => panel.label).join(" \u2194 ") || "Multi-Panel Compare");
25678
+ refreshSessionWindowTitle();
25374
25679
  if (mainWindow && !mainWindow.isDestroyed()) {
25375
25680
  setTimeout(() => {
25376
25681
  void mainWindow.webContents.executeJavaScript(`(() => ({
@@ -25488,7 +25793,7 @@ async function sendCurrentDiff() {
25488
25793
  directoryNavigation: buildDirectoryDrilldownNavigationState(),
25489
25794
  canReturnToDirectory: Boolean(session.returnDirectory)
25490
25795
  });
25491
- updateWindowTitle(`${session.left.label} \u2194 ${session.right.label}`);
25796
+ refreshSessionWindowTitle();
25492
25797
  scheduleCaptureIfNeeded();
25493
25798
  return;
25494
25799
  }
@@ -25516,7 +25821,7 @@ async function sendCurrentDiff() {
25516
25821
  comparisonSummary: session.returnDirectory?.comparisonSummary
25517
25822
  };
25518
25823
  postOrQueue(message);
25519
- updateWindowTitle(`${session.left.label} \u2194 ${session.right.label}`);
25824
+ refreshSessionWindowTitle();
25520
25825
  if (mainWindow && !mainWindow.isDestroyed()) {
25521
25826
  setTimeout(() => {
25522
25827
  void mainWindow.webContents.executeJavaScript(`(() => ({
@@ -25604,7 +25909,7 @@ async function sendCurrentHistoryEntry() {
25604
25909
  rail
25605
25910
  }
25606
25911
  });
25607
- updateWindowTitle(`${fileName} History`);
25912
+ refreshSessionWindowTitle();
25608
25913
  if (mainWindow && !mainWindow.isDestroyed()) {
25609
25914
  setTimeout(() => {
25610
25915
  void mainWindow.webContents.executeJavaScript(`(() => ({
@@ -25924,7 +26229,7 @@ async function saveDirtyMultiPanels() {
25924
26229
  }
25925
26230
  updateWatchers();
25926
26231
  await sendCurrentMultiDiff();
25927
- updateWindowTitle(session.multi.files.map((file) => file.label).join(" \u2194 ") || "Multi-Panel Compare");
26232
+ refreshSessionWindowTitle();
25928
26233
  return true;
25929
26234
  }
25930
26235
  async function saveMultiPanel(panel, { dialogTitle, refreshView }) {
@@ -25950,7 +26255,7 @@ async function saveMultiPanel(panel, { dialogTitle, refreshView }) {
25950
26255
  if (refreshView) {
25951
26256
  updateWatchers();
25952
26257
  await sendCurrentMultiDiff();
25953
- updateWindowTitle(session.multi.files.map((file) => file.label).join(" \u2194 ") || "Multi-Panel Compare");
26258
+ refreshSessionWindowTitle();
25954
26259
  }
25955
26260
  return true;
25956
26261
  }
@@ -26064,6 +26369,20 @@ function updateWindowTitle(title) {
26064
26369
  const dirtySuffix = hasUnsavedChanges() ? " \u2022 Unsaved" : "";
26065
26370
  mainWindow.setTitle(`${APP_NAME} \u2014 ${title}${dirtySuffix}`);
26066
26371
  }
26372
+ function refreshSessionWindowTitle() {
26373
+ if (session.mode === "history" && session.history) {
26374
+ const visibleIndices = getVisibleFileHistoryIndices(session.history);
26375
+ const visiblePosition = visibleIndices.indexOf(session.history.index);
26376
+ const entry = session.history.entries[session.history.index];
26377
+ const fileName = path8.basename(session.history.filePath);
26378
+ updateWindowTitle(buildHistoryTitle2(fileName, {
26379
+ shortCommit: entry?.shortCommit,
26380
+ positionLabel: visiblePosition >= 0 ? `${visiblePosition + 1} / ${visibleIndices.length}` : void 0
26381
+ }));
26382
+ return;
26383
+ }
26384
+ updateWindowTitle(buildStandaloneSessionTitle2(session));
26385
+ }
26067
26386
  async function confirmSessionReplacement(action) {
26068
26387
  if (!hasUnsavedChanges()) {
26069
26388
  return true;
@@ -481,6 +481,9 @@ function parseChangeTourManifest(value) {
481
481
  }
482
482
  requireString(value.title, "title");
483
483
  requireString(value.generatedAt, "generatedAt");
484
+ if (value.windowTitle !== void 0) {
485
+ requireString(value.windowTitle, "windowTitle");
486
+ }
484
487
  if (value.sourceUrl !== void 0) {
485
488
  requireString(value.sourceUrl, "sourceUrl");
486
489
  }
@@ -744,8 +747,9 @@ function parseChangeTourSource(value) {
744
747
  if (!isRecord2(value) || value.version !== CHANGE_TOUR_SOURCE_VERSION) {
745
748
  throw new Error("Unsupported or missing change-tour source version.");
746
749
  }
747
- requireOnlyKeys(value, ["version", "title", "sourceUrl", "range", "anchors", "connections", "chapters", "coverage"], "source");
750
+ requireOnlyKeys(value, ["version", "title", "windowTitle", "sourceUrl", "range", "anchors", "connections", "chapters", "coverage"], "source");
748
751
  optionalString(value.title, "title");
752
+ optionalString(value.windowTitle, "windowTitle");
749
753
  optionalString(value.sourceUrl, "sourceUrl");
750
754
  if (value.range !== void 0) {
751
755
  if (!isRecord2(value.range)) throw new Error("range must be an object.");
@@ -1162,7 +1166,7 @@ var CHAPTERS = {
1162
1166
  packaging: { id: "packaging", title: "Packaging and dependencies", priority: 4 }
1163
1167
  };
1164
1168
  function buildChangeTourManifest(startPath, options = {}) {
1165
- var _a, _b, _c, _d;
1169
+ var _a, _b, _c, _d, _e;
1166
1170
  const range = resolveBranchReviewRange(startPath, options.headRef, options.baseRef);
1167
1171
  const maxFileBytes = options.maxFileBytes ?? DEFAULT_MAX_TOUR_FILE_BYTES;
1168
1172
  const maxLineBytes = options.maxLineBytes ?? DEFAULT_MAX_TOUR_LINE_BYTES;
@@ -1234,7 +1238,8 @@ function buildChangeTourManifest(startPath, options = {}) {
1234
1238
  const manifest = {
1235
1239
  version: CHANGE_TOUR_MANIFEST_VERSION,
1236
1240
  title: ((_a = options.source) == null ? void 0 : _a.title) || ((_b = options.story) == null ? void 0 : _b.title) || options.title || `${range.headRef} against ${range.baseRef}`,
1237
- sourceUrl: ((_c = options.source) == null ? void 0 : _c.sourceUrl) || ((_d = options.story) == null ? void 0 : _d.sourceUrl) || options.sourceUrl,
1241
+ windowTitle: (_c = options.source) == null ? void 0 : _c.windowTitle,
1242
+ sourceUrl: ((_d = options.source) == null ? void 0 : _d.sourceUrl) || ((_e = options.story) == null ? void 0 : _e.sourceUrl) || options.sourceUrl,
1238
1243
  generatedAt: options.generatedAt || (/* @__PURE__ */ new Date()).toISOString(),
1239
1244
  range: {
1240
1245
  baseRef: range.baseRef,