diff --git a/CHANGELOG.md b/CHANGELOG.md index a6118a90e..93caaaafa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Update lighthouse search api _community pr!_ ([#6731](https://github.com/lbryio/lbry-desktop/pull/6731)) - Update sockety api _community pr!_ ([#6747](https://github.com/lbryio/lbry-desktop/pull/6747)) - Use resolve for OG metadata instead of chainquery _community pr!_ ([#6787](https://github.com/lbryio/lbry-desktop/pull/6787)) -- Improved clickability of notification links _community pr!_ ([#6711](https://github.com/lbryio/lbry-desktop/pull/6711)) ### Fixed - App now supports '#' and ':' for claimId separator ([#6496](https://github.com/lbryio/lbry-desktop/pull/6496)) diff --git a/ui/component/app/view.jsx b/ui/component/app/view.jsx index aadc719e4..4ab5d4fbf 100644 --- a/ui/component/app/view.jsx +++ b/ui/component/app/view.jsx @@ -5,7 +5,7 @@ import { lazyImport } from 'util/lazyImport'; import classnames from 'classnames'; import analytics from 'analytics'; import { buildURI, parseURI } from 'lbry-redux'; -import { SIMPLE_SITE, ENABLE_PREROLL_ADS } from 'config'; +import { SIMPLE_SITE } from 'config'; import Router from 'component/router/index'; import ReactModal from 'react-modal'; import { openContextMenu } from 'util/context-menu'; @@ -325,23 +325,6 @@ function App(props: Props) { } }, [previousRewardApproved, isRewardApproved]); - // Load IMA3 SDK for aniview - // @if TARGET='web' - useEffect(() => { - if (ENABLE_PREROLL_ADS) { - const script = document.createElement('script'); - script.src = `https://imasdk.googleapis.com/js/sdkloader/ima3.js`; - script.async = true; - // $FlowFixMe - document.body.appendChild(script); - return () => { - // $FlowFixMe - document.body.removeChild(script); - }; - } - }); - // @endif - // @if TARGET='app' useEffect(() => { if (updatePreferences && getWalletSyncPref && readyForPrefs) { diff --git a/ui/component/collectionsListMine/index.js b/ui/component/collectionsListMine/index.js index d4b92bf2a..92bd2f2f7 100644 --- a/ui/component/collectionsListMine/index.js +++ b/ui/component/collectionsListMine/index.js @@ -9,7 +9,7 @@ import CollectionsListMine from './view'; const select = (state) => ({ builtinCollections: selectBuiltinCollections(state), - publishedPlaylists: selectMyPublishedPlaylistCollections(state), + publishedCollections: selectMyPublishedPlaylistCollections(state), unpublishedCollections: selectMyUnpublishedCollections(state), // savedCollections: selectSavedCollections(state), }); diff --git a/ui/component/collectionsListMine/view.jsx b/ui/component/collectionsListMine/view.jsx index 45b3b6c96..ee3be8b17 100644 --- a/ui/component/collectionsListMine/view.jsx +++ b/ui/component/collectionsListMine/view.jsx @@ -8,48 +8,78 @@ import Icon from 'component/common/icon'; import * as ICONS from 'constants/icons'; import * as PAGES from 'constants/pages'; import Yrbl from 'component/yrbl'; -import usePersistedState from 'effects/use-persisted-state'; -import Card from 'component/common/card'; import classnames from 'classnames'; +import { FormField, Form } from 'component/common/form'; type Props = { builtinCollections: CollectionGroup, publishedCollections: CollectionGroup, - publishedPlaylists: CollectionGroup, + publishedCollections: CollectionGroup, unpublishedCollections: CollectionGroup, // savedCollections: CollectionGroup, }; +const ALL = 'All'; +const PRIVATE = 'Private'; +const PUBLIC = 'Public'; +const COLLECTION_FILTERS = [ALL, PRIVATE, PUBLIC]; + export default function CollectionsListMine(props: Props) { const { builtinCollections, - publishedPlaylists, + publishedCollections, unpublishedCollections, // savedCollections, these are resolved on startup from sync'd claimIds or urls } = props; const builtinCollectionsList = (Object.values(builtinCollections || {}): any); const unpublishedCollectionsList = (Object.keys(unpublishedCollections || {}): any); - const publishedList = (Object.keys(publishedPlaylists || {}): any); + const publishedList = (Object.keys(publishedCollections || {}): any); const hasCollections = unpublishedCollectionsList.length || publishedList.length; + const [filterType, setFilterType] = React.useState(ALL); + const [searchText, setSearchText] = React.useState(''); + + let collectionsToShow = []; + if (filterType === ALL) { + collectionsToShow = unpublishedCollectionsList.concat(publishedList); + } else if (filterType === PRIVATE) { + collectionsToShow = unpublishedCollectionsList; + } else if (filterType === PUBLIC) { + collectionsToShow = publishedList; + } + + let filteredCollections; + if (searchText && collectionsToShow) { + filteredCollections = collectionsToShow.filter((id) => { + return ( + (unpublishedCollections[id] && + unpublishedCollections[id].name.toLocaleLowerCase().includes(searchText.toLocaleLowerCase())) || + (publishedCollections[id] && + publishedCollections[id].name.toLocaleLowerCase().includes(searchText.toLocaleLowerCase())) + ); + }); + } else { + filteredCollections = collectionsToShow || []; + } const watchLater = builtinCollectionsList.find((list) => list.id === COLLECTIONS_CONSTS.WATCH_LATER_ID); const favorites = builtinCollectionsList.find((list) => list.id === COLLECTIONS_CONSTS.FAVORITES_ID); const builtin = [watchLater, favorites]; - const [showHelp, setShowHelp] = usePersistedState('livestream-help-seen', true); + function escapeListener(e: SyntheticKeyboardEvent<*>) { + const KEYCODE_ESCAPE = 27; + if (e.keyCode === KEYCODE_ESCAPE) { + e.preventDefault(); + setSearchText(''); + } + } - const helpText = ( -
-

{__(`Everyone starts with 2 private lists - Watch Later and Favorites.`)}

-

{__(`Add content to existing lists or new lists from content pages or content previews.`)}

-

- {__( - `By default, lists are private. You can edit them and later publish them from the Lists page or the Publish context menu on this page. Similar to uploads, small blockchain fees apply.` - )} -

-
- ); + function onTextareaFocus() { + window.addEventListener('keydown', escapeListener); + } + function onTextareaBlur() { + window.removeEventListener('keydown', escapeListener); + } return ( <> {builtin.map((list: Collection) => { @@ -68,9 +98,14 @@ export default function CollectionsListMine(props: Props) { {__(`${list.name}`)}
- + {itemUrls.length}
@@ -91,52 +126,57 @@ export default function CollectionsListMine(props: Props) { ); })}
-
+

{__('Playlists')} {!hasCollections && (
{__('(Empty) --[indicates empty playlist]--')}
)}

-
- {showHelp && ( - setShowHelp(false)} />} - title={__('Introducing Lists')} - actions={helpText} - /> - )} +
+
+
+ {COLLECTION_FILTERS.map((value) => ( +
+
+
{}} className="wunderbar--inline"> + + setSearchText(e.target.value)} + type="text" + placeholder={__('Search')} + /> + +
{Boolean(hasCollections) && ( -
+
{/* TODO: fix above spacing hack */}
- {unpublishedCollectionsList && - unpublishedCollectionsList.length > 0 && - unpublishedCollectionsList.map((key) => ( - - ))} - {publishedList && - publishedList.length > 0 && - publishedList.map((key) => )} + {filteredCollections && + filteredCollections.length > 0 && + filteredCollections.map((key) => )} + {!filteredCollections.length &&
{__('No matching collections')}
}
)} {!hasCollections && (
- - //
- // } - /> +
)}
diff --git a/ui/component/notification/view.jsx b/ui/component/notification/view.jsx index 3a0d70811..889d43ac4 100644 --- a/ui/component/notification/view.jsx +++ b/ui/component/notification/view.jsx @@ -16,8 +16,6 @@ import FileThumbnail from 'component/fileThumbnail'; import { Menu, MenuList, MenuButton, MenuItem } from '@reach/menu-button'; import NotificationContentChannelMenu from 'component/notificationContentChannelMenu'; import LbcMessage from 'component/common/lbc-message'; -import UriIndicator from 'component/uriIndicator'; -import { NavLink } from 'react-router-dom'; type Props = { notification: WebNotification, @@ -31,12 +29,13 @@ export default function Notification(props: Props) { const { notification, menuButton = false, doReadNotifications, doDeleteNotification } = props; const { push } = useHistory(); const { notification_rule, notification_parameters, is_read, id } = notification; - const isCommentNotification = notification_rule === RULE.COMMENT || notification_rule === RULE.COMMENT_REPLY || notification_rule === RULE.CREATOR_COMMENT; const commentText = isCommentNotification && notification_parameters.dynamic.comment; + const channelUrl = + (notification_rule === RULE.NEW_CONTENT && notification.notification_parameters.dynamic.channel_url) || ''; let notificationTarget; switch (notification_rule) { @@ -52,14 +51,21 @@ export default function Notification(props: Props) { notificationTarget = notification_parameters.device.target; } - const creatorIcon = (channelUrl) => { - return ( - - - - ); - }; - let channelUrl; + let notificationLink = formatLbryUrlForWeb(notificationTarget); + let urlParams = new URLSearchParams(); + if (isCommentNotification && notification_parameters.dynamic.hash) { + urlParams.append('lc', notification_parameters.dynamic.hash); + } + + try { + const { isChannel } = parseURI(notificationTarget); + if (isChannel) { + urlParams.append(PAGE_VIEW_QUERY, DISCUSSION_PAGE); + } + } catch (e) {} + + notificationLink += `?${urlParams.toString()}`; + let icon; switch (notification_rule) { case RULE.CREATOR_SUBSCRIBER: @@ -67,20 +73,16 @@ export default function Notification(props: Props) { break; case RULE.COMMENT: case RULE.CREATOR_COMMENT: - channelUrl = notification_parameters.dynamic.comment_author; - icon = creatorIcon(channelUrl); + icon = ; break; case RULE.COMMENT_REPLY: - channelUrl = notification_parameters.dynamic.reply_author; - icon = creatorIcon(channelUrl); + icon = ; break; case RULE.NEW_CONTENT: - channelUrl = notification_parameters.dynamic.channel_url; - icon = creatorIcon(channelUrl); + icon = ; break; case RULE.NEW_LIVESTREAM: - channelUrl = notification_parameters.dynamic.channel_url; - icon = creatorIcon(channelUrl); + icon = ; break; case RULE.DAILY_WATCH_AVAILABLE: case RULE.DAILY_WATCH_REMIND: @@ -95,54 +97,12 @@ export default function Notification(props: Props) { icon = ; } - let notificationLink = formatLbryUrlForWeb(notificationTarget); - let urlParams = new URLSearchParams(); - if (isCommentNotification && notification_parameters.dynamic.hash) { - urlParams.append('lc', notification_parameters.dynamic.hash); - } - - let channelName = channelUrl && '@' + channelUrl.split('@')[1].split('#')[0]; - - const notificationTitle = notification_parameters.device.title; - const titleSplit = notificationTitle.split(' '); - let fullTitle = [' ']; - let uriIndicator; - const title = titleSplit.map((message, index) => { - if (channelName === message) { - uriIndicator = ; - fullTitle.push(' '); - const resultTitle = fullTitle; - fullTitle = [' ']; - - return [resultTitle.join(' '), uriIndicator]; - } else { - fullTitle.push(message); - - if (index === titleSplit.length - 1) { - return {fullTitle.join(' ')}; - } - } - }); - - try { - const { isChannel } = parseURI(notificationTarget); - if (isChannel) { - urlParams.append(PAGE_VIEW_QUERY, DISCUSSION_PAGE); - } - } catch (e) {} - - notificationLink += `?${urlParams.toString()}`; - const navLinkProps = { - to: notificationLink, - onClick: (e) => e.stopPropagation(), - }; - function handleNotificationClick() { if (!is_read) { doReadNotifications([id]); } - if (menuButton && notificationLink) { + if (notificationLink) { push(notificationLink); } } @@ -160,11 +120,9 @@ export default function Notification(props: Props) { ) : notificationLink ? (props: { children: any }) => ( - - - {props.children} - - + + {props.children} + ) : (props: { children: any }) => (
- {!isCommentNotification &&
{title}
} + {!isCommentNotification && ( +
+ {notification_parameters.device.title} +
+ )} {isCommentNotification && commentText ? ( <> -
{title}
+
+ {notification_parameters.device.title} +
{commentText}
@@ -229,13 +193,7 @@ export default function Notification(props: Props) {
- { - e.preventDefault(); - e.stopPropagation(); - }} - > + e.stopPropagation()}> diff --git a/ui/component/viewers/videoViewer/internal/videojs.jsx b/ui/component/viewers/videoViewer/internal/videojs.jsx index 73ee97457..d27bf7f1d 100644 --- a/ui/component/viewers/videoViewer/internal/videojs.jsx +++ b/ui/component/viewers/videoViewer/internal/videojs.jsx @@ -624,8 +624,8 @@ export default React.memo(function VideoJs(props: Props) { const player = playerRef.current; if (player) { - player.dispose(); window.player = undefined; + player.dispose(); } }; }, [isAudio]); @@ -664,6 +664,22 @@ export default React.memo(function VideoJs(props: Props) { }); }, [source, reload]); + // Load IMA3 SDK for aniview + // @if TARGET='web' + useEffect(() => { + const script = document.createElement('script'); + script.src = `https://imasdk.googleapis.com/js/sdkloader/ima3.js`; + script.async = true; + // $FlowFixMe + document.body.appendChild(script); + + return () => { + // $FlowFixMe + document.body.removeChild(script); + }; + }); + // @endif + return ( // $FlowFixMe
diff --git a/ui/scss/component/_notification.scss b/ui/scss/component/_notification.scss index 6d61abba5..f092095c4 100644 --- a/ui/scss/component/_notification.scss +++ b/ui/scss/component/_notification.scss @@ -42,7 +42,6 @@ $contentMaxWidth: 60rem; width: 100%; display: flex; padding: var(--spacing-m) 0; - justify-content: space-between; .channel-thumbnail { @include handleChannelGif(3rem); @@ -61,7 +60,6 @@ $contentMaxWidth: 60rem; .notification__wrapper--unread { background-color: var(--color-card-background-highlighted); - justify-content: space-between; &:hover { background-color: var(--color-button-secondary-bg); @@ -122,7 +120,6 @@ $contentMaxWidth: 60rem; } .notification__title { - position: relative; font-size: var(--font-small); color: var(--color-text); margin-bottom: var(--spacing-s); @@ -138,7 +135,6 @@ $contentMaxWidth: 60rem; .notification__text { font-size: var(--font-body); - color: var(--color-text); display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical;