mirror of
https://github.com/cheeaun/phanpy.git
synced 2024-11-26 19:25:47 +03:00
More support for Pixelfed
This commit is contained in:
parent
afdfdb86da
commit
06c6360cae
5 changed files with 124 additions and 66 deletions
|
@ -1917,7 +1917,8 @@ body > .szh-menu-container {
|
||||||
/* two columns only */
|
/* two columns only */
|
||||||
grid-template-columns: repeat(2, 1fr);
|
grid-template-columns: repeat(2, 1fr);
|
||||||
}
|
}
|
||||||
.szh-menu .menu-horizontal:has(> .szh-menu__item:only-child) {
|
.szh-menu .menu-horizontal:has(> .szh-menu__item:only-child),
|
||||||
|
.szh-menu .menu-horizontal:has(> .szh-menu__submenu:only-child) {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
.szh-menu .menu-horizontal > .szh-menu__item:not(:only-child):first-child,
|
.szh-menu .menu-horizontal > .szh-menu__item:not(:only-child):first-child,
|
||||||
|
|
|
@ -12,6 +12,7 @@ import safeBoundingBoxPadding from '../utils/safe-bounding-box-padding';
|
||||||
import states from '../utils/states';
|
import states from '../utils/states';
|
||||||
import store from '../utils/store';
|
import store from '../utils/store';
|
||||||
import { getCurrentAccountID } from '../utils/store-utils';
|
import { getCurrentAccountID } from '../utils/store-utils';
|
||||||
|
import supports from '../utils/supports';
|
||||||
|
|
||||||
import Avatar from './avatar';
|
import Avatar from './avatar';
|
||||||
import Icon from './icon';
|
import Icon from './icon';
|
||||||
|
@ -83,8 +84,10 @@ function NavMenu(props) {
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const supportsLists = supports('@mastodon/lists');
|
||||||
const [lists, setLists] = useState([]);
|
const [lists, setLists] = useState([]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (!supportsLists) return;
|
||||||
if (menuState === 'open') {
|
if (menuState === 'open') {
|
||||||
getLists().then(setLists);
|
getLists().then(setLists);
|
||||||
}
|
}
|
||||||
|
@ -186,9 +189,11 @@ function NavMenu(props) {
|
||||||
<Icon icon="history2" size="l" />
|
<Icon icon="history2" size="l" />
|
||||||
<span>Catch-up</span>
|
<span>Catch-up</span>
|
||||||
</MenuLink>
|
</MenuLink>
|
||||||
<MenuLink to="/mentions">
|
{supports('@mastodon/mentions') && (
|
||||||
<Icon icon="at" size="l" /> <span>Mentions</span>
|
<MenuLink to="/mentions">
|
||||||
</MenuLink>
|
<Icon icon="at" size="l" /> <span>Mentions</span>
|
||||||
|
</MenuLink>
|
||||||
|
)}
|
||||||
<MenuLink to="/notifications">
|
<MenuLink to="/notifications">
|
||||||
<Icon icon="notification" size="l" /> <span>Notifications</span>
|
<Icon icon="notification" size="l" /> <span>Notifications</span>
|
||||||
{snapStates.notificationsShowNew && (
|
{snapStates.notificationsShowNew && (
|
||||||
|
@ -232,10 +237,12 @@ function NavMenu(props) {
|
||||||
)}
|
)}
|
||||||
</SubMenu2>
|
</SubMenu2>
|
||||||
) : (
|
) : (
|
||||||
<MenuLink to="/l">
|
supportsLists && (
|
||||||
<Icon icon="list" size="l" />
|
<MenuLink to="/l">
|
||||||
<span>Lists</span>
|
<Icon icon="list" size="l" />
|
||||||
</MenuLink>
|
<span>Lists</span>
|
||||||
|
</MenuLink>
|
||||||
|
)
|
||||||
)}
|
)}
|
||||||
<MenuLink to="/b">
|
<MenuLink to="/b">
|
||||||
<Icon icon="bookmark" size="l" /> <span>Bookmarks</span>
|
<Icon icon="bookmark" size="l" /> <span>Bookmarks</span>
|
||||||
|
@ -260,10 +267,12 @@ function NavMenu(props) {
|
||||||
<span>Followed Hashtags</span>
|
<span>Followed Hashtags</span>
|
||||||
</MenuLink>
|
</MenuLink>
|
||||||
<MenuDivider />
|
<MenuDivider />
|
||||||
<MenuLink to="/ft">
|
{supports('@mastodon/filters') && (
|
||||||
<Icon icon="filters" size="l" />
|
<MenuLink to="/ft">
|
||||||
Filters
|
<Icon icon="filters" size="l" />
|
||||||
</MenuLink>
|
Filters
|
||||||
|
</MenuLink>
|
||||||
|
)}
|
||||||
<MenuItem
|
<MenuItem
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
states.showGenericAccounts = {
|
states.showGenericAccounts = {
|
||||||
|
|
|
@ -55,6 +55,7 @@ import states, { getStatus, saveStatus, statusKey } from '../utils/states';
|
||||||
import statusPeek from '../utils/status-peek';
|
import statusPeek from '../utils/status-peek';
|
||||||
import store from '../utils/store';
|
import store from '../utils/store';
|
||||||
import { getCurrentAccountID } from '../utils/store-utils';
|
import { getCurrentAccountID } from '../utils/store-utils';
|
||||||
|
import supports from '../utils/supports';
|
||||||
import unfurlMastodonLink from '../utils/unfurl-link';
|
import unfurlMastodonLink from '../utils/unfurl-link';
|
||||||
import useHotkeys from '../utils/useHotkeys';
|
import useHotkeys from '../utils/useHotkeys';
|
||||||
import useTruncated from '../utils/useTruncated';
|
import useTruncated from '../utils/useTruncated';
|
||||||
|
@ -149,6 +150,12 @@ const PostContent = memo(
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const SIZE_CLASS = {
|
||||||
|
s: 'small',
|
||||||
|
m: 'medium',
|
||||||
|
l: 'large',
|
||||||
|
};
|
||||||
|
|
||||||
function Status({
|
function Status({
|
||||||
statusID,
|
statusID,
|
||||||
status,
|
status,
|
||||||
|
@ -174,7 +181,11 @@ function Status({
|
||||||
}) {
|
}) {
|
||||||
if (skeleton) {
|
if (skeleton) {
|
||||||
return (
|
return (
|
||||||
<div class={`status skeleton ${mediaFirst ? 'status-media-first' : ''}`}>
|
<div
|
||||||
|
class={`status skeleton ${
|
||||||
|
mediaFirst ? 'status-media-first small' : ''
|
||||||
|
}`}
|
||||||
|
>
|
||||||
{!mediaFirst && <Avatar size="xxl" />}
|
{!mediaFirst && <Avatar size="xxl" />}
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="meta">
|
<div class="meta">
|
||||||
|
@ -640,6 +651,7 @@ function Status({
|
||||||
};
|
};
|
||||||
|
|
||||||
const bookmarkStatus = async () => {
|
const bookmarkStatus = async () => {
|
||||||
|
if (!supports('@mastodon/post-bookmark')) return;
|
||||||
if (!sameInstance || !authenticated) {
|
if (!sameInstance || !authenticated) {
|
||||||
alert(unauthInteractionErrorMessage);
|
alert(unauthInteractionErrorMessage);
|
||||||
return false;
|
return false;
|
||||||
|
@ -827,13 +839,15 @@ function Status({
|
||||||
: 'Like'}
|
: 'Like'}
|
||||||
</span>
|
</span>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem
|
{supports('@mastodon/post-bookmark') && (
|
||||||
onClick={bookmarkStatusNotify}
|
<MenuItem
|
||||||
className={`menu-bookmark ${bookmarked ? 'checked' : ''}`}
|
onClick={bookmarkStatusNotify}
|
||||||
>
|
className={`menu-bookmark ${bookmarked ? 'checked' : ''}`}
|
||||||
<Icon icon="bookmark" />
|
>
|
||||||
<span>{bookmarked ? 'Unbookmark' : 'Bookmark'}</span>
|
<Icon icon="bookmark" />
|
||||||
</MenuItem>
|
<span>{bookmarked ? 'Unbookmark' : 'Bookmark'}</span>
|
||||||
|
</MenuItem>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
@ -1077,16 +1091,18 @@ function Status({
|
||||||
)}
|
)}
|
||||||
{isSelf && (
|
{isSelf && (
|
||||||
<div class="menu-horizontal">
|
<div class="menu-horizontal">
|
||||||
<MenuItem
|
{supports('@mastodon/post-edit') && (
|
||||||
onClick={() => {
|
<MenuItem
|
||||||
states.showCompose = {
|
onClick={() => {
|
||||||
editStatus: status,
|
states.showCompose = {
|
||||||
};
|
editStatus: status,
|
||||||
}}
|
};
|
||||||
>
|
}}
|
||||||
<Icon icon="pencil" />
|
>
|
||||||
<span>Edit</span>
|
<Icon icon="pencil" />
|
||||||
</MenuItem>
|
<span>Edit</span>
|
||||||
|
</MenuItem>
|
||||||
|
)}
|
||||||
{isSizeLarge && (
|
{isSizeLarge && (
|
||||||
<MenuConfirm
|
<MenuConfirm
|
||||||
subMenu
|
subMenu
|
||||||
|
@ -1395,11 +1411,7 @@ function Status({
|
||||||
? 'status-reply-to'
|
? 'status-reply-to'
|
||||||
: ''
|
: ''
|
||||||
} visibility-${visibility} ${_pinned ? 'status-pinned' : ''} ${
|
} visibility-${visibility} ${_pinned ? 'status-pinned' : ''} ${
|
||||||
{
|
SIZE_CLASS[size]
|
||||||
s: 'small',
|
|
||||||
m: 'medium',
|
|
||||||
l: 'large',
|
|
||||||
}[size]
|
|
||||||
} ${_deleted ? 'status-deleted' : ''} ${quoted ? 'status-card' : ''} ${
|
} ${_deleted ? 'status-deleted' : ''} ${quoted ? 'status-card' : ''} ${
|
||||||
isContextMenuOpen ? 'status-menu-open' : ''
|
isContextMenuOpen ? 'status-menu-open' : ''
|
||||||
} ${mediaFirst && hasMediaAttachments ? 'status-media-first' : ''}`}
|
} ${mediaFirst && hasMediaAttachments ? 'status-media-first' : ''}`}
|
||||||
|
@ -2160,16 +2172,18 @@ function Status({
|
||||||
onClick={favouriteStatus}
|
onClick={favouriteStatus}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="action">
|
{supports('@mastodon/post-bookmark') && (
|
||||||
<StatusButton
|
<div class="action">
|
||||||
checked={bookmarked}
|
<StatusButton
|
||||||
title={['Bookmark', 'Unbookmark']}
|
checked={bookmarked}
|
||||||
alt={['Bookmark', 'Bookmarked']}
|
title={['Bookmark', 'Unbookmark']}
|
||||||
class="bookmark-button"
|
alt={['Bookmark', 'Bookmarked']}
|
||||||
icon="bookmark"
|
class="bookmark-button"
|
||||||
onClick={bookmarkStatus}
|
icon="bookmark"
|
||||||
/>
|
onClick={bookmarkStatus}
|
||||||
</div>
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<Menu2
|
<Menu2
|
||||||
portal={{
|
portal={{
|
||||||
target:
|
target:
|
||||||
|
|
|
@ -19,6 +19,7 @@ import pmem from '../utils/pmem';
|
||||||
import shortenNumber from '../utils/shorten-number';
|
import shortenNumber from '../utils/shorten-number';
|
||||||
import states from '../utils/states';
|
import states from '../utils/states';
|
||||||
import { saveStatus } from '../utils/states';
|
import { saveStatus } from '../utils/states';
|
||||||
|
import supports from '../utils/supports';
|
||||||
import useTitle from '../utils/useTitle';
|
import useTitle from '../utils/useTitle';
|
||||||
|
|
||||||
const LIMIT = 20;
|
const LIMIT = 20;
|
||||||
|
@ -33,6 +34,17 @@ const fetchLinks = pmem(
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
function fetchTrends(masto) {
|
||||||
|
if (supports('@pixelfed/trending')) {
|
||||||
|
return masto.pixelfed.v2.discover.posts.trending.list({
|
||||||
|
range: 'daily',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return masto.v1.trends.statuses.list({
|
||||||
|
limit: LIMIT,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function Trending({ columnMode, ...props }) {
|
function Trending({ columnMode, ...props }) {
|
||||||
const snapStates = useSnapshot(states);
|
const snapStates = useSnapshot(states);
|
||||||
const params = columnMode ? {} : useParams();
|
const params = columnMode ? {} : useParams();
|
||||||
|
@ -48,36 +60,39 @@ function Trending({ columnMode, ...props }) {
|
||||||
const [hashtags, setHashtags] = useState([]);
|
const [hashtags, setHashtags] = useState([]);
|
||||||
const [links, setLinks] = useState([]);
|
const [links, setLinks] = useState([]);
|
||||||
const trendIterator = useRef();
|
const trendIterator = useRef();
|
||||||
|
|
||||||
async function fetchTrend(firstLoad) {
|
async function fetchTrend(firstLoad) {
|
||||||
if (firstLoad || !trendIterator.current) {
|
if (firstLoad || !trendIterator.current) {
|
||||||
trendIterator.current = masto.v1.trends.statuses.list({
|
trendIterator.current = fetchTrends(masto);
|
||||||
limit: LIMIT,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Get hashtags
|
// Get hashtags
|
||||||
try {
|
if (supports('@mastodon/trending-hashtags')) {
|
||||||
const iterator = masto.v1.trends.tags.list();
|
try {
|
||||||
const { value: tags } = await iterator.next();
|
const iterator = masto.v1.trends.tags.list();
|
||||||
console.log('tags', tags);
|
const { value: tags } = await iterator.next();
|
||||||
if (tags?.length) {
|
console.log('tags', tags);
|
||||||
setHashtags(tags);
|
if (tags?.length) {
|
||||||
|
setHashtags(tags);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get links
|
// Get links
|
||||||
try {
|
if (supports('@mastodon/trending-links')) {
|
||||||
const { value } = await fetchLinks(masto, instance);
|
try {
|
||||||
// 4 types available: link, photo, video, rich
|
const { value } = await fetchLinks(masto, instance);
|
||||||
// Only want links for now
|
// 4 types available: link, photo, video, rich
|
||||||
const links = value?.filter?.((link) => link.type === 'link');
|
// Only want links for now
|
||||||
console.log('links', links);
|
const links = value?.filter?.((link) => link.type === 'link');
|
||||||
if (links?.length) {
|
console.log('links', links);
|
||||||
setLinks(links);
|
if (links?.length) {
|
||||||
|
setLinks(links);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const results = await trendIterator.current.next();
|
const results = await trendIterator.current.next();
|
||||||
|
|
|
@ -4,6 +4,20 @@ import features from '../data/features.json';
|
||||||
|
|
||||||
import { getCurrentInstance } from './store-utils';
|
import { getCurrentInstance } from './store-utils';
|
||||||
|
|
||||||
|
// Non-semver(?) UA string detection
|
||||||
|
// Can't put this inside features.json due to regex
|
||||||
|
const containPixelfed = /pixelfed/i;
|
||||||
|
const notContainPixelfed = /^(?!.*pixelfed).*$/i;
|
||||||
|
const platformFeatures = {
|
||||||
|
'@mastodon/lists': notContainPixelfed,
|
||||||
|
'@mastodon/filters': notContainPixelfed,
|
||||||
|
'@mastodon/mentions': notContainPixelfed,
|
||||||
|
'@mastodon/trending-hashtags': notContainPixelfed,
|
||||||
|
'@mastodon/trending-links': notContainPixelfed,
|
||||||
|
'@mastodon/post-bookmark': notContainPixelfed,
|
||||||
|
'@mastodon/post-edit': notContainPixelfed,
|
||||||
|
'@pixelfed/trending': containPixelfed,
|
||||||
|
};
|
||||||
const supportsCache = {};
|
const supportsCache = {};
|
||||||
|
|
||||||
function supports(feature) {
|
function supports(feature) {
|
||||||
|
@ -11,6 +25,11 @@ function supports(feature) {
|
||||||
const { version, domain } = getCurrentInstance();
|
const { version, domain } = getCurrentInstance();
|
||||||
const key = `${domain}-${feature}`;
|
const key = `${domain}-${feature}`;
|
||||||
if (supportsCache[key]) return supportsCache[key];
|
if (supportsCache[key]) return supportsCache[key];
|
||||||
|
|
||||||
|
if (platformFeatures[feature]) {
|
||||||
|
return (supportsCache[key] = platformFeatures[feature].test(version));
|
||||||
|
}
|
||||||
|
|
||||||
const range = features[feature];
|
const range = features[feature];
|
||||||
if (!range) return false;
|
if (!range) return false;
|
||||||
return (supportsCache[key] = satisfies(version, range, {
|
return (supportsCache[key] = satisfies(version, range, {
|
||||||
|
|
Loading…
Reference in a new issue