Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion static/channels.js
Original file line number Diff line number Diff line change
Expand Up @@ -308,9 +308,14 @@ function switchChannel(name) {
const savedId = _channelScrollMsg[name];
if (savedId) {
const el = document.querySelector(`.message[data-id="${savedId}"]`);
if (el) { el.scrollIntoView({ block: 'start' }); return; }
if (el) {
el.scrollIntoView({ block: 'start' });
if (typeof dayFloatRefresh === 'function') dayFloatRefresh();
return;
}
}
window.scrollToBottom();
if (typeof dayFloatRefresh === 'function') dayFloatRefresh();
}

function filterMessagesByChannel() {
Expand Down
68 changes: 67 additions & 1 deletion static/chat.js
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,8 @@ function connectWebSocket() {
const container = document.getElementById('messages');
const toRemove = [];
for (const el of container.children) {
if (el.dataset.id && (el.dataset.channel || 'general') === clearChannel) {
const isDivider = el.classList.contains('date-divider');
if ((el.dataset.id || isDivider) && (el.dataset.channel || 'general') === clearChannel) {
toRemove.push(el);
}
}
Expand All @@ -591,6 +592,7 @@ function connectWebSocket() {
lastMessageDate = null;
lastMessageDates = {};
}
dayFloatRefresh();
requestAnimationFrame(() => {
const _clearDbgAfter = _clearDbgList ? _clearDbgList.children.length : -1;
console.log('CLEAR_DEBUG after clear (next frame), jobs-panel-children=' + _clearDbgAfter);
Expand Down Expand Up @@ -666,6 +668,69 @@ function maybeInsertDateDivider(container, msg) {
}
}

// --- Floating day indicator ---

let dayFloatDividers = null; // live HTMLCollection — follows divider add/remove
let dayFloatFadeTimer = null;
let dayFloatRafPending = false;

function dayFloatLabel() {
if (!dayFloatDividers) {
const container = document.getElementById('messages');
if (!container) return null;
dayFloatDividers = container.getElementsByClassName('date-divider');
}
const scroll = document.getElementById('timeline');
if (!scroll) return null;
const top = scroll.getBoundingClientRect().top;
let label = null;
for (const d of dayFloatDividers) {
if (d.style.display === 'none') continue;
if (d.getBoundingClientRect().top <= top) {
label = d.textContent;
} else {
break;
}
}
return label;
}

function dayFloatHide() {
const float = document.getElementById('day-float');
if (!float) return;
if (dayFloatFadeTimer) { clearTimeout(dayFloatFadeTimer); dayFloatFadeTimer = null; }
float.classList.remove('visible');
}

function dayFloatOnScroll() {
if (dayFloatRafPending) return;
dayFloatRafPending = true;
requestAnimationFrame(() => {
dayFloatRafPending = false;
const float = document.getElementById('day-float');
if (!float) return;
const label = dayFloatLabel();
if (!label) { dayFloatHide(); return; }
float.querySelector('span').textContent = label;
float.classList.add('visible');
if (dayFloatFadeTimer) clearTimeout(dayFloatFadeTimer);
dayFloatFadeTimer = setTimeout(() => {
dayFloatFadeTimer = null;
float.classList.remove('visible');
}, 1200);
});
}

function dayFloatRefresh() {
// Recompute without starting the show/fade cycle: swap the label if the
// pill is relevant, hide (cancelling any fade) if no day is above the top.
const float = document.getElementById('day-float');
if (!float) return;
const label = dayFloatLabel();
if (!label) { dayFloatHide(); return; }
float.querySelector('span').textContent = label;
}

// --- Messages ---

function appendMessage(msg) {
Expand Down Expand Up @@ -2499,6 +2564,7 @@ function setupScroll() {
unreadCount = 0;
}
updateScrollAnchor();
dayFloatOnScroll();
});

// Keep pinned to bottom when content changes (e.g. images load)
Expand Down
7 changes: 4 additions & 3 deletions static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>agentchattr</title>
<link rel="stylesheet" href="/static/style.css?v=249">
<link rel="stylesheet" href="/static/style.css?v=250">
<link rel="stylesheet" href="/static/sessions.css?v=223">
<link rel="stylesheet" href="/static/jobs.css?v=223">
<link rel="icon" href="/static/favicon.ico">
Expand Down Expand Up @@ -172,6 +172,7 @@ <h1 id="room-title">agentchattr</h1>
<div class="channel-sidebar-grip" id="channel-sidebar-grip"></div>
</aside>
<main id="timeline">
<div id="day-float" aria-hidden="true"><span></span></div>
<div id="loading-indicator">
<div class="loading-spinner"></div>
<span>Loading messages...</span>
Expand Down Expand Up @@ -342,8 +343,8 @@ <h1 id="room-title">agentchattr</h1>
<script src="/static/store.js?v=223"></script>
<script src="/static/sessions.js?v=223"></script>
<script src="/static/jobs.js?v=224"></script>
<script src="/static/channels.js?v=224"></script>
<script src="/static/channels.js?v=225"></script>
<script src="/static/rules-panel.js?v=223"></script>
<script src="/static/chat.js?v=266"></script>
<script src="/static/chat.js?v=267"></script>
</body>
</html>
32 changes: 32 additions & 0 deletions static/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -2553,6 +2553,38 @@ body.channels-in-sidebar #channel-bar {
background: var(--border);
}

/* --- Floating day indicator --- */

#day-float {
position: sticky;
top: 8px;
height: 0;
display: flex;
align-items: flex-start;
justify-content: center;
z-index: 6;
pointer-events: none;
}

#day-float span {
background: var(--bg-msg);
border: 1px solid var(--border);
border-radius: var(--radius-full);
padding: 3px 10px;
color: var(--text-dim);
font-size: 11px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.06em;
text-indent: 0.06em;
opacity: 0;
transition: opacity 0.25s ease;
}

#day-float.visible span {
opacity: 1;
}

/* --- Code copy button --- */

.code-copy-btn {
Expand Down