From 522d55ebb81ac17de42350ec6e96a9b04ed659c1 Mon Sep 17 00:00:00 2001 From: Lim Chee Aun Date: Sat, 18 Feb 2023 20:48:24 +0800 Subject: [PATCH] New experiment: multi-column mode --- src/app.css | 80 ++++++++++++++++++++---- src/app.jsx | 6 +- src/components/shortcuts-settings.jsx | 29 +++++++-- src/pages/{hashtags.jsx => hashtag.jsx} | 3 +- src/pages/home.jsx | 83 +++++++++++++++++++------ src/pages/list.jsx | 4 +- src/pages/public.jsx | 6 +- src/pages/search.jsx | 4 +- src/utils/states.js | 14 +++-- 9 files changed, 176 insertions(+), 53 deletions(-) rename src/pages/{hashtags.jsx => hashtag.jsx} (96%) diff --git a/src/app.css b/src/app.css index 1eed3ff1..6278357d 100644 --- a/src/app.css +++ b/src/app.css @@ -1197,12 +1197,12 @@ meter.donut:is(.danger, .explode):after { width: 100%; flex-grow: 1; } -:is(#home-page, #welcome) ~ .deck-container { +:is(#home-page, #welcome, #columns) ~ .deck-container { z-index: 10; position: fixed; inset: 0; } -:is(#home-page, #welcome):has(~ .deck-container) { +:is(#home-page, #welcome, #columns):has(~ .deck-container) { display: block; position: absolute; user-select: none; @@ -1338,28 +1338,82 @@ ul.link-list li a .icon { display: flex; width: 100vw; overflow-y: hidden; - overflow-x: auto; + overflow-x: scroll; scroll-snap-type: x mandatory; scroll-behavior: smooth; - scrollbar-width: none; + /* scrollbar-width: none; */ overscroll-behavior: contain; + overscroll-behavior-x: contain; } -#columns::-webkit-scrollbar { +/* #columns::-webkit-scrollbar { display: none; -} +} */ #columns > * { overscroll-behavior: auto; scroll-snap-align: left; scroll-snap-stop: always; - position: static !important; - opacity: 1 !important; - content-visibility: auto !important; - pointer-events: auto !important; - user-select: auto !important; - /* background-color: var(--bg-color); */ - flex-basis: min(100vw, 480px); + overscroll-behavior: auto; + flex-basis: min(100vw, 360px); flex-shrink: 0; } +#columns .header-grid input { + pointer-events: none; +} +#columns + .header-grid + .header-side:first-of-type + :is(button, .button) + ~ :is(button, .button), +#columns .deck-container:not(:first-of-type) .header-grid .header-side > * { + display: none; +} +@media (min-width: 40em) { + #columns { + gap: 16px; + padding: 16px; + background-color: var(--bg-blur-color); + height: 100vh; + height: 100dvh; + justify-content: stretch; + align-items: stretch; + } + #columns > * { + padding: 0 16px; + border: var(--hairline-width) solid var(--outline-color); + border-radius: 16px; + box-shadow: 0 4px 16px var(--drop-shadow-color); + height: unset; + background-image: linear-gradient( + 160deg, + transparent 20%, + var(--bg-color), + transparent 75% + ); + } + #columns > *:focus-visible, + #columns > *:has(:focus-visible) { + box-shadow: 0 4px 16px var(--drop-shadow-color), + 0 4px 16px var(--drop-shadow-color); + border-color: var(--outline-hover-color); + } + #columns .timeline:not(.flat) > li:has(.status-link.is-active), + #columns + .timeline:not(.flat) + > li:not(:has(.status-carousel)):has(+ li .status-link.is-active), + #columns + .timeline:not(.flat) + > li:not(:has(.status-carousel)):has(.status-link.is-active) + + li { + transform: none; + } + #columns .timeline-deck > header { + margin: 0; + } + #columns li:has(.status-carousel) { + width: auto; + transform: none; + } +} /* OTHERS */ diff --git a/src/app.jsx b/src/app.jsx index cf7c414f..e6258275 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -33,7 +33,7 @@ import Bookmarks from './pages/bookmarks'; import Favourites from './pages/favourites'; import FollowedHashtags from './pages/followed-hashtags'; import Following from './pages/following'; -import Hashtags from './pages/hashtags'; +import Hashtag from './pages/hashtag'; import Home from './pages/home'; import HomeV1 from './pages/home-v1'; import List from './pages/list'; @@ -269,7 +269,7 @@ function App() { )} {isLoggedIn && } />} - } /> + } /> } /> } /> @@ -298,7 +298,7 @@ function App() { - + {!snapStates.settings.shortcutsColumnsMode && } {!!snapStates.showCompose && ( (index === 0 ? '/' : '/l/f'), icon: 'home', }, @@ -188,7 +188,24 @@ function ShortcutsSettings() { Specify a list of shortcuts that'll appear in the floating Shortcuts button.

- {snapStates.shortcuts.length > 0 ? ( +

+

+ + Experimental Multi-column mode + + +
+

+ {shortcuts.length > 0 ? (
    {shortcuts.map((shortcut, i) => { const key = i + Object.values(shortcut); diff --git a/src/pages/hashtags.jsx b/src/pages/hashtag.jsx similarity index 96% rename from src/pages/hashtags.jsx rename to src/pages/hashtag.jsx index 8ae7a5b9..c51ca326 100644 --- a/src/pages/hashtags.jsx +++ b/src/pages/hashtag.jsx @@ -7,8 +7,9 @@ import useTitle from '../utils/useTitle'; const LIMIT = 20; -function Hashtags() { +function Hashtags(props) { let { hashtag, ...params } = useParams(); + if (props.hashtag) hashtag = props.hashtag; const { masto, instance } = api({ instance: params.instance }); const title = instance ? `#${hashtag} on ${instance}` : `#${hashtag}`; useTitle(title, `/:instance?/t/:hashtag`); diff --git a/src/pages/home.jsx b/src/pages/home.jsx index 65982744..a6fcfe78 100644 --- a/src/pages/home.jsx +++ b/src/pages/home.jsx @@ -1,4 +1,5 @@ -import { useEffect } from 'preact/hooks'; +import { useEffect, useState } from 'preact/hooks'; +import { useHotkeys } from 'react-hotkeys-hook'; import { useSnapshot } from 'valtio'; import Icon from '../components/icon'; @@ -25,27 +26,69 @@ function Home() { })(); }, []); + const { shortcuts } = snapStates; + const { shortcutsColumnsMode } = snapStates.settings || {}; + const [shortcutsComponents, setShortcutsComponents] = useState([]); + useEffect(() => { + if (shortcutsColumnsMode) { + const componentsPromises = shortcuts.map((shortcut) => { + const { type, ...params } = shortcut; + // Uppercase type + return import(`./${type}`).then((module) => { + const { default: Component } = module; + return ; + }); + }); + Promise.all(componentsPromises) + .then((components) => { + setShortcutsComponents(components); + }) + .catch((err) => { + console.error(err); + }); + } + }, [shortcutsColumnsMode, shortcuts]); + + useHotkeys( + ['1', '2', '3', '4', '5', '6', '7', '8', '9'], + (e, handler) => { + try { + const index = parseInt(handler.keys[0], 10) - 1; + document.querySelectorAll('#columns > *')[index].focus(); + } catch (e) { + console.error(e); + } + }, + { + enabled: shortcutsColumnsMode, + }, + ); + return ( <> - { - e.stopPropagation(); - }} - > - - - } - /> + {shortcutsColumnsMode ? ( +
    {shortcutsComponents}
    + ) : ( + { + e.stopPropagation(); + }} + > + + + } + /> + )}