Add note context menu

This commit is contained in:
Kieran 2023-01-20 22:59:26 +00:00
parent 34762d7039
commit e4b317f634
Signed by: Kieran
GPG Key ID: DE71CEB3925BE941
6 changed files with 146 additions and 60 deletions

View File

@ -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",

View File

@ -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);
}
}

View File

@ -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 (
<>
<div className="reaction-pill" onClick={(e) => setTip(true)}>
<div className="reaction-pill" onClick={() => setTip(true)}>
<div className="reaction-pill-icon">
<FontAwesomeIcon icon={faBolt} />
</div>
@ -111,7 +112,7 @@ export default function NoteFooter(props: NoteFooterProps) {
}
return (
<>
<div className={`reaction-pill ${hasReacted('+') ? 'reacted' : ''} `} onClick={(e) => react("+")}>
<div className={`reaction-pill ${hasReacted('+') ? 'reacted' : ''} `} onClick={() => react("+")}>
<div className="reaction-pill-icon">
<FontAwesomeIcon icon={faHeart} />
</div>
@ -119,19 +120,57 @@ export default function NoteFooter(props: NoteFooterProps) {
{formatShort(groupReactions[Reaction.Positive])}
</div>
</div>
<div className={`reaction-pill ${hasReacted('-') ? 'reacted' : ''}`} onClick={(e) => react("-")}>
<div className="reaction-pill-icon">
<FontAwesomeIcon icon={faThumbsDown} />
</div>
<div className="reaction-pill-number">
{formatShort(groupReactions[Reaction.Negative])}
</div>
</div>
{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 (
<>
<MenuItem onClick={() => react("-")}>
<div className={`reaction-pill ${hasReacted('-') ? 'reacted' : ''}`}>
<div className="reaction-pill-icon">
<FontAwesomeIcon icon={faThumbsDown} />
</div>
<div className="reaction-pill-number">
{formatShort(groupReactions[Reaction.Negative])}
</div>
</div>
Dislike
</MenuItem>
<MenuItem onClick={() => share()}>
<div className="reaction-pill mr-auto">
<div className="reaction-pill-icon">
<FontAwesomeIcon icon={faShareNodes} />
</div>
</div>
Share
</MenuItem>
{isMine && (
<MenuItem onClick={() => deleteEvent()}>
<div className="reaction-pill trash-icon">
<FontAwesomeIcon icon={faTrash} />
</div>
Delete
</MenuItem>
)}
</>
)
}
return (
<>
<div className="footer">
@ -140,15 +179,16 @@ export default function NoteFooter(props: NoteFooterProps) {
<FontAwesomeIcon icon={faReply} />
</div>
</div>
<Menu menuButton={<div className="reaction-pill">
<div className="reaction-pill-icon">
<FontAwesomeIcon icon={faEllipsisVertical} />
</div>
</div>} menuClassName="ctx-menu">
{menuItems()}
</Menu>
{reactionIcons()}
{tipButton()}
{isMine && (
<div className="reaction-pill trash-icon">
<div className="reaction-pill-icon">
<FontAwesomeIcon icon={faTrash} onClick={(e) => deleteEvent()} />
</div>
</div>
)}
</div>
<NoteCreator
autoFocus={true}

View File

@ -320,6 +320,10 @@ body.scroll-lock {
margin-bottom: 10px;
}
.mr-auto {
margin-right: auto;
}
.tabs {
display: flex;
align-content: center;

View File

@ -1,4 +1,5 @@
import './index.css';
import '@szhsin/react-menu/dist/index.css';
import { StrictMode } from 'react';
import { QueryClient, QueryClientProvider } from 'react-query';

View File

@ -1804,6 +1804,14 @@
"@svgr/plugin-svgo" "^5.5.0"
loader-utils "^2.0.0"
"@szhsin/react-menu@^3.3.1":
version "3.3.1"
resolved "https://registry.yarnpkg.com/@szhsin/react-menu/-/react-menu-3.3.1.tgz#c974c887bfcf94aca4c4cc07688a3c20d4e952bd"
integrity sha512-e8vK+N1YWwTdYXElvRRf5GIImtcDecqTCzpAa0DkGAknKwfQwtQtUnBn+DECodwsWi5H5ONKTU+kn0qJ70hEYQ==
dependencies:
prop-types "^15.7.2"
react-transition-state "^1.1.5"
"@tootallnate/once@1":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
@ -6035,6 +6043,11 @@ js-sha3@0.8.0:
resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840"
integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==
js-stylesheet@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/js-stylesheet/-/js-stylesheet-0.0.1.tgz#12cc1451220e454184b46de3b098c0d154762c38"
integrity sha512-jSPbDIaHlK8IFXEbE6MZkeAQshRHHxxOcQ+LCZejm3KpW+POpi2TE3GXWoFsOOG2+AhCTWHjD7AXRFt3FDm8Zw==
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
@ -7790,7 +7803,7 @@ prompts@^2.0.1, prompts@^2.4.2:
kleur "^3.0.3"
sisteransi "^1.0.5"
prop-types@^15.0.0, prop-types@^15.8.1:
prop-types@^15.0.0, prop-types@^15.7.2, prop-types@^15.8.1:
version "15.8.1"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
@ -7986,6 +7999,13 @@ react-markdown@^8.0.4:
unist-util-visit "^4.0.0"
vfile "^5.0.0"
react-menu@^0.0.10:
version "0.0.10"
resolved "https://registry.yarnpkg.com/react-menu/-/react-menu-0.0.10.tgz#c2b338cdd88e4c436325969239089e0752a142bc"
integrity sha512-SGl/OZljPUB1ITWBG2wt1p7hyE3Y449O9FUezxkKzu+JM5HWkPjrU/JRmG4ZguyegLAnZx3qyjhdFYqB44sqJw==
dependencies:
js-stylesheet "0.0.1"
react-query@^3.39.2:
version "3.39.2"
resolved "https://registry.yarnpkg.com/react-query/-/react-query-3.39.2.tgz#9224140f0296f01e9664b78ed6e4f69a0cc9216f"
@ -8091,6 +8111,11 @@ react-textarea-autosize@^8.4.0:
use-composed-ref "^1.3.0"
use-latest "^1.2.1"
react-transition-state@^1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/react-transition-state/-/react-transition-state-1.1.5.tgz#22accee21d0011b1d0245be24b6262ae67f494c3"
integrity sha512-ITY2mZqc2dWG2eitJkYNdcSFW8aKeOlkL2A/vowRrLL8GH3J6Re/SpD/BLvQzrVOTqjsP0b5S9N10vgNNzwMUQ==
react-twitter-embed@^4.0.4:
version "4.0.4"
resolved "https://registry.yarnpkg.com/react-twitter-embed/-/react-twitter-embed-4.0.4.tgz#4a6b8354acc266876ff1110b9f648518ea20db6d"