import { Platform, Text as NativeText, View } from "react-native";
import { cn } from "../../lib/cn";
import { MOBILE_CODE_SURFACE } from "../../lib/typography";
import type { ReviewRenderableLineRow } from "./reviewModel";
import type { ReviewHighlightedToken } from "./shikiReviewHighlighter";
export const REVIEW_MONO_FONT_FAMILY = Platform.select({
ios: "ui-monospace",
android: "monospace",
default: "monospace",
});
export const REVIEW_DIFF_LINE_HEIGHT = MOBILE_CODE_SURFACE.rowHeight;
const REVIEW_DELETE_STRIPE_COUNT = REVIEW_DIFF_LINE_HEIGHT / 2;
export function renderVisibleWhitespace(value: string): string {
const expandedTabs = value.replace(/\t/g, " ");
return expandedTabs.replace(/^( +)/, (leading) => leading.replaceAll(" ", "\u00A0"));
}
export function changeTone(change: ReviewRenderableLineRow["change"]): string {
if (change === "add") return "bg-emerald-500/10";
if (change === "delete") return "bg-rose-500/10";
return "bg-card";
}
export function changeBarTone(change: ReviewRenderableLineRow["change"]): string {
if (change === "add") return "bg-emerald-400";
if (change === "delete") return "bg-rose-400";
return "bg-border/50";
}
function diffHighlightColor(change: ReviewRenderableLineRow["change"]): string | undefined {
if (change === "add") return "rgba(16, 185, 129, 0.24)";
if (change === "delete") return "rgba(244, 63, 94, 0.24)";
return undefined;
}
export function ReviewChangeBar(props: { readonly change: ReviewRenderableLineRow["change"] }) {
if (props.change === "delete") {
return (
{Array.from({ length: REVIEW_DELETE_STRIPE_COUNT }, (_, index) => (
))}
);
}
return (
);
}
export function DiffTokenText(props: {
readonly tokens: ReadonlyArray | null;
readonly fallback: string;
readonly change?: ReviewRenderableLineRow["change"];
readonly className?: string;
}) {
if (!props.tokens || props.tokens.length === 0) {
return (
{renderVisibleWhitespace(props.fallback || " ")}
);
}
return (
{(() => {
let offset = 0;
return props.tokens.map((token) => {
const start = offset;
offset += token.content.length;
const fontWeight =
token.fontStyle !== null && (token.fontStyle & 2) === 2
? ("700" as const)
: ("500" as const);
const fontStyle =
token.fontStyle !== null && (token.fontStyle & 1) === 1
? ("italic" as const)
: ("normal" as const);
return (
{token.content.length > 0 ? renderVisibleWhitespace(token.content) : " "}
);
});
})()}
);
}