v0.4.3: Lock contention overhaul, StoragePool, mobile bottom nav, text scaling
Eliminate all conn_mgr lock holds during network I/O across 14 actor commands and bi-stream handlers. PostFetch, TcpPunch, PullFromPeer, FetchEngagement, ResolveAddress, AnchorProbe use brief locks for data gathering only. WormLookup, ContentSearch, WormQuery use connection snapshots for lock-free cascade fan-out. RelayIntroduce extracts forwarding data under brief lock, does I/O outside. BlobRequest, PostFetchRequest, ManifestRefresh use Arc clones instead of conn_mgr lock. ConnectionActor hoists shared Arcs (storage, blob_store, endpoint) for lock-free access. ResolveAddress adds 5s per-query timeout (was unbounded). Initial exchange failure now aborts mesh upgrade (was silently continuing with broken connection). connect_to_peer/connect_to_anchor use consistent 15s timeout. Rebalance connects outside the lock via pending_connects pattern. StoragePool: 8 concurrent SQLite connections in WAL mode replace single Mutex<Storage>. Reads run fully parallel; writes serialize at SQLite level only. PRAGMA busy_timeout=5000 for graceful write contention. Mobile bottom nav bar (<=768px) with icon tabs. Text sizes: XS/S/M/L/XL (75%/100%/125%/150%/200%), default M. localStorage persistence for instant restore. Toast repositioned above mobile nav. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f17535d61d
commit
43adbbdf7d
15 changed files with 1546 additions and 618 deletions
|
|
@ -3007,22 +3007,20 @@ $('#circle-profiles-toggle').addEventListener('click', () => {
|
|||
|
||||
// --- Notifications popover ---
|
||||
// Text size toggle
|
||||
const TEXT_SIZE_SCALES = { small: '100%', normal: '150%', large: '200%' };
|
||||
// Apply text size immediately (default Normal = 150%)
|
||||
document.documentElement.style.fontSize = '150%';
|
||||
(async () => {
|
||||
const saved = await invoke('get_setting', { key: 'text_size' }).catch(() => null) || 'normal';
|
||||
document.documentElement.style.fontSize = TEXT_SIZE_SCALES[saved] || '150%';
|
||||
document.querySelectorAll('.text-size-opt').forEach(b => {
|
||||
b.classList.toggle('active', b.dataset.size === saved);
|
||||
});
|
||||
})();
|
||||
const TEXT_SIZE_SCALES = { xsmall: '75%', small: '100%', normal: '125%', large: '150%', xlarge: '200%' };
|
||||
// Apply text size immediately from localStorage cache (no async wait)
|
||||
const _cachedTextSize = localStorage.getItem('text_size') || 'normal';
|
||||
document.documentElement.style.fontSize = TEXT_SIZE_SCALES[_cachedTextSize] || '125%';
|
||||
document.querySelectorAll('.text-size-opt').forEach(b => {
|
||||
b.classList.toggle('active', b.dataset.size === _cachedTextSize);
|
||||
});
|
||||
document.querySelectorAll('.text-size-opt').forEach(btn => {
|
||||
btn.addEventListener('click', async () => {
|
||||
const size = btn.dataset.size;
|
||||
document.documentElement.style.fontSize = TEXT_SIZE_SCALES[size] || '';
|
||||
document.querySelectorAll('.text-size-opt').forEach(b => b.classList.remove('active'));
|
||||
btn.classList.add('active');
|
||||
localStorage.setItem('text_size', size);
|
||||
await invoke('set_setting', { key: 'text_size', value: size }).catch(() => {});
|
||||
toast('Text size updated');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -30,11 +30,11 @@
|
|||
|
||||
<main>
|
||||
<nav id="tabs">
|
||||
<button class="tab" data-tab="feed">Feed</button>
|
||||
<button class="tab" data-tab="myposts">My Posts</button>
|
||||
<button class="tab" data-tab="people">People</button>
|
||||
<button class="tab" data-tab="messages">Messages</button>
|
||||
<button class="tab" data-tab="settings">Settings</button>
|
||||
<button class="tab" data-tab="feed"><span class="tab-icon">📰</span><span class="tab-label">Feed</span></button>
|
||||
<button class="tab" data-tab="myposts"><span class="tab-icon">✍</span><span class="tab-label">My Posts</span></button>
|
||||
<button class="tab" data-tab="people"><span class="tab-icon">👥</span><span class="tab-label">People</span></button>
|
||||
<button class="tab" data-tab="messages"><span class="tab-icon">💬</span><span class="tab-label">Messages</span></button>
|
||||
<button class="tab" data-tab="settings"><span class="tab-icon">⚙</span><span class="tab-label">Settings</span></button>
|
||||
</nav>
|
||||
|
||||
<!-- Welcome (shown on startup) -->
|
||||
|
|
@ -229,9 +229,11 @@
|
|||
<div class="section-card">
|
||||
<h3>Text Size</h3>
|
||||
<div id="text-size-btns" style="display:flex;gap:0.4rem;margin-top:0.3rem">
|
||||
<button class="notif-opt text-size-opt" data-size="small">Small</button>
|
||||
<button class="notif-opt text-size-opt active" data-size="normal">Normal</button>
|
||||
<button class="notif-opt text-size-opt" data-size="large">Large</button>
|
||||
<button class="notif-opt text-size-opt" data-size="xsmall">XS</button>
|
||||
<button class="notif-opt text-size-opt" data-size="small">S</button>
|
||||
<button class="notif-opt text-size-opt active" data-size="normal">M</button>
|
||||
<button class="notif-opt text-size-opt" data-size="large">L</button>
|
||||
<button class="notif-opt text-size-opt" data-size="xlarge">XL</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -81,13 +81,25 @@ header h1 { font-size: clamp(1.4rem, 2.5vw, 2rem); color: #7fdbca; margin: 0; }
|
|||
.compose-right { display: flex; align-items: center; gap: 0.5rem; flex-shrink: 0; }
|
||||
.compose-left { display: flex; flex-direction: column; gap: 0.25rem; min-width: 0; }
|
||||
|
||||
/* Tabs */
|
||||
/* Tabs — desktop (top bar) */
|
||||
#tabs { display: flex; gap: 0; margin-bottom: 1rem; border-bottom: 1px solid #333; }
|
||||
.tab { background: none; border: none; color: #99a; padding: 0.5rem 0.6rem; cursor: pointer; border-bottom: 2px solid transparent; font-size: 0.82rem; transition: color 0.15s, border-color 0.15s; position: relative; flex: 1; text-align: center; white-space: nowrap; }
|
||||
.tab:hover { color: #ccd; }
|
||||
.tab.active { color: #7fdbca; border-bottom-color: #7fdbca; }
|
||||
.tab-icon { display: none; }
|
||||
.tab-badge { display: inline-flex; align-items: center; justify-content: center; background: #0f3460; color: #7fdbca; font-size: 0.6rem; min-width: 1.1rem; height: 1.1rem; border-radius: 0.55rem; padding: 0 0.3rem; margin-left: 0.25rem; font-family: system-ui, sans-serif; vertical-align: middle; }
|
||||
|
||||
/* Tabs — mobile/tablet (bottom nav bar) */
|
||||
@media (max-width: 768px) {
|
||||
#tabs { position: fixed; bottom: 0; left: 0; right: 0; z-index: 900; background: #0a0a1a; border-bottom: none; border-top: 1px solid #333; margin-bottom: 0; padding: 0; padding-bottom: env(safe-area-inset-bottom, 0); }
|
||||
.tab { flex-direction: column; align-items: center; padding: 0.4rem 0.2rem 0.3rem; border-bottom: none; border-top: 2px solid transparent; font-size: 0.6rem; gap: 0.15rem; display: flex; }
|
||||
.tab.active { border-bottom: none; border-top-color: #7fdbca; }
|
||||
.tab-icon { display: block; font-size: 1.2rem; line-height: 1; }
|
||||
.tab-badge { position: absolute; top: 0.1rem; right: 0.2rem; margin-left: 0; font-size: 0.5rem; min-width: 0.9rem; height: 0.9rem; border-radius: 0.45rem; }
|
||||
main { padding-bottom: 4rem; }
|
||||
.toast { bottom: 4.5rem; }
|
||||
}
|
||||
|
||||
/* Views / tab content transitions */
|
||||
.view { display: none; animation: viewFadeIn 0.2s ease-out; }
|
||||
.view.active { display: block; }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue