File size: 5,728 Bytes
212c959
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import { useState, useRef, useEffect } from 'react'

function RenameModal({ current, onSave, onClose }) {
  const [val, setVal] = useState(current)
  return (
    <div className="modal-overlay" onClick={e => e.target === e.currentTarget && onClose()}>
      <div className="modal-card" style={{ maxWidth: 360 }}>
        <div className="modal-header">
          <span className="modal-title">Rename Chat</span>
          <button className="modal-close" onClick={onClose}>
            <svg viewBox="0 0 24 24"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
          </button>
        </div>
        <div className="modal-body">
          <input className="field-input" value={val} onChange={e => setVal(e.target.value)}
            onKeyDown={e => e.key === 'Enter' && onSave(val)} autoFocus maxLength={80} />
        </div>
        <div className="modal-footer">
          <button className="btn" onClick={onClose}>Cancel</button>
          <button className="btn btn-primary" onClick={() => onSave(val)}>Save</button>
        </div>
      </div>
    </div>
  )
}

export default function TopBar({
  onToggleSidebar, sessionTitle, user,
  onRename, onLogin, onLogout, onFeedback, onSettings, theme, onTheme, currentSessionId,
}) {
  const [dropOpen, setDropOpen] = useState(false)
  const [renaming, setRenaming] = useState(false)
  const dropRef = useRef(null)

  useEffect(() => {
    const h = e => { if (dropRef.current && !dropRef.current.contains(e.target)) setDropOpen(false) }
    document.addEventListener('mousedown', h)
    return () => document.removeEventListener('mousedown', h)
  }, [])

  const cycleTheme = () => onTheme(theme === 'dark' ? 'light' : 'dark')

  const initial = user ? (user.username[0] || 'U').toUpperCase() : '?'

  return (
    <>
      <div className="topbar">
        <div className="topbar-left">
          {/* Sidebar toggle */}
          <button className="icon-btn" onClick={onToggleSidebar} title="Toggle sidebar">
            <svg viewBox="0 0 24 24"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg>
          </button>

          <span className="session-title-display">{sessionTitle}</span>

          {user && currentSessionId && (
            <button className="icon-btn" onClick={() => setRenaming(true)} title="Rename">
              <svg viewBox="0 0 24 24"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>
            </button>
          )}
        </div>

        <div className="topbar-right">
          {/* Theme toggle */}
          <button className="icon-btn" onClick={cycleTheme} title={theme === 'dark' ? 'Switch to Light Mode' : 'Switch to Dark Mode'} style={{ transition: 'transform 0.4s var(--spring)' }}>
            {theme === 'dark' ? (
              <svg viewBox="0 0 24 24" style={{ transform: 'rotate(-20deg)' }}><path d="M21 12.79A9 9 0 1 1 11.21 3a7 7 0 0 0 9.79 9.79z"/></svg>
            ) : (
              <svg viewBox="0 0 24 24" style={{ transform: 'rotate(90deg)' }}><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/></svg>
            )}
          </button>

          {user ? (
            <div className="avatar-menu" ref={dropRef}>
              <button 
                className="avatar-btn" 
                onClick={() => setDropOpen(o => !o)} 
                title="Account"
                style={user.avatar_url ? { backgroundImage: `url(${user.avatar_url})`, backgroundSize: 'cover', backgroundPosition: 'center', color: 'transparent' } : {}}
              >
                {!user.avatar_url && initial}
                <span className="avatar-online" />
              </button>
              {dropOpen && (
                <div className="avatar-dropdown">
                  <div className="avd-user">
                    <div className="avd-name">{user.username}</div>
                    <div className="avd-sub">Free Plan</div>
                  </div>
                  <div className="avd-sep" />
                  <button className="avd-item" onClick={() => { setDropOpen(false); onSettings() }}>
                    <svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"/><path d="M19.07 4.93a10 10 0 0 1 0 14.14M4.93 4.93a10 10 0 0 0 0 14.14"/></svg>
                    Settings
                  </button>
                  <button className="avd-item" onClick={() => { setDropOpen(false); onFeedback() }}>
                    <svg viewBox="0 0 24 24"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
                    Send Feedback
                  </button>
                  <div className="avd-sep" />
                  <button className="avd-item danger" onClick={() => { setDropOpen(false); onLogout() }}>
                    <svg viewBox="0 0 24 24"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/></svg>
                    Sign Out
                  </button>
                </div>
              )}
            </div>
          ) : (
            <button className="btn btn-primary" onClick={onLogin}>Sign In</button>
          )}
        </div>
      </div>

      {renaming && (
        <RenameModal
          current={sessionTitle}
          onSave={t => { onRename(t); setRenaming(false) }}
          onClose={() => setRenaming(false)}
        />
      )}
    </>
  )
}