diff --git a/web/js/contacts.js b/web/js/contacts.js index 3048f08..91e3c81 100644 --- a/web/js/contacts.js +++ b/web/js/contacts.js @@ -43,7 +43,7 @@ async function contacts_save(contacts) { window.alert("An error occured saving contacts. Check console."); reject(ev); }; - }; + } return dbcall(_contacts_save); } @@ -76,10 +76,13 @@ async function contacts_load(model) { async function dbcall(fn) { return new Promise((resolve, reject) => { - var open = indexedDB.open("damus", 2); + var open = indexedDB.open("damus", 4); open.onupgradeneeded = (ev) => { const db = ev.target.result; - const os = db.createObjectStore("friends", {keyPath: "pubkey"}); + if (!db.objectStoreNames.contains("friends")) + db.createObjectStore("friends", {keyPath: "pubkey"}); + if (!db.objectStoreNames.contains("events")) + db.createObjectStore("events", {keyPath: "id"}); }; open.onsuccess = (ev) => { fn(ev, resolve, reject); diff --git a/web/js/damus.js b/web/js/damus.js index 56544f4..3f8bc04 100644 --- a/web/js/damus.js +++ b/web/js/damus.js @@ -1,7 +1,6 @@ let DAMUS const BOOTSTRAP_RELAYS = [ - "wss://nostr.rdfriedl.com", "wss://relay.damus.io", "wss://nostr-relay.wlvs.space", "wss://nostr-pub.wellorder.net" @@ -50,6 +49,8 @@ async function damus_web_init_ready() { unknowns: "unknowns", dms: "dms", } + model.ids = ids + model.pool = pool let err; err = await contacts_load(model); @@ -57,10 +58,9 @@ async function damus_web_init_ready() { window.alert("Unable to load contacts."); } - model.ids = ids - model.pool = pool - model.view_el = document.querySelector("#view") - //load_cache(model) + await model_load_events(model, (ev)=> { + model_process_event(model, ev); + }); view_timeline_apply_mode(model, VM_FRIENDS); document.addEventListener('visibilitychange', () => { @@ -107,6 +107,7 @@ function on_pool_notice(relay, notice) { // on_pool_eose occurs when all storage from a relay has been sent to the // client for a labeled (sub_id) REQ. async function on_pool_eose(relay, sub_id) { + log_info(`EOSE(${relay.url}): ${sub_id}`); const model = DAMUS; const { ids, pool } = model; switch (sub_id) { @@ -115,6 +116,9 @@ async function on_pool_eose(relay, sub_id) { // TODO filter out events to friends of friends on_eose_comments(ids, model, events, relay) pool.unsubscribe(ids.home, relay); + if (!model.inited) { + model.inited = true; + } break; case ids.profiles: model.pool.unsubscribe(ids.profiles, relay); @@ -137,18 +141,12 @@ function on_pool_ok(relay) { function on_pool_event(relay, sub_id, ev) { const model = DAMUS; - const { ids, pool } = model; + // Simply ignore any events that happened in the future. if (new Date(ev.created_at * 1000) > new Date()) { - // Simply ignore any events that happened in the future. return; } - - // Process event and apply side effects - if (!model.all_events[ev.id]) { - model.all_events[ev.id] = ev; - model_process_event(model, ev); - } + model_process_event(model, ev); } function on_eose_profiles(ids, model, relay) { diff --git a/web/js/event.js b/web/js/event.js index d86b6a1..e775aa5 100644 --- a/web/js/event.js +++ b/web/js/event.js @@ -121,3 +121,51 @@ function event_parse_reaction(ev) { } } +async function model_save_events(model) { + function _events_save(ev, resolve, reject) { + const db = ev.target.result; + let tx = db.transaction("events", "readwrite"); + let store = tx.objectStore("events"); + for (const evid in model.all_events) { + store.put(model.all_events[evid]); + } + tx.oncomplete = (ev) => { + db.close(); + resolve(); + log_debug("saved events!"); + }; + tx.onerror = (ev) => { + db.close(); + log_error("failed to save events"); + reject(ev); + }; + } + return dbcall(_events_save); +} + +async function model_load_events(model, fn) { + function _events_load(ev, resolve, reject) { + const db = ev.target.result; + const tx = db.transaction("events", "readonly"); + const store = tx.objectStore("events"); + const cursor = store.openCursor(); + cursor.onsuccess = (ev) => { + var cursor = ev.target.result; + if (cursor) { + fn(cursor.value); + cursor.continue(); + } else { + db.close(); + resolve(); + log_debug("Successfully loaded events"); + } + } + cursor.onerror = (ev) => { + db.close(); + reject(ev); + log_error("Could not load events."); + }; + } + return dbcall(_events_load); +} + diff --git a/web/js/model.js b/web/js/model.js index 9c92a28..51e85d7 100644 --- a/web/js/model.js +++ b/web/js/model.js @@ -3,6 +3,11 @@ * and fetching of unknown pubkey profiles. */ function model_process_event(model, ev) { + if (model.all_events[ev.id]) { + return; + } + + model.all_events[ev.id] = ev; ev.refs = event_get_tag_refs(ev.tags); ev.pow = event_calculate_pow(ev); diff --git a/web/js/ui/state.js b/web/js/ui/state.js index b26be60..2bd1151 100644 --- a/web/js/ui/state.js +++ b/web/js/ui/state.js @@ -96,16 +96,11 @@ function view_timeline_update(model) { continue; } - const html = render_event(model, ev, {}); // Put it back on the stack to re-render if it's not ready. - if (html == "") { + if (!view_render_event(model, ev)) { left_overs.push(evid); continue; } - const div = document.createElement("div"); - div.innerHTML = html; - ev_el = div.firstChild; - model.elements[evid] = ev_el; // If the new element is newer than the latest & is viewable then // we want to increase the count of how many to add to view @@ -116,18 +111,23 @@ function view_timeline_update(model) { model.invalidated = model.invalidated.concat(left_overs); if (count > 0) { - view_set_show_count(count, true); + // If we have things to show and we have initted and we don't have + // anything update the current view + if (!latest_ev && model.inited) { + view_timeline_show_new(model); + } + view_set_show_count(count, true, !model.inited); } } -function view_set_show_count(count, add) { +function view_set_show_count(count, add=false, hide=false) { const show_el = find_node("#show-new") const num_el = find_node("#show-new span", show_el); if (add) { count += parseInt(num_el.innerText || 0) } num_el.innerText = count; - show_el.classList.toggle("hide", count <= 0); + show_el.classList.toggle("hide", hide || count <= 0); } function view_timeline_show_new(model) { @@ -163,6 +163,20 @@ function view_timeline_show_new(model) { view_timeline_update_timestamps(); } +function view_render_event(model, ev, force=false) { + if (model.elements[ev.id] && !force) + return model.elements[ev.id]; + const html = render_event(model, ev, {}); + if (html == "") { + return; + } + const div = document.createElement("div"); + div.innerHTML = html; + const el = div.firstChild; + model.elements[ev.id] = el; + return el; +} + function view_timeline_update_profiles(model, ev) { let xs, html; const el = view_get_timeline_el();