Skip to content

Commit 606fa01

Browse files
committed
Better sharing feedback
1 parent 9bd5256 commit 606fa01

File tree

25 files changed

+437
-49
lines changed

25 files changed

+437
-49
lines changed

packages/types/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export * from "./message.js"
1313
export * from "./mode.js"
1414
export * from "./model.js"
1515
export * from "./provider-settings.js"
16+
export * from "./sharing.js"
1617
export * from "./telemetry.js"
1718
export * from "./terminal.js"
1819
export * from "./tool.js"

packages/types/src/sharing.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/**
2+
* Types related to task sharing functionality
3+
*/
4+
5+
/**
6+
* Visibility options for sharing tasks
7+
*/
8+
export type ShareVisibility = "organization" | "public"

src/core/webview/webviewMessageHandler.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,13 @@ export const webviewMessageHandler = async (
242242
? "common:info.public_share_link_copied"
243243
: "common:info.organization_share_link_copied"
244244
vscode.window.showInformationMessage(t(messageKey))
245+
246+
// Send success feedback to webview for inline display
247+
await provider.postMessageToWebview({
248+
type: "shareTaskSuccess",
249+
visibility,
250+
text: result.shareUrl,
251+
})
245252
} else {
246253
// Handle error
247254
const errorMessage = result.error || "Failed to create share link"

src/shared/ExtensionMessage.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import type {
99
ClineMessage,
1010
OrganizationAllowList,
1111
CloudUserInfo,
12+
ShareVisibility,
1213
} from "@roo-code/types"
1314

1415
import { GitCommit } from "../utils/git"
@@ -97,6 +98,7 @@ export interface ExtensionMessage {
9798
| "codebaseIndexConfig"
9899
| "marketplaceInstallResult"
99100
| "marketplaceData"
101+
| "shareTaskSuccess"
100102
text?: string
101103
payload?: any // Add a generic payload for now, can refine later
102104
action?:
@@ -145,6 +147,7 @@ export interface ExtensionMessage {
145147
tab?: string
146148
marketplaceItems?: MarketplaceItem[]
147149
marketplaceInstalledMetadata?: MarketplaceInstalledMetadata
150+
visibility?: ShareVisibility
148151
}
149152

150153
export type ExtensionState = Pick<

src/shared/WebviewMessage.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type {
66
ModeConfig,
77
InstallMarketplaceItemOptions,
88
MarketplaceItem,
9+
ShareVisibility,
910
} from "@roo-code/types"
1011
import { marketplaceItemSchema } from "@roo-code/types"
1112

@@ -172,6 +173,7 @@ export interface WebviewMessage {
172173
| "fetchMarketplaceData"
173174
| "switchTab"
174175
| "profileThresholds"
176+
| "shareTaskSuccess"
175177
text?: string
176178
tab?: "settings" | "history" | "mcp" | "modes" | "chat" | "marketplace" | "account"
177179
disabled?: boolean
@@ -209,7 +211,7 @@ export interface WebviewMessage {
209211
mpItem?: MarketplaceItem
210212
mpInstallOptions?: InstallMarketplaceItemOptions
211213
config?: Record<string, any> // Add config to the payload
212-
visibility?: "organization" | "public" // For share visibility
214+
visibility?: ShareVisibility // For share visibility
213215
}
214216

215217
export const checkoutDiffPayloadSchema = z.object({

webview-ui/src/components/chat/ShareButton.tsx

Lines changed: 68 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { useState, useEffect, useRef } from "react"
22
import { useTranslation } from "react-i18next"
33

4-
import type { HistoryItem } from "@roo-code/types"
4+
import type { HistoryItem, ShareVisibility } from "@roo-code/types"
55
import { TelemetryEventName } from "@roo-code/types"
66

77
import { vscode } from "@/utils/vscode"
@@ -30,6 +30,7 @@ interface ShareButtonProps {
3030
export const ShareButton = ({ item, disabled = false }: ShareButtonProps) => {
3131
const [shareDropdownOpen, setShareDropdownOpen] = useState(false)
3232
const [connectModalOpen, setConnectModalOpen] = useState(false)
33+
const [shareSuccess, setShareSuccess] = useState<{ visibility: ShareVisibility; url: string } | null>(null)
3334
const { t } = useTranslation()
3435
const { sharingEnabled, cloudIsAuthenticated, cloudUserInfo } = useExtensionState()
3536
const wasUnauthenticatedRef = useRef(false)
@@ -47,7 +48,31 @@ export const ShareButton = ({ item, disabled = false }: ShareButtonProps) => {
4748
}
4849
}, [cloudIsAuthenticated, sharingEnabled])
4950

50-
const handleShare = (visibility: "organization" | "public") => {
51+
// Listen for share success messages from the extension
52+
useEffect(() => {
53+
const handleMessage = (event: MessageEvent) => {
54+
const message = event.data
55+
if (message.type === "shareTaskSuccess") {
56+
setShareSuccess({
57+
visibility: message.visibility,
58+
url: message.text,
59+
})
60+
// Auto-hide success message and close popover after 5 seconds
61+
setTimeout(() => {
62+
setShareSuccess(null)
63+
setShareDropdownOpen(false)
64+
}, 5000)
65+
}
66+
}
67+
68+
window.addEventListener("message", handleMessage)
69+
return () => window.removeEventListener("message", handleMessage)
70+
}, [])
71+
72+
const handleShare = (visibility: ShareVisibility) => {
73+
// Clear any previous success state
74+
setShareSuccess(null)
75+
5176
// Send telemetry for share action
5277
if (visibility === "organization") {
5378
telemetryClient.capture(TelemetryEventName.SHARE_ORGANIZATION_CLICKED)
@@ -59,7 +84,7 @@ export const ShareButton = ({ item, disabled = false }: ShareButtonProps) => {
5984
type: "shareCurrentTask",
6085
visibility,
6186
})
62-
setShareDropdownOpen(false)
87+
// Don't close the dropdown immediately - let success message show first
6388
}
6489

6590
const handleConnectToCloud = () => {
@@ -130,40 +155,53 @@ export const ShareButton = ({ item, disabled = false }: ShareButtonProps) => {
130155
</Button>
131156
</PopoverTrigger>
132157
<PopoverContent className="w-56 p-0" align="start">
133-
<Command>
134-
<CommandList>
135-
<CommandGroup>
136-
{cloudUserInfo?.organizationName && (
137-
<CommandItem
138-
onSelect={() => handleShare("organization")}
139-
className="cursor-pointer">
158+
{shareSuccess ? (
159+
<div className="p-3">
160+
<div className="flex items-center gap-2 text-sm text-green-600 dark:text-green-400">
161+
<span className="codicon codicon-check"></span>
162+
<span>
163+
{shareSuccess.visibility === "public"
164+
? t("chat:task.shareSuccessPublic")
165+
: t("chat:task.shareSuccessOrganization")}
166+
</span>
167+
</div>
168+
</div>
169+
) : (
170+
<Command>
171+
<CommandList>
172+
<CommandGroup>
173+
{cloudUserInfo?.organizationName && (
174+
<CommandItem
175+
onSelect={() => handleShare("organization")}
176+
className="cursor-pointer">
177+
<div className="flex items-center gap-2">
178+
<span className="codicon codicon-organization text-sm"></span>
179+
<div className="flex flex-col">
180+
<span className="text-sm">
181+
{t("chat:task.shareWithOrganization")}
182+
</span>
183+
<span className="text-xs text-vscode-descriptionForeground">
184+
{t("chat:task.shareWithOrganizationDescription")}
185+
</span>
186+
</div>
187+
</div>
188+
</CommandItem>
189+
)}
190+
<CommandItem onSelect={() => handleShare("public")} className="cursor-pointer">
140191
<div className="flex items-center gap-2">
141-
<span className="codicon codicon-organization text-sm"></span>
192+
<span className="codicon codicon-globe text-sm"></span>
142193
<div className="flex flex-col">
143-
<span className="text-sm">
144-
{t("chat:task.shareWithOrganization")}
145-
</span>
194+
<span className="text-sm">{t("chat:task.sharePublicly")}</span>
146195
<span className="text-xs text-vscode-descriptionForeground">
147-
{t("chat:task.shareWithOrganizationDescription")}
196+
{t("chat:task.sharePubliclyDescription")}
148197
</span>
149198
</div>
150199
</div>
151200
</CommandItem>
152-
)}
153-
<CommandItem onSelect={() => handleShare("public")} className="cursor-pointer">
154-
<div className="flex items-center gap-2">
155-
<span className="codicon codicon-globe text-sm"></span>
156-
<div className="flex flex-col">
157-
<span className="text-sm">{t("chat:task.sharePublicly")}</span>
158-
<span className="text-xs text-vscode-descriptionForeground">
159-
{t("chat:task.sharePubliclyDescription")}
160-
</span>
161-
</div>
162-
</div>
163-
</CommandItem>
164-
</CommandGroup>
165-
</CommandList>
166-
</Command>
201+
</CommandGroup>
202+
</CommandList>
203+
</Command>
204+
)}
167205
</PopoverContent>
168206
</Popover>
169207
) : (

0 commit comments

Comments
 (0)