Updated modals to be better for everyone.
This commit is contained in:
parent
3970bb5acd
commit
8ddeca2227
7 changed files with 78 additions and 211 deletions
|
@ -33,4 +33,15 @@
|
|||
width: 44px;
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
dialog:modal {
|
||||
width: initial;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
margin-top: 0;
|
||||
border-radius: 0;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -370,6 +370,11 @@ button.nav > img.icon {
|
|||
|
||||
.action-bar button.icon {
|
||||
transition: opacity 0.3s linear;
|
||||
padding: 5px;
|
||||
}
|
||||
.action-bar button.icon img.icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
.action-bar button.icon:hover {
|
||||
opacity: 1;
|
||||
|
@ -385,51 +390,45 @@ details.cw summary {
|
|||
}
|
||||
|
||||
/* Modal */
|
||||
.modal {
|
||||
position: fixed;
|
||||
z-index: var(--zModal);
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(255,255,255,0.4);
|
||||
opacity: 1;
|
||||
transition: opacity 0.2s linear;
|
||||
dialog:modal {
|
||||
width: 80%;
|
||||
max-width: 700px;
|
||||
padding: 20px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: var(--clrText);
|
||||
}
|
||||
dialog::backdrop {
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
}
|
||||
.modal.scrollable {
|
||||
overflow-y: auto;
|
||||
}
|
||||
.modal.closed {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
.modal-content {
|
||||
padding: 20px;
|
||||
overflow: auto;
|
||||
border-radius: 15px;
|
||||
background: var(--clrPanel);
|
||||
max-width: 700px;
|
||||
margin: 0 auto;
|
||||
margin-top: 35px;
|
||||
}
|
||||
.modal header {
|
||||
dialog header {
|
||||
display: flex;
|
||||
}
|
||||
.modal header label {
|
||||
dialog header label {
|
||||
flex: 1;
|
||||
font-weight: 800;
|
||||
font-size: var(--fsEnlarged);
|
||||
flex: 1;
|
||||
word-break: break-word;
|
||||
}
|
||||
.modal header button {
|
||||
dialog header button {
|
||||
font-size: 24px;
|
||||
}
|
||||
.modal .modal-floating-close-btn {
|
||||
position: sticky;
|
||||
top: 20px;
|
||||
left: 20px;
|
||||
dialog > img {
|
||||
/* fix for media preview */
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
dialog > .container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: var(--clrPanel);
|
||||
border-radius: 15px;
|
||||
padding: 20px;
|
||||
}
|
||||
dialog > .container .max-content {
|
||||
max-height: min(100vh/2, 500px);
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/* Post & Reply */
|
||||
|
@ -440,6 +439,7 @@ details.cw summary {
|
|||
textarea.post-input {
|
||||
display: block;
|
||||
width: 100%;
|
||||
min-height: 25px;
|
||||
}
|
||||
|
||||
.post-tools {
|
||||
|
@ -452,6 +452,9 @@ textarea.post-input {
|
|||
.post-tools > button.icon.cw.active {
|
||||
opacity: 1.0;
|
||||
}
|
||||
.post-tools > button[name='reply-all'] {
|
||||
margin-right: 5px;
|
||||
}
|
||||
input[type="text"].cw {
|
||||
border: none;
|
||||
border-bottom: solid 2px var(--clrWarn);
|
||||
|
@ -490,21 +493,6 @@ label[role="profile-nip5"] {
|
|||
display: block;
|
||||
}
|
||||
|
||||
/* Media Preview */
|
||||
|
||||
.modal .media-container {
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.modal .media-container > img {
|
||||
object-fit: scale-down;
|
||||
object-position: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* Profile Editor */
|
||||
|
||||
#profile-editor header {
|
||||
|
|
134
index.html
134
index.html
|
@ -51,11 +51,6 @@
|
|||
Sign In with Key
|
||||
<img src="./icon/key.svg" class="icon svg small invert"/>
|
||||
</button>
|
||||
<br/>
|
||||
<br/>
|
||||
<button class="btn-text" action="open-faqs">
|
||||
What's Nostr?
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -211,7 +206,6 @@
|
|||
<label>
|
||||
</div>
|
||||
<div class="row">
|
||||
<button class="action mr-some" role='about-nostr'>Read About Nostr</button>
|
||||
<button class="action" role="sign-out">
|
||||
Sign Out
|
||||
<img class="icon svg small invert" src="icon/sign-out.svg"/>
|
||||
|
@ -246,15 +240,12 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal closed" id="media-preview">
|
||||
<div class="media-container">
|
||||
<img action="close-media" src=""/>
|
||||
</div>
|
||||
<dialog id="media-preview">
|
||||
<img action="close-media" src=""/>
|
||||
<!-- TODO add loader to media preview -->
|
||||
</div>
|
||||
|
||||
<div class="modal closed" id="reply-modal">
|
||||
<div id="reply-modal-content" class="modal-content">
|
||||
</dialog>
|
||||
<dialog id="reply-modal">
|
||||
<div class="container">
|
||||
<header>
|
||||
<label>Reply To</label>
|
||||
<button class="icon" action="close-modal">
|
||||
|
@ -266,14 +257,14 @@
|
|||
<textarea id="reply-content" class="post-input"
|
||||
placeholder="Reply..."></textarea>
|
||||
<div class="post-tools">
|
||||
<button id="reply-button" class="action">Reply</button>
|
||||
<button class="action" name="reply-all" data-all="1">Reply All</button>
|
||||
<button class="action" name="reply">Reply</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="profile-editor" class="modal closed">
|
||||
<div class="modal-content">
|
||||
</dialog>
|
||||
<dialog id="profile-editor">
|
||||
<div class="container">
|
||||
<header>
|
||||
<label>Update Profile</label>
|
||||
<button class="icon" action="close-modal">
|
||||
|
@ -290,116 +281,21 @@
|
|||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="event-details" class="modal closed">
|
||||
<div class="modal-content">
|
||||
</dialog>
|
||||
<dialog id="event-details">
|
||||
<div class="container">
|
||||
<header>
|
||||
<label>Event Details</label>
|
||||
<button class="icon modal-floating-close-btn" action="close-modal">
|
||||
<img class="icon svg" src="icon/close-modal.svg"/>
|
||||
</button>
|
||||
</header>
|
||||
<div>
|
||||
<div class="max-content">
|
||||
<pre><code></code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</dialog>
|
||||
|
||||
<div id="faqs" class="modal scrollable closed">
|
||||
<button class="icon modal-floating-close-btn" action="close-modal">
|
||||
<img class="icon svg" src="icon/close-modal.svg"/>
|
||||
</button>
|
||||
<div class="page-content">
|
||||
<h1>Welcome to Nostr</h1>
|
||||
<p>The open social network for "literally" everyone.</p>
|
||||
|
||||
<h2>What is Nostr?</h2>
|
||||
<p>
|
||||
Nostr is a protocol, not a platform or an app. This means that
|
||||
users can pick and choose which clients (apps) to use and which
|
||||
relays (servers) they wish to connect to.
|
||||
</p>
|
||||
<p>Nostr uses encryption to validate content authors. This means
|
||||
that there is no centralized account system. We use
|
||||
<a href="https://en.wikipedia.org/wiki/Public-key_cryptography"
|
||||
target="_blank">public & private</a> keys to sign our
|
||||
content when we post. Do not confuse this with blockchain
|
||||
technology.
|
||||
</p>
|
||||
<p>
|
||||
Nostr stands for "Notes and Other Stuff Transmitted by Relays".
|
||||
</p>
|
||||
<p>
|
||||
Read more about the protocol <a
|
||||
href="https://github.com/nostr-protocol/nostr"
|
||||
target="_blank">here</a>.
|
||||
</p>
|
||||
|
||||
<h2>Apps</h2>
|
||||
<p>
|
||||
You are using one right now! You just haven't signed in yet to see
|
||||
the actual application. Close this modal to sign in with your key.
|
||||
</p>
|
||||
<p>
|
||||
A rich app ecosystem for Nostr. Anyone can build an app for the
|
||||
protocol that fits their needs. This is the best option for users
|
||||
as everyone has their own style. Another benifit is that you can
|
||||
use multiple apps with the same account.
|
||||
</p>
|
||||
<p>
|
||||
Since there are many apps for Nostr it allows developers to focus
|
||||
on building certain experiences. Some apps may offer features that
|
||||
others don't, such as direct messages, content viewing methods,
|
||||
etc. You are allowed to choose how you want to interact with
|
||||
Nostr.
|
||||
</p>
|
||||
<h3>Pick One</h3>
|
||||
<p>
|
||||
Here are a list of (trusted) apps that work with Nostr. Pick one
|
||||
that fits you.
|
||||
</p>
|
||||
<ul>
|
||||
<li><a href="https://damus.io" target="_blank">Damus</a> (iOS)</li>
|
||||
<li><a href="https://github.com/fiatjaf/noscl" target="_blank">noscl</a> (Linux, Windows, MacOS)</li>
|
||||
</ul>
|
||||
|
||||
<h3>Web Apps Warning</h3>
|
||||
<p>
|
||||
While the web is great for accessibility and is cross platform, it
|
||||
is riddled with security implications you should be aware of. The
|
||||
browser is susceptible to cross-site scripting (<a
|
||||
href="https://en.wikipedia.org/wiki/Cross-site_scripting"
|
||||
target="_blank">XSS</a>) attacks and extension malware. Therefore
|
||||
you should be sure any web app you use is audited and trusted.
|
||||
Additionally be aware of what apps you are using.
|
||||
</p>
|
||||
<p>
|
||||
Secondly it is recommended you use a browser extension to handle
|
||||
your Nostr key(s). This will delegate the signing process to an
|
||||
extension that a XSS attack can't access. This is where native apps
|
||||
have a stronger use case, but you should equally trust those as
|
||||
well.
|
||||
</p>
|
||||
|
||||
<h2>Relays</h2>
|
||||
<p>
|
||||
Relays are points of connection, a server. They allow you to read
|
||||
events (content) and write to it depending on it's configuration.
|
||||
Some may be read only, others may require some sort of payment to
|
||||
use. Some may simply clone other relays.
|
||||
</p>
|
||||
<p>
|
||||
Relays allow for specific needs and niches. You can host your
|
||||
own relay for your club or community (such as gaming, art, sciences,
|
||||
etc.) Or you can build your own relay with your own logic that
|
||||
dictates who can access what and how. This is great for all kinds
|
||||
of use cases for a range of users from individuals to businesses.
|
||||
</p>
|
||||
|
||||
<h2>Account Creation</h2>
|
||||
<p>You need to use a CLI tool. TODO fill this out.</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -197,12 +197,9 @@ function render_action_bar(model, ev, opts={}) {
|
|||
let str = html`<div class="action-bar">`;
|
||||
if (!shared && event_can_reply(ev)) {
|
||||
str += html`
|
||||
<button class="icon" title="Reply" action="reply-author" 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"/>
|
||||
</button>
|
||||
<button class="icon" title="Reply All" action="reply-all" data-evid="${ev.id}">
|
||||
<img class="icon svg small" src="icon/event-reply-all.svg"/>
|
||||
</button>
|
||||
<button class="icon react heart ${ab(liked, 'liked', '')}"
|
||||
action="react-like"
|
||||
data-reaction-id="${reaction_id}"
|
||||
|
|
|
@ -5,7 +5,6 @@ function init_settings(model) {
|
|||
embeds_el.addEventListener("click", on_click_toggle_embeds);
|
||||
embeds_el.checked = model.embeds != "friends";
|
||||
find_node("[role='sign-out']", el).addEventListener("click", on_click_sign_out);
|
||||
find_node("[role='about-nostr']", el).addEventListener("click", open_faqs);
|
||||
const rlist = find_node("#relay-list tbody", el);
|
||||
model.relays.forEach((str) => {
|
||||
rlist.appendChild(new_relay_item(str));
|
||||
|
|
|
@ -501,11 +501,13 @@ function init_postbox(model) {
|
|||
// Do reply box
|
||||
// TODO refactor & cleanup reply modal init
|
||||
find_node("#reply-content").addEventListener("input", oninput_post);
|
||||
find_node("#reply-button").addEventListener("click", onclick_reply);
|
||||
find_node("button[name='reply']")
|
||||
.addEventListener("click", onclick_reply);
|
||||
find_node("button[name='reply-all']")
|
||||
.addEventListener("click", onclick_reply);
|
||||
}
|
||||
async function onclick_reply(ev) {
|
||||
// Temp method
|
||||
do_send_reply();
|
||||
do_send_reply(ev.target.dataset.all == "1");
|
||||
}
|
||||
async function onclick_send(ev) {
|
||||
const el = view_get_timeline_el();
|
||||
|
@ -571,9 +573,6 @@ function onclick_any(ev) {
|
|||
const el = ev.target;
|
||||
const action = el.getAttribute("action");
|
||||
switch (action) {
|
||||
case "open-faqs":
|
||||
open_faqs();
|
||||
break;
|
||||
case "toggle-gnav":
|
||||
toggle_gnav(el);
|
||||
break;
|
||||
|
@ -607,11 +606,8 @@ function onclick_any(ev) {
|
|||
case "delete":
|
||||
delete_post(el.dataset.evid);
|
||||
break;
|
||||
case "reply-author":
|
||||
reply_author(el.dataset.evid);
|
||||
break;
|
||||
case "reply-all":
|
||||
reply_all(el.dataset.evid);
|
||||
case "reply-to":
|
||||
reply(el.dataset.evid);
|
||||
break;
|
||||
case "react-like":
|
||||
click_toggle_like(el);
|
||||
|
|
|
@ -65,7 +65,7 @@ function click_toggle_like(el) {
|
|||
*/
|
||||
function open_media_preview(url, type) {
|
||||
const el = find_node("#media-preview");
|
||||
el.classList.remove("closed");
|
||||
el.showModal();
|
||||
find_node("img", el).src = url;
|
||||
// TODO handle different medias such as audio and video
|
||||
// TODO add loading state & error checking
|
||||
|
@ -74,7 +74,7 @@ function open_media_preview(url, type) {
|
|||
/* close_media_preview closes any present media modal.
|
||||
*/
|
||||
function close_media_preview() {
|
||||
find_node("#media-preview").classList.add("closed");
|
||||
find_node("#media-preview").close();
|
||||
}
|
||||
|
||||
function delete_post_confirm(evid) {
|
||||
|
@ -86,11 +86,10 @@ function delete_post_confirm(evid) {
|
|||
delete_post(evid, reason)
|
||||
}
|
||||
|
||||
async function do_send_reply() {
|
||||
async function do_send_reply(all=false) {
|
||||
const modal = document.querySelector("#reply-modal");
|
||||
const replying_to = modal.querySelector("#replying-to");
|
||||
const evid = replying_to.dataset.evid;
|
||||
const all = replying_to.dataset.toAll != "";
|
||||
const reply_content_el = document.querySelector("#reply-content");
|
||||
const content = reply_content_el.value;
|
||||
await send_reply(content, evid, all);
|
||||
|
@ -98,29 +97,20 @@ async function do_send_reply() {
|
|||
close_modal(modal);
|
||||
}
|
||||
|
||||
function reply(evid, all=false) {
|
||||
function reply(evid) {
|
||||
const ev = DAMUS.all_events[evid]
|
||||
const modal = document.querySelector("#reply-modal")
|
||||
const replybox = modal.querySelector("#reply-content")
|
||||
const replying_to = modal.querySelector("#replying-to")
|
||||
replying_to.dataset.evid = evid
|
||||
replying_to.dataset.toAll = all ? "all" : "";
|
||||
replying_to.innerHTML = render_event_nointeract(DAMUS, ev, {
|
||||
is_composing: true,
|
||||
nobar: true
|
||||
});
|
||||
modal.classList.remove("closed")
|
||||
modal.showModal();
|
||||
replybox.focus()
|
||||
}
|
||||
|
||||
function reply_author(evid) {
|
||||
reply(evid);
|
||||
}
|
||||
|
||||
function reply_all(evid) {
|
||||
reply(evid, true);
|
||||
}
|
||||
|
||||
function update_favicon(path) {
|
||||
let link = document.querySelector("link[rel~='icon']");
|
||||
const head = document.getElementsByTagName('head')[0]
|
||||
|
@ -194,18 +184,8 @@ function open_thread(thread_id) {
|
|||
view_timeline_apply_mode(DAMUS, VM_THREAD, { thread_id });
|
||||
}
|
||||
|
||||
function open_faqs() {
|
||||
find_node("#faqs").classList.remove("closed");
|
||||
}
|
||||
|
||||
function close_modal(el) {
|
||||
while (el) {
|
||||
if (el.classList.contains("modal")) {
|
||||
el.classList.add("closed");
|
||||
break;
|
||||
}
|
||||
el = el.parentElement;
|
||||
}
|
||||
find_parent(el, "dialog").close();
|
||||
}
|
||||
|
||||
function on_click_show_event_details(evid) {
|
||||
|
@ -214,7 +194,7 @@ function on_click_show_event_details(evid) {
|
|||
if (!ev)
|
||||
return;
|
||||
const el = find_node("#event-details");
|
||||
el.classList.remove("closed");
|
||||
el.showModal();
|
||||
find_node("code", el).innerText = JSON.stringify(ev, null, "\t");
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue