From 734a9b2b76c176a71c8723adbfd810e763b55417 Mon Sep 17 00:00:00 2001 From: Lim Chee Aun Date: Sat, 17 Dec 2022 19:51:48 +0800 Subject: [PATCH 01/17] Remove unused code --- src/components/status.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/status.jsx b/src/components/status.jsx index d4457617..818dc0ba 100644 --- a/src/components/status.jsx +++ b/src/components/status.jsx @@ -614,7 +614,6 @@ function Status({ ); } - const [actionsUIState, setActionsUIState] = useState(null); // boost-loading, favourite-loading, bookmark-loading const [showEdited, setShowEdited] = useState(false); const carouselRef = useRef(null); From 400bc6f696dc098916644d4cc804c01f68d15ed8 Mon Sep 17 00:00:00 2001 From: Lim Chee Aun Date: Sat, 17 Dec 2022 21:06:51 +0800 Subject: [PATCH 02/17] Truncate long posts on timeline, show "Read more" 10-line clamping for now --- package-lock.json | 74 ++++++++++++++++++++++++++++++++++++++- package.json | 3 +- src/components/status.css | 24 +++++++++++++ src/components/status.jsx | 39 ++++++++++++++++++++- 4 files changed, 137 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index c3886135..e1bfe48e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "preact-router": "~4.1.0", "react-intersection-observer": "~9.4.1", "string-length": "~5.0.1", + "use-resize-observer": "~9.1.0", "valtio": "~1.7.6" }, "devDependencies": { @@ -27,7 +28,7 @@ "autoprefixer": "~10.4.13", "postcss": "~8.4.20", "postcss-dark-theme-class": "~0.7.3", - "vite": "4.0.1" + "vite": "~4.0.1" } }, "node_modules/@ampproject/remapping": { @@ -848,6 +849,11 @@ "@jridgewell/sourcemap-codec": "1.4.14" } }, + "node_modules/@juggle/resize-observer": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.4.0.tgz", + "integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==" + }, "node_modules/@preact/preset-vite": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/@preact/preset-vite/-/preset-vite-2.5.0.tgz", @@ -1996,6 +2002,19 @@ "node": ">=0.10.0" } }, + "node_modules/react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, "node_modules/react-intersection-observer": { "version": "9.4.1", "resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-9.4.1.tgz", @@ -2042,6 +2061,15 @@ "fsevents": "~2.3.2" } }, + "node_modules/scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + } + }, "node_modules/semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -2205,6 +2233,18 @@ "tslib": "^2.0.3" } }, + "node_modules/use-resize-observer": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/use-resize-observer/-/use-resize-observer-9.1.0.tgz", + "integrity": "sha512-R25VqO9Wb3asSD4eqtcxk8sJalvIOYBqS8MNZlpDSQ4l4xMQxC/J7Id9HoTqPq8FwULIn0PVW+OAqF2dyYbjow==", + "dependencies": { + "@juggle/resize-observer": "^3.3.1" + }, + "peerDependencies": { + "react": "16.8.0 - 18", + "react-dom": "16.8.0 - 18" + } + }, "node_modules/use-sync-external-store": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", @@ -2836,6 +2876,11 @@ "@jridgewell/sourcemap-codec": "1.4.14" } }, + "@juggle/resize-observer": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.4.0.tgz", + "integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==" + }, "@preact/preset-vite": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/@preact/preset-vite/-/preset-vite-2.5.0.tgz", @@ -3702,6 +3747,16 @@ "loose-envify": "^1.1.0" } }, + "react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "peer": true, + "requires": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + } + }, "react-intersection-observer": { "version": "9.4.1", "resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-9.4.1.tgz", @@ -3733,6 +3788,15 @@ "fsevents": "~2.3.2" } }, + "scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "peer": true, + "requires": { + "loose-envify": "^1.1.0" + } + }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -3847,6 +3911,14 @@ "tslib": "^2.0.3" } }, + "use-resize-observer": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/use-resize-observer/-/use-resize-observer-9.1.0.tgz", + "integrity": "sha512-R25VqO9Wb3asSD4eqtcxk8sJalvIOYBqS8MNZlpDSQ4l4xMQxC/J7Id9HoTqPq8FwULIn0PVW+OAqF2dyYbjow==", + "requires": { + "@juggle/resize-observer": "^3.3.1" + } + }, "use-sync-external-store": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", diff --git a/package.json b/package.json index 1dede8e4..c0b64ec2 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "preact-router": "~4.1.0", "react-intersection-observer": "~9.4.1", "string-length": "~5.0.1", + "use-resize-observer": "~9.1.0", "valtio": "~1.7.6" }, "devDependencies": { @@ -28,7 +29,7 @@ "autoprefixer": "~10.4.13", "postcss": "~8.4.20", "postcss-dark-theme-class": "~0.7.3", - "vite": "4.0.1" + "vite": "~4.0.1" }, "postcss": { "plugins": { diff --git a/src/components/status.css b/src/components/status.css index 731dfb4d..eda87067 100644 --- a/src/components/status.css +++ b/src/components/status.css @@ -174,6 +174,30 @@ .status .content { margin-top: 8px; } +.timeline-deck .status .content { + display: -webkit-box; + -webkit-line-clamp: 10; + -webkit-box-orient: vertical; + overflow: hidden; + position: relative; +} +.timeline-deck .status .content.truncated:after { + content: attr(data-read-more); + line-height: 1; + display: inline-block; + position: absolute; + inset-block-end: 0; + inset-inline-end: 0; + color: var(--link-color); + background-color: var(--link-faded-color); + backdrop-filter: blur(4px) brightness(2); + padding: 0.5em 0.5em 0.5em 2em; + border-radius: 0 1em 1em 0; + font-size: 12px; + font-weight: bold; + text-transform: uppercase; + mask-image: linear-gradient(to right, transparent, black 2em); +} .status .content p { margin-block: 0.75em; } diff --git a/src/components/status.jsx b/src/components/status.jsx index 818dc0ba..3704e191 100644 --- a/src/components/status.jsx +++ b/src/components/status.jsx @@ -4,6 +4,7 @@ import { getBlurHashAverageColor } from 'fast-blurhash'; import mem from 'mem'; import { useEffect, useMemo, useRef, useState } from 'preact/hooks'; import { InView } from 'react-intersection-observer'; +import useResizeObserver from 'use-resize-observer'; import { useSnapshot } from 'valtio'; import Loader from '../components/loader'; @@ -619,6 +620,34 @@ function Status({ const carouselRef = useRef(null); const currentYear = new Date().getFullYear(); + const spoilerContentRef = useRef(null); + useResizeObserver({ + ref: spoilerContentRef, + onResize: () => { + if (spoilerContentRef.current) { + const { scrollHeight, clientHeight } = spoilerContentRef.current; + spoilerContentRef.current.classList.toggle( + 'truncated', + scrollHeight > clientHeight, + ); + } + }, + }); + const contentRef = useRef(null); + useResizeObserver({ + ref: contentRef, + onResize: () => { + if (contentRef.current) { + const { scrollHeight, clientHeight } = contentRef.current; + contentRef.current.classList.toggle( + 'truncated', + scrollHeight > clientHeight, + ); + } + }, + }); + const readMoreText = 'read more →'; + return (
{!!spoilerText && sensitive && ( <> -
+

{spoilerText}

From 4b49c6fb03ee309f23b559a4c0dc49219f6ee0b1 Mon Sep 17 00:00:00 2001 From: Lim Chee Aun Date: Sun, 18 Dec 2022 00:38:19 +0800 Subject: [PATCH 10/17] Aesthetic changes to Account sheet - Larger avatar - Less rounded sheet - Add Joined date --- src/app.css | 2 +- src/components/account.css | 8 +++++--- src/components/account.jsx | 18 ++++++++++++++++-- src/components/avatar.jsx | 1 + 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/app.css b/src/app.css index 3cdd82e4..3178b5e4 100644 --- a/src/app.css +++ b/src/app.css @@ -471,7 +471,7 @@ button.carousel-dot[disabled].active { background-color: var(--bg-color); width: 100%; max-width: calc(40em - 50px - 16px); - border-radius: 36px 36px 0 0; + border-radius: 16px 16px 0 0; padding: 16px; box-shadow: 0 -1px 32px var(--divider-color); animation: slide-up 0.2s ease-out; diff --git a/src/components/account.css b/src/components/account.css index 0b11377a..7f57af99 100644 --- a/src/components/account.css +++ b/src/components/account.css @@ -2,7 +2,7 @@ color: var(--outline-color); } -#account-container header{ +#account-container header { display: flex; align-items: center; gap: 8px; @@ -16,8 +16,10 @@ #account-container .stats { display: flex; flex-wrap: wrap; - gap: 16px; + column-gap: 16px; + row-gap: 4px; opacity: 0.75; + font-size: 90%; } #account-container .actions { @@ -28,4 +30,4 @@ } #account-container .actions button { align-self: flex-end; -} \ No newline at end of file +} diff --git a/src/components/account.jsx b/src/components/account.jsx index b5310217..ad7c77bd 100644 --- a/src/components/account.jsx +++ b/src/components/account.jsx @@ -104,7 +104,7 @@ function Account({ account }) { {!info || uiState === 'loading' ? ( <>
- + ███ ████████████
@@ -120,7 +120,7 @@ function Account({ account }) { ) : ( <>
- +
{shortenNumber(followersCount)}{' '} Followers + {!!createdAt && ( + + Joined:{' '} + + + + + )}

{followedBy ? Following you : }{' '} diff --git a/src/components/avatar.jsx b/src/components/avatar.jsx index 3059b1e2..f8e1ca29 100644 --- a/src/components/avatar.jsx +++ b/src/components/avatar.jsx @@ -6,6 +6,7 @@ const SIZES = { l: 24, xl: 32, xxl: 50, + xxxl: 64, }; function Avatar({ url, size, alt = '' }) { From 72b0931554d539410100ddd7377f732f93ce3991 Mon Sep 17 00:00:00 2001 From: Lim Chee Aun Date: Sun, 18 Dec 2022 01:04:26 +0800 Subject: [PATCH 11/17] Super lazy way to implement "only mentions" in Notifications #OnlyMentions Could have make another tab that makes another request to /notifications but I feel lazy --- src/index.css | 4 ++++ src/pages/notifications.css | 32 ++++++++++++++++++++++++++++++-- src/pages/notifications.jsx | 27 ++++++++++++++++++++++++++- 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/src/index.css b/src/index.css index 061c9f63..5fec3835 100644 --- a/src/index.css +++ b/src/index.css @@ -218,6 +218,10 @@ code { flex-grow: 1; } +.insignificant { + color: var(--text-insignificant-color); +} + /* KEYFRAMES */ @keyframes fade-in { diff --git a/src/pages/notifications.css b/src/pages/notifications.css index e91adcde..9b2c4179 100644 --- a/src/pages/notifications.css +++ b/src/pages/notifications.css @@ -3,6 +3,10 @@ padding: 16px !important; gap: 16px; } +.only-mentions .notification:not(.mention), +.only-mentions .timeline-empty { + display: none; +} .notification.skeleton { color: var(--outline-color); } @@ -30,7 +34,11 @@ max-height: 160px; overflow: hidden; /* fade out mask gradient bottom */ - mask-image: linear-gradient(rgba(0, 0, 0, 1), rgba(0, 0, 0, 1) 50%, transparent); + mask-image: linear-gradient( + rgba(0, 0, 0, 1), + rgba(0, 0, 0, 1) 50%, + transparent + ); filter: saturate(0.25); } .notification .status-link:hover { @@ -46,4 +54,24 @@ } .notification-content p:first-child { margin-top: 0; -} \ No newline at end of file +} + +#mentions-option { + float: right; + margin-top: 0.5em; +} +#mentions-option label { + color: var(--text-insignificant-color); + display: inline-block; + padding: 1em 16px; + position: relative; + cursor: pointer; + z-index: 1; + font-size: 90%; + background-color: var(--bg-blur-color); + border-radius: 2em; +} +#mentions-option label:has(:checked) { + color: var(--text-color); + background-color: var(--bg-color); +} diff --git a/src/pages/notifications.jsx b/src/pages/notifications.jsx index b82cf2c5..6796aabd 100644 --- a/src/pages/notifications.jsx +++ b/src/pages/notifications.jsx @@ -97,6 +97,18 @@ function Notification({ notification }) { )} {text} + {type === 'mention' && ( + + {' '} + •{' '} + + + )}

{_accounts?.length > 1 && (

@@ -192,6 +204,7 @@ function Notifications() { const snapStates = useSnapshot(states); const [uiState, setUIState] = useState('default'); const [showMore, setShowMore] = useState(false); + const [onlyMentions, setOnlyMentions] = useState(false); const notificationsIterator = useRef( masto.notifications.getIterator({ @@ -273,7 +286,7 @@ function Notifications() { // console.log(groupedNotifications); return (

-
+
+
+ +
{snapStates.notifications.length ? ( <>

Today

From 6e09d5f836f3f9578416dc54b232053ff5d80d2d Mon Sep 17 00:00:00 2001 From: Lim Chee Aun Date: Sun, 18 Dec 2022 01:14:44 +0800 Subject: [PATCH 12/17] Fix .insignificant class affecting other elements Remove them because they were used in previous discarded design --- src/app.css | 10 ---------- src/pages/status.jsx | 8 +++----- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/src/app.css b/src/app.css index 3178b5e4..fac7fcfb 100644 --- a/src/app.css +++ b/src/app.css @@ -121,16 +121,6 @@ a.mention span { .timeline.flat > li { border-bottom: none; } -/* .timeline li.insignificant { - filter: opacity(0.5); - background-color: var(--bg-faded-color); -} -.timeline li.insignificant > * { - opacity: 0.75; -} -.timeline li.insignificant:hover > * { - opacity: 1; -} */ .timeline.contextual > li { --width: 3px; diff --git a/src/pages/status.jsx b/src/pages/status.jsx index 8b27f7b6..e2f3a9ba 100644 --- a/src/pages/status.jsx +++ b/src/pages/status.jsx @@ -166,11 +166,9 @@ function StatusPage({ id }) {
  • {isHero ? ( From 1ffcffa1f46b7c101976d98f918693ed7f4e1297 Mon Sep 17 00:00:00 2001 From: Lim Chee Aun Date: Sun, 18 Dec 2022 10:08:44 +0800 Subject: [PATCH 13/17] Try different style for "Read more" --- src/components/status.css | 25 +++++++++++++++---------- src/components/status.jsx | 2 +- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/components/status.css b/src/components/status.css index 1875145c..72b7419b 100644 --- a/src/components/status.css +++ b/src/components/status.css @@ -181,30 +181,35 @@ position: relative; } .timeline-deck .status .content.truncated { - mask-image: linear-gradient(to top, transparent 0.5em, black 1.5em); + mask-image: linear-gradient( + to top, + transparent, + rgba(0, 0, 0, 0.5) 1em, + black 1.5em + ); } .timeline-deck .status .content.truncated:after { content: attr(data-read-more); line-height: 1; display: inline-block; position: absolute; - inset-block-end: 1em; + inset-block-end: 1.5em; left: 50%; transform: translateX(-50%); color: var(--text-color); background-color: var(--bg-faded-color); - border: 2px solid var(--link-light-color); - padding: 0.5em 1em; + border: 1px dashed var(--link-color); + padding: 0.75em 1em; border-radius: 10em; - font-size: 12px; - font-weight: bold; - text-transform: uppercase; - box-shadow: 0 0 0 2px var(--bg-color), 0 0 10px var(--bg-color), - 0 0 10px var(--bg-color), 0 0 10px var(--bg-color); + font-size: 90%; white-space: nowrap; + box-shadow: 0 0 0 1px var(--bg-color), 0 -5px 10px var(--bg-color), + 0 -5px 15px var(--bg-color), 0 -5px 20px var(--bg-color); + transition: transform 0.5s ease-in-out; } .timeline-deck .status .content.truncated:hover:after { - border-color: var(--link-color); + color: var(--link-color); + transform: translateX(-50%) translateY(-2px) scale(1.01); } .status .content p { margin-block: 0.75em; diff --git a/src/components/status.jsx b/src/components/status.jsx index a8fb9d6b..f0c90894 100644 --- a/src/components/status.jsx +++ b/src/components/status.jsx @@ -646,7 +646,7 @@ function Status({ } }, }); - const readMoreText = 'read more →'; + const readMoreText = 'Read more →'; return (
    Date: Sun, 18 Dec 2022 11:52:53 +0800 Subject: [PATCH 14/17] Replace deprecated methods --- src/pages/home.jsx | 6 +++--- src/pages/notifications.jsx | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pages/home.jsx b/src/pages/home.jsx index 06278693..1bcca842 100644 --- a/src/pages/home.jsx +++ b/src/pages/home.jsx @@ -16,13 +16,13 @@ function Home({ hidden }) { const [uiState, setUIState] = useState('default'); const [showMore, setShowMore] = useState(false); - const statusIterator = useRef( - masto.timelines.getHomeIterable({ + const homeIterator = useRef( + masto.timelines.iterateHome({ limit: LIMIT, }), ).current; async function fetchStatuses(firstLoad) { - const allStatuses = await statusIterator.next( + const allStatuses = await homeIterator.next( firstLoad ? { limit: LIMIT, diff --git a/src/pages/notifications.jsx b/src/pages/notifications.jsx index 6796aabd..2820e8f4 100644 --- a/src/pages/notifications.jsx +++ b/src/pages/notifications.jsx @@ -207,7 +207,7 @@ function Notifications() { const [onlyMentions, setOnlyMentions] = useState(false); const notificationsIterator = useRef( - masto.notifications.getIterator({ + masto.notifications.iterate({ limit: LIMIT, }), ).current; From 03b319a517a7913e76311cf6dfb08e3cb6139bb6 Mon Sep 17 00:00:00 2001 From: Lim Chee Aun Date: Sun, 18 Dec 2022 11:53:41 +0800 Subject: [PATCH 15/17] Make loading new posts less destructive --- src/pages/home.jsx | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/pages/home.jsx b/src/pages/home.jsx index 1bcca842..6abbb049 100644 --- a/src/pages/home.jsx +++ b/src/pages/home.jsx @@ -83,8 +83,16 @@ function Home({ hidden }) { if (diffMins > 1) { console.log('visible', { lastHidden, diffMins }); setTimeout(() => { - loadStatuses(true); - states.homeNew = []; + (async () => { + const newStatus = await masto.timelines.fetchHome({ + limit: 1, + }); + if (newStatus.length && newStatus[0].id !== states.home[0].id) { + states.homeNew = newStatus; + } + })(); + // loadStatuses(true); + // states.homeNew = []; }, 100); } } From 548af18bee7c4ef9838c5c7a998befc540a854e6 Mon Sep 17 00:00:00 2001 From: Lim Chee Aun Date: Sun, 18 Dec 2022 11:53:58 +0800 Subject: [PATCH 16/17] Only show "New posts" when more than 1 new post --- src/pages/home.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home.jsx b/src/pages/home.jsx index 6abbb049..c2c2cca8 100644 --- a/src/pages/home.jsx +++ b/src/pages/home.jsx @@ -141,7 +141,7 @@ function Home({ hidden }) {
    - {snapStates.homeNew.length > 0 && ( + {snapStates.homeNew.length > 1 && (