Added URL history paths & loading

This commit is contained in:
Thomas Mathews 2023-01-24 12:23:04 -08:00
parent f169ee7bf6
commit 1df924df1b
4 changed files with 128 additions and 82 deletions

View file

@ -7,36 +7,36 @@
<meta http-equiv="Content-Security-Policy" <meta http-equiv="Content-Security-Policy"
content="default-src 'none'; manifest-src 'self'; connect-src 'self' ws: wss:; script-src 'self'; script-src-elem 'self'; script-src-attr 'none'; style-src 'self' fonts.googleapis.com; img-src http: https: data:; media-src *; font-src 'self' fonts.gstatic.com; child-src 'none';" /> content="default-src 'none'; manifest-src 'self'; connect-src 'self' ws: wss:; script-src 'self'; script-src-elem 'self'; script-src-attr 'none'; style-src 'self' fonts.googleapis.com; img-src http: https: data:; media-src *; font-src 'self' fonts.gstatic.com; child-src 'none';" />
<title>Yo, Sup</title> <title>Yo, Sup</title>
<link rel="manifest" href="pwa/manifest.json"/> <link rel="manifest" href="/pwa/manifest.json"/>
<link rel="icon" href="icon/icon.svg" type="image/svg+xml"/> <link rel="icon" href="/icon/icon.svg" type="image/svg+xml"/>
<link rel="apple-touch-icon" href="pwa/icon-256.png"/> <link rel="apple-touch-icon" href="/pwa/icon-256.png"/>
<link rel="stylesheet" href="css/vars.css?v=1"> <link rel="stylesheet" href="/css/vars.css?v=1">
<link rel="stylesheet" href="css/utils.css?v=1"> <link rel="stylesheet" href="/css/utils.css?v=1">
<link rel="stylesheet" href="css/styles.css?v=13"> <link rel="stylesheet" href="/css/styles.css?v=13">
<link rel="stylesheet" href="css/responsive.css?v=10"> <link rel="stylesheet" href="/css/responsive.css?v=10">
<script defer src="js/ui/safe-html.js?v=1"></script> <script defer src="/js/ui/safe-html.js?v=1"></script>
<script defer src="js/util.js?v=5"></script> <script defer src="/js/util.js?v=5"></script>
<script defer src="js/ui/util.js?v=8"></script> <script defer src="/js/ui/util.js?v=8"></script>
<script defer src="js/ui/render.js?v=15"></script> <script defer src="/js/ui/render.js?v=15"></script>
<script defer src="js/ui/state.js?v=1"></script> <script defer src="/js/ui/state.js?v=1"></script>
<script defer src="js/ui/fmt.js?v=1"></script> <script defer src="/js/ui/fmt.js?v=1"></script>
<script defer src="js/ui/profile.js?v=1"></script> <script defer src="/js/ui/profile.js?v=1"></script>
<script defer src="js/ui/settings.js?v=1"></script> <script defer src="/js/ui/settings.js?v=1"></script>
<script defer src="js/ui/dm.js?v=1"></script> <script defer src="/js/ui/dm.js?v=1"></script>
<script defer src="js/noble-secp256k1.js?v=1"></script> <script defer src="/js/noble-secp256k1.js?v=1"></script>
<script defer src="js/bech32.js?v=1"></script> <script defer src="/js/bech32.js?v=1"></script>
<script defer src="js/nostr.js?v=7"></script> <script defer src="/js/nostr.js?v=7"></script>
<script defer src="js/core.js?v=1"></script> <script defer src="/js/core.js?v=1"></script>
<script defer src="js/model.js?v=1"></script> <script defer src="/js/model.js?v=1"></script>
<script defer src="js/contacts.js?v=1"></script> <script defer src="/js/contacts.js?v=1"></script>
<script defer src="js/event.js?v=1"></script> <script defer src="/js/event.js?v=1"></script>
<script defer src="js/lib.js?v=1"></script> <script defer src="/js/lib.js?v=1"></script>
<script defer src="js/main.js?v=1"></script> <script defer src="/js/main.js?v=1"></script>
</head> </head>
<body> <body>
<div id="container-busy"> <div id="container-busy">
<div class="loader" title="Loading..."> <div class="loader" title="Loading...">
<img class="dark-invert" src="icon/loader-fragment.svg"/> <img class="dark-invert" src="/icon/loader-fragment.svg"/>
</div> </div>
</div> </div>
<div id="container-welcome" class="hide"> <div id="container-welcome" class="hide">
@ -44,12 +44,12 @@
<div class="padded"> <div class="padded">
<h1> <h1>
Yo, Sup? Yo, Sup?
<img class="icon svg" src="icon/logo-inverted.svg"/> <img class="icon svg" src="/icon/logo-inverted.svg"/>
</h1> </h1>
<p>The blue bird experience for Nostr.</p> <p>The blue bird experience for Nostr.</p>
<button class="action" action="sign-in"> <button class="action" action="sign-in">
Sign In with Key Sign In with Key
<img src="./icon/key.svg" class="icon svg small invert"/> <img src="/icon/key.svg" class="icon svg small invert"/>
</button> </button>
</div> </div>
</div> </div>
@ -58,24 +58,24 @@
<div id="container-app" class="hide"> <div id="container-app" class="hide">
<nav id="gnav"> <nav id="gnav">
<button class="icon" action="toggle-gnav" title="Open Menu"> <button class="icon" action="toggle-gnav" title="Open Menu">
<img class="icon svg invert" src="icon/logo.svg"/> <img class="icon svg invert" src="/icon/logo.svg"/>
</button> </button>
<button class="icon" action="open-view" data-view="friends" title="Home"> <button class="icon" action="open-view" data-view="friends" title="Home">
<img class="icon svg invert" src="icon/home.svg"/> <img class="icon svg invert" src="/icon/home.svg"/>
</button> </button>
<button class="icon" action="open-view" data-view="explore" title="Explore"> <button class="icon" action="open-view" data-view="explore" title="Explore">
<img class="icon svg invert" src="icon/explore.svg"/> <img class="icon svg invert" src="/icon/explore.svg"/>
</button> </button>
<button class="icon" action="open-view" data-view="dm" title="Direct Messages"> <button class="icon" action="open-view" data-view="dm" title="Direct Messages">
<img class="icon svg invert" src="icon/messages.svg"/> <img class="icon svg invert" src="/icon/messages.svg"/>
<div class="new-notifications hide" role="dm"></div> <div class="new-notifications hide" role="dm"></div>
</button> </button>
<button class="icon" action="open-view" data-view="notifications" title="Notifications"> <button class="icon" action="open-view" data-view="notifications" title="Notifications">
<img class="icon svg invert" src="icon/notifications.svg"/> <img class="icon svg invert" src="/icon/notifications.svg"/>
<div class="new-notifications hide" role="activity"></div> <div class="new-notifications hide" role="activity"></div>
</button> </button>
<button class="icon" action="open-view" data-view="settings" title="Settings"> <button class="icon" action="open-view" data-view="settings" title="Settings">
<img class="icon svg invert" src="icon/settings.svg"/> <img class="icon svg invert" src="/icon/settings.svg"/>
</button> </button>
</nav> </nav>
<div id="container"> <div id="container">
@ -83,33 +83,33 @@
<div id="nav" class="flex-noshrink vertical-hide"> <div id="nav" class="flex-noshrink vertical-hide">
<div data-active="home"> <div data-active="home">
<div id="app-icon-logo"> <div id="app-icon-logo">
<img class="icon svg" title="Damus" src="icon/logo-inverted.svg"/> <img class="icon svg" title="Damus" src="/icon/logo-inverted.svg"/>
</div> </div>
<button action="open-view" data-view="friends" class="nav icon" <button action="open-view" data-view="friends" class="nav icon"
title="Home"> title="Home">
<img class="icon svg inactive" src="icon/home.svg"/> <img class="icon svg inactive" src="/icon/home.svg"/>
<img class="icon svg active" src="icon/home-active.svg"/> <img class="icon svg active" src="/icon/home-active.svg"/>
</button> </button>
<button action="open-view" data-view="explore" class="nav icon" <button action="open-view" data-view="explore" class="nav icon"
title="Explore"> <img class="icon svg inactive" src="icon/explore.svg"/> title="Explore"> <img class="icon svg inactive" src="/icon/explore.svg"/>
<img class="icon svg active" src="icon/explore-active.svg"/> <img class="icon svg active" src="/icon/explore-active.svg"/>
</button> </button>
<button action="open-view" data-view="dm" class="nav icon" <button action="open-view" data-view="dm" class="nav icon"
title="Direct Messages"> title="Direct Messages">
<img class="icon svg inactive" src="icon/messages.svg"/> <img class="icon svg inactive" src="/icon/messages.svg"/>
<img class="icon svg active" src="icon/messages-active.svg"/> <img class="icon svg active" src="/icon/messages-active.svg"/>
<div class="new-notifications hide" role="dm"></div> <div class="new-notifications hide" role="dm"></div>
</button> </button>
<button action="open-view" data-view="notifications" <button action="open-view" data-view="notifications"
class="nav icon" title="Notifications"> class="nav icon" title="Notifications">
<img class="icon svg inactive" src="icon/notifications.svg"/> <img class="icon svg inactive" src="/icon/notifications.svg"/>
<img class="icon svg active" src="icon/notifications-active.svg"/> <img class="icon svg active" src="/icon/notifications-active.svg"/>
<div class="new-notifications hide" role="activity"></div> <div class="new-notifications hide" role="activity"></div>
</button> </button>
<button action="open-view" data-view="settings" <button action="open-view" data-view="settings"
title="Settings" class="nav icon"> title="Settings" class="nav icon">
<img class="icon svg inactive" src="icon/settings.svg"/> <img class="icon svg inactive" src="/icon/settings.svg"/>
<img class="icon svg active" src="icon/settings-active.svg"/> <img class="icon svg active" src="/icon/settings-active.svg"/>
</button> </button>
</div> </div>
</div> </div>
@ -128,9 +128,9 @@
Mark All Read Mark All Read
</button> </button>
<img class="pfp hide" role="their-pfp" data-pubkey="" <img class="pfp hide" role="their-pfp" data-pubkey=""
src="icon/no-user.svg"/> src="/icon/no-user.svg"/>
<img class="pfp hide" role="my-pfp" data-pubkey="" <img class="pfp hide" role="my-pfp" data-pubkey=""
src="icon/no-user.svg"/> src="/icon/no-user.svg"/>
</div> </div>
</header> </header>
<div id="newpost"> <div id="newpost">
@ -142,7 +142,7 @@
<button class="cw icon" role="toggle-cw" <button class="cw icon" role="toggle-cw"
title="Mark this message as sensitive."> title="Mark this message as sensitive.">
<img class="icon svg small" <img class="icon svg small"
src="icon/content-warning.svg"/> src="/icon/content-warning.svg"/>
</button> </button>
<button class="action" role="send" <button class="action" role="send"
id="post-button" disabled>Send</button> id="post-button" disabled>Send</button>
@ -154,14 +154,14 @@
<div class="profile-tools"> <div class="profile-tools">
<button class="icon" role="message-user" <button class="icon" role="message-user"
title="Directly Message"> title="Directly Message">
<img class="icon svg" src="icon/message-user.svg"/> <img class="icon svg" src="/icon/message-user.svg"/>
</button> </button>
<button class="icon hide" role="edit-profile" <button class="icon hide" role="edit-profile"
title="Edit Profile"> title="Edit Profile">
<img class="icon svg" src="icon/edit-profile.svg"/></button> <img class="icon svg" src="/icon/edit-profile.svg"/></button>
<button class="icon" role="copy-pk" <button class="icon" role="copy-pk"
data-pk="" title="Copy Public Key"> data-pk="" title="Copy Public Key">
<img class="icon svg" src="icon/pubkey.svg"/></button> <img class="icon svg" src="/icon/pubkey.svg"/></button>
<button class="action" role="follow-user" <button class="action" role="follow-user"
data-pk="">Follow</button> data-pk="">Follow</button>
</div> </div>
@ -173,7 +173,7 @@
</div> </div>
<div class="loading-events"> <div class="loading-events">
<div class="loader" title="Loading..."> <div class="loader" title="Loading...">
<img class="dark-invert" src="icon/loader-fragment.svg"/> <img class="dark-invert" src="/icon/loader-fragment.svg"/>
</div> </div>
</div> </div>
<div id="show-new" class="show-new bottom-border hide"> <div id="show-new" class="show-new bottom-border hide">
@ -193,7 +193,7 @@
<header> <header>
<label>Relays</label> <label>Relays</label>
<button id="add-relay" class="btn-text"> <button id="add-relay" class="btn-text">
<img class="svg icon small" src="icon/add-relay.svg"/> <img class="svg icon small" src="/icon/add-relay.svg"/>
</button> </button>
</header> </header>
<table id="relay-list" class="row"> <table id="relay-list" class="row">
@ -218,7 +218,7 @@
<div class="row"> <div class="row">
<button class="action" role="sign-out"> <button class="action" role="sign-out">
Sign Out Sign Out
<img class="icon svg small invert" src="icon/sign-out.svg"/> <img class="icon svg small invert" src="/icon/sign-out.svg"/>
</button> </button>
</div> </div>
</section> </section>
@ -260,7 +260,7 @@
<header> <header>
<label>Reply To</label> <label>Reply To</label>
<button class="icon" action="close-modal"> <button class="icon" action="close-modal">
<img class="icon svg" src="icon/close-modal.svg"/> <img class="icon svg" src="/icon/close-modal.svg"/>
</button> </button>
</header> </header>
<div id="replying-to"></div> <div id="replying-to"></div>
@ -279,7 +279,7 @@
<header> <header>
<label>Update Profile</label> <label>Update Profile</label>
<button class="icon" action="close-modal"> <button class="icon" action="close-modal">
<img class="icon svg" src="icon/close-modal.svg"/> <img class="icon svg" src="/icon/close-modal.svg"/>
</button> </button>
</header> </header>
<div> <div>
@ -298,7 +298,7 @@
<header> <header>
<label>Event Details</label> <label>Event Details</label>
<button class="icon modal-floating-close-btn" action="close-modal"> <button class="icon modal-floating-close-btn" action="close-modal">
<img class="icon svg" src="icon/close-modal.svg"/> <img class="icon svg" src="/icon/close-modal.svg"/>
</button> </button>
</header> </header>
<div class="max-content"> <div class="max-content">

