chore: cleanup
Some checks are pending
continuous-integration/drone/push Build is running

This commit is contained in:
Kieran 2023-11-16 15:54:02 +00:00
parent 981ab5790a
commit 5a63a21fec
Signed by: Kieran
GPG Key ID: DE71CEB3925BE941
6 changed files with 127 additions and 78 deletions

View File

@ -314,18 +314,18 @@ export function NoteCreator() {
onChange={e => { onChange={e => {
note.update( note.update(
v => v =>
(v.selectedCustomRelays = (v.selectedCustomRelays =
// set false if all relays selected // set false if all relays selected
e.target.checked && e.target.checked &&
note.selectedCustomRelays && note.selectedCustomRelays &&
note.selectedCustomRelays.length == a.length - 1 note.selectedCustomRelays.length == a.length - 1
? undefined ? undefined
: // otherwise return selectedCustomRelays with target relay added / removed : // otherwise return selectedCustomRelays with target relay added / removed
a.filter(el => a.filter(el =>
el === r el === r
? e.target.checked ? e.target.checked
: !note.selectedCustomRelays || note.selectedCustomRelays.includes(el), : !note.selectedCustomRelays || note.selectedCustomRelays.includes(el),
)), )),
); );
}} }}
/> />
@ -394,9 +394,9 @@ export function NoteCreator() {
onChange={e => onChange={e =>
note.update( note.update(
v => v =>
(v.zapSplits = arr.map((vv, ii) => (v.zapSplits = arr.map((vv, ii) =>
ii === i ? { ...vv, weight: Number(e.target.value) } : vv, ii === i ? { ...vv, weight: Number(e.target.value) } : vv,
)), )),
) )
} }
/> />
@ -572,35 +572,43 @@ export function NoteCreator() {
</> </>
)} )}
{note.preview && getPreviewNote()} {note.preview && getPreviewNote()}
{!note.preview && (<> {!note.preview && (
<div onPaste={handlePaste} className={classNames("note-creator", { poll: Boolean(note.pollOptions) })}> <>
<Textarea <div onPaste={handlePaste} className={classNames("note-creator", { poll: Boolean(note.pollOptions) })}>
onDragOver={handleDragOver} <Textarea
onDragLeave={handleDragLeave} onDragOver={handleDragOver}
onDrop={handleDrop} onDragLeave={handleDragLeave}
autoFocus onDrop={handleDrop}
className={classNames("textarea", { "textarea--focused": note.active })} autoFocus
onChange={c => onChange(c)} className={classNames("textarea", { "textarea--focused": note.active })}
value={note.note} onChange={c => onChange(c)}
onFocus={() => note.update(v => (v.active = true))} value={note.note}
onKeyDown={e => { onFocus={() => note.update(v => (v.active = true))}
if (e.key === "Enter" && e.metaKey) { onKeyDown={e => {
sendNote().catch(console.warn); if (e.key === "Enter" && e.metaKey) {
} sendNote().catch(console.warn);
}} }
/> }}
{renderPollOptions()} />
</div> {renderPollOptions()}
<div className="flex flex-col g4"> </div>
<TagsInput value={note.hashTags} onChange={e => note.update(s => s.hashTags = e)} placeHolder={formatMessage({ <div className="flex flex-col g4">
defaultMessage: "Add up to 4 hashtags" <TagsInput
})} separators={["Enter", ","]} /> value={note.hashTags}
{note.hashTags.length > 4 && <small className="warning"> onChange={e => note.update(s => (s.hashTags = e))}
<FormattedMessage defaultMessage="Try to use less than 4 hashtags to stay on topic 🙏" /> placeHolder={formatMessage({
</small>} defaultMessage: "Add up to 4 hashtags",
<TrendingHashTagsLine onClick={t => note.update(s => s.hashTags = appendDedupe(s.hashTags, [t]))} /> })}
</div> separators={["Enter", ","]}
</> />
{note.hashTags.length > 4 && (
<small className="warning">
<FormattedMessage defaultMessage="Try to use less than 5 hashtags to stay on topic 🙏" />
</small>
)}
<TrendingHashTagsLine onClick={t => note.update(s => (s.hashTags = appendDedupe(s.hashTags, [t])))} />
</div>
</>
)} )}
{uploader.progress.length > 0 && <FileUploadProgress progress={uploader.progress} />} {uploader.progress.length > 0 && <FileUploadProgress progress={uploader.progress} />}
{noteCreatorFooter()} {noteCreatorFooter()}
@ -627,7 +635,7 @@ export function NoteCreator() {
} }
function TrendingHashTagsLine(props: { onClick: (tag: string) => void }) { function TrendingHashTagsLine(props: { onClick: (tag: string) => void }) {
const [hashtags, setHashtags] = useState<Array<{ hashtag: string, posts: number }>>(); const [hashtags, setHashtags] = useState<Array<{ hashtag: string; posts: number }>>();
const { lang } = useLocale(); const { lang } = useLocale();
async function loadTrendingHashtags() { async function loadTrendingHashtags() {
@ -641,14 +649,18 @@ function TrendingHashTagsLine(props: { onClick: (tag: string) => void }) {
}, []); }, []);
if (!hashtags || hashtags.length === 0) return; if (!hashtags || hashtags.length === 0) return;
return <div className="flex flex-col g4"> return (
<small> <div className="flex flex-col g4">
<FormattedMessage defaultMessage="Popular Hashtags" /> <small>
</small> <FormattedMessage defaultMessage="Popular Hashtags" />
<div className="flex g4 flex-wrap"> </small>
{hashtags.slice(0, 5).map(a => <span className="px-2 py-1 bg-dark rounded-full pointer nowrap" onClick={() => props.onClick(a.hashtag)}> <div className="flex g4 flex-wrap">
#{a.hashtag} {hashtags.slice(0, 5).map(a => (
</span>)} <span className="px-2 py-1 bg-dark rounded-full pointer nowrap" onClick={() => props.onClick(a.hashtag)}>
#{a.hashtag}
</span>
))}
</div>
</div> </div>
</div> );
} }

