import * as React from "react" import { CircleAlertIcon, CheckIcon, FileCode2Icon, RotateCcwIcon, SaveIcon, SearchIcon, } from "@workspace/ui/components/icon" import { useDevtoolLocalization } from "./devtool-localization" import { formatMessageOrigin, MessageCopyMenu } from "./message-copy-menu" import { createMessageNavigationModel, MessageNavigation, } from "./message-navigation" import { useOptionalMessageRepository } from "./message-repository" import type { DevtoolMessage, DevtoolMessagePackage, MessageRepository, } from "./types" // oxlint-disable-next-line import/no-unassigned-import -- Loads the message panel stylesheet. import "./message-panel.css" type LoadState = | { status: "loading" } | { error: Error; status: "error" } | { messages: readonly DevtoolMessage[] packages: readonly DevtoolMessagePackage[] status: "ready" } export interface MessagePanelProps { className?: string locale: string refreshToken?: unknown repository?: MessageRepository } function getMessageSearchText(message: DevtoolMessage) { return [ message.id, message.source, message.translation, message.packageName, ...message.comments, ...message.origins.map((origin) => origin.file), ] .join("\n") .toLocaleLowerCase() } function MessageEditor({ locale, message, onSave, }: { locale: string message: DevtoolMessage onSave: (translation: string) => Promise }) { const { messages } = useDevtoolLocalization() const [translation, setTranslation] = React.useState(message.translation) const [saveState, setSaveState] = React.useState< "idle" | "saving" | "saved" | "error" >("idle") const repositoryTranslationRef = React.useRef(message.translation) const submittedTranslationRef = React.useRef(undefined) const isEditable = message.editable const isDirty = translation !== message.translation const primaryOrigin = message.origins[0] React.useEffect(() => { if (repositoryTranslationRef.current === message.translation) { return } repositoryTranslationRef.current = message.translation setTranslation(message.translation) if (submittedTranslationRef.current === message.translation) { submittedTranslationRef.current = undefined return } setSaveState("idle") }, [message.translation]) React.useEffect(() => { if (saveState !== "saved") { return } const timeout = window.setTimeout(() => setSaveState("idle"), 1600) return () => window.clearTimeout(timeout) }, [saveState]) const handleSave = async () => { if (!isEditable || !isDirty || saveState === "saving") { return } setSaveState("saving") submittedTranslationRef.current = translation try { await onSave(translation) setSaveState("saved") } catch { submittedTranslationRef.current = undefined setSaveState("error") } } const handleReset = () => { submittedTranslationRef.current = undefined setTranslation(message.translation) setSaveState("idle") } return (
{message.id}
{messages.messagePanel.source} {message.sourceLocale}

{message.source || message.id}