fix: compact timestamps, historical alias resolution, wider ts column
- Timestamps now show "Jun 28 10:58" for older messages (dropped "Yesterday" which overflowed the fixed-width column) - Timestamp column widened from 52px to 72px to fit date+time - state_snapshot now includes known_peers (historically seen, not currently connected) so the UI can resolve aliases in history - MessagePane aliasFor falls back to knownPeers map Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -459,6 +459,22 @@ func stateSnapshot(mgr *netmgr.Manager) proto.IpcMessage {
|
||||
msg.Rooms = append(msg.Rooms, r)
|
||||
}
|
||||
}
|
||||
// Include all historically-known peers so the UI can resolve aliases in history.
|
||||
if known, err := all[0].Store.KnownPeers(); err == nil {
|
||||
connected := map[proto.PeerID]bool{}
|
||||
for _, p := range msg.ConnectedPeers {
|
||||
connected[p.ID] = true
|
||||
}
|
||||
for id, alias := range known {
|
||||
if connected[id] {
|
||||
continue // already in ConnectedPeers
|
||||
}
|
||||
msg.KnownPeers = append(msg.KnownPeers, proto.PeerInfo{
|
||||
ID: id,
|
||||
Alias: alias,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return msg
|
||||
|
||||
@@ -350,6 +350,7 @@ type IpcMessage struct {
|
||||
MasterID string `json:"master_id,omitempty"` // daemon's master public key hex
|
||||
LocalPeer *PeerInfo `json:"local_peer,omitempty"`
|
||||
ConnectedPeers []PeerInfo `json:"connected_peers,omitempty"`
|
||||
KnownPeers []PeerInfo `json:"known_peers,omitempty"` // historically seen, not currently connected
|
||||
Rooms []string `json:"rooms,omitempty"`
|
||||
// multi-network: all joined networks (additive)
|
||||
Networks []NetworkInfo `json:"networks,omitempty"`
|
||||
|
||||
@@ -88,7 +88,7 @@ details summary { color: var(--muted); font-size: 12px; cursor: pointer; }
|
||||
.messages { flex: 1; overflow-y: auto; padding: 8px 0; display: flex; flex-direction: column; }
|
||||
.message { display: flex; align-items: baseline; gap: 0; padding: 2px 16px; line-height: 1.5; }
|
||||
.message:hover { background: rgba(255,255,255,0.02); }
|
||||
.message-ts { color: var(--muted); font-size: 11px; white-space: nowrap; flex-shrink: 0; width: 52px; }
|
||||
.message-ts { color: var(--muted); font-size: 11px; white-space: nowrap; flex-shrink: 0; width: 72px; }
|
||||
.message-alias { font-weight: 600; font-size: 13px; text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex-shrink: 0; width: 90px; padding-right: 10px; }
|
||||
.message.mine .message-alias { color: var(--accent); }
|
||||
.message-text { word-break: break-word; font-size: 14px; color: var(--text); }
|
||||
|
||||
@@ -4,17 +4,16 @@ import { useWaste } from '../store'
|
||||
const today = new Date()
|
||||
today.setHours(0, 0, 0, 0)
|
||||
const todayMs = today.getTime()
|
||||
const yesterdayMs = todayMs - 86400000
|
||||
|
||||
function formatTs(ts: number): string {
|
||||
const time = new Date(ts).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', hour12: false })
|
||||
const d = new Date(ts)
|
||||
const time = d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', hour12: false })
|
||||
if (ts >= todayMs) return time
|
||||
if (ts >= yesterdayMs) return `Yesterday ${time}`
|
||||
return new Date(ts).toLocaleDateString([], { month: 'short', day: 'numeric' }) + ' ' + time
|
||||
return d.toLocaleDateString([], { month: 'short', day: 'numeric' }) + ' ' + time
|
||||
}
|
||||
|
||||
export function MessagePane() {
|
||||
const { messages, historyCutoff, activeRoom, activeNetworkId, localPeer, connectedPeers, send } = useWaste()
|
||||
const { messages, historyCutoff, activeRoom, activeNetworkId, localPeer, connectedPeers, knownPeers, send } = useWaste()
|
||||
const [draft, setDraft] = useState('')
|
||||
const bottomRef = useRef<HTMLDivElement>(null)
|
||||
const roomMessages = messages[activeRoom] ?? []
|
||||
@@ -53,7 +52,9 @@ export function MessagePane() {
|
||||
|
||||
function aliasFor(fromId: string) {
|
||||
if (fromId === localPeer?.id) return localPeer.alias
|
||||
return connectedPeers.find(p => p.id === fromId)?.alias ?? fromId.slice(0, 8)
|
||||
return connectedPeers.find(p => p.id === fromId)?.alias
|
||||
?? knownPeers[fromId]
|
||||
?? fromId.slice(0, 8)
|
||||
}
|
||||
|
||||
const roomLabel = activeRoom.startsWith('dm:')
|
||||
|
||||
@@ -29,6 +29,7 @@ interface WasteState {
|
||||
|
||||
// peers
|
||||
connectedPeers: PeerInfo[]
|
||||
knownPeers: Record<string, string> // id → alias for historical peers
|
||||
|
||||
// chat — keyed by room
|
||||
messages: Record<string, ChatMessage[]>
|
||||
@@ -87,6 +88,7 @@ export const useWaste = create<WasteState>((set, get) => ({
|
||||
networks: [],
|
||||
activeNetworkId: null,
|
||||
connectedPeers: [],
|
||||
knownPeers: {},
|
||||
messages: {},
|
||||
historyCutoff: {},
|
||||
activeRoom: 'general',
|
||||
@@ -215,6 +217,8 @@ export const useWaste = create<WasteState>((set, get) => ({
|
||||
switch (msg.type) {
|
||||
case 'state_snapshot': {
|
||||
const networks = msg.networks ?? []
|
||||
const knownPeers: Record<string, string> = {}
|
||||
for (const p of msg.known_peers ?? []) knownPeers[p.id] = p.alias
|
||||
set({
|
||||
masterAlias: msg.master_alias ?? null,
|
||||
masterId: msg.master_id ?? null,
|
||||
@@ -222,6 +226,7 @@ export const useWaste = create<WasteState>((set, get) => ({
|
||||
networks,
|
||||
connectedPeers: msg.connected_peers ?? [],
|
||||
activeNetworkId: networks[0]?.network_id ?? null,
|
||||
knownPeers,
|
||||
})
|
||||
break
|
||||
}
|
||||
|
||||
@@ -117,6 +117,7 @@ export interface IpcMessage {
|
||||
master_id?: string
|
||||
local_peer?: PeerInfo
|
||||
connected_peers?: PeerInfo[]
|
||||
known_peers?: PeerInfo[]
|
||||
rooms?: string[]
|
||||
networks?: NetworkInfo[]
|
||||
error_message?: string
|
||||
|
||||
Reference in New Issue
Block a user