@agent-native/core 0.70.2 → 0.71.0
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/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +19 -0
- package/corpus/core/docs/content/multi-app-workspace.md +2 -2
- package/corpus/core/docs/design/durable-agent-runs.md +458 -4
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/action.ts +21 -10
- package/corpus/core/src/agent/durable-background.ts +192 -0
- package/corpus/core/src/agent/production-agent.ts +330 -13
- package/corpus/core/src/agent/run-manager.ts +66 -3
- package/corpus/core/src/agent/run-store.ts +129 -23
- package/corpus/core/src/agent/types.ts +20 -0
- package/corpus/core/src/client/AgentPanel.tsx +12 -9
- package/corpus/core/src/client/blocks/library/FileTreeBlock.tsx +72 -14
- package/corpus/core/src/deploy/build.ts +96 -0
- package/corpus/core/src/deploy/workspace-deploy.ts +121 -0
- package/corpus/core/src/mcp/build-server.ts +22 -13
- package/corpus/core/src/server/agent-chat-plugin.ts +133 -66
- package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +19 -0
- package/corpus/templates/analytics/AGENTS.md +8 -0
- package/corpus/templates/analytics/actions/compose-dashboard.ts +317 -0
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +33 -6
- package/corpus/templates/analytics/changelog/2026-06-23-build-large-first-party-analytics-dashboards-in-one-fast-cal.md +6 -0
- package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +574 -0
- package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +8 -2
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +1 -9
- package/corpus/templates/clips/changelog/2026-06-23-dragging-the-desktop-camera-bubble-now-glides-to-a-stop-at-t.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-23-screen-recordings-now-capture-at-a-crisp-1080p-bitrate-inste.md +6 -0
- package/corpus/templates/clips/chrome-extension/package.json +1 -0
- package/corpus/templates/clips/chrome-extension/scripts/dev.ts +102 -0
- package/corpus/templates/clips/chrome-extension/src/background.ts +164 -32
- package/corpus/templates/clips/chrome-extension/src/content-script.ts +163 -13
- package/corpus/templates/clips/chrome-extension/src/offscreen.ts +198 -35
- package/corpus/templates/clips/chrome-extension/src/overlay.css +73 -23
- package/corpus/templates/clips/chrome-extension/src/overlay.ts +82 -13
- package/corpus/templates/clips/chrome-extension/src/popup.html +62 -5
- package/corpus/templates/clips/chrome-extension/src/popup.ts +290 -1
- package/corpus/templates/clips/chrome-extension/src/styles.css +34 -0
- package/corpus/templates/clips/desktop/src/lib/audio-cue.ts +21 -16
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +17 -20
- package/corpus/templates/clips/desktop/src/overlays/bubble.tsx +73 -23
- package/corpus/templates/clips/desktop/src/overlays/countdown.tsx +0 -6
- package/corpus/templates/clips/desktop/src/overlays/toolbar.tsx +56 -46
- package/corpus/templates/clips/desktop/src/styles.css +33 -5
- package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +113 -0
- package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +3 -0
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +2 -2
- package/corpus/templates/clips/server/routes/api/video/[recordingId].get.ts +9 -1
- package/corpus/templates/clips/shared/upload-limits.ts +5 -2
- package/corpus/templates/plan/app/pages/PlansPage.tsx +11 -7
- package/corpus/templates/plan/changelog/2026-06-23-plan-loading-skeleton-no-longer-cuts-off-the-canvas-preview-.md +6 -0
- package/dist/action.js +21 -10
- package/dist/action.js.map +1 -1
- package/dist/agent/durable-background.d.ts +60 -0
- package/dist/agent/durable-background.d.ts.map +1 -0
- package/dist/agent/durable-background.js +144 -0
- package/dist/agent/durable-background.js.map +1 -0
- package/dist/agent/production-agent.d.ts +20 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +292 -14
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-manager.d.ts +48 -0
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +45 -3
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/agent/run-store.d.ts +30 -1
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +124 -24
- package/dist/agent/run-store.js.map +1 -1
- package/dist/agent/types.d.ts +20 -0
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +2 -2
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/blocks/library/FileTreeBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/FileTreeBlock.js +37 -4
- package/dist/client/blocks/library/FileTreeBlock.js.map +1 -1
- package/dist/deploy/build.d.ts +29 -0
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +85 -0
- package/dist/deploy/build.js.map +1 -1
- package/dist/deploy/workspace-deploy.d.ts.map +1 -1
- package/dist/deploy/workspace-deploy.js +108 -0
- package/dist/deploy/workspace-deploy.js.map +1 -1
- package/dist/mcp/build-server.d.ts.map +1 -1
- package/dist/mcp/build-server.js +23 -9
- package/dist/mcp/build-server.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +68 -13
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/docs/content/multi-app-workspace.md +2 -2
- package/docs/design/durable-agent-runs.md +458 -4
- package/package.json +1 -1
|
@@ -39,10 +39,9 @@ body {
|
|
|
39
39
|
height: 100%;
|
|
40
40
|
border-radius: 50%;
|
|
41
41
|
overflow: hidden;
|
|
42
|
-
background: #
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
0 0 0 4px rgba(255, 255, 255, 0.92);
|
|
42
|
+
background: #18181b;
|
|
43
|
+
border: 3px solid rgba(255, 255, 255, 0.92);
|
|
44
|
+
box-shadow: 0 6px 18px rgba(9, 9, 11, 0.4);
|
|
46
45
|
display: flex;
|
|
47
46
|
align-items: center;
|
|
48
47
|
justify-content: center;
|
|
@@ -75,7 +74,7 @@ body {
|
|
|
75
74
|
display: flex;
|
|
76
75
|
align-items: center;
|
|
77
76
|
justify-content: center;
|
|
78
|
-
background: rgba(
|
|
77
|
+
background: rgba(9, 9, 11, 0.55);
|
|
79
78
|
backdrop-filter: blur(2px);
|
|
80
79
|
}
|
|
81
80
|
|
|
@@ -126,9 +125,9 @@ body {
|
|
|
126
125
|
font-size: clamp(96px, 22vmin, 240px);
|
|
127
126
|
font-weight: 700;
|
|
128
127
|
color: #fff;
|
|
129
|
-
text-shadow: 0 6px 30px rgba(
|
|
128
|
+
text-shadow: 0 6px 30px rgba(9, 9, 11, 0.6);
|
|
130
129
|
line-height: 1;
|
|
131
|
-
animation: countdown-pop
|
|
130
|
+
animation: countdown-pop 0.45s ease-out forwards;
|
|
132
131
|
}
|
|
133
132
|
|
|
134
133
|
.countdown-go {
|
|
@@ -138,21 +137,17 @@ body {
|
|
|
138
137
|
|
|
139
138
|
@keyframes countdown-pop {
|
|
140
139
|
0% {
|
|
141
|
-
transform: scale(0.
|
|
140
|
+
transform: scale(0.55);
|
|
142
141
|
opacity: 0;
|
|
143
142
|
}
|
|
144
|
-
|
|
145
|
-
transform: scale(1);
|
|
143
|
+
45% {
|
|
144
|
+
transform: scale(1.08);
|
|
146
145
|
opacity: 1;
|
|
147
146
|
}
|
|
148
|
-
|
|
147
|
+
100% {
|
|
149
148
|
transform: scale(1);
|
|
150
149
|
opacity: 1;
|
|
151
150
|
}
|
|
152
|
-
100% {
|
|
153
|
-
transform: scale(1.25);
|
|
154
|
-
opacity: 0;
|
|
155
|
-
}
|
|
156
151
|
}
|
|
157
152
|
|
|
158
153
|
.countdown-hint {
|
|
@@ -163,7 +158,7 @@ body {
|
|
|
163
158
|
color: rgba(255, 255, 255, 0.85);
|
|
164
159
|
font-size: 15px;
|
|
165
160
|
font-weight: 500;
|
|
166
|
-
background: rgba(
|
|
161
|
+
background: rgba(9, 9, 11, 0.45);
|
|
167
162
|
padding: 8px 16px;
|
|
168
163
|
border-radius: 999px;
|
|
169
164
|
}
|
|
@@ -181,19 +176,21 @@ body {
|
|
|
181
176
|
}
|
|
182
177
|
|
|
183
178
|
.toolbar-v {
|
|
179
|
+
/* Top-anchored so Stop/time/pause stay put and the pill grows DOWNWARD on
|
|
180
|
+
hover (centering shifted the buttons up and caused misclicks). */
|
|
184
181
|
position: absolute;
|
|
185
|
-
top:
|
|
182
|
+
top: 0;
|
|
186
183
|
left: 50%;
|
|
187
|
-
transform:
|
|
184
|
+
transform: translateX(-50%);
|
|
188
185
|
display: flex;
|
|
189
186
|
flex-direction: column;
|
|
190
187
|
align-items: center;
|
|
191
188
|
gap: 8px;
|
|
192
189
|
padding: 9px;
|
|
193
190
|
border-radius: 20px;
|
|
194
|
-
background: rgba(
|
|
191
|
+
background: rgba(24, 24, 27, 0.94);
|
|
195
192
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
196
|
-
box-shadow: 0 10px 28px rgba(
|
|
193
|
+
box-shadow: 0 10px 28px rgba(9, 9, 11, 0.45);
|
|
197
194
|
color: #fff;
|
|
198
195
|
-webkit-user-select: none;
|
|
199
196
|
user-select: none;
|
|
@@ -323,9 +320,9 @@ body {
|
|
|
323
320
|
gap: 9px;
|
|
324
321
|
padding: 14px 16px;
|
|
325
322
|
border-radius: 14px;
|
|
326
|
-
background: rgba(
|
|
323
|
+
background: rgba(24, 24, 27, 0.95);
|
|
327
324
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
328
|
-
box-shadow: 0 10px 28px rgba(
|
|
325
|
+
box-shadow: 0 10px 28px rgba(9, 9, 11, 0.45);
|
|
329
326
|
color: #fff;
|
|
330
327
|
}
|
|
331
328
|
|
|
@@ -363,7 +360,7 @@ body {
|
|
|
363
360
|
height: 100%;
|
|
364
361
|
width: 40%;
|
|
365
362
|
border-radius: 999px;
|
|
366
|
-
background: #
|
|
363
|
+
background: #d4d4d8;
|
|
367
364
|
animation: saving-indeterminate 1.1s ease-in-out infinite;
|
|
368
365
|
}
|
|
369
366
|
|
|
@@ -375,3 +372,56 @@ body {
|
|
|
375
372
|
margin-left: 100%;
|
|
376
373
|
}
|
|
377
374
|
}
|
|
375
|
+
|
|
376
|
+
/* Bubble size dots (small / large), revealed on hover — desktop-style. */
|
|
377
|
+
.bubble-sizes {
|
|
378
|
+
position: absolute;
|
|
379
|
+
bottom: 7%;
|
|
380
|
+
left: 50%;
|
|
381
|
+
transform: translateX(-50%);
|
|
382
|
+
display: flex;
|
|
383
|
+
align-items: center;
|
|
384
|
+
gap: 9px;
|
|
385
|
+
padding: 5px 9px;
|
|
386
|
+
border-radius: 999px;
|
|
387
|
+
background: rgba(9, 9, 11, 0.55);
|
|
388
|
+
-webkit-backdrop-filter: blur(4px);
|
|
389
|
+
backdrop-filter: blur(4px);
|
|
390
|
+
opacity: 0;
|
|
391
|
+
transition: opacity 0.15s ease;
|
|
392
|
+
pointer-events: none;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
.bubble:hover .bubble-sizes {
|
|
396
|
+
opacity: 1;
|
|
397
|
+
pointer-events: auto;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
.bubble-size-dot {
|
|
401
|
+
border: none;
|
|
402
|
+
padding: 0;
|
|
403
|
+
border-radius: 50%;
|
|
404
|
+
background: rgba(255, 255, 255, 0.55);
|
|
405
|
+
cursor: pointer;
|
|
406
|
+
transition:
|
|
407
|
+
background 0.12s ease,
|
|
408
|
+
transform 0.1s ease;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
.bubble-size-dot:hover {
|
|
412
|
+
background: #fff;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
.bubble-size-dot:active {
|
|
416
|
+
transform: scale(0.9);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
.bubble-size-sm {
|
|
420
|
+
width: 8px;
|
|
421
|
+
height: 8px;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
.bubble-size-lg {
|
|
425
|
+
width: 13px;
|
|
426
|
+
height: 13px;
|
|
427
|
+
}
|
|
@@ -75,21 +75,82 @@ function send(type: string, extra: Record<string, unknown> = {}): void {
|
|
|
75
75
|
|
|
76
76
|
/* ---------------------------------------------------------------- bubble --- */
|
|
77
77
|
|
|
78
|
+
function postBubble(kind: string, extra: Record<string, unknown> = {}): void {
|
|
79
|
+
try {
|
|
80
|
+
window.parent.postMessage(
|
|
81
|
+
{ source: "clips-overlay", kind, part: "bubble", ...extra },
|
|
82
|
+
"*",
|
|
83
|
+
);
|
|
84
|
+
} catch {
|
|
85
|
+
/* parent gone */
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
78
89
|
async function initBubble(): Promise<void> {
|
|
79
90
|
const bubble = document.createElement("div");
|
|
80
91
|
bubble.className = "bubble";
|
|
81
92
|
const ring = document.createElement("div");
|
|
82
93
|
ring.className = "bubble-ring";
|
|
83
94
|
bubble.appendChild(ring);
|
|
95
|
+
|
|
96
|
+
// Drag: the content script owns the iframe position, so we just signal the
|
|
97
|
+
// start of a drag and it captures the pointer page-wide.
|
|
98
|
+
bubble.style.cursor = "grab";
|
|
99
|
+
bubble.addEventListener("pointerdown", (e) => {
|
|
100
|
+
if (e.button !== 0) return;
|
|
101
|
+
if ((e.target as HTMLElement).closest("[data-no-drag]")) return;
|
|
102
|
+
e.preventDefault();
|
|
103
|
+
bubble.style.cursor = "grabbing";
|
|
104
|
+
postBubble("bubble-drag-start");
|
|
105
|
+
const restore = (): void => {
|
|
106
|
+
bubble.style.cursor = "grab";
|
|
107
|
+
window.removeEventListener("pointerup", restore);
|
|
108
|
+
};
|
|
109
|
+
window.addEventListener("pointerup", restore);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// Size dots (small / large), revealed on hover — like the desktop bubble.
|
|
113
|
+
const sizes = document.createElement("div");
|
|
114
|
+
sizes.className = "bubble-sizes";
|
|
115
|
+
sizes.setAttribute("data-no-drag", "");
|
|
116
|
+
for (const key of ["sm", "lg"] as const) {
|
|
117
|
+
const dot = document.createElement("button");
|
|
118
|
+
dot.type = "button";
|
|
119
|
+
dot.className = `bubble-size-dot bubble-size-${key}`;
|
|
120
|
+
dot.title = key === "sm" ? "Small" : "Large";
|
|
121
|
+
dot.setAttribute(
|
|
122
|
+
"aria-label",
|
|
123
|
+
key === "sm" ? "Small bubble" : "Large bubble",
|
|
124
|
+
);
|
|
125
|
+
dot.setAttribute("data-no-drag", "");
|
|
126
|
+
dot.addEventListener("click", (e) => {
|
|
127
|
+
e.stopPropagation();
|
|
128
|
+
postBubble("bubble-size", { size: key });
|
|
129
|
+
});
|
|
130
|
+
sizes.appendChild(dot);
|
|
131
|
+
}
|
|
132
|
+
bubble.appendChild(sizes);
|
|
133
|
+
|
|
84
134
|
root.appendChild(bubble);
|
|
85
135
|
|
|
86
136
|
try {
|
|
137
|
+
const videoDeviceId = await new Promise<string>((resolve) => {
|
|
138
|
+
try {
|
|
139
|
+
chrome.storage.sync.get("videoDeviceId", (v) =>
|
|
140
|
+
resolve(typeof v.videoDeviceId === "string" ? v.videoDeviceId : ""),
|
|
141
|
+
);
|
|
142
|
+
} catch {
|
|
143
|
+
resolve("");
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
const videoConstraint: MediaTrackConstraints = {
|
|
147
|
+
width: { ideal: 640 },
|
|
148
|
+
height: { ideal: 640 },
|
|
149
|
+
};
|
|
150
|
+
if (videoDeviceId) videoConstraint.deviceId = { exact: videoDeviceId };
|
|
151
|
+
else videoConstraint.facingMode = "user";
|
|
87
152
|
const stream = await navigator.mediaDevices.getUserMedia({
|
|
88
|
-
video:
|
|
89
|
-
width: { ideal: 640 },
|
|
90
|
-
height: { ideal: 640 },
|
|
91
|
-
facingMode: "user",
|
|
92
|
-
},
|
|
153
|
+
video: videoConstraint,
|
|
93
154
|
audio: false,
|
|
94
155
|
});
|
|
95
156
|
const video = document.createElement("video");
|
|
@@ -99,7 +160,9 @@ async function initBubble(): Promise<void> {
|
|
|
99
160
|
video.srcObject = stream;
|
|
100
161
|
ring.appendChild(video);
|
|
101
162
|
await video.play().catch(() => undefined);
|
|
102
|
-
|
|
163
|
+
console.log("[clips-overlay] camera bubble live");
|
|
164
|
+
} catch (err) {
|
|
165
|
+
console.warn("[clips-overlay] camera getUserMedia failed:", err);
|
|
103
166
|
const empty = document.createElement("div");
|
|
104
167
|
empty.className = "bubble-empty";
|
|
105
168
|
empty.innerHTML = ICONS.cameraOff;
|
|
@@ -148,14 +211,20 @@ function initCountdown(): void {
|
|
|
148
211
|
root.appendChild(wrap);
|
|
149
212
|
|
|
150
213
|
let lastShown = "";
|
|
214
|
+
// Compute the fallback end-time ONCE (if the worker's countdownEndsAtMs never
|
|
215
|
+
// arrives) — recomputing it every frame froze the number on "3".
|
|
216
|
+
let fallbackEndsAt = 0;
|
|
151
217
|
const render = (): void => {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
218
|
+
let endsAt = state.countdownEndsAtMs;
|
|
219
|
+
if (endsAt <= 0) {
|
|
220
|
+
if (fallbackEndsAt === 0) {
|
|
221
|
+
const fallback =
|
|
222
|
+
Number(params.get("seconds") || String(COUNTDOWN_FALLBACK)) ||
|
|
223
|
+
COUNTDOWN_FALLBACK;
|
|
224
|
+
fallbackEndsAt = Date.now() + fallback * 1000;
|
|
225
|
+
}
|
|
226
|
+
endsAt = fallbackEndsAt;
|
|
227
|
+
}
|
|
159
228
|
const remainingMs = endsAt - Date.now();
|
|
160
229
|
if (state.phase !== "countdown" || remainingMs <= 0) {
|
|
161
230
|
if (lastShown !== "Go") {
|
|
@@ -162,6 +162,31 @@
|
|
|
162
162
|
</header>
|
|
163
163
|
|
|
164
164
|
<div id="idle-content">
|
|
165
|
+
<div id="unsupported-notice" class="notice" role="alert" hidden>
|
|
166
|
+
<svg
|
|
167
|
+
class="notice-icon"
|
|
168
|
+
viewBox="0 0 24 24"
|
|
169
|
+
fill="none"
|
|
170
|
+
aria-hidden="true"
|
|
171
|
+
>
|
|
172
|
+
<path
|
|
173
|
+
d="M12 9v4M12 17h.01M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z"
|
|
174
|
+
stroke="currentColor"
|
|
175
|
+
stroke-width="1.75"
|
|
176
|
+
stroke-linecap="round"
|
|
177
|
+
stroke-linejoin="round"
|
|
178
|
+
/>
|
|
179
|
+
</svg>
|
|
180
|
+
<div class="notice-body">
|
|
181
|
+
<div class="notice-title">Clips can't draw controls here</div>
|
|
182
|
+
<div class="notice-text">
|
|
183
|
+
This is a browser page (like New Tab), so the countdown and
|
|
184
|
+
on-screen controls won't appear. You can still record a window or
|
|
185
|
+
full screen — stop from the Clips icon — or open a website for the
|
|
186
|
+
full experience.
|
|
187
|
+
</div>
|
|
188
|
+
</div>
|
|
189
|
+
</div>
|
|
165
190
|
<section class="panel" aria-label="Recorder setup">
|
|
166
191
|
<div id="source-row" class="row row-on">
|
|
167
192
|
<span class="row-icon" aria-hidden="true">
|
|
@@ -242,10 +267,24 @@
|
|
|
242
267
|
/>
|
|
243
268
|
</svg>
|
|
244
269
|
</span>
|
|
245
|
-
<button type="button" class="row-button"
|
|
246
|
-
<span class="row-label"
|
|
270
|
+
<button id="camera-device-button" type="button" class="row-button">
|
|
271
|
+
<span id="camera-device-label" class="row-label"
|
|
272
|
+
>Default camera</span
|
|
273
|
+
>
|
|
247
274
|
<span class="row-flex" aria-hidden="true"></span>
|
|
275
|
+
<span class="row-chev" aria-hidden="true">
|
|
276
|
+
<svg viewBox="0 0 24 24" fill="none">
|
|
277
|
+
<path
|
|
278
|
+
d="M6 9l6 6 6-6"
|
|
279
|
+
stroke="currentColor"
|
|
280
|
+
stroke-width="2"
|
|
281
|
+
stroke-linecap="round"
|
|
282
|
+
stroke-linejoin="round"
|
|
283
|
+
/>
|
|
284
|
+
</svg>
|
|
285
|
+
</span>
|
|
248
286
|
</button>
|
|
287
|
+
<div id="camera-device-menu" class="row-menu" hidden></div>
|
|
249
288
|
<button
|
|
250
289
|
id="include-camera"
|
|
251
290
|
class="toggle toggle-on"
|
|
@@ -257,7 +296,7 @@
|
|
|
257
296
|
</button>
|
|
258
297
|
</div>
|
|
259
298
|
|
|
260
|
-
<div class="row row-on">
|
|
299
|
+
<div id="microphone-row" class="row row-on">
|
|
261
300
|
<span class="row-icon" aria-hidden="true">
|
|
262
301
|
<svg viewBox="0 0 24 24" fill="none">
|
|
263
302
|
<rect
|
|
@@ -277,10 +316,28 @@
|
|
|
277
316
|
/>
|
|
278
317
|
</svg>
|
|
279
318
|
</span>
|
|
280
|
-
<button
|
|
281
|
-
|
|
319
|
+
<button
|
|
320
|
+
id="microphone-device-button"
|
|
321
|
+
type="button"
|
|
322
|
+
class="row-button"
|
|
323
|
+
>
|
|
324
|
+
<span id="microphone-device-label" class="row-label"
|
|
325
|
+
>Default mic</span
|
|
326
|
+
>
|
|
282
327
|
<span class="row-flex" aria-hidden="true"></span>
|
|
328
|
+
<span class="row-chev" aria-hidden="true">
|
|
329
|
+
<svg viewBox="0 0 24 24" fill="none">
|
|
330
|
+
<path
|
|
331
|
+
d="M6 9l6 6 6-6"
|
|
332
|
+
stroke="currentColor"
|
|
333
|
+
stroke-width="2"
|
|
334
|
+
stroke-linecap="round"
|
|
335
|
+
stroke-linejoin="round"
|
|
336
|
+
/>
|
|
337
|
+
</svg>
|
|
338
|
+
</span>
|
|
283
339
|
</button>
|
|
340
|
+
<div id="microphone-device-menu" class="row-menu" hidden></div>
|
|
284
341
|
<button
|
|
285
342
|
id="include-microphone"
|
|
286
343
|
class="toggle toggle-on"
|