birdclaw 0.8.5 → 0.9.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/CHANGELOG.md +24 -0
- package/README.md +22 -2
- package/dist/cli/birdclaw.js +1228 -186
- package/dist/client/assets/AvatarChip-C8zELEVt.js +1 -0
- package/dist/client/assets/ProfilePreview-CsiLpFrb.js +1 -0
- package/dist/client/assets/SavedTimelineView-DE4CXK-h.js +1 -0
- package/dist/client/assets/SmartTimestamp-BypN4KPq.js +1 -0
- package/dist/client/assets/TimelineRouteFrame-D6djyMAT.js +1 -0
- package/dist/client/assets/blocks-h27nF3TL.js +1 -0
- package/dist/client/assets/{bookmarks-LbYOsoKf.js → bookmarks-Cprrli-V.js} +1 -1
- package/dist/client/assets/circle-check-BCK_qvXt.js +1 -0
- package/dist/client/assets/client-stream-contracts-D1QUdWfh.js +5 -0
- package/dist/client/assets/createLucideIcon-CMLcIxOz.js +1 -0
- package/dist/client/assets/data-sources-Beb3JZkl.js +1 -0
- package/dist/client/assets/discuss-ciwVz7Fo.js +1 -0
- package/dist/client/assets/dms-BZ3GUPey.js +1 -0
- package/dist/client/assets/inbox-Dajdut79.js +1 -0
- package/dist/client/assets/index-a1ZAcWSa.js +31 -0
- package/dist/client/assets/likes-CxZZqiZC.js +1 -0
- package/dist/client/assets/links-CsWS9uKL.js +1 -0
- package/dist/client/assets/mapbox-dx7h2mOm.js +2 -0
- package/dist/client/assets/{mapbox-gl-DYNcLcll.js → mapbox-gl-WUhsQcSS.js} +1 -1
- package/dist/client/assets/{mentions-BoVVAIT7.js → mentions-C3JYXV2K.js} +1 -1
- package/dist/client/assets/network-map-D4XA7TTO.js +2 -0
- package/dist/client/assets/profile-analyze-QAznTMjZ.js +1 -0
- package/dist/client/assets/{profile-hydration-client-YEtJsNTv.js → profile-hydration-client-BQyC5--e.js} +1 -1
- package/dist/client/assets/profiles._handle-qntfbCE1.js +1 -0
- package/dist/client/assets/query-client-DZ5C7UNo.js +17 -0
- package/dist/client/assets/rate-limits-eHs_5dDB.js +1 -0
- package/dist/client/assets/react-BwGzW7mM.js +1 -0
- package/dist/client/assets/react-dom-DEMAB80t.js +1 -0
- package/dist/client/assets/{repeat-2-xCwHM9hD.js → repeat-2-CQ0lek01.js} +1 -1
- package/dist/client/assets/rolldown-runtime-B-9mzPXz.js +1 -0
- package/dist/client/assets/{routes-CiLuYpZr.js → routes-CeIv5bkV.js} +1 -1
- package/dist/client/assets/schemas-CntsNLmN.js +64 -0
- package/dist/client/assets/search-C_LqodNa.js +1 -0
- package/dist/client/assets/{sparkles-CQVlvHsZ.js → sparkles-Gx_BHkDX.js} +1 -1
- package/dist/client/assets/styles-DTMajAmk.css +2 -0
- package/dist/client/assets/today-DxppbQGF.js +1 -0
- package/dist/client/assets/{triangle-alert-CBL7s2pf.js → triangle-alert-DJPCW6jQ.js} +1 -1
- package/dist/client/assets/useTimelineRouteData-CWvBmHLE.js +1 -0
- package/dist/client/assets/{users-CHbKlqUr.js → users-DI3w8Mol.js} +1 -1
- package/dist/server/assets/{AvatarChip-zUDAEmjL.js → AvatarChip-DWag3IzT.js} +1 -1
- package/dist/server/assets/{FeedState-ntW0Q2GB.js → FeedState-CwzcvP-p.js} +1 -1
- package/dist/server/assets/{ProfileAnalysisStream-L7bs6IHH.js → ProfileAnalysisStream-CLjrYzEx.js} +2 -2
- package/dist/server/assets/{ProfilePreview-Cg-AOHBE.js → ProfilePreview-Bq-DSUM2.js} +2 -2
- package/dist/server/assets/{SavedTimelineView-BtCq1dHk.js → SavedTimelineView-Bk9nfnb-.js} +2 -2
- package/dist/server/assets/{SmartTimestamp-DfwE1NGf.js → SmartTimestamp-C06w_f9J.js} +1 -1
- package/dist/server/assets/SyncNowButton-CKuXKYcd.js +259 -0
- package/dist/server/assets/{TimelineRouteFrame-CjMIh63G.js → TimelineRouteFrame-Bg3e7X_N.js} +5 -3
- package/dist/server/assets/{TweetRichText-DDywESRF.js → TweetRichText-wzUAtbPS.js} +2 -2
- package/dist/server/assets/{_tanstack-start-manifest_v-aLWUdbAc.js → _tanstack-start-manifest_v-CjYYXQ8Z.js} +35 -35
- package/dist/server/assets/{blocks-DSgQghqP.js → blocks-CaP_u3mY.js} +3 -3
- package/dist/server/assets/{blocks-C1mgGTB3.js → blocks-DKy4yTF-.js} +3 -3
- package/dist/server/assets/{bookmarks-D_YkmCK3.js → bookmarks-CPFq3JVX.js} +1 -1
- package/dist/server/assets/{client-stream-contracts-Bq6kMmhh.js → client-stream-contracts-gtXEreFY.js} +72 -8
- package/dist/server/assets/{data-sources-BnA1Q94p.js → data-sources-DWwmQqcO.js} +1 -1
- package/dist/server/assets/{discuss-DAq6ehL9.js → discuss-BB8wFy4L.js} +3 -3
- package/dist/server/assets/{discuss-C1QMBBSk.js → discuss-CVGB4_I0.js} +3 -3
- package/dist/server/assets/{dms-DAyQrVM2.js → dms-7NzdyQZQ.js} +6 -6
- package/dist/server/assets/{dms-BuLj4bp8.js → dms-vbEumuuO.js} +4 -4
- package/dist/server/assets/{empty-plugin-adapters-DzrEkdBF.js → empty-plugin-adapters-D9UWiqvJ.js} +1 -1
- package/dist/server/assets/{inbox-CkGOaW1q.js → inbox-CBeZctFd.js} +2 -2
- package/dist/server/assets/{inbox-DpWd1EzC.js → inbox-UpHhXODd.js} +4 -4
- package/dist/server/assets/{likes-BMm2JWYI.js → likes-CDAjYyTm.js} +1 -1
- package/dist/server/assets/{links-dqXb35YM.js → links-DU-TIHtg.js} +6 -6
- package/dist/server/assets/{links-Da4tjWtI.js → links-sQ3q2jvO.js} +6 -6
- package/dist/server/assets/{mentions-CEyEcOFw.js → mentions-DdndGSRw.js} +1 -1
- package/dist/server/assets/{network-map-D3CzRcC4.js → network-map-B9iOapuB.js} +2 -2
- package/dist/server/assets/{network-map-D5DoLOwR.js → network-map-CcOz-T9O.js} +2 -2
- package/dist/server/assets/{profile-analyze-DH1TSBkT.js → profile-analyze-BmDeTif5.js} +1 -1
- package/dist/server/assets/{profile-analyze-CGCj4VFd.js → profile-analyze-CUfXmXEH.js} +3 -3
- package/dist/server/assets/{profiles._handle-B5V-huoo.js → profiles._handle-8snagiR1.js} +4 -4
- package/dist/server/assets/{profiles._handle-CJ6rgzt8.js → profiles._handle-BAqnghwo.js} +5 -5
- package/dist/server/assets/{rate-limits-VAr2qzYD.js → rate-limits-BY2-aQPT.js} +1 -1
- package/dist/server/assets/{router-C4cz9ypd.js → router-DP7iZD-q.js} +421 -125
- package/dist/server/assets/{routes-B9aikOdB.js → routes-D9226vKz.js} +1 -1
- package/dist/server/assets/start-5Z2QO8AU.js +4 -0
- package/dist/server/assets/{today-JkxZXdBt.js → today-BmvIMJzI.js} +3 -3
- package/dist/server/assets/{today-B_TA16QG.js → today-DKWphGrC.js} +112 -57
- package/dist/server/assets/{ui-qbmcMSSX.js → ui-rDHeS-cc.js} +2 -1
- package/dist/server/assets/{useTimelineRouteData-BLXvMGb2.js → useTimelineRouteData-BmDbGvQ8.js} +7 -7
- package/dist/server/server.js +50 -3413
- package/package.json +13 -13
- package/dist/client/assets/AvatarChip-DLoqM5xD.js +0 -1
- package/dist/client/assets/ProfilePreview-DQX6_xc3.js +0 -1
- package/dist/client/assets/SavedTimelineView-BhSiVyR1.js +0 -1
- package/dist/client/assets/SmartTimestamp-BR0-9se2.js +0 -1
- package/dist/client/assets/TimelineRouteFrame-9NDLnXzH.js +0 -1
- package/dist/client/assets/blocks-CFp_njvG.js +0 -1
- package/dist/client/assets/chunk-C0phanGV.js +0 -1
- package/dist/client/assets/circle-check-C_Vq3ElD.js +0 -1
- package/dist/client/assets/client-stream-contracts-sR4xMQxY.js +0 -5
- package/dist/client/assets/createLucideIcon-JV8isFFR.js +0 -1
- package/dist/client/assets/data-sources-euTr6T_L.js +0 -1
- package/dist/client/assets/discuss-BWKu_p7B.js +0 -1
- package/dist/client/assets/dms-SLXMtC4v.js +0 -1
- package/dist/client/assets/inbox-BybSI5Vf.js +0 -1
- package/dist/client/assets/index-DZVisyna.js +0 -31
- package/dist/client/assets/likes-dyh9p8y_.js +0 -1
- package/dist/client/assets/links-CIwqK_dX.js +0 -1
- package/dist/client/assets/mapbox-B4zqX7r0.js +0 -2
- package/dist/client/assets/network-map-zRysIY_b.js +0 -2
- package/dist/client/assets/profile-analyze-C_yDeX6-.js +0 -1
- package/dist/client/assets/profiles._handle-DdIVPqU-.js +0 -1
- package/dist/client/assets/query-client-fYu2rzRC.js +0 -17
- package/dist/client/assets/rate-limits-BWPmPOSh.js +0 -1
- package/dist/client/assets/react-dom-DHl6Ug7F.js +0 -1
- package/dist/client/assets/react-nBylq1U5.js +0 -1
- package/dist/client/assets/schemas-I9r6F6ya.js +0 -64
- package/dist/client/assets/search-Dq5kYsxA.js +0 -1
- package/dist/client/assets/styles-B8s3tt3r.css +0 -2
- package/dist/client/assets/today-BoO64YoY.js +0 -1
- package/dist/client/assets/useTimelineRouteData-BaO3Rna1.js +0 -1
- package/dist/server/assets/SyncNowButton-BOn_IBXS.js +0 -76
- package/dist/server/assets/start-FaDOTmto.js +0 -4
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import { Yt as selectFieldClass, m as cx } from "./ui-rDHeS-cc.js";
|
|
2
|
+
import { c as postSync } from "./query-client-BdauHBgd.js";
|
|
3
|
+
import { n as setStoredAccountId, r as useSelectedAccountId, t as defaultAccountId } from "./account-selection-CTdFGWRk.js";
|
|
4
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
5
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { RefreshCw } from "lucide-react";
|
|
7
|
+
//#region src/components/SyncNowButton.tsx
|
|
8
|
+
var AUTO_SYNC_INTERVALS = [
|
|
9
|
+
{
|
|
10
|
+
label: "5m",
|
|
11
|
+
value: 5 * 6e4
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
label: "10m",
|
|
15
|
+
value: 10 * 6e4
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
label: "15m",
|
|
19
|
+
value: 15 * 6e4
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
label: "30m",
|
|
23
|
+
value: 30 * 6e4
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
label: "1h",
|
|
27
|
+
value: 60 * 6e4
|
|
28
|
+
}
|
|
29
|
+
];
|
|
30
|
+
var DEFAULT_AUTO_SYNC_INTERVAL_MS = 10 * 6e4;
|
|
31
|
+
var MAX_AUTO_SYNC_BACKOFF_MS = 60 * 6e4;
|
|
32
|
+
function autoSyncStorageKey(kind, accountId) {
|
|
33
|
+
return `birdclaw:auto-sync:${kind}:${accountId ?? "default"}`;
|
|
34
|
+
}
|
|
35
|
+
function validAutoSyncInterval(value) {
|
|
36
|
+
return AUTO_SYNC_INTERVALS.some((option) => option.value === value);
|
|
37
|
+
}
|
|
38
|
+
function readAutoSyncSettings(key) {
|
|
39
|
+
try {
|
|
40
|
+
const value = JSON.parse(window.localStorage.getItem(key) ?? "null");
|
|
41
|
+
return {
|
|
42
|
+
enabled: value?.enabled === true,
|
|
43
|
+
intervalMs: validAutoSyncInterval(value?.intervalMs) ? value.intervalMs : DEFAULT_AUTO_SYNC_INTERVAL_MS
|
|
44
|
+
};
|
|
45
|
+
} catch {
|
|
46
|
+
return {
|
|
47
|
+
enabled: false,
|
|
48
|
+
intervalMs: DEFAULT_AUTO_SYNC_INTERVAL_MS
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function SyncNowButton({ kind, label, accounts, onSynced, allowAutoSync = false, autoSyncBlocked = false, showAccountPicker = false, syncOptions }) {
|
|
53
|
+
const [syncing, setSyncing] = useState(false);
|
|
54
|
+
const [message, setMessage] = useState(null);
|
|
55
|
+
const [error, setError] = useState(null);
|
|
56
|
+
const syncingRef = useRef(false);
|
|
57
|
+
const onSyncedRef = useRef(onSynced);
|
|
58
|
+
const [autoSyncing, setAutoSyncing] = useState(false);
|
|
59
|
+
const [autoSyncError, setAutoSyncError] = useState(null);
|
|
60
|
+
const [autoFailureCount, setAutoFailureCount] = useState(0);
|
|
61
|
+
const [autoCycle, setAutoCycle] = useState(0);
|
|
62
|
+
const [lastAutoSyncedAt, setLastAutoSyncedAt] = useState(null);
|
|
63
|
+
const [nextAutoSyncAt, setNextAutoSyncAt] = useState(null);
|
|
64
|
+
const accountList = accounts ?? [];
|
|
65
|
+
const globalAccountId = useSelectedAccountId(accounts);
|
|
66
|
+
const defaultAccountId$1 = useMemo(() => defaultAccountId(accounts), [accounts]);
|
|
67
|
+
const accountId = globalAccountId ?? defaultAccountId$1;
|
|
68
|
+
const autoSyncKey = autoSyncStorageKey(kind, accountId);
|
|
69
|
+
const autoSyncKeyRef = useRef(autoSyncKey);
|
|
70
|
+
autoSyncKeyRef.current = autoSyncKey;
|
|
71
|
+
const [autoSettings, setAutoSettings] = useState({
|
|
72
|
+
key: "",
|
|
73
|
+
enabled: false,
|
|
74
|
+
intervalMs: DEFAULT_AUTO_SYNC_INTERVAL_MS
|
|
75
|
+
});
|
|
76
|
+
const autoSettingsReady = autoSettings.key === autoSyncKey;
|
|
77
|
+
const accountAwareSync = kind !== "dms";
|
|
78
|
+
const waitingForAccount = accountAwareSync && accounts === void 0 && (showAccountPicker || kind !== "timeline");
|
|
79
|
+
const birdOnlyWrongAccount = !accountAwareSync && accountId !== void 0 && defaultAccountId$1 !== void 0 && accountId !== defaultAccountId$1;
|
|
80
|
+
const disabled = syncing || waitingForAccount || birdOnlyWrongAccount;
|
|
81
|
+
const statusMessage = birdOnlyWrongAccount ? "Switch to default to sync" : waitingForAccount ? "Loading account" : error ?? message ?? "";
|
|
82
|
+
const autoStatusMessage = autoSyncError ? `Auto sync failed: ${autoSyncError}` : autoSyncing ? "Auto syncing..." : lastAutoSyncedAt ? `Last auto sync ${new Date(lastAutoSyncedAt).toLocaleTimeString()}` : nextAutoSyncAt ? `Next sync ${new Date(nextAutoSyncAt).toLocaleTimeString()}` : autoSettings.enabled ? "Auto sync waiting" : "Auto sync off";
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
onSyncedRef.current = onSynced;
|
|
85
|
+
}, [onSynced]);
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
setAutoSettings({
|
|
88
|
+
key: autoSyncKey,
|
|
89
|
+
...readAutoSyncSettings(autoSyncKey)
|
|
90
|
+
});
|
|
91
|
+
setAutoSyncError(null);
|
|
92
|
+
setAutoSyncing(false);
|
|
93
|
+
setAutoFailureCount(0);
|
|
94
|
+
setLastAutoSyncedAt(null);
|
|
95
|
+
setNextAutoSyncAt(null);
|
|
96
|
+
setAutoCycle((current) => current + 1);
|
|
97
|
+
}, [autoSyncKey]);
|
|
98
|
+
function selectAccount(accountId) {
|
|
99
|
+
setStoredAccountId(accountId);
|
|
100
|
+
}
|
|
101
|
+
const syncNow = useCallback(async (source) => {
|
|
102
|
+
if (syncingRef.current || waitingForAccount || birdOnlyWrongAccount || source === "auto" && autoSyncBlocked) return false;
|
|
103
|
+
const launchedAutoSyncKey = source === "auto" ? autoSyncKeyRef.current : null;
|
|
104
|
+
syncingRef.current = true;
|
|
105
|
+
setSyncing(true);
|
|
106
|
+
if (source === "auto") {
|
|
107
|
+
setAutoSyncing(true);
|
|
108
|
+
setAutoSyncError(null);
|
|
109
|
+
} else {
|
|
110
|
+
setError(null);
|
|
111
|
+
setMessage(null);
|
|
112
|
+
}
|
|
113
|
+
try {
|
|
114
|
+
const data = await postSync(kind, accountAwareSync ? accountId : void 0, syncOptions);
|
|
115
|
+
if (!data.ok) throw new Error(data.summary);
|
|
116
|
+
if (launchedAutoSyncKey !== null && autoSyncKeyRef.current !== launchedAutoSyncKey) return false;
|
|
117
|
+
if (source === "auto") {
|
|
118
|
+
setLastAutoSyncedAt(Date.now());
|
|
119
|
+
setAutoFailureCount(0);
|
|
120
|
+
} else setMessage(data.summary);
|
|
121
|
+
onSyncedRef.current(data);
|
|
122
|
+
return true;
|
|
123
|
+
} catch (syncError) {
|
|
124
|
+
if (launchedAutoSyncKey !== null && autoSyncKeyRef.current !== launchedAutoSyncKey) return false;
|
|
125
|
+
const syncMessage = syncError instanceof Error ? syncError.message : "Sync failed";
|
|
126
|
+
if (source === "auto") {
|
|
127
|
+
setAutoSyncError(syncMessage);
|
|
128
|
+
setAutoFailureCount((current) => current + 1);
|
|
129
|
+
} else setError(syncMessage);
|
|
130
|
+
return false;
|
|
131
|
+
} finally {
|
|
132
|
+
syncingRef.current = false;
|
|
133
|
+
setSyncing(false);
|
|
134
|
+
if (source === "auto") setAutoSyncing(false);
|
|
135
|
+
}
|
|
136
|
+
}, [
|
|
137
|
+
accountAwareSync,
|
|
138
|
+
accountId,
|
|
139
|
+
autoSyncBlocked,
|
|
140
|
+
birdOnlyWrongAccount,
|
|
141
|
+
kind,
|
|
142
|
+
syncOptions,
|
|
143
|
+
waitingForAccount
|
|
144
|
+
]);
|
|
145
|
+
useEffect(() => {
|
|
146
|
+
if (!allowAutoSync || !autoSettingsReady || !autoSettings.enabled || autoSyncBlocked || waitingForAccount || birdOnlyWrongAccount) {
|
|
147
|
+
setNextAutoSyncAt(null);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
const delayMs = Math.min(autoSettings.intervalMs * 2 ** autoFailureCount, MAX_AUTO_SYNC_BACKOFF_MS);
|
|
151
|
+
setNextAutoSyncAt(Date.now() + delayMs);
|
|
152
|
+
const timer = window.setTimeout(() => {
|
|
153
|
+
if (document.visibilityState === "hidden" || syncingRef.current) {
|
|
154
|
+
setAutoCycle((current) => current + 1);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
syncNow("auto").finally(() => {
|
|
158
|
+
setAutoCycle((current) => current + 1);
|
|
159
|
+
});
|
|
160
|
+
}, delayMs);
|
|
161
|
+
return () => window.clearTimeout(timer);
|
|
162
|
+
}, [
|
|
163
|
+
allowAutoSync,
|
|
164
|
+
autoCycle,
|
|
165
|
+
autoFailureCount,
|
|
166
|
+
autoSettings.enabled,
|
|
167
|
+
autoSettings.intervalMs,
|
|
168
|
+
autoSettingsReady,
|
|
169
|
+
autoSyncBlocked,
|
|
170
|
+
birdOnlyWrongAccount,
|
|
171
|
+
syncNow,
|
|
172
|
+
waitingForAccount
|
|
173
|
+
]);
|
|
174
|
+
function updateAutoSettings(next) {
|
|
175
|
+
setAutoSettings({
|
|
176
|
+
key: autoSyncKey,
|
|
177
|
+
...next
|
|
178
|
+
});
|
|
179
|
+
window.localStorage.setItem(autoSyncKey, JSON.stringify({
|
|
180
|
+
enabled: next.enabled,
|
|
181
|
+
intervalMs: next.intervalMs
|
|
182
|
+
}));
|
|
183
|
+
setAutoSyncError(null);
|
|
184
|
+
setAutoFailureCount(0);
|
|
185
|
+
setLastAutoSyncedAt(null);
|
|
186
|
+
setAutoCycle((current) => current + 1);
|
|
187
|
+
}
|
|
188
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
189
|
+
className: cx("flex shrink-0 flex-wrap items-center justify-end gap-2", allowAutoSync && "w-full lg:w-auto"),
|
|
190
|
+
children: [
|
|
191
|
+
showAccountPicker && accountAwareSync && accountList.length > 1 ? /* @__PURE__ */ jsx("select", {
|
|
192
|
+
"aria-label": "Sync account",
|
|
193
|
+
className: cx(selectFieldClass, "h-9 w-[132px]!"),
|
|
194
|
+
disabled: syncing,
|
|
195
|
+
onChange: (event) => selectAccount(event.target.value),
|
|
196
|
+
value: accountId ?? "",
|
|
197
|
+
children: accountList.map((account) => /* @__PURE__ */ jsx("option", {
|
|
198
|
+
value: account.id,
|
|
199
|
+
children: account.handle
|
|
200
|
+
}, account.id))
|
|
201
|
+
}) : null,
|
|
202
|
+
/* @__PURE__ */ jsxs("button", {
|
|
203
|
+
type: "button",
|
|
204
|
+
className: cx("inline-flex h-9 shrink-0 items-center gap-1.5 rounded-full border border-[var(--line)] bg-[var(--bg)] px-3 text-[13px] font-semibold text-[var(--ink)] transition-[background,border-color,color,transform] duration-150 hover:border-[color:color-mix(in_srgb,var(--accent)_45%,var(--line))] hover:bg-[var(--accent-soft)] hover:text-[var(--accent)] active:scale-[0.98] disabled:opacity-65", syncing && "text-[var(--ink-soft)]", birdOnlyWrongAccount ? "disabled:cursor-not-allowed" : "disabled:cursor-wait"),
|
|
205
|
+
"aria-label": birdOnlyWrongAccount ? `${label}: default account only` : syncing ? `${label}: syncing` : label,
|
|
206
|
+
disabled,
|
|
207
|
+
onClick: () => void syncNow("manual"),
|
|
208
|
+
children: [/* @__PURE__ */ jsx(RefreshCw, {
|
|
209
|
+
className: cx("size-4", syncing && "animate-spin"),
|
|
210
|
+
strokeWidth: 2
|
|
211
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
212
|
+
className: "hidden sm:inline",
|
|
213
|
+
children: syncing ? "Syncing..." : label
|
|
214
|
+
})]
|
|
215
|
+
}),
|
|
216
|
+
/* @__PURE__ */ jsx("span", {
|
|
217
|
+
className: cx("hidden max-w-[190px] truncate text-[12px] sm:inline", error ? "text-[var(--alert)]" : "text-[var(--ink-soft)]"),
|
|
218
|
+
role: "status",
|
|
219
|
+
children: statusMessage
|
|
220
|
+
}),
|
|
221
|
+
allowAutoSync && autoSettingsReady ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
222
|
+
/* @__PURE__ */ jsxs("label", {
|
|
223
|
+
className: "inline-flex h-9 items-center gap-1.5 rounded-full border border-[var(--line)] bg-[var(--bg)] px-2.5 text-[12px] font-medium text-[var(--ink-soft)]",
|
|
224
|
+
children: [/* @__PURE__ */ jsx("input", {
|
|
225
|
+
"aria-label": `Auto sync ${kind}`,
|
|
226
|
+
type: "checkbox",
|
|
227
|
+
checked: autoSettings.enabled,
|
|
228
|
+
disabled: waitingForAccount || birdOnlyWrongAccount,
|
|
229
|
+
onChange: (event) => updateAutoSettings({
|
|
230
|
+
enabled: event.currentTarget.checked,
|
|
231
|
+
intervalMs: autoSettings.intervalMs
|
|
232
|
+
})
|
|
233
|
+
}), "Auto sync"]
|
|
234
|
+
}),
|
|
235
|
+
/* @__PURE__ */ jsx("select", {
|
|
236
|
+
"aria-label": `${label} auto-sync interval`,
|
|
237
|
+
className: cx(selectFieldClass, "h-9 w-[70px]!"),
|
|
238
|
+
disabled: !autoSettings.enabled,
|
|
239
|
+
onChange: (event) => updateAutoSettings({
|
|
240
|
+
enabled: autoSettings.enabled,
|
|
241
|
+
intervalMs: Number(event.currentTarget.value)
|
|
242
|
+
}),
|
|
243
|
+
value: autoSettings.intervalMs,
|
|
244
|
+
children: AUTO_SYNC_INTERVALS.map((option) => /* @__PURE__ */ jsx("option", {
|
|
245
|
+
value: option.value,
|
|
246
|
+
children: option.label
|
|
247
|
+
}, option.value))
|
|
248
|
+
}),
|
|
249
|
+
/* @__PURE__ */ jsx("span", {
|
|
250
|
+
className: cx("max-w-[190px] truncate text-[12px]", autoSyncError ? "text-[var(--alert)]" : "text-[var(--ink-soft)]"),
|
|
251
|
+
role: "status",
|
|
252
|
+
children: autoStatusMessage
|
|
253
|
+
})
|
|
254
|
+
] }) : null
|
|
255
|
+
]
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
//#endregion
|
|
259
|
+
export { SyncNowButton as t };
|
package/dist/server/assets/{TimelineRouteFrame-CjMIh63G.js → TimelineRouteFrame-Bg3e7X_N.js}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as SyncNowButton } from "./SyncNowButton-
|
|
3
|
-
import { a as TimelineSearchField, i as TimelineHeaderSubtitle, n as TimelineFeedHeader, o as TimelineCard, r as TimelineFeedShell, t as useTimelineRouteData } from "./useTimelineRouteData-
|
|
1
|
+
import { dn as tabStripClass, ln as tabButtonClass, m as cx, mn as timestampClass, un as tabButtonIndicatorClass } from "./ui-rDHeS-cc.js";
|
|
2
|
+
import { t as SyncNowButton } from "./SyncNowButton-CKuXKYcd.js";
|
|
3
|
+
import { a as TimelineSearchField, i as TimelineHeaderSubtitle, n as TimelineFeedHeader, o as TimelineCard, r as TimelineFeedShell, t as useTimelineRouteData } from "./useTimelineRouteData-BmDbGvQ8.js";
|
|
4
4
|
import { useMemo, useState } from "react";
|
|
5
5
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
//#region src/components/TimelineRouteFrame.tsx
|
|
@@ -33,6 +33,8 @@ function TimelineRouteFrame({ title, resource, initialReplyFilter, searchPlaceho
|
|
|
33
33
|
subtitles: /* @__PURE__ */ jsx(TimelineHeaderSubtitle, { children: useMemo(() => subtitle(meta), [meta, subtitle]) }),
|
|
34
34
|
action: /* @__PURE__ */ jsx(SyncNowButton, {
|
|
35
35
|
accounts: meta?.accounts,
|
|
36
|
+
allowAutoSync: true,
|
|
37
|
+
autoSyncBlocked: loading,
|
|
36
38
|
kind: syncKind,
|
|
37
39
|
label: syncLabel,
|
|
38
40
|
onSynced: refreshLocalView,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { c as collectTweetSegmentsForText, d as isTweetArticleUrlEntity, f as normalizeTweetUrlEntityRangeForText, s as safeHttpUrl, t as ProfilePreview, u as enrichFallbackUrlEntities } from "./ProfilePreview-
|
|
1
|
+
import { gn as tweetLinkClass, hn as tweetHashtagClass, s as bodyCopyClass, yn as tweetMentionClass } from "./ui-rDHeS-cc.js";
|
|
2
|
+
import { c as collectTweetSegmentsForText, d as isTweetArticleUrlEntity, f as normalizeTweetUrlEntityRangeForText, s as safeHttpUrl, t as ProfilePreview, u as enrichFallbackUrlEntities } from "./ProfilePreview-Bq-DSUM2.js";
|
|
3
3
|
import { Fragment } from "react";
|
|
4
4
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
//#region src/components/TweetRichText.tsx
|
|
@@ -38,110 +38,110 @@ var tsrStartManifest = () => ({ routes: {
|
|
|
38
38
|
],
|
|
39
39
|
css: ["/assets/index-bpFrQ5yG.css"],
|
|
40
40
|
preloads: [
|
|
41
|
-
"/assets/index-
|
|
42
|
-
"/assets/
|
|
43
|
-
"/assets/
|
|
44
|
-
"/assets/
|
|
45
|
-
"/assets/
|
|
46
|
-
"/assets/
|
|
47
|
-
"/assets/
|
|
48
|
-
"/assets/
|
|
49
|
-
"/assets/
|
|
50
|
-
"/assets/
|
|
51
|
-
"/assets/AvatarChip-
|
|
52
|
-
"/assets/ProfilePreview-
|
|
53
|
-
"/assets/SmartTimestamp-
|
|
54
|
-
"/assets/profile-hydration-client-
|
|
41
|
+
"/assets/index-a1ZAcWSa.js",
|
|
42
|
+
"/assets/rolldown-runtime-B-9mzPXz.js",
|
|
43
|
+
"/assets/react-BwGzW7mM.js",
|
|
44
|
+
"/assets/react-dom-DEMAB80t.js",
|
|
45
|
+
"/assets/schemas-CntsNLmN.js",
|
|
46
|
+
"/assets/createLucideIcon-CMLcIxOz.js",
|
|
47
|
+
"/assets/circle-check-BCK_qvXt.js",
|
|
48
|
+
"/assets/client-stream-contracts-D1QUdWfh.js",
|
|
49
|
+
"/assets/sparkles-Gx_BHkDX.js",
|
|
50
|
+
"/assets/query-client-DZ5C7UNo.js",
|
|
51
|
+
"/assets/AvatarChip-C8zELEVt.js",
|
|
52
|
+
"/assets/ProfilePreview-CsiLpFrb.js",
|
|
53
|
+
"/assets/SmartTimestamp-BypN4KPq.js",
|
|
54
|
+
"/assets/profile-hydration-client-BQyC5--e.js"
|
|
55
55
|
],
|
|
56
56
|
scripts: [{ attrs: {
|
|
57
57
|
type: "module",
|
|
58
58
|
async: !0,
|
|
59
|
-
src: "/assets/index-
|
|
59
|
+
src: "/assets/index-a1ZAcWSa.js"
|
|
60
60
|
} }]
|
|
61
61
|
},
|
|
62
62
|
"/": {
|
|
63
63
|
filePath: "/Users/steipete/Projects/birdclaw/src/routes/index.tsx",
|
|
64
64
|
children: void 0,
|
|
65
|
-
preloads: ["/assets/routes-
|
|
65
|
+
preloads: ["/assets/routes-CeIv5bkV.js", "/assets/TimelineRouteFrame-D6djyMAT.js"]
|
|
66
66
|
},
|
|
67
67
|
"/blocks": {
|
|
68
68
|
filePath: "/Users/steipete/Projects/birdclaw/src/routes/blocks.tsx",
|
|
69
69
|
children: void 0,
|
|
70
|
-
preloads: ["/assets/blocks-
|
|
70
|
+
preloads: ["/assets/blocks-h27nF3TL.js"]
|
|
71
71
|
},
|
|
72
72
|
"/bookmarks": {
|
|
73
73
|
filePath: "/Users/steipete/Projects/birdclaw/src/routes/bookmarks.tsx",
|
|
74
74
|
children: void 0,
|
|
75
|
-
preloads: ["/assets/bookmarks-
|
|
75
|
+
preloads: ["/assets/bookmarks-Cprrli-V.js", "/assets/SavedTimelineView-DE4CXK-h.js"]
|
|
76
76
|
},
|
|
77
77
|
"/data-sources": {
|
|
78
78
|
filePath: "/Users/steipete/Projects/birdclaw/src/routes/data-sources.tsx",
|
|
79
79
|
children: void 0,
|
|
80
|
-
preloads: ["/assets/data-sources-
|
|
80
|
+
preloads: ["/assets/data-sources-Beb3JZkl.js", "/assets/triangle-alert-DJPCW6jQ.js"]
|
|
81
81
|
},
|
|
82
82
|
"/discuss": {
|
|
83
83
|
filePath: "/Users/steipete/Projects/birdclaw/src/routes/discuss.tsx",
|
|
84
84
|
children: void 0,
|
|
85
|
-
preloads: ["/assets/discuss-
|
|
85
|
+
preloads: ["/assets/discuss-ciwVz7Fo.js", "/assets/search-C_LqodNa.js"]
|
|
86
86
|
},
|
|
87
87
|
"/dms": {
|
|
88
88
|
filePath: "/Users/steipete/Projects/birdclaw/src/routes/dms.tsx",
|
|
89
89
|
children: void 0,
|
|
90
|
-
preloads: ["/assets/dms-
|
|
90
|
+
preloads: ["/assets/dms-BZ3GUPey.js", "/assets/search-C_LqodNa.js"]
|
|
91
91
|
},
|
|
92
92
|
"/inbox": {
|
|
93
93
|
filePath: "/Users/steipete/Projects/birdclaw/src/routes/inbox.tsx",
|
|
94
94
|
children: void 0,
|
|
95
|
-
preloads: ["/assets/inbox-
|
|
95
|
+
preloads: ["/assets/inbox-Dajdut79.js"]
|
|
96
96
|
},
|
|
97
97
|
"/likes": {
|
|
98
98
|
filePath: "/Users/steipete/Projects/birdclaw/src/routes/likes.tsx",
|
|
99
99
|
children: void 0,
|
|
100
|
-
preloads: ["/assets/likes-
|
|
100
|
+
preloads: ["/assets/likes-CxZZqiZC.js", "/assets/SavedTimelineView-DE4CXK-h.js"]
|
|
101
101
|
},
|
|
102
102
|
"/links": {
|
|
103
103
|
filePath: "/Users/steipete/Projects/birdclaw/src/routes/links.tsx",
|
|
104
104
|
children: void 0,
|
|
105
105
|
preloads: [
|
|
106
|
-
"/assets/links-
|
|
107
|
-
"/assets/repeat-2-
|
|
108
|
-
"/assets/search-
|
|
109
|
-
"/assets/users-
|
|
106
|
+
"/assets/links-CsWS9uKL.js",
|
|
107
|
+
"/assets/repeat-2-CQ0lek01.js",
|
|
108
|
+
"/assets/search-C_LqodNa.js",
|
|
109
|
+
"/assets/users-DI3w8Mol.js"
|
|
110
110
|
]
|
|
111
111
|
},
|
|
112
112
|
"/mentions": {
|
|
113
113
|
filePath: "/Users/steipete/Projects/birdclaw/src/routes/mentions.tsx",
|
|
114
114
|
children: void 0,
|
|
115
|
-
preloads: ["/assets/mentions-
|
|
115
|
+
preloads: ["/assets/mentions-C3JYXV2K.js", "/assets/TimelineRouteFrame-D6djyMAT.js"]
|
|
116
116
|
},
|
|
117
117
|
"/network-map": {
|
|
118
118
|
filePath: "/Users/steipete/Projects/birdclaw/src/routes/network-map.tsx",
|
|
119
119
|
children: void 0,
|
|
120
120
|
preloads: [
|
|
121
|
-
"/assets/network-map-
|
|
122
|
-
"/assets/search-
|
|
123
|
-
"/assets/users-
|
|
121
|
+
"/assets/network-map-D4XA7TTO.js",
|
|
122
|
+
"/assets/search-C_LqodNa.js",
|
|
123
|
+
"/assets/users-DI3w8Mol.js"
|
|
124
124
|
]
|
|
125
125
|
},
|
|
126
126
|
"/profile-analyze": {
|
|
127
127
|
filePath: "/Users/steipete/Projects/birdclaw/src/routes/profile-analyze.tsx",
|
|
128
128
|
children: void 0,
|
|
129
|
-
preloads: ["/assets/profile-analyze-
|
|
129
|
+
preloads: ["/assets/profile-analyze-QAznTMjZ.js", "/assets/search-C_LqodNa.js"]
|
|
130
130
|
},
|
|
131
131
|
"/rate-limits": {
|
|
132
132
|
filePath: "/Users/steipete/Projects/birdclaw/src/routes/rate-limits.tsx",
|
|
133
133
|
children: void 0,
|
|
134
|
-
preloads: ["/assets/rate-limits-
|
|
134
|
+
preloads: ["/assets/rate-limits-eHs_5dDB.js", "/assets/triangle-alert-DJPCW6jQ.js"]
|
|
135
135
|
},
|
|
136
136
|
"/today": {
|
|
137
137
|
filePath: "/Users/steipete/Projects/birdclaw/src/routes/today.tsx",
|
|
138
138
|
children: void 0,
|
|
139
|
-
preloads: ["/assets/today-
|
|
139
|
+
preloads: ["/assets/today-DxppbQGF.js"]
|
|
140
140
|
},
|
|
141
141
|
"/profiles/$handle": {
|
|
142
142
|
filePath: "/Users/steipete/Projects/birdclaw/src/routes/profiles.$handle.tsx",
|
|
143
143
|
children: void 0,
|
|
144
|
-
preloads: ["/assets/profiles._handle-
|
|
144
|
+
preloads: ["/assets/profiles._handle-qntfbCE1.js"]
|
|
145
145
|
}
|
|
146
146
|
} });
|
|
147
147
|
//#endregion
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import "./ui-
|
|
1
|
+
import "./ui-rDHeS-cc.js";
|
|
2
2
|
import "./query-client-BdauHBgd.js";
|
|
3
|
-
import "./AvatarChip-
|
|
3
|
+
import "./AvatarChip-DWag3IzT.js";
|
|
4
4
|
import { t as validateBlocksSearch } from "./route-search-BUlQ5lGM.js";
|
|
5
5
|
import "./useDebouncedValue-DOnA6Xcy.js";
|
|
6
6
|
import "react";
|
|
@@ -8,7 +8,7 @@ import { createFileRoute, lazyRouteComponent } from "@tanstack/react-router";
|
|
|
8
8
|
import "react/jsx-runtime";
|
|
9
9
|
import "@tanstack/react-query";
|
|
10
10
|
//#region src/routes/blocks.tsx
|
|
11
|
-
var $$splitComponentImporter = () => import("./blocks-
|
|
11
|
+
var $$splitComponentImporter = () => import("./blocks-DKy4yTF-.js");
|
|
12
12
|
var Route = createFileRoute("/blocks")({
|
|
13
13
|
component: lazyRouteComponent($$splitComponentImporter, "component"),
|
|
14
14
|
validateSearch: validateBlocksSearch
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { Dt as pageSubtitleClass, Et as pageHeaderRowClass,
|
|
1
|
+
import { Dt as pageSubtitleClass, Et as pageHeaderRowClass, K as emptyStateClass, Mt as primaryButtonClass, Ot as pageTitleClass, Tt as pageHeaderClass, Wt as secondaryButtonClass, Yt as selectFieldClass, _t as mutedDotClass, a as blockRowClass, fn as textFieldClass, h as dangerButtonClass, i as blockRowBodyClass, m as cx, mn as timestampClass, pn as textFieldShortClass, q as errorCopyClass, sn as statusCopyClass } from "./ui-rDHeS-cc.js";
|
|
2
2
|
import { _ as blockListResponseSchema, a as fetchQueryEnvelope, n as queryKeys, r as fetchJson, s as postAction } from "./query-client-BdauHBgd.js";
|
|
3
|
-
import { r as formatCompactNumber, t as AvatarChip } from "./AvatarChip-
|
|
3
|
+
import { r as formatCompactNumber, t as AvatarChip } from "./AvatarChip-DWag3IzT.js";
|
|
4
4
|
import { t as validateBlocksSearch } from "./route-search-BUlQ5lGM.js";
|
|
5
5
|
import { t as useDebouncedValue } from "./useDebouncedValue-DOnA6Xcy.js";
|
|
6
|
-
import { t as Route } from "./blocks-
|
|
6
|
+
import { t as Route } from "./blocks-CaP_u3mY.js";
|
|
7
7
|
import { useEffect, useMemo, useState } from "react";
|
|
8
8
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
9
9
|
import { keepPreviousData, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as SavedTimelineView } from "./SavedTimelineView-
|
|
1
|
+
import { t as SavedTimelineView } from "./SavedTimelineView-Bk9nfnb-.js";
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
3
|
//#region src/routes/bookmarks.tsx?tsr-split=component
|
|
4
4
|
function BookmarksRoute() {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { r as formatCompactNumber, t as AvatarChip } from "./AvatarChip-
|
|
3
|
-
import { m as renderTweetPlainText, n as useFloatingPreview, r as useAvatarPreload, s as safeHttpUrl, t as ProfilePreview } from "./ProfilePreview-
|
|
4
|
-
import { t as SmartTimestamp } from "./SmartTimestamp-
|
|
1
|
+
import { gn as tweetLinkClass, m as cx, yn as tweetMentionClass } from "./ui-rDHeS-cc.js";
|
|
2
|
+
import { r as formatCompactNumber, t as AvatarChip } from "./AvatarChip-DWag3IzT.js";
|
|
3
|
+
import { m as renderTweetPlainText, n as useFloatingPreview, r as useAvatarPreload, s as safeHttpUrl, t as ProfilePreview } from "./ProfilePreview-Bq-DSUM2.js";
|
|
4
|
+
import { t as SmartTimestamp } from "./SmartTimestamp-C06w_f9J.js";
|
|
5
5
|
import { Fragment, useCallback, useEffect, useRef, useState } from "react";
|
|
6
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
import { z } from "zod";
|
|
@@ -78,6 +78,66 @@ function getTweetUrl(tweet) {
|
|
|
78
78
|
function getFallbackTweetUrl(tweetId) {
|
|
79
79
|
return `https://x.com/i/status/${normalizeTweetReference(tweetId)}`;
|
|
80
80
|
}
|
|
81
|
+
function comparableUrl(value) {
|
|
82
|
+
try {
|
|
83
|
+
const parsed = new URL(value);
|
|
84
|
+
return `${parsed.protocol}//${parsed.hostname}${parsed.pathname}`;
|
|
85
|
+
} catch {
|
|
86
|
+
return value.split("?")[0] ?? value;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function isOwnStatusMediaUrl(value, tweetId) {
|
|
90
|
+
try {
|
|
91
|
+
const parsed = new URL(value);
|
|
92
|
+
const host = parsed.hostname.replace(/^www\./, "");
|
|
93
|
+
if (host !== "x.com" && host !== "twitter.com") return false;
|
|
94
|
+
return new RegExp(`/status/${tweetId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}/(?:photo|video)(?:/|$)`).test(parsed.pathname);
|
|
95
|
+
} catch {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function previewTextWithoutMediaLink(text, tweet, media) {
|
|
100
|
+
if (media.length === 0) return text;
|
|
101
|
+
const match = /(https?:\/\/[^\s]+)\s*$/.exec(text);
|
|
102
|
+
if (!match) return text;
|
|
103
|
+
const trailingUrl = match[1];
|
|
104
|
+
if (!trailingUrl) return text;
|
|
105
|
+
const mediaUrls = new Set(media.flatMap((item) => item.thumbnailUrl ? [item.url, item.thumbnailUrl] : [item.url]));
|
|
106
|
+
const comparableTrailing = comparableUrl(trailingUrl);
|
|
107
|
+
const directlyMatchesMedia = [...mediaUrls].some((url) => comparableUrl(url) === comparableTrailing);
|
|
108
|
+
const mediaEntityLostItsRange = (tweet.entities?.urls ?? []).some((entry) => {
|
|
109
|
+
if (entry.end > entry.start) return false;
|
|
110
|
+
return [...mediaUrls].some((url) => comparableUrl(url) === comparableUrl(entry.expandedUrl));
|
|
111
|
+
});
|
|
112
|
+
const isUnresolvedShortUrl = (() => {
|
|
113
|
+
try {
|
|
114
|
+
return new URL(trailingUrl).hostname.replace(/^www\./, "") === "t.co";
|
|
115
|
+
} catch {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
})();
|
|
119
|
+
if (!directlyMatchesMedia && !isOwnStatusMediaUrl(trailingUrl, tweet.id) && !(isUnresolvedShortUrl && mediaEntityLostItsRange)) return text;
|
|
120
|
+
return text.slice(0, match.index).trimEnd();
|
|
121
|
+
}
|
|
122
|
+
function TweetPreviewMedia({ items }) {
|
|
123
|
+
const images = items.flatMap((item) => {
|
|
124
|
+
const url = item.type === "image" ? safeHttpUrl(item.thumbnailUrl ?? item.url) : safeHttpUrl(item.thumbnailUrl);
|
|
125
|
+
return url ? [{
|
|
126
|
+
item,
|
|
127
|
+
url
|
|
128
|
+
}] : [];
|
|
129
|
+
}).slice(0, 4);
|
|
130
|
+
if (images.length === 0) return null;
|
|
131
|
+
return /* @__PURE__ */ jsx("span", {
|
|
132
|
+
className: images.length === 1 ? "mt-2 block overflow-hidden rounded-xl border border-[var(--line)] bg-[var(--bg-active)]" : "mt-2 grid grid-cols-2 gap-1.5 overflow-hidden rounded-xl",
|
|
133
|
+
children: images.map(({ item, url }, index) => /* @__PURE__ */ jsx("img", {
|
|
134
|
+
alt: item.altText ?? `Tweet media ${String(index + 1)}`,
|
|
135
|
+
className: images.length === 1 ? "block max-h-64 w-full object-contain" : "block aspect-square size-full rounded-lg border border-[var(--line)] object-cover",
|
|
136
|
+
decoding: "async",
|
|
137
|
+
src: url
|
|
138
|
+
}, `${url}-${String(index)}`))
|
|
139
|
+
});
|
|
140
|
+
}
|
|
81
141
|
function TweetSourceLink({ children, href, onClick, describedBy }) {
|
|
82
142
|
return /* @__PURE__ */ jsx("a", {
|
|
83
143
|
"aria-describedby": describedBy,
|
|
@@ -93,8 +153,9 @@ function TweetPreviewToken({ tweet, children }) {
|
|
|
93
153
|
const preview = useFloatingPreview();
|
|
94
154
|
useAvatarPreload(preview.referenceRef, tweet.authorProfile.id, tweet.authorProfile.avatarUrl);
|
|
95
155
|
const article = tweet.entities?.article;
|
|
156
|
+
const media = tweet.media ?? [];
|
|
96
157
|
const renderedText = renderTweetPlainText(tweet.text, tweet.entities ?? {});
|
|
97
|
-
const previewText = article ? [article.title, article.previewText].filter((value, index, values) => Boolean(value) && values.indexOf(value) === index).join("\n\n") : renderedText;
|
|
158
|
+
const previewText = article ? [article.title, article.previewText].filter((value, index, values) => Boolean(value) && values.indexOf(value) === index).join("\n\n") : previewTextWithoutMediaLink(renderedText, tweet, media);
|
|
98
159
|
return /* @__PURE__ */ jsxs("span", {
|
|
99
160
|
ref: preview.referenceRef,
|
|
100
161
|
className: "inline align-baseline",
|
|
@@ -143,9 +204,10 @@ function TweetPreviewToken({ tweet, children }) {
|
|
|
143
204
|
})]
|
|
144
205
|
}),
|
|
145
206
|
/* @__PURE__ */ jsx("span", {
|
|
146
|
-
className: "
|
|
207
|
+
className: "whitespace-pre-wrap [overflow-wrap:anywhere]",
|
|
147
208
|
children: previewText
|
|
148
209
|
}),
|
|
210
|
+
/* @__PURE__ */ jsx(TweetPreviewMedia, { items: media }),
|
|
149
211
|
/* @__PURE__ */ jsxs("span", {
|
|
150
212
|
className: "mt-2 flex gap-3 text-[12px] text-[var(--ink-soft)]",
|
|
151
213
|
children: [
|
|
@@ -418,7 +480,8 @@ function profileAnalysisTweetToCitation(tweet, profile) {
|
|
|
418
480
|
likeCount: tweet.likeCount,
|
|
419
481
|
liked: false,
|
|
420
482
|
bookmarked: false,
|
|
421
|
-
needsReply: false
|
|
483
|
+
needsReply: false,
|
|
484
|
+
media: []
|
|
422
485
|
};
|
|
423
486
|
}
|
|
424
487
|
function conversationTweetToCitation(tweet) {
|
|
@@ -436,7 +499,8 @@ function conversationTweetToCitation(tweet) {
|
|
|
436
499
|
likeCount: tweet.likeCount,
|
|
437
500
|
liked: false,
|
|
438
501
|
bookmarked: false,
|
|
439
|
-
needsReply: false
|
|
502
|
+
needsReply: false,
|
|
503
|
+
media: []
|
|
440
504
|
};
|
|
441
505
|
}
|
|
442
506
|
function buildLookup(context) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Dt as pageSubtitleClass, Et as pageHeaderRowClass, Ot as pageTitleClass, Tt as pageHeaderClass, Wt as secondaryButtonClass, m as cx,
|
|
1
|
+
import { Dt as pageSubtitleClass, Et as pageHeaderRowClass, Ot as pageTitleClass, Tt as pageHeaderClass, Wt as secondaryButtonClass, m as cx, q as errorCopyClass, sn as statusCopyClass, wt as pageHeaderActionsClass } from "./ui-rDHeS-cc.js";
|
|
2
2
|
import { S as liveDataSourcesResponseSchema, n as queryKeys, r as fetchJson } from "./query-client-BdauHBgd.js";
|
|
3
3
|
import { useMemo } from "react";
|
|
4
4
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import "./ui-
|
|
2
|
-
import "./client-stream-contracts-
|
|
1
|
+
import "./ui-rDHeS-cc.js";
|
|
2
|
+
import "./client-stream-contracts-gtXEreFY.js";
|
|
3
3
|
import { n as validateDiscussSearch } from "./route-search-BUlQ5lGM.js";
|
|
4
4
|
import "react";
|
|
5
5
|
import { createFileRoute, lazyRouteComponent } from "@tanstack/react-router";
|
|
6
6
|
import "react/jsx-runtime";
|
|
7
7
|
import "lucide-react";
|
|
8
8
|
//#region src/routes/discuss.tsx
|
|
9
|
-
var $$splitComponentImporter = () => import("./discuss-
|
|
9
|
+
var $$splitComponentImporter = () => import("./discuss-CVGB4_I0.js");
|
|
10
10
|
var Route$1 = createFileRoute("/discuss")({
|
|
11
11
|
component: lazyRouteComponent($$splitComponentImporter, "component"),
|
|
12
12
|
validateSearch: validateDiscussSearch
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Dt as pageSubtitleClass, Et as pageHeaderRowClass, Ht as searchFieldInputClass,
|
|
2
|
-
import { a as useNdjsonRun, i as searchDiscussionStreamEventSchema, o as MarkdownViewer, t as isTerminalStreamEvent } from "./client-stream-contracts-
|
|
1
|
+
import { Dt as pageSubtitleClass, Et as pageHeaderRowClass, Ht as searchFieldInputClass, Mt as primaryButtonClass, Ot as pageTitleClass, Tt as pageHeaderClass, Ut as searchFieldShellClass, Vt as searchFieldIconClass, Wt as secondaryButtonClass, Yt as selectFieldClass, fn as textFieldClass, m as cx, q as errorCopyClass, wt as pageHeaderActionsClass } from "./ui-rDHeS-cc.js";
|
|
2
|
+
import { a as useNdjsonRun, i as searchDiscussionStreamEventSchema, o as MarkdownViewer, t as isTerminalStreamEvent } from "./client-stream-contracts-gtXEreFY.js";
|
|
3
3
|
import { n as validateDiscussSearch } from "./route-search-BUlQ5lGM.js";
|
|
4
|
-
import { t as Route$1 } from "./discuss-
|
|
4
|
+
import { t as Route$1 } from "./discuss-BB8wFy4L.js";
|
|
5
5
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
6
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
import { CheckCircle2, ChevronDown, Loader2, RefreshCw, Search, Sparkles } from "lucide-react";
|