Add 'Full' view for status pages

This commit is contained in:
Lim Chee Aun 2023-04-17 00:14:09 +08:00
parent 39ec0d29e2
commit 9a04cb6ba3
4 changed files with 82 additions and 20 deletions

View file

@ -826,6 +826,29 @@ a[href^='http'][rel*='nofollow']:visited:not(:has(div)) {
.deck-backdrop .deck .status { .deck-backdrop .deck .status {
max-width: var(--main-width); max-width: var(--main-width);
} }
.deck-backdrop .deck.deck-view-full .menu-switch-view {
display: none;
}
@media (min-width: 40em) {
.deck-backdrop .deck.deck-view-full .menu-switch-view {
display: flex;
}
.deck-backdrop .deck.deck-view-full {
min-width: 100%;
background-image: radial-gradient(
circle,
transparent 30em,
var(--bg-faded-color)
);
}
.deck-backdrop .deck.deck-view-full > * {
max-width: calc(var(--main-width) + 32px);
margin: 0 auto;
}
.deck-backdrop .deck.deck-view-full .status {
max-width: 100%;
}
}
.deck-close { .deck-close {
color: var(--text-insignificant-color) !important; color: var(--text-insignificant-color) !important;
@ -1096,7 +1119,7 @@ body:has(.media-modal-container + .status-deck) .media-post-link {
width: 100%; width: 100%;
flex-grow: 0; flex-grow: 0;
} }
.deck-backdrop .media-modal-container + .status-deck { .deck-backdrop .media-modal-container + .status-deck:not(.deck-view-full) {
/* display: block; */ /* display: block; */
/* width: 350px; */ /* width: 350px; */
min-width: 350px; min-width: 350px;

View file

@ -77,6 +77,8 @@ const ICONS = {
filter: 'mingcute:filter-2-line', filter: 'mingcute:filter-2-line',
chart: 'mingcute:chart-line-line', chart: 'mingcute:chart-line-line',
react: 'mingcute:react-line', react: 'mingcute:react-line',
layout4: 'mingcute:layout-4-line',
layout5: 'mingcute:layout-5-line',
}; };
const modules = import.meta.glob('/node_modules/@iconify-icons/mingcute/*.js'); const modules = import.meta.glob('/node_modules/@iconify-icons/mingcute/*.js');

View file

@ -1037,7 +1037,7 @@ function Status({
onClick={ onClick={
onMediaClick onMediaClick
? (e) => { ? (e) => {
onMediaClick(e, i, media); onMediaClick(e, i, media, status);
} }
: undefined : undefined
} }

View file

@ -3,7 +3,13 @@ import './status.css';
import { Menu, MenuDivider, MenuHeader, MenuItem } from '@szhsin/react-menu'; import { Menu, MenuDivider, MenuHeader, MenuItem } from '@szhsin/react-menu';
import debounce from 'just-debounce-it'; import debounce from 'just-debounce-it';
import pRetry from 'p-retry'; import pRetry from 'p-retry';
import { useEffect, useMemo, useRef, useState } from 'preact/hooks'; import {
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from 'preact/hooks';
import { useHotkeys } from 'react-hotkeys-hook'; import { useHotkeys } from 'react-hotkeys-hook';
import { InView } from 'react-intersection-observer'; import { InView } from 'react-intersection-observer';
import { matchPath, useParams, useSearchParams } from 'react-router-dom'; import { matchPath, useParams, useSearchParams } from 'react-router-dom';
@ -129,6 +135,7 @@ function StatusThread({ closeLink = '/' }) {
const [searchParams, setSearchParams] = useSearchParams(); const [searchParams, setSearchParams] = useSearchParams();
const mediaParam = searchParams.get('media'); const mediaParam = searchParams.get('media');
const showMedia = parseInt(mediaParam, 10) > 0; const showMedia = parseInt(mediaParam, 10) > 0;
const [viewMode, setViewMode] = useState(searchParams.get('view'));
const { masto, instance } = api({ instance: params.instance }); const { masto, instance } = api({ instance: params.instance });
const { const {
masto: currentMasto, masto: currentMasto,
@ -545,13 +552,24 @@ function StatusThread({ closeLink = '/' }) {
const initialPageState = useRef(showMedia ? 'media+status' : 'status'); const initialPageState = useRef(showMedia ? 'media+status' : 'status');
const handleMediaClick = useCallback((e, i, media, status) => {
e.preventDefault();
e.stopPropagation();
setSearchParams({
media: i + 1,
mediaStatusID: status.id,
});
}, []);
return ( return (
<div <div
tabIndex="-1" tabIndex="-1"
ref={scrollableRef} ref={scrollableRef}
class={`status-deck deck contained ${ class={`status-deck deck contained ${
statuses.length > 1 ? 'padded-bottom' : '' statuses.length > 1 ? 'padded-bottom' : ''
} ${initialPageState.current === 'status' ? 'slide-in' : ''}`} } ${initialPageState.current === 'status' ? 'slide-in' : ''} ${
viewMode ? `deck-view-${viewMode}` : ''
}`}
> >
<header <header
class={`${heroInView ? 'inview' : ''} ${ class={`${heroInView ? 'inview' : ''} ${
@ -651,6 +669,30 @@ function StatusThread({ closeLink = '/' }) {
<Icon icon="refresh" /> <Icon icon="refresh" />
<span>Refresh</span> <span>Refresh</span>
</MenuItem> </MenuItem>
<MenuItem
className="menu-switch-view"
onClick={() => {
setViewMode(viewMode === 'full' ? null : 'full');
if (viewMode === 'full') {
searchParams.delete('view');
} else {
searchParams.set('view', 'full');
}
setSearchParams(searchParams);
}}
>
<Icon
icon={
{
'': 'layout5',
full: 'layout4',
}[viewMode || '']
}
/>
<span>
Switch to {viewMode === 'full' ? 'Side Peek' : 'Full'} view
</span>
</MenuItem>
<MenuItem <MenuItem
onClick={() => { onClick={() => {
// Click all buttons with class .spoiler but not .spoiling // Click all buttons with class .spoiler but not .spoiling
@ -802,14 +844,7 @@ function StatusThread({ closeLink = '/' }) {
withinContext withinContext
size={thread || ancestor ? 'm' : 's'} size={thread || ancestor ? 'm' : 's'}
enableTranslate enableTranslate
onMediaClick={(e, i) => { onMediaClick={handleMediaClick}
e.preventDefault();
e.stopPropagation();
setSearchParams({
media: i + 1,
mediaStatusID: statusID,
});
}}
/> />
{ancestor && isThread && repliesCount > 1 && ( {ancestor && isThread && repliesCount > 1 && (
<div class="replies-link"> <div class="replies-link">
@ -962,6 +997,15 @@ function SubComments({
(!hasParentThread || replies.length === 1) && (isBrief || !hasManyStatuses); (!hasParentThread || replies.length === 1) && (isBrief || !hasManyStatuses);
const openBefore = cachedRepliesToggle[replies[0].id]; const openBefore = cachedRepliesToggle[replies[0].id];
const handleMediaClick = useCallback((e, i, media, status) => {
e.preventDefault();
e.stopPropagation();
setSearchParams({
media: i + 1,
mediaStatusID: status.id,
});
}, []);
return ( return (
<details <details
class="replies" class="replies"
@ -1021,14 +1065,7 @@ function SubComments({
withinContext withinContext
size="s" size="s"
enableTranslate enableTranslate
onMediaClick={(e, i) => { onMediaClick={handleMediaClick}
e.preventDefault();
e.stopPropagation();
setSearchParams({
media: i + 1,
mediaStatusID: r.id,
});
}}
/> />
{!r.replies?.length && r.repliesCount > 0 && ( {!r.replies?.length && r.repliesCount > 0 && (
<div class="replies-link"> <div class="replies-link">