View File

@ -7,29 +7,33 @@ import { HashTagHeader } from "Pages/HashTagsPage";
import { useLocale } from "IntlProvider"; import { useLocale } from "IntlProvider";
export default function TrendingHashtags({ title }: { title?: ReactNode }) { export default function TrendingHashtags({ title }: { title?: ReactNode }) {
const [hashtags, setHashtags] = useState<Array<{ hashtag: string, posts: number }>>(); const [hashtags, setHashtags] = useState<Array<{ hashtag: string; posts: number }>>();
const [error, setError] = useState<Error>(); const [error, setError] = useState<Error>();
const { lang } = useLocale(); const { lang } = useLocale();
async function loadTrendingHashtags() { async function loadTrendingHashtags() {
const api = new NostrBandApi(); const api = new NostrBandApi();
const rsp = await api.trendingHashtags(lang); const rsp = await api.trendingHashtags(lang);
setHashtags(rsp.hashtags); setHashtags(rsp.hashtags);
} }
useEffect(() => { useEffect(() => {
loadTrendingHashtags().catch(e => { loadTrendingHashtags().catch(e => {
if (e instanceof Error) { if (e instanceof Error) {
setError(e); setError(e);
} }
}); });
}, []); }, []);
if (error) return <ErrorOrOffline error={error} onRetry={loadTrendingHashtags} className="p" />; if (error) return <ErrorOrOffline error={error} onRetry={loadTrendingHashtags} className="p" />;
if (!hashtags) return <PageSpinner />; if (!hashtags) return <PageSpinner />;
return <> return (
{title} <>
{hashtags.map(a => <HashTagHeader tag={a.hashtag} className="bb p" />)} {title}
{hashtags.map(a => (
<HashTagHeader tag={a.hashtag} events={a.posts} className="bb p" />
))}
</> </>
);
} }

View File

