From 43564c8b45111c17d67e66de80bf32fd7a7106b5 Mon Sep 17 00:00:00 2001 From: infinite-persistence Date: Mon, 13 Sep 2021 09:58:43 +0800 Subject: [PATCH 1/7] Settings: use 'smooth' instead of 'instant' scroll. With 'instant', it is not clear that we are actually scrolling within the existing page (not opening a new page). --- ui/component/settingsSideNavigation/view.jsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ui/component/settingsSideNavigation/view.jsx b/ui/component/settingsSideNavigation/view.jsx index e791e7ffb..5acb442c6 100644 --- a/ui/component/settingsSideNavigation/view.jsx +++ b/ui/component/settingsSideNavigation/view.jsx @@ -56,7 +56,11 @@ export default function SettingsSideNavigation() { const TOP_MARGIN_PX = 20; const element = document.getElementById(section); if (element) { - window.scrollTo(0, element.offsetTop - TOP_MARGIN_PX); + window.scrollTo({ + top: element.offsetTop - TOP_MARGIN_PX, + left: 0, + behavior: 'smooth', + }); } } -- 2.45.2 From c2a2068926d5609c0cb5c2bce528c9535a8f825b Mon Sep 17 00:00:00 2001 From: infinite-persistence Date: Mon, 13 Sep 2021 11:28:22 +0800 Subject: [PATCH 2/7] Sort props to clarify "client vs. redux". No functional change. --- ui/component/claimListDiscover/view.jsx | 111 +++++++++++++----------- 1 file changed, 61 insertions(+), 50 deletions(-) diff --git a/ui/component/claimListDiscover/view.jsx b/ui/component/claimListDiscover/view.jsx index 39f705500..423d7bee3 100644 --- a/ui/component/claimListDiscover/view.jsx +++ b/ui/component/claimListDiscover/view.jsx @@ -18,68 +18,79 @@ import { getLivestreamOnlyOptions } from 'util/search'; type Props = { uris: Array, - showHeader: boolean, + name?: string, type: string, - subscribedChannels: Array, - doClaimSearch: ({}) => void, - loading: boolean, - personalView: boolean, - doToggleTagFollowDesktop: (string) => void, - meta?: Node, - showNsfw: boolean, - hideReposts: boolean, + pageSize?: number, + fetchViewCount?: boolean, - history: { action: string, push: (string) => void, replace: (string) => void }, - location: { search: string, pathname: string }, - claimSearchByQuery: { - [string]: Array, - }, - claimSearchByQueryLastPageReached: { [string]: boolean }, - mutedUris: Array, - blockedUris: Array, - hiddenNsfwMessage?: Node, - channelIds?: Array, - claimIds?: Array, - tags: string, // these are just going to be string. pass a CSV if you want multi - defaultTags: string, + forceShowReposts?: boolean, + hasNoSource?: boolean, + hasSource?: boolean, + hideAdvancedFilter?: boolean, + hideFilters?: boolean, + includeSupportAction?: boolean, + infiniteScroll?: Boolean, + isChannel?: boolean, + liveLivestreamsFirst?: boolean, + personalView: boolean, + showHeader: boolean, + showHiddenByUser?: boolean, + showNoSourceClaims?: boolean, + tileLayout: boolean, + orderBy?: Array, defaultOrderBy?: string, freshness?: string, defaultFreshness?: string, - header?: Node, - headerLabel?: string | Node, - name?: string, - hideAdvancedFilter?: boolean, + + tags: string, // these are just going to be string. pass a CSV if you want multi + defaultTags: string, + claimType?: string | Array, defaultClaimType?: Array, + streamType?: string | Array, defaultStreamType?: string | Array, - renderProperties?: (Claim) => Node, - includeSupportAction?: boolean, - repostedClaimId?: string, - pageSize?: number, - followedTags?: Array, - injectedItem: ?Node, - infiniteScroll?: Boolean, - feeAmount?: string, - tileLayout: boolean, - hideFilters?: boolean, - maxPages?: number, - forceShowReposts?: boolean, - languageSetting: string, - searchInLanguage: boolean, - scrollAnchor?: string, - showHiddenByUser?: boolean, - liveLivestreamsFirst?: boolean, - livestreamMap?: { [string]: any }, - hasSource?: boolean, - hasNoSource?: boolean, - limitClaimsPerChannel?: number, - releaseTime?: string, - showNoSourceClaims?: boolean, - isChannel?: boolean, + empty?: string, + feeAmount?: string, + releaseTime?: string, + repostedClaimId?: string, + scrollAnchor?: string, + maxPages?: number, + limitClaimsPerChannel?: number, + + channelIds?: Array, + claimIds?: Array, + subscribedChannels: Array, + livestreamMap?: { [string]: any }, + + header?: Node, + headerLabel?: string | Node, + hiddenNsfwMessage?: Node, + injectedItem: ?Node, + meta?: Node, + renderProperties?: (Claim) => Node, + + history: { action: string, push: (string) => void, replace: (string) => void }, + location: { search: string, pathname: string }, + + // --- select --- + followedTags?: Array, + claimSearchByQuery: { [string]: Array }, + claimSearchByQueryLastPageReached: { [string]: boolean }, claimsByUri: { [string]: any }, + loading: boolean, + showNsfw: boolean, + hideReposts: boolean, + languageSetting: string, + mutedUris: Array, + blockedUris: Array, + searchInLanguage: boolean, + + // --- perform --- + doClaimSearch: ({}) => void, + doToggleTagFollowDesktop: (string) => void, doFetchViewCount: (claimIdCsv: string) => void, }; -- 2.45.2 From 40ed8059b7d725e272bc189440b293e28349afdb Mon Sep 17 00:00:00 2001 From: infinite-persistence Date: Mon, 13 Sep 2021 15:42:46 +0800 Subject: [PATCH 3/7] Fix jumpy ui when changing language Closes 7070 Spinner at wrong location when changing language --- ui/component/settingLanguage/view.jsx | 28 ++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/ui/component/settingLanguage/view.jsx b/ui/component/settingLanguage/view.jsx index 515970d6e..74c2d5491 100644 --- a/ui/component/settingLanguage/view.jsx +++ b/ui/component/settingLanguage/view.jsx @@ -35,20 +35,22 @@ function SettingLanguage(props: Props) { return ( - {previousLanguage && } + {!previousLanguage && ( + + {sortLanguageMap(SUPPORTED_LANGUAGES).map(([langKey, langName]) => ( + + ))} + + )} - - {sortLanguageMap(SUPPORTED_LANGUAGES).map(([langKey, langName]) => ( - - ))} - + {previousLanguage && } ); } -- 2.45.2 From 903a7c8afd634c5a2ed93bc0e1da986989e209f5 Mon Sep 17 00:00:00 2001 From: saltrafael Date: Mon, 13 Sep 2021 06:02:41 -0300 Subject: [PATCH 4/7] Fix Floating Player stopping on certain files --- ui/component/fileRenderInitiator/index.js | 8 ++------ ui/component/fileRenderInitiator/view.jsx | 7 +++---- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/ui/component/fileRenderInitiator/index.js b/ui/component/fileRenderInitiator/index.js index efa2f28c9..2a9765ce1 100644 --- a/ui/component/fileRenderInitiator/index.js +++ b/ui/component/fileRenderInitiator/index.js @@ -4,7 +4,6 @@ import { makeSelectFileInfoForUri, makeSelectThumbnailForUri, makeSelectClaimForUri, - makeSelectStreamingUrlForUri, makeSelectClaimWasPurchased, SETTINGS, COLLECTIONS_CONSTS, @@ -16,7 +15,6 @@ import { withRouter } from 'react-router'; import { makeSelectIsPlaying, makeSelectShouldObscurePreview, - selectPlayingUri, makeSelectInsufficientCreditsForUri, makeSelectFileRenderModeForUri, } from 'redux/selectors/content'; @@ -33,9 +31,7 @@ const select = (state, props) => { fileInfo: makeSelectFileInfoForUri(props.uri)(state), obscurePreview: makeSelectShouldObscurePreview(props.uri)(state), isPlaying: makeSelectIsPlaying(props.uri)(state), - playingUri: selectPlayingUri(state), insufficientCredits: makeSelectInsufficientCreditsForUri(props.uri)(state), - streamingUrl: makeSelectStreamingUrlForUri(props.uri)(state), autoplay: makeSelectClientSetting(SETTINGS.AUTOPLAY_MEDIA)(state), costInfo: makeSelectCostInfoForUri(props.uri)(state), renderMode: makeSelectFileRenderModeForUri(props.uri)(state), @@ -47,9 +43,9 @@ const select = (state, props) => { }; const perform = (dispatch) => ({ - play: (uri, collectionId) => { + play: (uri, collectionId, isPlayable) => { dispatch(doSetPrimaryUri(uri)); - dispatch(doSetPlayingUri({ uri, collectionId })); + if (isPlayable) dispatch(doSetPlayingUri({ uri, collectionId })); dispatch(doPlayUri(uri, undefined, undefined, (fileInfo) => dispatch(doAnaltyicsPurchaseEvent(fileInfo)))); }, }); diff --git a/ui/component/fileRenderInitiator/view.jsx b/ui/component/fileRenderInitiator/view.jsx index aac98c99d..a654ee967 100644 --- a/ui/component/fileRenderInitiator/view.jsx +++ b/ui/component/fileRenderInitiator/view.jsx @@ -16,8 +16,7 @@ import Nag from 'component/common/nag'; import FileRenderPlaceholder from 'static/img/fileRenderPlaceholder.png'; type Props = { - play: (string, string) => void, - isLoading: boolean, + play: (string, string, boolean) => void, isPlaying: boolean, fileInfo: FileListItem, uri: string, @@ -104,9 +103,9 @@ export default function FileRenderInitiator(props: Props) { e.stopPropagation(); } - play(uri, collectionId); + play(uri, collectionId, isPlayable); }, - [play, uri, collectionId] + [play, uri, isPlayable, collectionId] ); useEffect(() => { -- 2.45.2 From 37ce82edb4b0babd6dcc05f30750f80054da46db Mon Sep 17 00:00:00 2001 From: saltrafael Date: Mon, 13 Sep 2021 06:11:48 -0300 Subject: [PATCH 5/7] Dont show additional player buttons from markdown and comments --- ui/component/viewers/videoViewer/index.js | 17 ++-- ui/component/viewers/videoViewer/view.jsx | 106 ++++++++++------------ 2 files changed, 56 insertions(+), 67 deletions(-) diff --git a/ui/component/viewers/videoViewer/index.js b/ui/component/viewers/videoViewer/index.js index 36ebd422b..2ca09af22 100644 --- a/ui/component/viewers/videoViewer/index.js +++ b/ui/component/viewers/videoViewer/index.js @@ -1,7 +1,6 @@ import { connect } from 'react-redux'; import { makeSelectClaimForUri, - makeSelectFileInfoForUri, makeSelectThumbnailForUri, SETTINGS, COLLECTIONS_CONSTS, @@ -40,6 +39,7 @@ const select = (state, props) => { const userId = selectUser(state) && selectUser(state).id; const playingUri = selectPlayingUri(state); const collectionId = urlParams.get(COLLECTIONS_CONSTS.COLLECTION_ID) || (playingUri && playingUri.collectionId); + const isMarkdownOrComment = playingUri && (playingUri.source === 'markdown' || playingUri.source === 'comment'); let nextRecommendedUri; let previousListUri; @@ -51,24 +51,23 @@ const select = (state, props) => { } return { + position, + userId, + collectionId, + nextRecommendedUri, + previousListUri, + isMarkdownOrComment, autoplayIfEmbedded: Boolean(autoplay), - autoplayMedia: Boolean(makeSelectClientSetting(SETTINGS.AUTOPLAY_MEDIA)(state)), - autoplayNext: Boolean(makeSelectClientSetting(SETTINGS.AUTOPLAY_NEXT)(state)), + autoplayNext: makeSelectClientSetting(SETTINGS.AUTOPLAY_NEXT)(state), volume: selectVolume(state), muted: selectMute(state), videoPlaybackRate: makeSelectClientSetting(SETTINGS.VIDEO_PLAYBACK_RATE)(state), - position: position, - hasFileInfo: Boolean(makeSelectFileInfoForUri(uri)(state)), thumbnail: makeSelectThumbnailForUri(uri)(state), claim: makeSelectClaimForUri(uri)(state), homepageData: selectHomepageData(state), authenticated: selectUserVerifiedEmail(state), - userId: userId, shareTelemetry: IS_WEB || selectDaemonSettings(state).share_usage_data, isFloating: makeSelectIsPlayerFloating(props.location)(state), - collectionId, - nextRecommendedUri, - previousListUri, videoTheaterMode: makeSelectClientSetting(SETTINGS.VIDEO_THEATER_MODE)(state), }; }; diff --git a/ui/component/viewers/videoViewer/view.jsx b/ui/component/viewers/videoViewer/view.jsx index 2f5764bac..efe534dd1 100644 --- a/ui/component/viewers/videoViewer/view.jsx +++ b/ui/component/viewers/videoViewer/view.jsx @@ -42,7 +42,6 @@ type Props = { videoPlaybackRate: number, volume: number, uri: string, - autoplayMedia: boolean, autoplayNext: boolean, autoplayIfEmbedded: boolean, desktopPlayStartTime?: number, @@ -64,6 +63,7 @@ type Props = { nextRecommendedUri: string, previousListUri: string, videoTheaterMode: boolean, + isMarkdownOrComment: boolean, }; /* @@ -84,7 +84,6 @@ function VideoViewer(props: Props) { uri, muted, volume, - autoplayMedia, autoplayNext, autoplayIfEmbedded, doAnalyticsView, @@ -106,6 +105,7 @@ function VideoViewer(props: Props) { nextRecommendedUri, previousListUri, videoTheaterMode, + isMarkdownOrComment, } = props; const permanentUrl = claim && claim.permanent_url; const adApprovedChannelIds = homepageData ? getAllIds(homepageData) : []; @@ -196,32 +196,32 @@ function VideoViewer(props: Props) { ); useEffect(() => { - if (doNavigate) { - if (playNextUrl) { - if (permanentUrl !== nextRecommendedUri) { - if (nextRecommendedUri) { - if (collectionId) clearPosition(permanentUrl); - doPlay(nextRecommendedUri); - } - } else { - setReplay(true); + if (!doNavigate) return; + + if (playNextUrl) { + if (permanentUrl !== nextRecommendedUri) { + if (nextRecommendedUri) { + if (collectionId) clearPosition(permanentUrl); + doPlay(nextRecommendedUri); } } else { - if (videoNode) { - const currentTime = videoNode.currentTime; - - if (currentTime <= 5) { - if (previousListUri && permanentUrl !== previousListUri) doPlay(previousListUri); - } else { - videoNode.currentTime = 0; - } - setDoNavigate(false); - } + setReplay(true); + } + } else { + if (videoNode) { + const currentTime = videoNode.currentTime; + + if (currentTime <= 5) { + if (previousListUri && permanentUrl !== previousListUri) doPlay(previousListUri); + } else { + videoNode.currentTime = 0; + } + setDoNavigate(false); } - if (!ended) setDoNavigate(false); - setEnded(false); - setPlayNextUrl(true); } + if (!ended) setDoNavigate(false); + setEnded(false); + setPlayNextUrl(true); }, [ clearPosition, collectionId, @@ -236,37 +236,25 @@ function VideoViewer(props: Props) { ]); React.useEffect(() => { - if (ended) { - analytics.videoIsPlaying(false); + if (!ended) return; - if (adUrl) { - setAdUrl(null); - return; - } + analytics.videoIsPlaying(false); - if (embedded) { - setIsEndedEmbed(true); - } else if (!collectionId && autoplayNext) { - setShowAutoplayCountdown(true); - } else if (collectionId) { - setDoNavigate(true); - } - - clearPosition(uri); + if (adUrl) { + setAdUrl(null); + return; } - }, [ - embedded, - setIsEndedEmbed, - autoplayMedia, - setShowAutoplayCountdown, - adUrl, - setAdUrl, - clearPosition, - uri, - ended, - collectionId, - autoplayNext, - ]); + + if (embedded) { + setIsEndedEmbed(true); + } else if (!collectionId && autoplayNext) { + setShowAutoplayCountdown(true); + } else if (collectionId) { + setDoNavigate(true); + } + + clearPosition(uri); + }, [adUrl, autoplayNext, clearPosition, collectionId, embedded, ended, setAdUrl, uri]); function onPlay(player) { setEnded(false); @@ -321,12 +309,14 @@ function VideoViewer(props: Props) { player.muted(muted); player.volume(volume); player.playbackRate(videoPlaybackRate); - addTheaterModeButton(player, toggleVideoTheaterMode); - if (collectionId) { - addPlayNextButton(player, doPlayNext); - addPlayPreviousButton(player, doPlayPrevious); - } else { - addAutoplayNextButton(player, toggleAutoplayNext, autoplayNext); + if (!isMarkdownOrComment) { + addTheaterModeButton(player, toggleVideoTheaterMode); + if (collectionId) { + addPlayNextButton(player, doPlayNext); + addPlayPreviousButton(player, doPlayPrevious); + } else { + addAutoplayNextButton(player, toggleAutoplayNext, autoplayNext); + } } } -- 2.45.2 From f77c9f5279b2fc90e9bf0f6580deb3588dc97602 Mon Sep 17 00:00:00 2001 From: saltrafael Date: Mon, 13 Sep 2021 06:52:16 -0300 Subject: [PATCH 6/7] Fix markdown resizing for the same video playing --- flow-typed/content.js | 1 + ui/component/embedPlayButton/view.jsx | 10 +++++----- ui/component/fileRenderFloating/view.jsx | 21 ++++++++++----------- ui/redux/selectors/content.js | 4 ++-- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/flow-typed/content.js b/flow-typed/content.js index 6246a7c95..e32f6188f 100644 --- a/flow-typed/content.js +++ b/flow-typed/content.js @@ -2,6 +2,7 @@ declare type PlayingUri = { uri: string, + primaryUri: string, pathname: string, commentId?: string, source?: string, diff --git a/ui/component/embedPlayButton/view.jsx b/ui/component/embedPlayButton/view.jsx index 9a796478d..57d66fa2b 100644 --- a/ui/component/embedPlayButton/view.jsx +++ b/ui/component/embedPlayButton/view.jsx @@ -12,12 +12,12 @@ type Props = { uri: string, thumbnail: string, claim: ?Claim, - doResolveUri: string => void, - doFetchCostInfoForUri: string => void, + doResolveUri: (string) => void, + doFetchCostInfoForUri: (string) => void, costInfo: ?{ cost: number }, floatingPlayerEnabled: boolean, doPlayUri: (string, ?boolean, ?boolean, (GetResponse) => void) => void, - doAnaltyicsPurchaseEvent: GetResponse => void, + doAnaltyicsPurchaseEvent: (GetResponse) => void, parentCommentId?: string, isMarkdownPost: boolean, doSetPlayingUri: ({}) => void, @@ -69,8 +69,8 @@ export default function EmbedPlayButton(props: Props) { const formattedUrl = formatLbryUrlForWeb(uri); push(formattedUrl); } else { - doPlayUri(uri, undefined, undefined, fileInfo => { - let playingOptions: PlayingUri = { uri, pathname }; + doPlayUri(uri, undefined, undefined, (fileInfo) => { + let playingOptions = { uri, pathname, source: undefined, commentId: undefined }; if (parentCommentId) { playingOptions.source = 'comment'; playingOptions.commentId = parentCommentId; diff --git a/ui/component/fileRenderFloating/view.jsx b/ui/component/fileRenderFloating/view.jsx index 02fa9e6fc..911e50987 100644 --- a/ui/component/fileRenderFloating/view.jsx +++ b/ui/component/fileRenderFloating/view.jsx @@ -69,7 +69,7 @@ export default function FileRenderFloating(props: Props) { const { location, push } = useHistory(); const hideFloatingPlayer = location.state && location.state.hideFloatingPlayer; const isMobile = useIsMobile(); - const mainFilePlaying = playingUri && isURIEqual(playingUri.uri, primaryUri); + const mainFilePlaying = !isFloating && isURIEqual(uri, primaryUri); const [fileViewerRect, setFileViewerRect] = useState(); const [desktopPlayStartTime, setDesktopPlayStartTime] = useState(); const [wasDragging, setWasDragging] = useState(false); @@ -85,7 +85,8 @@ export default function FileRenderFloating(props: Props) { y: 0, }); - const navigateUrl = uri + (collectionId ? generateListSearchUrlParams(collectionId) : ''); + const navigateUrl = + playingUri && playingUri.primaryUri + (collectionId ? generateListSearchUrlParams(collectionId) : ''); const isFree = costInfo && costInfo.cost === 0; const canViewFile = isFree || claimWasPurchased; @@ -154,7 +155,7 @@ export default function FileRenderFloating(props: Props) { // Listen to main-window resizing and adjust the fp position accordingly: useEffect(() => { - const handleMainWindowResize = debounce((e) => { + const handleMainWindowResize = debounce(() => { let newPos = { x: Math.round(relativePos.x * getScreenWidth()), y: Math.round(relativePos.y * getScreenHeight()), @@ -175,13 +176,11 @@ export default function FileRenderFloating(props: Props) { ? document.querySelector(`.${PRIMARY_PLAYER_WRAPPER_CLASS}`) : document.querySelector(`.${INLINE_PLAYER_WRAPPER_CLASS}`); - if (!element) { - return; - } + if (!element) return; const rect = element.getBoundingClientRect(); - // getBoundingCLientRect returns a DomRect, not an object + // getBoundingClientRect returns a DomRect, not an object const objectRect = { top: rect.top, right: rect.right, @@ -198,11 +197,11 @@ export default function FileRenderFloating(props: Props) { }, [mainFilePlaying]); useEffect(() => { - if (streamingUrl) { + if (playingUri && playingUri.primaryUri) { handleResize(); setCountdownCanceled(false); } - }, [handleResize, streamingUrl, videoTheaterMode]); + }, [handleResize, playingUri, videoTheaterMode]); useEffect(() => { handleResize(); @@ -270,7 +269,7 @@ export default function FileRenderFloating(props: Props) { return null; } - function handleDragStart(e, ui) { + function handleDragStart() { // Not really necessary, but reset just in case 'handleStop' didn't fire. setWasDragging(false); } @@ -286,7 +285,7 @@ export default function FileRenderFloating(props: Props) { }); } - function handleDragStop(e, ui) { + function handleDragStop(e) { if (wasDragging) { e.stopPropagation(); setWasDragging(false); diff --git a/ui/redux/selectors/content.js b/ui/redux/selectors/content.js index 208b9818b..736904f0b 100644 --- a/ui/redux/selectors/content.js +++ b/ui/redux/selectors/content.js @@ -34,14 +34,14 @@ export const makeSelectIsPlaying = (uri: string) => createSelector(selectPrimaryUri, (primaryUri) => primaryUri === uri); export const makeSelectIsPlayerFloating = (location: UrlLocation) => - createSelector(selectPrimaryUri, selectPlayingUri, selectClaimsByUri, (primaryUri, playingUri, claimsByUri) => { + createSelector(selectPrimaryUri, selectPlayingUri, (primaryUri, playingUri) => { const isInlineSecondaryPlayer = playingUri && playingUri.uri !== primaryUri && location.pathname === playingUri.pathname && (playingUri.source === 'comment' || playingUri.source === 'markdown'); - if ((playingUri && playingUri.uri === primaryUri) || isInlineSecondaryPlayer) { + if ((playingUri && playingUri.primaryUri === primaryUri) || isInlineSecondaryPlayer) { return false; } -- 2.45.2 From caa99e91f35d0934bd1cd19ca20ab2f84785a892 Mon Sep 17 00:00:00 2001 From: saltrafael Date: Mon, 13 Sep 2021 06:36:47 -0300 Subject: [PATCH 7/7] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b6272a75c..7970ae03a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Fix Paid embed warning overlay redirection button now links to odysee _community pr!_ ([#6819](https://github.com/lbryio/lbry-desktop/pull/6819)) - Fix comment section redirection to create channel _community pr!_ ([#6557](https://github.com/lbryio/lbry-desktop/pull/6557)) - Clicking on the title of a floating player will take you back to the list ([#6921](https://github.com/lbryio/lbry-desktop/pull/6921)) +- Fix floating player stopping on markdown or image files ([#7073](https://github.com/lbryio/lbry-desktop/pull/7073)) ## [0.51.1] - [2021-06-26] -- 2.45.2