chore: improve thread navigation
This commit is contained in:
parent
a96a8eb11f
commit
6d8416f88e
|
@ -38,6 +38,7 @@ export interface NoteProps {
|
||||||
related: readonly TaggedRawEvent[];
|
related: readonly TaggedRawEvent[];
|
||||||
highlight?: boolean;
|
highlight?: boolean;
|
||||||
ignoreModeration?: boolean;
|
ignoreModeration?: boolean;
|
||||||
|
onClick?: (e: TaggedRawEvent) => void;
|
||||||
options?: {
|
options?: {
|
||||||
showHeader?: boolean;
|
showHeader?: boolean;
|
||||||
showTime?: boolean;
|
showTime?: boolean;
|
||||||
|
@ -203,6 +204,12 @@ export default function Note(props: NoteProps) {
|
||||||
eTarget: TaggedRawEvent,
|
eTarget: TaggedRawEvent,
|
||||||
isTargetAllowed: boolean = e.target === e.currentTarget
|
isTargetAllowed: boolean = e.target === e.currentTarget
|
||||||
) {
|
) {
|
||||||
|
if (props.onClick) {
|
||||||
|
e.stopPropagation();
|
||||||
|
props.onClick(eTarget);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!isTargetAllowed || opt?.canClick === false) {
|
if (!isTargetAllowed || opt?.canClick === false) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import "./Thread.css";
|
||||||
import { useMemo, useState, ReactNode } from "react";
|
import { useMemo, useState, ReactNode } from "react";
|
||||||
import { useIntl } from "react-intl";
|
import { useIntl } from "react-intl";
|
||||||
import { useNavigate, useLocation, Link, useParams } from "react-router-dom";
|
import { useNavigate, useLocation, Link, useParams } from "react-router-dom";
|
||||||
import { TaggedRawEvent, u256, EventKind } from "@snort/nostr";
|
import { TaggedRawEvent, u256, EventKind, encodeTLV, NostrPrefix } from "@snort/nostr";
|
||||||
import { EventExt, Thread as ThreadInfo } from "System/EventExt";
|
import { EventExt, Thread as ThreadInfo } from "System/EventExt";
|
||||||
|
|
||||||
import { eventLink, unwrap, getReactions, parseNostrLink, getAllReactions } from "Util";
|
import { eventLink, unwrap, getReactions, parseNostrLink, getAllReactions } from "Util";
|
||||||
|
@ -34,7 +34,7 @@ interface SubthreadProps {
|
||||||
notes: readonly TaggedRawEvent[];
|
notes: readonly TaggedRawEvent[];
|
||||||
related: readonly TaggedRawEvent[];
|
related: readonly TaggedRawEvent[];
|
||||||
chains: Map<u256, Array<TaggedRawEvent>>;
|
chains: Map<u256, Array<TaggedRawEvent>>;
|
||||||
onNavigate: (e: u256) => void;
|
onNavigate: (e: TaggedRawEvent) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Subthread = ({ active, notes, related, chains, onNavigate }: SubthreadProps) => {
|
const Subthread = ({ active, notes, related, chains, onNavigate }: SubthreadProps) => {
|
||||||
|
@ -51,6 +51,7 @@ const Subthread = ({ active, notes, related, chains, onNavigate }: SubthreadProp
|
||||||
data={a}
|
data={a}
|
||||||
key={a.id}
|
key={a.id}
|
||||||
related={related}
|
related={related}
|
||||||
|
onClick={onNavigate}
|
||||||
/>
|
/>
|
||||||
<div className="line-container"></div>
|
<div className="line-container"></div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -95,6 +96,7 @@ const ThreadNote = ({ active, note, isLast, isLastSubthread, from, related, chai
|
||||||
data={note}
|
data={note}
|
||||||
key={note.id}
|
key={note.id}
|
||||||
related={related}
|
related={related}
|
||||||
|
onClick={onNavigate}
|
||||||
/>
|
/>
|
||||||
<div className="line-container"></div>
|
<div className="line-container"></div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -200,6 +202,7 @@ const TierThree = ({ active, isLastSubthread, from, notes, related, chains, onNa
|
||||||
data={r}
|
data={r}
|
||||||
key={r.id}
|
key={r.id}
|
||||||
related={related}
|
related={related}
|
||||||
|
onClick={onNavigate}
|
||||||
/>
|
/>
|
||||||
<div className="line-container"></div>
|
<div className="line-container"></div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -222,6 +225,14 @@ export default function Thread() {
|
||||||
const isSingleNote = thread.data?.filter(a => a.kind === EventKind.TextNote).length === 1;
|
const isSingleNote = thread.data?.filter(a => a.kind === EventKind.TextNote).length === 1;
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
|
|
||||||
|
function navigateThread(e: TaggedRawEvent) {
|
||||||
|
setCurrentId(e.id);
|
||||||
|
const link = encodeTLV(e.id, NostrPrefix.Event, e.relays);
|
||||||
|
navigate(`/e/${link}`, {
|
||||||
|
replace: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const chains = useMemo(() => {
|
const chains = useMemo(() => {
|
||||||
const chains = new Map<u256, Array<TaggedRawEvent>>();
|
const chains = new Map<u256, Array<TaggedRawEvent>>();
|
||||||
if (thread.data) {
|
if (thread.data) {
|
||||||
|
@ -300,6 +311,7 @@ export default function Thread() {
|
||||||
data={note}
|
data={note}
|
||||||
related={getReactions(thread.data, note.id)}
|
related={getReactions(thread.data, note.id)}
|
||||||
options={{ showReactionsLink: true }}
|
options={{ showReactionsLink: true }}
|
||||||
|
onClick={navigateThread}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -323,9 +335,7 @@ export default function Thread() {
|
||||||
replies.map(a => a.id)
|
replies.map(a => a.id)
|
||||||
)}
|
)}
|
||||||
chains={chains}
|
chains={chains}
|
||||||
onNavigate={() => {
|
onNavigate={navigateThread}
|
||||||
//nothing
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,12 +93,7 @@
|
||||||
|
|
||||||
.login .login-actions > button {
|
.login .login-actions > button {
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
margin-bottom: 10px;
|
||||||
|
|
||||||
@media (max-width: 520px) {
|
|
||||||
.login .login-actions > button {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.login .login-or {
|
.login .login-or {
|
||||||
|
|
|
@ -8,8 +8,7 @@ import { faShop } from "@fortawesome/free-solid-svg-icons";
|
||||||
|
|
||||||
import useEventPublisher from "Feed/EventPublisher";
|
import useEventPublisher from "Feed/EventPublisher";
|
||||||
import { useUserProfile } from "Hooks/useUserProfile";
|
import { useUserProfile } from "Hooks/useUserProfile";
|
||||||
import { hexToBech32, openFile } from "Util";
|
import { openFile } from "Util";
|
||||||
import Copy from "Element/Copy";
|
|
||||||
import useFileUpload from "Upload";
|
import useFileUpload from "Upload";
|
||||||
import AsyncButton from "Element/AsyncButton";
|
import AsyncButton from "Element/AsyncButton";
|
||||||
import { mapEventToProfile, UserCache } from "Cache";
|
import { mapEventToProfile, UserCache } from "Cache";
|
||||||
|
@ -20,12 +19,11 @@ import messages from "./messages";
|
||||||
export interface ProfileSettingsProps {
|
export interface ProfileSettingsProps {
|
||||||
avatar?: boolean;
|
avatar?: boolean;
|
||||||
banner?: boolean;
|
banner?: boolean;
|
||||||
privateKey?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ProfileSettings(props: ProfileSettingsProps) {
|
export default function ProfileSettings(props: ProfileSettingsProps) {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { publicKey: id, privateKey: privKey } = useLogin();
|
const { publicKey: id } = useLogin();
|
||||||
const user = useUserProfile(id ?? "");
|
const user = useUserProfile(id ?? "");
|
||||||
const publisher = useEventPublisher();
|
const publisher = useEventPublisher();
|
||||||
const uploader = useFileUpload();
|
const uploader = useFileUpload();
|
||||||
|
@ -154,12 +152,10 @@ export default function ProfileSettings(props: ProfileSettingsProps) {
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<input type="text" className="mr10" value={nip05} onChange={e => setNip05(e.target.value)} />
|
<input type="text" className="mr10" value={nip05} onChange={e => setNip05(e.target.value)} />
|
||||||
{nip05 === "" && (
|
<button type="button" onClick={() => navigate("/verification")}>
|
||||||
<button type="button" onClick={() => navigate("/verification")}>
|
<FontAwesomeIcon icon={faShop} />
|
||||||
<FontAwesomeIcon icon={faShop} />
|
<FormattedMessage {...messages.Buy} />
|
||||||
<FormattedMessage {...messages.Buy} />
|
</button>
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="form-group card">
|
<div className="form-group card">
|
||||||
|
@ -227,18 +223,6 @@ export default function ProfileSettings(props: ProfileSettingsProps) {
|
||||||
<FormattedMessage {...messages.EditProfile} />
|
<FormattedMessage {...messages.EditProfile} />
|
||||||
</h3>
|
</h3>
|
||||||
{settings()}
|
{settings()}
|
||||||
{privKey && (props.privateKey ?? true) && (
|
|
||||||
<div className="flex f-col bg-grey">
|
|
||||||
<div>
|
|
||||||
<h4>
|
|
||||||
<FormattedMessage {...messages.PrivateKey} />:
|
|
||||||
</h4>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<Copy text={hexToBech32("nsec", privKey)} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue