From e4b317f634496f5bdca3386427b308f83ddbc062 Mon Sep 17 00:00:00 2001 From: Kieran Date: Fri, 20 Jan 2023 22:59:26 +0000 Subject: [PATCH] Add note context menu --- package.json | 1 + src/Element/Note.css | 95 ++++++++++++++++++++++---------------- src/Element/NoteFooter.tsx | 78 +++++++++++++++++++++++-------- src/index.css | 4 ++ src/index.tsx | 1 + yarn.lock | 27 ++++++++++- 6 files changed, 146 insertions(+), 60 deletions(-) diff --git a/package.json b/package.json index 241c4c0df..8fbdd4b2d 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "@noble/secp256k1": "^1.7.0", "@protobufjs/base64": "^1.1.2", "@reduxjs/toolkit": "^1.9.1", + "@szhsin/react-menu": "^3.3.1", "@types/jest": "^29.2.5", "@types/node": "^18.11.18", "@types/react": "^18.0.26", diff --git a/src/Element/Note.css b/src/Element/Note.css index 111849518..a82e62306 100644 --- a/src/Element/Note.css +++ b/src/Element/Note.css @@ -1,43 +1,55 @@ .note.thread { - border-bottom: none; + border-bottom: none; } -.note > .header .reply { - font-size: var(--font-size-tiny); - color: var(--font-secondary-color); +.note>.header .reply { + font-size: var(--font-size-tiny); + color: var(--font-secondary-color); } -.note > .header > .info { - font-size: var(--font-size); - white-space: nowrap; - color: var(--font-secondary-color); +.note>.header>.info { + font-size: var(--font-size); + white-space: nowrap; + color: var(--font-secondary-color); } -.note > .body { - margin-top: 12px; - padding-left: 56px; - text-overflow: ellipsis; - white-space: pre-wrap; - word-break: normal; - overflow-x: hidden; - overflow-y: visible; +.note>.body { + margin-top: 12px; + padding-left: 56px; + text-overflow: ellipsis; + white-space: pre-wrap; + word-break: normal; + overflow-x: hidden; + overflow-y: visible; } -.note > .footer { - padding-left: 46px; +.note>.footer { + padding-left: 46px; } -.note > .header img:hover, .note > .header .name > .reply:hover, .note .body:hover { - cursor: pointer; +.note>.footer .ctx-menu { + background-color: var(--note-bg); + color: var(--font-secondary-color); + border: 1px solid var(--font-secondary-color); + border-radius: 16px; } -.note > .note-creator { +.note>.header img:hover, .note>.header .name>.reply:hover, .note .body:hover { + cursor: pointer; +} + +.note>.note-creator { margin-top: 12px; } @media (min-width: 720px) { - .note > .footer { margin-top: 24px; } - .note > .note-creator { margin-top: 24px; } + .note>.footer { + margin-top: 24px; + } + + .note>.note-creator { + margin-top: 24px; + } } @@ -55,8 +67,8 @@ } .indented { - border-left: 3px solid var(--gray-tertiary); - padding-left: 2px; + border-left: 3px solid var(--gray-tertiary); + padding-left: 2px; } .note:last-child { @@ -69,16 +81,16 @@ margin-bottom: 24px; } -.indented > .indented .note:last-child { +.indented>.indented .note:last-child { border-bottom-right-radius: 0px; margin-bottom: 0; } .indented .active { - background-color: var(--gray-tertiary); - margin-left: -5px; - border-left: 3px solid var(--highlight); - border-radius: 0; + background-color: var(--gray-tertiary); + margin-left: -5px; + border-left: 3px solid var(--highlight); + border-radius: 0; } .reaction-pill { @@ -95,7 +107,7 @@ } .reaction-pill.reacted { - color: var(--highlight); + color: var(--highlight); } .reaction-pill:hover { @@ -107,33 +119,36 @@ margin-right: auto; } -.note.active > .header .reply { +.note.active>.header .reply { color: var(--font-tertiary-color); } -.note.active > .header > .info { +.note.active>.header>.info { color: var(--font-tertiary-color); } -.note.active > .footer > .reaction-pill { +.note.active>.footer>.reaction-pill { color: var(--font-tertiary-color); } -.note.active > .footer > .reaction-pill.reacted { +.note.active>.footer>.reaction-pill.reacted { color: var(--highlight); } @media (prefers-color-scheme: light) { .indented .active { - background-color: var(--gray-secondary); + background-color: var(--gray-secondary); } - .note.active > .header .reply { + + .note.active>.header .reply { color: var(--font-secondary-color); } - .note.active > .header > .info { + + .note.active>.header>.info { color: var(--font-secondary-color); } - .note.active > .footer > .reaction-pill { + + .note.active>.footer>.reaction-pill { color: var(--font-secondary-color); } -} +} \ No newline at end of file diff --git a/src/Element/NoteFooter.tsx b/src/Element/NoteFooter.tsx index ce4057434..6ddd90eef 100644 --- a/src/Element/NoteFooter.tsx +++ b/src/Element/NoteFooter.tsx @@ -1,11 +1,12 @@ import { useMemo, useState } from "react"; import { useSelector } from "react-redux"; -import { faHeart, faReply, faThumbsDown, faTrash, faBolt, faRepeat } from "@fortawesome/free-solid-svg-icons"; +import { faHeart, faReply, faThumbsDown, faTrash, faBolt, faRepeat, faEllipsisVertical, faShareNodes } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { Menu, MenuItem } from '@szhsin/react-menu'; import { formatShort } from "Number"; import useEventPublisher from "Feed/EventPublisher"; -import { getReactions, normalizeReaction, Reaction } from "Util"; +import { getReactions, hexToBech32, normalizeReaction, Reaction } from "Util"; import { NoteCreator } from "Element/NoteCreator"; import LNURLTip from "Element/LNURLTip"; import useProfile from "Feed/ProfileFeed"; @@ -79,7 +80,7 @@ export default function NoteFooter(props: NoteFooterProps) { if (service) { return ( <> -
setTip(true)}> +
setTip(true)}>
@@ -111,7 +112,7 @@ export default function NoteFooter(props: NoteFooterProps) { } return ( <> -
react("+")}> +
react("+")}>
@@ -119,19 +120,57 @@ export default function NoteFooter(props: NoteFooterProps) { {formatShort(groupReactions[Reaction.Positive])}
-
react("-")}> -
- -
-
- {formatShort(groupReactions[Reaction.Negative])} -
-
{repostIcon()} ) } + async function share() { + const url = `${window.location.protocol}//${window.location.host}/e/${hexToBech32("npub", ev.Id)}`; + if ("share" in window.navigator) { + await window.navigator.share({ + title: "Snort", + url: url + }); + } else { + await navigator.clipboard.writeText(url); + } + } + + function menuItems() { + return ( + <> + react("-")}> +
+
+ +
+
+ {formatShort(groupReactions[Reaction.Negative])} +
+
+ Dislike +
+ share()}> +
+
+ +
+
+ Share +
+ + {isMine && ( + deleteEvent()}> +
+ +
+ Delete +
+ )} + + ) + } return ( <>
@@ -140,15 +179,16 @@ export default function NoteFooter(props: NoteFooterProps) {
+ +
+ +
+
} menuClassName="ctx-menu"> + {menuItems()} + + {reactionIcons()} {tipButton()} - {isMine && ( -
-
- deleteEvent()} /> -
-
- )}