open-nami 1.2.6 → 1.2.8
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/cli.js +186 -230
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -9,7 +9,7 @@ var require_package = __commonJS({
|
|
|
9
9
|
"package.json"(exports, module) {
|
|
10
10
|
module.exports = {
|
|
11
11
|
name: "open-nami",
|
|
12
|
-
version: "1.2.
|
|
12
|
+
version: "1.2.8",
|
|
13
13
|
description: "Open Nami: terminal-first bulk social media profile downloader for Instagram, TikTok, Facebook & X.",
|
|
14
14
|
type: "module",
|
|
15
15
|
bin: {
|
|
@@ -77,8 +77,8 @@ import { createRequire } from "module";
|
|
|
77
77
|
import { render } from "ink";
|
|
78
78
|
|
|
79
79
|
// src/app.tsx
|
|
80
|
-
import { useState as useState9, useCallback as
|
|
81
|
-
import { Box as Box15, Text as Text17, useApp, useInput as
|
|
80
|
+
import { useState as useState9, useCallback as useCallback4, useRef as useRef5, useEffect as useEffect8, useMemo as useMemo3 } from "react";
|
|
81
|
+
import { Box as Box15, Text as Text17, useApp, useInput as useInput5, useStdout as useStdout3 } from "ink";
|
|
82
82
|
import Spinner4 from "ink-spinner";
|
|
83
83
|
|
|
84
84
|
// src/components/fullscreen.tsx
|
|
@@ -691,8 +691,8 @@ function Panel({ title, width, children }) {
|
|
|
691
691
|
}
|
|
692
692
|
|
|
693
693
|
// src/components/views/picking-view.tsx
|
|
694
|
-
import { useState as useState4, useEffect as useEffect4
|
|
695
|
-
import { Box as Box6, Text as Text7
|
|
694
|
+
import { useState as useState4, useEffect as useEffect4 } from "react";
|
|
695
|
+
import { Box as Box6, Text as Text7 } from "ink";
|
|
696
696
|
import SelectInput from "ink-select-input";
|
|
697
697
|
|
|
698
698
|
// src/lib/engines/checkpoint.ts
|
|
@@ -4368,7 +4368,7 @@ async function dispatchDownload(options) {
|
|
|
4368
4368
|
}
|
|
4369
4369
|
|
|
4370
4370
|
// src/components/views/picking-view.tsx
|
|
4371
|
-
import {
|
|
4371
|
+
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
4372
4372
|
function ChoiceIndicator({ isSelected }) {
|
|
4373
4373
|
const theme = useTheme();
|
|
4374
4374
|
return /* @__PURE__ */ jsx8(Box6, { marginRight: 1, children: /* @__PURE__ */ jsx8(Text7, { color: theme.primary, children: isSelected ? "\u276F" : " " }) });
|
|
@@ -4392,14 +4392,13 @@ function getPickingOptions(platform) {
|
|
|
4392
4392
|
});
|
|
4393
4393
|
return items;
|
|
4394
4394
|
}
|
|
4395
|
-
var DATE_PRESETS = ["all", "24h", "7d", "30d", "2024", "2023", "2022", "2021", "custom"];
|
|
4396
|
-
var LIMIT_PRESETS = [void 0, 10, 24, 50, 100, "custom"];
|
|
4397
4395
|
function PickingView({
|
|
4398
4396
|
contentWidth,
|
|
4399
4397
|
profile,
|
|
4400
4398
|
outputDir,
|
|
4401
4399
|
initialLimit,
|
|
4402
4400
|
initialSince,
|
|
4401
|
+
initialUntil,
|
|
4403
4402
|
initialWriteMetadata = false,
|
|
4404
4403
|
initialResume = true,
|
|
4405
4404
|
onSelect,
|
|
@@ -4409,26 +4408,13 @@ function PickingView({
|
|
|
4409
4408
|
}) {
|
|
4410
4409
|
const platformName = profile.platform.charAt(0).toUpperCase() + profile.platform.slice(1);
|
|
4411
4410
|
const items = getPickingOptions(profile.platform);
|
|
4412
|
-
const [limit, setLimit] = useState4(initialLimit);
|
|
4413
|
-
const [dateFilter, setDateFilter] = useState4(() => {
|
|
4414
|
-
if (typeof initialSince === "string" && initialSince.trim()) {
|
|
4415
|
-
return initialSince.trim();
|
|
4416
|
-
}
|
|
4417
|
-
return "all";
|
|
4418
|
-
});
|
|
4419
|
-
const [writeMetadata, setWriteMetadata] = useState4(initialWriteMetadata);
|
|
4420
|
-
const [resume, setResume] = useState4(initialResume);
|
|
4421
4411
|
const [hasCheckpoint, setHasCheckpoint] = useState4(false);
|
|
4422
|
-
const [editingModal, setEditingModal] = useState4(null);
|
|
4423
|
-
const [customLimitText, setCustomLimitText] = useState4("");
|
|
4424
|
-
const [customDateText, setCustomDateText] = useState4("");
|
|
4425
4412
|
const targetDir = resolveDefaultDownloadDir(profile.platform, profile.username, outputDir);
|
|
4426
4413
|
useEffect4(() => {
|
|
4427
4414
|
let isMounted = true;
|
|
4428
4415
|
loadCheckpoint(targetDir).then((cp) => {
|
|
4429
4416
|
if (isMounted && cp && !cp.completed && Object.keys(cp.cursors || {}).length > 0) {
|
|
4430
4417
|
setHasCheckpoint(true);
|
|
4431
|
-
setResume(true);
|
|
4432
4418
|
}
|
|
4433
4419
|
}).catch(() => {
|
|
4434
4420
|
});
|
|
@@ -4436,68 +4422,14 @@ function PickingView({
|
|
|
4436
4422
|
isMounted = false;
|
|
4437
4423
|
};
|
|
4438
4424
|
}, [targetDir]);
|
|
4439
|
-
const cycleLimit = useCallback(() => {
|
|
4440
|
-
const curIdx = LIMIT_PRESETS.findIndex((p) => p === limit);
|
|
4441
|
-
const nextIdx = (curIdx + 1) % LIMIT_PRESETS.length;
|
|
4442
|
-
const nextVal = LIMIT_PRESETS[nextIdx];
|
|
4443
|
-
if (nextVal === "custom") {
|
|
4444
|
-
setCustomLimitText(limit ? String(limit) : "24");
|
|
4445
|
-
setEditingModal("limit");
|
|
4446
|
-
} else {
|
|
4447
|
-
setLimit(nextVal);
|
|
4448
|
-
}
|
|
4449
|
-
}, [limit]);
|
|
4450
|
-
const cycleDate = useCallback(() => {
|
|
4451
|
-
const curIdx = DATE_PRESETS.indexOf(dateFilter);
|
|
4452
|
-
const nextIdx = (curIdx + 1) % DATE_PRESETS.length;
|
|
4453
|
-
const nextVal = DATE_PRESETS[nextIdx];
|
|
4454
|
-
if (nextVal === "custom") {
|
|
4455
|
-
setCustomDateText(dateFilter !== "all" ? dateFilter : "2021");
|
|
4456
|
-
setEditingModal("date");
|
|
4457
|
-
} else {
|
|
4458
|
-
setDateFilter(nextVal);
|
|
4459
|
-
}
|
|
4460
|
-
}, [dateFilter]);
|
|
4461
|
-
const toggleMetadata = useCallback(() => {
|
|
4462
|
-
setWriteMetadata((prev) => !prev);
|
|
4463
|
-
}, []);
|
|
4464
|
-
const toggleResume = useCallback(() => {
|
|
4465
|
-
setResume((prev) => !prev);
|
|
4466
|
-
}, []);
|
|
4467
|
-
useInput2((input, key) => {
|
|
4468
|
-
if (editingModal) {
|
|
4469
|
-
if (key.escape) {
|
|
4470
|
-
setEditingModal(null);
|
|
4471
|
-
}
|
|
4472
|
-
return;
|
|
4473
|
-
}
|
|
4474
|
-
if (input === "l" || input === "L") {
|
|
4475
|
-
cycleLimit();
|
|
4476
|
-
return;
|
|
4477
|
-
}
|
|
4478
|
-
if (input === "d" || input === "D") {
|
|
4479
|
-
cycleDate();
|
|
4480
|
-
return;
|
|
4481
|
-
}
|
|
4482
|
-
if (input === "m" || input === "M") {
|
|
4483
|
-
toggleMetadata();
|
|
4484
|
-
return;
|
|
4485
|
-
}
|
|
4486
|
-
if (input === "r" || input === "R") {
|
|
4487
|
-
toggleResume();
|
|
4488
|
-
return;
|
|
4489
|
-
}
|
|
4490
|
-
}, { isActive: Boolean(process.stdin.isTTY) });
|
|
4491
4425
|
const handleItemSelect = (selectedChoice) => {
|
|
4492
|
-
if (editingModal) return;
|
|
4493
|
-
const dateRange = resolveDateFilter(dateFilter);
|
|
4494
4426
|
onSelect({
|
|
4495
4427
|
choice: selectedChoice,
|
|
4496
|
-
limit,
|
|
4497
|
-
since:
|
|
4498
|
-
until:
|
|
4499
|
-
writeMetadata,
|
|
4500
|
-
resume
|
|
4428
|
+
limit: initialLimit,
|
|
4429
|
+
since: typeof initialSince === "string" ? initialSince : void 0,
|
|
4430
|
+
until: typeof initialUntil === "string" ? initialUntil : void 0,
|
|
4431
|
+
writeMetadata: initialWriteMetadata,
|
|
4432
|
+
resume: initialResume
|
|
4501
4433
|
});
|
|
4502
4434
|
};
|
|
4503
4435
|
return /* @__PURE__ */ jsxs6(Box6, { width: contentWidth, children: [
|
|
@@ -4513,90 +4445,23 @@ function PickingView({
|
|
|
4513
4445
|
profile.cleanUrl ? ` \xB7 ${profile.cleanUrl}` : ""
|
|
4514
4446
|
] }),
|
|
4515
4447
|
/* @__PURE__ */ jsx8(Gap2, {}),
|
|
4516
|
-
/* @__PURE__ */ jsx8(Text7, { color: theme.gray, dimColor: theme.dimSecondary, children: "Select
|
|
4448
|
+
/* @__PURE__ */ jsx8(Text7, { color: theme.gray, dimColor: theme.dimSecondary, children: "Select what to download from this profile." }),
|
|
4517
4449
|
hasCheckpoint ? /* @__PURE__ */ jsx8(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx8(Text7, { color: theme.primary, bold: true, children: "\u26A1 Checkpoint found (cursor saved)" }) }) : null
|
|
4518
4450
|
] }),
|
|
4519
|
-
/* @__PURE__ */
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4524
|
-
|
|
4525
|
-
|
|
4526
|
-
|
|
4527
|
-
|
|
4528
|
-
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
|
|
4532
|
-
|
|
4533
|
-
),
|
|
4534
|
-
/* @__PURE__ */ jsx8(
|
|
4535
|
-
Box6,
|
|
4536
|
-
{
|
|
4537
|
-
flexDirection: "column",
|
|
4538
|
-
marginTop: 1,
|
|
4539
|
-
borderStyle: "round",
|
|
4540
|
-
borderColor: editingModal ? theme.primary : theme.gray,
|
|
4541
|
-
borderDimColor: !editingModal,
|
|
4542
|
-
paddingX: 1,
|
|
4543
|
-
children: editingModal === "limit" ? /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
4544
|
-
/* @__PURE__ */ jsx8(Text7, { bold: true, color: theme.primary, children: "Set post limit (e.g. 24, all):" }),
|
|
4545
|
-
/* @__PURE__ */ jsx8(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx8(
|
|
4546
|
-
TextInput,
|
|
4547
|
-
{
|
|
4548
|
-
value: customLimitText,
|
|
4549
|
-
onChange: setCustomLimitText,
|
|
4550
|
-
onSubmit: (val) => {
|
|
4551
|
-
const parsed = parseLimit(val);
|
|
4552
|
-
setLimit(parsed);
|
|
4553
|
-
setEditingModal(null);
|
|
4554
|
-
},
|
|
4555
|
-
width: 24
|
|
4556
|
-
}
|
|
4557
|
-
) }),
|
|
4558
|
-
/* @__PURE__ */ jsx8(Text7, { color: theme.gray, dimColor: theme.dimSecondary, children: "\u21B5 confirm \xB7 esc cancel" })
|
|
4559
|
-
] }) : editingModal === "date" ? /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
4560
|
-
/* @__PURE__ */ jsx8(Text7, { bold: true, color: theme.primary, children: "Set date or year (e.g. 2021, 7d):" }),
|
|
4561
|
-
/* @__PURE__ */ jsx8(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx8(
|
|
4562
|
-
TextInput,
|
|
4563
|
-
{
|
|
4564
|
-
value: customDateText,
|
|
4565
|
-
onChange: setCustomDateText,
|
|
4566
|
-
onSubmit: (val) => {
|
|
4567
|
-
const trimmed = val.trim();
|
|
4568
|
-
setDateFilter(trimmed ? trimmed : "all");
|
|
4569
|
-
setEditingModal(null);
|
|
4570
|
-
},
|
|
4571
|
-
width: 24
|
|
4572
|
-
}
|
|
4573
|
-
) }),
|
|
4574
|
-
/* @__PURE__ */ jsx8(Text7, { color: theme.gray, dimColor: theme.dimSecondary, children: "\u21B5 confirm \xB7 esc cancel" })
|
|
4575
|
-
] }) : /* @__PURE__ */ jsxs6(Fragment2, { children: [
|
|
4576
|
-
/* @__PURE__ */ jsxs6(Box6, { justifyContent: "space-between", children: [
|
|
4577
|
-
/* @__PURE__ */ jsxs6(Text7, { color: theme.gray, dimColor: theme.dimSecondary, children: [
|
|
4578
|
-
"[l] Posts: ",
|
|
4579
|
-
/* @__PURE__ */ jsx8(Text7, { color: theme.primary, bold: true, children: limit ? `${limit}` : "ALL" })
|
|
4580
|
-
] }),
|
|
4581
|
-
/* @__PURE__ */ jsxs6(Text7, { color: theme.gray, dimColor: theme.dimSecondary, children: [
|
|
4582
|
-
"[d] Date: ",
|
|
4583
|
-
/* @__PURE__ */ jsx8(Text7, { color: theme.primary, bold: true, children: dateFilter.toUpperCase() })
|
|
4584
|
-
] })
|
|
4585
|
-
] }),
|
|
4586
|
-
/* @__PURE__ */ jsxs6(Box6, { justifyContent: "space-between", children: [
|
|
4587
|
-
/* @__PURE__ */ jsxs6(Text7, { color: theme.gray, dimColor: theme.dimSecondary, children: [
|
|
4588
|
-
"[m] Meta: ",
|
|
4589
|
-
/* @__PURE__ */ jsx8(Text7, { color: theme.primary, bold: true, children: writeMetadata ? "ON" : "OFF" })
|
|
4590
|
-
] }),
|
|
4591
|
-
/* @__PURE__ */ jsxs6(Text7, { color: theme.gray, dimColor: theme.dimSecondary, children: [
|
|
4592
|
-
"[r] Resume: ",
|
|
4593
|
-
/* @__PURE__ */ jsx8(Text7, { color: theme.primary, bold: true, children: resume ? "ON" : "OFF" })
|
|
4594
|
-
] })
|
|
4595
|
-
] })
|
|
4596
|
-
] })
|
|
4597
|
-
}
|
|
4598
|
-
)
|
|
4599
|
-
] })
|
|
4451
|
+
/* @__PURE__ */ jsx8(Panel, { title: "Download", width: 38, children: /* @__PURE__ */ jsx8(
|
|
4452
|
+
SelectInput,
|
|
4453
|
+
{
|
|
4454
|
+
indicatorComponent: ChoiceIndicator,
|
|
4455
|
+
itemComponent: ChoiceItem,
|
|
4456
|
+
items: items.map((item, index) => ({
|
|
4457
|
+
key: String(index),
|
|
4458
|
+
label: item.label,
|
|
4459
|
+
value: item.value
|
|
4460
|
+
})),
|
|
4461
|
+
onSelect: (item) => handleItemSelect(item.value),
|
|
4462
|
+
onHighlight: (item) => onHighlight?.(item.value)
|
|
4463
|
+
}
|
|
4464
|
+
) })
|
|
4600
4465
|
] });
|
|
4601
4466
|
}
|
|
4602
4467
|
|
|
@@ -4808,7 +4673,7 @@ function DownloadingView({
|
|
|
4808
4673
|
// src/components/views/completion-view.tsx
|
|
4809
4674
|
import os7 from "os";
|
|
4810
4675
|
import { Box as Box10, Text as Text12 } from "ink";
|
|
4811
|
-
import { Fragment as
|
|
4676
|
+
import { Fragment as Fragment2, jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
4812
4677
|
var DONE_LABEL = "\u21B5 download another";
|
|
4813
4678
|
function CompletionView({
|
|
4814
4679
|
profile,
|
|
@@ -4820,10 +4685,10 @@ function CompletionView({
|
|
|
4820
4685
|
const plural = result.downloadedCount === 1 ? "" : "s";
|
|
4821
4686
|
const skipText = result.skippedCount > 0 ? ` (${result.skippedCount} archived)` : "";
|
|
4822
4687
|
return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", alignItems: "center", children: [
|
|
4823
|
-
/* @__PURE__ */ jsx13(Text12, { children: isZero ? /* @__PURE__ */ jsxs10(
|
|
4688
|
+
/* @__PURE__ */ jsx13(Text12, { children: isZero ? /* @__PURE__ */ jsxs10(Fragment2, { children: [
|
|
4824
4689
|
/* @__PURE__ */ jsx13(Text12, { bold: true, color: theme.primary, children: "\u2713 profile scanned " }),
|
|
4825
4690
|
/* @__PURE__ */ jsx13(Text12, { color: theme.primary, children: "\u2014 0 media items found" })
|
|
4826
|
-
] }) : /* @__PURE__ */ jsxs10(
|
|
4691
|
+
] }) : /* @__PURE__ */ jsxs10(Fragment2, { children: [
|
|
4827
4692
|
/* @__PURE__ */ jsx13(Text12, { bold: true, color: theme.primary, children: "\u2713 profile downloaded! " }),
|
|
4828
4693
|
/* @__PURE__ */ jsx13(Text12, { color: theme.primary, children: "saved to:" })
|
|
4829
4694
|
] }) }),
|
|
@@ -4870,8 +4735,8 @@ function ErrorView({ message, hint, columns, theme }) {
|
|
|
4870
4735
|
}
|
|
4871
4736
|
|
|
4872
4737
|
// src/components/views/settings-view.tsx
|
|
4873
|
-
import { useState as useState6, useMemo as useMemo2, useCallback
|
|
4874
|
-
import { Box as Box12, Text as Text14, useInput as
|
|
4738
|
+
import { useState as useState6, useMemo as useMemo2, useCallback } from "react";
|
|
4739
|
+
import { Box as Box12, Text as Text14, useInput as useInput2 } from "ink";
|
|
4875
4740
|
import fs11 from "fs";
|
|
4876
4741
|
import path11 from "path";
|
|
4877
4742
|
import os8 from "os";
|
|
@@ -4895,7 +4760,7 @@ function SettingsView({
|
|
|
4895
4760
|
const initialConfig = useMemo2(() => loadConfig(), []);
|
|
4896
4761
|
const [internalFocus, setInternalFocus] = useState6("cookies");
|
|
4897
4762
|
const focusedField = controlledFocus ?? internalFocus;
|
|
4898
|
-
const setField =
|
|
4763
|
+
const setField = useCallback(
|
|
4899
4764
|
(field) => {
|
|
4900
4765
|
setInternalFocus(field);
|
|
4901
4766
|
onFocusChange?.(field);
|
|
@@ -4907,7 +4772,7 @@ function SettingsView({
|
|
|
4907
4772
|
const [writeMetadata, setWriteMetadata] = useState6(Boolean(initialConfig.writeMetadata));
|
|
4908
4773
|
const [defaultLimit, setDefaultLimit] = useState6(initialConfig.defaultLimit);
|
|
4909
4774
|
const [saved, setSaved] = useState6(false);
|
|
4910
|
-
const handleSave =
|
|
4775
|
+
const handleSave = useCallback(() => {
|
|
4911
4776
|
const existing = loadConfig();
|
|
4912
4777
|
const nextConfig = {
|
|
4913
4778
|
...existing,
|
|
@@ -4955,20 +4820,20 @@ function SettingsView({
|
|
|
4955
4820
|
}
|
|
4956
4821
|
return `target: ${path11.resolve(expandDir(dir))}`;
|
|
4957
4822
|
}, [downloadDir]);
|
|
4958
|
-
const cycleFocus =
|
|
4823
|
+
const cycleFocus = useCallback((forward = true) => {
|
|
4959
4824
|
const fields = ["cookies", "download", "metadata", "limit"];
|
|
4960
4825
|
const idx = fields.indexOf(focusedField);
|
|
4961
4826
|
const nextIdx = forward ? (idx + 1) % fields.length : (idx - 1 + fields.length) % fields.length;
|
|
4962
4827
|
setField(fields[nextIdx]);
|
|
4963
4828
|
}, [focusedField, setField]);
|
|
4964
|
-
const cycleLimit =
|
|
4829
|
+
const cycleLimit = useCallback(() => {
|
|
4965
4830
|
setDefaultLimit((prev) => {
|
|
4966
4831
|
const idx = LIMIT_OPTIONS.indexOf(prev);
|
|
4967
4832
|
const nextIdx = (idx + 1) % LIMIT_OPTIONS.length;
|
|
4968
4833
|
return LIMIT_OPTIONS[nextIdx];
|
|
4969
4834
|
});
|
|
4970
4835
|
}, []);
|
|
4971
|
-
|
|
4836
|
+
useInput2((input, key) => {
|
|
4972
4837
|
if (key.escape) {
|
|
4973
4838
|
onCancel();
|
|
4974
4839
|
return;
|
|
@@ -5096,8 +4961,8 @@ function SettingsView({
|
|
|
5096
4961
|
}
|
|
5097
4962
|
|
|
5098
4963
|
// src/components/views/watcher-view.tsx
|
|
5099
|
-
import { useState as useState7, useEffect as useEffect6, useRef as useRef3, useCallback as
|
|
5100
|
-
import { Box as Box13, Text as Text15, useInput as
|
|
4964
|
+
import { useState as useState7, useEffect as useEffect6, useRef as useRef3, useCallback as useCallback2 } from "react";
|
|
4965
|
+
import { Box as Box13, Text as Text15, useInput as useInput3 } from "ink";
|
|
5101
4966
|
import Spinner2 from "ink-spinner";
|
|
5102
4967
|
|
|
5103
4968
|
// src/lib/clipboard.ts
|
|
@@ -5352,9 +5217,9 @@ function startClipboardWatcher(options = {}) {
|
|
|
5352
5217
|
try {
|
|
5353
5218
|
const res = await dispatch({
|
|
5354
5219
|
profile: parsed,
|
|
5355
|
-
choice,
|
|
5356
|
-
outputDir: options.outputDir,
|
|
5357
|
-
writeMetadata: options.writeMetadata,
|
|
5220
|
+
choice: options.getChoice ? options.getChoice() : options.choice || "all",
|
|
5221
|
+
outputDir: resolveDefaultDownloadDir(parsed.platform, parsed.username, options.outputDir),
|
|
5222
|
+
writeMetadata: options.getWriteMetadata ? options.getWriteMetadata() : options.writeMetadata ?? false,
|
|
5358
5223
|
signal: options.signal,
|
|
5359
5224
|
onProgress: (p) => {
|
|
5360
5225
|
if (p.statusText) {
|
|
@@ -5444,16 +5309,19 @@ function revealInFileManager(targetPath) {
|
|
|
5444
5309
|
|
|
5445
5310
|
// src/components/views/watcher-view.tsx
|
|
5446
5311
|
import { jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
5312
|
+
var CHOICES = ["all", "photos", "videos", "stories", "highlights"];
|
|
5447
5313
|
function WatcherView({
|
|
5448
5314
|
onBack,
|
|
5449
5315
|
outputDir,
|
|
5450
5316
|
theme,
|
|
5451
5317
|
gapComponent: Gap2,
|
|
5452
5318
|
defaultChoice = "all",
|
|
5453
|
-
defaultWriteMetadata = false
|
|
5319
|
+
defaultWriteMetadata = false,
|
|
5320
|
+
onRegisterClickTargets
|
|
5454
5321
|
}) {
|
|
5455
5322
|
const [mediaChoice, setMediaChoice] = useState7(defaultChoice);
|
|
5456
5323
|
const [writeMetadata, setWriteMetadata] = useState7(defaultWriteMetadata);
|
|
5324
|
+
const [focusedIndex, setFocusedIndex] = useState7(0);
|
|
5457
5325
|
const [history, setHistory] = useState7([]);
|
|
5458
5326
|
const [activeJob, setActiveJob] = useState7(null);
|
|
5459
5327
|
const [stats, setStats] = useState7({ detected: 0, downloaded: 0, skipped: 0 });
|
|
@@ -5471,8 +5339,10 @@ function WatcherView({
|
|
|
5471
5339
|
useEffect6(() => {
|
|
5472
5340
|
const watcher = startClipboardWatcher({
|
|
5473
5341
|
choice: mediaChoiceRef.current,
|
|
5342
|
+
getChoice: () => mediaChoiceRef.current,
|
|
5474
5343
|
outputDir,
|
|
5475
5344
|
writeMetadata: writeMetadataRef.current,
|
|
5345
|
+
getWriteMetadata: () => writeMetadataRef.current,
|
|
5476
5346
|
onDetected: (profile) => {
|
|
5477
5347
|
setStats((prev) => ({ ...prev, detected: prev.detected + 1 }));
|
|
5478
5348
|
const newItem = {
|
|
@@ -5526,34 +5396,82 @@ function WatcherView({
|
|
|
5526
5396
|
watcher.stop();
|
|
5527
5397
|
};
|
|
5528
5398
|
}, [outputDir]);
|
|
5529
|
-
const cycleChoice =
|
|
5399
|
+
const cycleChoice = useCallback2(() => {
|
|
5530
5400
|
setMediaChoice((prev) => {
|
|
5531
|
-
|
|
5532
|
-
|
|
5533
|
-
return
|
|
5401
|
+
const idx = CHOICES.indexOf(prev);
|
|
5402
|
+
const nextChoice = CHOICES[(idx + 1) % CHOICES.length] || "all";
|
|
5403
|
+
return nextChoice;
|
|
5534
5404
|
});
|
|
5535
5405
|
}, []);
|
|
5536
|
-
const toggleMetadata =
|
|
5406
|
+
const toggleMetadata = useCallback2(() => {
|
|
5537
5407
|
setWriteMetadata((prev) => !prev);
|
|
5538
5408
|
}, []);
|
|
5539
|
-
const openFolder =
|
|
5409
|
+
const openFolder = useCallback2(() => {
|
|
5540
5410
|
const target = outputDir || resolveDefaultDownloadDir("instagram", "watcher");
|
|
5541
5411
|
revealInFileManager(target);
|
|
5542
5412
|
}, [outputDir]);
|
|
5543
|
-
|
|
5413
|
+
useEffect6(() => {
|
|
5414
|
+
if (!onRegisterClickTargets) return;
|
|
5415
|
+
const targets = [
|
|
5416
|
+
{ match: "Target:", padX: 1, action: () => {
|
|
5417
|
+
setFocusedIndex(0);
|
|
5418
|
+
cycleChoice();
|
|
5419
|
+
} },
|
|
5420
|
+
{ match: "Sidecars:", padX: 1, action: () => {
|
|
5421
|
+
setFocusedIndex(1);
|
|
5422
|
+
toggleMetadata();
|
|
5423
|
+
} },
|
|
5424
|
+
{ match: "Open Folder", padX: 1, action: () => {
|
|
5425
|
+
setFocusedIndex(2);
|
|
5426
|
+
openFolder();
|
|
5427
|
+
} },
|
|
5428
|
+
{ match: "c target", padX: 1, action: () => {
|
|
5429
|
+
setFocusedIndex(0);
|
|
5430
|
+
cycleChoice();
|
|
5431
|
+
} },
|
|
5432
|
+
{ match: "m sidecar", padX: 1, action: () => {
|
|
5433
|
+
setFocusedIndex(1);
|
|
5434
|
+
toggleMetadata();
|
|
5435
|
+
} },
|
|
5436
|
+
{ match: "o open dir", padX: 1, action: () => {
|
|
5437
|
+
setFocusedIndex(2);
|
|
5438
|
+
openFolder();
|
|
5439
|
+
} },
|
|
5440
|
+
{ match: "esc back", padX: 1, action: onBack }
|
|
5441
|
+
];
|
|
5442
|
+
onRegisterClickTargets(targets);
|
|
5443
|
+
}, [onRegisterClickTargets, cycleChoice, toggleMetadata, openFolder, onBack, mediaChoice, writeMetadata]);
|
|
5444
|
+
useInput3((input, key) => {
|
|
5544
5445
|
if (key.escape) {
|
|
5545
5446
|
onBack();
|
|
5546
5447
|
return;
|
|
5547
5448
|
}
|
|
5449
|
+
if (key.leftArrow) {
|
|
5450
|
+
setFocusedIndex((prev) => prev === 0 ? 2 : prev - 1);
|
|
5451
|
+
return;
|
|
5452
|
+
}
|
|
5453
|
+
if (key.rightArrow || key.tab) {
|
|
5454
|
+
setFocusedIndex((prev) => prev === 2 ? 0 : prev + 1);
|
|
5455
|
+
return;
|
|
5456
|
+
}
|
|
5457
|
+
if (key.return || input === " ") {
|
|
5458
|
+
if (focusedIndex === 0) cycleChoice();
|
|
5459
|
+
else if (focusedIndex === 1) toggleMetadata();
|
|
5460
|
+
else if (focusedIndex === 2) openFolder();
|
|
5461
|
+
return;
|
|
5462
|
+
}
|
|
5548
5463
|
if (input === "c" || input === "C") {
|
|
5464
|
+
setFocusedIndex(0);
|
|
5549
5465
|
cycleChoice();
|
|
5550
5466
|
return;
|
|
5551
5467
|
}
|
|
5552
5468
|
if (input === "m" || input === "M") {
|
|
5469
|
+
setFocusedIndex(1);
|
|
5553
5470
|
toggleMetadata();
|
|
5554
5471
|
return;
|
|
5555
5472
|
}
|
|
5556
5473
|
if (input === "o" || input === "O") {
|
|
5474
|
+
setFocusedIndex(2);
|
|
5557
5475
|
openFolder();
|
|
5558
5476
|
return;
|
|
5559
5477
|
}
|
|
@@ -5569,8 +5487,10 @@ function WatcherView({
|
|
|
5569
5487
|
] }),
|
|
5570
5488
|
/* @__PURE__ */ jsx16(ProgressBar, { indeterminate: true, width: 58, tick: pulseTick }),
|
|
5571
5489
|
/* @__PURE__ */ jsx16(Gap2, {}),
|
|
5572
|
-
/* @__PURE__ */
|
|
5573
|
-
|
|
5490
|
+
/* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", children: [
|
|
5491
|
+
/* @__PURE__ */ jsx16(Text15, { color: theme.gray, dimColor: theme.dimSecondary, children: "Auto-monitoring clipboard for profile links (Instagram, TikTok, FB, X)." }),
|
|
5492
|
+
/* @__PURE__ */ jsx16(Text15, { color: theme.gray, dimColor: theme.dimSecondary, children: "Copy any profile link in your browser: Open Nami downloads it in background." })
|
|
5493
|
+
] }),
|
|
5574
5494
|
/* @__PURE__ */ jsx16(Gap2, {}),
|
|
5575
5495
|
/* @__PURE__ */ jsx16(
|
|
5576
5496
|
Box13,
|
|
@@ -5606,15 +5526,42 @@ function WatcherView({
|
|
|
5606
5526
|
] }) : null,
|
|
5607
5527
|
/* @__PURE__ */ jsx16(Gap2, {}),
|
|
5608
5528
|
/* @__PURE__ */ jsxs13(Box13, { justifyContent: "space-between", children: [
|
|
5609
|
-
/* @__PURE__ */
|
|
5610
|
-
|
|
5611
|
-
|
|
5612
|
-
|
|
5613
|
-
|
|
5614
|
-
|
|
5615
|
-
|
|
5616
|
-
|
|
5617
|
-
|
|
5529
|
+
/* @__PURE__ */ jsx16(
|
|
5530
|
+
Box13,
|
|
5531
|
+
{
|
|
5532
|
+
borderStyle: "round",
|
|
5533
|
+
borderColor: focusedIndex === 0 ? theme.primary : theme.gray,
|
|
5534
|
+
borderDimColor: focusedIndex !== 0,
|
|
5535
|
+
paddingX: 1,
|
|
5536
|
+
children: /* @__PURE__ */ jsxs13(Text15, { color: focusedIndex === 0 ? theme.primary : theme.gray, bold: focusedIndex === 0, children: [
|
|
5537
|
+
"[c] Target: ",
|
|
5538
|
+
/* @__PURE__ */ jsx16(Text15, { color: theme.primary, bold: true, children: mediaChoice === "all" ? "EVERYTHING" : mediaChoice.toUpperCase() })
|
|
5539
|
+
] })
|
|
5540
|
+
}
|
|
5541
|
+
),
|
|
5542
|
+
/* @__PURE__ */ jsx16(
|
|
5543
|
+
Box13,
|
|
5544
|
+
{
|
|
5545
|
+
borderStyle: "round",
|
|
5546
|
+
borderColor: focusedIndex === 1 ? theme.primary : theme.gray,
|
|
5547
|
+
borderDimColor: focusedIndex !== 1,
|
|
5548
|
+
paddingX: 1,
|
|
5549
|
+
children: /* @__PURE__ */ jsxs13(Text15, { color: focusedIndex === 1 ? theme.primary : theme.gray, bold: focusedIndex === 1, children: [
|
|
5550
|
+
"[m] Sidecars: ",
|
|
5551
|
+
/* @__PURE__ */ jsx16(Text15, { color: theme.primary, bold: true, children: writeMetadata ? "ON" : "OFF" })
|
|
5552
|
+
] })
|
|
5553
|
+
}
|
|
5554
|
+
),
|
|
5555
|
+
/* @__PURE__ */ jsx16(
|
|
5556
|
+
Box13,
|
|
5557
|
+
{
|
|
5558
|
+
borderStyle: "round",
|
|
5559
|
+
borderColor: focusedIndex === 2 ? theme.primary : theme.gray,
|
|
5560
|
+
borderDimColor: focusedIndex !== 2,
|
|
5561
|
+
paddingX: 1,
|
|
5562
|
+
children: /* @__PURE__ */ jsx16(Text15, { color: focusedIndex === 2 ? theme.primary : theme.gray, bold: focusedIndex === 2, children: "[o] Open Folder" })
|
|
5563
|
+
}
|
|
5564
|
+
)
|
|
5618
5565
|
] }),
|
|
5619
5566
|
/* @__PURE__ */ jsx16(Box13, { marginTop: 1, justifyContent: "center", children: /* @__PURE__ */ jsxs13(Text15, { color: theme.gray, dimColor: theme.dimSecondary, children: [
|
|
5620
5567
|
"Session Stats: ",
|
|
@@ -5629,8 +5576,8 @@ function WatcherView({
|
|
|
5629
5576
|
}
|
|
5630
5577
|
|
|
5631
5578
|
// src/components/views/batch-view.tsx
|
|
5632
|
-
import { useState as useState8, useRef as useRef4, useCallback as
|
|
5633
|
-
import { Box as Box14, Text as Text16, useInput as
|
|
5579
|
+
import { useState as useState8, useRef as useRef4, useCallback as useCallback3, useEffect as useEffect7 } from "react";
|
|
5580
|
+
import { Box as Box14, Text as Text16, useInput as useInput4 } from "ink";
|
|
5634
5581
|
import Spinner3 from "ink-spinner";
|
|
5635
5582
|
import fs13 from "fs";
|
|
5636
5583
|
|
|
@@ -5754,11 +5701,11 @@ async function runBatchQueue(options) {
|
|
|
5754
5701
|
}
|
|
5755
5702
|
|
|
5756
5703
|
// src/components/views/batch-view.tsx
|
|
5757
|
-
import { Fragment as
|
|
5704
|
+
import { Fragment as Fragment3, jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
5758
5705
|
var PLATFORMS = ["instagram", "tiktok", "facebook", "x"];
|
|
5759
|
-
var
|
|
5760
|
-
var
|
|
5761
|
-
var
|
|
5706
|
+
var CHOICES2 = ["all", "photos", "videos", "stories", "highlights"];
|
|
5707
|
+
var DATE_PRESETS = ["all", "24h", "7d", "30d", "2024", "2023", "2022", "2021", "custom"];
|
|
5708
|
+
var LIMIT_PRESETS = [void 0, 10, 24, 50, 100, "custom"];
|
|
5762
5709
|
function BatchView({
|
|
5763
5710
|
onBack,
|
|
5764
5711
|
outputDir,
|
|
@@ -5790,22 +5737,22 @@ function BatchView({
|
|
|
5790
5737
|
const [isCooldown, setIsCooldown] = useState8(false);
|
|
5791
5738
|
const [result, setResult] = useState8(null);
|
|
5792
5739
|
const abortControllerRef = useRef4(null);
|
|
5793
|
-
const cyclePlatform =
|
|
5740
|
+
const cyclePlatform = useCallback3(() => {
|
|
5794
5741
|
setDefaultPlatform((prev) => {
|
|
5795
5742
|
const idx = PLATFORMS.indexOf(prev);
|
|
5796
5743
|
return PLATFORMS[(idx + 1) % PLATFORMS.length];
|
|
5797
5744
|
});
|
|
5798
5745
|
}, []);
|
|
5799
|
-
const cycleChoice =
|
|
5746
|
+
const cycleChoice = useCallback3(() => {
|
|
5800
5747
|
setChoice((prev) => {
|
|
5801
|
-
const idx =
|
|
5802
|
-
return
|
|
5748
|
+
const idx = CHOICES2.indexOf(prev);
|
|
5749
|
+
return CHOICES2[(idx + 1) % CHOICES2.length];
|
|
5803
5750
|
});
|
|
5804
5751
|
}, []);
|
|
5805
|
-
const cycleLimit =
|
|
5806
|
-
const curIdx =
|
|
5807
|
-
const nextIdx = (curIdx + 1) %
|
|
5808
|
-
const nextVal =
|
|
5752
|
+
const cycleLimit = useCallback3(() => {
|
|
5753
|
+
const curIdx = LIMIT_PRESETS.findIndex((p) => p === limit);
|
|
5754
|
+
const nextIdx = (curIdx + 1) % LIMIT_PRESETS.length;
|
|
5755
|
+
const nextVal = LIMIT_PRESETS[nextIdx];
|
|
5809
5756
|
if (nextVal === "custom") {
|
|
5810
5757
|
setCustomLimitText(limit ? String(limit) : "24");
|
|
5811
5758
|
setFocusedControl("custom-limit");
|
|
@@ -5813,10 +5760,10 @@ function BatchView({
|
|
|
5813
5760
|
setLimit(nextVal);
|
|
5814
5761
|
}
|
|
5815
5762
|
}, [limit]);
|
|
5816
|
-
const cycleDate =
|
|
5817
|
-
const curIdx =
|
|
5818
|
-
const nextIdx = (curIdx + 1) %
|
|
5819
|
-
const nextVal =
|
|
5763
|
+
const cycleDate = useCallback3(() => {
|
|
5764
|
+
const curIdx = DATE_PRESETS.indexOf(dateFilter);
|
|
5765
|
+
const nextIdx = (curIdx + 1) % DATE_PRESETS.length;
|
|
5766
|
+
const nextVal = DATE_PRESETS[nextIdx];
|
|
5820
5767
|
if (nextVal === "custom") {
|
|
5821
5768
|
setCustomDateText(dateFilter !== "all" ? dateFilter : "2024");
|
|
5822
5769
|
setFocusedControl("custom-date");
|
|
@@ -5824,13 +5771,13 @@ function BatchView({
|
|
|
5824
5771
|
setDateFilter(nextVal);
|
|
5825
5772
|
}
|
|
5826
5773
|
}, [dateFilter]);
|
|
5827
|
-
const toggleMetadata =
|
|
5774
|
+
const toggleMetadata = useCallback3(() => {
|
|
5828
5775
|
setWriteMetadata((prev) => !prev);
|
|
5829
5776
|
}, []);
|
|
5830
|
-
const toggleResume =
|
|
5777
|
+
const toggleResume = useCallback3(() => {
|
|
5831
5778
|
setResume((prev) => !prev);
|
|
5832
5779
|
}, []);
|
|
5833
|
-
const startQueue =
|
|
5780
|
+
const startQueue = useCallback3(async () => {
|
|
5834
5781
|
setErrorMessage(null);
|
|
5835
5782
|
let lines = [];
|
|
5836
5783
|
if (inputField === "file") {
|
|
@@ -5917,7 +5864,7 @@ function BatchView({
|
|
|
5917
5864
|
setPhase("input");
|
|
5918
5865
|
}
|
|
5919
5866
|
}, [inputField, filePath, rawText, choice, defaultPlatform, outputDir, dateFilter, limit, resume, writeMetadata]);
|
|
5920
|
-
|
|
5867
|
+
useInput4((input, key) => {
|
|
5921
5868
|
if (key.ctrl && (input === "c" || input === "C")) {
|
|
5922
5869
|
return;
|
|
5923
5870
|
}
|
|
@@ -6461,7 +6408,7 @@ function BatchView({
|
|
|
6461
6408
|
}
|
|
6462
6409
|
) }),
|
|
6463
6410
|
/* @__PURE__ */ jsx17(Text16, { color: theme.gray, dimColor: theme.dimSecondary, children: "\u21B5 confirm \xB7 esc cancel" })
|
|
6464
|
-
] }) : /* @__PURE__ */ jsxs14(
|
|
6411
|
+
] }) : /* @__PURE__ */ jsxs14(Fragment3, { children: [
|
|
6465
6412
|
/* @__PURE__ */ jsxs14(Box14, { justifyContent: "space-between", width: "100%", children: [
|
|
6466
6413
|
/* @__PURE__ */ jsxs14(Box14, { width: colWidth, children: [
|
|
6467
6414
|
/* @__PURE__ */ jsx17(Text16, { color: theme.gray, dimColor: theme.dimSecondary, children: "[p] Platform: " }),
|
|
@@ -6673,7 +6620,7 @@ function frameRowSpan(row) {
|
|
|
6673
6620
|
}
|
|
6674
6621
|
|
|
6675
6622
|
// src/app.tsx
|
|
6676
|
-
import { Fragment as
|
|
6623
|
+
import { Fragment as Fragment4, jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
6677
6624
|
var TAGLINE = "grab any profile. paste. download. done.";
|
|
6678
6625
|
var DOWNLOAD_BUTTON = "download";
|
|
6679
6626
|
var Gap = ({ lines = 1 }) => /* @__PURE__ */ jsx18(Box15, { flexDirection: "column", flexShrink: 0, children: Array.from({ length: lines }, (_, i) => /* @__PURE__ */ jsx18(Text17, { children: " " }, i)) });
|
|
@@ -6752,7 +6699,7 @@ function App({
|
|
|
6752
6699
|
version = "1.0.0"
|
|
6753
6700
|
}) {
|
|
6754
6701
|
const [themeMode, setThemeMode] = useState9(initialThemeMode);
|
|
6755
|
-
const cycleTheme =
|
|
6702
|
+
const cycleTheme = useCallback4(() => {
|
|
6756
6703
|
setThemeMode(nextThemeMode);
|
|
6757
6704
|
}, []);
|
|
6758
6705
|
return /* @__PURE__ */ jsx18(ThemeProvider, { mode: themeMode, children: /* @__PURE__ */ jsx18(
|
|
@@ -6793,6 +6740,7 @@ function InnerApp({
|
|
|
6793
6740
|
const [clipboardUrl, setClipboardUrl] = useState9(void 0);
|
|
6794
6741
|
const [settingsFocus, setSettingsFocus] = useState9("cookies");
|
|
6795
6742
|
const [batchClickTargets, setBatchClickTargets] = useState9([]);
|
|
6743
|
+
const [watcherClickTargets, setWatcherClickTargets] = useState9([]);
|
|
6796
6744
|
const columns = stdout?.columns && stdout.columns > 0 ? stdout.columns : 80;
|
|
6797
6745
|
const boxWidth = Math.max(14, Math.min(64, columns - 6));
|
|
6798
6746
|
const contentWidth = Math.max(10, Math.min(columns - 4, 78));
|
|
@@ -6829,7 +6777,7 @@ function InnerApp({
|
|
|
6829
6777
|
}
|
|
6830
6778
|
};
|
|
6831
6779
|
}, []);
|
|
6832
|
-
const resetToInput =
|
|
6780
|
+
const resetToInput = useCallback4(() => {
|
|
6833
6781
|
if (probingTimeoutRef.current) {
|
|
6834
6782
|
clearTimeout(probingTimeoutRef.current);
|
|
6835
6783
|
probingTimeoutRef.current = null;
|
|
@@ -6839,7 +6787,7 @@ function InnerApp({
|
|
|
6839
6787
|
setUrlInput("");
|
|
6840
6788
|
setPhase({ name: "input" });
|
|
6841
6789
|
}, []);
|
|
6842
|
-
const handleModeSelect =
|
|
6790
|
+
const handleModeSelect = useCallback4(async (choiceOrOptions, profile) => {
|
|
6843
6791
|
abortControllerRef.current?.abort();
|
|
6844
6792
|
const controller = new AbortController();
|
|
6845
6793
|
abortControllerRef.current = controller;
|
|
@@ -6889,7 +6837,7 @@ function InnerApp({
|
|
|
6889
6837
|
});
|
|
6890
6838
|
}
|
|
6891
6839
|
}, [outputDir, since, until, effectiveLimit, resume, effectiveWriteMetadata]);
|
|
6892
|
-
const handlePlatformSelect =
|
|
6840
|
+
const handlePlatformSelect = useCallback4((platform, username, rawInput) => {
|
|
6893
6841
|
const canonical = buildCanonicalProfile(platform, username, rawInput);
|
|
6894
6842
|
setPhase({ name: "probing", target: canonical.cleanUrl, status: "probing profile\u2026" });
|
|
6895
6843
|
if (probingTimeoutRef.current) clearTimeout(probingTimeoutRef.current);
|
|
@@ -6902,7 +6850,7 @@ function InnerApp({
|
|
|
6902
6850
|
}
|
|
6903
6851
|
}, 450);
|
|
6904
6852
|
}, [initialChoice, handleModeSelect]);
|
|
6905
|
-
const handleInputSubmit =
|
|
6853
|
+
const handleInputSubmit = useCallback4((input) => {
|
|
6906
6854
|
const trimmed = input.trim();
|
|
6907
6855
|
if (!trimmed) return;
|
|
6908
6856
|
const parsed = parseProfileInput(trimmed);
|
|
@@ -6928,7 +6876,7 @@ function InnerApp({
|
|
|
6928
6876
|
warning: "paste a full profile url (e.g. instagram.com/profile) or @profile"
|
|
6929
6877
|
});
|
|
6930
6878
|
}, [initialChoice, handleModeSelect]);
|
|
6931
|
-
|
|
6879
|
+
useInput5((input, key) => {
|
|
6932
6880
|
if (key.ctrl && input === "t") {
|
|
6933
6881
|
cycleTheme();
|
|
6934
6882
|
return;
|
|
@@ -6944,8 +6892,11 @@ function InnerApp({
|
|
|
6944
6892
|
if (key.ctrl && (input === "w" || input === "W")) {
|
|
6945
6893
|
if (phase.name === "watcher") {
|
|
6946
6894
|
setPhase({ name: "input" });
|
|
6947
|
-
|
|
6895
|
+
return;
|
|
6896
|
+
}
|
|
6897
|
+
if (phase.name === "input" && urlInput.length === 0) {
|
|
6948
6898
|
setPhase({ name: "watcher" });
|
|
6899
|
+
return;
|
|
6949
6900
|
}
|
|
6950
6901
|
return;
|
|
6951
6902
|
}
|
|
@@ -7063,6 +7014,9 @@ function InnerApp({
|
|
|
7063
7014
|
if (phase.name === "batch") {
|
|
7064
7015
|
targets.push(...batchClickTargets);
|
|
7065
7016
|
}
|
|
7017
|
+
if (phase.name === "watcher") {
|
|
7018
|
+
targets.push(...watcherClickTargets);
|
|
7019
|
+
}
|
|
7066
7020
|
for (const [key, label] of hints) {
|
|
7067
7021
|
const action = hintAction(key);
|
|
7068
7022
|
if (action) targets.push({ match: `${key} ${label}`, action });
|
|
@@ -7083,7 +7037,8 @@ function InnerApp({
|
|
|
7083
7037
|
handlePlatformSelect,
|
|
7084
7038
|
handleModeSelect,
|
|
7085
7039
|
resetToInput,
|
|
7086
|
-
batchClickTargets
|
|
7040
|
+
batchClickTargets,
|
|
7041
|
+
watcherClickTargets
|
|
7087
7042
|
]);
|
|
7088
7043
|
useMouseClick(
|
|
7089
7044
|
(x, y) => {
|
|
@@ -7210,7 +7165,8 @@ function InnerApp({
|
|
|
7210
7165
|
theme,
|
|
7211
7166
|
gapComponent: Gap,
|
|
7212
7167
|
defaultChoice: initialChoice,
|
|
7213
|
-
defaultWriteMetadata: effectiveWriteMetadata
|
|
7168
|
+
defaultWriteMetadata: effectiveWriteMetadata,
|
|
7169
|
+
onRegisterClickTargets: setWatcherClickTargets
|
|
7214
7170
|
}
|
|
7215
7171
|
),
|
|
7216
7172
|
phase.name === "batch" && /* @__PURE__ */ jsx18(
|
|
@@ -7228,7 +7184,7 @@ function InnerApp({
|
|
|
7228
7184
|
onRegisterClickTargets: setBatchClickTargets
|
|
7229
7185
|
}
|
|
7230
7186
|
),
|
|
7231
|
-
hints.length > 0 ? /* @__PURE__ */ jsxs15(
|
|
7187
|
+
hints.length > 0 ? /* @__PURE__ */ jsxs15(Fragment4, { children: [
|
|
7232
7188
|
/* @__PURE__ */ jsx18(Gap, { lines: 2 }),
|
|
7233
7189
|
/* @__PURE__ */ jsx18(
|
|
7234
7190
|
Shortcuts,
|