From 174ef96e661403d8015d4dac292ab6ff1070aac0 Mon Sep 17 00:00:00 2001 From: snehasishcodes Date: Mon, 7 Sep 2026 19:11:44 +0530 Subject: [PATCH 1/2] fix(mobile): parse file content JSON for preview --- apps/mobile/lib/file-browser.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/apps/mobile/lib/file-browser.ts b/apps/mobile/lib/file-browser.ts index 2c65962..0a4fb43 100644 --- a/apps/mobile/lib/file-browser.ts +++ b/apps/mobile/lib/file-browser.ts @@ -61,7 +61,16 @@ export async function readFileContent(url: string, token: string, path: string): }, }) if (!res.ok) throw new Error(`Failed to read file (${res.status})`) - const text = await res.text() + const raw = await res.text() + let text = raw + try { + const data = JSON.parse(raw) as { content?: unknown; text?: unknown; data?: unknown } + if (typeof data.content === "string") text = data.content + else if (typeof data.text === "string") text = data.text + else if (typeof data.data === "string") text = data.data + } catch { + text = raw + } return text.length > MAX_CONTENT_BYTES ? text.slice(0, MAX_CONTENT_BYTES) : text } From de0701efb2e9a9a7040689dccf91765482f08a69 Mon Sep 17 00:00:00 2001 From: snehasishcodes Date: Mon, 7 Sep 2026 21:22:51 +0530 Subject: [PATCH 2/2] fix(mobile): pure file preview with line numbers and header copy --- .../mobile/app/project/[projectId]/viewer.tsx | 28 ++++++++-- apps/mobile/components/code-block.tsx | 54 ++++++++++++++++++- 2 files changed, 77 insertions(+), 5 deletions(-) diff --git a/apps/mobile/app/project/[projectId]/viewer.tsx b/apps/mobile/app/project/[projectId]/viewer.tsx index bdcc65f..86b1b13 100644 --- a/apps/mobile/app/project/[projectId]/viewer.tsx +++ b/apps/mobile/app/project/[projectId]/viewer.tsx @@ -3,7 +3,10 @@ import { ActivityIndicator, ScrollView, View } from "react-native" import { useLocalSearchParams, useRouter } from "expo-router" import { useSafeAreaInsets } from "react-native-safe-area-context" import { useColorScheme } from "nativewind" +import * as Clipboard from "expo-clipboard" import ArrowLeftIcon from "lucide-react-native/dist/esm/icons/arrow-left" +import CheckIcon from "lucide-react-native/dist/esm/icons/check" +import CopyIcon from "lucide-react-native/dist/esm/icons/copy" import FileQuestionIcon from "lucide-react-native/dist/esm/icons/file-question" import { Button } from "@/components/ui/button" import { Text } from "@/components/ui/text" @@ -31,6 +34,14 @@ export default function ViewerPage() { const [truncated, setTruncated] = useState(false) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) + const [copied, setCopied] = useState(false) + + const copyFile = useCallback(async () => { + if (!content) return + await Clipboard.setStringAsync(content) + setCopied(true) + setTimeout(() => setCopied(false), 1500) + }, [content]) const binary = useMemo(() => isBinaryPath(filePath), [filePath]) const language = useMemo(() => languageFromPath(filePath), [filePath]) @@ -83,9 +94,18 @@ export default function ViewerPage() { {directory || "/"} {!loading && content !== null && ( - - {language} - + )} @@ -114,7 +134,7 @@ export default function ViewerPage() { className="flex-1" contentContainerStyle={{ padding: 12, paddingBottom: insets.bottom + 20 }} > - + {truncated && ( Preview limited to the first {MAX_LINES.toLocaleString()} lines. diff --git a/apps/mobile/components/code-block.tsx b/apps/mobile/components/code-block.tsx index 3141a18..f2475cb 100644 --- a/apps/mobile/components/code-block.tsx +++ b/apps/mobile/components/code-block.tsx @@ -20,9 +20,11 @@ interface CodeBlockProps { text: string language?: string theme: "light" | "dark" + header?: boolean + lineNumbers?: boolean } -export function CodeBlock({ text, language, theme }: CodeBlockProps) { +export function CodeBlock({ text, language, theme, header = true, lineNumbers = false }: CodeBlockProps) { const [copied, setCopied] = useState(false) ensurePrismLanguages() const prismTheme = theme === "dark" ? themes.oneDark : themes.github @@ -36,6 +38,56 @@ export function CodeBlock({ text, language, theme }: CodeBlockProps) { setTimeout(() => setCopied(false), 1500) } + if (!header) { + return ( + + + {({ tokens, getTokenProps }) => ( + + {tokens.map((line, lineIndex) => ( + + {lineNumbers && ( + + {lineIndex + 1} + + )} + + {line.map((token, tokenIndex) => { + const tokenProps = getTokenProps({ token }) + return ( + + {tokenProps.children} + + ) + })} + + + ))} + + )} + + + ) + } + return (