mirror of
https://github.com/block/goose.git
synced 2026-07-17 12:56:20 +02:00
Transform ticker into Matrix notification system
- Extended TickerItem interface with priority, actionable, notification, and invitation types - Added Matrix-specific notification functions: - addSessionInvitation() - for session invites - addMessageNotification() - for new messages - addSessionJoined/Left() - for user activity - addConnectionStatus() - for Matrix connection state - addSessionWaiting() - for sessions awaiting participants - Updated default items to show Matrix notifications instead of system stats - Added demo notification system in AppLayout with realistic Matrix scenarios - Focused route notifications on Matrix-related sections only - Creates authentic collaborative workspace notification experience
This commit is contained in:
@@ -328,9 +328,34 @@ const AppLayoutContent: React.FC<AppLayoutProps> = ({ setIsGoosehintsModalOpen }
|
||||
return () => window.removeEventListener('open-sidecar-localhost', handler);
|
||||
}, [sidecar]);
|
||||
|
||||
// Add ticker updates based on navigation changes and system events
|
||||
// Add Matrix-related notifications and demo content
|
||||
useEffect(() => {
|
||||
// Simulate Matrix notifications for demo purposes
|
||||
const demoNotifications = [
|
||||
() => ticker.addSessionInvitation('project-gamma', 'david'),
|
||||
() => ticker.addMessageNotification('eve', 'design-team', 2),
|
||||
() => ticker.addSessionJoined('frank', 'standup-meeting'),
|
||||
() => ticker.addSessionWaiting('code-review-session', 3),
|
||||
() => ticker.addConnectionStatus('connected'),
|
||||
];
|
||||
|
||||
// Add initial demo notification
|
||||
setTimeout(() => {
|
||||
const randomNotification = demoNotifications[Math.floor(Math.random() * demoNotifications.length)];
|
||||
randomNotification();
|
||||
}, 2000);
|
||||
|
||||
// Add periodic demo notifications
|
||||
const interval = setInterval(() => {
|
||||
const randomNotification = demoNotifications[Math.floor(Math.random() * demoNotifications.length)];
|
||||
randomNotification();
|
||||
}, 15000); // Every 15 seconds
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, []); // Removed ticker from dependencies
|
||||
|
||||
// Add route change notifications
|
||||
useEffect(() => {
|
||||
// Update ticker when route changes
|
||||
const routeNames: Record<string, string> = {
|
||||
'/': 'hub',
|
||||
'/pair': 'chat',
|
||||
@@ -344,41 +369,15 @@ const AppLayoutContent: React.FC<AppLayoutProps> = ({ setIsGoosehintsModalOpen }
|
||||
};
|
||||
|
||||
const currentRoute = routeNames[location.pathname] || 'unknown';
|
||||
ticker.addItem({
|
||||
text: `section: ${currentRoute}`,
|
||||
type: 'info'
|
||||
});
|
||||
}, [location.pathname]); // Removed ticker from dependencies
|
||||
|
||||
// Add ticker updates for sidecar changes
|
||||
useEffect(() => {
|
||||
if (sidecar?.activeViews.length) {
|
||||
|
||||
// Only add route notifications for Matrix-related sections
|
||||
if (currentRoute === 'sessions' || currentRoute === 'peers' || currentRoute === 'channels') {
|
||||
ticker.addItem({
|
||||
text: `sidecars active: ${sidecar.activeViews.length}`,
|
||||
type: 'success'
|
||||
text: `navigated to ${currentRoute}`,
|
||||
type: 'info'
|
||||
});
|
||||
}
|
||||
}, [sidecar?.activeViews.length]); // Removed ticker from dependencies
|
||||
|
||||
// Add periodic system status updates
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
const memoryUsage = Math.floor(Math.random() * 30) + 40; // Mock memory usage 40-70%
|
||||
const activeConnections = Math.floor(Math.random() * 5) + 1; // Mock 1-6 connections
|
||||
|
||||
ticker.addItem({
|
||||
text: `mem: ${memoryUsage}%`,
|
||||
type: memoryUsage > 60 ? 'warning' : 'info'
|
||||
});
|
||||
|
||||
ticker.addItem({
|
||||
text: `connections: ${activeConnections}`,
|
||||
type: 'neutral'
|
||||
});
|
||||
}, 30000); // Update every 30 seconds
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, []); // Removed ticker from dependencies
|
||||
}, [location.pathname]); // Removed ticker from dependencies
|
||||
|
||||
// Determine layout direction based on navigation position (only for push mode)
|
||||
const isHorizontalNav = navigationPosition === 'top' || navigationPosition === 'bottom';
|
||||
|
||||
@@ -4,8 +4,10 @@ import { cn } from '../utils';
|
||||
interface TickerItem {
|
||||
id: string;
|
||||
text: string;
|
||||
type?: 'info' | 'warning' | 'error' | 'success' | 'neutral';
|
||||
type?: 'info' | 'warning' | 'error' | 'success' | 'neutral' | 'notification' | 'invitation';
|
||||
timestamp?: Date;
|
||||
priority?: 'low' | 'medium' | 'high';
|
||||
actionable?: boolean;
|
||||
}
|
||||
|
||||
interface NotificationTickerProps {
|
||||
@@ -16,12 +18,12 @@ interface NotificationTickerProps {
|
||||
}
|
||||
|
||||
const defaultItems: TickerItem[] = [
|
||||
{ id: '1', text: 'goose ai agent online', type: 'success' },
|
||||
{ id: '2', text: 'system status: operational', type: 'info' },
|
||||
{ id: '3', text: 'extensions loaded: 12', type: 'info' },
|
||||
{ id: '4', text: 'last sync: 2 min ago', type: 'neutral' },
|
||||
{ id: '5', text: 'memory usage: 45%', type: 'info' },
|
||||
{ id: '6', text: 'active sessions: 3', type: 'success' },
|
||||
{ id: '1', text: 'matrix: connected', type: 'success', priority: 'high' },
|
||||
{ id: '2', text: 'session invitation from alice: project-alpha', type: 'invitation', priority: 'high', actionable: true },
|
||||
{ id: '3', text: 'new message from bob in dev-team', type: 'notification', priority: 'medium', actionable: true },
|
||||
{ id: '4', text: 'charlie joined project-beta', type: 'success', priority: 'low' },
|
||||
{ id: '5', text: 'session waiting: code-review (2 participants)', type: 'invitation', priority: 'high', actionable: true },
|
||||
{ id: '6', text: '3 new messages from team in general', type: 'notification', priority: 'medium', actionable: true },
|
||||
];
|
||||
|
||||
export const NotificationTicker: React.FC<NotificationTickerProps> = ({
|
||||
@@ -212,12 +214,82 @@ export const useNotificationTicker = () => {
|
||||
});
|
||||
}, [addItem]);
|
||||
|
||||
// Matrix-specific notification functions
|
||||
const addSessionInvitation = useCallback((sessionName: string, inviterName: string) => {
|
||||
addItem({
|
||||
text: `session invitation from ${inviterName.toLowerCase()}: ${sessionName.toLowerCase()}`,
|
||||
type: 'invitation',
|
||||
priority: 'high',
|
||||
actionable: true,
|
||||
});
|
||||
}, [addItem]);
|
||||
|
||||
const addMessageNotification = useCallback((senderName: string, sessionName: string, messageCount: number = 1) => {
|
||||
const messageText = messageCount === 1
|
||||
? `new message from ${senderName.toLowerCase()} in ${sessionName.toLowerCase()}`
|
||||
: `${messageCount} new messages from ${senderName.toLowerCase()} in ${sessionName.toLowerCase()}`;
|
||||
|
||||
addItem({
|
||||
text: messageText,
|
||||
type: 'notification',
|
||||
priority: 'medium',
|
||||
actionable: true,
|
||||
});
|
||||
}, [addItem]);
|
||||
|
||||
const addSessionJoined = useCallback((userName: string, sessionName: string) => {
|
||||
addItem({
|
||||
text: `${userName.toLowerCase()} joined ${sessionName.toLowerCase()}`,
|
||||
type: 'success',
|
||||
priority: 'low',
|
||||
});
|
||||
}, [addItem]);
|
||||
|
||||
const addSessionLeft = useCallback((userName: string, sessionName: string) => {
|
||||
addItem({
|
||||
text: `${userName.toLowerCase()} left ${sessionName.toLowerCase()}`,
|
||||
type: 'neutral',
|
||||
priority: 'low',
|
||||
});
|
||||
}, [addItem]);
|
||||
|
||||
const addConnectionStatus = useCallback((status: 'connected' | 'disconnected' | 'reconnecting') => {
|
||||
const statusMessages = {
|
||||
connected: { text: 'matrix: connected', type: 'success' as const },
|
||||
disconnected: { text: 'matrix: disconnected', type: 'error' as const },
|
||||
reconnecting: { text: 'matrix: reconnecting...', type: 'warning' as const },
|
||||
};
|
||||
|
||||
const { text, type } = statusMessages[status];
|
||||
addItem({
|
||||
text,
|
||||
type,
|
||||
priority: 'high',
|
||||
});
|
||||
}, [addItem]);
|
||||
|
||||
const addSessionWaiting = useCallback((sessionName: string, participantCount: number) => {
|
||||
addItem({
|
||||
text: `session waiting: ${sessionName.toLowerCase()} (${participantCount} participants)`,
|
||||
type: 'invitation',
|
||||
priority: 'high',
|
||||
actionable: true,
|
||||
});
|
||||
}, [addItem]);
|
||||
|
||||
return {
|
||||
items,
|
||||
addItem,
|
||||
removeItem,
|
||||
clearItems,
|
||||
updateSystemStatus,
|
||||
// Matrix-specific functions
|
||||
addSessionInvitation,
|
||||
addMessageNotification,
|
||||
addSessionJoined,
|
||||
addSessionLeft,
|
||||
addConnectionStatus,
|
||||
addSessionWaiting,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user