Use a shadcn dialog for the announcement (#3604)

This commit is contained in:
Chris Estreich 2025-05-14 09:00:55 -07:00 committed by GitHub
parent a4e2b66351
commit 35fd4e68cd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 86 additions and 100 deletions

View file

@ -0,0 +1,5 @@
---
"roo-cline": patch
---
Update announcement to use a @shadcn/ui dialog

View file

@ -20,7 +20,7 @@ async function main() {
fs.writeFileSync("src/exports/types.ts", types.join("\n\n"))
await $`npx tsup src/exports/interface.ts --dts-only -d out`
await $`npx tsup src/exports/interface.ts -d out`
fs.copyFileSync("out/interface.d.ts", "src/exports/roo-code.d.ts")
await $`npx prettier --write src/exports/types.ts src/exports/roo-code.d.ts`

View file

@ -1,113 +1,94 @@
import { VSCodeButton, VSCodeLink } from "@vscode/webview-ui-toolkit/react"
import { memo } from "react"
import { useAppTranslation } from "@/i18n/TranslationContext"
import { useState, memo } from "react"
import { Trans } from "react-i18next"
import { VSCodeLink } from "@vscode/webview-ui-toolkit/react"
import { useAppTranslation } from "@src/i18n/TranslationContext"
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@src/components/ui"
interface AnnouncementProps {
hideAnnouncement: () => void
}
/*
You must update the latestAnnouncementId in ClineProvider for new announcements to show to users. This new id will be compared with whats in state for the 'last announcement shown', and if it's different then the announcement will render. As soon as an announcement is shown, the id will be updated in state. This ensures that announcements are not shown more than once, even if the user doesn't close it themselves.
*/
/**
* You must update the `latestAnnouncementId` in ClineProvider for new
* announcements to show to users. This new id will be compared with what's in
* state for the 'last announcement shown', and if it's different then the
* announcement will render. As soon as an announcement is shown, the id will be
* updated in state. This ensures that announcements are not shown more than
* once, even if the user doesn't close it themselves.
*/
const Announcement = ({ hideAnnouncement }: AnnouncementProps) => {
const { t } = useAppTranslation()
const discordLink = (
<VSCodeLink
href="https://discord.gg/roocode"
onClick={(e) => {
e.preventDefault()
window.postMessage(
{ type: "action", action: "openExternal", data: { url: "https://discord.gg/roocode" } },
"*",
)
}}>
Discord
</VSCodeLink>
)
const redditLink = (
<VSCodeLink
href="https://reddit.com/r/RooCode"
onClick={(e) => {
e.preventDefault()
window.postMessage(
{ type: "action", action: "openExternal", data: { url: "https://reddit.com/r/RooCode" } },
"*",
)
}}>
Reddit
</VSCodeLink>
)
const [open, setOpen] = useState(true)
return (
<div className="flex flex-col justify-center absolute top-0 bottom-0 left-0 right-0 z-50 p-10 bg-black/50">
<div
style={{
backgroundColor: "var(--vscode-editor-background)",
borderRadius: "3px",
padding: "12px 16px",
margin: "5px 15px 5px 15px",
position: "relative",
flexShrink: 0,
}}>
<VSCodeButton
appearance="icon"
onClick={hideAnnouncement}
title={t("chat:announcement.hideButton")}
style={{ position: "absolute", top: "8px", right: "8px" }}>
<span className="codicon codicon-close"></span>
</VSCodeButton>
<h2 style={{ margin: "0 0 8px" }}>{t("chat:announcement.title")}</h2>
<Dialog
open={open}
onOpenChange={(open) => {
setOpen(open)
<p style={{ margin: "5px 0px" }}>{t("chat:announcement.description")}</p>
<h3 style={{ margin: "12px 0 5px", fontSize: "14px" }}>{t("chat:announcement.whatsNew")}</h3>
<ul style={{ margin: "5px 0" }}>
<li>
{" "}
<Trans
i18nKey="chat:announcement.feature1"
components={{
bold: <b />,
code: <code />,
}}
/>
</li>
<li>
{" "}
<Trans
i18nKey="chat:announcement.feature2"
components={{
bold: <b />,
code: <code />,
}}
/>
</li>
<li>
{" "}
<Trans
i18nKey="chat:announcement.feature3"
components={{
bold: <b />,
code: <code />,
}}
/>
</li>
</ul>
<p style={{ margin: "10px 0px 0px" }}>
if (!open) {
hideAnnouncement()
}
}}>
<DialogContent className="max-w-96">
<DialogHeader>
<DialogTitle>{t("chat:announcement.title")}</DialogTitle>
<DialogDescription>{t("chat:announcement.description")}</DialogDescription>
</DialogHeader>
<div>
<h3>{t("chat:announcement.whatsNew")}</h3>
<ul className="space-y-2">
<li>
{" "}
<Trans i18nKey="chat:announcement.feature1" components={{ bold: <b />, code: <code /> }} />
</li>
<li>
{" "}
<Trans i18nKey="chat:announcement.feature2" components={{ bold: <b />, code: <code /> }} />
</li>
<li>
{" "}
<Trans i18nKey="chat:announcement.feature3" components={{ bold: <b />, code: <code /> }} />
</li>
</ul>
<Trans
i18nKey="chat:announcement.detailsDiscussLinks"
components={{
discordLink: discordLink,
redditLink: redditLink,
}}
components={{ discordLink: <DiscordLink />, redditLink: <RedditLink /> }}
/>
</p>
</div>
</div>
</div>
</DialogContent>
</Dialog>
)
}
const DiscordLink = () => (
<VSCodeLink
href="https://discord.gg/roocode"
onClick={(e) => {
e.preventDefault()
window.postMessage(
{ type: "action", action: "openExternal", data: { url: "https://discord.gg/roocode" } },
"*",
)
}}>
Discord
</VSCodeLink>
)
const RedditLink = () => (
<VSCodeLink
href="https://reddit.com/r/RooCode"
onClick={(e) => {
e.preventDefault()
window.postMessage(
{ type: "action", action: "openExternal", data: { url: "https://reddit.com/r/RooCode" } },
"*",
)
}}>
Reddit
</VSCodeLink>
)
export default memo(Announcement)

View file

@ -40,7 +40,7 @@ function DialogContent({ className, children, ...props }: React.ComponentProps<t
<DialogPrimitive.Content
data-slot="dialog-content"
className={cn(
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
"bg-vscode-editor-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
className,
)}
{...props}>
@ -78,7 +78,7 @@ function DialogTitle({ className, ...props }: React.ComponentProps<typeof Dialog
return (
<DialogPrimitive.Title
data-slot="dialog-title"
className={cn("text-lg leading-none font-semibold", className)}
className={cn("text-lg leading-none font-semibold my-0", className)}
{...props}
/>
)
@ -88,7 +88,7 @@ function DialogDescription({ className, ...props }: React.ComponentProps<typeof
return (
<DialogPrimitive.Description
data-slot="dialog-description"
className={cn("text-muted-foreground text-sm", className)}
className={cn("text-muted-foreground text-sm my-0", className)}
{...props}
/>
)