@agent-native/core 0.76.10 → 0.76.12
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 +13 -0
- package/corpus/core/docs/content/locales/ar-SA/actions.md +7 -7
- package/corpus/core/docs/content/locales/ar-SA/template-plan.md +6 -4
- package/corpus/core/docs/content/locales/de-DE/actions.md +9 -9
- package/corpus/core/docs/content/locales/de-DE/template-plan.md +6 -4
- package/corpus/core/docs/content/locales/es-ES/actions.md +9 -9
- package/corpus/core/docs/content/locales/es-ES/template-plan.md +6 -4
- package/corpus/core/docs/content/locales/fr-FR/actions.md +9 -9
- package/corpus/core/docs/content/locales/fr-FR/template-plan.md +6 -4
- package/corpus/core/docs/content/locales/hi-IN/actions.md +9 -9
- package/corpus/core/docs/content/locales/hi-IN/template-plan.md +4 -4
- package/corpus/core/docs/content/locales/ja-JP/actions.md +9 -9
- package/corpus/core/docs/content/locales/ja-JP/template-plan.md +4 -4
- package/corpus/core/docs/content/locales/ko-KR/actions.md +9 -9
- package/corpus/core/docs/content/locales/ko-KR/template-plan.md +4 -4
- package/corpus/core/docs/content/locales/pt-BR/actions.md +9 -9
- package/corpus/core/docs/content/locales/pt-BR/template-plan.md +6 -4
- package/corpus/core/docs/content/locales/zh-CN/actions.md +9 -9
- package/corpus/core/docs/content/locales/zh-CN/template-plan.md +4 -4
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/client/ErrorBoundary.tsx +151 -10
- package/corpus/core/src/client/FeedbackButton.tsx +162 -18
- package/corpus/core/src/client/blocks/library/AnnotatedCodeBlock.tsx +11 -2
- package/corpus/core/src/client/blocks/library/ApiEndpointBlock.tsx +46 -19
- package/corpus/core/src/client/blocks/library/MermaidBlock.tsx +7 -5
- package/corpus/core/src/client/blocks/library/block-copy.ts +367 -0
- package/corpus/core/src/client/blocks/library/diagram.tsx +8 -6
- package/corpus/core/src/client/blocks/library/wireframe.tsx +7 -2
- package/corpus/core/src/client/i18n.tsx +4 -0
- package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +51 -31
- package/corpus/templates/analytics/app/components/layout/DashboardHeader.tsx +26 -16
- package/corpus/templates/analytics/app/components/layout/Header.tsx +1 -2
- package/corpus/templates/analytics/app/components/layout/HeaderActions.tsx +8 -1
- package/corpus/templates/analytics/app/components/layout/Layout.tsx +2 -5
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +172 -107
- package/corpus/templates/analytics/app/i18n-data.ts +1076 -5
- package/corpus/templates/analytics/app/pages/Settings.tsx +2 -2
- package/corpus/templates/analytics/changelog/2026-06-24-analytics-navigation-command-palette-and-settings-now-honor-.md +6 -0
- package/corpus/templates/assets/app/components/layout/Header.tsx +0 -2
- package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +0 -2
- package/corpus/templates/calendar/app/pages/CalendarView.tsx +0 -2
- package/corpus/templates/chat/app/components/layout/Header.tsx +1 -6
- package/corpus/templates/clips/app/components/layout/Header.tsx +1 -6
- package/corpus/templates/clips/app/hooks/use-library.ts +2 -0
- package/corpus/templates/clips/app/routes/_app.settings._index.tsx +3 -1
- package/corpus/templates/clips/changelog/2026-06-24-archive-and-spaces-navigation-is-more-resilient-when-sidebar.md +6 -0
- package/corpus/templates/content/app/components/layout/Header.tsx +0 -2
- package/corpus/templates/design/app/components/layout/Header.tsx +1 -6
- package/corpus/templates/forms/app/components/layout/Header.tsx +1 -6
- package/corpus/templates/macros/app/components/layout/Header.tsx +1 -6
- package/corpus/templates/mail/app/components/email/CodeBlockLangPicker.tsx +4 -2
- package/corpus/templates/mail/app/components/email/ComposeBubbleToolbar.tsx +18 -12
- package/corpus/templates/mail/app/components/email/ComposeEditor.tsx +9 -5
- package/corpus/templates/mail/app/components/email/ComposeModal.tsx +36 -19
- package/corpus/templates/mail/app/components/email/EmailList.tsx +59 -55
- package/corpus/templates/mail/app/components/email/EmailListItem.tsx +7 -3
- package/corpus/templates/mail/app/components/email/EmailThread.tsx +25 -16
- package/corpus/templates/mail/app/components/email/InlineReplyComposer.tsx +25 -19
- package/corpus/templates/mail/app/components/email/IntegrationsSidebar.tsx +32 -17
- package/corpus/templates/mail/app/components/email/RecipientInput.tsx +26 -10
- package/corpus/templates/mail/app/components/email/SendLaterButton.tsx +5 -3
- package/corpus/templates/mail/app/components/email/SnoozeModal.tsx +4 -2
- package/corpus/templates/mail/app/components/email/SnoozePopover.tsx +9 -5
- package/corpus/templates/mail/app/components/email/extensions/ComposeImageBlock.tsx +4 -2
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +168 -86
- package/corpus/templates/mail/app/components/layout/SearchBar.tsx +4 -2
- package/corpus/templates/mail/app/i18n/ar-SA.ts +212 -0
- package/corpus/templates/mail/app/i18n/de-DE.ts +212 -0
- package/corpus/templates/mail/app/i18n/en-US.ts +212 -0
- package/corpus/templates/mail/app/i18n/es-ES.ts +212 -0
- package/corpus/templates/mail/app/i18n/fr-FR.ts +212 -0
- package/corpus/templates/mail/app/i18n/hi-IN.ts +212 -0
- package/corpus/templates/mail/app/i18n/ja-JP.ts +212 -0
- package/corpus/templates/mail/app/i18n/ko-KR.ts +212 -0
- package/corpus/templates/mail/app/i18n/pt-BR.ts +212 -0
- package/corpus/templates/mail/app/i18n/zh-CN.ts +211 -0
- package/corpus/templates/mail/app/root.tsx +90 -6
- package/corpus/templates/mail/changelog/2026-06-24-interface-language-support-now-covers-more-mail-controls-and.md +6 -0
- package/corpus/templates/plan/app/components/layout/Header.tsx +1 -6
- package/corpus/templates/slides/app/components/layout/Header.tsx +1 -6
- package/corpus/templates/videos/app/components/layout/Header.tsx +1 -6
- package/dist/client/ErrorBoundary.d.ts.map +1 -1
- package/dist/client/ErrorBoundary.js +128 -7
- package/dist/client/ErrorBoundary.js.map +1 -1
- package/dist/client/FeedbackButton.d.ts.map +1 -1
- package/dist/client/FeedbackButton.js +142 -14
- package/dist/client/FeedbackButton.js.map +1 -1
- package/dist/client/blocks/library/AnnotatedCodeBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/AnnotatedCodeBlock.js +6 -2
- package/dist/client/blocks/library/AnnotatedCodeBlock.js.map +1 -1
- package/dist/client/blocks/library/ApiEndpointBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/ApiEndpointBlock.js +14 -6
- package/dist/client/blocks/library/ApiEndpointBlock.js.map +1 -1
- package/dist/client/blocks/library/MermaidBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/MermaidBlock.js +6 -4
- package/dist/client/blocks/library/MermaidBlock.js.map +1 -1
- package/dist/client/blocks/library/block-copy.d.ts +33 -0
- package/dist/client/blocks/library/block-copy.d.ts.map +1 -0
- package/dist/client/blocks/library/block-copy.js +329 -0
- package/dist/client/blocks/library/block-copy.js.map +1 -0
- package/dist/client/blocks/library/diagram.d.ts.map +1 -1
- package/dist/client/blocks/library/diagram.js +7 -5
- package/dist/client/blocks/library/diagram.js.map +1 -1
- package/dist/client/blocks/library/wireframe.d.ts.map +1 -1
- package/dist/client/blocks/library/wireframe.js +4 -2
- package/dist/client/blocks/library/wireframe.js.map +1 -1
- package/dist/client/i18n.d.ts +1 -0
- package/dist/client/i18n.d.ts.map +1 -1
- package/dist/client/i18n.js +3 -0
- package/dist/client/i18n.js.map +1 -1
- package/docs/content/locales/ar-SA/actions.md +7 -7
- package/docs/content/locales/ar-SA/template-plan.md +6 -4
- package/docs/content/locales/de-DE/actions.md +9 -9
- package/docs/content/locales/de-DE/template-plan.md +6 -4
- package/docs/content/locales/es-ES/actions.md +9 -9
- package/docs/content/locales/es-ES/template-plan.md +6 -4
- package/docs/content/locales/fr-FR/actions.md +9 -9
- package/docs/content/locales/fr-FR/template-plan.md +6 -4
- package/docs/content/locales/hi-IN/actions.md +9 -9
- package/docs/content/locales/hi-IN/template-plan.md +4 -4
- package/docs/content/locales/ja-JP/actions.md +9 -9
- package/docs/content/locales/ja-JP/template-plan.md +4 -4
- package/docs/content/locales/ko-KR/actions.md +9 -9
- package/docs/content/locales/ko-KR/template-plan.md +4 -4
- package/docs/content/locales/pt-BR/actions.md +9 -9
- package/docs/content/locales/pt-BR/template-plan.md +6 -4
- package/docs/content/locales/zh-CN/actions.md +9 -9
- package/docs/content/locales/zh-CN/template-plan.md +4 -4
- package/package.json +1 -1
|
@@ -53,6 +53,7 @@ import {
|
|
|
53
53
|
TooltipContent,
|
|
54
54
|
TooltipTrigger,
|
|
55
55
|
} from "@/components/ui/tooltip";
|
|
56
|
+
import { useT } from "@agent-native/core/client";
|
|
56
57
|
|
|
57
58
|
type EmailsPage = { emails: EmailMessage[]; nextPageToken?: string };
|
|
58
59
|
type InfiniteEmails = InfiniteData<EmailsPage, string | undefined>;
|
|
@@ -119,34 +120,35 @@ const INBOX_ZERO_PHOTOS = [
|
|
|
119
120
|
"photo-1552083375-1447ce886485", // Japanese garden
|
|
120
121
|
];
|
|
121
122
|
|
|
122
|
-
function
|
|
123
|
+
function emptyStateHintKeyForView(view: string): string {
|
|
123
124
|
switch (view) {
|
|
124
125
|
case "snoozed":
|
|
125
|
-
return "
|
|
126
|
+
return "mail.empty.snoozed";
|
|
126
127
|
case "drafts":
|
|
127
|
-
return "
|
|
128
|
+
return "mail.empty.drafts";
|
|
128
129
|
case "starred":
|
|
129
|
-
return "
|
|
130
|
+
return "mail.empty.starred";
|
|
130
131
|
case "sent":
|
|
131
|
-
return "
|
|
132
|
+
return "mail.empty.sent";
|
|
132
133
|
case "scheduled":
|
|
133
|
-
return "
|
|
134
|
+
return "mail.empty.scheduled";
|
|
134
135
|
case "archive":
|
|
135
|
-
return "
|
|
136
|
+
return "mail.empty.archive";
|
|
136
137
|
case "trash":
|
|
137
|
-
return "
|
|
138
|
+
return "mail.empty.trash";
|
|
138
139
|
case "spam":
|
|
139
|
-
return "
|
|
140
|
+
return "mail.empty.spam";
|
|
140
141
|
case "all":
|
|
141
|
-
return "
|
|
142
|
+
return "mail.empty.all";
|
|
142
143
|
case "unread":
|
|
143
|
-
return "
|
|
144
|
+
return "mail.empty.unread";
|
|
144
145
|
default:
|
|
145
|
-
return "
|
|
146
|
+
return "mail.empty.default";
|
|
146
147
|
}
|
|
147
148
|
}
|
|
148
149
|
|
|
149
150
|
export function InboxZero() {
|
|
151
|
+
const t = useT();
|
|
150
152
|
const [loaded, setLoaded] = useState(false);
|
|
151
153
|
const isEmbedded = isMcpEmbedSurface();
|
|
152
154
|
|
|
@@ -195,10 +197,10 @@ export function InboxZero() {
|
|
|
195
197
|
{/* Bottom text */}
|
|
196
198
|
<div className="relative mt-auto px-6 pb-6">
|
|
197
199
|
<p className="text-[15px] font-medium text-white/90 drop-shadow-lg">
|
|
198
|
-
|
|
200
|
+
{t("mail.empty.inboxZeroTitle")}
|
|
199
201
|
</p>
|
|
200
202
|
<p className="text-[13px] text-white/60 drop-shadow-lg mt-0.5">
|
|
201
|
-
|
|
203
|
+
{t("mail.empty.inboxZeroSubtitle")}
|
|
202
204
|
</p>
|
|
203
205
|
</div>
|
|
204
206
|
</div>
|
|
@@ -261,6 +263,7 @@ function EmailErrorState({
|
|
|
261
263
|
onRetry: () => unknown;
|
|
262
264
|
containerRef: React.RefObject<HTMLDivElement | null>;
|
|
263
265
|
}) {
|
|
266
|
+
const t = useT();
|
|
264
267
|
const rateLimitRetryMs = isQuotaError ? getRateLimitRetryMs(message) : 0;
|
|
265
268
|
const [cooldownRemaining, setCooldownRemaining] = useState(rateLimitRetryMs);
|
|
266
269
|
const autoRetryFired = useRef(false);
|
|
@@ -305,11 +308,11 @@ function EmailErrorState({
|
|
|
305
308
|
|
|
306
309
|
let buttonLabel: string;
|
|
307
310
|
if (isFetching) {
|
|
308
|
-
buttonLabel = "
|
|
311
|
+
buttonLabel = t("mail.error.retrying");
|
|
309
312
|
} else if (cooldownRemaining > 0) {
|
|
310
|
-
buttonLabel =
|
|
313
|
+
buttonLabel = t("mail.error.tryAgainIn", { seconds: cooldownSeconds });
|
|
311
314
|
} else {
|
|
312
|
-
buttonLabel = "
|
|
315
|
+
buttonLabel = t("mail.error.tryAgain");
|
|
313
316
|
}
|
|
314
317
|
|
|
315
318
|
return (
|
|
@@ -321,12 +324,12 @@ function EmailErrorState({
|
|
|
321
324
|
</div>
|
|
322
325
|
<div className="space-y-1">
|
|
323
326
|
<p className="text-sm font-medium text-foreground">
|
|
324
|
-
{isQuotaError
|
|
327
|
+
{isQuotaError
|
|
328
|
+
? t("mail.error.rateLimitTitle")
|
|
329
|
+
: t("mail.error.loadTitle")}
|
|
325
330
|
</p>
|
|
326
331
|
<p className="text-xs text-muted-foreground">
|
|
327
|
-
{isQuotaError
|
|
328
|
-
? "Too many recent requests to Google. Waiting a moment before retrying."
|
|
329
|
-
: message}
|
|
332
|
+
{isQuotaError ? t("mail.error.rateLimitDescription") : message}
|
|
330
333
|
</p>
|
|
331
334
|
</div>
|
|
332
335
|
<button
|
|
@@ -363,6 +366,7 @@ export function EmailList({
|
|
|
363
366
|
onDraftOpen,
|
|
364
367
|
onNavigateThread,
|
|
365
368
|
}: EmailListProps) {
|
|
369
|
+
const t = useT();
|
|
366
370
|
const navigate = useNavigate();
|
|
367
371
|
const { view = "inbox", threadId } = useParams<{
|
|
368
372
|
view: string;
|
|
@@ -648,9 +652,9 @@ export function EmailList({
|
|
|
648
652
|
setUndoAction(undo);
|
|
649
653
|
toast(
|
|
650
654
|
threadKeys.length > 1
|
|
651
|
-
?
|
|
652
|
-
: "
|
|
653
|
-
{ action: { label: "
|
|
655
|
+
? t("mail.toasts.archivedMany", { count: threadKeys.length })
|
|
656
|
+
: t("mail.toasts.archived"),
|
|
657
|
+
{ action: { label: t("mail.actions.undo"), onClick: undo } },
|
|
654
658
|
);
|
|
655
659
|
for (const t of targets) {
|
|
656
660
|
archiveEmail.mutate({
|
|
@@ -740,9 +744,9 @@ export function EmailList({
|
|
|
740
744
|
setUndoAction(undo);
|
|
741
745
|
toast(
|
|
742
746
|
threadKeys.length > 1
|
|
743
|
-
?
|
|
744
|
-
: "
|
|
745
|
-
{ action: { label: "
|
|
747
|
+
? t("mail.toasts.trashedMany", { count: threadKeys.length })
|
|
748
|
+
: t("mail.toasts.trashed"),
|
|
749
|
+
{ action: { label: t("mail.actions.undo"), onClick: undo } },
|
|
746
750
|
);
|
|
747
751
|
for (const id of emailIds) trashEmail.mutate(id);
|
|
748
752
|
setSelectedIds(new Set());
|
|
@@ -1131,12 +1135,12 @@ export function EmailList({
|
|
|
1131
1135
|
const jobId = getScheduledJobId(thread.latestMessage);
|
|
1132
1136
|
if (!jobId) return;
|
|
1133
1137
|
sendScheduledJobNow.mutate(jobId, {
|
|
1134
|
-
onSuccess: () => toast("
|
|
1138
|
+
onSuccess: () => toast(t("mail.toasts.scheduledSent")),
|
|
1135
1139
|
onError: (error) =>
|
|
1136
1140
|
toast.error(
|
|
1137
1141
|
error instanceof Error
|
|
1138
1142
|
? error.message
|
|
1139
|
-
: "
|
|
1143
|
+
: t("mail.toasts.scheduledSendFailed"),
|
|
1140
1144
|
),
|
|
1141
1145
|
});
|
|
1142
1146
|
};
|
|
@@ -1149,8 +1153,8 @@ export function EmailList({
|
|
|
1149
1153
|
const jobId = getScheduledJobId(thread.latestMessage);
|
|
1150
1154
|
if (!jobId) return;
|
|
1151
1155
|
cancelScheduledJob.mutate(jobId, {
|
|
1152
|
-
onSuccess: () => toast("
|
|
1153
|
-
onError: () => toast.error("
|
|
1156
|
+
onSuccess: () => toast(t("mail.toasts.scheduledCancelled")),
|
|
1157
|
+
onError: () => toast.error(t("mail.toasts.scheduledCancelFailed")),
|
|
1154
1158
|
});
|
|
1155
1159
|
};
|
|
1156
1160
|
|
|
@@ -1202,8 +1206,8 @@ export function EmailList({
|
|
|
1202
1206
|
unarchiveEmail.mutate(id);
|
|
1203
1207
|
};
|
|
1204
1208
|
setUndoAction(undo);
|
|
1205
|
-
toast("
|
|
1206
|
-
action: { label: "
|
|
1209
|
+
toast(t("mail.toasts.archived"), {
|
|
1210
|
+
action: { label: t("mail.actions.undo"), onClick: undo },
|
|
1207
1211
|
});
|
|
1208
1212
|
archiveEmail.mutate({
|
|
1209
1213
|
id,
|
|
@@ -1253,15 +1257,15 @@ export function EmailList({
|
|
|
1253
1257
|
type="button"
|
|
1254
1258
|
onClick={clearSelection}
|
|
1255
1259
|
className="flex size-5 items-center justify-center rounded transition-colors hover:bg-accent hover:text-foreground"
|
|
1256
|
-
aria-label="
|
|
1260
|
+
aria-label={t("mail.selection.clear")}
|
|
1257
1261
|
>
|
|
1258
1262
|
<IconX className="h-3.5 w-3.5" />
|
|
1259
1263
|
</button>
|
|
1260
1264
|
</TooltipTrigger>
|
|
1261
|
-
<TooltipContent>
|
|
1265
|
+
<TooltipContent>{t("mail.selection.clear")}</TooltipContent>
|
|
1262
1266
|
</Tooltip>
|
|
1263
1267
|
<span className="whitespace-nowrap text-xs font-medium text-foreground/80">
|
|
1264
|
-
{selectedIds.size}
|
|
1268
|
+
{t("mail.selection.selected", { count: selectedIds.size })}
|
|
1265
1269
|
</span>
|
|
1266
1270
|
<DropdownMenu>
|
|
1267
1271
|
<Tooltip>
|
|
@@ -1270,13 +1274,13 @@ export function EmailList({
|
|
|
1270
1274
|
<button
|
|
1271
1275
|
type="button"
|
|
1272
1276
|
className="flex size-5 items-center justify-center rounded transition-colors hover:bg-accent hover:text-foreground"
|
|
1273
|
-
aria-label="
|
|
1277
|
+
aria-label={t("mail.selection.actions")}
|
|
1274
1278
|
>
|
|
1275
1279
|
<IconDots className="h-3.5 w-3.5" />
|
|
1276
1280
|
</button>
|
|
1277
1281
|
</DropdownMenuTrigger>
|
|
1278
1282
|
</TooltipTrigger>
|
|
1279
|
-
<TooltipContent>
|
|
1283
|
+
<TooltipContent>{t("mail.selection.actions")}</TooltipContent>
|
|
1280
1284
|
</Tooltip>
|
|
1281
1285
|
<DropdownMenuContent align="end" className="w-56">
|
|
1282
1286
|
<DropdownMenuItem
|
|
@@ -1284,27 +1288,27 @@ export function EmailList({
|
|
|
1284
1288
|
className="gap-2 text-xs"
|
|
1285
1289
|
>
|
|
1286
1290
|
<IconArchive className="h-3.5 w-3.5" />
|
|
1287
|
-
|
|
1291
|
+
{t("mail.actions.archive")}
|
|
1288
1292
|
</DropdownMenuItem>
|
|
1289
1293
|
<DropdownMenuItem
|
|
1290
1294
|
onClick={markFocusedRead}
|
|
1291
1295
|
className="gap-2 text-xs"
|
|
1292
1296
|
>
|
|
1293
1297
|
<IconMailOpened className="h-3.5 w-3.5" />
|
|
1294
|
-
|
|
1298
|
+
{t("mail.actions.markRead")}
|
|
1295
1299
|
</DropdownMenuItem>
|
|
1296
1300
|
<DropdownMenuItem
|
|
1297
1301
|
onClick={markFocusedUnread}
|
|
1298
1302
|
className="gap-2 text-xs"
|
|
1299
1303
|
>
|
|
1300
1304
|
<IconMail className="h-3.5 w-3.5" />
|
|
1301
|
-
|
|
1305
|
+
{t("mail.actions.markUnread")}
|
|
1302
1306
|
</DropdownMenuItem>
|
|
1303
1307
|
{movableLabels.length > 0 && (
|
|
1304
1308
|
<DropdownMenuSub>
|
|
1305
1309
|
<DropdownMenuSubTrigger className="gap-2 text-xs">
|
|
1306
1310
|
<IconFolder className="h-3.5 w-3.5" />
|
|
1307
|
-
|
|
1311
|
+
{t("mail.actions.moveTo")}
|
|
1308
1312
|
</DropdownMenuSubTrigger>
|
|
1309
1313
|
<DropdownMenuSubContent className="max-h-72 w-56 overflow-y-auto">
|
|
1310
1314
|
{movableLabels.map((label) => (
|
|
@@ -1325,34 +1329,34 @@ export function EmailList({
|
|
|
1325
1329
|
className="gap-2 text-xs text-destructive focus:text-destructive"
|
|
1326
1330
|
>
|
|
1327
1331
|
<IconTrash className="h-3.5 w-3.5" />
|
|
1328
|
-
|
|
1332
|
+
{t("mail.actions.moveToTrash")}
|
|
1329
1333
|
</DropdownMenuItem>
|
|
1330
1334
|
)}
|
|
1331
1335
|
<DropdownMenuSeparator />
|
|
1332
|
-
<DropdownMenuLabel>
|
|
1336
|
+
<DropdownMenuLabel>{t("mail.selection.select")}</DropdownMenuLabel>
|
|
1333
1337
|
<DropdownMenuItem onClick={selectAllThreads} className="text-xs">
|
|
1334
|
-
|
|
1338
|
+
{t("mail.selection.all")}
|
|
1335
1339
|
</DropdownMenuItem>
|
|
1336
1340
|
<DropdownMenuItem onClick={clearSelection} className="text-xs">
|
|
1337
|
-
|
|
1341
|
+
{t("mail.selection.none")}
|
|
1338
1342
|
</DropdownMenuItem>
|
|
1339
1343
|
<DropdownMenuItem onClick={selectReadThreads} className="text-xs">
|
|
1340
|
-
|
|
1344
|
+
{t("mail.selection.read")}
|
|
1341
1345
|
</DropdownMenuItem>
|
|
1342
1346
|
<DropdownMenuItem onClick={selectUnreadThreads} className="text-xs">
|
|
1343
|
-
|
|
1347
|
+
{t("mail.views.unread")}
|
|
1344
1348
|
</DropdownMenuItem>
|
|
1345
1349
|
<DropdownMenuItem
|
|
1346
1350
|
onClick={selectStarredThreads}
|
|
1347
1351
|
className="text-xs"
|
|
1348
1352
|
>
|
|
1349
|
-
|
|
1353
|
+
{t("mail.views.starred")}
|
|
1350
1354
|
</DropdownMenuItem>
|
|
1351
1355
|
<DropdownMenuItem
|
|
1352
1356
|
onClick={selectUnstarredThreads}
|
|
1353
1357
|
className="text-xs"
|
|
1354
1358
|
>
|
|
1355
|
-
|
|
1359
|
+
{t("mail.selection.unstarred")}
|
|
1356
1360
|
</DropdownMenuItem>
|
|
1357
1361
|
</DropdownMenuContent>
|
|
1358
1362
|
</DropdownMenu>
|
|
@@ -1417,10 +1421,10 @@ export function EmailList({
|
|
|
1417
1421
|
</svg>
|
|
1418
1422
|
</div>
|
|
1419
1423
|
<p className="text-sm font-medium text-foreground/80">
|
|
1420
|
-
|
|
1424
|
+
{t("mail.empty.noSearchResults", { query: searchQuery })}
|
|
1421
1425
|
</p>
|
|
1422
1426
|
<p className="text-xs text-muted-foreground mt-1">
|
|
1423
|
-
|
|
1427
|
+
{t("mail.empty.tryDifferentKeywords")}
|
|
1424
1428
|
</p>
|
|
1425
1429
|
</div>
|
|
1426
1430
|
</div>
|
|
@@ -1435,10 +1439,10 @@ export function EmailList({
|
|
|
1435
1439
|
<div className="flex flex-1 flex-col items-center justify-center">
|
|
1436
1440
|
<div className="text-center px-8">
|
|
1437
1441
|
<p className="text-sm font-medium text-foreground/80">
|
|
1438
|
-
|
|
1442
|
+
{t("mail.empty.nothingHere")}
|
|
1439
1443
|
</p>
|
|
1440
1444
|
<p className="text-xs text-muted-foreground mt-1">
|
|
1441
|
-
{
|
|
1445
|
+
{t(emptyStateHintKeyForView(view))}
|
|
1442
1446
|
</p>
|
|
1443
1447
|
</div>
|
|
1444
1448
|
</div>
|
|
@@ -1515,7 +1519,7 @@ export function EmailList({
|
|
|
1515
1519
|
{isFetchingNextPage && (
|
|
1516
1520
|
<div className="flex items-center gap-2 text-xs text-muted-foreground">
|
|
1517
1521
|
<Spinner className="size-3 text-muted-foreground" />
|
|
1518
|
-
|
|
1522
|
+
{t("mail.empty.loadingMore")}
|
|
1519
1523
|
</div>
|
|
1520
1524
|
)}
|
|
1521
1525
|
</div>
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
TooltipContent,
|
|
22
22
|
TooltipTrigger,
|
|
23
23
|
} from "@/components/ui/tooltip";
|
|
24
|
+
import { useT } from "@agent-native/core/client";
|
|
24
25
|
|
|
25
26
|
interface EmailListItemProps {
|
|
26
27
|
email: EmailMessage;
|
|
@@ -158,6 +159,7 @@ export const EmailListItem = memo(function EmailListItem({
|
|
|
158
159
|
onSwipeSnooze,
|
|
159
160
|
highlight,
|
|
160
161
|
}: EmailListItemProps) {
|
|
162
|
+
const t = useT();
|
|
161
163
|
const { allAccounts } = useAccountFilter();
|
|
162
164
|
const isMultiAccount = allAccounts.length > 1;
|
|
163
165
|
|
|
@@ -597,7 +599,7 @@ export const EmailListItem = memo(function EmailListItem({
|
|
|
597
599
|
<IconSend className="h-3.5 w-3.5 rtl:-scale-x-100" />
|
|
598
600
|
</button>
|
|
599
601
|
</TooltipTrigger>
|
|
600
|
-
<TooltipContent>
|
|
602
|
+
<TooltipContent>{t("mail.sendLater.sendNow")}</TooltipContent>
|
|
601
603
|
</Tooltip>
|
|
602
604
|
)}
|
|
603
605
|
{onCancelSchedule && (
|
|
@@ -611,7 +613,9 @@ export const EmailListItem = memo(function EmailListItem({
|
|
|
611
613
|
<IconX className="h-3.5 w-3.5" />
|
|
612
614
|
</button>
|
|
613
615
|
</TooltipTrigger>
|
|
614
|
-
<TooltipContent>
|
|
616
|
+
<TooltipContent>
|
|
617
|
+
{t("mail.sendLater.cancelScheduledSend")}
|
|
618
|
+
</TooltipContent>
|
|
615
619
|
</Tooltip>
|
|
616
620
|
)}
|
|
617
621
|
{onTrash && (
|
|
@@ -625,7 +629,7 @@ export const EmailListItem = memo(function EmailListItem({
|
|
|
625
629
|
<IconTrash className="h-3.5 w-3.5" />
|
|
626
630
|
</button>
|
|
627
631
|
</TooltipTrigger>
|
|
628
|
-
<TooltipContent>
|
|
632
|
+
<TooltipContent>{t("mail.actions.moveToTrash")}</TooltipContent>
|
|
629
633
|
</Tooltip>
|
|
630
634
|
)}
|
|
631
635
|
<Tooltip>
|
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
import { useQueryClient } from "@tanstack/react-query";
|
|
35
35
|
import { ensureThread, warmThreads } from "@/lib/thread-cache";
|
|
36
36
|
import { getResolvedTheme } from "@/lib/theme";
|
|
37
|
-
import { appApiPath } from "@agent-native/core/client";
|
|
37
|
+
import { appApiPath, useT } from "@agent-native/core/client";
|
|
38
38
|
import {
|
|
39
39
|
decodeHtmlEntities,
|
|
40
40
|
processHtmlImages,
|
|
@@ -111,6 +111,7 @@ export function EmailThread({
|
|
|
111
111
|
isMaximized?: boolean;
|
|
112
112
|
onToggleMaximize?: () => void;
|
|
113
113
|
}) {
|
|
114
|
+
const t = useT();
|
|
114
115
|
const { view = "inbox", threadId: routeThreadId } = useParams<{
|
|
115
116
|
view: string;
|
|
116
117
|
threadId: string;
|
|
@@ -1211,7 +1212,7 @@ export function EmailThread({
|
|
|
1211
1212
|
className="inline-flex items-center gap-1.5 text-[12px] text-muted-foreground/50 hover:text-muted-foreground transition-colors"
|
|
1212
1213
|
>
|
|
1213
1214
|
<IconExternalLink className="h-3 w-3" />
|
|
1214
|
-
|
|
1215
|
+
{t("mail.thread.viewPullRequest")}
|
|
1215
1216
|
</a>
|
|
1216
1217
|
</TooltipTrigger>
|
|
1217
1218
|
<TooltipContent
|
|
@@ -1219,7 +1220,7 @@ export function EmailThread({
|
|
|
1219
1220
|
align="start"
|
|
1220
1221
|
className="flex items-center gap-1.5 text-[12px] font-medium"
|
|
1221
1222
|
>
|
|
1222
|
-
|
|
1223
|
+
{t("mail.thread.viewPullRequest")}
|
|
1223
1224
|
<kbd className="flex items-center justify-center rounded border border-border/60 bg-muted px-1 text-[10px] text-muted-foreground">
|
|
1224
1225
|
{formatShortcut("cmd")}
|
|
1225
1226
|
</kbd>
|
|
@@ -1238,11 +1239,13 @@ export function EmailThread({
|
|
|
1238
1239
|
className="inline-flex items-center gap-1.5 text-[12px] text-muted-foreground/50 hover:text-muted-foreground transition-colors disabled:opacity-50"
|
|
1239
1240
|
>
|
|
1240
1241
|
<IconMailOff className="h-3 w-3" />
|
|
1241
|
-
{unsubscribing
|
|
1242
|
+
{unsubscribing
|
|
1243
|
+
? t("mail.thread.unsubscribing")
|
|
1244
|
+
: t("mail.thread.unsubscribe")}
|
|
1242
1245
|
</button>
|
|
1243
1246
|
</TooltipTrigger>
|
|
1244
1247
|
<TooltipContent>
|
|
1245
|
-
|
|
1248
|
+
{t("mail.thread.unsubscribeTooltip")}
|
|
1246
1249
|
</TooltipContent>
|
|
1247
1250
|
</Tooltip>
|
|
1248
1251
|
)}
|
|
@@ -1679,6 +1682,7 @@ const ExpandedMessageCard = forwardRef<
|
|
|
1679
1682
|
},
|
|
1680
1683
|
ref,
|
|
1681
1684
|
) {
|
|
1685
|
+
const t = useT();
|
|
1682
1686
|
const [showDetails, setShowDetails] = useState(false);
|
|
1683
1687
|
const senderName = email.from.name || email.from.email;
|
|
1684
1688
|
const recipients = [
|
|
@@ -1960,7 +1964,7 @@ const ExpandedMessageCard = forwardRef<
|
|
|
1960
1964
|
className="flex items-center gap-1.5 text-xs text-muted-foreground hover:text-foreground"
|
|
1961
1965
|
>
|
|
1962
1966
|
<IconDownload className="h-3 w-3" />
|
|
1963
|
-
|
|
1967
|
+
{t("mail.thread.downloadAll")}
|
|
1964
1968
|
</button>
|
|
1965
1969
|
)}
|
|
1966
1970
|
</div>
|
|
@@ -2070,6 +2074,7 @@ function PlainTextBody({
|
|
|
2070
2074
|
searchTerm?: string;
|
|
2071
2075
|
activeLocalIdx?: number | null;
|
|
2072
2076
|
}) {
|
|
2077
|
+
const t = useT();
|
|
2073
2078
|
const [showQuoted, setShowQuoted] = useState(false);
|
|
2074
2079
|
const [showSig, setShowSig] = useState(false);
|
|
2075
2080
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
@@ -2169,7 +2174,7 @@ function PlainTextBody({
|
|
|
2169
2174
|
{hasSig && !showSig && !forceShowAll && (
|
|
2170
2175
|
<button
|
|
2171
2176
|
type="button"
|
|
2172
|
-
aria-label="
|
|
2177
|
+
aria-label={t("mail.thread.showSignature")}
|
|
2173
2178
|
onClick={() => setShowSig(true)}
|
|
2174
2179
|
className="mt-1 inline-flex h-6 w-6 items-center justify-center rounded text-muted-foreground/50 transition-colors hover:bg-accent hover:text-muted-foreground"
|
|
2175
2180
|
>
|
|
@@ -2179,7 +2184,7 @@ function PlainTextBody({
|
|
|
2179
2184
|
{hasQuoted && !showQuoted && !forceShowAll && (showSig || !hasSig) && (
|
|
2180
2185
|
<button
|
|
2181
2186
|
type="button"
|
|
2182
|
-
aria-label="
|
|
2187
|
+
aria-label={t("mail.thread.showQuotedText")}
|
|
2183
2188
|
onClick={() => setShowQuoted(true)}
|
|
2184
2189
|
className="mt-1 inline-flex h-6 w-6 items-center justify-center rounded text-muted-foreground/50 transition-colors hover:bg-accent hover:text-muted-foreground"
|
|
2185
2190
|
>
|
|
@@ -2541,6 +2546,7 @@ function HtmlEmailBody({
|
|
|
2541
2546
|
searchTerm?: string;
|
|
2542
2547
|
activeLocalIdx?: number | null;
|
|
2543
2548
|
}) {
|
|
2549
|
+
const t = useT();
|
|
2544
2550
|
const frameHostRef = useRef<HTMLDivElement>(null);
|
|
2545
2551
|
const iframeRef = useRef<HTMLIFrameElement>(null);
|
|
2546
2552
|
const [height, setHeight] = useState(200);
|
|
@@ -2977,7 +2983,7 @@ function HtmlEmailBody({
|
|
|
2977
2983
|
if (lightened) el.setAttribute("color", lightened);
|
|
2978
2984
|
});
|
|
2979
2985
|
|
|
2980
|
-
// Transform dark text color rules in <style> blocks
|
|
2986
|
+
// Transform dark text color rules in <style> blocks // i18n-ignore
|
|
2981
2987
|
doc.querySelectorAll("style").forEach((tag) => {
|
|
2982
2988
|
const text = tag.textContent || "";
|
|
2983
2989
|
tag.textContent = text.replace(
|
|
@@ -3287,8 +3293,8 @@ function HtmlEmailBody({
|
|
|
3287
3293
|
<IconPhoto className="h-3.5 w-3.5 shrink-0 text-muted-foreground/60" />
|
|
3288
3294
|
<span>
|
|
3289
3295
|
{isEmbedded
|
|
3290
|
-
? "
|
|
3291
|
-
: "
|
|
3296
|
+
? t("mail.thread.remoteImagesHidden")
|
|
3297
|
+
: t("mail.thread.imagesBlocked")}
|
|
3292
3298
|
</span>
|
|
3293
3299
|
{!isEmbedded && (
|
|
3294
3300
|
<>
|
|
@@ -3296,14 +3302,16 @@ function HtmlEmailBody({
|
|
|
3296
3302
|
onClick={() => setShowImagesForThread(true)}
|
|
3297
3303
|
className="text-primary hover:text-primary/80 font-medium transition-colors"
|
|
3298
3304
|
>
|
|
3299
|
-
|
|
3305
|
+
{t("mail.thread.showImages")}
|
|
3300
3306
|
</button>
|
|
3301
3307
|
{senderEmail && (
|
|
3302
3308
|
<button
|
|
3303
3309
|
onClick={handleAlwaysTrust}
|
|
3304
3310
|
className="text-muted-foreground/60 hover:text-muted-foreground font-medium transition-colors"
|
|
3305
3311
|
>
|
|
3306
|
-
|
|
3312
|
+
{t("mail.thread.alwaysFrom", {
|
|
3313
|
+
domain: senderEmail.split("@")[1],
|
|
3314
|
+
})}
|
|
3307
3315
|
</button>
|
|
3308
3316
|
)}
|
|
3309
3317
|
</>
|
|
@@ -3321,7 +3329,7 @@ function HtmlEmailBody({
|
|
|
3321
3329
|
colorScheme: useDarkIframeCss ? "dark" : "light",
|
|
3322
3330
|
borderRadius: hasDesignedBg && isDark ? "6px" : undefined,
|
|
3323
3331
|
}}
|
|
3324
|
-
title="
|
|
3332
|
+
title={t("mail.thread.emailContent")}
|
|
3325
3333
|
/>
|
|
3326
3334
|
</div>
|
|
3327
3335
|
);
|
|
@@ -3348,6 +3356,7 @@ function ThreadSearchBar({
|
|
|
3348
3356
|
totalMatches: number;
|
|
3349
3357
|
inputRef: React.RefObject<HTMLInputElement | null>;
|
|
3350
3358
|
}) {
|
|
3359
|
+
const t = useT();
|
|
3351
3360
|
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
|
3352
3361
|
if (e.key === "Escape") {
|
|
3353
3362
|
e.preventDefault();
|
|
@@ -3368,7 +3377,7 @@ function ThreadSearchBar({
|
|
|
3368
3377
|
value={query}
|
|
3369
3378
|
onChange={(e) => onChange(e.target.value)}
|
|
3370
3379
|
onKeyDown={handleKeyDown}
|
|
3371
|
-
placeholder="
|
|
3380
|
+
placeholder={t("mail.thread.searchConversation")}
|
|
3372
3381
|
className="flex-1 bg-transparent text-[13px] text-foreground placeholder:text-muted-foreground/40 outline-none min-w-0"
|
|
3373
3382
|
autoComplete="off"
|
|
3374
3383
|
spellCheck={false}
|
|
@@ -3376,7 +3385,7 @@ function ThreadSearchBar({
|
|
|
3376
3385
|
{query && (
|
|
3377
3386
|
<span className="text-[12px] text-muted-foreground/50 tabular-nums shrink-0 select-none">
|
|
3378
3387
|
{totalMatches === 0
|
|
3379
|
-
? "
|
|
3388
|
+
? t("mail.search.noMatches")
|
|
3380
3389
|
: `${matchIdx + 1} / ${totalMatches}`}
|
|
3381
3390
|
</span>
|
|
3382
3391
|
)}
|