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)
|
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
|
return msg
|
||||||
|
|||||||
@@ -350,6 +350,7 @@ type IpcMessage struct {
|
|||||||
MasterID string `json:"master_id,omitempty"` // daemon's master public key hex
|
MasterID string `json:"master_id,omitempty"` // daemon's master public key hex
|
||||||
LocalPeer *PeerInfo `json:"local_peer,omitempty"`
|
LocalPeer *PeerInfo `json:"local_peer,omitempty"`
|
||||||
ConnectedPeers []PeerInfo `json:"connected_peers,omitempty"`
|
ConnectedPeers []PeerInfo `json:"connected_peers,omitempty"`
|
||||||
|
KnownPeers []PeerInfo `json:"known_peers,omitempty"` // historically seen, not currently connected
|
||||||
Rooms []string `json:"rooms,omitempty"`
|
Rooms []string `json:"rooms,omitempty"`
|
||||||
// multi-network: all joined networks (additive)
|
// multi-network: all joined networks (additive)
|
||||||
Networks []NetworkInfo `json:"networks,omitempty"`
|
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; }
|
.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 { display: flex; align-items: baseline; gap: 0; padding: 2px 16px; line-height: 1.5; }
|
||||||
.message:hover { background: rgba(255,255,255,0.02); }
|
.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-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.mine .message-alias { color: var(--accent); }
|
||||||
.message-text { word-break: break-word; font-size: 14px; color: var(--text); }
|
.message-text { word-break: break-word; font-size: 14px; color: var(--text); }
|
||||||
|
|||||||
@@ -4,17 +4,16 @@ import { useWaste } from '../store'
|
|||||||
const today = new Date()
|
const today = new Date()
|
||||||
today.setHours(0, 0, 0, 0)
|
today.setHours(0, 0, 0, 0)
|
||||||
const todayMs = today.getTime()
|
const todayMs = today.getTime()
|
||||||
const yesterdayMs = todayMs - 86400000
|
|
||||||
|
|
||||||
function formatTs(ts: number): string {
|
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 >= todayMs) return time
|
||||||
if (ts >= yesterdayMs) return `Yesterday ${time}`
|
return d.toLocaleDateString([], { month: 'short', day: 'numeric' }) + ' ' + time
|
||||||
return new Date(ts).toLocaleDateString([], { month: 'short', day: 'numeric' }) + ' ' + time
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function MessagePane() {
|
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 [draft, setDraft] = useState('')
|
||||||
const bottomRef = useRef<HTMLDivElement>(null)
|
const bottomRef = useRef<HTMLDivElement>(null)
|
||||||
const roomMessages = messages[activeRoom] ?? []
|
const roomMessages = messages[activeRoom] ?? []
|
||||||
@@ -53,7 +52,9 @@ export function MessagePane() {
|
|||||||
|
|
||||||
function aliasFor(fromId: string) {
|
function aliasFor(fromId: string) {
|
||||||
if (fromId === localPeer?.id) return localPeer.alias
|
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:')
|
const roomLabel = activeRoom.startsWith('dm:')
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ interface WasteState {
|
|||||||
|
|
||||||
// peers
|
// peers
|
||||||
connectedPeers: PeerInfo[]
|
connectedPeers: PeerInfo[]
|
||||||
|
knownPeers: Record<string, string> // id → alias for historical peers
|
||||||
|
|
||||||
// chat — keyed by room
|
// chat — keyed by room
|
||||||
messages: Record<string, ChatMessage[]>
|
messages: Record<string, ChatMessage[]>
|
||||||
@@ -87,6 +88,7 @@ export const useWaste = create<WasteState>((set, get) => ({
|
|||||||
networks: [],
|
networks: [],
|
||||||
activeNetworkId: null,
|
activeNetworkId: null,
|
||||||
connectedPeers: [],
|
connectedPeers: [],
|
||||||
|
knownPeers: {},
|
||||||
messages: {},
|
messages: {},
|
||||||
historyCutoff: {},
|
historyCutoff: {},
|
||||||
activeRoom: 'general',
|
activeRoom: 'general',
|
||||||
@@ -215,6 +217,8 @@ export const useWaste = create<WasteState>((set, get) => ({
|
|||||||
switch (msg.type) {
|
switch (msg.type) {
|
||||||
case 'state_snapshot': {
|
case 'state_snapshot': {
|
||||||
const networks = msg.networks ?? []
|
const networks = msg.networks ?? []
|
||||||
|
const knownPeers: Record<string, string> = {}
|
||||||
|
for (const p of msg.known_peers ?? []) knownPeers[p.id] = p.alias
|
||||||
set({
|
set({
|
||||||
masterAlias: msg.master_alias ?? null,
|
masterAlias: msg.master_alias ?? null,
|
||||||
masterId: msg.master_id ?? null,
|
masterId: msg.master_id ?? null,
|
||||||
@@ -222,6 +226,7 @@ export const useWaste = create<WasteState>((set, get) => ({
|
|||||||
networks,
|
networks,
|
||||||
connectedPeers: msg.connected_peers ?? [],
|
connectedPeers: msg.connected_peers ?? [],
|
||||||
activeNetworkId: networks[0]?.network_id ?? null,
|
activeNetworkId: networks[0]?.network_id ?? null,
|
||||||
|
knownPeers,
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,6 +117,7 @@ export interface IpcMessage {
|
|||||||
master_id?: string
|
master_id?: string
|
||||||
local_peer?: PeerInfo
|
local_peer?: PeerInfo
|
||||||
connected_peers?: PeerInfo[]
|
connected_peers?: PeerInfo[]
|
||||||
|
known_peers?: PeerInfo[]
|
||||||
rooms?: string[]
|
rooms?: string[]
|
||||||
networks?: NetworkInfo[]
|
networks?: NetworkInfo[]
|
||||||
error_message?: string
|
error_message?: string
|
||||||
|
|||||||
Reference in New Issue
Block a user