@ -20,9 +20,9 @@ export interface TrendingNoteResponse {
export interface TrendingHashtagsResponse { export interface TrendingHashtagsResponse {
hashtags: Array<{ hashtags: Array<{
hashtag: string, hashtag: string;
posts: number posts: number;
}> }>;
} }
export interface SuggestedFollow { export interface SuggestedFollow {

View File

@ -12,6 +12,7 @@ import { setTags } from "Login";
import AsyncButton from "Element/AsyncButton"; import AsyncButton from "Element/AsyncButton";
import ProfileImage from "Element/User/ProfileImage"; import ProfileImage from "Element/User/ProfileImage";
import classNames from "classnames"; import classNames from "classnames";
import { formatShort } from "Number";
const HashTagsPage = () => { const HashTagsPage = () => {
const params = useParams(); const params = useParams();
@ -34,7 +35,7 @@ const HashTagsPage = () => {
export default HashTagsPage; export default HashTagsPage;
export function HashTagHeader({ tag, className }: { tag: string, className?: string }) { export function HashTagHeader({ tag, events, className }: { tag: string; events?: number; className?: string }) {
const login = useLogin(); const login = useLogin();
const isFollowing = useMemo(() => { const isFollowing = useMemo(() => {
return login.tags.item.includes(tag); return login.tags.item.includes(tag);
@ -63,7 +64,19 @@ export function HashTagHeader({ tag, className }: { tag: string, className?: str
return ( return (
<div className={classNames("flex flex-col", className)}> <div className={classNames("flex flex-col", className)}>
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<b className="text-lg">#{tag}</b> <div className="flex g8 items-center">
<b className="text-xl">#{tag}</b>
{events && (
<small>
<FormattedMessage
defaultMessage="{n} notes"
values={{
n: formatShort(events),
}}
/>
</small>
)}
</div>
{isFollowing ? ( {isFollowing ? (
<AsyncButton className="secondary" onClick={() => followTags(login.tags.item.filter(t => t !== tag))}> <AsyncButton className="secondary" onClick={() => followTags(login.tags.item.filter(t => t !== tag))}>
<FormattedMessage defaultMessage="Unfollow" /> <FormattedMessage defaultMessage="Unfollow" />

View File

@ -298,6 +298,9 @@
"defaultMessage": "Parent", "defaultMessage": "Parent",
"description": "Link to parent note in thread" "description": "Link to parent note in thread"
}, },
"AIgmDy": {
"defaultMessage": "Add up to 4 hashtags"
},
"AN0Z7Q": { "AN0Z7Q": {
"defaultMessage": "Muted Words" "defaultMessage": "Muted Words"
}, },
@ -879,6 +882,9 @@
"XICsE8": { "XICsE8": {
"defaultMessage": "File hosts" "defaultMessage": "File hosts"
}, },
"XXm7jJ": {
"defaultMessage": "Trending Hashtags"
},
"XgWvGA": { "XgWvGA": {
"defaultMessage": "Reactions" "defaultMessage": "Reactions"
}, },
@ -993,9 +999,15 @@
"d7d0/x": { "d7d0/x": {
"defaultMessage": "LN Address" "defaultMessage": "LN Address"
}, },
"d8gpCh": {
"defaultMessage": "Try to use less than 5 hashtags to stay on topic 🙏"
},
"dOQCL8": { "dOQCL8": {
"defaultMessage": "Display name" "defaultMessage": "Display name"
}, },
"ddd3JX": {
"defaultMessage": "Popular Hashtags"
},
"deEeEI": { "deEeEI": {
"defaultMessage": "Register" "defaultMessage": "Register"
}, },
@ -1382,6 +1394,9 @@
"ugyJnE": { "ugyJnE": {
"defaultMessage": "Sending notes and other stuff" "defaultMessage": "Sending notes and other stuff"
}, },
"un1nGw": {
"defaultMessage": "{n} notes"
},
"usAvMr": { "usAvMr": {
"defaultMessage": "Edit Profile" "defaultMessage": "Edit Profile"
}, },

View File

@ -98,6 +98,7 @@
"9wO4wJ": "Lightning Invoice", "9wO4wJ": "Lightning Invoice",
"ABAQyo": "Chats", "ABAQyo": "Chats",
"ADmfQT": "Parent", "ADmfQT": "Parent",
"AIgmDy": "Add up to 4 hashtags",
"AN0Z7Q": "Muted Words", "AN0Z7Q": "Muted Words",
"ASRK0S": "This author has been muted", "ASRK0S": "This author has been muted",
"Ai8VHU": "Unlimited note retention on Snort relay", "Ai8VHU": "Unlimited note retention on Snort relay",
@ -289,6 +290,7 @@
"X7xU8J": "nsec, npub, nip-05, hex, mnemonic", "X7xU8J": "nsec, npub, nip-05, hex, mnemonic",
"XECMfW": "Send usage metrics", "XECMfW": "Send usage metrics",
"XICsE8": "File hosts", "XICsE8": "File hosts",
"XXm7jJ": "Trending Hashtags",
"XgWvGA": "Reactions", "XgWvGA": "Reactions",
"Xopqkl": "Your default zap amount is {number} sats, example values are calculated from this.", "Xopqkl": "Your default zap amount is {number} sats, example values are calculated from this.",
"XrSk2j": "Redeem", "XrSk2j": "Redeem",
@ -326,7 +328,9 @@
"d+6YsV": "Lists to mute:", "d+6YsV": "Lists to mute:",
"d6CyG5": "History", "d6CyG5": "History",
"d7d0/x": "LN Address", "d7d0/x": "LN Address",
"d8gpCh": "Try to use less than 5 hashtags to stay on topic 🙏",
"dOQCL8": "Display name", "dOQCL8": "Display name",
"ddd3JX": "Popular Hashtags",
"deEeEI": "Register", "deEeEI": "Register",
"dmsiLv": "A default Zap Pool split of {n} has been configured for {site} developers, you can disable it at any time in {link}", "dmsiLv": "A default Zap Pool split of {n} has been configured for {site} developers, you can disable it at any time in {link}",
"e61Jf3": "Coming soon", "e61Jf3": "Coming soon",
@ -455,6 +459,7 @@
"uSV4Ti": "Reposts need to be manually confirmed", "uSV4Ti": "Reposts need to be manually confirmed",
"uc0din": "Send sats splits to", "uc0din": "Send sats splits to",
"ugyJnE": "Sending notes and other stuff", "ugyJnE": "Sending notes and other stuff",
"un1nGw": "{n} notes",
"usAvMr": "Edit Profile", "usAvMr": "Edit Profile",
"v8lolG": "Start chat", "v8lolG": "Start chat",
"vB3oQ/": "Must be a contact list or pubkey list", "vB3oQ/": "Must be a contact list or pubkey list",