From e60e5742879735c4d99a8773a0e4e159b49f31be Mon Sep 17 00:00:00 2001 From: djuka Date: Wed, 18 Feb 2026 06:56:13 +0000 Subject: [PATCH] Uklonjen autofocus sa modala koji prikazuje formu bez poziva MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - autofocus na inputu u hidden modalu izazivao prikaz forme na nekim browserima pri učitavanju stranice - Fokus se sada daje programski tek kad se modal otvori - Isto rešenje primenjeno i na projects.html i chat.html Co-Authored-By: Claude Opus 4.6 --- pty_session.go | 9 +- templates/chat.html | 545 ++++++++++++++++++++++++++++++++++------ templates/projects.html | 14 +- 3 files changed, 491 insertions(+), 77 deletions(-) diff --git a/pty_session.go b/pty_session.go index 5e1a938..4a48a7d 100644 --- a/pty_session.go +++ b/pty_session.go @@ -221,17 +221,18 @@ func NewPTYSessionManager() *PTYSessionManager { } // GetOrCreate returns an existing session or creates a new one. -func (m *PTYSessionManager) GetOrCreate(project, projectDir string) (*PTYSession, bool, error) { +// sessionKey is a free-form string (e.g. "project:tabId"). +func (m *PTYSessionManager) GetOrCreate(sessionKey, projectDir string) (*PTYSession, bool, error) { m.mu.Lock() defer m.mu.Unlock() - if sess, ok := m.sessions[project]; ok { + if sess, ok := m.sessions[sessionKey]; ok { // Check if process is still alive select { case <-sess.Done(): // Process exited, remove and create new sess.Close() - delete(m.sessions, project) + delete(m.sessions, sessionKey) default: sess.mu.Lock() sess.lastActive = time.Now() @@ -245,7 +246,7 @@ func (m *PTYSessionManager) GetOrCreate(project, projectDir string) (*PTYSession return nil, false, err } - m.sessions[project] = sess + m.sessions[sessionKey] = sess return sess, true, nil } diff --git a/templates/chat.html b/templates/chat.html index 3eb4c50..d96712f 100644 --- a/templates/chat.html +++ b/templates/chat.html @@ -16,6 +16,7 @@ --text-muted: #6c6c80; --accent: #e94560; --accent-hover: #ff6b81; + --error: #f44336; } body { background: var(--bg-primary); @@ -141,7 +142,99 @@ cursor: pointer; } .terminal-header button:hover { border-color: var(--accent); color: var(--text-primary); } - #terminal-container { flex: 1; overflow: hidden; } + + /* Tab bar */ + .tab-bar { + display: flex; + align-items: center; + background: var(--bg-secondary); + border-bottom: 1px solid var(--border); + padding: 0 0.25rem; + flex-shrink: 0; + overflow-x: auto; + gap: 2px; + min-height: 30px; + } + .tab-bar::-webkit-scrollbar { height: 0; } + .tab { + display: flex; + align-items: center; + gap: 0.4rem; + padding: 0.2rem 0.5rem; + font-size: 0.7rem; + color: var(--text-muted); + cursor: pointer; + border: 1px solid transparent; + border-bottom: none; + border-radius: 4px 4px 0 0; + white-space: nowrap; + user-select: none; + transition: color 0.15s, background 0.15s; + } + .tab:hover { color: var(--text-secondary); background: rgba(255,255,255,0.03); } + .tab.active { color: var(--text-primary); background: var(--bg-primary); border-color: var(--border); } + .tab-close { + display: inline-flex; + align-items: center; + justify-content: center; + width: 16px; + height: 16px; + font-size: 0.65rem; + border-radius: 3px; + color: var(--text-muted); + transition: background 0.1s, color 0.1s; + } + .tab-close:hover { background: rgba(244,67,54,0.3); color: var(--error); } + .tab-add-wrap { position: relative; flex-shrink: 0; } + .tab-add { + display: flex; + align-items: center; + justify-content: center; + width: 24px; + height: 24px; + font-size: 0.85rem; + color: var(--text-muted); + cursor: pointer; + border-radius: 4px; + border: none; + background: none; + font-family: inherit; + transition: color 0.15s, background 0.15s; + } + .tab-add:hover { color: var(--text-primary); background: rgba(255,255,255,0.05); } + .tab-dropdown { + position: absolute; + top: 100%; + left: 0; + background: var(--bg-secondary); + border: 1px solid var(--border); + border-radius: 6px; + min-width: 180px; + max-height: 300px; + overflow-y: auto; + z-index: 100; + box-shadow: 0 4px 12px rgba(0,0,0,0.4); + } + .tab-dropdown.hidden { display: none; } + .tab-dropdown-item { + display: block; + width: 100%; + padding: 0.4rem 0.75rem; + font-size: 0.75rem; + font-family: inherit; + color: var(--text-secondary); + background: none; + border: none; + text-align: left; + cursor: pointer; + transition: background 0.1s, color 0.1s; + } + .tab-dropdown-item:hover { background: rgba(233,69,96,0.15); color: var(--text-primary); } + + /* Terminal containers */ + #terminals { flex: 1; overflow: hidden; position: relative; } + .term-pane { position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: none; } + .term-pane.active { display: block; } .xterm { height: 100%; } /* File viewer overlay */ @@ -201,6 +294,47 @@ .file-viewer-content th { background: var(--bg-secondary); color: var(--accent); font-weight: 600; } .file-viewer-content tr:nth-child(even) { background: rgba(22,27,34,0.5); } + /* Sidebar project list */ + .sidebar-projects-list { max-height: 180px; overflow-y: auto; } + .sidebar-projects-list .file-item.active { + color: var(--accent); + background: rgba(233,69,96,0.1); + font-weight: 600; + } + .sidebar-add-btn { + display: inline-flex; + align-items: center; + justify-content: center; + width: 16px; + height: 16px; + font-size: 0.8rem; + color: var(--text-muted); + cursor: pointer; + border-radius: 3px; + transition: color 0.15s, background 0.15s; + line-height: 1; + } + .sidebar-add-btn:hover { color: var(--accent); background: rgba(233,69,96,0.15); } + + /* Create project modal */ + .create-project-modal { + position: fixed; top: 0; left: 0; width: 100%; height: 100%; + background: rgba(0,0,0,0.5); display: flex; align-items: center; + justify-content: center; z-index: 300; + } + .create-project-box { + background: var(--bg-secondary); border: 1px solid var(--border); + border-radius: 8px; padding: 1rem; width: 260px; + box-shadow: 0 4px 16px rgba(0,0,0,0.4); + } + .create-project-box h3 { color: var(--accent); font-size: 0.85rem; margin-bottom: 0.6rem; } + .create-project-box input { + width: 100%; padding: 0.35rem 0.5rem; background: var(--bg-primary); + border: 1px solid var(--border); border-radius: 4px; color: var(--text-primary); + font-size: 0.75rem; font-family: inherit; outline: none; + } + .create-project-box input:focus { border-color: var(--accent); } + /* Scrollbar */ ::-webkit-scrollbar { width: 5px; } ::-webkit-scrollbar-track { background: transparent; } @@ -215,6 +349,20 @@

{{.Project}}

+ + + + + {{if .Files}} - {{else}} - {{end}} + + +
@@ -255,10 +414,16 @@ - Projekti
-
+
+ +
+ + +
+
+
@@ -274,8 +439,12 @@ diff --git a/templates/projects.html b/templates/projects.html index 8294f20..170eb2d 100644 --- a/templates/projects.html +++ b/templates/projects.html @@ -11,7 +11,7 @@

Projekti

- + Promeni lozinku Odjavi se
@@ -27,7 +27,7 @@
- +
+