User preferences #104

Merged
v0l merged 2 commits from preferences into main 2023-01-20 20:10:17 +00:00
17 changed files with 524 additions and 507 deletions

View File

@ -13,6 +13,7 @@ import { default as NEvent } from "Nostr/Event";
import { RootState } from "State/Store"; import { RootState } from "State/Store";
import { HexKey, TaggedRawEvent } from "Nostr"; import { HexKey, TaggedRawEvent } from "Nostr";
import EventKind from "Nostr/EventKind"; import EventKind from "Nostr/EventKind";
import { UserPreferences } from "State/Login";
export interface NoteFooterProps { export interface NoteFooterProps {
related: TaggedRawEvent[], related: TaggedRawEvent[],
@ -23,6 +24,7 @@ export default function NoteFooter(props: NoteFooterProps) {
const { related, ev } = props; const { related, ev } = props;
const login = useSelector<RootState, HexKey | undefined>(s => s.login.publicKey); const login = useSelector<RootState, HexKey | undefined>(s => s.login.publicKey);
const prefs = useSelector<RootState, UserPreferences>(s => s.login.preferences);
const author = useProfile(ev.RootPubKey)?.get(ev.RootPubKey); const author = useProfile(ev.RootPubKey)?.get(ev.RootPubKey);
const publisher = useEventPublisher(); const publisher = useEventPublisher();
const [reply, setReply] = useState(false); const [reply, setReply] = useState(false);
@ -65,10 +67,12 @@ export default function NoteFooter(props: NoteFooterProps) {
async function repost() { async function repost() {
if (!hasReposted()) { if (!hasReposted()) {
if (!prefs.confirmReposts || window.confirm(`Are you sure you want to repost: ${ev.Id}`)) {
let evRepost = await publisher.repost(ev); let evRepost = await publisher.repost(ev);
publisher.broadcast(evRepost); publisher.broadcast(evRepost);
} }
} }
}
function tipButton() { function tipButton() {
let service = author?.lud16 || author?.lud06; let service = author?.lud16 || author?.lud06;
@ -86,18 +90,6 @@ export default function NoteFooter(props: NoteFooterProps) {
return null; return null;
} }
function reactionIcon(content: string, reacted: boolean) {
switch (content) {
case Reaction.Positive: {
return <FontAwesomeIcon icon={faHeart} />;
}
case Reaction.Negative: {
return <FontAwesomeIcon icon={faThumbsDown} />;
}
}
return content;
}
function repostIcon() { function repostIcon() {
return ( return (
<div className={`reaction-pill ${hasReposted() ? 'reacted' : ''}`} onClick={() => repost()}> <div className={`reaction-pill ${hasReposted() ? 'reacted' : ''}`} onClick={() => repost()}>
@ -113,15 +105,12 @@ export default function NoteFooter(props: NoteFooterProps) {
) )
} }
function reactionIcons() {
if (!prefs.enableReactions) {
return null;
}
return ( return (
<> <>
<div className="footer">
<div className={`reaction-pill ${reply ? 'reacted' : ''}`} onClick={(e) => setReply(s => !s)}>
<div className="reaction-pill-icon">
<FontAwesomeIcon icon={faReply} />
</div>
</div>
<div className={`reaction-pill ${hasReacted('+') ? 'reacted' : ''} `} onClick={(e) => react("+")}> <div className={`reaction-pill ${hasReacted('+') ? 'reacted' : ''} `} onClick={(e) => react("+")}>
<div className="reaction-pill-icon"> <div className="reaction-pill-icon">
<FontAwesomeIcon icon={faHeart} /> <FontAwesomeIcon icon={faHeart} />
@ -139,6 +128,19 @@ export default function NoteFooter(props: NoteFooterProps) {
</div> </div>
</div> </div>
{repostIcon()} {repostIcon()}
</>
)
}
return (
<>
<div className="footer">
<div className={`reaction-pill ${reply ? 'reacted' : ''}`} onClick={(e) => setReply(s => !s)}>
<div className="reaction-pill-icon">
<FontAwesomeIcon icon={faReply} />
</div>
</div>
{reactionIcons()}
{tipButton()} {tipButton()}
{isMine && ( {isMine && (
<div className="reaction-pill trash-icon"> <div className="reaction-pill trash-icon">

View File

@ -13,9 +13,15 @@ import Tag from "Nostr/Tag";
import { MetadataCache } from "Db/User"; import { MetadataCache } from "Db/User";
import Mention from "Element/Mention"; import Mention from "Element/Mention";
import TidalEmbed from "Element/TidalEmbed"; import TidalEmbed from "Element/TidalEmbed";
import { useSelector } from 'react-redux';
import { RootState } from 'State/Store';
import { UserPreferences } from 'State/Login';
function transformHttpLink(a: string) { function transformHttpLink(a: string, pref: UserPreferences) {
try { try {
if (!pref.autoLoadMedia) {
return <a href={a} onClick={(e) => e.stopPropagation()} target="_blank" rel="noreferrer" className="ext">{a}</a>
}
const url = new URL(a); const url = new URL(a);
const youtubeId = YoutubeUrlRegex.test(a) && RegExp.$1; const youtubeId = YoutubeUrlRegex.test(a) && RegExp.$1;
const tweetId = TweetUrlRegex.test(a) && RegExp.$2; const tweetId = TweetUrlRegex.test(a) && RegExp.$2;
@ -73,12 +79,12 @@ function transformHttpLink(a: string) {
return <a href={a} onClick={(e) => e.stopPropagation()} target="_blank" rel="noreferrer" className="ext">{a}</a> return <a href={a} onClick={(e) => e.stopPropagation()} target="_blank" rel="noreferrer" className="ext">{a}</a>
} }
function extractLinks(fragments: Fragment[]) { function extractLinks(fragments: Fragment[], pref: UserPreferences) {
return fragments.map(f => { return fragments.map(f => {
if (typeof f === "string") { if (typeof f === "string") {
return f.split(UrlRegex).map(a => { return f.split(UrlRegex).map(a => {
if (a.startsWith("http")) { if (a.startsWith("http")) {
return transformHttpLink(a) return transformHttpLink(a, pref)
} }
return a; return a;
}); });
@ -87,14 +93,14 @@ function extractLinks(fragments: Fragment[]) {
}).flat(); }).flat();
} }
function extractMentions(fragments: Fragment[], tags: Tag[], users: Map<string, MetadataCache>) { function extractMentions(frag: TextFragment) {
return fragments.map(f => { return frag.body.map(f => {
if (typeof f === "string") { if (typeof f === "string") {
return f.split(MentionRegex).map((match) => { return f.split(MentionRegex).map((match) => {
let matchTag = match.match(/#\[(\d+)\]/); let matchTag = match.match(/#\[(\d+)\]/);
if (matchTag && matchTag.length === 2) { if (matchTag && matchTag.length === 2) {
let idx = parseInt(matchTag[1]); let idx = parseInt(matchTag[1]);
let ref = tags?.find(a => a.Index === idx); let ref = frag.tags?.find(a => a.Index === idx);
if (ref) { if (ref) {
switch (ref.Key) { switch (ref.Key) {
case "p": { case "p": {
@ -149,25 +155,25 @@ function extractHashtags(fragments: Fragment[]) {
}).flat(); }).flat();
} }
function transformLi({ body, tags, users }: TextFragment) { function transformLi(frag: TextFragment) {
let fragments = transformText({ body, tags, users }) let fragments = transformText(frag)
return <li>{fragments}</li> return <li>{fragments}</li>
} }
function transformParagraph({ body, tags, users }: TextFragment) { function transformParagraph(frag: TextFragment) {
const fragments = transformText({ body, tags, users }) const fragments = transformText(frag)
if (fragments.every(f => typeof f === 'string')) { if (fragments.every(f => typeof f === 'string')) {
return <p>{fragments}</p> return <p>{fragments}</p>
} }
return <>{fragments}</> return <>{fragments}</>
} }
function transformText({ body, tags, users }: TextFragment) { function transformText(frag: TextFragment) {
if (body === undefined) { if (frag.body === undefined) {
debugger; debugger;
} }
let fragments = extractMentions(body, tags, users); let fragments = extractMentions(frag);
fragments = extractLinks(fragments); fragments = extractLinks(fragments, frag.pref);
fragments = extractInvoices(fragments); fragments = extractInvoices(fragments);
fragments = extractHashtags(fragments); fragments = extractHashtags(fragments);
return fragments; return fragments;
@ -178,7 +184,8 @@ export type Fragment = string | JSX.Element;
export interface TextFragment { export interface TextFragment {
body: Fragment[], body: Fragment[],
tags: Tag[], tags: Tag[],
users: Map<string, MetadataCache> users: Map<string, MetadataCache>,
pref: UserPreferences
} }
export interface TextProps { export interface TextProps {
@ -188,11 +195,12 @@ export interface TextProps {
} }
export default function Text({ content, tags, users }: TextProps) { export default function Text({ content, tags, users }: TextProps) {
const pref = useSelector<RootState, UserPreferences>(s => s.login.preferences);
const components = useMemo(() => { const components = useMemo(() => {
return { return {
p: (x: any) => transformParagraph({ body: x.children ?? [], tags, users }), p: (x: any) => transformParagraph({ body: x.children ?? [], tags, users, pref }),
a: (x: any) => transformHttpLink(x.href), a: (x: any) => transformHttpLink(x.href, pref),
li: (x: any) => transformLi({ body: x.children ?? [], tags, users }), li: (x: any) => transformLi({ body: x.children ?? [], tags, users, pref }),
}; };
}, [content]); }, [content]);
return <ReactMarkdown className="text" components={components}>{content}</ReactMarkdown> return <ReactMarkdown className="text" components={components}>{content}</ReactMarkdown>

View File

@ -3,9 +3,13 @@ import { u256 } from "Nostr";
import EventKind from "Nostr/EventKind"; import EventKind from "Nostr/EventKind";
import { Subscriptions } from "Nostr/Subscriptions"; import { Subscriptions } from "Nostr/Subscriptions";
import useSubscription from "Feed/Subscription"; import useSubscription from "Feed/Subscription";
import { useSelector } from "react-redux";
import { RootState } from "State/Store";
import { UserPreferences } from "State/Login";
export default function useThreadFeed(id: u256) { export default function useThreadFeed(id: u256) {
const [trackingEvents, setTrackingEvent] = useState<u256[]>([id]); const [trackingEvents, setTrackingEvent] = useState<u256[]>([id]);
const pref = useSelector<RootState, UserPreferences>(s => s.login.preferences);
function addId(id: u256[]) { function addId(id: u256[]) {
setTrackingEvent((s) => { setTrackingEvent((s) => {
@ -21,7 +25,7 @@ export default function useThreadFeed(id: u256) {
// get replies to this event // get replies to this event
const subRelated = new Subscriptions(); const subRelated = new Subscriptions();
subRelated.Kinds = new Set([EventKind.Reaction, EventKind.TextNote, EventKind.Deletion, EventKind.Repost]); subRelated.Kinds = new Set(pref.enableReactions ? [EventKind.Reaction, EventKind.TextNote, EventKind.Deletion, EventKind.Repost] : [EventKind.TextNote]);
subRelated.ETags = thisSub.Ids; subRelated.ETags = thisSub.Ids;
thisSub.AddSubscription(subRelated); thisSub.AddSubscription(subRelated);

View File

@ -4,6 +4,9 @@ import EventKind from "Nostr/EventKind";
import { Subscriptions } from "Nostr/Subscriptions"; import { Subscriptions } from "Nostr/Subscriptions";
import { unixNow } from "Util"; import { unixNow } from "Util";
import useSubscription from "Feed/Subscription"; import useSubscription from "Feed/Subscription";
import { useSelector } from "react-redux";
import { RootState } from "State/Store";
import { UserPreferences } from "State/Login";
export interface TimelineFeedOptions { export interface TimelineFeedOptions {
method: "TIME_RANGE" | "LIMIT_UNTIL" method: "TIME_RANGE" | "LIMIT_UNTIL"
@ -20,6 +23,7 @@ export default function useTimelineFeed(subject: TimelineSubject, options: Timel
const [until, setUntil] = useState<number>(now); const [until, setUntil] = useState<number>(now);
const [since, setSince] = useState<number>(now - window); const [since, setSince] = useState<number>(now - window);
const [trackingEvents, setTrackingEvent] = useState<u256[]>([]); const [trackingEvents, setTrackingEvent] = useState<u256[]>([]);
const pref = useSelector<RootState, UserPreferences>(s => s.login.preferences);
const sub = useMemo(() => { const sub = useMemo(() => {
if (subject.type !== "global" && subject.items.length == 0) { if (subject.type !== "global" && subject.items.length == 0) {
@ -56,7 +60,7 @@ export default function useTimelineFeed(subject: TimelineSubject, options: Timel
const main = useSubscription(sub, { leaveOpen: true }); const main = useSubscription(sub, { leaveOpen: true });
const subNext = useMemo(() => { const subNext = useMemo(() => {
if (trackingEvents.length > 0) { if (trackingEvents.length > 0 && pref.enableReactions) {
let sub = new Subscriptions(); let sub = new Subscriptions();
sub.Id = `timeline-related:${subject.type}`; sub.Id = `timeline-related:${subject.type}`;
sub.Kinds = new Set([EventKind.Reaction, EventKind.Deletion, EventKind.Repost]); sub.Kinds = new Set([EventKind.Reaction, EventKind.Deletion, EventKind.Repost]);

View File

@ -1,9 +1,15 @@
import ProfilePreview from "Element/ProfilePreview"; import ProfilePreview from "Element/ProfilePreview";
import ZapButton from "Element/ZapButton"; import ZapButton from "Element/ZapButton";
import { bech32ToHex } from "Util";
const Developers = [ const Developers = [
"63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed", // kieran bech32ToHex("npub1v0lxxxxutpvrelsksy8cdhgfux9l6a42hsj2qzquu2zk7vc9qnkszrqj49"), // kieran
"7fa56f5d6962ab1e3cd424e758c3002b8665f7b0d8dcee9fe9e288d7751ac194" // verbiricha bech32ToHex("npub107jk7htfv243u0x5ynn43scq9wrxtaasmrwwa8lfu2ydwag6cx2quqncxg") // verbiricha
];
const Contributors = [
bech32ToHex("npub10djxr5pvdu97rjkde7tgcsjxzpdzmdguwacfjwlchvj7t88dl7nsdl54nf"), // ivan
bech32ToHex("npub148jmlutaa49y5wl5mcll003ftj59v79vf7wuv3apcwpf75hx22vs7kk9ay"), // liran cohen
]; ];
const DonatePage = () => { const DonatePage = () => {
@ -19,8 +25,10 @@ const DonatePage = () => {
<p> <p>
Check out the code here: <a className="highlight" href="https://github.com/v0l/snort" rel="noreferrer" target="_blank">https://github.com/v0l/snort</a> Check out the code here: <a className="highlight" href="https://github.com/v0l/snort" rel="noreferrer" target="_blank">https://github.com/v0l/snort</a>
</p> </p>
<h3>Developers</h3> <h3>Primary Developers</h3>
{Developers.map(a => <ProfilePreview pubkey={a} key={a} actions={<ZapButton pubkey={a} />} />)} {Developers.map(a => <ProfilePreview pubkey={a} key={a} actions={<ZapButton pubkey={a} />} />)}
<h4>Contributors</h4>
{Contributors.map(a => <ProfilePreview pubkey={a} key={a} actions={<ZapButton pubkey={a} />} />)}
</div> </div>
); );
} }

View File

@ -6,7 +6,7 @@ import { faBell, faMessage } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { RootState } from "State/Store"; import { RootState } from "State/Store";
import { init } from "State/Login"; import { init, setPreferences, UserPreferences } from "State/Login";
import { HexKey, RawEvent, TaggedRawEvent } from "Nostr"; import { HexKey, RawEvent, TaggedRawEvent } from "Nostr";
import { RelaySettings } from "Nostr/Connection"; import { RelaySettings } from "Nostr/Connection";
import { System } from "Nostr/System" import { System } from "Nostr/System"
@ -23,6 +23,7 @@ export default function Layout() {
const notifications = useSelector<RootState, TaggedRawEvent[]>(s => s.login.notifications); const notifications = useSelector<RootState, TaggedRawEvent[]>(s => s.login.notifications);
const readNotifications = useSelector<RootState, number>(s => s.login.readNotifications); const readNotifications = useSelector<RootState, number>(s => s.login.readNotifications);
const dms = useSelector<RootState, RawEvent[]>(s => s.login.dms); const dms = useSelector<RootState, RawEvent[]>(s => s.login.dms);
const prefs = useSelector<RootState, UserPreferences>(s => s.login.preferences);
useLoginFeed(); useLoginFeed();
useEffect(() => { useEffect(() => {
@ -38,6 +39,27 @@ export default function Layout() {
} }
}, [relays]); }, [relays]);
function setTheme(theme: "light" | "dark") {
const elm = document.documentElement;
if (theme === "light" && !elm.classList.contains("light")) {
elm.classList.add("light");
} else if (theme === "dark" && elm.classList.contains("light")) {
elm.classList.remove("light");
}
}
useEffect(() => {
let osTheme = window.matchMedia("(prefers-color-scheme: light)");
setTheme(prefs.theme === "system" && osTheme.matches ? "light" : prefs.theme === "light" ? "light" : "dark");
osTheme.onchange = (e) => {
if (prefs.theme === "system") {
setTheme(e.matches ? "light" : "dark");
}
}
return () => { osTheme.onchange = null; }
}, [prefs.theme]);
useEffect(() => { useEffect(() => {
dispatch(init()); dispatch(init());
}, []); }, []);

View File

@ -1,240 +1,35 @@
import "./SettingsPage.css"; import { Outlet, RouteObject, useNavigate } from "react-router-dom";
import Nostrich from "nostrich.jpg"; import SettingsIndex from "Pages/settings/Index";
import Profile from "Pages/settings/Profile";
import { useEffect, useState } from "react"; import Relay from "Pages/settings/Relays";
import { useDispatch, useSelector } from "react-redux"; import Preferences from "Pages/settings/Preferences";
import { useNavigate } from "react-router-dom";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faShop } from "@fortawesome/free-solid-svg-icons";
import { RootState } from "State/Store";
import { logout, setRelays } from "State/Login";
import useEventPublisher from "Feed/EventPublisher";
import useProfile from "Feed/ProfileFeed";
import VoidUpload from "Feed/VoidUpload";
import { hexToBech32, openFile } from "Util";
import Relay from "Element/Relay";
import Copy from "Element/Copy";
import { HexKey, UserMetadata } from "Nostr";
import { RelaySettings } from "Nostr/Connection";
import { MetadataCache } from "Db/User";
export default function SettingsPage() { export default function SettingsPage() {
const navigate = useNavigate(); const navigate = useNavigate();
const id = useSelector<RootState, HexKey | undefined>(s => s.login.publicKey);
const privKey = useSelector<RootState, HexKey | undefined>(s => s.login.privateKey);
const relays = useSelector<RootState, Record<string, RelaySettings>>(s => s.login.relays);
const dispatch = useDispatch();
const user = useProfile(id)?.get(id || "");
const publisher = useEventPublisher();
const [name, setName] = useState<string>();
const [displayName, setDisplayName] = useState<string>();
const [picture, setPicture] = useState<string>();
const [banner, setBanner] = useState<string>();
const [about, setAbout] = useState<string>();
const [website, setWebsite] = useState<string>();
const [nip05, setNip05] = useState<string>();
const [lud06, setLud06] = useState<string>();
const [lud16, setLud16] = useState<string>();
const [newRelay, setNewRelay] = useState<string>();
const avatarPicture = (picture?.length ?? 0) === 0 ? Nostrich : picture
useEffect(() => {
if (user) {
setName(user.name);
setDisplayName(user.display_name)
setPicture(user.picture);
setBanner(user.banner);
setAbout(user.about);
setWebsite(user.website);
setNip05(user.nip05);
setLud06(user.lud06);
setLud16(user.lud16);
}
}, [user]);
async function saveProfile() {
// copy user object and delete internal fields
let userCopy = {
...user,
name,
display_name: displayName,
about,
picture,
banner,
website,
nip05,
lud16
};
delete userCopy["loaded"];
delete userCopy["created"];
delete userCopy["pubkey"];
console.debug(userCopy);
let ev = await publisher.metadata(userCopy);
console.debug(ev);
publisher.broadcast(ev);
}
async function uploadFile() {
let file = await openFile();
if (file) {
console.log(file);
let rsp = await VoidUpload(file, file.name);
if (!rsp?.ok) {
throw "Upload failed, please try again later";
}
return rsp.file;
}
}
async function setNewAvatar() {
const rsp = await uploadFile();
if (rsp) {
setPicture(rsp.meta?.url ?? `https://void.cat/d/${rsp.id}`);
}
}
async function setNewBanner() {
const rsp = await uploadFile();
if (rsp) {
setBanner(rsp.meta?.url ?? `https://void.cat/d/${rsp.id}`);
}
}
async function saveRelays() {
let ev = await publisher.saveRelays();
publisher.broadcast(ev);
}
function editor() {
return (
<div className="editor">
<div className="form-group">
<div>Name:</div>
<div>
<input type="text" value={name} onChange={(e) => setName(e.target.value)} />
</div>
</div>
<div className="form-group">
<div>Display name:</div>
<div>
<input type="text" value={displayName} onChange={(e) => setDisplayName(e.target.value)} />
</div>
</div>
<div className="form-group f-col">
<div>About:</div>
<div className="w-max">
<textarea className="w-max" onChange={(e) => setAbout(e.target.value)} value={about}></textarea>
</div>
</div>
<div className="form-group">
<div>Website:</div>
<div>
<input type="text" value={website} onChange={(e) => setWebsite(e.target.value)} />
</div>
</div>
<div className="form-group">
<div>NIP-05:</div>
<div>
<input type="text" className="mr10" value={nip05} onChange={(e) => setNip05(e.target.value)} />
<div className="btn" onClick={() => navigate("/verification")}>
<FontAwesomeIcon icon={faShop} />
&nbsp;
Buy
</div>
</div>
</div>
<div className="form-group">
<div>LN Address:</div>
<div>
<input type="text" value={lud16} onChange={(e) => setLud16(e.target.value)} />
</div>
</div>
<div className="form-group">
<div>
<div className="btn" onClick={() => { dispatch(logout()); navigate("/"); }}>Logout</div>
</div>
<div>
<div className="btn" onClick={() => saveProfile()}>Save</div>
</div>
</div>
</div>
)
}
function addNewRelay() {
if ((newRelay?.length ?? 0) > 0) {
const parsed = new URL(newRelay!);
const payload = {
relays: {
...relays,
[parsed.toString()]: { read: false, write: false }
},
createdAt: Math.floor(new Date().getTime() / 1000)
};
dispatch(setRelays(payload))
}
}
function addRelay() {
return ( return (
<> <>
<h4>Add Relays</h4> <h2 onClick={() => navigate("/settings")} className="pointer">Settings</h2>
<div className="flex mb10"> <Outlet />
<input type="text" className="f-grow" placeholder="wss://my-relay.com" value={newRelay} onChange={(e) => setNewRelay(e.target.value)} />
</div>
<div className="btn mb10" onClick={() => addNewRelay()}>Add</div>
</> </>
)
}
function settings() {
if (!id) return null;
return (
<>
<h1>Settings</h1>
<div className="flex f-center image-settings">
<div>
<h2>Avatar</h2>
<div style={{ backgroundImage: `url(${avatarPicture})` }} className="avatar">
<div className="edit" onClick={() => setNewAvatar()}>Edit</div>
</div>
</div>
<div>
<h2>Header</h2>
<div style={{ backgroundImage: `url(${(banner?.length ?? 0) === 0 ? Nostrich : banner})` }} className="banner">
<div className="edit" onClick={() => setNewBanner()}>Edit</div>
</div>
</div>
</div>
{editor()}
</>
)
}
return (
<div className="settings">
{settings()}
{privKey && (<div className="flex f-col bg-grey">
<div>
<h4>Private Key:</h4>
</div>
<div>
<Copy text={hexToBech32("nsec", privKey)} />
</div>
</div>)}
<h4>Relays</h4>
<div className="flex f-col">
{Object.keys(relays || {}).map(a => <Relay addr={a} key={a} />)}
</div>
<div className="flex actions">
<div className="f-grow"></div>
<div className="btn" onClick={() => saveRelays()}>Save</div>
</div>
{addRelay()}
</div>
); );
} }
export const SettingsRoutes: RouteObject[] = [
{
path: "",
element: <SettingsIndex />
},
{
path: "profile",
element: <Profile />
},
{
path: "relays",
element: <Relay />
},
{
path: "preferences",
element: <Preferences />
}
]

View File

@ -0,0 +1,3 @@
verbiricha commented 2023-01-20 17:42:09 +00:00 (Migrated from github.com)
Review
    background-color: var(--note-bg);
    cursor: pointer;
```suggestion background-color: var(--note-bg); cursor: pointer; ```
verbiricha commented 2023-01-20 17:42:09 +00:00 (Migrated from github.com)
Review
    background-color: var(--note-bg);
    cursor: pointer;
```suggestion background-color: var(--note-bg); cursor: pointer; ```
.settings-nav .card {
verbiricha commented 2023-01-20 17:42:09 +00:00 (Migrated from github.com)
Review
    background-color: var(--note-bg);
    cursor: pointer;
```suggestion background-color: var(--note-bg); cursor: pointer; ```
cursor: pointer;
verbiricha commented 2023-01-20 17:42:09 +00:00 (Migrated from github.com)
Review
    background-color: var(--note-bg);
    cursor: pointer;
```suggestion background-color: var(--note-bg); cursor: pointer; ```
}
verbiricha commented 2023-01-20 17:42:09 +00:00 (Migrated from github.com)
Review
    background-color: var(--note-bg);
    cursor: pointer;
```suggestion background-color: var(--note-bg); cursor: pointer; ```

View File

@ -0,0 +1,31 @@
import { faCircleDollarToSlot, faGear, faPlug, faUser } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useNavigate } from "react-router-dom";
import "./Index.css";
const SettingsIndex = () => {
const navigate = useNavigate();
return (
<div className="settings-nav">
<div className="card" onClick={() => navigate("profile")}>
<FontAwesomeIcon icon={faUser} size="xl" className="mr10" />
Profile
</div>
<div className="card" onClick={() => navigate("relays")}>
<FontAwesomeIcon icon={faPlug} size="xl" className="mr10" />
Relays
</div>
<div className="card" onClick={() => navigate("preferences")}>
<FontAwesomeIcon icon={faGear} size="xl" className="mr10" />
Preferences
</div>
<div className="card" onClick={() => navigate("/donate")}>
<FontAwesomeIcon icon={faCircleDollarToSlot} size="xl" className="mr10" />
Donate
</div>
</div>
)
}
export default SettingsIndex;

View File

@ -0,0 +1,8 @@
.preferences small {
margin-top: 0.5em;
color: var(--font-secondary-color);
}
.preferences select {
min-width: 100px;
}

View File

@ -0,0 +1,56 @@
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
import { useDispatch, useSelector } from "react-redux";
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
import { setPreferences, UserPreferences } from "State/Login";
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
import { RootState } from "State/Store";
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
import "./Preferences.css";
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
const PreferencesPage = () => {
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
const dispatch = useDispatch();
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
const perf = useSelector<RootState, UserPreferences>(s => s.login.preferences);
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
return (
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
<div className="preferences">
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
<h3>Preferences</h3>
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
<div className="card flex">
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
<div className="flex f-col f-grow">
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
<div>Theme</div>
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
</div>
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
<div>
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
<select value={perf.theme} onChange={e => dispatch(setPreferences({ ...perf, theme: e.target.value} as UserPreferences))}>
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
<option value="system">System (Default)</option>
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
<option value="light">Light</option>
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
<option value="dark">Dark</option>
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
</select>
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
</div>
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
</div>
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
<div className="card flex">
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
<div className="flex f-col f-grow">
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
<div>Automatically load media</div>
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
<small>Media in posts will automatically be shown, if disabled only the link will show</small>
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
</div>
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
<div>
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
<input type="checkbox" checked={perf.autoLoadMedia} onChange={e => dispatch(setPreferences({ ...perf, autoLoadMedia: e.target.checked }))} />
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
</div>
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
</div>
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
<div className="card flex">
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
<div className="flex f-col f-grow">
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
<div>Enable reactions</div>
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
<small>Reactions will be shown on every page, if disabled no reactions will be shown</small>
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
</div>
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
<div>
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
<input type="checkbox" checked={perf.enableReactions} onChange={e => dispatch(setPreferences({ ...perf, enableReactions: e.target.checked }))} />
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
</div>
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
</div>
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
<div className="card flex">
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
<div className="flex f-col f-grow">
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
<div>Confirm reposts</div>
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
<small>Reposts need to be manually confirmed</small>
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
</div>
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
<div>
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
<input type="checkbox" checked={perf.confirmReposts} onChange={e => dispatch(setPreferences({ ...perf, confirmReposts: e.target.checked }))} />
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
</div>
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
</div>
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
</div>
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
)
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
}
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.
export default PreferencesPage;
verbiricha commented 2023-01-20 17:49:00 +00:00 (Migrated from github.com)
Review

Wdyt about keeping current default (use system theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences.

This would be similar to other preferences, keeping the current default but offering customization.

Wdyt about keeping current default (use `system` theme)? If user explicitly sets a theme we can override it but if not use system theme. Have my devices configured to use dark/light depending on time of the day, don't want to be manually changing it from preferences. This would be similar to other preferences, keeping the current default but offering customization.

View File

@ -1,4 +1,4 @@
import "./SettingsPage.css"; import "./Profile.css";
import Nostrich from "nostrich.jpg"; import Nostrich from "nostrich.jpg";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
@ -10,20 +10,16 @@ import { faShop } from "@fortawesome/free-solid-svg-icons";
import useEventPublisher from "Feed/EventPublisher"; import useEventPublisher from "Feed/EventPublisher";
import useProfile from "Feed/ProfileFeed"; import useProfile from "Feed/ProfileFeed";
import VoidUpload from "Feed/VoidUpload"; import VoidUpload from "Feed/VoidUpload";
import { logout, setRelays } from "State/Login"; import { logout } from "State/Login";
import { hexToBech32, openFile } from "Util"; import { hexToBech32, openFile } from "Util";
import Relay from "Element/Relay";
import Copy from "Element/Copy"; import Copy from "Element/Copy";
import { RootState } from "State/Store"; import { RootState } from "State/Store";
import { HexKey, UserMetadata } from "Nostr"; import { HexKey } from "Nostr";
import { RelaySettings } from "Nostr/Connection";
import { MetadataCache } from "Db/User";
export default function SettingsPage() { export default function ProfileSettings() {
const navigate = useNavigate(); const navigate = useNavigate();
const id = useSelector<RootState, HexKey | undefined>(s => s.login.publicKey); const id = useSelector<RootState, HexKey | undefined>(s => s.login.publicKey);
const privKey = useSelector<RootState, HexKey | undefined>(s => s.login.privateKey); const privKey = useSelector<RootState, HexKey | undefined>(s => s.login.privateKey);
const relays = useSelector<RootState, Record<string, RelaySettings>>(s => s.login.relays);
const dispatch = useDispatch(); const dispatch = useDispatch();
const user = useProfile(id)?.get(id || ""); const user = useProfile(id)?.get(id || "");
const publisher = useEventPublisher(); const publisher = useEventPublisher();
@ -37,7 +33,6 @@ export default function SettingsPage() {
const [nip05, setNip05] = useState<string>(); const [nip05, setNip05] = useState<string>();
const [lud06, setLud06] = useState<string>(); const [lud06, setLud06] = useState<string>();
const [lud16, setLud16] = useState<string>(); const [lud16, setLud16] = useState<string>();
const [newRelay, setNewRelay] = useState<string>();
const avatarPicture = (picture?.length ?? 0) === 0 ? Nostrich : picture const avatarPicture = (picture?.length ?? 0) === 0 ? Nostrich : picture
@ -104,11 +99,6 @@ export default function SettingsPage() {
} }
} }
async function saveRelays() {
let ev = await publisher.saveRelays();
publisher.broadcast(ev);
}
function editor() { function editor() {
return ( return (
<div className="editor"> <div className="editor">
@ -165,37 +155,10 @@ export default function SettingsPage() {
) )
} }
function addNewRelay() {
if ((newRelay?.length ?? 0) > 0) {
const parsed = new URL(newRelay!);
const payload = {
relays: {
...relays,
[parsed.toString()]: { read: false, write: false }
},
createdAt: Math.floor(new Date().getTime() / 1000)
};
dispatch(setRelays(payload))
}
}
function addRelay() {
return (
<>
<h4>Add Relays</h4>
<div className="flex mb10">
<input type="text" className="f-grow" placeholder="wss://my-relay.com" value={newRelay} onChange={(e) => setNewRelay(e.target.value)} />
</div>
<div className="btn mb10" onClick={() => addNewRelay()}>Add</div>
</>
)
}
function settings() { function settings() {
if (!id) return null; if (!id) return null;
return ( return (
<> <>
<h1>Settings</h1>
<div className="flex f-center image-settings"> <div className="flex f-center image-settings">
<div> <div>
<h2>Avatar</h2> <h2>Avatar</h2>
@ -217,6 +180,7 @@ export default function SettingsPage() {
return ( return (
<div className="settings"> <div className="settings">
<h3>Profile</h3>
{settings()} {settings()}
{privKey && (<div className="flex f-col bg-grey"> {privKey && (<div className="flex f-col bg-grey">
<div> <div>
@ -226,15 +190,6 @@ export default function SettingsPage() {
<Copy text={hexToBech32("nsec", privKey)} /> <Copy text={hexToBech32("nsec", privKey)} />
</div> </div>
</div>)} </div>)}
<h4>Relays</h4>
<div className="flex f-col">
{Object.keys(relays || {}).map(a => <Relay addr={a} key={a} />)}
</div>
<div className="flex actions">
<div className="f-grow"></div>
<div className="btn" onClick={() => saveRelays()}>Save</div>
</div>
{addRelay()}
</div> </div>
); );
} }

View File

@ -0,0 +1,63 @@
import { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import Relay from "Element/Relay";
import useEventPublisher from "Feed/EventPublisher";
import { RootState } from "State/Store";
import { RelaySettings } from "Nostr/Connection";
import { setRelays } from "State/Login";
const RelaySettingsPage = () => {
const dispatch = useDispatch();
const publisher = useEventPublisher();
const relays = useSelector<RootState, Record<string, RelaySettings>>(s => s.login.relays);
const [newRelay, setNewRelay] = useState<string>();
async function saveRelays() {
let ev = await publisher.saveRelays();
publisher.broadcast(ev);
}
function addRelay() {
return (
<>
<h4>Add Relays</h4>
<div className="flex mb10">
<input type="text" className="f-grow" placeholder="wss://my-relay.com" value={newRelay} onChange={(e) => setNewRelay(e.target.value)} />
</div>
<div className="btn mb10" onClick={() => addNewRelay()}>Add</div>
</>
)
}
function addNewRelay() {
if ((newRelay?.length ?? 0) > 0) {
const parsed = new URL(newRelay!);
const payload = {
relays: {
...relays,
[parsed.toString()]: { read: false, write: false }
},
createdAt: Math.floor(new Date().getTime() / 1000)
};
dispatch(setRelays(payload))
}
}
return (
<>
<h3>Relays</h3>
<div className="flex f-col">
{Object.keys(relays || {}).map(a => <Relay addr={a} key={a} />)}
</div>
<div className="flex actions">
<div className="f-grow"></div>
<div className="btn" onClick={() => saveRelays()}>Save</div>
</div>
{addRelay()}
</>
)
}
export default RelaySettingsPage;

View File

@ -3,12 +3,36 @@ import * as secp from '@noble/secp256k1';
import { DefaultRelays } from 'Const'; import { DefaultRelays } from 'Const';
import { HexKey, RawEvent, TaggedRawEvent } from 'Nostr'; import { HexKey, RawEvent, TaggedRawEvent } from 'Nostr';
import { RelaySettings } from 'Nostr/Connection'; import { RelaySettings } from 'Nostr/Connection';
import { useDispatch } from 'react-redux';
const PrivateKeyItem = "secret"; const PrivateKeyItem = "secret";
const PublicKeyItem = "pubkey"; const PublicKeyItem = "pubkey";
const NotificationsReadItem = "notifications-read"; const NotificationsReadItem = "notifications-read";
const UserPreferencesKey = "preferences";
interface LoginStore { export interface UserPreferences {
/**
* Enable reactions / reposts / zaps
*/
enableReactions: boolean,
/**
* Automatically load media (show link only) (bandwidth/privacy)
*/
autoLoadMedia: boolean,
/**
* Select between light/dark theme
*/
theme: "system" | "light" | "dark",
/**
* Ask for confirmation when reposting notes
*/
confirmReposts: boolean
}
export interface LoginStore {
/** /**
* If there is no login * If there is no login
*/ */
@ -57,7 +81,12 @@ interface LoginStore {
/** /**
* Counter to trigger refresh of unread dms * Counter to trigger refresh of unread dms
*/ */
dmInteraction: 0 dmInteraction: 0,
/**
* Users cusom preferences
*/
preferences: UserPreferences
}; };
const InitState = { const InitState = {
@ -70,7 +99,13 @@ const InitState = {
notifications: [], notifications: [],
readNotifications: new Date().getTime(), readNotifications: new Date().getTime(),
dms: [], dms: [],
dmInteraction: 0 dmInteraction: 0,
preferences: {
enableReactions: true,
autoLoadMedia: true,
theme: "system",
confirmReposts: false
}
} as LoginStore; } as LoginStore;
export interface SetRelaysPayload { export interface SetRelaysPayload {
@ -106,6 +141,12 @@ const LoginSlice = createSlice({
if (!isNaN(readNotif)) { if (!isNaN(readNotif)) {
state.readNotifications = readNotif; state.readNotifications = readNotif;
} }
// preferences
let pref = window.localStorage.getItem(UserPreferencesKey);
if (pref) {
state.preferences = JSON.parse(pref);
}
}, },
setPrivateKey: (state, action: PayloadAction<HexKey>) => { setPrivateKey: (state, action: PayloadAction<HexKey>) => {
state.loggedOut = false; state.loggedOut = false;
@ -205,6 +246,10 @@ const LoginSlice = createSlice({
markNotificationsRead: (state) => { markNotificationsRead: (state) => {
state.readNotifications = new Date().getTime(); state.readNotifications = new Date().getTime();
window.localStorage.setItem(NotificationsReadItem, state.readNotifications.toString()); window.localStorage.setItem(NotificationsReadItem, state.readNotifications.toString());
},
setPreferences: (state, action: PayloadAction<UserPreferences>) => {
state.preferences = action.payload;
window.localStorage.setItem(UserPreferencesKey, JSON.stringify(state.preferences));
} }
} }
}); });
@ -220,6 +265,7 @@ export const {
addDirectMessage, addDirectMessage,
incDmInteraction, incDmInteraction,
logout, logout,
markNotificationsRead markNotificationsRead,
setPreferences
} = LoginSlice.actions; } = LoginSlice.actions;
export const reducer = LoginSlice.reducer; export const reducer = LoginSlice.reducer;

View File

@ -8,7 +8,7 @@
--font-size: 16px; --font-size: 16px;
--font-size-small: 14px; --font-size-small: 14px;
--font-size-tiny: 12px; --font-size-tiny: 12px;
--modal-bg-color: rgba(0,0,0, 0.8); --modal-bg-color: rgba(0, 0, 0, 0.8);
--note-bg: #111; --note-bg: #111;
--highlight-light: #ffd342; --highlight-light: #ffd342;
--highlight: #ffc400; --highlight: #ffc400;
@ -28,8 +28,7 @@
--strike-army-gradient: linear-gradient(to bottom right, #CCFF00, #a1c900); --strike-army-gradient: linear-gradient(to bottom right, #CCFF00, #a1c900);
} }
@media (prefers-color-scheme: light) { html.light {
:root {
--bg-color: #F1F1F1; --bg-color: #F1F1F1;
--font-color: #57534E; --font-color: #57534E;
--font-secondary-color: #B9B9B9; --font-secondary-color: #B9B9B9;
@ -47,7 +46,6 @@
--gray-tertiary: #EEE; --gray-tertiary: #EEE;
--gray-superlight: #333; --gray-superlight: #333;
--gray-light: #555; --gray-light: #555;
}
} }
body { body {
@ -70,18 +68,18 @@ code {
margin-right: auto; margin-right: auto;
} }
.page > .header { .page>.header {
display: flex; display: flex;
align-items: center; align-items: center;
margin: 10px 0; margin: 10px 0;
} }
.page > .header > div:nth-child(1) { .page>.header>div:nth-child(1) {
font-size: x-large; font-size: x-large;
flex-grow: 1; flex-grow: 1;
} }
.page > .header > div:nth-child(2) { .page>.header>div:nth-child(2) {
display: flex; display: flex;
align-items: center; align-items: center;
} }
@ -92,22 +90,26 @@ code {
background-color: var(--note-bg); background-color: var(--note-bg);
padding: 6px 12px; padding: 6px 12px;
} }
@media (min-width: 720px) { @media (min-width: 720px) {
.card { margin-bottom: 24px; padding: 12px 24px; }
}
@media (prefers-color-scheme: light) {
.card { .card {
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.05); margin-bottom: 24px;
padding: 12px 24px;
} }
} }
html.light .card {
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.05);
}
.card .header { .card .header {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: space-between; justify-content: space-between;
} }
.card > .footer { .card>.footer {
display: flex; display: flex;
flex-direction: row-reverse; flex-direction: row-reverse;
margin-top: 12px; margin-top: 12px;
@ -167,9 +169,14 @@ input[type="text"], input[type="password"], input[type="number"], textarea, sele
color: var(--font-color); color: var(--font-color);
} }
input[type="checkbox"] {
width: 24px;
height: 24px;
}
input:disabled { input:disabled {
color: var(--gray-medium); color: var(--gray-medium);
cursor:not-allowed; cursor: not-allowed;
} }
textarea:placeholder { textarea:placeholder {
@ -244,22 +251,22 @@ div.form-group {
align-items: center; align-items: center;
} }
div.form-group > div { div.form-group>div {
padding: 3px 5px; padding: 3px 5px;
word-break: break-word; word-break: break-word;
} }
div.form-group > div:nth-child(1) { div.form-group>div:nth-child(1) {
min-width: 100px; min-width: 100px;
} }
div.form-group > div:nth-child(2) { div.form-group>div:nth-child(2) {
display: flex; display: flex;
flex-grow: 1; flex-grow: 1;
justify-content: end; justify-content: end;
} }
div.form-group > div:nth-child(2) input { div.form-group>div:nth-child(2) input {
flex-grow: 1; flex-grow: 1;
} }
@ -269,7 +276,7 @@ div.form-group > div:nth-child(2) input {
height: 100vh; height: 100vh;
top: 0; top: 0;
left: 0; left: 0;
background-color: rgba(0,0,0,0.8); background-color: rgba(0, 0, 0, 0.8);
} }
.modal .modal-content { .modal .modal-content {
@ -277,7 +284,7 @@ div.form-group > div:nth-child(2) input {
justify-content: center; justify-content: center;
} }
.modal .modal-content > div { .modal .modal-content>div {
padding: 10px; padding: 10px;
border-radius: 10px; border-radius: 10px;
background-color: var(--gray); background-color: var(--gray);
@ -321,12 +328,12 @@ body.scroll-lock {
overflow-x: auto; overflow-x: auto;
} }
.tabs > div { .tabs>div {
margin-right: 10px; margin-right: 10px;
cursor: pointer; cursor: pointer;
} }
.tabs > div:last-child { .tabs>div:last-child {
margin: 0; margin: 0;
} }
@ -355,6 +362,7 @@ body.scroll-lock {
.root-tab { .root-tab {
border-bottom: 3px solid var(--gray-secondary); border-bottom: 3px solid var(--gray-secondary);
} }
.root-tab.active { .root-tab.active {
border-bottom: 3px solid var(--highlight); border-bottom: 3px solid var(--highlight);
} }
@ -373,7 +381,7 @@ body.scroll-lock {
margin: 0 auto; margin: 0 auto;
} }
.tweet div .twitter-tweet > iframe { .tweet div .twitter-tweet>iframe {
max-height: unset; max-height: unset;
} }
@ -381,10 +389,13 @@ body.scroll-lock {
.page { .page {
width: calc(100vw - 8px); width: calc(100vw - 8px);
} }
div.form-group { div.form-group {
flex-direction: column; flex-direction: column;
align-items: flex-start; align-items: flex-start;
} }
} }
.highlight { color: var(--highlight); } .highlight {
color: var(--highlight);
}

View File

@ -19,7 +19,7 @@ import ProfilePage from 'Pages/ProfilePage';
import RootPage from 'Pages/Root'; import RootPage from 'Pages/Root';
import NotificationsPage from 'Pages/Notifications'; import NotificationsPage from 'Pages/Notifications';
import NewUserPage from 'Pages/NewUserPage'; import NewUserPage from 'Pages/NewUserPage';
import SettingsPage from 'Pages/SettingsPage'; import SettingsPage, { SettingsRoutes } from 'Pages/SettingsPage';
import ErrorPage from 'Pages/ErrorPage'; import ErrorPage from 'Pages/ErrorPage';
import VerificationPage from 'Pages/Verification'; import VerificationPage from 'Pages/Verification';
import MessagesPage from 'Pages/MessagesPage'; import MessagesPage from 'Pages/MessagesPage';
@ -65,7 +65,8 @@ const router = createBrowserRouter([
}, },
{ {
path: "/settings", path: "/settings",
element: <SettingsPage /> element: <SettingsPage />,
children: SettingsRoutes
}, },
{ {
path: "/verification", path: "/verification",