Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion components/automation/FlowViewer.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from "react";
import { View, Text, ScrollView } from "react-native";
import { useTranslation } from "react-i18next";

/* ------------------------------------------------------------------ */
/* Props */
Expand Down Expand Up @@ -46,6 +47,7 @@ function findEdgesForNode(
* Read-only flow diagram showing automation nodes and edges.
*/
export function FlowViewer({ nodes, edges }: FlowViewerProps) {
const { t } = useTranslation();
if (nodes.length === 0) {
return (
<View className="items-center py-8">
Expand All @@ -57,7 +59,7 @@ export function FlowViewer({ nodes, edges }: FlowViewerProps) {
}

return (
<ScrollView className="flex-1" accessibilityRole="list" accessibilityLabel="Flow diagram">
<ScrollView className="flex-1" accessibilityRole="list" accessibilityLabel={t("a11y.flowDiagram")}>
<View className="gap-3 px-4 py-3">
{nodes.map((node, index) => {
const outEdges = findEdgesForNode(node.id, edges);
Expand Down
4 changes: 3 additions & 1 deletion components/common/ScreenHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { View, Text, Pressable } from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { ChevronLeft } from "lucide-react-native";
import { useRouter } from "expo-router";
import { useTranslation } from "react-i18next";
import { useThemeColors } from "~/lib/theme-colors";

export interface ScreenHeaderProps {
Expand Down Expand Up @@ -45,6 +46,7 @@ export function ScreenHeader({
}: ScreenHeaderProps) {
const router = useRouter();
const insets = useSafeAreaInsets();
const { t } = useTranslation();
const { accent } = useThemeColors();

const handleBack = () => {
Expand Down Expand Up @@ -73,7 +75,7 @@ export function ScreenHeader({
onPress={handleBack}
hitSlop={8}
accessibilityRole="button"
accessibilityLabel="Go back"
accessibilityLabel={t("a11y.goBack")}
className="h-11 w-11 items-center justify-center rounded-full active:bg-muted"
>
<ChevronLeft size={26} color={accent} />
Expand Down
4 changes: 3 additions & 1 deletion components/common/SearchBar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from "react";
import { Pressable, TextInput, View } from "react-native";
import { Search, X } from "lucide-react-native";
import { useTranslation } from "react-i18next";
import { cn } from "~/lib/utils";

export interface SearchBarProps {
Expand All @@ -18,6 +19,7 @@ export function SearchBar({
debounceMs = 300,
className,
}: SearchBarProps) {
const { t } = useTranslation();
const [localValue, setLocalValue] = React.useState(value);
const timerRef = React.useRef<ReturnType<typeof setTimeout> | null>(null);

Expand Down Expand Up @@ -70,7 +72,7 @@ export function SearchBar({
onPress={handleClear}
hitSlop={8}
accessibilityRole="button"
accessibilityLabel="Clear search"
accessibilityLabel={t("a11y.clearSearch")}
className="rounded-full p-1 active:opacity-60"
>
<X size={16} className="text-muted-foreground" />
Expand Down
4 changes: 3 additions & 1 deletion components/common/SkeletonDashboard.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from "react";
import { View } from "react-native";
import { useTranslation } from "react-i18next";

export interface SkeletonDashboardProps {
cards?: number;
Expand All @@ -10,8 +11,9 @@ export function SkeletonDashboard({
cards = 4,
testID = "skeleton-dashboard",
}: SkeletonDashboardProps) {
const { t } = useTranslation();
return (
<View testID={testID} accessibilityLabel="Loading dashboard" accessibilityRole="progressbar">
<View testID={testID} accessibilityLabel={t("a11y.loadingDashboard")} accessibilityRole="progressbar">
<View className="flex-row flex-wrap px-2 py-2">
{Array.from({ length: cards }).map((_, i) => (
<View key={i} testID={`${testID}-card-${i}`} className="w-1/2 p-2">
Expand Down
4 changes: 3 additions & 1 deletion components/common/SkeletonDetail.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from "react";
import { View } from "react-native";
import { useTranslation } from "react-i18next";

export interface SkeletonDetailProps {
sections?: number;
Expand All @@ -12,8 +13,9 @@ export function SkeletonDetail({
fieldsPerSection = 4,
testID = "skeleton-detail",
}: SkeletonDetailProps) {
const { t } = useTranslation();
return (
<View testID={testID} accessibilityLabel="Loading detail" accessibilityRole="progressbar">
<View testID={testID} accessibilityLabel={t("a11y.loadingDetail")} accessibilityRole="progressbar">
{/* Header skeleton */}
<View className="px-4 py-5">
<View className="h-6 w-2/3 rounded bg-muted animate-pulse mb-2" />
Expand Down
4 changes: 3 additions & 1 deletion components/common/SkeletonForm.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from "react";
import { View } from "react-native";
import { useTranslation } from "react-i18next";

export interface SkeletonFormProps {
fields?: number;
Expand All @@ -10,8 +11,9 @@ export function SkeletonForm({
fields = 5,
testID = "skeleton-form",
}: SkeletonFormProps) {
const { t } = useTranslation();
return (
<View testID={testID} accessibilityLabel="Loading form" accessibilityRole="progressbar">
<View testID={testID} accessibilityLabel={t("a11y.loadingForm")} accessibilityRole="progressbar">
{Array.from({ length: fields }).map((_, i) => (
<View key={i} testID={`${testID}-field-${i}`} className="px-4 py-3">
{/* Label skeleton */}
Expand Down
4 changes: 3 additions & 1 deletion components/common/SkeletonList.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from "react";
import { View } from "react-native";
import { useTranslation } from "react-i18next";

export interface SkeletonListProps {
rows?: number;
Expand All @@ -8,8 +9,9 @@ export interface SkeletonListProps {
}

export function SkeletonList({ rows = 5, showAvatar = true, testID = "skeleton-list" }: SkeletonListProps) {
const { t } = useTranslation();
return (
<View testID={testID} accessibilityLabel="Loading list" accessibilityRole="progressbar">
<View testID={testID} accessibilityLabel={t("a11y.loadingList")} accessibilityRole="progressbar">
{Array.from({ length: rows }).map((_, i) => (
<View key={i} className="flex-row items-center px-4 py-3 border-b border-border/30">
{showAvatar && (
Expand Down
4 changes: 2 additions & 2 deletions components/renderers/SwipeableRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export function SwipeableRow({
onEdit();
}}
accessibilityRole="button"
accessibilityLabel="Edit"
accessibilityLabel={t("common.edit")}
className="items-center justify-center bg-blue-600 active:opacity-80"
style={{ width: ACTION_WIDTH }}
>
Expand All @@ -94,7 +94,7 @@ export function SwipeableRow({
onDelete();
}}
accessibilityRole="button"
accessibilityLabel="Delete"
accessibilityLabel={t("common.delete")}
className="items-center justify-center bg-red-600 active:opacity-80"
style={{ width: ACTION_WIDTH }}
>
Expand Down
4 changes: 3 additions & 1 deletion components/ui/BottomSheet.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from "react";
import { Modal, Pressable, Text, View } from "react-native";
import { useTranslation } from "react-i18next";
import { cn } from "~/lib/utils";

export interface BottomSheetProps {
Expand All @@ -17,6 +18,7 @@ export function BottomSheet({
children,
className,
}: BottomSheetProps) {
const { t } = useTranslation();
return (
<Modal
visible={open}
Expand All @@ -27,7 +29,7 @@ export function BottomSheet({
<Pressable
className="flex-1 bg-black/50"
accessibilityRole="button"
accessibilityLabel="Close"
accessibilityLabel={t("common.close")}
onPress={() => onOpenChange(false)}
/>

Expand Down
2 changes: 1 addition & 1 deletion components/ui/Reasoning.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export function Reasoning({
className="flex-row items-center gap-2 px-2.5 py-2 active:bg-muted"
onPress={() => setOpen((o) => !o)}
accessibilityRole="button"
accessibilityLabel="Reasoning"
accessibilityLabel={t("ai.reasoning")}
accessibilityState={{ expanded: open }}
>
<Brain size={13} color="#64748b" />
Expand Down
4 changes: 3 additions & 1 deletion components/ui/Toast.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from "react";
import { Pressable, Text, View } from "react-native";
import { X } from "lucide-react-native";
import { useTranslation } from "react-i18next";
import * as Haptics from "expo-haptics";
import { cn } from "~/lib/utils";

Expand Down Expand Up @@ -35,6 +36,7 @@ const variantTextStyles: Record<ToastVariant, string> = {
};

export function ToastProvider({ children }: { children: React.ReactNode }) {
const { t: tr } = useTranslation();
const [toasts, setToasts] = React.useState<ToastItem[]>([]);

const dismiss = React.useCallback((id: number) => {
Expand Down Expand Up @@ -90,7 +92,7 @@ export function ToastProvider({ children }: { children: React.ReactNode }) {
onPress={() => dismiss(t.id)}
hitSlop={8}
accessibilityRole="button"
accessibilityLabel="Dismiss"
accessibilityLabel={tr("a11y.dismiss")}
className="active:opacity-70"
>
<X size={16} className={variantTextStyles[t.variant]} />
Expand Down
4 changes: 3 additions & 1 deletion components/ui/ToolInvocations.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useState } from "react";
import { View, Text, Pressable } from "react-native";
import { ChevronRight, ChevronDown, Wrench, Check, Loader } from "lucide-react-native";
import { useTranslation } from "react-i18next";
import { cn } from "~/lib/utils";
import type { ToolInvocation } from "~/lib/ai-chat";

Expand Down Expand Up @@ -87,9 +88,10 @@ export function ToolInvocations({
tools: ToolInvocation[];
className?: string;
}) {
const { t } = useTranslation();
if (!tools || tools.length === 0) return null;
return (
<View className={cn("mb-1 gap-1", className)} accessibilityLabel="Tool activity">
<View className={cn("mb-1 gap-1", className)} accessibilityLabel={t("a11y.toolActivity")}>
{tools.map((t) => (
<ToolRow key={t.id} tool={t} />
))}
Expand Down
6 changes: 4 additions & 2 deletions components/workflow/StateMachineViewer.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from "react";
import { View, Text, ScrollView } from "react-native";
import { useTranslation } from "react-i18next";

/* ------------------------------------------------------------------ */
/* Props */
Expand Down Expand Up @@ -96,6 +97,7 @@ export function StateMachineViewer({
currentState,
scrollable = true,
}: StateMachineViewerProps) {
const { t: tr } = useTranslation();
if (states.length === 0) {
return (
<View className="items-center py-8">
Expand Down Expand Up @@ -144,14 +146,14 @@ export function StateMachineViewer({

if (!scrollable) {
return (
<View accessibilityRole="list" accessibilityLabel="State machine diagram">
<View accessibilityRole="list" accessibilityLabel={tr("a11y.stateMachineDiagram")}>
{body}
</View>
);
}

return (
<ScrollView className="flex-1" accessibilityRole="list" accessibilityLabel="State machine diagram">
<ScrollView className="flex-1" accessibilityRole="list" accessibilityLabel={tr("a11y.stateMachineDiagram")}>
{body}
</ScrollView>
);
Expand Down
12 changes: 12 additions & 0 deletions locales/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,18 @@
"flowsDesc": "لا توجد تدفقات أتمتة على هذا الخادم بعد.",
"flowCount": "{{count}} تدفقات"
},
"a11y": {
"goBack": "رجوع",
"clearSearch": "مسح البحث",
"dismiss": "إغلاق",
"toolActivity": "نشاط الأداة",
"flowDiagram": "مخطط التدفق",
"stateMachineDiagram": "مخطط آلة الحالة",
"loadingList": "جارٍ تحميل القائمة",
"loadingDashboard": "جارٍ تحميل لوحة المعلومات",
"loadingDetail": "جارٍ تحميل التفاصيل",
"loadingForm": "جارٍ تحميل النموذج"
},
"nav": {
"home": "الرئيسية",
"search": "بحث",
Expand Down
12 changes: 12 additions & 0 deletions locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,18 @@
"flowsDesc": "This server has no automation flows yet.",
"flowCount": "{{count}} flows"
},
"a11y": {
"goBack": "Go back",
"clearSearch": "Clear search",
"dismiss": "Dismiss",
"toolActivity": "Tool activity",
"flowDiagram": "Flow diagram",
"stateMachineDiagram": "State machine diagram",
"loadingList": "Loading list",
"loadingDashboard": "Loading dashboard",
"loadingDetail": "Loading detail",
"loadingForm": "Loading form"
},
"nav": {
"home": "Home",
"search": "Search",
Expand Down
12 changes: 12 additions & 0 deletions locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,18 @@
"flowsDesc": "此服务器还没有自动化流程。",
"flowCount": "{{count}} 个流程"
},
"a11y": {
"goBack": "返回",
"clearSearch": "清除搜索",
"dismiss": "关闭",
"toolActivity": "工具活动",
"flowDiagram": "流程图",
"stateMachineDiagram": "状态机图",
"loadingList": "正在加载列表",
"loadingDashboard": "正在加载仪表盘",
"loadingDetail": "正在加载详情",
"loadingForm": "正在加载表单"
},
"nav": {
"home": "首页",
"search": "搜索",
Expand Down
Loading