SHARE_PAGE_COMPONENT.md

Overview

The SharePage component is a comprehensive full-page interface that manages shared assistant access with authentication, access control, and collaborative features. It provides the main user experience for accessing shared AI assistants with different permission levels and states.

Purpose

  • Shared Assistant Access: Main interface for accessing shared AI assistants
  • Access Control Management: Enforces permission-based access with multiple authorization levels
  • Authentication Integration: Handles user login state and Firebase authentication
  • Tool Configuration: Manages dynamic tool enabling/disabling for shared sessions
  • Assistant Duplication: Allows users to create personal copies of shared assistants

Key Features

Authentication States

  • not-logged-in: Anonymous user access (if permitted)
  • receiver: Authenticated user with access permissions
  • admin: Assistant creator with full management rights

Access Control Types

  • Private: Only creator access
  • Domain-based: Users from specific email domains
  • Link-based: Anyone with the link
  • Public: Open access

UI States

  • Loading: Initial authentication and permission checking
  • Access Denied: Permission-based rejection with helpful messaging
  • Welcome: Initial assistant introduction before chat begins
  • Main Chat: Full chat interface with sidebar and artifact support

Component Interface

interface SharePageProps {
  config: ConfigProps;
}

// Key destructured properties from config:
{
  name,               // Assistant display name
  avatar,             // Assistant avatar URL
  assistantId,        // Unique assistant identifier
  accessControl,      // Permission configuration
  adminEmail,         // Creator's email
  senderName,         // Creator's display name
  initialMessage,     // Welcome message
  initialInstructions,// Assistant instructions
  initialDocuments,   // Attached documents
  tools,              // Available tools array
  toolConfigs,        // Tool configuration objects
  templateId          // Template identifier
}

Core Functionality

1. Authentication Management

// Firebase auth state listener
useEffect(() => {
  const unsubscribe = FirebaseService.onAuthStateChange((user) => {
    setCurrentUser(user);
    setIsAuthInitialized(true);
  });
  return () => unsubscribe();
}, []);

// User state determination
if (currentUser) {
  setUserState(currentUser.email === adminEmail ? 'admin' : 'receiver');
} else {
  setUserState('not-logged-in');
}

2. Access Control Logic

// Access validation
const accessGranted = checkAccess(localAccessControl, currentUser, adminEmail);
setHasAccess(accessGranted);

// Usage tracking (only once per session)
if (accessGranted && !hasIncrementedUsageRef.current && assistantId) {
  FirebaseService.incrementAssistantUsage(assistantId);
  hasIncrementedUsageRef.current = true;
}

3. Tool Configuration Persistence

// Session-based tool state management
const handleToolsChange = useCallback((updatedTools: string[]) => {
  setActiveTools(updatedTools);
  
  // Save to sessionStorage for persistence
  if (assistantId) {
    sessionStorage.setItem(`assistant_tools_${assistantId}`, JSON.stringify(updatedTools));
  }
}, [assistantId]);

// Restore tools on component mount
useEffect(() => {
  if (assistantId) {
    const savedTools = sessionStorage.getItem(`assistant_tools_${assistantId}`);
    if (savedTools) {
      setActiveTools(JSON.parse(savedTools));
    }
  }
}, [assistantId]);

4. Assistant Duplication

// Create personal copy of shared assistant
const handleDuplication = async () => {
  const duplicateData = createDuplicateConfig({
    assistantId,
    templateId,
    name,
    avatar,
    ownerEmail: currentUser.email || '',
    initialMessage,
    initialInstructions,
    tools: activeTools,
    toolConfigs,
    initialDocuments: initialDocuments || [],
    accessControl: { type: 'private' } // Always private for copies
  }, currentUser.uid, currentUser.email || '');
  
  const newAssistantId = await FirebaseService.createAssistant(duplicateData);
  if (newAssistantId) {
    window.location.href = `/assistant/${newAssistantId}`;
  }
};

5. Sharing Settings Management

// Admin-only access control updates
const handleAccessChange = useCallback(async (newAccessControl: AccessControl) => {
  if (userState !== 'admin' || !assistantId) {
    toast({
      title: "Not authorized",
      description: "Only the assistant's creator can change sharing settings.",
      variant: "destructive"
    });
    return;
  }

  await FirebaseService.updateAssistant(assistantId, {
    accessControl: newAccessControl
  });
  
  setLocalAccessControl(newAccessControl);
}, [userState, assistantId, toast]);

UI Components Integration

Main Layout Structure

