Remove individual entries
This commit is contained in:
parent
1a7b92c4fa
commit
ea686474fc
6 changed files with 92 additions and 166 deletions
|
@ -60,6 +60,7 @@ type Props = {
|
|||
droppableProvided?: any,
|
||||
unavailableUris?: Array<string>,
|
||||
showMemberBadge?: boolean,
|
||||
inHistory?: boolean,
|
||||
};
|
||||
|
||||
export default function ClaimList(props: Props) {
|
||||
|
@ -100,6 +101,7 @@ export default function ClaimList(props: Props) {
|
|||
droppableProvided,
|
||||
unavailableUris,
|
||||
showMemberBadge,
|
||||
inHistory,
|
||||
} = props;
|
||||
|
||||
const [currentSort, setCurrentSort] = usePersistedState(persistedStorageKey, SORT_NEW);
|
||||
|
@ -202,6 +204,7 @@ export default function ClaimList(props: Props) {
|
|||
dragHandleProps={draggableProvided && draggableProvided.dragHandleProps}
|
||||
unavailableUris={unavailableUris}
|
||||
showMemberBadge={showMemberBadge}
|
||||
inHistory={inHistory}
|
||||
/>
|
||||
);
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ import { ENABLE_NO_SOURCE_CLAIMS } from 'config';
|
|||
import CollectionEditButtons from 'component/collectionEditButtons';
|
||||
import * as ICONS from 'constants/icons';
|
||||
import { useIsMobile } from 'effects/use-screensize';
|
||||
import usePersistedState from 'effects/use-persisted-state';
|
||||
|
||||
const AbandonedChannelPreview = lazyImport(() =>
|
||||
import('component/abandonedChannelPreview' /* webpackChunkName: "abandonedChannelPreview" */)
|
||||
|
@ -96,6 +97,7 @@ type Props = {
|
|||
dragHandleProps?: any,
|
||||
unavailableUris?: Array<string>,
|
||||
showMemberBadge?: boolean,
|
||||
inHistory?: boolean,
|
||||
};
|
||||
|
||||
const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
||||
|
@ -161,6 +163,7 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
|||
dragHandleProps,
|
||||
unavailableUris,
|
||||
showMemberBadge,
|
||||
inHistory,
|
||||
} = props;
|
||||
|
||||
const isMobile = useIsMobile();
|
||||
|
@ -211,6 +214,7 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
|||
? claim.permanent_url || claim.canonical_url
|
||||
: undefined;
|
||||
const repostedContentUri = claim && (claim.reposted_claim ? claim.reposted_claim.permanent_url : claim.permanent_url);
|
||||
const [watchHistory, setHistory] = usePersistedState('watch-history', []);
|
||||
|
||||
// Get channel title ( use name as fallback )
|
||||
let channelTitle = null;
|
||||
|
@ -281,6 +285,7 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
|||
|
||||
function handleOnClick(e) {
|
||||
if (onClick) {
|
||||
console.log('click: ', e);
|
||||
onClick(e, claim, indexInContainer);
|
||||
}
|
||||
|
||||
|
@ -292,6 +297,14 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
|||
}
|
||||
}
|
||||
|
||||
function removeFromHistory(e, uri) {
|
||||
e.stopPropagation();
|
||||
if (watchHistory.find((entry) => entry === uri)) {
|
||||
watchHistory.splice(watchHistory.indexOf(uri), 1);
|
||||
setHistory(watchHistory);
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (isValid && !isResolvingUri && shouldFetch && uri) {
|
||||
resolveUri(uri);
|
||||
|
@ -364,7 +377,6 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
|||
>
|
||||
<>
|
||||
{!hideRepostLabel && <ClaimRepostAuthor uri={uri} />}
|
||||
|
||||
<div
|
||||
className={classnames('claim-preview', {
|
||||
'claim-preview--small': type === 'small' || type === 'tooltip',
|
||||
|
@ -487,7 +499,11 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
|||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{inHistory && (
|
||||
<div onClick={(e) => removeFromHistory(e, uri)} className="claim-preview__history-remove">
|
||||
<Icon icon={ICONS.REMOVE} />
|
||||
</div>
|
||||
)}
|
||||
{/* Todo: check isLivestreamActive once we have that data consistently everywhere. */}
|
||||
{claim && isLivestream && <ClaimPreviewReset uri={uri} />}
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ const PLAYLISTS: SideNavLink = {
|
|||
const HISTORY: SideNavLink = {
|
||||
title: 'History',
|
||||
link: `/$/${PAGES.HISTORY}`,
|
||||
icon: ICONS.TIME,
|
||||
icon: ICONS.EYE,
|
||||
hideForUnauth: true,
|
||||
};
|
||||
|
||||
|
|
|
@ -154,7 +154,7 @@ function VideoViewer(props: Props) {
|
|||
|
||||
const [history, setHistory] = usePersistedState('watch-history', []);
|
||||
React.useEffect(() => {
|
||||
if (!history[0].indexOf(claim.permanent_url) !== -1) {
|
||||
if (!history[0] || !history[0].indexOf(claim.permanent_url) !== -1) {
|
||||
if (!history || !history.length) {
|
||||
setHistory([claim.permanent_url]);
|
||||
} else {
|
||||
|
@ -306,7 +306,6 @@ function VideoViewer(props: Props) {
|
|||
setIsEndedEmbed(false);
|
||||
setReplay(false);
|
||||
setDoNavigate(false);
|
||||
// setWatchHistory()
|
||||
analytics.videoIsPlaying(true, player);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,27 +2,15 @@
|
|||
import React from 'react';
|
||||
import ClaimList from 'component/claimList';
|
||||
import Page from 'component/page';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import Card from 'component/common/card';
|
||||
import Button from 'component/button';
|
||||
import classnames from 'classnames';
|
||||
import * as COLLECTIONS_CONSTS from 'constants/collections';
|
||||
import Icon from 'component/common/icon';
|
||||
import * as ICONS from 'constants/icons';
|
||||
import Spinner from 'component/spinner';
|
||||
|
||||
import usePersistedState from 'effects/use-persisted-state';
|
||||
|
||||
// prettier-ignore
|
||||
const Lazy = {
|
||||
// $FlowFixMe
|
||||
DragDropContext: React.lazy(() => import('react-beautiful-dnd' /* webpackChunkName: "dnd" */).then((module) => ({ default: module.DragDropContext }))),
|
||||
// $FlowFixMe
|
||||
Droppable: React.lazy(() => import('react-beautiful-dnd' /* webpackChunkName: "dnd" */).then((module) => ({ default: module.Droppable }))),
|
||||
};
|
||||
|
||||
export const PAGE_VIEW_QUERY = 'view';
|
||||
export const EDIT_PAGE = 'edit';
|
||||
// export const EDIT_PAGE = 'edit';
|
||||
|
||||
type Props = {
|
||||
collectionId: string,
|
||||
|
@ -31,163 +19,51 @@ type Props = {
|
|||
thumbnail: string,
|
||||
collectionUrls: Array<string>,
|
||||
isResolvingCollection: boolean,
|
||||
isMyClaim: boolean,
|
||||
isMyCollection: boolean,
|
||||
claimIsPending: boolean,
|
||||
collectionHasEdits: boolean,
|
||||
deleteCollection: (string, string) => void,
|
||||
editCollection: (string, CollectionEditParams) => void,
|
||||
// isMyClaim: boolean,
|
||||
// isMyCollection: boolean,
|
||||
// claimIsPending: boolean,
|
||||
// collectionHasEdits: boolean,
|
||||
// deleteCollection: (string, string) => void,
|
||||
// editCollection: (string, CollectionEditParams) => void,
|
||||
fetchCollectionItems: (string, () => void) => void,
|
||||
resolveUris: (string) => void,
|
||||
user: ?User,
|
||||
};
|
||||
|
||||
export default function HistoryPage(props: Props) {
|
||||
const {
|
||||
collectionId,
|
||||
claim,
|
||||
collectionHasEdits,
|
||||
claimIsPending,
|
||||
isResolvingCollection,
|
||||
editCollection,
|
||||
fetchCollectionItems,
|
||||
deleteCollection,
|
||||
} = props;
|
||||
const { collectionId } = props;
|
||||
const [history, setHistory] = usePersistedState('watch-history', []);
|
||||
const [unavailableUris] = React.useState([]);
|
||||
|
||||
const collection = {
|
||||
id: 'watchhistory',
|
||||
name: __('Watch History'),
|
||||
type: 'playlist',
|
||||
};
|
||||
const collectionUrls = [];
|
||||
|
||||
const [history] = usePersistedState('watch-history', []);
|
||||
|
||||
const {
|
||||
location: { search },
|
||||
} = useHistory();
|
||||
|
||||
const [didTryResolve, setDidTryResolve] = React.useState(false);
|
||||
const [unavailableUris, setUnavailable] = React.useState([]);
|
||||
const isBuiltin = COLLECTIONS_CONSTS.BUILTIN_LISTS.includes(collectionId);
|
||||
|
||||
function handleOnDragEnd(result) {
|
||||
const { source, destination } = result;
|
||||
|
||||
if (!destination) return;
|
||||
|
||||
const { index: from } = source;
|
||||
const { index: to } = destination;
|
||||
|
||||
editCollection(collectionId, { order: { from, to } });
|
||||
function clearHistory() {
|
||||
setHistory([]);
|
||||
}
|
||||
|
||||
const urlParams = new URLSearchParams(search);
|
||||
const editing = urlParams.get(PAGE_VIEW_QUERY) === EDIT_PAGE;
|
||||
return (
|
||||
<Page className="historyPage-wrapper">
|
||||
<div className={classnames('section card-stack')}>
|
||||
<div className="claim-list__header">
|
||||
<h1 className="card__title">
|
||||
<Icon icon={ICONS.EYE} style={{ marginRight: 'var(--spacing-s)' }} />
|
||||
{__('Watch History')}
|
||||
</h1>
|
||||
|
||||
const urlsReady = collectionUrls && history.length;
|
||||
|
||||
React.useEffect(() => {
|
||||
if (collectionId && !urlsReady && !didTryResolve && !collection) {
|
||||
fetchCollectionItems(collectionId, () => setDidTryResolve(true));
|
||||
}
|
||||
}, [collectionId, urlsReady, didTryResolve, setDidTryResolve, fetchCollectionItems, collection]);
|
||||
|
||||
const pending = (
|
||||
<div className="help card__title--help">
|
||||
<Spinner type={'small'} />
|
||||
{__('Your publish is being confirmed and will be live soon')}
|
||||
</div>
|
||||
);
|
||||
|
||||
const unpublished = (
|
||||
<Button
|
||||
button="close"
|
||||
icon={ICONS.REFRESH}
|
||||
label={__('Clear Edits')}
|
||||
onClick={() => deleteCollection(collectionId, COLLECTIONS_CONSTS.COL_KEY_EDITED)}
|
||||
/>
|
||||
);
|
||||
|
||||
const removeUnavailable = (
|
||||
<Button
|
||||
button="close"
|
||||
icon={ICONS.DELETE}
|
||||
label={__('Remove all unavailable claims')}
|
||||
onClick={() => {
|
||||
editCollection(collectionId, { uris: unavailableUris, remove: true });
|
||||
setUnavailable([]);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
let titleActions;
|
||||
if (collectionHasEdits) {
|
||||
titleActions = unpublished;
|
||||
} else if (claimIsPending) {
|
||||
titleActions = pending;
|
||||
}
|
||||
|
||||
const listName = claim ? claim.value.title || claim.name : collection && collection.name;
|
||||
|
||||
const info = (
|
||||
<Card
|
||||
title={
|
||||
<span>
|
||||
<Icon
|
||||
icon={
|
||||
(collectionId === COLLECTIONS_CONSTS.WATCH_LATER_ID && ICONS.TIME) ||
|
||||
(collectionId === COLLECTIONS_CONSTS.FAVORITES_ID && ICONS.STAR) ||
|
||||
ICONS.TIME
|
||||
}
|
||||
className="icon--margin-right"
|
||||
/>
|
||||
{isBuiltin ? __(listName) : listName}
|
||||
</span>
|
||||
}
|
||||
titleActions={unavailableUris.length > 0 ? removeUnavailable : titleActions}
|
||||
/>
|
||||
);
|
||||
|
||||
if (!collection && (isResolvingCollection || !didTryResolve)) {
|
||||
return (
|
||||
<Page>
|
||||
<h2 className="main--empty empty">{__('Loading...')}</h2>
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
|
||||
if (!collection && !isResolvingCollection && didTryResolve) {
|
||||
return (
|
||||
<Page>
|
||||
<h2 className="main--empty empty">{__('Nothing here')}</h2>
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
|
||||
if (urlsReady) {
|
||||
return (
|
||||
<Page className="playlistPage-wrapper">
|
||||
{editing}
|
||||
<div className={classnames('section card-stack')}>
|
||||
{info}
|
||||
<React.Suspense fallback={null}>
|
||||
<Lazy.DragDropContext onDragEnd={handleOnDragEnd}>
|
||||
<Lazy.Droppable droppableId="list__ordering">
|
||||
{(DroppableProvided) => (
|
||||
<ClaimList
|
||||
uris={history}
|
||||
collectionId={collectionId}
|
||||
// showEdit={showEdit}
|
||||
droppableProvided={DroppableProvided}
|
||||
unavailableUris={unavailableUris}
|
||||
/>
|
||||
)}
|
||||
</Lazy.Droppable>
|
||||
</Lazy.DragDropContext>
|
||||
</React.Suspense>
|
||||
<div className="claim-list__alt-controls--wrap">
|
||||
{history.length > 0 && (
|
||||
<Button
|
||||
title={__('Clear History')}
|
||||
button="primary"
|
||||
label={__('Clear History')}
|
||||
onClick={() => clearHistory()}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
{history.length > 0 && (
|
||||
<ClaimList uris={history} collectionId={collectionId} unavailableUris={unavailableUris} inHistory />
|
||||
)}
|
||||
{history.length === 0 && <h2 className="main--empty empty">{__('Nothing here')}</h2>}
|
||||
</div>
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1205,6 +1205,38 @@ img {
|
|||
}
|
||||
}
|
||||
|
||||
.historyPage-wrapper {
|
||||
.claim-preview__wrapper {
|
||||
.claim-preview__history-remove {
|
||||
position: absolute;
|
||||
top: var(--spacing-s);
|
||||
right: var(--spacing-xs);
|
||||
opacity: 0;
|
||||
|
||||
.icon {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.icon {
|
||||
stroke: var(--color-primary);
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
.menu__button.claim__menu-button {
|
||||
top: 2.2rem;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.claim-preview__history-remove {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.premium-wrapper {
|
||||
.membership_title {
|
||||
.comment__badge {
|
||||
|
|
Loading…
Reference in a new issue