View file

@ -1,9 +1,9 @@
let DAMUS = new_model(); let DAMUS = new_model();
// TODO autogenerate these constants with a bash script // TODO autogenerate these constants with a bash script
const IMG_EVENT_LIKED = "icon/event-liked.svg"; const IMG_EVENT_LIKED = "/icon/event-liked.svg";
const IMG_EVENT_LIKE = "icon/event-like.svg"; const IMG_EVENT_LIKE = "/icon/event-like.svg";
const IMG_NO_USER = "icon/no-user.svg"; const IMG_NO_USER = "/icon/no-user.svg";
const SID_META = "meta"; const SID_META = "meta";
const SID_HISTORY = "history"; const SID_HISTORY = "history";
@ -103,10 +103,10 @@ async function webapp_init() {
model_process_event(model, undefined, ev); model_process_event(model, undefined, ev);
}); });
log_debug("loaded events", Object.keys(model.all_events).length); log_debug("loaded events", Object.keys(model.all_events).length);
*/
// Update our view and apply timer methods once all data is ready to go. var { mode, opts, valid } = parse_url_mode();
view_timeline_update(model);*/ view_timeline_apply_mode(model, mode, opts, !valid);
view_timeline_apply_mode(model, VM_FRIENDS, {hide_replys: true});
on_timer_timestamps(); on_timer_timestamps();
on_timer_invalidations(); on_timer_invalidations();
on_timer_save(); on_timer_save();
@ -115,6 +115,36 @@ async function webapp_init() {
return pool; return pool;
} }
function parse_url_mode() {
var mode;
var valid = true;
var opts = {};
var parts = window.location.pathname.split("/").slice(1);
for (var key in VIEW_NAMES) {
if (VIEW_NAMES[key].toLowerCase() == parts[0]) {
mode = key;
break;
}
}
if (!mode) {
mode = VM_FRIENDS;
valid = false;
}
switch (mode) {
case VM_FRIENDS:
opts.hide_replys = true;
break;
case VM_THREAD:
opts.thread_id = parts[1];
break;
case VM_DM_THREAD:
case VM_USER:
opts.pubkey = parts[1];
break;
}
return { mode, opts, valid };
}
function on_timer_timestamps() { function on_timer_timestamps() {
setTimeout(() => { setTimeout(() => {
view_timeline_update_timestamps(); view_timeline_update_timestamps();

View file

@ -198,7 +198,7 @@ function render_action_bar(model, ev, opts={}) {
if (!shared && event_can_reply(ev)) { if (!shared && event_can_reply(ev)) {
str += html` str += html`
<button class="icon" title="Reply" action="reply-to" data-evid="${ev.id}"> <button class="icon" title="Reply" action="reply-to" data-evid="${ev.id}">
<img class="icon svg small" src="icon/event-reply.svg"/> <img class="icon svg small" src="/icon/event-reply.svg"/>
</button> </button>
<button class="icon react heart ${ab(liked, 'liked', '')}" <button class="icon react heart ${ab(liked, 'liked', '')}"
action="react-like" action="react-like"
@ -212,28 +212,28 @@ function render_action_bar(model, ev, opts={}) {
if (!shared) { if (!shared) {
str += html`<button class="icon" title="Share" data-evid="${ev.id}" str += html`<button class="icon" title="Share" data-evid="${ev.id}"
action="share"> action="share">
<img class="icon svg small" src="icon/event-share.svg"/> <img class="icon svg small" src="/icon/event-share.svg"/>
</button>`; </button>`;
} }
str += ` str += `
<button class="icon" title="View Thread" action="open-thread" <button class="icon" title="View Thread" action="open-thread"
data-thread-id="${thread_root}"> data-thread-id="${thread_root}">
<img class="icon svg small" src="icon/open-thread.svg"/> <img class="icon svg small" src="/icon/open-thread.svg"/>
</button> </button>
<button class="icon" title="View Replies" action="open-thread" <button class="icon" title="View Replies" action="open-thread"
data-thread-id="${ev.id}"> data-thread-id="${ev.id}">
<img class="icon svg small" src="icon/open-thread-here.svg"/> <img class="icon svg small" src="/icon/open-thread-here.svg"/>
</button> </button>
<button class="icon" title="View Event JSON" action="show-event-json" <button class="icon" title="View Event JSON" action="show-event-json"
data-evid="${ev.id}"> data-evid="${ev.id}">
<img class="icon svg small" src="icon/event-details.svg"/> <img class="icon svg small" src="/icon/event-details.svg"/>
</button>`; </button>`;
if (can_delete) { if (can_delete) {
const delete_id = shared ? shared.share_evid : ev.id; const delete_id = shared ? shared.share_evid : ev.id;
str += html` str += html`
<button class="icon" title="Delete" action="confirm-delete" <button class="icon" title="Delete" action="confirm-delete"
data-evid="${delete_id}"> data-evid="${delete_id}">
<img class="icon svg small" src="icon/event-delete.svg"/> <img class="icon svg small" src="/icon/event-delete.svg"/>
</button>` </button>`
} }
return str + "</div>"; return str + "</div>";

View file

@ -7,6 +7,16 @@ const VM_THREAD = "thread"; // all events in response to target event
const VM_USER = "user"; // all events by pubkey const VM_USER = "user"; // all events by pubkey
const VM_SETTINGS = "settings"; const VM_SETTINGS = "settings";
const VIEW_NAMES= {};
VIEW_NAMES[VM_FRIENDS] = "Home";
VIEW_NAMES[VM_EXPLORE] = "Explore";
VIEW_NAMES[VM_NOTIFICATIONS] = "Notifications";
VIEW_NAMES[VM_DM] = "Messages";
VIEW_NAMES[VM_DM_THREAD] = "DM";
VIEW_NAMES[VM_USER] = "Profile";
VIEW_NAMES[VM_THREAD] = "Thread";
VIEW_NAMES[VM_SETTINGS] = "Settings";
function view_get_timeline_el() { function view_get_timeline_el() {
return find_node("#timeline"); return find_node("#timeline");
} }
@ -48,10 +58,6 @@ function view_timeline_apply_mode(model, mode, opts={}, push_state=true) {
} }
} }
// Push a new state to the browser history stack
if (push_state)
history.pushState({mode, opts}, '');
// Fetch history for certain views // Fetch history for certain views
if (mode == VM_THREAD) { if (mode == VM_THREAD) {
view_show_spinner(true); view_show_spinner(true);
@ -65,18 +71,28 @@ function view_timeline_apply_mode(model, mode, opts={}, push_state=true) {
reset_notifications(model); reset_notifications(model);
} }
const names = {}; const names = VIEW_NAMES;
names[VM_FRIENDS] = "Home";
names[VM_EXPLORE] = "Explore";
names[VM_NOTIFICATIONS] = "Notifications";
names[VM_DM] = "Messages";
names[VM_DM_THREAD] = "Messages";
names[VM_USER] = "Profile";
names[VM_THREAD] = "Thread";
names[VM_SETTINGS] = "Settings";
let name = names[mode]; let name = names[mode];
let profile; let profile;
// Push a new state to the browser history stack
if (push_state) {
let pieces = [name.toLowerCase()];
switch (mode) {
case VM_FRIENDS:
pieces = [];
break;
case VM_THREAD:
pieces.push(thread_id);
break;
case VM_USER:
case VM_DM_THREAD:
pieces.push(pubkey);
break;
}
history.pushState({mode, opts}, "", "/"+pieces.join("/"));
}
el.dataset.mode = mode; el.dataset.mode = mode;
delete el.dataset.threadId; delete el.dataset.threadId;
delete el.dataset.pubkey; delete el.dataset.pubkey;