return (
  <ArtifactProvider assistantId={assistantId}>
    <TooltipProvider delayDuration={100}>
      <div className="flex min-h-screen bg-gray-50">
        {/* Aurora background animation */}
        <Aurora
          colorStops={["#FF9966", "#FFD93D", "#FF6B6B"]}
          blend={0.9}
          amplitude={0.8}
          speed={0.3}
        />
        
        <SidebarProvider defaultOpen={false}>
          <AppSidebar {...sidebarProps} />
          
          <main className="flex-1 overflow-hidden">
            {/* Header with sharing status */}
            <div className="flex items-center justify-between p-4 border-b">
              <SidebarTrigger />
              <h1>{name || 'Messages'}</h1>
              <SharingStatus 
                accessControl={localAccessControl}
                isEditable={userState === 'admin'}
                onAccessChange={handleAccessChange}
              />
              <ArtifactToggleButton tools={activeTools} />
            </div>
            
            {/* Chat interface with artifacts */}
            <ChatWithArtifacts sharedProps={sharedProps} />
          </main>
        </SidebarProvider>
      </div>
    </TooltipProvider>
  </ArtifactProvider>
);

Access Denied UI

const AccessDeniedContent = () => {
  const message = getAccessDeniedMessage(localAccessControl, !!currentUser, adminEmail);
  return (
    <Card className="max-w-xl w-full shadow-lg">
      <CardHeader className="text-center">
        <Avatar className="h-28 w-28">
          <AvatarImage src={avatar} alt={name} />
          <AvatarFallback>
            <Shield className="h-12 w-12 text-destructive" />
          </AvatarFallback>
        </Avatar>
        <h2>Access Denied</h2>
        <p>Cannot access '{name}'</p>
      </CardHeader>
      <CardContent>
        <p>{message}</p>
        <Button asChild>
          <Link href="/"><Home /> Go Home</Link>
        </Button>
      </CardContent>
    </Card>
  );
};

State Management

Key State Variables

const [accepted, setAccepted] = useState(false);           // Welcome acceptance
const [userState, setUserState] = useState('not-logged-in'); // User role
const [currentUser, setCurrentUser] = useState<User | null>(null); // Firebase user
const [isAuthInitialized, setIsAuthInitialized] = useState(false); // Auth ready
const [showLoginDialog, setShowLoginDialog] = useState(false); // Login modal
const [hasAccess, setHasAccess] = useState<boolean | null>(null); // Permission state
const [localAccessControl, setLocalAccessControl] = useState<AccessControl>(); // Sharing config
const [activeTools, setActiveTools] = useState<string[]>(tools || []); // Tool selection

Conditional Rendering Logic

// Loading state (waiting for auth + access check)
if (hasAccess === null) {
  return <LoadingSpinner />;
}

// Access denied state
if (hasAccess === false) {
  return <AccessDeniedContent />;
}

// Welcome screen (before chat begins)
if (!accepted) {
  return <WelcomeMessage onAccept={() => setAccepted(true)} />;
}

// Main chat interface
return <ChatInterface />;

Dependencies

External Libraries

  • Firebase: Authentication and data persistence
  • Lucide React: Icon components
  • Next.js: Routing and Link components

Internal Components

  • EmissaryOptimized: Core chat functionality
  • AppSidebar: Navigation and tool configuration
  • ChatWithArtifacts: Chat interface with artifact display
  • SharingStatus: Access control management UI
  • WelcomeMessage: Initial assistant introduction
  • LoginDialog: Authentication modal

Utility Functions

  • checkAccess(): Permission validation logic
  • getAccessDeniedMessage(): Context-aware error messaging
  • createDuplicateConfig(): Assistant duplication logic

Usage Examples

Basic Shared Assistant Access

// Page component receiving config from server
export default function SharedAssistantPage({ assistantConfig }) {
  return <SharePage config={assistantConfig} />;
}

Integration with Next.js Dynamic Routes

// pages/assistant/[assistantId]/page.tsx
export default async function AssistantPage({ params }) {
  const config = await getAssistantConfig(params.assistantId);
  
  if (!config) {
    return <NotFound />;
  }
  
  return <SharePage config={config} />;
}

Security Considerations

  1. Access Control Validation: Always validates permissions on both client and server
  2. Usage Tracking: Increments usage counters only once per authorized session
  3. Admin-Only Operations: Restricts sharing settings changes to assistant creators
  4. Session Persistence: Safely stores tool preferences without exposing sensitive data
  5. Authentication State: Properly handles auth initialization and user state changes

Performance Optimizations

  1. Memoized Props: Uses useMemo for expensive prop calculations
  2. Callback Optimization: useCallback for event handlers to prevent re-renders
  3. Conditional Rendering: Efficient state-based UI switching
  4. Session Storage: Persists tool configurations without server requests
  5. Single Auth Listener: Prevents multiple Firebase auth subscriptions

Error Handling

  1. Authentication Errors: Graceful handling of Firebase auth failures
  2. Access Control Updates: Toast notifications for permission errors
  3. Usage Tracking: Non-critical error logging without blocking UX
  4. Tool Configuration: Fallback to defaults if session storage fails
  5. Assistant Duplication: User-friendly error messages for creation failures

Testing Considerations

  • Authentication States: Mock Firebase auth for different user types
  • Access Control: Test all permission combinations
  • Tool Configuration: Verify session storage persistence
  • UI States: Test loading, denied, welcome, and main interfaces
  • Assistant Duplication: Mock FirebaseService methods
  • Error Scenarios: Test network failures and invalid configurations