mirror of https://github.com/kortix-ai/suna.git
Merge pull request #1011 from kubet/feat/usage-snack
fix: snack stream re rendering other component and closing issue
This commit is contained in:
commit
91b9cff776
|
@ -509,8 +509,11 @@ export default function ThreadPage({
|
|||
setDebugMode(debugParam === 'true');
|
||||
}, [searchParams]);
|
||||
|
||||
const hasCheckedUpgradeDialog = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (initialLoadCompleted && subscriptionData) {
|
||||
if (initialLoadCompleted && subscriptionData && !hasCheckedUpgradeDialog.current) {
|
||||
hasCheckedUpgradeDialog.current = true;
|
||||
const hasSeenUpgradeDialog = localStorage.getItem('suna_upgrade_dialog_displayed');
|
||||
const isFreeTier = subscriptionStatus === 'no_subscription';
|
||||
if (!hasSeenUpgradeDialog && isFreeTier && !isLocalMode()) {
|
||||
|
|
|
@ -125,6 +125,7 @@ export const ChatInput = forwardRef<ChatInputHandles, ChatInputProps>(
|
|||
const [configModalTab, setConfigModalTab] = useState('integrations');
|
||||
const [registryDialogOpen, setRegistryDialogOpen] = useState(false);
|
||||
const [showSnackbar, setShowSnackbar] = useState(defaultShowSnackbar);
|
||||
const [userDismissedUsage, setUserDismissedUsage] = useState(false);
|
||||
const [billingModalOpen, setBillingModalOpen] = useState(false);
|
||||
|
||||
const {
|
||||
|
@ -161,12 +162,12 @@ export const ChatInput = forwardRef<ChatInputHandles, ChatInputProps>(
|
|||
|
||||
// Auto-show usage preview when we have subscription data
|
||||
useEffect(() => {
|
||||
if (shouldShowUsage && defaultShowSnackbar !== false && (showSnackbar === false || showSnackbar === defaultShowSnackbar)) {
|
||||
if (shouldShowUsage && defaultShowSnackbar !== false && !userDismissedUsage && (showSnackbar === false || showSnackbar === defaultShowSnackbar)) {
|
||||
setShowSnackbar('upgrade');
|
||||
} else if (!shouldShowUsage && showSnackbar !== false) {
|
||||
setShowSnackbar(false);
|
||||
}
|
||||
}, [subscriptionData, showSnackbar, defaultShowSnackbar, shouldShowUsage, subscriptionStatus, showToLowCreditUsers]);
|
||||
}, [subscriptionData, showSnackbar, defaultShowSnackbar, shouldShowUsage, subscriptionStatus, showToLowCreditUsers, userDismissedUsage]);
|
||||
|
||||
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
|
@ -340,7 +341,7 @@ export const ChatInput = forwardRef<ChatInputHandles, ChatInputProps>(
|
|||
showToolPreview={showToolPreview}
|
||||
showUsagePreview={showSnackbar}
|
||||
subscriptionData={subscriptionData}
|
||||
onCloseUsage={() => setShowSnackbar(false)}
|
||||
onCloseUsage={() => { setShowSnackbar(false); setUserDismissedUsage(true); }}
|
||||
onOpenUpgrade={() => setBillingModalOpen(true)}
|
||||
isVisible={showToolPreview || !!showSnackbar}
|
||||
/>
|
||||
|
|
|
@ -56,6 +56,8 @@ export const ChatSnack: React.FC<ChatSnackProps> = ({
|
|||
notifications.push('usage');
|
||||
}
|
||||
|
||||
|
||||
|
||||
const totalNotifications = notifications.length;
|
||||
const hasMultiple = totalNotifications > 1;
|
||||
|
||||
|
@ -136,13 +138,15 @@ export const ChatSnack: React.FC<ChatSnackProps> = ({
|
|||
type={showUsagePreview}
|
||||
subscriptionData={subscriptionData}
|
||||
onClose={() => {
|
||||
// First close the usage notification
|
||||
if (onCloseUsage) onCloseUsage();
|
||||
// If there are other notifications, switch to them
|
||||
if (totalNotifications > 1) {
|
||||
const remainingNotifications = notifications.filter(n => n !== 'usage');
|
||||
if (remainingNotifications.length > 0) {
|
||||
setCurrentView(0); // Switch to first remaining notification
|
||||
}
|
||||
|
||||
// Check what notifications will remain after closing usage
|
||||
const willHaveToolNotification = showToolPreview && toolCalls.length > 0;
|
||||
|
||||
// If there will be other notifications, switch to them
|
||||
if (willHaveToolNotification) {
|
||||
setCurrentView(0); // Switch to tool notification
|
||||
}
|
||||
}}
|
||||
hasMultiple={hasMultiple}
|
||||
|
|
|
@ -84,7 +84,7 @@ export const UsagePreview: React.FC<UsagePreviewProps> = ({
|
|||
<div className="flex-1 min-w-0">
|
||||
<motion.div className="flex items-center gap-2 mb-1">
|
||||
<h4 className="text-sm font-medium text-foreground truncate">
|
||||
Upgrade for more usage
|
||||
Upgrade for more usage & better AI Models
|
||||
</h4>
|
||||
</motion.div>
|
||||
|
||||
|
@ -124,8 +124,8 @@ export const UsagePreview: React.FC<UsagePreviewProps> = ({
|
|||
</button>
|
||||
)}
|
||||
|
||||
<Button value='ghost' data-close-click className="bg-transparent hover:bg-transparent flex-shrink-0" onClick={onClose}>
|
||||
<X className="h-4 w-4 text-muted-foreground group-hover:text-foreground transition-colors" />
|
||||
<Button variant="ghost" size="icon" className="h-8 w-8 flex-shrink-0 hover:bg-muted/50" onClick={(e) => { e.stopPropagation(); onClose?.(); }}>
|
||||
<X className="h-4 w-4 text-muted-foreground hover:text-foreground transition-colors" />
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue