mirror of
https://github.com/cheeaun/phanpy.git
synced 2024-11-21 16:55:25 +03:00
Breaking: rewrote filters implementation
This commit is contained in:
parent
1cdc4ebbe8
commit
0bc1b598c3
13 changed files with 287 additions and 207 deletions
|
@ -1,9 +1,13 @@
|
|||
import './media-post.css';
|
||||
|
||||
import { memo } from 'preact/compat';
|
||||
import { useContext, useMemo } from 'preact/hooks';
|
||||
import { useSnapshot } from 'valtio';
|
||||
|
||||
import FilterContext from '../utils/filter-context';
|
||||
import { isFiltered } from '../utils/filters';
|
||||
import states, { statusKey } from '../utils/states';
|
||||
import store from '../utils/store';
|
||||
|
||||
import Media from './media';
|
||||
|
||||
|
@ -13,7 +17,7 @@ function MediaPost({
|
|||
status,
|
||||
instance,
|
||||
parent,
|
||||
allowFilters,
|
||||
// allowFilters,
|
||||
onMediaClick,
|
||||
}) {
|
||||
let sKey = statusKey(statusID, instance);
|
||||
|
@ -68,7 +72,7 @@ function MediaPost({
|
|||
// Non-API props
|
||||
_deleted,
|
||||
_pinned,
|
||||
_filtered,
|
||||
// _filtered,
|
||||
} = status;
|
||||
|
||||
if (!mediaAttachments?.length) {
|
||||
|
@ -83,6 +87,20 @@ function MediaPost({
|
|||
}
|
||||
};
|
||||
|
||||
const currentAccount = useMemo(() => {
|
||||
return store.session.get('currentAccount');
|
||||
}, []);
|
||||
const isSelf = useMemo(() => {
|
||||
return currentAccount && currentAccount === accountId;
|
||||
}, [accountId, currentAccount]);
|
||||
|
||||
const filterContext = useContext(FilterContext);
|
||||
const filterInfo = !isSelf && isFiltered(filtered, filterContext);
|
||||
|
||||
if (filterInfo?.action === 'hide') {
|
||||
return null;
|
||||
}
|
||||
|
||||
console.debug('RENDER Media post', id, status?.account.displayName);
|
||||
|
||||
// const readingExpandSpoilers = useMemo(() => {
|
||||
|
@ -95,6 +113,7 @@ function MediaPost({
|
|||
|
||||
return mediaAttachments.map((media, i) => {
|
||||
const mediaKey = `${sKey}-${media.id}`;
|
||||
const filterTitleStr = filterInfo?.titlesStr;
|
||||
return (
|
||||
<Parent
|
||||
onMouseEnter={debugHover}
|
||||
|
@ -102,10 +121,14 @@ function MediaPost({
|
|||
data-spoiler-text={
|
||||
spoilerText || (sensitive ? 'Sensitive media' : undefined)
|
||||
}
|
||||
data-filtered-text={_filtered ? 'Filtered' : undefined}
|
||||
data-filtered-text={
|
||||
filterInfo
|
||||
? `Filtered${filterTitleStr ? `: ${filterTitleStr}` : ''}`
|
||||
: undefined
|
||||
}
|
||||
class={`
|
||||
media-post
|
||||
${allowFilters && _filtered ? 'filtered' : ''}
|
||||
${filterInfo ? 'filtered' : ''}
|
||||
${hasSpoiler ? 'has-spoiler' : ''}
|
||||
`}
|
||||
>
|
||||
|
|
|
@ -13,6 +13,7 @@ import pThrottle from 'p-throttle';
|
|||
import { memo } from 'preact/compat';
|
||||
import {
|
||||
useCallback,
|
||||
useContext,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
|
@ -34,6 +35,8 @@ import Poll from '../components/poll';
|
|||
import { api } from '../utils/api';
|
||||
import emojifyText from '../utils/emojify-text';
|
||||
import enhanceContent from '../utils/enhance-content';
|
||||
import FilterContext from '../utils/filter-context';
|
||||
import { isFiltered } from '../utils/filters';
|
||||
import getTranslateTargetLanguage from '../utils/get-translate-target-language';
|
||||
import getHTMLText from '../utils/getHTMLText';
|
||||
import handleContentLinks from '../utils/handle-content-links';
|
||||
|
@ -90,7 +93,7 @@ function Status({
|
|||
enableTranslate,
|
||||
forceTranslate: _forceTranslate,
|
||||
previewMode,
|
||||
allowFilters,
|
||||
// allowFilters,
|
||||
onMediaClick,
|
||||
quoted,
|
||||
onStatusLinkClick = () => {},
|
||||
|
@ -166,9 +169,24 @@ function Status({
|
|||
// Non-API props
|
||||
_deleted,
|
||||
_pinned,
|
||||
_filtered,
|
||||
// _filtered,
|
||||
} = status;
|
||||
|
||||
const currentAccount = useMemo(() => {
|
||||
return store.session.get('currentAccount');
|
||||
}, []);
|
||||
const isSelf = useMemo(() => {
|
||||
return currentAccount && currentAccount === accountId;
|
||||
}, [accountId, currentAccount]);
|
||||
|
||||
const filterContext = useContext(FilterContext);
|
||||
const filterInfo =
|
||||
!isSelf && !readOnly && !previewMode && isFiltered(filtered, filterContext);
|
||||
|
||||
if (filterInfo?.action === 'hide') {
|
||||
return null;
|
||||
}
|
||||
|
||||
console.debug('RENDER Status', id, status?.account.displayName, quoted);
|
||||
|
||||
const debugHover = (e) => {
|
||||
|
@ -179,11 +197,11 @@ function Status({
|
|||
}
|
||||
};
|
||||
|
||||
if (allowFilters && size !== 'l' && _filtered) {
|
||||
if (/*allowFilters && */ size !== 'l' && filterInfo) {
|
||||
return (
|
||||
<FilteredStatus
|
||||
status={status}
|
||||
filterInfo={_filtered}
|
||||
filterInfo={filterInfo}
|
||||
instance={instance}
|
||||
containerProps={{
|
||||
onMouseEnter: debugHover,
|
||||
|
@ -195,13 +213,6 @@ function Status({
|
|||
const createdAtDate = new Date(createdAt);
|
||||
const editedAtDate = new Date(editedAt);
|
||||
|
||||
const currentAccount = useMemo(() => {
|
||||
return store.session.get('currentAccount');
|
||||
}, []);
|
||||
const isSelf = useMemo(() => {
|
||||
return currentAccount && currentAccount === accountId;
|
||||
}, [accountId, currentAccount]);
|
||||
|
||||
let inReplyToAccountRef = mentions?.find(
|
||||
(mention) => mention.id === inReplyToAccountId,
|
||||
);
|
||||
|
|
|
@ -4,6 +4,8 @@ import { InView } from 'react-intersection-observer';
|
|||
import { useDebouncedCallback } from 'use-debounce';
|
||||
import { useSnapshot } from 'valtio';
|
||||
|
||||
import FilterContext from '../utils/filter-context';
|
||||
import { isFiltered } from '../utils/filters';
|
||||
import states, { statusKey } from '../utils/states';
|
||||
import statusPeek from '../utils/status-peek';
|
||||
import { groupBoosts, groupContext } from '../utils/timeline-utils';
|
||||
|
@ -13,7 +15,6 @@ import useScroll from '../utils/useScroll';
|
|||
|
||||
import Icon from './icon';
|
||||
import Link from './link';
|
||||
import Media from './media';
|
||||
import MediaPost from './media-post';
|
||||
import NavMenu from './nav-menu';
|
||||
import Status from './status';
|
||||
|
@ -39,9 +40,10 @@ function Timeline({
|
|||
headerStart,
|
||||
headerEnd,
|
||||
timelineStart,
|
||||
allowFilters,
|
||||
// allowFilters,
|
||||
refresh,
|
||||
view,
|
||||
filterContext,
|
||||
}) {
|
||||
const snapStates = useSnapshot(states);
|
||||
const [items, setItems] = useState([]);
|
||||
|
@ -285,172 +287,182 @@ function Timeline({
|
|||
const hiddenUI = scrollDirection === 'end' && !nearReachStart;
|
||||
|
||||
return (
|
||||
<div
|
||||
id={`${id}-page`}
|
||||
class="deck-container"
|
||||
ref={(node) => {
|
||||
scrollableRef.current = node;
|
||||
jRef.current = node;
|
||||
kRef.current = node;
|
||||
oRef.current = node;
|
||||
}}
|
||||
tabIndex="-1"
|
||||
>
|
||||
<div class="timeline-deck deck">
|
||||
<header
|
||||
hidden={hiddenUI}
|
||||
onClick={(e) => {
|
||||
if (!e.target.closest('a, button')) {
|
||||
scrollableRef.current?.scrollTo({
|
||||
top: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
}
|
||||
}}
|
||||
onDblClick={(e) => {
|
||||
if (!e.target.closest('a, button')) {
|
||||
loadItems(true);
|
||||
}
|
||||
}}
|
||||
class={uiState === 'loading' ? 'loading' : ''}
|
||||
>
|
||||
<div class="header-grid">
|
||||
<div class="header-side">
|
||||
<NavMenu />
|
||||
{headerStart !== null && headerStart !== undefined ? (
|
||||
headerStart
|
||||
) : (
|
||||
<Link to="/" class="button plain home-button">
|
||||
<Icon icon="home" size="l" />
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
{title && (titleComponent ? titleComponent : <h1>{title}</h1>)}
|
||||
<div class="header-side">
|
||||
{/* <Loader hidden={uiState !== 'loading'} /> */}
|
||||
{!!headerEnd && headerEnd}
|
||||
</div>
|
||||
</div>
|
||||
{items.length > 0 &&
|
||||
uiState !== 'loading' &&
|
||||
!hiddenUI &&
|
||||
showNew && (
|
||||
<button
|
||||
class="updates-button shiny-pill"
|
||||
type="button"
|
||||
onClick={() => {
|
||||
loadItems(true);
|
||||
scrollableRef.current?.scrollTo({
|
||||
top: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Icon icon="arrow-up" /> New posts
|
||||
</button>
|
||||
)}
|
||||
</header>
|
||||
{!!timelineStart && (
|
||||
<div
|
||||
class={`timeline-start ${uiState === 'loading' ? 'loading' : ''}`}
|
||||
<FilterContext.Provider value={filterContext}>
|
||||
<div
|
||||
id={`${id}-page`}
|
||||
class="deck-container"
|
||||
ref={(node) => {
|
||||
scrollableRef.current = node;
|
||||
jRef.current = node;
|
||||
kRef.current = node;
|
||||
oRef.current = node;
|
||||
}}
|
||||
tabIndex="-1"
|
||||
>
|
||||
<div class="timeline-deck deck">
|
||||
<header
|
||||
hidden={hiddenUI}
|
||||
onClick={(e) => {
|
||||
if (!e.target.closest('a, button')) {
|
||||
scrollableRef.current?.scrollTo({
|
||||
top: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
}
|
||||
}}
|
||||
onDblClick={(e) => {
|
||||
if (!e.target.closest('a, button')) {
|
||||
loadItems(true);
|
||||
}
|
||||
}}
|
||||
class={uiState === 'loading' ? 'loading' : ''}
|
||||
>
|
||||
{timelineStart}
|
||||
</div>
|
||||
)}
|
||||
{!!items.length ? (
|
||||
<>
|
||||
<ul class={`timeline ${view ? `timeline-${view}` : ''}`}>
|
||||
{items.map((status) => (
|
||||
<TimelineItem
|
||||
status={status}
|
||||
instance={instance}
|
||||
useItemID={useItemID}
|
||||
allowFilters={allowFilters}
|
||||
key={status.id + status?._pinned}
|
||||
view={view}
|
||||
/>
|
||||
))}
|
||||
{showMore &&
|
||||
uiState === 'loading' &&
|
||||
(view === 'media' ? null : (
|
||||
<>
|
||||
<li
|
||||
style={{
|
||||
height: '20vh',
|
||||
}}
|
||||
>
|
||||
<Status skeleton />
|
||||
</li>
|
||||
<li
|
||||
style={{
|
||||
height: '25vh',
|
||||
}}
|
||||
>
|
||||
<Status skeleton />
|
||||
</li>
|
||||
</>
|
||||
))}
|
||||
</ul>
|
||||
{uiState === 'default' &&
|
||||
(showMore ? (
|
||||
<InView
|
||||
onChange={(inView) => {
|
||||
if (inView) {
|
||||
loadItems();
|
||||
}
|
||||
<div class="header-grid">
|
||||
<div class="header-side">
|
||||
<NavMenu />
|
||||
{headerStart !== null && headerStart !== undefined ? (
|
||||
headerStart
|
||||
) : (
|
||||
<Link to="/" class="button plain home-button">
|
||||
<Icon icon="home" size="l" />
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
{title && (titleComponent ? titleComponent : <h1>{title}</h1>)}
|
||||
<div class="header-side">
|
||||
{/* <Loader hidden={uiState !== 'loading'} /> */}
|
||||
{!!headerEnd && headerEnd}
|
||||
</div>
|
||||
</div>
|
||||
{items.length > 0 &&
|
||||
uiState !== 'loading' &&
|
||||
!hiddenUI &&
|
||||
showNew && (
|
||||
<button
|
||||
class="updates-button shiny-pill"
|
||||
type="button"
|
||||
onClick={() => {
|
||||
loadItems(true);
|
||||
scrollableRef.current?.scrollTo({
|
||||
top: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
}}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="plain block"
|
||||
onClick={() => loadItems()}
|
||||
style={{ marginBlockEnd: '6em' }}
|
||||
>
|
||||
Show more…
|
||||
</button>
|
||||
</InView>
|
||||
) : (
|
||||
<p class="ui-state insignificant">The end.</p>
|
||||
))}
|
||||
</>
|
||||
) : uiState === 'loading' ? (
|
||||
<ul class="timeline">
|
||||
{Array.from({ length: 5 }).map((_, i) =>
|
||||
view === 'media' ? (
|
||||
<div
|
||||
style={{
|
||||
height: '50vh',
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<li key={i}>
|
||||
<Status skeleton />
|
||||
</li>
|
||||
),
|
||||
)}
|
||||
</ul>
|
||||
) : (
|
||||
uiState !== 'error' && <p class="ui-state">{emptyText}</p>
|
||||
)}
|
||||
{uiState === 'error' && (
|
||||
<p class="ui-state">
|
||||
{errorText}
|
||||
<br />
|
||||
<br />
|
||||
<button
|
||||
class="button plain"
|
||||
onClick={() => loadItems(!items.length)}
|
||||
<Icon icon="arrow-up" /> New posts
|
||||
</button>
|
||||
)}
|
||||
</header>
|
||||
{!!timelineStart && (
|
||||
<div
|
||||
class={`timeline-start ${uiState === 'loading' ? 'loading' : ''}`}
|
||||
>
|
||||
Try again
|
||||
</button>
|
||||
</p>
|
||||
)}
|
||||
{timelineStart}
|
||||
</div>
|
||||
)}
|
||||
{!!items.length ? (
|
||||
<>
|
||||
<ul class={`timeline ${view ? `timeline-${view}` : ''}`}>
|
||||
{items.map((status) => (
|
||||
<TimelineItem
|
||||
status={status}
|
||||
instance={instance}
|
||||
useItemID={useItemID}
|
||||
// allowFilters={allowFilters}
|
||||
filterContext={filterContext}
|
||||
key={status.id + status?._pinned}
|
||||
view={view}
|
||||
/>
|
||||
))}
|
||||
{showMore &&
|
||||
uiState === 'loading' &&
|
||||
(view === 'media' ? null : (
|
||||
<>
|
||||
<li
|
||||
style={{
|
||||
height: '20vh',
|
||||
}}
|
||||
>
|
||||
<Status skeleton />
|
||||
</li>
|
||||
<li
|
||||
style={{
|
||||
height: '25vh',
|
||||
}}
|
||||
>
|
||||
<Status skeleton />
|
||||
</li>
|
||||
</>
|
||||
))}
|
||||
</ul>
|
||||
{uiState === 'default' &&
|
||||
(showMore ? (
|
||||
<InView
|
||||
onChange={(inView) => {
|
||||
if (inView) {
|
||||
loadItems();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="plain block"
|
||||
onClick={() => loadItems()}
|
||||
style={{ marginBlockEnd: '6em' }}
|
||||
>
|
||||
Show more…
|
||||
</button>
|
||||
</InView>
|
||||
) : (
|
||||
<p class="ui-state insignificant">The end.</p>
|
||||
))}
|
||||
</>
|
||||
) : uiState === 'loading' ? (
|
||||
<ul class="timeline">
|
||||
{Array.from({ length: 5 }).map((_, i) =>
|
||||
view === 'media' ? (
|
||||
<div
|
||||
style={{
|
||||
height: '50vh',
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<li key={i}>
|
||||
<Status skeleton />
|
||||
</li>
|
||||
),
|
||||
)}
|
||||
</ul>
|
||||
) : (
|
||||
uiState !== 'error' && <p class="ui-state">{emptyText}</p>
|
||||
)}
|
||||
{uiState === 'error' && (
|
||||
<p class="ui-state">
|
||||
{errorText}
|
||||
<br />
|
||||
<br />
|
||||
<button
|
||||
class="button plain"
|
||||
onClick={() => loadItems(!items.length)}
|
||||
>
|
||||
Try again
|
||||
</button>
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</FilterContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
function TimelineItem({ status, instance, useItemID, allowFilters, view }) {
|
||||
function TimelineItem({
|
||||
status,
|
||||
instance,
|
||||
useItemID,
|
||||
// allowFilters,
|
||||
filterContext,
|
||||
view,
|
||||
}) {
|
||||
const { id: statusID, reblog, items, type, _pinned } = status;
|
||||
const actualStatusID = reblog?.id || statusID;
|
||||
const url = instance
|
||||
|
@ -467,10 +479,18 @@ function TimelineItem({ status, instance, useItemID, allowFilters, view }) {
|
|||
if (isCarousel) {
|
||||
// Here, we don't hide filtered posts, but we sort them last
|
||||
items.sort((a, b) => {
|
||||
if (a._filtered && !b._filtered) {
|
||||
// if (a._filtered && !b._filtered) {
|
||||
// return 1;
|
||||
// }
|
||||
// if (!a._filtered && b._filtered) {
|
||||
// return -1;
|
||||
// }
|
||||
const aFiltered = isFiltered(a.filtered, filterContext);
|
||||
const bFiltered = isFiltered(b.filtered, filterContext);
|
||||
if (aFiltered && !bFiltered) {
|
||||
return 1;
|
||||
}
|
||||
if (!a._filtered && b._filtered) {
|
||||
if (!aFiltered && bFiltered) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -493,7 +513,7 @@ function TimelineItem({ status, instance, useItemID, allowFilters, view }) {
|
|||
instance={instance}
|
||||
size="s"
|
||||
contentTextWeight
|
||||
allowFilters={allowFilters}
|
||||
// allowFilters={allowFilters}
|
||||
/>
|
||||
) : (
|
||||
<Status
|
||||
|
@ -501,7 +521,7 @@ function TimelineItem({ status, instance, useItemID, allowFilters, view }) {
|
|||
instance={instance}
|
||||
size="s"
|
||||
contentTextWeight
|
||||
allowFilters={allowFilters}
|
||||
// allowFilters={allowFilters}
|
||||
/>
|
||||
)}
|
||||
</Link>
|
||||
|
@ -541,13 +561,13 @@ function TimelineItem({ status, instance, useItemID, allowFilters, view }) {
|
|||
<Status
|
||||
statusID={statusID}
|
||||
instance={instance}
|
||||
allowFilters={allowFilters}
|
||||
// allowFilters={allowFilters}
|
||||
/>
|
||||
) : (
|
||||
<Status
|
||||
status={item}
|
||||
instance={instance}
|
||||
allowFilters={allowFilters}
|
||||
// allowFilters={allowFilters}
|
||||
/>
|
||||
)}
|
||||
</Link>
|
||||
|
@ -566,7 +586,7 @@ function TimelineItem({ status, instance, useItemID, allowFilters, view }) {
|
|||
key={itemKey}
|
||||
statusID={statusID}
|
||||
instance={instance}
|
||||
allowFilters={allowFilters}
|
||||
// allowFilters={allowFilters}
|
||||
/>
|
||||
) : (
|
||||
<MediaPost
|
||||
|
@ -575,7 +595,7 @@ function TimelineItem({ status, instance, useItemID, allowFilters, view }) {
|
|||
key={itemKey}
|
||||
status={status}
|
||||
instance={instance}
|
||||
allowFilters={allowFilters}
|
||||
// allowFilters={allowFilters}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -587,13 +607,13 @@ function TimelineItem({ status, instance, useItemID, allowFilters, view }) {
|
|||
<Status
|
||||
statusID={statusID}
|
||||
instance={instance}
|
||||
allowFilters={allowFilters}
|
||||
// allowFilters={allowFilters}
|
||||
/>
|
||||
) : (
|
||||
<Status
|
||||
status={status}
|
||||
instance={instance}
|
||||
allowFilters={allowFilters}
|
||||
// allowFilters={allowFilters}
|
||||
/>
|
||||
)}
|
||||
</Link>
|
||||
|
|
|
@ -32,7 +32,7 @@ function Following({ title, path, id, ...props }) {
|
|||
console.log('First load', latestItem.current);
|
||||
}
|
||||
|
||||
value = filteredItems(value, 'home');
|
||||
// value = filteredItems(value, 'home');
|
||||
value.forEach((item) => {
|
||||
saveStatus(item, instance);
|
||||
});
|
||||
|
@ -115,7 +115,8 @@ function Following({ title, path, id, ...props }) {
|
|||
useItemID
|
||||
boostsCarousel={snapStates.settings.boostsCarousel}
|
||||
{...props}
|
||||
allowFilters
|
||||
// allowFilters
|
||||
filterContext="home"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ function Hashtags({ media: mediaView, columnMode, ...props }) {
|
|||
latestItem.current = value[0].id;
|
||||
}
|
||||
|
||||
value = filteredItems(value, 'public');
|
||||
// value = filteredItems(value, 'public');
|
||||
value.forEach((item) => {
|
||||
saveStatus(item, instance, {
|
||||
skipThreading: media, // If media view, no need to form threads
|
||||
|
@ -153,7 +153,8 @@ function Hashtags({ media: mediaView, columnMode, ...props }) {
|
|||
useItemID
|
||||
view={media ? 'media' : undefined}
|
||||
refresh={media}
|
||||
allowFilters
|
||||
// allowFilters
|
||||
filterContext="public"
|
||||
headerEnd={
|
||||
<Menu2
|
||||
portal
|
||||
|
|
|
@ -43,7 +43,7 @@ function List(props) {
|
|||
latestItem.current = value[0].id;
|
||||
}
|
||||
|
||||
value = filteredItems(value, 'home');
|
||||
// value = filteredItems(value, 'home');
|
||||
value.forEach((item) => {
|
||||
saveStatus(item, instance);
|
||||
});
|
||||
|
@ -102,7 +102,8 @@ function List(props) {
|
|||
checkForUpdates={checkForUpdates}
|
||||
useItemID
|
||||
boostsCarousel={snapStates.settings.boostsCarousel}
|
||||
allowFilters
|
||||
// allowFilters
|
||||
filterContext="home"
|
||||
// refresh={reloadCount}
|
||||
headerStart={
|
||||
<Link to="/l" class="button plain">
|
||||
|
|
|
@ -195,6 +195,7 @@ function Notifications({ columnMode }) {
|
|||
snapStates.notificationsShowNew &&
|
||||
uiState !== 'loading'
|
||||
) {
|
||||
setShowNew(false);
|
||||
loadNotifications(true);
|
||||
} else {
|
||||
setShowNew(snapStates.notificationsShowNew);
|
||||
|
|
|
@ -41,7 +41,7 @@ function Public({ local, columnMode, ...props }) {
|
|||
latestItem.current = value[0].id;
|
||||
}
|
||||
|
||||
value = filteredItems(value, 'public');
|
||||
// value = filteredItems(value, 'public');
|
||||
value.forEach((item) => {
|
||||
saveStatus(item, instance);
|
||||
});
|
||||
|
@ -91,7 +91,8 @@ function Public({ local, columnMode, ...props }) {
|
|||
useItemID
|
||||
headerStart={<></>}
|
||||
boostsCarousel={snapStates.settings.boostsCarousel}
|
||||
allowFilters
|
||||
// allowFilters
|
||||
filterContext="public"
|
||||
headerEnd={
|
||||
<Menu2
|
||||
portal
|
||||
|
|
|
@ -85,7 +85,7 @@ function Trending({ columnMode, ...props }) {
|
|||
latestItem.current = value[0].id;
|
||||
}
|
||||
|
||||
value = filteredItems(value, 'public'); // Might not work here
|
||||
// value = filteredItems(value, 'public'); // Might not work here
|
||||
value.forEach((item) => {
|
||||
saveStatus(item, instance);
|
||||
});
|
||||
|
@ -257,7 +257,8 @@ function Trending({ columnMode, ...props }) {
|
|||
useItemID
|
||||
headerStart={<></>}
|
||||
boostsCarousel={snapStates.settings.boostsCarousel}
|
||||
allowFilters
|
||||
// allowFilters
|
||||
filterContext="public"
|
||||
timelineStart={TimelineStart}
|
||||
headerEnd={
|
||||
<Menu2
|
||||
|
|
4
src/utils/filter-context.js
Normal file
4
src/utils/filter-context.js
Normal file
|
@ -0,0 +1,4 @@
|
|||
import { createContext } from 'preact';
|
||||
|
||||
const FilterContext = createContext();
|
||||
export default FilterContext;
|
|
@ -1,10 +1,8 @@
|
|||
import mem from './mem';
|
||||
import store from './store';
|
||||
|
||||
export function filteredItem(item, filterContext, currentAccountID) {
|
||||
const { filtered } = item;
|
||||
if (!filtered?.length) return true;
|
||||
const isSelf = currentAccountID && item.account?.id === currentAccountID;
|
||||
if (isSelf) return true;
|
||||
function _isFiltered(filtered, filterContext) {
|
||||
if (!filtered?.length) return false;
|
||||
const appliedFilters = filtered.filter((f) => {
|
||||
const { filter } = f;
|
||||
const hasContext = filter.context.includes(filterContext);
|
||||
|
@ -12,19 +10,35 @@ export function filteredItem(item, filterContext, currentAccountID) {
|
|||
if (!filter.expiresAt) return hasContext;
|
||||
return new Date(filter.expiresAt) > new Date();
|
||||
});
|
||||
if (!appliedFilters.length) return true;
|
||||
if (!appliedFilters.length) return false;
|
||||
const isHidden = appliedFilters.some((f) => f.filter.filterAction === 'hide');
|
||||
console.log({ isHidden, filtered, appliedFilters, item });
|
||||
if (isHidden) return false;
|
||||
if (isHidden)
|
||||
return {
|
||||
action: 'hide',
|
||||
};
|
||||
const isWarn = appliedFilters.some((f) => f.filter.filterAction === 'warn');
|
||||
if (isWarn) {
|
||||
const filterTitles = appliedFilters.map((f) => f.filter.title);
|
||||
item._filtered = {
|
||||
return {
|
||||
action: 'warn',
|
||||
titles: filterTitles,
|
||||
titlesStr: filterTitles.join(' • '),
|
||||
};
|
||||
}
|
||||
return isWarn;
|
||||
return false;
|
||||
}
|
||||
export const isFiltered = mem(_isFiltered);
|
||||
|
||||
export function filteredItem(item, filterContext, currentAccountID) {
|
||||
const { filtered } = item;
|
||||
if (!filtered?.length) return true;
|
||||
const isSelf = currentAccountID && item.account?.id === currentAccountID;
|
||||
if (isSelf) return true;
|
||||
const filterState = isFiltered(filtered, filterContext);
|
||||
if (!filterState) return true;
|
||||
if (filterState.action === 'hide') return false;
|
||||
// item._filtered = filterState;
|
||||
return true;
|
||||
}
|
||||
export function filteredItems(items, filterContext) {
|
||||
if (!items?.length) return [];
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import moize from 'moize';
|
||||
|
||||
window._moize = moize;
|
||||
|
||||
export default function mem(fn, opts = {}) {
|
||||
return moize(fn, { ...opts, maxSize: 100 });
|
||||
return moize(fn, { ...opts, maxSize: 100, isDeepEqual: true });
|
||||
}
|
||||
|
|
|
@ -168,7 +168,7 @@ export function saveStatus(status, instance, opts) {
|
|||
if (!override && oldStatus) return;
|
||||
const key = statusKey(status.id, instance);
|
||||
if (oldStatus?._pinned) status._pinned = oldStatus._pinned;
|
||||
if (oldStatus?._filtered) status._filtered = oldStatus._filtered;
|
||||
// if (oldStatus?._filtered) status._filtered = oldStatus._filtered;
|
||||
states.statuses[key] = status;
|
||||
if (status.reblog) {
|
||||
const key = statusKey(status.reblog.id, instance);
|
||||
|
|
Loading…
Reference in a new issue