Skip to content
This repository has been archived by the owner on Oct 4, 2023. It is now read-only.

Commit

Permalink
[C-2113 C-2114] Add useThrottledCallback, fix indicators (#2835)
Browse files Browse the repository at this point in the history
  • Loading branch information
dylanjeffers authored Feb 13, 2023
1 parent 1a48846 commit 30d0a21
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export const DownloadStatusIndicator = (
const renderIndicator = () => {
// If we are offline, display as download succeeded
// since we only show the user successfully downloaded things.
if (!isReachable) {
if (!isReachable && status !== OfflineDownloadStatus.INACTIVE) {
return (
<IconDownloaded
fill={styles.iconDownloaded.fill}
Expand Down
18 changes: 0 additions & 18 deletions packages/mobile/src/hooks/useDebouncedCallback.ts

This file was deleted.

13 changes: 13 additions & 0 deletions packages/mobile/src/hooks/useThrottledCallback.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { DependencyList } from 'react'
import { useMemo } from 'react'

import { throttle } from 'lodash'

export const useThrottledCallback = <T extends (...args: any) => any>(
callback: T,
wait: number,
deps: DependencyList
) => {
// eslint-disable-next-line react-hooks/exhaustive-deps
return useMemo(() => throttle(callback, wait), [wait, ...deps])
}
58 changes: 22 additions & 36 deletions packages/mobile/src/screens/collection-screen/CollectionHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback, useEffect, useState } from 'react'
import { useLayoutEffect, useState } from 'react'

import type { Collection, SmartCollectionVariant } from '@audius/common'
import {
Expand All @@ -13,11 +13,10 @@ import { useSelector, useDispatch } from 'react-redux'
import { Switch, Text } from 'app/components/core'
import { getCollectionDownloadStatus } from 'app/components/offline-downloads/CollectionDownloadStatusIndicator'
import { DownloadStatusIndicator } from 'app/components/offline-downloads/DownloadStatusIndicator'
import { useDebouncedCallback } from 'app/hooks/useDebouncedCallback'
import { useIsOfflineModeEnabled } from 'app/hooks/useIsOfflineModeEnabled'
import { useProxySelector } from 'app/hooks/useProxySelector'
import { useThrottledCallback } from 'app/hooks/useThrottledCallback'
import { DOWNLOAD_REASON_FAVORITES } from 'app/services/offline-downloader'
import { getVisibility } from 'app/store/drawers/selectors'
import { setVisibility } from 'app/store/drawers/slice'
import { getIsCollectionMarkedForDownload } from 'app/store/offline-downloads/selectors'
import {
Expand Down Expand Up @@ -135,16 +134,19 @@ const OfflineCollectionHeader = (props: OfflineCollectionHeaderProps) => {
const { collection, headerText } = props
const { playlist_id } = collection
const dispatch = useDispatch()
const isReachable = useSelector(getIsReachable)
const currentUserId = useSelector(getUserId)

const isMarkedForDownload = useSelector(
getIsCollectionMarkedForDownload(playlist_id)
const isMarkedForDownload = useSelector((state) =>
Boolean(getCollectionDownloadStatus(state, playlist_id))
)

const isFavoritesToggleOn = useSelector(
getIsCollectionMarkedForDownload(DOWNLOAD_REASON_FAVORITES)
)
const isSwitchDisabled = useSelector((state) => {
const isReachable = getIsReachable(state)
const isFavoritesMarkedForDownload = getIsCollectionMarkedForDownload(
DOWNLOAD_REASON_FAVORITES
)(state)
return isFavoritesMarkedForDownload || !isReachable
})

const downloadStatus = useProxySelector(
(state) => {
Expand All @@ -157,28 +159,23 @@ const OfflineCollectionHeader = (props: OfflineCollectionHeaderProps) => {
const [downloadSwitchValue, setDownloadSwitchValue] =
useState(isMarkedForDownload)

const removeDrawerVisibility = useSelector(
getVisibility('RemoveDownloadedCollection')
)

const showDownloadSwitchAndIndicator =
downloadStatus ||
collection.has_current_user_saved ||
collection.playlist_owner_id === currentUserId

useEffect(() => {
if (
removeDrawerVisibility !== true &&
isMarkedForDownload !== downloadSwitchValue
) {
setDownloadSwitchValue(isMarkedForDownload)
// When user confirms removal, turn switch off
useLayoutEffect(() => {
if (!isMarkedForDownload) {
setDownloadSwitchValue(false)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isMarkedForDownload, removeDrawerVisibility])
}, [isMarkedForDownload])

const handleToggleDownload = useCallback(
const handleDownloadSwitchValueChange = useThrottledCallback(
(isDownloadEnabled: boolean) => {
if (isDownloadEnabled) {
dispatch(requestDownloadCollection({ collectionId: playlist_id }))
setDownloadSwitchValue(true)
} else {
dispatch(
setVisibility({
Expand All @@ -189,19 +186,10 @@ const OfflineCollectionHeader = (props: OfflineCollectionHeaderProps) => {
)
}
},
800,
[dispatch, playlist_id]
)

const debouncedHandleToggleDownload = useDebouncedCallback(
handleToggleDownload,
800
)

const handleDownloadSwitchChange = (isEnabled: boolean) => {
setDownloadSwitchValue(isEnabled)
debouncedHandleToggleDownload(isEnabled)
}

const getTextColor = () => {
if (
downloadStatus === OfflineDownloadStatus.LOADING ||
Expand Down Expand Up @@ -237,10 +225,8 @@ const OfflineCollectionHeader = (props: OfflineCollectionHeaderProps) => {
{showDownloadSwitchAndIndicator ? (
<Switch
value={downloadSwitchValue}
onValueChange={handleDownloadSwitchChange}
disabled={
isFavoritesToggleOn || (!isReachable && !isMarkedForDownload)
}
onValueChange={handleDownloadSwitchValueChange}
disabled={isSwitchDisabled}
/>
) : null}
</View>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { useCallback, useLayoutEffect, useState } from 'react'
import { useLayoutEffect, useState } from 'react'

import { reachabilitySelectors } from '@audius/common'
import type { SwitchProps } from 'react-native'
import { useDispatch, useSelector } from 'react-redux'

import { Switch } from 'app/components/core'
import { useThrottledCallback } from 'app/hooks/useThrottledCallback'
import { DOWNLOAD_REASON_FAVORITES } from 'app/services/offline-downloader'
import { setVisibility } from 'app/store/drawers/slice'
import { getCollectionDownloadStatus } from 'app/store/offline-downloads/selectors'
Expand All @@ -22,11 +23,7 @@ export const DownloadFavoritesSwitch = (

const isSwitchDisabled = useSelector((state) => {
const isReachable = getIsReachable(state)
const isMarkedForDownload = getCollectionDownloadStatus(
state,
DOWNLOAD_REASON_FAVORITES
)
return Boolean(!isReachable && isMarkedForDownload)
return !isReachable
})

const isMarkedForDownload = useSelector((state) =>
Expand All @@ -35,7 +32,7 @@ export const DownloadFavoritesSwitch = (

const [value, setValue] = useState(isMarkedForDownload)

const handleValueChange = useCallback(
const handleValueChange = useThrottledCallback(
(newValue: boolean) => {
if (newValue) {
dispatch(requestDownloadAllFavorites())
Expand All @@ -50,6 +47,7 @@ export const DownloadFavoritesSwitch = (
)
}
},
800,
[dispatch, onValueChange]
)

Expand All @@ -62,13 +60,11 @@ export const DownloadFavoritesSwitch = (
}, [isMarkedForDownload, onValueChange])

return (
<>
<Switch
value={value}
onValueChange={handleValueChange}
disabled={isSwitchDisabled}
{...other}
/>
</>
<Switch
value={value}
onValueChange={handleValueChange}
disabled={isSwitchDisabled}
{...other}
/>
)
}
13 changes: 0 additions & 13 deletions packages/web/src/types/react/useCallback.d.ts

This file was deleted.

0 comments on commit 30d0a21

Please sign in to comment.