mirror of
https://github.com/dergigi/boris.git
synced 2025-12-26 11:04:24 +01:00
refactor: improve relay list display with airplane icons
- Remove separate 'Offline' section, show all relays in one list - Local relays always shown first (sorted to top) - Local relays use airplane icon instead of checkmark - Airplane icon is green when connected, red when offline - Remote relays use green checkmark (connected) or red dot (offline) - Last seen timestamp shown only for disconnected relays - Simplified layout for better readability
This commit is contained in:
@@ -11,9 +11,6 @@ interface RelaySettingsProps {
|
||||
}
|
||||
|
||||
const RelaySettings: React.FC<RelaySettingsProps> = ({ relayStatuses }) => {
|
||||
const activeRelays = relayStatuses.filter(r => r.isInPool)
|
||||
const recentRelays = relayStatuses.filter(r => !r.isInPool)
|
||||
|
||||
const formatRelayUrl = (url: string) => {
|
||||
return url.replace(/^wss?:\/\//, '').replace(/\/$/, '')
|
||||
}
|
||||
@@ -26,150 +23,109 @@ const RelaySettings: React.FC<RelaySettingsProps> = ({ relayStatuses }) => {
|
||||
}
|
||||
}
|
||||
|
||||
// Sort relays: local relays first, then by connection status, then by URL
|
||||
const sortedRelays = [...relayStatuses].sort((a, b) => {
|
||||
const aIsLocal = isLocalRelay(a.url)
|
||||
const bIsLocal = isLocalRelay(b.url)
|
||||
|
||||
// Local relays always first
|
||||
if (aIsLocal && !bIsLocal) return -1
|
||||
if (!aIsLocal && bIsLocal) return 1
|
||||
|
||||
// Within local or remote groups, connected before disconnected
|
||||
if (a.isInPool !== b.isInPool) return a.isInPool ? -1 : 1
|
||||
|
||||
// Finally sort by URL
|
||||
return a.url.localeCompare(b.url)
|
||||
})
|
||||
|
||||
const getRelayIcon = (relay: RelayStatus) => {
|
||||
const isLocal = isLocalRelay(relay.url)
|
||||
const isConnected = relay.isInPool
|
||||
|
||||
if (isLocal) {
|
||||
return {
|
||||
icon: faPlane,
|
||||
color: isConnected ? '#22c55e' : '#ef4444',
|
||||
size: '1rem'
|
||||
}
|
||||
} else {
|
||||
if (isConnected) {
|
||||
return {
|
||||
icon: faCheckCircle,
|
||||
color: '#22c55e',
|
||||
size: '1rem'
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
icon: faCircle,
|
||||
color: '#ef4444',
|
||||
size: '0.7rem'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="settings-section">
|
||||
<h3>Relays</h3>
|
||||
|
||||
{activeRelays.length > 0 && (
|
||||
<div className="relay-group" style={{ marginBottom: '1.5rem' }}>
|
||||
<div className="relay-list">
|
||||
{activeRelays.map((relay) => (
|
||||
<div
|
||||
key={relay.url}
|
||||
className="relay-item"
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '0.75rem',
|
||||
padding: '0.75rem',
|
||||
background: 'var(--surface-secondary)',
|
||||
borderRadius: '6px',
|
||||
marginBottom: '0.5rem'
|
||||
}}
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
icon={faCheckCircle}
|
||||
style={{
|
||||
color: 'var(--success, #22c55e)',
|
||||
fontSize: '1rem'
|
||||
}}
|
||||
/>
|
||||
<div style={{ flex: 1, minWidth: 0 }}>
|
||||
<div style={{
|
||||
fontSize: '0.9rem',
|
||||
fontFamily: 'var(--font-mono, monospace)',
|
||||
whiteSpace: 'nowrap',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '0.5rem'
|
||||
}}>
|
||||
{formatRelayUrl(relay.url)}
|
||||
{isLocalRelay(relay.url) && (
|
||||
<span
|
||||
title="Local relay"
|
||||
style={{
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
padding: '0.15rem 0.4rem',
|
||||
background: 'rgba(245, 158, 11, 0.15)',
|
||||
borderRadius: '4px',
|
||||
color: '#f59e0b',
|
||||
fontSize: '0.75rem',
|
||||
flexShrink: 0
|
||||
}}
|
||||
>
|
||||
<FontAwesomeIcon icon={faPlane} />
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{recentRelays.length > 0 && (
|
||||
{sortedRelays.length > 0 && (
|
||||
<div className="relay-group">
|
||||
<h4 style={{
|
||||
fontSize: '0.85rem',
|
||||
fontWeight: 600,
|
||||
color: '#ef4444',
|
||||
marginBottom: '0.75rem',
|
||||
textTransform: 'uppercase',
|
||||
letterSpacing: '0.05em'
|
||||
}}>
|
||||
Offline
|
||||
</h4>
|
||||
<div className="relay-list">
|
||||
{recentRelays.map((relay) => (
|
||||
<div
|
||||
key={relay.url}
|
||||
className="relay-item"
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '0.75rem',
|
||||
padding: '0.75rem',
|
||||
background: 'var(--surface-secondary)',
|
||||
borderRadius: '6px',
|
||||
marginBottom: '0.5rem',
|
||||
opacity: 0.7
|
||||
}}
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
icon={faCircle}
|
||||
style={{
|
||||
color: '#ef4444',
|
||||
fontSize: '0.7rem'
|
||||
}}
|
||||
/>
|
||||
<div style={{ flex: 1, minWidth: 0 }}>
|
||||
<div style={{
|
||||
fontSize: '0.9rem',
|
||||
fontFamily: 'var(--font-mono, monospace)',
|
||||
whiteSpace: 'nowrap',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
{sortedRelays.map((relay) => {
|
||||
const iconConfig = getRelayIcon(relay)
|
||||
const isDisconnected = !relay.isInPool
|
||||
|
||||
return (
|
||||
<div
|
||||
key={relay.url}
|
||||
className="relay-item"
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '0.5rem'
|
||||
}}>
|
||||
{formatRelayUrl(relay.url)}
|
||||
{isLocalRelay(relay.url) && (
|
||||
<span
|
||||
title="Local relay"
|
||||
style={{
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
padding: '0.15rem 0.4rem',
|
||||
background: 'rgba(245, 158, 11, 0.15)',
|
||||
borderRadius: '4px',
|
||||
color: '#f59e0b',
|
||||
fontSize: '0.75rem',
|
||||
flexShrink: 0
|
||||
}}
|
||||
>
|
||||
<FontAwesomeIcon icon={faPlane} />
|
||||
</span>
|
||||
)}
|
||||
gap: '0.75rem',
|
||||
padding: '0.75rem',
|
||||
background: 'var(--surface-secondary)',
|
||||
borderRadius: '6px',
|
||||
marginBottom: '0.5rem',
|
||||
opacity: isDisconnected ? 0.7 : 1
|
||||
}}
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
icon={iconConfig.icon}
|
||||
style={{
|
||||
color: iconConfig.color,
|
||||
fontSize: iconConfig.size
|
||||
}}
|
||||
/>
|
||||
<div style={{ flex: 1, minWidth: 0 }}>
|
||||
<div style={{
|
||||
fontSize: '0.9rem',
|
||||
fontFamily: 'var(--font-mono, monospace)',
|
||||
whiteSpace: 'nowrap',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis'
|
||||
}}>
|
||||
{formatRelayUrl(relay.url)}
|
||||
</div>
|
||||
</div>
|
||||
{isDisconnected && (
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '0.5rem',
|
||||
fontSize: '0.8rem',
|
||||
color: 'var(--text-tertiary)',
|
||||
whiteSpace: 'nowrap'
|
||||
}}>
|
||||
<FontAwesomeIcon icon={faClock} />
|
||||
{formatLastSeen(relay.lastSeen)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '0.5rem',
|
||||
fontSize: '0.8rem',
|
||||
color: 'var(--text-tertiary)',
|
||||
whiteSpace: 'nowrap'
|
||||
}}>
|
||||
<FontAwesomeIcon icon={faClock} />
|
||||
{formatLastSeen(relay.lastSeen)}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user