+
+
+
{root ?
: null}
{!root && refEvent ? (
diff --git a/packages/app/src/Element/ProfileImage.tsx b/packages/app/src/Element/ProfileImage.tsx
index 203dd9e31..9bed17c82 100644
--- a/packages/app/src/Element/ProfileImage.tsx
+++ b/packages/app/src/Element/ProfileImage.tsx
@@ -50,8 +50,7 @@ export default function ProfileImage({
+ onClick={handleClick}>
diff --git a/packages/app/src/Element/Tabs.css b/packages/app/src/Element/Tabs.css
index 54cd1afcf..fc0ef6d40 100644
--- a/packages/app/src/Element/Tabs.css
+++ b/packages/app/src/Element/Tabs.css
@@ -5,8 +5,9 @@
overflow-x: scroll;
-ms-overflow-style: none; /* for Internet Explorer, Edge */
scrollbar-width: none; /* Firefox */
- margin-bottom: 18px;
white-space: nowrap;
+ gap: 8px;
+ padding: 16px 12px;
}
.tabs::-webkit-scrollbar {
@@ -14,23 +15,21 @@
}
.tab {
+ background: var(--gray-ultradark);
color: var(--font-tertiary-color);
- border: 1px solid var(--border-color);
- border-radius: 16px;
+ border-radius: 100px;
font-weight: 600;
- font-size: 14px;
- padding: 6px 12px;
- text-align: center;
- font-feature-settings: "tnum";
-}
-
-.tab:not(:last-of-type) {
- margin-right: 8px;
+ font-size: 16px;
+ padding: 10px 16px;
+ display: flex;
+ align-items: center;
+ justify-items: center;
+ gap: 6px;
}
.tab.active {
- border-color: var(--font-color);
- color: var(--font-color);
+ color: black;
+ background: white;
}
.tabs > div {
diff --git a/packages/app/src/Element/Tabs.tsx b/packages/app/src/Element/Tabs.tsx
index baca3e183..318afefc8 100644
--- a/packages/app/src/Element/Tabs.tsx
+++ b/packages/app/src/Element/Tabs.tsx
@@ -1,8 +1,9 @@
+import { ReactNode } from "react";
import "./Tabs.css";
import useHorizontalScroll from "Hooks/useHorizontalScroll";
export interface Tab {
- text: string;
+ text: ReactNode;
value: number;
disabled?: boolean;
}
diff --git a/packages/app/src/Element/Thread.css b/packages/app/src/Element/Thread.css
index 3049886e3..59a057fdb 100644
--- a/packages/app/src/Element/Thread.css
+++ b/packages/app/src/Element/Thread.css
@@ -1,7 +1,3 @@
-.thread-container {
- margin: 12px 0 150px 0;
-}
-
.thread-container .hidden-note {
margin: 0;
border-radius: 0;
@@ -11,11 +7,6 @@
box-shadow: none;
}
-.thread-root.note > .body {
- margin-top: 8px;
- padding-left: 8px;
-}
-
.thread-root.note > .body .text {
font-size: 19px;
}
@@ -31,12 +22,13 @@
}
.thread-note.note {
- border-radius: 0;
- margin-bottom: 0;
+ border: 0;
}
-.light .thread-note.note.card {
- box-shadow: none;
+.thread-note.note .zaps-summary,
+.thread-note.note .footer,
+.thread-note.note .body {
+ margin-left: 61px;
}
.thread-container .hidden-note {
@@ -58,83 +50,47 @@
position: relative;
}
-.line-container {
- background: var(--note-bg);
-}
-
.subthread-container.subthread-multi .line-container:before {
content: "";
position: absolute;
- left: 36px;
+ left: calc(48px / 2 + 16px);
top: 48px;
border-left: 1px solid var(--gray-superdark);
height: 100%;
+ z-index: -1;
}
-@media (min-width: 720px) {
- .subthread-container.subthread-multi .line-container:before {
- left: 48px;
- }
-}
-
-.subthread-container.subthread-mid:not(.subthread-last) .line-container:after {
- content: "";
- position: absolute;
- left: 36px;
- top: 48px;
- border-left: 1px solid var(--gray-superdark);
- height: 100%;
-}
-
-@media (min-width: 720px) {
- .subthread-container.subthread-mid:not(.subthread-last) .line-container:after {
- left: 48px;
- }
-}
-
-.subthread-container.subthread-mid:not(.subthread-last) .line-container:after {
+.subthread-container.subthread-mid:not(.subthread-last) .line-container:before {
content: "";
position: absolute;
border-left: 1px solid var(--gray-superdark);
- left: 36px;
+ left: calc(48px / 2 + 16px);
top: 0;
height: 48px;
-}
-
-@media (min-width: 720px) {
- .subthread-container.subthread-mid:not(.subthread-last) .line-container:after {
- left: 48px;
- }
+ z-index: -1;
}
.subthread-container.subthread-last .line-container:before {
content: "";
position: absolute;
border-left: 1px solid var(--gray-superdark);
- left: 36px;
+ left: calc(48px / 2 + 16px);
top: 0;
height: 48px;
-}
-
-@media (min-width: 720px) {
- .subthread-container.subthread-last .line-container:before {
- left: 48px;
- }
+ z-index: -1;
}
.divider-container {
- background: var(--note-bg);
+ margin-right: 16px;
}
.divider {
height: 1px;
background: var(--gray-superdark);
- margin-left: 28px;
- margin-right: 22px;
}
.divider.divider-small {
- margin-left: 80px;
+ margin-left: calc(16px + 61px);
}
.thread-container .collapsed,
@@ -143,11 +99,6 @@
min-height: 48px;
}
-.thread-note.is-last-note {
- border-bottom-left-radius: 16px;
- border-bottom-right-radius: 16px;
-}
-
.thread-container .collapsed {
background-color: var(--note-bg);
}
@@ -155,13 +106,3 @@
.thread-container .hidden-note {
padding-left: 48px;
}
-
-.thread-root.thread-root-single.note {
- border-bottom-left-radius: 16px;
- border-bottom-right-radius: 16px;
-}
-
-.thread-root.ghost-root {
- border-top-left-radius: 16px;
- border-top-right-radius: 16px;
-}
diff --git a/packages/app/src/Element/Thread.tsx b/packages/app/src/Element/Thread.tsx
index 77e1f265c..3e32e40ec 100644
--- a/packages/app/src/Element/Thread.tsx
+++ b/packages/app/src/Element/Thread.tsx
@@ -374,9 +374,11 @@ export default function Thread() {
description: "Navigate back button on threads view",
});
return (
-
-
-
+ <>
+
+
+
+
{root && renderRoot(root)}
{root && renderChain(root.id)}
@@ -392,7 +394,7 @@ export default function Thread() {
);
})}
-
+ >
);
}
diff --git a/packages/app/src/Pages/Layout.tsx b/packages/app/src/Pages/Layout.tsx
index 8cb594595..f06711ee4 100644
--- a/packages/app/src/Pages/Layout.tsx
+++ b/packages/app/src/Pages/Layout.tsx
@@ -40,7 +40,7 @@ export default function Layout() {
};
const shouldHideNoteCreator = useMemo(() => {
- const hideOn = ["/settings", "/messages", "/new", "/login", "/donate", "/p/", "/e", "/subscribe", "/live"];
+ const hideOn = ["/settings", "/messages", "/new", "/login", "/donate", "/p/", "/e", "/subscribe"];
return isReplyNoteCreatorShowing || hideOn.some(a => location.pathname.startsWith(a));
}, [location, isReplyNoteCreatorShowing]);
@@ -50,8 +50,8 @@ export default function Layout() {
}, [location]);
useEffect(() => {
- const widePage = ["/login", "/messages", "/live"];
- const noScroll = ["/messages", "/live"];
+ const widePage = ["/login", "/messages"];
+ const noScroll = ["/messages"];
if (widePage.some(a => location.pathname.startsWith(a))) {
setPageClass(noScroll.some(a => location.pathname.startsWith(a)) ? "scroll-lock" : "");
} else {
diff --git a/packages/app/src/Pages/ProfilePage.css b/packages/app/src/Pages/ProfilePage.css
index e81b203ea..e25d57a58 100644
--- a/packages/app/src/Pages/ProfilePage.css
+++ b/packages/app/src/Pages/ProfilePage.css
@@ -2,28 +2,21 @@
display: flex;
flex-direction: column;
align-items: flex-start;
+ border: 1px solid var(--gray-superdark);
}
.profile .banner {
width: 100%;
height: 160px;
object-fit: cover;
- margin-bottom: -60px;
+ margin-bottom: -37px;
z-index: 0;
}
-@media (min-width: 720px) {
- .profile .banner {
- border-radius: 12px;
- }
-}
.profile .profile-actions {
- position: absolute;
- top: 72px;
- right: 0;
display: flex;
- flex-direction: row;
align-items: center;
+ align-self: flex-end;
}
.profile .icon-actions {
@@ -52,13 +45,13 @@
}
.profile .profile-wrapper {
- margin: 0 16px;
- width: calc(100% - 32px);
+ margin: 0 16px 12px 16px;
display: flex;
flex-direction: column;
align-items: flex-start;
position: relative;
overflow: hidden;
+ gap: 16px;
}
.profile p {
@@ -66,21 +59,26 @@
}
.details-wrapper > .name > h2 {
- margin: 12px 0 0 0;
+ margin: 0 0 4px 0;
font-weight: 600;
- font-size: 19px;
- line-height: 23px;
+ font-size: 21px;
+}
+
+.details-wrapper > .name > .nip05 {
+ font-size: 15px;
}
.profile-wrapper > .avatar-wrapper {
z-index: 1;
+ display: flex;
+ justify-content: space-between;
}
.profile-wrapper > .avatar-wrapper .avatar {
- width: 120px;
- height: 120px;
+ width: 100px;
+ height: 100px;
background-image: var(--img-url);
- border: 3px solid var(--bg-color);
+ border: 3px solid #fff;
}
.profile .name {
@@ -88,28 +86,30 @@
flex-direction: column;
}
-.profile .details {
- width: 100%;
+.profile .about {
color: var(--font-secondary-color);
- margin-bottom: 12px;
- font-weight: 400;
- font-size: 14px;
- line-height: 22px;
+ font-size: 16px;
+ line-height: 26px;
}
-.profile .details p {
+.profile .about p {
word-break: break-word;
}
-.profile .details a {
+.profile .about a {
color: var(--highlight);
text-decoration: none;
}
-.profile .details a:hover {
+.profile .about a:hover {
text-decoration: underline;
}
+.profile .about .text {
+ font-size: inherit;
+ line-height: inherit;
+}
+
.profile .btn-icon {
color: var(--font-color);
padding: 6px;
@@ -118,54 +118,36 @@
.profile .details-wrapper {
display: flex;
flex-direction: column;
- justify-content: space-between;
- width: calc(100% - 32px);
+ gap: 16px;
}
-.profile .details .text {
- font-size: 14px;
-}
-
-.profile .links {
- font-size: 14px;
- margin-top: 4px;
- margin-left: 2px;
- margin-bottom: 12px;
-}
-
-.profile .website {
- margin: 4px 0;
+.profile .link-section {
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+ font-size: 15px;
+ line-height: 24px;
+}
+
+.profile .link {
display: flex;
- flex-direction: row;
align-items: center;
-}
-
-@media (max-width: 720px) {
- .profile .lnurl {
- display: none;
- }
-}
-
-.profile .website a {
- color: var(--font-color);
+ gap: 8px;
}
.profile .website a {
text-decoration: none;
}
-
.profile .website a:hover {
text-decoration: underline;
}
-.profile .lnurl {
- cursor: pointer;
+.profile .link svg {
+ color: var(--highlight);
}
-.profile .ln-address {
- display: flex;
- flex-direction: row;
- align-items: center;
+.profile .lnurl {
+ cursor: pointer;
}
.profile .lnurl:hover {
@@ -177,21 +159,9 @@
text-overflow: ellipsis;
}
-.profile .links svg {
- color: var(--highlight);
- margin-right: 8px;
- width: 12px;
- height: 12px;
-}
-
-.profile .npub {
- display: flex;
- flex-direction: row;
- align-items: center;
-}
-
-.profile .copy {
- margin-top: 12px;
+.profile .copy .body {
+ font-size: inherit;
+ line-height: inherit;
}
.qr-modal .pfp {
diff --git a/packages/app/src/Pages/ProfilePage.tsx b/packages/app/src/Pages/ProfilePage.tsx
index 69115c359..b78d0df09 100644
--- a/packages/app/src/Pages/ProfilePage.tsx
+++ b/packages/app/src/Pages/ProfilePage.tsx
@@ -1,6 +1,6 @@
import "./ProfilePage.css";
import { useEffect, useState } from "react";
-import { useIntl, FormattedMessage } from "react-intl";
+import { FormattedMessage } from "react-intl";
import { useNavigate, useParams } from "react-router-dom";
import {
encodeTLV,
@@ -109,7 +109,6 @@ function BookMarksTab({ id }: { id: HexKey }) {
}
export default function ProfilePage() {
- const { formatMessage } = useIntl();
const params = useParams();
const navigate = useNavigate();
const [id, setId] = useState
();
@@ -144,16 +143,88 @@ export default function ProfilePage() {
const follows = useFollowsFeed(id);
// tabs
const ProfileTab = {
- Notes: { text: formatMessage({ defaultMessage: "Notes" }), value: NOTES },
- Reactions: { text: formatMessage(messages.Reactions), value: REACTIONS },
- Followers: { text: formatMessage(messages.Followers), value: FOLLOWERS },
- Follows: { text: formatMessage(messages.Follows), value: FOLLOWS },
- Zaps: { text: formatMessage(messages.Zaps), value: ZAPS },
- Muted: { text: formatMessage(messages.Muted), value: MUTED },
- Blocked: { text: formatMessage(messages.BlockedCount, { n: blocked.length }), value: BLOCKED },
- Relays: { text: formatMessage(messages.Relays), value: RELAYS },
- Bookmarks: { text: formatMessage(messages.Bookmarks), value: BOOKMARKS },
- };
+ Notes: {
+ text: (
+ <>
+
+
+ >
+ ),
+ value: NOTES,
+ },
+ Reactions: {
+ text: (
+ <>
+
+
+ >
+ ),
+ value: REACTIONS,
+ },
+ Followers: {
+ text: (
+ <>
+
+
+ >
+ ),
+ value: FOLLOWERS,
+ },
+ Follows: {
+ text: (
+ <>
+
+
+ >
+ ),
+ value: FOLLOWS,
+ },
+ Zaps: {
+ text: (
+ <>
+
+
+ >
+ ),
+ value: ZAPS,
+ },
+ Muted: {
+ text: (
+ <>
+
+
+ >
+ ),
+ value: MUTED,
+ },
+ Blocked: {
+ text: (
+ <>
+
+
+ >
+ ),
+ value: BLOCKED,
+ },
+ Relays: {
+ text: (
+ <>
+
+
+ >
+ ),
+ value: RELAYS,
+ },
+ Bookmarks: {
+ text: (
+ <>
+
+
+ >
+ ),
+ value: BOOKMARKS,
+ },
+ } as { [key: string]: Tab };
const [tab, setTab] = useState(ProfileTab.Notes);
const optionalTabs = [ProfileTab.Zaps, ProfileTab.Relays, ProfileTab.Bookmarks, ProfileTab.Muted].filter(a =>
unwrap(a)
@@ -179,34 +250,48 @@ export default function ProfilePage() {
function username() {
return (
-
-
- {user?.display_name || user?.name || "Nostrich"}
-
-
- {user?.nip05 &&
}
+ <>
+
+
+ {user?.display_name || user?.name || "Nostrich"}
+
+
+ {user?.nip05 && }
+
-
- {links()}
-
+
+
+ {links()}
+
+ >
);
}
+ function tryFormatWebsite(url: string) {
+ try {
+ const u = new URL(url);
+ return `${u.hostname}${u.pathname !== "/" ? u.pathname : ""}`;
+ } catch {
+ // ignore
+ }
+ return url;
+ }
+
function links() {
return (
-
+ <>
{user?.website && (
-
-
+
)}
{lnurl && (
-
setShowLnQr(true)}>
-
+
setShowLnQr(true)}>
+
{lnurl.name}
)}
@@ -218,14 +303,14 @@ export default function ProfilePage() {
author={id}
target={user?.display_name || user?.name}
/>
-
+ >
);
}
function bio() {
return (
aboutText.length > 0 && (
-
+
{about}
)
@@ -296,8 +381,12 @@ export default function ProfilePage() {
function avatar() {
return (
-
+
+
+ {renderIcons()}
+ {!isMe && id && }
+
);
}
@@ -356,12 +445,8 @@ export default function ProfilePage() {
function userDetails() {
if (!id) return;
return (
-
+
{username()}
-
- {renderIcons()}
- {!isMe && }
-
{bio()}
);
@@ -374,9 +459,9 @@ export default function ProfilePage() {
const w = window.document.querySelector(".page")?.clientWidth;
return (
<>
-
+
{user?.banner &&
}
-
+
{avatar()}
{userDetails()}
diff --git a/packages/app/src/Pages/Root.tsx b/packages/app/src/Pages/Root.tsx
index 351d58d4e..b2b0f3f70 100644
--- a/packages/app/src/Pages/Root.tsx
+++ b/packages/app/src/Pages/Root.tsx
@@ -31,15 +31,6 @@ export default function RootPage() {
const { publicKey: pubKey, tags, preferences } = useLogin();
const [rootType, setRootType] = useState
("following");
- useEffect(() => {
- if (location.pathname === "/") {
- const t = pubKey ? preferences.defaultRootTab ?? "/notes" : "/global";
- navigate(t, {
- replace: true,
- });
- }
- }, [location]);
-
const menuItems = [
{
tab: "following",
@@ -107,6 +98,18 @@ export default function RootPage() {
element: ReactNode;
}>;
+ useEffect(() => {
+ if (location.pathname === "/") {
+ const t = pubKey ? preferences.defaultRootTab ?? "/notes" : "/global";
+ navigate(t);
+ } else {
+ const currentTab = menuItems.find(a => a.path === location.pathname)?.tab;
+ if (currentTab) {
+ setRootType(currentTab);
+ }
+ }
+ }, [location]);
+
function currentMenuItem() {
if (location.pathname.startsWith("/t/")) {
return (
@@ -139,8 +142,7 @@ export default function RootPage() {
{menuItems.map(a => (
@@ -148,8 +150,7 @@ export default function RootPage() {
{tags.item.map(v => (