privateboard 0.1.31 → 0.1.32
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/dist/boot.js +5 -1
- package/dist/boot.js.map +1 -1
- package/dist/cli.js +5 -1
- package/dist/cli.js.map +1 -1
- package/dist/server.js +5 -1
- package/dist/server.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +2 -1
- package/public/app.js +9 -108
- package/public/home.html +1 -1
- package/public/i18n.js +8 -8
- package/public/index.html +88 -168
- package/public/onboarding.css +8 -0
- package/public/themes.css +37 -6
- package/public/typing-sfx.js +32 -2
- package/public/vendor/mp4-muxer.min.js +1904 -0
- package/public/voice-3d-banner.js +21 -0
- package/public/voice-onboarding.css +7 -0
- package/public/voice-recorder.js +427 -81
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED
package/dist/version.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/version.ts"],"sourcesContent":["/**\n * Single source of truth for the app version.\n *\n * Imported by `cli.ts` (CLI banner / `--version`), `server.ts` (the\n * `/health` payload + the `/api/version` endpoint), and bundled into\n * the frontend via the version endpoint. Bump alongside `package.json`\n * on every release — the existing `npm version <patch|minor|major>`\n * + commit pattern updates package.json automatically; this file\n * needs the matching manual bump.\n *\n * If two strings drift (bumped one but not the other), the wrong\n * number ends up surfaced in the user-facing footer or banner. Keep\n * this file as the canonical source — every callsite reads from here.\n */\nexport const VERSION = \"0.1.
|
|
1
|
+
{"version":3,"sources":["../src/version.ts"],"sourcesContent":["/**\n * Single source of truth for the app version.\n *\n * Imported by `cli.ts` (CLI banner / `--version`), `server.ts` (the\n * `/health` payload + the `/api/version` endpoint), and bundled into\n * the frontend via the version endpoint. Bump alongside `package.json`\n * on every release — the existing `npm version <patch|minor|major>`\n * + commit pattern updates package.json automatically; this file\n * needs the matching manual bump.\n *\n * If two strings drift (bumped one but not the other), the wrong\n * number ends up surfaced in the user-facing footer or banner. Keep\n * this file as the canonical source — every callsite reads from here.\n */\nexport const VERSION = \"0.1.32\";\n"],"mappings":";;;AAcO,IAAM,UAAU;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "privateboard",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.32",
|
|
4
4
|
"description": "PrivateBoard · your private board meeting, on call. Local-first, multi-agent thinking amplifier.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "electron-entry.cjs",
|
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
"commander": "^12.1.0",
|
|
58
58
|
"electron-updater": "^6.8.3",
|
|
59
59
|
"hono": "^4.6.14",
|
|
60
|
+
"mp4-muxer": "^5.2.2",
|
|
60
61
|
"open": "^10.1.0",
|
|
61
62
|
"three": "^0.184.0",
|
|
62
63
|
"tiny-pinyin": "^1.3.2",
|
package/public/app.js
CHANGED
|
@@ -362,7 +362,6 @@
|
|
|
362
362
|
document.addEventListener("boardroom:locale", () => {
|
|
363
363
|
this.renderSidebarRooms();
|
|
364
364
|
this.renderSidebarAgents();
|
|
365
|
-
this.renderSidebarCounts();
|
|
366
365
|
this.renderUserBlock();
|
|
367
366
|
if (this.currentRoomId) this.renderRoom();
|
|
368
367
|
else this.renderEmptyState();
|
|
@@ -546,14 +545,7 @@
|
|
|
546
545
|
document.querySelector("[data-sidebar-collapse]")?.click();
|
|
547
546
|
});
|
|
548
547
|
|
|
549
|
-
// Sidebar count badges · refresh on boot.
|
|
550
|
-
// Notes: also refreshed on every note:created / note:deleted
|
|
551
|
-
// (handlers below). Reports: refreshed when a brief lands or
|
|
552
|
-
// is deleted (see SSE brief-final / brief-deleted handlers).
|
|
553
|
-
this.refreshNotesCount();
|
|
554
|
-
this.refreshReportsCount();
|
|
555
548
|
document.addEventListener("note:created", (e) => {
|
|
556
|
-
this.refreshNotesCount();
|
|
557
549
|
// Live-update currentNotes for the active room so the new
|
|
558
550
|
// span gets its highlight without waiting for a navigation.
|
|
559
551
|
const note = e && e.detail && e.detail.note;
|
|
@@ -566,7 +558,6 @@
|
|
|
566
558
|
}
|
|
567
559
|
});
|
|
568
560
|
document.addEventListener("note:deleted", (e) => {
|
|
569
|
-
this.refreshNotesCount();
|
|
570
561
|
const detail = e && e.detail;
|
|
571
562
|
if (detail && detail.noteId && this.currentNotes) {
|
|
572
563
|
for (const [mid, arr] of this.currentNotes) {
|
|
@@ -755,7 +746,6 @@
|
|
|
755
746
|
if (j.chair) this.currentChair = j.chair;
|
|
756
747
|
if (this.currentChair) this.agentsById[this.currentChair.id] = this.currentChair;
|
|
757
748
|
this.renderSidebarAgents();
|
|
758
|
-
this.renderSidebarCounts();
|
|
759
749
|
} catch (e) { /* ignore */ }
|
|
760
750
|
},
|
|
761
751
|
|
|
@@ -2337,8 +2327,6 @@
|
|
|
2337
2327
|
this.renderBrief();
|
|
2338
2328
|
}
|
|
2339
2329
|
this.renderHeader();
|
|
2340
|
-
// A new brief just landed → bump the All Reports badge.
|
|
2341
|
-
this.refreshReportsCount();
|
|
2342
2330
|
// Refresh the FULL brief list so the tab strip picks up the
|
|
2343
2331
|
// newly filed brief (including any "add a perspective"
|
|
2344
2332
|
// regenerations). Active brief = the just-finalised one.
|
|
@@ -5134,7 +5122,6 @@
|
|
|
5134
5122
|
this.currentBrief = this.currentBriefs[0] || null;
|
|
5135
5123
|
}
|
|
5136
5124
|
this.renderBrief();
|
|
5137
|
-
this.refreshReportsCount();
|
|
5138
5125
|
},
|
|
5139
5126
|
|
|
5140
5127
|
/** Retry handler for the orphaned-brief recovery UI. Drops the
|
|
@@ -6606,7 +6593,6 @@
|
|
|
6606
6593
|
|
|
6607
6594
|
// ── Rendering · sidebar rooms ─────────────────────────────
|
|
6608
6595
|
renderSidebarRooms() {
|
|
6609
|
-
this.renderSidebarCounts();
|
|
6610
6596
|
const list = document.querySelector("[data-rooms-list]");
|
|
6611
6597
|
if (!list) return;
|
|
6612
6598
|
const live = this.rooms.filter((r) => r.status === "live");
|
|
@@ -6614,38 +6600,17 @@
|
|
|
6614
6600
|
const adj = this.rooms.filter((r) => r.status === "adjourned");
|
|
6615
6601
|
|
|
6616
6602
|
const renderRow = (r) => {
|
|
6617
|
-
const pausedLbl = this._t("sidebar_paused");
|
|
6618
|
-
const status =
|
|
6619
|
-
r.status === "paused"
|
|
6620
|
-
? `<span class="row-status paused">❚❚ ${this.escape(pausedLbl)}</span>`
|
|
6621
|
-
: "";
|
|
6622
|
-
const time =
|
|
6623
|
-
r.status === "paused"
|
|
6624
|
-
? this.relTime(r.pausedAt || r.createdAt)
|
|
6625
|
-
: r.status === "adjourned"
|
|
6626
|
-
? this.relTime(r.adjournedAt || r.createdAt)
|
|
6627
|
-
: this.relTime(r.createdAt);
|
|
6628
6603
|
const fullTitle = r.name || r.subject || "";
|
|
6629
6604
|
// Layout: a wrapper holds the anchor + the delete button as
|
|
6630
6605
|
// siblings. Putting the <button> inside the <a> is invalid HTML
|
|
6631
6606
|
// and some browsers route the click to the link, swallowing the
|
|
6632
6607
|
// delete action — moving it out fixes that.
|
|
6633
|
-
// No `title` attr · the native browser tooltip popping the full
|
|
6634
|
-
// subject on hover competes with the row's own subtitle line
|
|
6635
|
-
// and felt redundant. The subtitle already shows the subject;
|
|
6636
|
-
// truncated names are rare and the user can click in to see
|
|
6637
|
-
// the full thing if needed.
|
|
6638
6608
|
return `
|
|
6639
6609
|
<div class="session-row-shell" data-room-id="${this.escape(r.id)}" data-status="${this.escape(r.status)}">
|
|
6640
6610
|
<a href="#/r/${this.escape(r.id)}" class="session-row">
|
|
6641
|
-
<
|
|
6642
|
-
<div class="row-top-line">
|
|
6643
|
-
<span class="row-title">${this.escape(fullTitle)}</span>
|
|
6644
|
-
</div>
|
|
6645
|
-
<div class="row-subtitle">${status}${this.escape(r.subject || "")}</div>
|
|
6646
|
-
</div>
|
|
6611
|
+
<span class="row-title">${this.escape(fullTitle)}</span>
|
|
6647
6612
|
</a>
|
|
6648
|
-
<button type="button" class="row-delete" data-room-delete title="${this.escape(this._t("sidebar_delete_room"))}"
|
|
6613
|
+
<button type="button" class="row-delete" data-room-delete title="${this.escape(this._t("sidebar_delete_room"))}" aria-label="${this.escape(this._t("sidebar_delete_room"))}"></button>
|
|
6649
6614
|
</div>
|
|
6650
6615
|
`;
|
|
6651
6616
|
};
|
|
@@ -6655,7 +6620,6 @@
|
|
|
6655
6620
|
<div class="section-header live">
|
|
6656
6621
|
<span>${this.escape(this._t("sidebar_section_live"))}</span>
|
|
6657
6622
|
<span class="line"></span>
|
|
6658
|
-
<span class="badge">${live.length}</span>
|
|
6659
6623
|
</div>
|
|
6660
6624
|
${live.map(renderRow).join("")}
|
|
6661
6625
|
` : ""}
|
|
@@ -6664,7 +6628,6 @@
|
|
|
6664
6628
|
<div class="section-header paused">
|
|
6665
6629
|
<span>${this.escape(this._t("sidebar_section_paused"))}</span>
|
|
6666
6630
|
<span class="line"></span>
|
|
6667
|
-
<span class="badge">${paused.length}</span>
|
|
6668
6631
|
</div>
|
|
6669
6632
|
${paused.map(renderRow).join("")}
|
|
6670
6633
|
` : ""}
|
|
@@ -6672,7 +6635,6 @@
|
|
|
6672
6635
|
<div class="section-header adjourned">
|
|
6673
6636
|
<span>${this.escape(this._t("sidebar_section_adjourned"))}</span>
|
|
6674
6637
|
<span class="line"></span>
|
|
6675
|
-
<span class="badge" data-adjourned-count>${adj.length}</span>
|
|
6676
6638
|
</div>
|
|
6677
6639
|
<div class="adjourned-list" data-adjourned-list>
|
|
6678
6640
|
${adj.map(renderRow).join("")}
|
|
@@ -6898,7 +6860,7 @@
|
|
|
6898
6860
|
</a>
|
|
6899
6861
|
`;
|
|
6900
6862
|
|
|
6901
|
-
const sectionHeader = (label,
|
|
6863
|
+
const sectionHeader = (label, kind) => {
|
|
6902
6864
|
const pinned = kind === "pinned";
|
|
6903
6865
|
const chair = kind === "chair";
|
|
6904
6866
|
const glyph = pinned
|
|
@@ -6910,7 +6872,6 @@
|
|
|
6910
6872
|
${glyph}
|
|
6911
6873
|
<span>${this.escape(label)}</span>
|
|
6912
6874
|
<span class="line"></span>
|
|
6913
|
-
<span class="badge">${count}</span>
|
|
6914
6875
|
</div>
|
|
6915
6876
|
`;
|
|
6916
6877
|
};
|
|
@@ -6921,7 +6882,7 @@
|
|
|
6921
6882
|
// user immediately sees the orchestrator, and so it can't get
|
|
6922
6883
|
// grouped with directors they pin or create.
|
|
6923
6884
|
if (this.currentChair) {
|
|
6924
|
-
parts.push(sectionHeader(this._t("sidebar_sec_chair"),
|
|
6885
|
+
parts.push(sectionHeader(this._t("sidebar_sec_chair"), "chair"));
|
|
6925
6886
|
parts.push(renderChairRow(this.currentChair));
|
|
6926
6887
|
}
|
|
6927
6888
|
// Building section · placeholder row for the in-flight Full
|
|
@@ -6940,19 +6901,19 @@
|
|
|
6940
6901
|
// right now". The earlier i18n key fallback to "Building"
|
|
6941
6902
|
// tested as confusing.
|
|
6942
6903
|
const headerLabel = job.status === "done" ? "Ready to save" : "Generating";
|
|
6943
|
-
parts.push(`<div class="agents-section-header building"><span>${this.escape(headerLabel)}</span><span class="line"></span
|
|
6904
|
+
parts.push(`<div class="agents-section-header building"><span>${this.escape(headerLabel)}</span><span class="line"></span></div>`);
|
|
6944
6905
|
parts.push(this._renderPersonaBuildingRow(job));
|
|
6945
6906
|
}
|
|
6946
6907
|
if (pinned.length) {
|
|
6947
|
-
parts.push(sectionHeader(this._t("sidebar_sec_pinned"),
|
|
6908
|
+
parts.push(sectionHeader(this._t("sidebar_sec_pinned"), "pinned"));
|
|
6948
6909
|
parts.push(pinned.map((a) => renderRow(a)).join(""));
|
|
6949
6910
|
}
|
|
6950
6911
|
if (custom.length) {
|
|
6951
|
-
parts.push(sectionHeader(this._t("sidebar_sec_custom")
|
|
6912
|
+
parts.push(sectionHeader(this._t("sidebar_sec_custom")));
|
|
6952
6913
|
parts.push(custom.map((a) => renderRow(a)).join(""));
|
|
6953
6914
|
}
|
|
6954
6915
|
if (core.length) {
|
|
6955
|
-
parts.push(sectionHeader(this._t("sidebar_sec_core")
|
|
6916
|
+
parts.push(sectionHeader(this._t("sidebar_sec_core")));
|
|
6956
6917
|
parts.push(core.map((a) => renderRow(a)).join(""));
|
|
6957
6918
|
}
|
|
6958
6919
|
// Same idempotency guard as renderSidebarRooms · skip the
|
|
@@ -7058,16 +7019,6 @@
|
|
|
7058
7019
|
if (mt) mt.textContent = meta;
|
|
7059
7020
|
},
|
|
7060
7021
|
|
|
7061
|
-
renderSidebarCounts() {
|
|
7062
|
-
const roomsCount = this.rooms.length;
|
|
7063
|
-
const agentsCount = this.agents.length;
|
|
7064
|
-
|
|
7065
|
-
const r = document.querySelector('[data-sidebar-tab-count="rooms"]');
|
|
7066
|
-
if (r) r.textContent = String(roomsCount);
|
|
7067
|
-
const a = document.querySelector('[data-sidebar-tab-count="agents"]');
|
|
7068
|
-
if (a) a.textContent = String(agentsCount);
|
|
7069
|
-
},
|
|
7070
|
-
|
|
7071
7022
|
// ── Rendering · main view ─────────────────────────────────
|
|
7072
7023
|
renderRoom() {
|
|
7073
7024
|
this.renderHeader();
|
|
@@ -9665,61 +9616,11 @@
|
|
|
9665
9616
|
return;
|
|
9666
9617
|
}
|
|
9667
9618
|
// Patch local cache so the immediate re-render reflects the
|
|
9668
|
-
// delete without a refetch round-trip.
|
|
9669
|
-
// re-fetches via the /count endpoint.
|
|
9619
|
+
// delete without a refetch round-trip.
|
|
9670
9620
|
if (Array.isArray(this._notesCache)) {
|
|
9671
9621
|
this._notesCache = this._notesCache.filter((n) => n && n.id !== id);
|
|
9672
9622
|
this.renderNotesPage(this._notesCache);
|
|
9673
9623
|
}
|
|
9674
|
-
this.refreshNotesCount();
|
|
9675
|
-
},
|
|
9676
|
-
|
|
9677
|
-
/** Refresh the sidebar count badge · called on boot, after
|
|
9678
|
-
* every successful save (note:created event), and after a
|
|
9679
|
-
* delete. Hits /api/notes/count which is cheap (one COUNT query),
|
|
9680
|
-
* so we don't need to debounce.
|
|
9681
|
-
*
|
|
9682
|
-
* When count is 0 the badge is hidden (the `hidden` attr stays
|
|
9683
|
-
* on); otherwise the count renders. The CSS bumps the colour to
|
|
9684
|
-
* lime on hover/active so the badge tracks the link's cascade. */
|
|
9685
|
-
async refreshNotesCount() {
|
|
9686
|
-
try {
|
|
9687
|
-
const r = await fetch("/api/notes/count");
|
|
9688
|
-
if (!r.ok) return;
|
|
9689
|
-
const j = await r.json();
|
|
9690
|
-
const total = typeof j.total === "number" ? j.total : 0;
|
|
9691
|
-
const badge = document.querySelector("[data-notes-count]");
|
|
9692
|
-
if (!badge) return;
|
|
9693
|
-
if (total > 0) {
|
|
9694
|
-
badge.textContent = String(total);
|
|
9695
|
-
badge.removeAttribute("hidden");
|
|
9696
|
-
} else {
|
|
9697
|
-
badge.textContent = "";
|
|
9698
|
-
badge.setAttribute("hidden", "");
|
|
9699
|
-
}
|
|
9700
|
-
} catch { /* fail closed — leave badge as-is */ }
|
|
9701
|
-
},
|
|
9702
|
-
|
|
9703
|
-
/** Mirror of refreshNotesCount for the All Reports sidebar badge.
|
|
9704
|
-
* Hits /api/briefs/count (cheap COUNT, excludes empty placeholder
|
|
9705
|
-
* rows). Called on boot and whenever a brief is filed / deleted
|
|
9706
|
-
* so the badge stays in sync with the All Reports list. */
|
|
9707
|
-
async refreshReportsCount() {
|
|
9708
|
-
try {
|
|
9709
|
-
const r = await fetch("/api/briefs/count");
|
|
9710
|
-
if (!r.ok) return;
|
|
9711
|
-
const j = await r.json();
|
|
9712
|
-
const total = typeof j.total === "number" ? j.total : 0;
|
|
9713
|
-
const badge = document.querySelector("[data-reports-count]");
|
|
9714
|
-
if (!badge) return;
|
|
9715
|
-
if (total > 0) {
|
|
9716
|
-
badge.textContent = String(total);
|
|
9717
|
-
badge.removeAttribute("hidden");
|
|
9718
|
-
} else {
|
|
9719
|
-
badge.textContent = "";
|
|
9720
|
-
badge.setAttribute("hidden", "");
|
|
9721
|
-
}
|
|
9722
|
-
} catch { /* fail closed */ }
|
|
9723
9624
|
},
|
|
9724
9625
|
|
|
9725
9626
|
// ── In-room note highlight overlay ────────────────────────
|
package/public/home.html
CHANGED
|
@@ -1622,7 +1622,7 @@
|
|
|
1622
1622
|
|
|
1623
1623
|
<div class="hero-actions">
|
|
1624
1624
|
<a href="#install" class="big-btn primary">[ ◆ Convene a Room ]</a>
|
|
1625
|
-
<a href="https://github.com/kaysaith1900/privateboard/releases/download/v0.1.
|
|
1625
|
+
<a href="https://github.com/kaysaith1900/privateboard/releases/download/v0.1.31/PrivateBoard-0.1.31-arm64.dmg"
|
|
1626
1626
|
class="big-btn secondary"
|
|
1627
1627
|
download
|
|
1628
1628
|
aria-label="Download PrivateBoard for macOS (Apple Silicon)"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M12 3v12"/><polyline points="6 11 12 17 18 11"/><path d="M5 21h14"/></svg> Download for Mac</a>
|
package/public/i18n.js
CHANGED
|
@@ -531,7 +531,7 @@
|
|
|
531
531
|
// Meeting recording · head button + REC pill + exit modal.
|
|
532
532
|
head_record_tip: "Record meeting",
|
|
533
533
|
head_record_label: "Record meeting",
|
|
534
|
-
head_record_stop_tip: "Stop recording · save .
|
|
534
|
+
head_record_stop_tip: "Stop recording · save .mp4",
|
|
535
535
|
head_record_stop_label: "Stop recording",
|
|
536
536
|
rec_pill_label: "REC",
|
|
537
537
|
rec_error_toast: "Couldn't start the meeting recording. Check screen-capture permission and try again.",
|
|
@@ -541,7 +541,7 @@
|
|
|
541
541
|
rec_exit_title: "Stop the recording before you leave?",
|
|
542
542
|
rec_exit_deck: "The meeting is still being captured. Stop now to save the file; otherwise the in-flight chunks are discarded.",
|
|
543
543
|
rec_exit_stop_mark: "▍ Stop & save",
|
|
544
|
-
rec_exit_stop_deck: "End the recording, download the .
|
|
544
|
+
rec_exit_stop_deck: "End the recording, download the .mp4, then continue.",
|
|
545
545
|
rec_exit_cancel_mark: "↩ Cancel",
|
|
546
546
|
rec_exit_cancel_deck: "Stay here · the recording keeps running.",
|
|
547
547
|
// Stop-recording choice modal · how to handle the live room.
|
|
@@ -1752,7 +1752,7 @@ When the room ___, raise an objection.`,
|
|
|
1752
1752
|
// 会议录制 · header 按钮 + REC 提示牌 + 退出弹窗
|
|
1753
1753
|
head_record_tip: "录制会议",
|
|
1754
1754
|
head_record_label: "录制会议",
|
|
1755
|
-
head_record_stop_tip: "停止录制 · 保存 .
|
|
1755
|
+
head_record_stop_tip: "停止录制 · 保存 .mp4",
|
|
1756
1756
|
head_record_stop_label: "停止录制",
|
|
1757
1757
|
rec_pill_label: "录制中",
|
|
1758
1758
|
rec_error_toast: "无法开始会议录制。请检查屏幕录制权限后重试。",
|
|
@@ -1762,7 +1762,7 @@ When the room ___, raise an objection.`,
|
|
|
1762
1762
|
rec_exit_title: "离开前先停止录制?",
|
|
1763
1763
|
rec_exit_deck: "会议正在录制中。现在停止可以保存视频文件;否则正在采集的最后片段将被丢弃。",
|
|
1764
1764
|
rec_exit_stop_mark: "▍ 停止并保存",
|
|
1765
|
-
rec_exit_stop_deck: "结束录制,下载 .
|
|
1765
|
+
rec_exit_stop_deck: "结束录制,下载 .mp4 后再继续。",
|
|
1766
1766
|
rec_exit_cancel_mark: "↩ 取消",
|
|
1767
1767
|
rec_exit_cancel_deck: "留在这里 · 录制继续。",
|
|
1768
1768
|
// 停止录制 · 选择如何处理当前 live 房间
|
|
@@ -2899,7 +2899,7 @@ When the room ___, raise an objection.`,
|
|
|
2899
2899
|
// ミーティング録画 · ヘッダーボタン + REC バッジ + 退出ダイアログ
|
|
2900
2900
|
head_record_tip: "ミーティングを録画",
|
|
2901
2901
|
head_record_label: "ミーティングを録画",
|
|
2902
|
-
head_record_stop_tip: "録画を停止 · .
|
|
2902
|
+
head_record_stop_tip: "録画を停止 · .mp4 を保存",
|
|
2903
2903
|
head_record_stop_label: "録画を停止",
|
|
2904
2904
|
rec_pill_label: "録画中",
|
|
2905
2905
|
rec_error_toast: "ミーティングの録画を開始できませんでした。画面録画の権限を確認してください。",
|
|
@@ -2909,7 +2909,7 @@ When the room ___, raise an objection.`,
|
|
|
2909
2909
|
rec_exit_title: "退出前に録画を停止しますか?",
|
|
2910
2910
|
rec_exit_deck: "ミーティングを録画中です。停止すれば動画ファイルを保存できます。停止しないと録画中のチャンクは破棄されます。",
|
|
2911
2911
|
rec_exit_stop_mark: "▍ 停止して保存",
|
|
2912
|
-
rec_exit_stop_deck: "録画を終了し .
|
|
2912
|
+
rec_exit_stop_deck: "録画を終了し .mp4 をダウンロードしてから続行。",
|
|
2913
2913
|
rec_exit_cancel_mark: "↩ キャンセル",
|
|
2914
2914
|
rec_exit_cancel_deck: "ここに留まる · 録画は続行されます。",
|
|
2915
2915
|
// 録画停止 · ライブルームの扱いを選択
|
|
@@ -3806,7 +3806,7 @@ When the room ___, raise an objection.`,
|
|
|
3806
3806
|
// Grabación de reunión · botón en cabecera + chip REC + modal de salida
|
|
3807
3807
|
head_record_tip: "Grabar reunión",
|
|
3808
3808
|
head_record_label: "Grabar reunión",
|
|
3809
|
-
head_record_stop_tip: "Detener grabación · guardar .
|
|
3809
|
+
head_record_stop_tip: "Detener grabación · guardar .mp4",
|
|
3810
3810
|
head_record_stop_label: "Detener grabación",
|
|
3811
3811
|
rec_pill_label: "GRAB.",
|
|
3812
3812
|
rec_error_toast: "No se pudo iniciar la grabación. Revisa el permiso de captura de pantalla e inténtalo de nuevo.",
|
|
@@ -3816,7 +3816,7 @@ When the room ___, raise an objection.`,
|
|
|
3816
3816
|
rec_exit_title: "¿Detener la grabación antes de salir?",
|
|
3817
3817
|
rec_exit_deck: "La reunión sigue grabándose. Detén ahora para guardar el archivo; de lo contrario se descartan los fragmentos en curso.",
|
|
3818
3818
|
rec_exit_stop_mark: "▍ Detener y guardar",
|
|
3819
|
-
rec_exit_stop_deck: "Termina la grabación, descarga el .
|
|
3819
|
+
rec_exit_stop_deck: "Termina la grabación, descarga el .mp4 y luego continúa.",
|
|
3820
3820
|
rec_exit_cancel_mark: "↩ Cancelar",
|
|
3821
3821
|
rec_exit_cancel_deck: "Quédate aquí · la grabación sigue corriendo.",
|
|
3822
3822
|
// Modal · cómo manejar la sala en vivo al detener la grabación
|