dsh-figmark 1.2.3 → 1.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -0
- package/lib/client.js +523 -337
- package/lib/index.js +20 -5
- package/market/index.json +2 -2
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -73,15 +73,17 @@ window.__ModuleLoader__.load({
|
|
|
73
73
|
reveal_hidden: "元素目前不可见,请先展开或翻到对应页面",
|
|
74
74
|
reveal_wrong_surface: "无法切换到标注所在的页面",
|
|
75
75
|
reveal_timeout: "页面没有响应定位请求",
|
|
76
|
-
serviceKicker: "LOCAL RUNTIME",
|
|
77
76
|
serviceTitle: "本机网页",
|
|
78
|
-
serviceHint: "
|
|
79
|
-
serviceSearch: "
|
|
77
|
+
serviceHint: "打开正在运行的本机网页,直接圈画与批注。",
|
|
78
|
+
serviceSearch: "搜索页面,或输入 localhost:5173",
|
|
80
79
|
serviceOpen: "打开",
|
|
81
80
|
serviceOpening: "正在连接",
|
|
82
81
|
serviceLocal: "正在运行",
|
|
83
82
|
serviceScanning: "检索中",
|
|
84
83
|
serviceRescan: "重新检索",
|
|
84
|
+
serviceNoMatch: "没有匹配的页面",
|
|
85
|
+
serviceChooseMatch: "找到多个页面,请选择下方的一项。",
|
|
86
|
+
serviceSearchHint: "换个关键词,或输入完整的本机地址。",
|
|
85
87
|
serviceEmpty: "没有发现本机服务",
|
|
86
88
|
serviceEmptyHint: "先启动开发服务器,或在上方直接输入地址。",
|
|
87
89
|
serviceBadAddress: "请输入本机 HTTP 地址",
|
|
@@ -169,18 +171,25 @@ window.__ModuleLoader__.load({
|
|
|
169
171
|
detailHint: "当前选中",
|
|
170
172
|
detailUnset: "未选中",
|
|
171
173
|
detailIdle: "在图上点一下、框一块或画一笔,就能为那处写说明。",
|
|
172
|
-
cardOpen: "
|
|
174
|
+
cardOpen: "打开原文件",
|
|
173
175
|
cardOpenLive: "回到本机网页",
|
|
174
176
|
cardCaptureOmitted: "位置标注",
|
|
175
177
|
cardCaptureFailed: "截图失败",
|
|
176
|
-
cardMore: "
|
|
178
|
+
cardMore: "查看其余 {n} 处",
|
|
179
|
+
cardExpand: "查看完整批注",
|
|
180
|
+
cardCollapse: "收起详情",
|
|
181
|
+
cardOpenFailed: "未能打开原内容,请重试。",
|
|
177
182
|
cardGoal: "目标",
|
|
178
183
|
cardPage: "第 {n} 页",
|
|
184
|
+
cardPages: "共 {n} 页",
|
|
179
185
|
cardCount: "{n} 处标注",
|
|
180
186
|
pendingCount: "{n}",
|
|
181
187
|
pendingRemove: "移除附图标注",
|
|
182
|
-
pendingSendHint: "
|
|
183
|
-
|
|
188
|
+
pendingSendHint: "发送当前消息及全部待发送标注",
|
|
189
|
+
pendingSendMessage: "发送消息",
|
|
190
|
+
pendingSending: "发送中…",
|
|
191
|
+
pendingUnavailable: "当前输入框暂时无法发送。",
|
|
192
|
+
pendingSendNow: "发送这份标注",
|
|
184
193
|
pendingFailed: "没能发送:"
|
|
185
194
|
};
|
|
186
195
|
/** English copy. */
|
|
@@ -223,15 +232,17 @@ window.__ModuleLoader__.load({
|
|
|
223
232
|
reveal_hidden: "The element is not visible yet",
|
|
224
233
|
reveal_wrong_surface: "Could not switch to the mark’s page",
|
|
225
234
|
reveal_timeout: "The page did not answer the locate request",
|
|
226
|
-
serviceKicker: "LOCAL RUNTIME",
|
|
227
235
|
serviceTitle: "Local pages",
|
|
228
|
-
serviceHint: "
|
|
229
|
-
serviceSearch: "
|
|
236
|
+
serviceHint: "Open a running local page to draw and comment.",
|
|
237
|
+
serviceSearch: "Find a page or enter localhost:5173",
|
|
230
238
|
serviceOpen: "Open",
|
|
231
239
|
serviceOpening: "Connecting",
|
|
232
240
|
serviceLocal: "Running",
|
|
233
241
|
serviceScanning: "Scanning",
|
|
234
242
|
serviceRescan: "Scan again",
|
|
243
|
+
serviceNoMatch: "No matching pages",
|
|
244
|
+
serviceChooseMatch: "Several pages match. Choose one below.",
|
|
245
|
+
serviceSearchHint: "Try another keyword or enter the full local address.",
|
|
235
246
|
serviceEmpty: "No local services found",
|
|
236
247
|
serviceEmptyHint: "Start a development server, or type its address above.",
|
|
237
248
|
serviceBadAddress: "Enter a local HTTP address",
|
|
@@ -319,18 +330,25 @@ window.__ModuleLoader__.load({
|
|
|
319
330
|
detailHint: "selected",
|
|
320
331
|
detailUnset: "nothing selected",
|
|
321
332
|
detailIdle: "Click the figure, or box a region or draw a stroke, to write about that spot.",
|
|
322
|
-
cardOpen: "Open
|
|
333
|
+
cardOpen: "Open source file",
|
|
323
334
|
cardOpenLive: "Return to the local page",
|
|
324
335
|
cardCaptureOmitted: "location only",
|
|
325
336
|
cardCaptureFailed: "screenshot failed",
|
|
326
|
-
cardMore: "
|
|
337
|
+
cardMore: "Show {n} more",
|
|
338
|
+
cardExpand: "Review all annotations",
|
|
339
|
+
cardCollapse: "Collapse details",
|
|
340
|
+
cardOpenFailed: "Could not open the source. Try again.",
|
|
327
341
|
cardGoal: "Goal",
|
|
328
342
|
cardPage: "page {n}",
|
|
343
|
+
cardPages: "{n} pages",
|
|
329
344
|
cardCount: "{n} annotations",
|
|
330
345
|
pendingCount: "{n}",
|
|
331
346
|
pendingRemove: "Remove the annotation",
|
|
332
|
-
pendingSendHint: "Send
|
|
333
|
-
|
|
347
|
+
pendingSendHint: "Send the message and all staged reviews",
|
|
348
|
+
pendingSendMessage: "Send message",
|
|
349
|
+
pendingSending: "Sending…",
|
|
350
|
+
pendingUnavailable: "This composer cannot send right now.",
|
|
351
|
+
pendingSendNow: "Send this review",
|
|
334
352
|
pendingFailed: "Could not send: "
|
|
335
353
|
};
|
|
336
354
|
/** Locale namespace this dictionary registers under. */
|
|
@@ -3970,6 +3988,7 @@ window.__ModuleLoader__.load({
|
|
|
3970
3988
|
style: { pointerEvents: "none" },
|
|
3971
3989
|
children: [boxed ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
|
|
3972
3990
|
"data-da-element-box": mark.id,
|
|
3991
|
+
onPointerDown: props.onPress,
|
|
3973
3992
|
x: box.x,
|
|
3974
3993
|
y: box.y,
|
|
3975
3994
|
width: box.width,
|
|
@@ -4001,7 +4020,8 @@ window.__ModuleLoader__.load({
|
|
|
4001
4020
|
const code = elideCode(anchorCodeName(mark.anchor));
|
|
4002
4021
|
const pad = 4 * unit;
|
|
4003
4022
|
const fontSize = CODE_FONT_SIZE * unit;
|
|
4004
|
-
const
|
|
4023
|
+
const advance = Array.from(code).reduce((sum, char) => sum + (char.charCodeAt(0) > 255 ? 1 : .62), 0);
|
|
4024
|
+
const width = Math.min(advance * fontSize + pad * 2, Math.max(pad * 2, paper.right - paper.left));
|
|
4005
4025
|
const height = fontSize + pad * 1.6;
|
|
4006
4026
|
const gap = 4 * unit;
|
|
4007
4027
|
const limit = Math.max(paper.left, paper.right - width);
|
|
@@ -4019,17 +4039,27 @@ window.__ModuleLoader__.load({
|
|
|
4019
4039
|
fillOpacity: .94,
|
|
4020
4040
|
stroke: mark.color,
|
|
4021
4041
|
strokeWidth: 1.2 * unit
|
|
4022
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("
|
|
4023
|
-
"data-da-element-code": mark.id,
|
|
4042
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("foreignObject", {
|
|
4024
4043
|
x: x + pad,
|
|
4025
|
-
y
|
|
4026
|
-
|
|
4027
|
-
|
|
4028
|
-
|
|
4029
|
-
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
4044
|
+
y,
|
|
4045
|
+
width: Math.max(0, width - pad * 2),
|
|
4046
|
+
height,
|
|
4047
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4048
|
+
"data-da-element-code": mark.id,
|
|
4049
|
+
title: anchorCodeName(mark.anchor),
|
|
4050
|
+
style: {
|
|
4051
|
+
display: "block",
|
|
4052
|
+
overflow: "hidden",
|
|
4053
|
+
textOverflow: "ellipsis",
|
|
4054
|
+
whiteSpace: "nowrap",
|
|
4055
|
+
fontFamily: CODE_FONT_FAMILY,
|
|
4056
|
+
fontSize,
|
|
4057
|
+
fontWeight: 600,
|
|
4058
|
+
color: CODE_TEXT_COLOR,
|
|
4059
|
+
lineHeight: `${height}px`
|
|
4060
|
+
},
|
|
4061
|
+
children: code
|
|
4062
|
+
})
|
|
4033
4063
|
})] });
|
|
4034
4064
|
}
|
|
4035
4065
|
/** One mark: its shape, its hit area, and whatever its selection asks for. */
|
|
@@ -4120,7 +4150,10 @@ window.__ModuleLoader__.load({
|
|
|
4120
4150
|
bottom: -props.originY + props.height - 2
|
|
4121
4151
|
},
|
|
4122
4152
|
boxed: props.elementExtent === "box",
|
|
4123
|
-
named: selected
|
|
4153
|
+
named: selected,
|
|
4154
|
+
onPress: (event) => {
|
|
4155
|
+
onPressMark(mark, event);
|
|
4156
|
+
}
|
|
4124
4157
|
}),
|
|
4125
4158
|
selected && !isDraft && isPoint ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FixedFrame, {
|
|
4126
4159
|
box: pointMarkBox(shown, unit),
|
|
@@ -4815,14 +4848,14 @@ window.__ModuleLoader__.load({
|
|
|
4815
4848
|
* Upload one file as a draft attachment without putting it in the rail yet.
|
|
4816
4849
|
* @param conversation - the conversation service.
|
|
4817
4850
|
* @param sessionId - session the draft belongs to.
|
|
4818
|
-
* @param
|
|
4851
|
+
* @param files - the rendered review images to hold.
|
|
4819
4852
|
* @returns the ids the send will add, empty when the file could not be made into one.
|
|
4820
4853
|
*/
|
|
4821
|
-
function
|
|
4854
|
+
function holdFiles(conversation, sessionId, files) {
|
|
4822
4855
|
const create = conversation.createDrafts?.bind(conversation);
|
|
4823
|
-
if (
|
|
4856
|
+
if (files.length === 0 || create === void 0) return [];
|
|
4824
4857
|
try {
|
|
4825
|
-
return create(sessionId,
|
|
4858
|
+
return create(sessionId, files);
|
|
4826
4859
|
} catch {
|
|
4827
4860
|
return [];
|
|
4828
4861
|
}
|
|
@@ -4833,9 +4866,10 @@ window.__ModuleLoader__.load({
|
|
|
4833
4866
|
* @param sessionId - session the draft belongs to.
|
|
4834
4867
|
* @param message - the message, verbatim.
|
|
4835
4868
|
* @param file - the review picture, when the surface has one to attach.
|
|
4869
|
+
* @param additionalFiles - marked page images of a multi-page review.
|
|
4836
4870
|
* @returns what was armed, or undefined when this session cannot be armed.
|
|
4837
4871
|
*/
|
|
4838
|
-
function armReview(conversation, sessionId, message, file) {
|
|
4872
|
+
function armReview(conversation, sessionId, message, file, additionalFiles = []) {
|
|
4839
4873
|
let shell;
|
|
4840
4874
|
try {
|
|
4841
4875
|
shell = conversation.input.shell(sessionId);
|
|
@@ -4843,10 +4877,12 @@ window.__ModuleLoader__.load({
|
|
|
4843
4877
|
return;
|
|
4844
4878
|
}
|
|
4845
4879
|
if (typeof shell.submit !== "function") return void 0;
|
|
4880
|
+
const drafts = holdFiles(conversation, sessionId, file === void 0 ? additionalFiles : [file, ...additionalFiles]);
|
|
4846
4881
|
return {
|
|
4847
4882
|
shell,
|
|
4848
4883
|
text: message,
|
|
4849
|
-
attachmentIds:
|
|
4884
|
+
attachmentIds: drafts.map((draft) => draft.id),
|
|
4885
|
+
previewUrls: drafts.flatMap((draft) => draft.previewUrl === void 0 ? [] : [draft.previewUrl])
|
|
4850
4886
|
};
|
|
4851
4887
|
}
|
|
4852
4888
|
/**
|
|
@@ -4909,12 +4945,13 @@ window.__ModuleLoader__.load({
|
|
|
4909
4945
|
for (const claim of claims) {
|
|
4910
4946
|
const { text, attachmentIds } = claim.armed;
|
|
4911
4947
|
if (draft.includes(text)) continue;
|
|
4912
|
-
|
|
4913
|
-
|
|
4948
|
+
const missing = attachmentIds.filter((id) => !live.attachmentIds?.includes(id));
|
|
4949
|
+
if (missing.length > 0) {
|
|
4950
|
+
if (!attach(shell, missing)) {
|
|
4914
4951
|
unwind(shell, typed, added);
|
|
4915
4952
|
return;
|
|
4916
4953
|
}
|
|
4917
|
-
added.push(...
|
|
4954
|
+
added.push(...missing);
|
|
4918
4955
|
}
|
|
4919
4956
|
draft = draft.trim() === "" ? text : `${draft}\n\n${text}`;
|
|
4920
4957
|
}
|
|
@@ -4959,22 +4996,34 @@ window.__ModuleLoader__.load({
|
|
|
4959
4996
|
try {
|
|
4960
4997
|
live = shell.snapshot;
|
|
4961
4998
|
} catch {
|
|
4962
|
-
for (const claim of claims)
|
|
4999
|
+
for (const claim of claims) {
|
|
5000
|
+
claim.armed.admission?.release();
|
|
5001
|
+
claim.done();
|
|
5002
|
+
}
|
|
4963
5003
|
return;
|
|
4964
5004
|
}
|
|
4965
5005
|
if (live.phase !== void 0 && live.phase !== "plain") {
|
|
4966
|
-
for (const claim of claims)
|
|
5006
|
+
for (const claim of claims) {
|
|
5007
|
+
claim.armed.admission?.release();
|
|
5008
|
+
claim.done();
|
|
5009
|
+
}
|
|
4967
5010
|
return;
|
|
4968
5011
|
}
|
|
4969
5012
|
const draft = live.draft;
|
|
4970
5013
|
if (claims.every((claim) => !draft.includes(claim.armed.text))) {
|
|
4971
|
-
for (const claim of claims)
|
|
5014
|
+
for (const claim of claims) {
|
|
5015
|
+
claim.armed.admission?.release();
|
|
5016
|
+
claim.done();
|
|
5017
|
+
}
|
|
4972
5018
|
return;
|
|
4973
5019
|
}
|
|
4974
5020
|
try {
|
|
4975
5021
|
shell.setDraft(merge.typed);
|
|
4976
5022
|
} catch {}
|
|
4977
|
-
for (const claim of claims)
|
|
5023
|
+
for (const claim of claims) {
|
|
5024
|
+
if (claim.armed.admission !== void 0) attach(shell, claim.armed.admission.ids.filter((id) => !live.attachmentIds?.includes(id)));
|
|
5025
|
+
if (claim.armed.staged !== true) for (const id of claim.armed.attachmentIds) shell.removeAttachment?.(id);
|
|
5026
|
+
}
|
|
4978
5027
|
}
|
|
4979
5028
|
/**
|
|
4980
5029
|
* Take one card off whatever patch its shell is currently carrying.
|
|
@@ -5046,10 +5095,11 @@ window.__ModuleLoader__.load({
|
|
|
5046
5095
|
}
|
|
5047
5096
|
const send = () => {
|
|
5048
5097
|
try {
|
|
5098
|
+
for (const claim of claims) for (const id of claim.armed.admission?.ids ?? []) if (shell.removeAttachment?.(id) !== true) return;
|
|
5049
5099
|
original.apply(shell, args);
|
|
5050
|
-
settleClaims(shell, claims, merge);
|
|
5051
5100
|
} finally {
|
|
5052
5101
|
waiting = false;
|
|
5102
|
+
settleClaims(shell, claims, merge);
|
|
5053
5103
|
}
|
|
5054
5104
|
};
|
|
5055
5105
|
if (wroteThrough(shell, merge)) {
|
|
@@ -5102,13 +5152,39 @@ window.__ModuleLoader__.load({
|
|
|
5102
5152
|
*/
|
|
5103
5153
|
function parkInComposer(input) {
|
|
5104
5154
|
const { document: document_, locale, paths, sessionId } = input;
|
|
5105
|
-
|
|
5155
|
+
let armed = input.conversation === void 0 ? void 0 : armReview(input.conversation, sessionId, "", input.file, input.files);
|
|
5156
|
+
const planned = (input.file === void 0 ? 0 : 1) + (input.files?.length ?? 0);
|
|
5157
|
+
const attached = armed?.attachmentIds.length ?? planned;
|
|
5158
|
+
const pageCapture = input.pageCapture === "attached" && attached === 0 ? "failed" : input.pageCapture;
|
|
5159
|
+
const message = buildAnnotationMessage(document_, paths, locale, attached > 0, Math.min(input.pageImages ?? 0, attached), pageCapture);
|
|
5160
|
+
if (armed !== void 0 && input.conversation !== void 0) {
|
|
5161
|
+
const admission = armed.attachmentIds.length === 0;
|
|
5162
|
+
const drafts = admission && armed.shell.removeAttachment !== void 0 ? holdFiles(input.conversation, sessionId, [new File([Uint8Array.from(atob("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII="), (char) => char.charCodeAt(0))], "figmark-draft.png", { type: "image/png" })]) : [];
|
|
5163
|
+
const ids = admission ? drafts.map((draft) => draft.id) : armed.attachmentIds;
|
|
5164
|
+
const conversation = input.conversation;
|
|
5165
|
+
if (ids.length > 0 && attach(armed.shell, ids)) armed = {
|
|
5166
|
+
...armed,
|
|
5167
|
+
attachmentIds: ids,
|
|
5168
|
+
staged: true,
|
|
5169
|
+
...admission ? {
|
|
5170
|
+
previewUrls: drafts.flatMap((draft) => draft.previewUrl === void 0 ? [] : [draft.previewUrl]),
|
|
5171
|
+
admission: {
|
|
5172
|
+
ids,
|
|
5173
|
+
release: () => {
|
|
5174
|
+
for (const id of ids) conversation.releaseDraftAttachment?.(id);
|
|
5175
|
+
}
|
|
5176
|
+
}
|
|
5177
|
+
} : {}
|
|
5178
|
+
};
|
|
5179
|
+
else {
|
|
5180
|
+
for (const id of ids) conversation.releaseDraftAttachment?.(id);
|
|
5181
|
+
armed = void 0;
|
|
5182
|
+
}
|
|
5183
|
+
}
|
|
5106
5184
|
rememberDelivered(message, input.thumb);
|
|
5107
|
-
const block = matchAnnotation(message, 0);
|
|
5108
|
-
const armed = input.conversation === void 0 ? void 0 : armReview(input.conversation, sessionId, message, input.file);
|
|
5109
5185
|
parkAnnotation({
|
|
5110
5186
|
sessionId,
|
|
5111
|
-
data:
|
|
5187
|
+
data: matchAnnotation(message, 0)?.data ?? {
|
|
5112
5188
|
file: document_.figure.path,
|
|
5113
5189
|
scope: "",
|
|
5114
5190
|
target: "",
|
|
@@ -5119,7 +5195,10 @@ window.__ModuleLoader__.load({
|
|
|
5119
5195
|
},
|
|
5120
5196
|
raw: message,
|
|
5121
5197
|
conversation: input.conversation,
|
|
5122
|
-
armed
|
|
5198
|
+
armed: armed === void 0 ? void 0 : {
|
|
5199
|
+
...armed,
|
|
5200
|
+
text: message
|
|
5201
|
+
},
|
|
5123
5202
|
send: input.send
|
|
5124
5203
|
});
|
|
5125
5204
|
}
|
|
@@ -8563,12 +8642,13 @@ body[data-ds-dark-theme] .da-root{--da-quiet:#9aa0a8}
|
|
|
8563
8642
|
/* The hand-off appears only once the field says something: an empty pill is a
|
|
8564
8643
|
place to type, not a decision to make. */
|
|
8565
8644
|
.da-comment-send{display:flex;align-items:center;gap:4px;flex:0 0 auto;padding-bottom:3px;padding-right:3px}
|
|
8645
|
+
.da-comment-remove{flex:0 0 30px;margin-bottom:3px}
|
|
8566
8646
|
.da-comment-send-btn{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;
|
|
8567
8647
|
border:0;border-radius:50%;background:var(--dsw-alias-interactive-bg-hover,rgba(127,127,127,.12));
|
|
8568
8648
|
color:var(--dsw-alias-label-secondary,currentColor);cursor:pointer;padding:0}
|
|
8569
8649
|
.da-comment-send-btn:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(127,127,127,.2));
|
|
8570
8650
|
color:var(--dsw-alias-label-primary,currentColor)}
|
|
8571
|
-
.da-comment-send-btn:disabled{opacity:.45;cursor:default}
|
|
8651
|
+
.da-comment-send-btn[aria-disabled="true"],.da-comment-send-btn:disabled{opacity:.45;cursor:default}
|
|
8572
8652
|
.da-comment-send-btn svg{width:15px;height:15px}
|
|
8573
8653
|
/* Both ways out of the pill are the same neutral chip. Which hand-off is "primary"
|
|
8574
8654
|
is the reader's judgement at the moment of sending, not something the panel gets to
|
|
@@ -8792,11 +8872,11 @@ body[data-ds-dark-theme] .da-root{--da-quiet:#9aa0a8}
|
|
|
8792
8872
|
border:0.5px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));border-radius:12px;
|
|
8793
8873
|
background:var(--dsw-alias-bg-base,rgba(255,255,255,.72));
|
|
8794
8874
|
box-shadow:0 1px 2px rgba(20,40,80,.04);white-space:normal}
|
|
8795
|
-
|
|
8796
|
-
|
|
8797
|
-
|
|
8798
|
-
|
|
8799
|
-
.da-card-head{display:flex;align-items:center;gap:8px;min-width:0;padding:7px 9px;
|
|
8875
|
+
/* Review, source navigation and delivery are separate native buttons. */
|
|
8876
|
+
.da-card button,.da-staged-send{appearance:none;font:inherit;color:inherit;cursor:pointer}
|
|
8877
|
+
.da-card button:focus-visible,.da-staged-send:focus-visible{outline:2px solid var(--da-accent,#176df2);outline-offset:-2px}
|
|
8878
|
+
.da-card button:hover,.da-staged-send:hover{background:var(--dsw-alias-bg-layer-2,rgba(128,128,128,.08));color:var(--da-accent,#176df2)}
|
|
8879
|
+
.da-card-head{width:100%;box-sizing:border-box;border:0;text-align:left;display:flex;align-items:center;gap:8px;min-width:0;padding:7px 9px;
|
|
8800
8880
|
border-bottom:0.5px solid var(--dsw-alias-border-l2,rgba(128,128,128,.2));
|
|
8801
8881
|
background:var(--dsw-alias-bg-layer-1,rgba(128,128,128,.025))}
|
|
8802
8882
|
.da-card-shot{position:relative;display:flex;flex:0 0 auto;align-items:center;justify-content:center;width:34px;height:34px;overflow:hidden;border-radius:7px;
|
|
@@ -8804,7 +8884,7 @@ button.da-card:focus-visible{outline:2px solid var(--da-accent,#176df2);outline-
|
|
|
8804
8884
|
background:var(--dsw-alias-bg-layer-3,rgba(128,128,128,.1));color:var(--da-accent,#176df2)}
|
|
8805
8885
|
/* The picture covers the glyph; a picture that fails hides itself, and the glyph
|
|
8806
8886
|
underneath it all along is what is left. A miss is never an empty box. */
|
|
8807
|
-
.da-card-shot img{position:absolute;inset:0;width:100%;height:100%;object-fit:
|
|
8887
|
+
.da-card-shot img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain}
|
|
8808
8888
|
.da-card-shot img[hidden]{display:none}
|
|
8809
8889
|
.da-card-glyph{width:18px;height:18px}
|
|
8810
8890
|
.da-card-text{display:flex;flex:1 1 auto;flex-direction:column;gap:2px;min-width:0}
|
|
@@ -8827,10 +8907,11 @@ button.da-card:focus-visible{outline:2px solid var(--da-accent,#176df2);outline-
|
|
|
8827
8907
|
border-radius:50%;background:var(--dsw-alias-bg-layer-3,rgba(128,128,128,.1));
|
|
8828
8908
|
color:var(--dsw-alias-label-tertiary,inherit)}
|
|
8829
8909
|
.da-card-go svg{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round}
|
|
8830
|
-
|
|
8910
|
+
.da-card-head:hover .da-card-go{background:var(--da-accent-soft,rgba(23,109,242,.14));color:var(--da-accent,#176df2)}
|
|
8831
8911
|
/* Each mark is a compact record, not a line of debug output. The row head answers
|
|
8832
8912
|
"which mark and where"; the element name and selector follow only when the message
|
|
8833
8913
|
carried them; the reader's sentence is the strongest text. */
|
|
8914
|
+
.da-card[data-expanded="true"] .da-card-go{transform:rotate(90deg)}
|
|
8834
8915
|
.da-card-body{display:flex;flex-direction:column;min-width:0;padding:0 9px 2px}
|
|
8835
8916
|
.da-card-row{display:flex;flex-direction:column;gap:2px;min-width:0;padding:6px 0}
|
|
8836
8917
|
.da-card-row+.da-card-row{border-top:0.5px solid var(--dsw-alias-border-l2,rgba(128,128,128,.14))}
|
|
@@ -8932,21 +9013,33 @@ button.da-card:hover .da-card-go{background:var(--da-accent-soft,rgba(23,109,242
|
|
|
8932
9013
|
background:none;font:inherit;font-size:13px;line-height:1;cursor:pointer;opacity:.65}
|
|
8933
9014
|
.da-staged-result-x:hover{opacity:1;background:var(--dsw-alias-bg-layer-2,rgba(255,255,255,.72))}
|
|
8934
9015
|
.da-staged-result-x:focus-visible{outline:2px solid var(--da-accent,#176df2);outline-offset:1px}
|
|
8935
|
-
/*
|
|
8936
|
-
|
|
8937
|
-
|
|
8938
|
-
|
|
8939
|
-
|
|
8940
|
-
|
|
8941
|
-
|
|
8942
|
-
|
|
8943
|
-
|
|
8944
|
-
|
|
8945
|
-
|
|
8946
|
-
|
|
8947
|
-
|
|
8948
|
-
|
|
8949
|
-
[data-
|
|
9016
|
+
/* Attachments belong to the message. A review may carry several PDF pages,
|
|
9017
|
+
and a message may also carry unrelated files; its source is not that snapshot. */
|
|
9018
|
+
.da-card-actions{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:4px;padding:3px 5px;
|
|
9019
|
+
border-top:0.5px solid var(--dsw-alias-border-l2,rgba(128,128,128,.2))}
|
|
9020
|
+
.da-card-toggle,.da-card-source{border:0;border-radius:6px;background:none;padding:6px 4px;min-height:30px;font-size:11px!important}
|
|
9021
|
+
.da-card-source{color:var(--da-accent,#176df2)!important}
|
|
9022
|
+
.da-card-error{padding:6px 9px;color:var(--dsw-alias-label-error,#c0392b);font-size:11px}
|
|
9023
|
+
.da-card-locator{margin-left:22px;overflow-wrap:anywhere;white-space:pre-wrap;color:var(--dsw-alias-label-tertiary,inherit);
|
|
9024
|
+
font:10px/1.5 var(--dsw-font-family-mono,ui-monospace,SFMono-Regular,Menlo,monospace)}
|
|
9025
|
+
.da-card[data-expanded="true"] .da-card-said{display:block;white-space:pre-wrap;-webkit-line-clamp:unset}
|
|
9026
|
+
.da-card[data-expanded="true"] .da-card-name{white-space:normal;overflow-wrap:anywhere}
|
|
9027
|
+
.da-card-target{overflow-wrap:anywhere}
|
|
9028
|
+
.da-staged-type{font-size:9px;font-weight:650;letter-spacing:.04em;color:var(--dsw-alias-label-tertiary,inherit)}
|
|
9029
|
+
.da-staged-card[data-expanded="true"]{width:min(440px,100%)}
|
|
9030
|
+
.da-staged-card[data-expanded="true"] .da-staged-line{display:none}
|
|
9031
|
+
.da-staged-chevron{display:flex;flex:0 0 18px;margin-left:auto;color:var(--dsw-alias-label-tertiary,#858991)}
|
|
9032
|
+
.da-staged-chevron svg{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:1.5}
|
|
9033
|
+
.da-staged-open[aria-expanded="true"] .da-staged-chevron{transform:rotate(90deg)}
|
|
9034
|
+
.da-staged-text{flex:1 1 auto;padding-right:0}
|
|
9035
|
+
.da-staged-open{padding-right:18px}
|
|
9036
|
+
.da-staged-details{display:block;width:100%;margin-top:8px;border-top:1px solid var(--dsw-alias-border-main,rgba(128,128,128,.18))}
|
|
9037
|
+
.da-staged-details .da-card{width:100%;max-width:none;margin:0;border:0;border-radius:0;box-shadow:none;background:transparent}
|
|
9038
|
+
.da-staged-details .da-card-body{padding:8px 0 0}
|
|
9039
|
+
.da-overlay[data-tool="select"] [data-da-element-box]{pointer-events:all;cursor:pointer}
|
|
9040
|
+
.da-staged-details[hidden]{display:none}
|
|
9041
|
+
.da-staged-send{border:0;border-radius:6px;background:none;min-height:28px;padding:4px 8px;font-size:11px;color:var(--da-accent,#176df2)}
|
|
9042
|
+
.da-staged-send[disabled]{opacity:.6;cursor:default}
|
|
8950
9043
|
|
|
8951
9044
|
/* --- local service browser ------------------------------------------------ */
|
|
8952
9045
|
.da-service-shell{display:flex;flex-direction:column;height:100%;min-height:0}
|
|
@@ -8998,7 +9091,7 @@ button.da-card:hover .da-card-go{background:var(--da-accent-soft,rgba(23,109,242
|
|
|
8998
9091
|
.da-services{--da-service-ink:var(--dsw-alias-label-primary,#1b1d20);
|
|
8999
9092
|
--da-service-muted:var(--dsw-alias-label-tertiary,#787d85);
|
|
9000
9093
|
--da-service-line:color-mix(in srgb,var(--dsw-alias-border-l2,#c9cbd0) 66%,transparent);
|
|
9001
|
-
box-sizing:border-box;height:100%;overflow:auto;padding:
|
|
9094
|
+
box-sizing:border-box;height:100%;overflow:auto;padding:24px 20px 32px;width:100%;
|
|
9002
9095
|
color:var(--da-service-ink);
|
|
9003
9096
|
background:
|
|
9004
9097
|
radial-gradient(circle at 18% 0%,color-mix(in srgb,#4c8a63 8%,transparent),transparent 36%),
|
|
@@ -9006,10 +9099,7 @@ button.da-card:hover .da-card-go{background:var(--da-accent-soft,rgba(23,109,242
|
|
|
9006
9099
|
.da-services-head,.da-service-search,.da-services-toolbar,.da-service-list,.da-services-error{
|
|
9007
9100
|
width:min(480px,100%);margin-left:auto;margin-right:auto}
|
|
9008
9101
|
.da-services-head{padding:0 4px 18px}
|
|
9009
|
-
.da-services-
|
|
9010
|
-
font:9px/1.2 var(--dsw-font-family-mono,ui-monospace,SFMono-Regular,Menlo,monospace);
|
|
9011
|
-
letter-spacing:.16em}
|
|
9012
|
-
.da-services-head h1{margin:0;font-size:clamp(25px,4.5vw,34px);font-weight:680;line-height:1.08;letter-spacing:-.035em}
|
|
9102
|
+
.da-services-head h1{margin:0;font-size:20px;font-weight:680;line-height:1.08;letter-spacing:-.035em}
|
|
9013
9103
|
.da-services-head p{max-width:410px;margin:9px 0 0;color:var(--da-service-muted);font-size:12px;line-height:1.65}
|
|
9014
9104
|
.da-service-search{display:flex;align-items:center;gap:9px;box-sizing:border-box;height:48px;padding:0 7px 0 14px;
|
|
9015
9105
|
border:1px solid var(--da-service-line);border-radius:15px;
|
|
@@ -9913,46 +10003,60 @@ button.da-card:hover .da-card-go{background:var(--da-accent-soft,rgba(23,109,242
|
|
|
9913
10003
|
left: props.at.left,
|
|
9914
10004
|
top: props.at.top
|
|
9915
10005
|
},
|
|
9916
|
-
children: [
|
|
9917
|
-
|
|
9918
|
-
|
|
9919
|
-
|
|
9920
|
-
|
|
9921
|
-
|
|
9922
|
-
|
|
9923
|
-
|
|
9924
|
-
|
|
9925
|
-
|
|
9926
|
-
onKeyDown: (event) => {
|
|
9927
|
-
if (event.key !== "Escape") return;
|
|
9928
|
-
event.preventDefault();
|
|
9929
|
-
event.stopPropagation();
|
|
9930
|
-
event.currentTarget.blur();
|
|
9931
|
-
}
|
|
9932
|
-
}), hasDetail(mark) ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9933
|
-
className: "da-comment-send",
|
|
9934
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
9935
|
-
type: "button",
|
|
9936
|
-
className: "da-comment-send-btn da-comment-send-primary",
|
|
9937
|
-
disabled: props.busy,
|
|
9938
|
-
"aria-label": t("sendToAgent"),
|
|
9939
|
-
title: t("sendToAgent"),
|
|
9940
|
-
onClick: () => {
|
|
9941
|
-
props.onSendToAgent();
|
|
10006
|
+
children: [
|
|
10007
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
10008
|
+
ref: props.inputRef,
|
|
10009
|
+
className: "da-comment",
|
|
10010
|
+
value: mark.detail ?? "",
|
|
10011
|
+
placeholder: hasDetail(mark) ? t("detailPlaceholder") : t("addComment"),
|
|
10012
|
+
rows: 1,
|
|
10013
|
+
maxLength: MAX_DETAIL_CHARS,
|
|
10014
|
+
onChange: (event) => {
|
|
10015
|
+
props.onWrite(event.target.value);
|
|
9942
10016
|
},
|
|
9943
|
-
|
|
9944
|
-
|
|
10017
|
+
onKeyDown: (event) => {
|
|
10018
|
+
if (event.key !== "Escape") return;
|
|
10019
|
+
event.preventDefault();
|
|
10020
|
+
event.stopPropagation();
|
|
10021
|
+
event.currentTarget.blur();
|
|
10022
|
+
}
|
|
10023
|
+
}),
|
|
10024
|
+
hasDetail(mark) ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10025
|
+
className: "da-comment-send",
|
|
10026
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
10027
|
+
type: "button",
|
|
10028
|
+
className: "da-comment-send-btn da-comment-send-primary",
|
|
10029
|
+
disabled: props.busy,
|
|
10030
|
+
"aria-label": t("sendToAgent"),
|
|
10031
|
+
title: t("sendToAgent"),
|
|
10032
|
+
onClick: () => {
|
|
10033
|
+
props.onSendToAgent();
|
|
10034
|
+
},
|
|
10035
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SendIcon, {})
|
|
10036
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
10037
|
+
type: "button",
|
|
10038
|
+
className: "da-comment-send-btn",
|
|
10039
|
+
disabled: props.busy,
|
|
10040
|
+
"aria-label": t("sendToComposer"),
|
|
10041
|
+
title: t("sendToComposer"),
|
|
10042
|
+
onClick: () => {
|
|
10043
|
+
props.onSendToComposer();
|
|
10044
|
+
},
|
|
10045
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChatIcon, {})
|
|
10046
|
+
})]
|
|
10047
|
+
}) : null,
|
|
10048
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
9945
10049
|
type: "button",
|
|
9946
|
-
className: "da-comment-send-btn",
|
|
9947
|
-
|
|
9948
|
-
|
|
9949
|
-
|
|
10050
|
+
className: "da-comment-send-btn da-comment-remove",
|
|
10051
|
+
"aria-label": t("delete"),
|
|
10052
|
+
title: t("delete"),
|
|
10053
|
+
"aria-disabled": props.busy,
|
|
9950
10054
|
onClick: () => {
|
|
9951
|
-
props.
|
|
10055
|
+
if (!props.busy) props.onRemove();
|
|
9952
10056
|
},
|
|
9953
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
9954
|
-
})
|
|
9955
|
-
|
|
10057
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TrashIcon, {})
|
|
10058
|
+
})
|
|
10059
|
+
]
|
|
9956
10060
|
});
|
|
9957
10061
|
}
|
|
9958
10062
|
//#endregion
|
|
@@ -15538,6 +15642,9 @@ button.da-card:hover .da-card-go{background:var(--da-accent-soft,rgba(23,109,242
|
|
|
15538
15642
|
onWrite: (value) => {
|
|
15539
15643
|
setMarkDetail(selected.id, value);
|
|
15540
15644
|
},
|
|
15645
|
+
onRemove: () => {
|
|
15646
|
+
removeMark(selected.id);
|
|
15647
|
+
},
|
|
15541
15648
|
onSendToAgent: () => {
|
|
15542
15649
|
sendOne(selected, "agent");
|
|
15543
15650
|
},
|
|
@@ -15559,6 +15666,32 @@ button.da-card:hover .da-card-go{background:var(--da-accent-soft,rgba(23,109,242
|
|
|
15559
15666
|
});
|
|
15560
15667
|
}
|
|
15561
15668
|
//#endregion
|
|
15669
|
+
//#region src/client/annotation-subject.ts
|
|
15670
|
+
/** Shared display identity for a review, before and after sending. */
|
|
15671
|
+
/**
|
|
15672
|
+
* Identify the reviewed source, independently of its mark tools or screenshot.
|
|
15673
|
+
* @param data - the immutable message facts.
|
|
15674
|
+
* @returns a readable name, media badge, and whether navigation belongs to the service tab.
|
|
15675
|
+
*/
|
|
15676
|
+
function annotationSubject(data) {
|
|
15677
|
+
const address = data.html ? loopbackAddressOf(data.file) : void 0;
|
|
15678
|
+
if (address !== void 0) {
|
|
15679
|
+
const url = new URL(address);
|
|
15680
|
+
return {
|
|
15681
|
+
name: `${url.host}${url.pathname === "/" ? "" : url.pathname}`,
|
|
15682
|
+
badge: "WEB",
|
|
15683
|
+
live: true
|
|
15684
|
+
};
|
|
15685
|
+
}
|
|
15686
|
+
const suffix = suffixOf(data.file);
|
|
15687
|
+
const badge = data.html ? "HTML" : /^(?:pdf|svg|png|jpe?g|webp|gif|bmp|ico)$/u.test(suffix) ? suffix.toUpperCase() : "FIG";
|
|
15688
|
+
return {
|
|
15689
|
+
name: baseNameOf(data.file),
|
|
15690
|
+
badge,
|
|
15691
|
+
live: false
|
|
15692
|
+
};
|
|
15693
|
+
}
|
|
15694
|
+
//#endregion
|
|
15562
15695
|
//#region src/client/annotation-card.tsx
|
|
15563
15696
|
/**
|
|
15564
15697
|
* The annotation a reader sent, as a card inside their own bubble.
|
|
@@ -15566,8 +15699,8 @@ button.da-card:hover .da-card-go{background:var(--da-accent-soft,rgba(23,109,242
|
|
|
15566
15699
|
* The message still says everything it said — the model reads the same text,
|
|
15567
15700
|
* copying it copies the same text — but in the transcript the same block is easier
|
|
15568
15701
|
* to scan as a small sheet: which figure, how large, how many marks, and what each
|
|
15569
|
-
* of them asked for. Clicking
|
|
15570
|
-
*
|
|
15702
|
+
* of them asked for. Clicking its header expands the delivered review; a separate action opens the
|
|
15703
|
+
* current source in the Sidebar, which may have changed since this message was sent.
|
|
15571
15704
|
*
|
|
15572
15705
|
* Two rules keep this a view and nothing more. It reads the block it was dispatched
|
|
15573
15706
|
* for and never edits it; and it draws from the parsed data alone, so a block whose
|
|
@@ -15693,9 +15826,10 @@ button.da-card:hover .da-card-go{background:var(--da-accent-soft,rgba(23,109,242
|
|
|
15693
15826
|
* @returns the row.
|
|
15694
15827
|
*/
|
|
15695
15828
|
function CardRow(props) {
|
|
15696
|
-
const { mark, ordinal, page } = props;
|
|
15829
|
+
const { mark, ordinal, page, expanded } = props;
|
|
15697
15830
|
const said = mark.comment === "" ? void 0 : mark.comment;
|
|
15698
15831
|
const parts = readCardMarkLabel(mark.label);
|
|
15832
|
+
const number = /\d+$/u.exec(parts.name)?.[0] ?? String(ordinal);
|
|
15699
15833
|
const kind = parts.name.replace(/\s*\d+$/u, "");
|
|
15700
15834
|
const label = parts.element === "" ? kind : parts.element;
|
|
15701
15835
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
@@ -15708,7 +15842,7 @@ button.da-card:hover .da-card-go{background:var(--da-accent-soft,rgba(23,109,242
|
|
|
15708
15842
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
15709
15843
|
className: "da-card-kind",
|
|
15710
15844
|
"aria-hidden": "true",
|
|
15711
|
-
children:
|
|
15845
|
+
children: number
|
|
15712
15846
|
}),
|
|
15713
15847
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
15714
15848
|
className: "da-card-mark",
|
|
@@ -15737,6 +15871,10 @@ button.da-card:hover .da-card-go{background:var(--da-accent-soft,rgba(23,109,242
|
|
|
15737
15871
|
className: "da-card-said",
|
|
15738
15872
|
children: said
|
|
15739
15873
|
}),
|
|
15874
|
+
expanded ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
15875
|
+
className: "da-card-locator",
|
|
15876
|
+
children: mark.label
|
|
15877
|
+
}) : null,
|
|
15740
15878
|
parts.aside === "" ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
15741
15879
|
className: "da-card-warning",
|
|
15742
15880
|
children: parts.aside
|
|
@@ -15750,7 +15888,6 @@ button.da-card:hover .da-card-go{background:var(--da-accent-soft,rgba(23,109,242
|
|
|
15750
15888
|
* @returns the card, or the block's own text when its data is not one it can draw.
|
|
15751
15889
|
*/
|
|
15752
15890
|
function AnnotationCard(props) {
|
|
15753
|
-
const [shot, setShot] = (0, react.useState)(true);
|
|
15754
15891
|
(0, react.useEffect)(() => {
|
|
15755
15892
|
ensureStyles(document);
|
|
15756
15893
|
}, []);
|
|
@@ -15760,85 +15897,110 @@ button.da-card:hover .da-card-go{background:var(--da-accent-soft,rgba(23,109,242
|
|
|
15760
15897
|
className: "da-card-fallback",
|
|
15761
15898
|
children: raw
|
|
15762
15899
|
});
|
|
15900
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReviewCard, {
|
|
15901
|
+
...props,
|
|
15902
|
+
data,
|
|
15903
|
+
raw
|
|
15904
|
+
}, raw || JSON.stringify(data));
|
|
15905
|
+
}
|
|
15906
|
+
/** The review snapshot; navigation to the current source is a separate action. */
|
|
15907
|
+
function ReviewCard(props) {
|
|
15908
|
+
const { data, raw, embedded = false } = props;
|
|
15909
|
+
const [failedThumb, setFailedThumb] = (0, react.useState)();
|
|
15910
|
+
const [expanded, setExpanded] = (0, react.useState)(embedded);
|
|
15911
|
+
const [trouble, setTrouble] = (0, react.useState)(false);
|
|
15912
|
+
const bodyId = (0, react.useId)();
|
|
15763
15913
|
const interactive = props.interactive !== false;
|
|
15764
15914
|
const open = props.open;
|
|
15765
|
-
const
|
|
15766
|
-
const
|
|
15915
|
+
const candidate = thumbFor(raw);
|
|
15916
|
+
const thumb = candidate === failedThumb ? void 0 : candidate;
|
|
15917
|
+
const shown = embedded || expanded ? data.marks : data.marks.slice(0, MAX_ROWS);
|
|
15767
15918
|
const rest = data.marks.length - shown.length;
|
|
15768
|
-
const
|
|
15769
|
-
const
|
|
15919
|
+
const subject = annotationSubject(data);
|
|
15920
|
+
const liveFile = subject.live;
|
|
15770
15921
|
const captureNotice = liveFile && thumb === void 0 ? data.pageCapture === "omitted" ? resolveTranslate(props, "cardCaptureOmitted") : data.pageCapture === "failed" ? resolveTranslate(props, "cardCaptureFailed") : "" : "";
|
|
15771
|
-
const
|
|
15772
|
-
const cut = Math.max(displayFile.lastIndexOf("/"), displayFile.lastIndexOf("\\"));
|
|
15773
|
-
const name = displayFile.slice(cut + 1);
|
|
15922
|
+
const sourceOpener = interactive && (props.canOpen?.(data.file, data.html) ?? true) ? open : void 0;
|
|
15774
15923
|
const dimensions = /(\d+)\s*[×x]\s*(\d+)/u.exec(data.scope);
|
|
15775
15924
|
const size = dimensions === null ? "" : `${dimensions[1]}×${dimensions[2]}`;
|
|
15776
|
-
const
|
|
15777
|
-
|
|
15778
|
-
|
|
15779
|
-
|
|
15780
|
-
|
|
15781
|
-
|
|
15782
|
-
|
|
15783
|
-
|
|
15784
|
-
|
|
15785
|
-
|
|
15786
|
-
|
|
15787
|
-
|
|
15788
|
-
|
|
15789
|
-
|
|
15790
|
-
|
|
15791
|
-
|
|
15792
|
-
|
|
15793
|
-
|
|
15794
|
-
|
|
15795
|
-
|
|
15796
|
-
|
|
15797
|
-
|
|
15798
|
-
|
|
15799
|
-
|
|
15800
|
-
|
|
15801
|
-
|
|
15802
|
-
|
|
15803
|
-
|
|
15804
|
-
|
|
15805
|
-
|
|
15806
|
-
|
|
15807
|
-
|
|
15808
|
-
|
|
15809
|
-
|
|
15810
|
-
|
|
15811
|
-
|
|
15812
|
-
|
|
15813
|
-
|
|
15814
|
-
|
|
15815
|
-
|
|
15816
|
-
|
|
15817
|
-
|
|
15818
|
-
|
|
15925
|
+
const pages = /^(?:共 (\d+) 页|(\d+) pages)(?:,|,|$)/u.exec(data.scope);
|
|
15926
|
+
const scope = pages === null ? size : resolveTranslate(props, "cardPages", { n: Number(pages[1] ?? pages[2]) });
|
|
15927
|
+
const headContent = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
15928
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
15929
|
+
className: "da-card-shot",
|
|
15930
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SheetIcon, {}), thumb === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
|
|
15931
|
+
alt: "",
|
|
15932
|
+
src: thumb,
|
|
15933
|
+
onError: () => {
|
|
15934
|
+
setFailedThumb(thumb);
|
|
15935
|
+
}
|
|
15936
|
+
})]
|
|
15937
|
+
}),
|
|
15938
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
15939
|
+
className: "da-card-text",
|
|
15940
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
15941
|
+
className: "da-card-title-row",
|
|
15942
|
+
children: [
|
|
15943
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
15944
|
+
className: "da-card-title",
|
|
15945
|
+
title: data.file,
|
|
15946
|
+
children: subject.name
|
|
15947
|
+
}),
|
|
15948
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
15949
|
+
className: "da-card-type",
|
|
15950
|
+
children: subject.badge
|
|
15951
|
+
}),
|
|
15952
|
+
captureNotice === "" ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
15953
|
+
className: "da-card-capture",
|
|
15954
|
+
children: captureNotice
|
|
15955
|
+
})
|
|
15956
|
+
]
|
|
15957
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
15958
|
+
className: "da-card-scope",
|
|
15959
|
+
children: [scope === "" ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
15960
|
+
className: "da-card-meta",
|
|
15961
|
+
title: data.scope,
|
|
15962
|
+
children: scope
|
|
15963
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
15964
|
+
className: "da-card-tally",
|
|
15965
|
+
"aria-label": resolveTranslate(props, "cardCount", { n: data.marks.length }),
|
|
15966
|
+
title: data.scope,
|
|
15967
|
+
children: data.marks.length
|
|
15819
15968
|
})]
|
|
15820
|
-
})
|
|
15821
|
-
|
|
15822
|
-
|
|
15823
|
-
|
|
15824
|
-
|
|
15825
|
-
|
|
15826
|
-
|
|
15827
|
-
|
|
15828
|
-
})
|
|
15829
|
-
})
|
|
15830
|
-
|
|
15969
|
+
})]
|
|
15970
|
+
}),
|
|
15971
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
15972
|
+
className: "da-card-go",
|
|
15973
|
+
"aria-hidden": "true",
|
|
15974
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
15975
|
+
viewBox: "0 0 16 16",
|
|
15976
|
+
focusable: "false",
|
|
15977
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "m6 3.5 4.5 4.5L6 12.5" })
|
|
15978
|
+
})
|
|
15979
|
+
})
|
|
15980
|
+
] });
|
|
15981
|
+
const head = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
15982
|
+
type: "button",
|
|
15983
|
+
className: "da-card-head",
|
|
15984
|
+
"aria-expanded": expanded,
|
|
15985
|
+
"aria-controls": bodyId,
|
|
15986
|
+
title: resolveTranslate(props, expanded ? "cardCollapse" : "cardExpand"),
|
|
15987
|
+
onClick: () => {
|
|
15988
|
+
setExpanded((value) => !value);
|
|
15989
|
+
},
|
|
15990
|
+
children: headContent
|
|
15831
15991
|
});
|
|
15832
15992
|
const body = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
15833
15993
|
className: "da-card-body",
|
|
15994
|
+
id: bodyId,
|
|
15834
15995
|
children: [
|
|
15835
15996
|
shown.map((mark, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CardRow, {
|
|
15836
15997
|
mark,
|
|
15837
15998
|
ordinal: index + 1,
|
|
15999
|
+
expanded,
|
|
15838
16000
|
page: mark.page === void 0 ? void 0 : resolveTranslate(props, "cardPage", { n: mark.page })
|
|
15839
16001
|
}, `${String(mark.page ?? "")}-${String(index)}`)),
|
|
15840
16002
|
rest > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
15841
|
-
className: "da-card-
|
|
16003
|
+
className: "da-card-rest",
|
|
15842
16004
|
children: resolveTranslate(props, "cardMore", { n: rest })
|
|
15843
16005
|
}) : null,
|
|
15844
16006
|
data.target === "" ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
@@ -15850,20 +16012,39 @@ button.da-card:hover .da-card-go{background:var(--da-accent-soft,rgba(23,109,242
|
|
|
15850
16012
|
})
|
|
15851
16013
|
]
|
|
15852
16014
|
});
|
|
15853
|
-
|
|
15854
|
-
open(data.file, data.html);
|
|
15855
|
-
} : void 0;
|
|
15856
|
-
if (onClick === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
15857
|
-
className: "da-card",
|
|
15858
|
-
"data-static": "",
|
|
15859
|
-
children: [head, body]
|
|
15860
|
-
});
|
|
15861
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
15862
|
-
type: "button",
|
|
16015
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
15863
16016
|
className: "da-card",
|
|
15864
|
-
|
|
15865
|
-
|
|
15866
|
-
|
|
16017
|
+
"data-expanded": expanded,
|
|
16018
|
+
children: [
|
|
16019
|
+
embedded ? null : head,
|
|
16020
|
+
body,
|
|
16021
|
+
embedded ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
16022
|
+
className: "da-card-actions",
|
|
16023
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
16024
|
+
type: "button",
|
|
16025
|
+
className: "da-card-toggle",
|
|
16026
|
+
"aria-expanded": expanded,
|
|
16027
|
+
"aria-controls": bodyId,
|
|
16028
|
+
onClick: () => {
|
|
16029
|
+
setExpanded((value) => !value);
|
|
16030
|
+
},
|
|
16031
|
+
children: resolveTranslate(props, expanded ? "cardCollapse" : "cardExpand")
|
|
16032
|
+
}), sourceOpener === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
16033
|
+
type: "button",
|
|
16034
|
+
className: "da-card-source",
|
|
16035
|
+
title: data.file,
|
|
16036
|
+
onClick: () => {
|
|
16037
|
+
setTrouble(sourceOpener(data.file, data.html) === false);
|
|
16038
|
+
},
|
|
16039
|
+
children: resolveTranslate(props, liveFile ? "cardOpenLive" : "cardOpen")
|
|
16040
|
+
})]
|
|
16041
|
+
}),
|
|
16042
|
+
trouble ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
16043
|
+
className: "da-card-error",
|
|
16044
|
+
role: "status",
|
|
16045
|
+
children: resolveTranslate(props, "cardOpenFailed")
|
|
16046
|
+
}) : null
|
|
16047
|
+
]
|
|
15867
16048
|
});
|
|
15868
16049
|
}
|
|
15869
16050
|
//#endregion
|
|
@@ -15948,7 +16129,8 @@ button.da-card:hover .da-card-go{background:var(--da-accent-soft,rgba(23,109,242
|
|
|
15948
16129
|
paths: saved,
|
|
15949
16130
|
thumb,
|
|
15950
16131
|
file: void 0,
|
|
15951
|
-
|
|
16132
|
+
files: images.slice(0, 8).map(({ page, image }) => new File([image], `${baseNameOf(document.figure.path)}${pageFileSuffix(page)}.annotated.png`, { type: "image/png" })),
|
|
16133
|
+
pageImages: Math.min(images.length, 8),
|
|
15952
16134
|
locale: options.locale,
|
|
15953
16135
|
send: async () => {
|
|
15954
16136
|
if (sessions === void 0) throw new Error("the sessions service is unavailable");
|
|
@@ -16167,31 +16349,9 @@ button.da-card:hover .da-card-go{background:var(--da-accent-soft,rgba(23,109,242
|
|
|
16167
16349
|
//#endregion
|
|
16168
16350
|
//#region src/client/pending-card.tsx
|
|
16169
16351
|
/**
|
|
16170
|
-
*
|
|
16171
|
-
*
|
|
16172
|
-
*
|
|
16173
|
-
* written into it that stays a card, and the whole annotation block sitting in the
|
|
16174
|
-
* input box is exactly what a reader cannot scan. So the block is armed beside the box
|
|
16175
|
-
* — its message held, its picture uploaded — and the chip stands beside the reader's
|
|
16176
|
-
* own attachments as the face of what that send will carry: the figure's thumbnail, how
|
|
16177
|
-
* many marks it carries, the file's name, and the first mark's note.
|
|
16178
|
-
* It is portalled into the composer card's own flow (see `composer-seat`), so it
|
|
16179
|
-
* sits where an attached picture sits; the dock entry that owns it holds only the
|
|
16180
|
-
* anchor, and falls back to drawing in the dock itself when there is no card.
|
|
16181
|
-
*
|
|
16182
|
-
* What the card shows and what it hides is the point. A dimension or a pair of
|
|
16183
|
-
* coordinates is not something to read at a glance, so it stays in the block the model
|
|
16184
|
-
* reads and in the hover title, and never on the face: the face says the figure and the
|
|
16185
|
-
* count first, the note second, and truncates both rather than wrapping into a wall of
|
|
16186
|
-
* text.
|
|
16187
|
-
*
|
|
16188
|
-
* One press is the point, and the box keeps the reader's own words while it is not
|
|
16189
|
-
* pressed: nothing is written into the draft, so the sentence being typed stays the only
|
|
16190
|
-
* text in it. The box's own send carries the armed message — typing above the card and
|
|
16191
|
-
* pressing Send sends the sentence and the review as one message, with the annotation
|
|
16192
|
-
* behind the sentence — and the card's own action runs that same send for a reader who
|
|
16193
|
-
* wants to fire it from the card. The card goes when that send takes it, or when the
|
|
16194
|
-
* reader drops it, because that is when it stops standing for anything.
|
|
16352
|
+
* Reviews staged beside the composer. The chip previews its immutable payload;
|
|
16353
|
+
* the native composer Send carries armed reviews, with or without typed text.
|
|
16354
|
+
* Older hosts without draft admission retain a direct-delivery fallback.
|
|
16195
16355
|
* @module dsh-figmark/client/pending-card
|
|
16196
16356
|
*/
|
|
16197
16357
|
/**
|
|
@@ -16229,28 +16389,6 @@ button.da-card:hover .da-card-go{background:var(--da-accent-soft,rgba(23,109,242
|
|
|
16229
16389
|
});
|
|
16230
16390
|
}
|
|
16231
16391
|
/**
|
|
16232
|
-
* The small outline that stands for a mark's shape on the card's one line.
|
|
16233
|
-
* @returns the glyph.
|
|
16234
|
-
*/
|
|
16235
|
-
function MarkIcon() {
|
|
16236
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
16237
|
-
className: "da-staged-mark-icon",
|
|
16238
|
-
viewBox: "0 0 12 12",
|
|
16239
|
-
"aria-hidden": "true",
|
|
16240
|
-
focusable: "false",
|
|
16241
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
|
|
16242
|
-
x: "1",
|
|
16243
|
-
y: "2",
|
|
16244
|
-
width: "10",
|
|
16245
|
-
height: "8",
|
|
16246
|
-
rx: "1.5",
|
|
16247
|
-
fill: "none",
|
|
16248
|
-
stroke: "currentColor",
|
|
16249
|
-
strokeWidth: "1.1"
|
|
16250
|
-
})
|
|
16251
|
-
});
|
|
16252
|
-
}
|
|
16253
|
-
/**
|
|
16254
16392
|
* A mark's name without its coordinates: the kind and its number, which is what a
|
|
16255
16393
|
* reader recognises, with a space between the two the way the product writes it.
|
|
16256
16394
|
* @param label - the mark's own name, coordinates and all.
|
|
@@ -16269,25 +16407,15 @@ button.da-card:hover .da-card-go{background:var(--da-accent-soft,rgba(23,109,242
|
|
|
16269
16407
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
16270
16408
|
const [trouble, setTrouble] = (0, react.useState)("");
|
|
16271
16409
|
const [shot, setShot] = (0, react.useState)(true);
|
|
16410
|
+
const [expanded, setExpanded] = (0, react.useState)(false);
|
|
16411
|
+
const detailId = (0, react.useId)();
|
|
16272
16412
|
const sending = (0, react.useRef)(false);
|
|
16273
16413
|
const armed = entry.armed;
|
|
16274
16414
|
const data = entry.data;
|
|
16275
16415
|
const thumb = shot ? thumbFor(entry.raw) : void 0;
|
|
16276
16416
|
const send = async () => {
|
|
16277
16417
|
if (sending.current) return;
|
|
16278
|
-
|
|
16279
|
-
sending.current = true;
|
|
16280
|
-
setBusy(true);
|
|
16281
|
-
try {
|
|
16282
|
-
armed.shell.submit?.();
|
|
16283
|
-
} finally {
|
|
16284
|
-
queueMicrotask(() => {
|
|
16285
|
-
sending.current = false;
|
|
16286
|
-
setBusy(false);
|
|
16287
|
-
});
|
|
16288
|
-
}
|
|
16289
|
-
return;
|
|
16290
|
-
}
|
|
16418
|
+
setTrouble("");
|
|
16291
16419
|
sending.current = true;
|
|
16292
16420
|
setBusy(true);
|
|
16293
16421
|
try {
|
|
@@ -16311,88 +16439,142 @@ button.da-card:hover .da-card-go{background:var(--da-accent-soft,rgba(23,109,242
|
|
|
16311
16439
|
entry.id,
|
|
16312
16440
|
sessionId
|
|
16313
16441
|
]);
|
|
16314
|
-
const
|
|
16315
|
-
const
|
|
16316
|
-
const name = shownFile.slice(cut + 1);
|
|
16442
|
+
const subject = annotationSubject(data);
|
|
16443
|
+
const name = subject.name;
|
|
16317
16444
|
const first = data.marks[0];
|
|
16318
|
-
const captureNotice =
|
|
16445
|
+
const captureNotice = subject.live && thumb === void 0 ? data.pageCapture === "omitted" ? resolveTranslate(props, "cardCaptureOmitted") : data.pageCapture === "failed" ? resolveTranslate(props, "cardCaptureFailed") : "" : "";
|
|
16319
16446
|
const detail = first === void 0 ? name : first.comment === "" ? first.label : `${first.label} · ${first.comment}`;
|
|
16320
16447
|
const hover = data.scope === "" ? data.file : `${data.file} · ${data.scope}`;
|
|
16321
16448
|
const removeLabel = resolveTranslate(props, "pendingRemove");
|
|
16449
|
+
const hint = resolveTranslate(props, "pendingSendNow");
|
|
16322
16450
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
16323
16451
|
className: "da-staged",
|
|
16324
|
-
children: [
|
|
16325
|
-
|
|
16326
|
-
|
|
16327
|
-
|
|
16328
|
-
|
|
16329
|
-
|
|
16330
|
-
|
|
16331
|
-
|
|
16332
|
-
|
|
16333
|
-
|
|
16334
|
-
|
|
16335
|
-
|
|
16336
|
-
|
|
16337
|
-
|
|
16338
|
-
|
|
16339
|
-
src: thumb,
|
|
16340
|
-
onError: () => {
|
|
16341
|
-
setShot(false);
|
|
16342
|
-
}
|
|
16343
|
-
})]
|
|
16344
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
16345
|
-
className: "da-staged-text",
|
|
16346
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
16347
|
-
className: "da-staged-head",
|
|
16452
|
+
children: [
|
|
16453
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
16454
|
+
className: "da-staged-card",
|
|
16455
|
+
"data-expanded": expanded,
|
|
16456
|
+
title: hover,
|
|
16457
|
+
children: [
|
|
16458
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
16459
|
+
type: "button",
|
|
16460
|
+
className: "da-staged-open",
|
|
16461
|
+
"aria-expanded": expanded,
|
|
16462
|
+
"aria-controls": detailId,
|
|
16463
|
+
title: resolveTranslate(props, expanded ? "cardCollapse" : "cardExpand"),
|
|
16464
|
+
onClick: () => {
|
|
16465
|
+
setExpanded((value) => !value);
|
|
16466
|
+
},
|
|
16348
16467
|
children: [
|
|
16349
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
16350
|
-
className: "da-staged-
|
|
16351
|
-
|
|
16352
|
-
|
|
16468
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
16469
|
+
className: "da-staged-shot",
|
|
16470
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(FigureIcon, {}), thumb === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
|
|
16471
|
+
alt: "",
|
|
16472
|
+
src: thumb,
|
|
16473
|
+
onError: () => {
|
|
16474
|
+
setShot(false);
|
|
16475
|
+
}
|
|
16476
|
+
})]
|
|
16353
16477
|
}),
|
|
16354
|
-
|
|
16355
|
-
className: "da-staged-
|
|
16356
|
-
children:
|
|
16478
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
16479
|
+
className: "da-staged-text",
|
|
16480
|
+
children: [
|
|
16481
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
16482
|
+
className: "da-staged-head",
|
|
16483
|
+
children: [
|
|
16484
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
16485
|
+
className: "da-staged-title",
|
|
16486
|
+
title: name,
|
|
16487
|
+
children: name
|
|
16488
|
+
}),
|
|
16489
|
+
captureNotice === "" ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
16490
|
+
className: "da-staged-capture",
|
|
16491
|
+
children: captureNotice
|
|
16492
|
+
}),
|
|
16493
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
16494
|
+
className: "da-staged-count",
|
|
16495
|
+
"aria-label": resolveTranslate(props, "cardCount", { n: data.marks.length }),
|
|
16496
|
+
children: resolveTranslate(props, "pendingCount", { n: data.marks.length })
|
|
16497
|
+
})
|
|
16498
|
+
]
|
|
16499
|
+
}),
|
|
16500
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
16501
|
+
className: "da-staged-type",
|
|
16502
|
+
children: subject.badge
|
|
16503
|
+
}),
|
|
16504
|
+
first === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
16505
|
+
className: "da-staged-line",
|
|
16506
|
+
title: detail,
|
|
16507
|
+
children: [
|
|
16508
|
+
first.page === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
16509
|
+
className: "da-card-page",
|
|
16510
|
+
children: resolveTranslate(props, "cardPage", { n: first.page })
|
|
16511
|
+
}),
|
|
16512
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
16513
|
+
className: "da-staged-shape",
|
|
16514
|
+
children: shortLabel(first.label)
|
|
16515
|
+
}),
|
|
16516
|
+
first.comment === "" ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
16517
|
+
className: "da-staged-said",
|
|
16518
|
+
children: first.comment
|
|
16519
|
+
})
|
|
16520
|
+
]
|
|
16521
|
+
})
|
|
16522
|
+
]
|
|
16357
16523
|
}),
|
|
16358
16524
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
16359
|
-
className: "da-staged-
|
|
16360
|
-
"aria-
|
|
16361
|
-
children:
|
|
16362
|
-
|
|
16363
|
-
|
|
16364
|
-
|
|
16365
|
-
className: "da-staged-line",
|
|
16366
|
-
title: detail,
|
|
16367
|
-
children: [
|
|
16368
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MarkIcon, {}),
|
|
16369
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
16370
|
-
className: "da-staged-shape",
|
|
16371
|
-
children: shortLabel(first.label)
|
|
16372
|
-
}),
|
|
16373
|
-
first.comment === "" ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
16374
|
-
className: "da-staged-said",
|
|
16375
|
-
children: first.comment
|
|
16525
|
+
className: "da-staged-chevron",
|
|
16526
|
+
"aria-hidden": "true",
|
|
16527
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
16528
|
+
viewBox: "0 0 16 16",
|
|
16529
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "m6 3.5 4.5 4.5L6 12.5" })
|
|
16530
|
+
})
|
|
16376
16531
|
})
|
|
16377
16532
|
]
|
|
16378
|
-
})
|
|
16379
|
-
|
|
16380
|
-
|
|
16533
|
+
}),
|
|
16534
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
16535
|
+
type: "button",
|
|
16536
|
+
className: "da-staged-x",
|
|
16537
|
+
"aria-label": removeLabel,
|
|
16538
|
+
title: removeLabel,
|
|
16539
|
+
disabled: busy,
|
|
16540
|
+
onClick: () => {
|
|
16541
|
+
if (sending.current) return;
|
|
16542
|
+
if (armed !== void 0) disarmReview(armed, entry.conversation);
|
|
16543
|
+
unparkAnnotation(sessionId, entry.id);
|
|
16544
|
+
},
|
|
16545
|
+
children: "×"
|
|
16546
|
+
}),
|
|
16547
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
16548
|
+
id: detailId,
|
|
16549
|
+
className: "da-staged-details",
|
|
16550
|
+
hidden: !expanded,
|
|
16551
|
+
children: expanded ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AnnotationCard, {
|
|
16552
|
+
node: { data },
|
|
16553
|
+
raw: entry.raw,
|
|
16554
|
+
interactive: false,
|
|
16555
|
+
embedded: true,
|
|
16556
|
+
t: props.t,
|
|
16557
|
+
localeId: props.localeId
|
|
16558
|
+
}) : null
|
|
16559
|
+
})
|
|
16560
|
+
]
|
|
16561
|
+
}),
|
|
16562
|
+
armed === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
16381
16563
|
type: "button",
|
|
16382
|
-
className: "da-staged-
|
|
16383
|
-
"aria-label": removeLabel,
|
|
16384
|
-
title: removeLabel,
|
|
16564
|
+
className: "da-staged-send",
|
|
16385
16565
|
disabled: busy,
|
|
16566
|
+
title: hint,
|
|
16386
16567
|
onClick: () => {
|
|
16387
|
-
|
|
16388
|
-
unparkAnnotation(sessionId, entry.id);
|
|
16568
|
+
send();
|
|
16389
16569
|
},
|
|
16390
|
-
children: "
|
|
16391
|
-
})
|
|
16392
|
-
|
|
16393
|
-
|
|
16394
|
-
|
|
16395
|
-
|
|
16570
|
+
children: resolveTranslate(props, busy ? "pendingSending" : "pendingSendNow")
|
|
16571
|
+
}) : null,
|
|
16572
|
+
trouble === "" ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
16573
|
+
className: "da-staged-trouble",
|
|
16574
|
+
role: "alert",
|
|
16575
|
+
children: trouble
|
|
16576
|
+
})
|
|
16577
|
+
]
|
|
16396
16578
|
});
|
|
16397
16579
|
}
|
|
16398
16580
|
/**
|
|
@@ -16427,6 +16609,11 @@ button.da-card:hover .da-card-go{background:var(--da-accent-soft,rgba(23,109,242
|
|
|
16427
16609
|
return mountSeat(node, setSeat);
|
|
16428
16610
|
}, [sessionId, showing]);
|
|
16429
16611
|
if (!showing) return null;
|
|
16612
|
+
const owned = entries.flatMap((entry) => entry.armed?.previewUrls ?? []).map((url) => `img[src=${JSON.stringify(url)}]`).join(",");
|
|
16613
|
+
const thumbnailStyle = owned === "" ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: `
|
|
16614
|
+
[data-composer-card] [role="group"] > div:has(${owned}){display:none}
|
|
16615
|
+
[data-composer-card] > div:has(> div > [role="group"]):not(:has([role="group"] > div:not(:has(${owned})))){display:none}
|
|
16616
|
+
` });
|
|
16430
16617
|
const cards = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: entries.map((entry) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ParkedChip, {
|
|
16431
16618
|
entry,
|
|
16432
16619
|
sessionId,
|
|
@@ -16453,11 +16640,15 @@ button.da-card:hover .da-card-go{background:var(--da-accent-soft,rgba(23,109,242
|
|
|
16453
16640
|
children: "×"
|
|
16454
16641
|
})]
|
|
16455
16642
|
});
|
|
16456
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
16457
|
-
|
|
16458
|
-
|
|
16459
|
-
|
|
16460
|
-
|
|
16643
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
16644
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
16645
|
+
className: "da-staged-anchor",
|
|
16646
|
+
ref: anchor,
|
|
16647
|
+
hidden: true
|
|
16648
|
+
}),
|
|
16649
|
+
thumbnailStyle,
|
|
16650
|
+
seat === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [cards, report] }) : (0, react_dom.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [cards, report] }), seat)
|
|
16651
|
+
] });
|
|
16461
16652
|
}
|
|
16462
16653
|
//#endregion
|
|
16463
16654
|
//#region src/client/live-drafts.ts
|
|
@@ -17041,13 +17232,13 @@ button.da-card:hover .da-card-go{background:var(--da-accent-soft,rgba(23,109,242
|
|
|
17041
17232
|
return;
|
|
17042
17233
|
}
|
|
17043
17234
|
const needle = query.trim().toLowerCase();
|
|
17044
|
-
|
|
17045
|
-
|
|
17046
|
-
|
|
17047
|
-
|
|
17048
|
-
|
|
17049
|
-
|
|
17050
|
-
|
|
17235
|
+
if (needle === "") return;
|
|
17236
|
+
const titleMatch = visible.some((service) => service.title?.toLowerCase().includes(needle) === true);
|
|
17237
|
+
if (looksLikeAddress(query) && !titleMatch) openWorkspace(query);
|
|
17238
|
+
else if (visible.length === 1) {
|
|
17239
|
+
const only = visible[0];
|
|
17240
|
+
openWorkspace(only.url, only.title);
|
|
17241
|
+
} else setError(t(visible.length === 0 ? "serviceNoMatch" : "serviceChooseMatch"));
|
|
17051
17242
|
};
|
|
17052
17243
|
const visible = (0, react.useMemo)(() => {
|
|
17053
17244
|
const needle = query.trim().toLowerCase();
|
|
@@ -17146,14 +17337,7 @@ button.da-card:hover .da-card-go{background:var(--da-accent-soft,rgba(23,109,242
|
|
|
17146
17337
|
children: [
|
|
17147
17338
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", {
|
|
17148
17339
|
className: "da-services-head",
|
|
17149
|
-
children: [
|
|
17150
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
17151
|
-
className: "da-services-kicker",
|
|
17152
|
-
children: t("serviceKicker")
|
|
17153
|
-
}),
|
|
17154
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", { children: t("serviceTitle") }),
|
|
17155
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("serviceHint") })
|
|
17156
|
-
]
|
|
17340
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", { children: t("serviceTitle") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("serviceHint") })]
|
|
17157
17341
|
}),
|
|
17158
17342
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("form", {
|
|
17159
17343
|
className: "da-service-search",
|
|
@@ -17211,7 +17395,7 @@ button.da-card:hover .da-card-go{background:var(--da-accent-soft,rgba(23,109,242
|
|
|
17211
17395
|
children: t("serviceScanning")
|
|
17212
17396
|
}) : visible.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
17213
17397
|
className: "da-services-empty",
|
|
17214
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("serviceEmpty") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("serviceEmptyHint") })]
|
|
17398
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t(query.trim() === "" ? "serviceEmpty" : "serviceNoMatch") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t(query.trim() === "" ? "serviceEmptyHint" : "serviceSearchHint") })]
|
|
17215
17399
|
}) : visible.map((service) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
17216
17400
|
type: "button",
|
|
17217
17401
|
className: "da-service-row",
|
|
@@ -18445,6 +18629,7 @@ button.da-card:hover .da-card-go{background:var(--da-accent-soft,rgba(23,109,242
|
|
|
18445
18629
|
*/
|
|
18446
18630
|
function canOpenFigure(ctx, sessionId, path, html) {
|
|
18447
18631
|
if (sessionId === "" || path === "") return false;
|
|
18632
|
+
if (/^[a-z][a-z\d+.-]*:\/\//iu.test(path) && !isLivePage(path, html)) return false;
|
|
18448
18633
|
const sidebar = ctx.get("sidebarRight");
|
|
18449
18634
|
if (sidebar === void 0) return false;
|
|
18450
18635
|
return !isLivePage(path, html) || sidebar.openTab !== void 0;
|
|
@@ -18521,6 +18706,7 @@ button.da-card:hover .da-card-go{background:var(--da-accent-soft,rgba(23,109,242
|
|
|
18521
18706
|
ctx.effect(() => sidebarTabs.register({
|
|
18522
18707
|
id: SERVICE_BODY_ID,
|
|
18523
18708
|
kind: SERVICE_KIND,
|
|
18709
|
+
keepMounted: true,
|
|
18524
18710
|
priority: "extension",
|
|
18525
18711
|
title: () => locale.bind(NAMESPACE)("serviceTitle"),
|
|
18526
18712
|
guide: [{
|