diff --git a/src/app.css b/src/app.css index a9e6e60..d64ce87 100644 --- a/src/app.css +++ b/src/app.css @@ -291,11 +291,23 @@ a.hashtag { .box { width: 40em; max-width: 100vw; - text-align: center; padding: 16px; background-color: var(--bg-color); border-radius: 8px; border: 1px solid var(--divider-color); + overflow: auto; + max-height: 90vh; + position: relative; +} +.box > :is(h1, h2, h3):first-of-type { + margin-top: 0; +} +.box .close-button { + position: sticky; + top: 0; + float: right; + margin: -16px -8px 0 0; + transform: translate(0, -8px); } .box-shadow { diff --git a/src/components/status.css b/src/components/status.css index f529b68..2b10cc3 100644 --- a/src/components/status.css +++ b/src/components/status.css @@ -91,7 +91,7 @@ color: var(--reply-to-color); vertical-align: middle; } -.status > .container > .meta .time { +.status > .container > .meta :is(.time, .edited) { color: inherit; text-align: end; opacity: 0.5; @@ -369,6 +369,32 @@ a.card:hover { margin: 8px 0; } +/* EXTRA META */ + +.status .extra-meta { + padding-top: 8px; + color: var(--text-insignificant-color); +} +.status .extra-meta * { + vertical-align: middle; +} +.status .extra-meta a { + color: inherit; + text-decoration: none; +} +.status .extra-meta a:hover { + text-decoration: underline; +} +.status .extra-meta .edited:hover { + cursor: pointer; + color: var(--text-color); +} +.status.large .extra-meta { + padding-top: 0; + margin-left: calc(-50px - 16px); + background-color: var(--bg-color); +} + /* ACTIONS */ .status .actions { @@ -451,3 +477,21 @@ a.card:hover { vertical-align: middle; object-fit: contain; } + +/* EDIT HISTORY */ + +#edit-history { + min-height: 50vh; + min-height: 50dvh; +} + +#edit-history :is(ol, ol li){ + list-style: none; + margin: 0; + padding: 0; +} + +#edit-history .history-item .status { + border: 1px solid var(--outline-color); + border-radius: 8px; +} diff --git a/src/components/status.jsx b/src/components/status.jsx index 4862f8c..0f81b2b 100644 --- a/src/components/status.jsx +++ b/src/components/status.jsx @@ -6,6 +6,7 @@ import { useEffect, useRef, useState } from 'preact/hooks'; import { InView } from 'react-intersection-observer'; import { useSnapshot } from 'valtio'; +import Loader from '../components/loader'; import Modal from '../components/modal'; import NameText from '../components/name-text'; import enhanceContent from '../utils/enhance-content'; @@ -375,12 +376,86 @@ function Poll({ poll }) { ); } +function EditedAtModal({ statusID, onClose = () => {} }) { + const [uiState, setUIState] = useState('default'); + const [editHistory, setEditHistory] = useState([]); + + useEffect(() => { + setUIState('loading'); + (async () => { + try { + const editHistory = await masto.statuses.fetchHistory(statusID); + console.log(editHistory); + setEditHistory(editHistory); + setUIState('default'); + } catch (e) { + console.error(e); + setUIState('error'); + } + })(); + }, []); + + const currentYear = new Date().getFullYear(); + + return ( +
+ +

Edit History

+ {uiState === 'error' &&

Failed to load history

} + {uiState === 'loading' && ( +

+ Loading… +

+ )} + {editHistory.length > 0 && ( +
    + {editHistory.map((status) => { + const { createdAt } = status; + const createdAtDate = new Date(createdAt); + return ( +
  1. +

    + +

    + +
  2. + ); + })} +
+ )} +
+ ); +} + function fetchAccount(id) { return masto.accounts.fetch(id); } const memFetchAccount = mem(fetchAccount); -function Status({ statusID, status, withinContext, size = 'm', skeleton }) { +function Status({ + statusID, + status, + withinContext, + size = 'm', + skeleton, + editStatus, +}) { if (skeleton) { return (
@@ -443,8 +518,9 @@ function Status({ statusID, status, withinContext, size = 'm', skeleton }) { } = status; const createdAtDate = new Date(createdAt); + const editedAtDate = new Date(editedAt); - let inReplyToAccountRef = mentions.find( + let inReplyToAccountRef = mentions?.find( (mention) => mention.id === inReplyToAccountId, ); if (!inReplyToAccountRef && inReplyToAccountId === id) { @@ -498,8 +574,10 @@ function Status({ statusID, status, withinContext, size = 'm', skeleton }) { } const [actionsUIState, setActionsUIState] = useState(null); // boost-loading, favourite-loading, bookmark-loading + const [showEdited, setShowEdited] = useState(false); const carouselRef = useRef(null); + const currentYear = new Date().getFullYear(); return (
)} {' '} - - {' '} - - {createdAtDate.toLocaleString()} - - + {size !== 'l' && !editStatus && ( + + {' '} + + {createdAtDate.toLocaleString()} + + + )}
{size === 'l' && ( -
- - {/* TODO: if visibility = private, only can reblog own statuses */} - {visibility !== 'direct' && ( +
+
+ {/* TODO: if visibility = private, only can reblog own statuses */} + {visibility !== 'direct' && ( + + )} + - )} - - -
+ }} + > + + +
+ )}
{showMediaModal !== false && ( @@ -908,6 +1036,22 @@ function Status({ statusID, status, withinContext, size = 'm', skeleton }) { )} )} + {!!showEdited && ( + { + if (e.target === e.currentTarget) { + setShowEdited(false); + } + }} + > + { + setShowEdited(false); + }} + /> + + )} ); } diff --git a/src/pages/login.jsx b/src/pages/login.jsx index 5916ed7..ef703c2 100644 --- a/src/pages/login.jsx +++ b/src/pages/login.jsx @@ -53,7 +53,7 @@ export default () => { }; return ( -
+

Log in