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

Commit

Permalink
Merge remote-tracking branch 'origin/main' into gated-content-updates
Browse files Browse the repository at this point in the history
* origin/main:
  Manually set the libs state to prevent retry storm (#3753)
  Fix android announcement notifs (#3750)
  [PAY-1599] Fix font in Start Conversation prompt (#3748)
  [C-2851] Add privacy policy to settings page (#3741)
  [PAY-1595] Hide chat textinput until chat exists (#3746)
  [PAY-1597] Fix mobile chat screen empty state font (#3744)
  Bump Android again (#3745)
  Get the first storage node for o-auth not all of them (#3743)
  Bump app versions (#3742)
  Notification cursor reflects clickability (#3740)
  [C-2823] Improve autogenerated image logic (#3729)
  • Loading branch information
schottra committed Jul 17, 2023
2 parents b4854a1 + cd49430 commit 9700a7c
Show file tree
Hide file tree
Showing 47 changed files with 460 additions and 238 deletions.
7 changes: 7 additions & 0 deletions packages/common/src/context/appContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { createContext, useContext } from 'react'
import { StorageNodeSelectorService } from '@audius/sdk'

import { AnalyticsEvent, AllTrackingEvents } from 'models/Analytics'
import { AudiusBackend } from 'services/audius-backend'

type AppContextType = {
analytics: {
Expand All @@ -15,6 +16,12 @@ type AppContextType = {
}
}
storageNodeSelector?: StorageNodeSelectorService
imageUtils: {
generatePlaylistArtwork: (
imageUrls: string[]
) => Promise<{ url: string; file: File }>
}
audiusBackend: AudiusBackend
}

export const AppContext = createContext<AppContextType | null>(null)
Expand Down
1 change: 1 addition & 0 deletions packages/common/src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ export * from './useThrottledCallback'
export * from './useDebouncedCallback'
export * from './useSavedCollections'
export * from './chats'
export * from './useGeneratePlaylistArtwork'
53 changes: 53 additions & 0 deletions packages/common/src/hooks/useGeneratePlaylistArtwork.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { useCallback } from 'react'

import { useSelector } from 'react-redux'

import { ID } from 'models/Identifiers'
import { SquareSizes } from 'models/ImageSizes'
import { useAppContext } from 'src/context'
import { getCollection } from 'store/cache/collections/selectors'
import { getTrack } from 'store/cache/tracks/selectors'
import { CommonState } from 'store/index'
import { removeNullable } from 'utils/typeUtils'

export const useGeneratePlaylistArtwork = (collectionId: ID) => {
const collection = useSelector(
(state: CommonState) => getCollection(state, { id: collectionId })!
)

const collectionTracks = useSelector((state: CommonState) => {
const trackIds = collection.playlist_contents.track_ids.map(
({ track }) => track
)
const tracks = trackIds
.map((trackId) => getTrack(state, { id: trackId }))
.filter(removeNullable)
.slice(0, 4)

if (tracks.length < 4) {
return tracks.slice(0, 1)
}

return tracks
})

const { imageUtils, audiusBackend } = useAppContext()

return useCallback(async () => {
if (collectionTracks.length === 0) {
return { url: '', file: undefined }
}

const trackArtworkUrls = await Promise.all(
collectionTracks.map(async (track) => {
const { cover_art_sizes, cover_art } = track
return await audiusBackend.getImageUrl(
cover_art_sizes || cover_art,
SquareSizes.SIZE_1000_BY_1000
)
})
)

return await imageUtils.generatePlaylistArtwork(trackArtworkUrls)
}, [collectionTracks, audiusBackend, imageUtils])
}
3 changes: 2 additions & 1 deletion packages/common/src/models/Collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export type CollectionMetadata = {
has_current_user_saved: boolean
is_album: boolean
is_delete: boolean
is_image_autogenerated?: boolean
is_private: boolean
playlist_contents: {
track_ids: PlaylistTrackId[]
Expand Down Expand Up @@ -70,7 +71,7 @@ export type ComputedCollectionProperties = {
_cover_art_sizes: CoverArtSizes
_moved?: UID
_temp?: boolean
artwork?: { file?: File; url?: string }
artwork?: { file?: File; url?: string; source?: string; error?: string }
}

export type Collection = CollectionMetadata & ComputedCollectionProperties
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1924,6 +1924,11 @@ export class AudiusAPIClient {
// initialization state if needed before retrying
if (this.initializationState.type === 'manual') {
await this.waitForLibsInit()
this.initializationState = {
type: 'libs',
state: 'initialized',
endpoint: this.initializationState.endpoint
}
}
return this._getResponse(path, sanitizedParams, retry, pathType)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,6 @@ export const audiusBackend = ({
if (imagePreloader) {
try {
const preloaded = await imagePreloader(imageUrl)
console.log('we doing this actually?')
if (preloaded) {
return imageUrl
}
Expand Down
2 changes: 1 addition & 1 deletion packages/common/src/store/cache/collections/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export type Image = {
size?: number
fileType?: string
url: string
file?: string
file?: string | File
}

export type EditPlaylistValues = Collection & {
Expand Down
2 changes: 1 addition & 1 deletion packages/common/src/store/storeContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export type CommonStoreContext = {
openSeaClient: OpenSeaClient
audiusSdk: () => Promise<AudiusSdk>
imageUtils: {
createPlaylistArtwork: (
generatePlaylistArtwork: (
urls: string[]
) => Promise<{ file: File; url: string }>
}
Expand Down
6 changes: 3 additions & 3 deletions packages/mobile/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ android {
pickFirst 'lib/armeabi-v7a/libc++_shared.so'
pickFirst 'lib/arm64-v8a/libc++_shared.so'
}

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
Expand All @@ -132,13 +132,13 @@ android {
// versionCode is automatically incremented in CI
versionCode 1
// Make sure this is above the currently released Android version in the play store if your changes touch native code:
versionName "1.1.391"
versionName "1.1.393"
resValue "string", "build_config_package", "co.audius.app"
resValue 'string', "CODE_PUSH_APK_BUILD_TIME", String.format("\"%d\"", System.currentTimeMillis())
resConfigs "en"
}

productFlavors {
productFlavors {
prod {
resValue "string", "CodePushDeploymentKey", '"09yN4-3LHKp_GVKFJEOoDDRqx2o3fJirP5nZf"'
manifestPlaceholders = [
Expand Down
2 changes: 1 addition & 1 deletion packages/mobile/ios/AudiusReactNative/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.1.67</string>
<string>1.1.68</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
Expand Down
6 changes: 5 additions & 1 deletion packages/mobile/src/app/AppContextProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import { AppContext } from '@audius/common'
import { useAsync } from 'react-use'

import * as analytics from 'app/services/analytics'
import { audiusBackendInstance } from 'app/services/audius-backend-instance'
import { getStorageNodeSelector } from 'app/services/sdk/storageNodeSelector'
import { generatePlaylistArtwork } from 'app/utils/generatePlaylistArtwork'

type AppContextProviderProps = {
children: ReactNode
Expand All @@ -18,7 +20,9 @@ export const AppContextProvider = (props: AppContextProviderProps) => {
const value = useMemo(
() => ({
analytics,
storageNodeSelector
storageNodeSelector,
imageUtils: { generatePlaylistArtwork },
audiusBackend: audiusBackendInstance
}),
[storageNodeSelector]
)
Expand Down
59 changes: 45 additions & 14 deletions packages/mobile/src/components/fields/PickArtworkField.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useCallback, useMemo, useState } from 'react'
import { useCallback, useMemo } from 'react'

import { useField } from 'formik'
import { useGeneratePlaylistArtwork } from '@audius/common'
import { useField, useFormikContext } from 'formik'
import { capitalize } from 'lodash'
import { View } from 'react-native'
import type { Asset } from 'react-native-image-picker'
Expand Down Expand Up @@ -56,7 +57,10 @@ const useStyles = makeStyles(({ palette, spacing }) => ({

const messages = {
addArtwork: 'Add Artwork',
changeArtwork: 'Change Artwork'
changeArtwork: 'Change Artwork',
removeArtwork: 'Remove Artwork',
removingArtwork: 'Removing Artwork',
updatingArtwork: 'Updating Artwork'
}

type PickArtworkFieldProps = {
Expand All @@ -67,18 +71,21 @@ export const PickArtworkField = (props: PickArtworkFieldProps) => {
const { name } = props
const styles = useStyles()
const { neutralLight8 } = useThemeColors()
// const name = 'artwork'
const [{ value }, { error, touched }, { setValue }] = useField(name)
const [{ value }, { error, touched }, { setValue: setArtwork }] =
useField(name)
const [{ value: existingTrackArtwork }] = useField('trackArtwork')
const trackArtworkUrl = value?.url ?? existingTrackArtwork
const [{ value: collectionId }] = useField('playlist_id')
const [{ value: isImageAutogenerated }, , { setValue: setIsAutogenerated }] =
useField('is_image_autogenerated')

const { secondary } = useThemeColors()

const [isLoading, setIsLoading] = useState(false)
const { status, setStatus } = useFormikContext()

const handlePress = useCallback(() => {
const handleChangeArtwork = useCallback(() => {
const handleImageSelected = (_image: Image, rawResponse: Asset) => {
setValue({
setArtwork({
url: rawResponse.uri,
file: {
uri: rawResponse.uri,
Expand All @@ -87,23 +94,35 @@ export const PickArtworkField = (props: PickArtworkFieldProps) => {
},
source: 'original'
})
setIsLoading(true)
setIsAutogenerated(false)
setStatus({ imageLoading: true })
}
launchSelectImageActionSheet(handleImageSelected, secondary)
}, [secondary, setValue])
}, [secondary, setArtwork, setIsAutogenerated, setStatus])

const source = useMemo(() => ({ uri: trackArtworkUrl }), [trackArtworkUrl])

const generatePlaylistArtwork = useGeneratePlaylistArtwork(collectionId)

const handleRemoveArtwork = useCallback(async () => {
setStatus({ imageLoading: true, imageGenerating: true })
const { file, url } = await generatePlaylistArtwork()
setArtwork({ url, file })
setIsAutogenerated(true)
}, [setStatus, generatePlaylistArtwork, setArtwork, setIsAutogenerated])

return (
<View style={styles.root}>
<DynamicImage
source={source}
onLoad={() => setIsLoading(false)}
onLoad={() =>
setStatus({ imageLoading: false, imageGenerating: false })
}
style={styles.image}
noSkeleton
>
<View style={styles.iconPicture}>
{isLoading ? (
{status.imageLoading || status.imageGenerating ? (
<LoadingSpinner style={styles.loading} />
) : trackArtworkUrl ? null : (
<IconImage height={128} width={128} fill={neutralLight8} />
Expand All @@ -114,11 +133,23 @@ export const PickArtworkField = (props: PickArtworkFieldProps) => {
variant='secondaryAlt'
size='large'
title={
trackArtworkUrl ? messages.changeArtwork : messages.addArtwork
status.imageGenerating && isImageAutogenerated
? messages.updatingArtwork
: trackArtworkUrl && status.imageGenerating
? messages.removingArtwork
: trackArtworkUrl && !isImageAutogenerated
? messages.removeArtwork
: trackArtworkUrl
? messages.changeArtwork
: messages.addArtwork
}
icon={IconPencil}
iconPosition='left'
onPress={handlePress}
onPress={
trackArtworkUrl && !isImageAutogenerated
? handleRemoveArtwork
: handleChangeArtwork
}
/>
</View>
</DynamicImage>
Expand Down
32 changes: 1 addition & 31 deletions packages/mobile/src/hooks/useIsOfflineModeEnabled.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,7 @@
import { FeatureFlags } from '@audius/common'
import AsyncStorage from '@react-native-async-storage/async-storage'
import { useAsync } from 'react-use'

import { useFeatureFlag } from './useRemoteConfig'

const OFFLINE_OVERRIDE_ASYNC_STORAGE_KEY = 'offline_mode_release_local_override'

// DO NOT CHECK IN VALUE: true
const hardCodeOverride = false
let asyncOverride = false

export const toggleLocalOfflineModeOverride = () => {
asyncOverride = !asyncOverride
AsyncStorage.setItem(
OFFLINE_OVERRIDE_ASYNC_STORAGE_KEY,
asyncOverride.toString()
)
alert(`Offline mode ${asyncOverride ? 'enabled' : 'disabled'}`)
}

export const useReadOfflineOverride = () =>
useAsync(async () => {
try {
asyncOverride =
(await AsyncStorage.getItem(OFFLINE_OVERRIDE_ASYNC_STORAGE_KEY)) ===
'true'
} catch (e) {
console.log('error reading local offline mode override')
}
})

// TODO: remove helpers when feature is shipped
export const useIsOfflineModeEnabled = () =>
useFeatureFlag(FeatureFlags.OFFLINE_MODE_RELEASE).isEnabled ||
asyncOverride ||
hardCodeOverride
useFeatureFlag(FeatureFlags.OFFLINE_MODE_RELEASE).isEnabled
17 changes: 7 additions & 10 deletions packages/mobile/src/screens/chat-screen/ChatListScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { useCallback, useEffect } from 'react'

import { chatActions, chatSelectors, Status } from '@audius/common'
import { View, Text, TouchableOpacity } from 'react-native'
import { View, TouchableOpacity } from 'react-native'
import { useDispatch, useSelector } from 'react-redux'

import IconCompose from 'app/assets/images/iconCompose.svg'
import IconMessage from 'app/assets/images/iconMessage.svg'
import Button, { ButtonType } from 'app/components/button'
import { Screen, FlatList, ScreenContent } from 'app/components/core'
import { Text, Screen, FlatList, ScreenContent } from 'app/components/core'
import { useNavigation } from 'app/hooks/useNavigation'
import type { AppTabScreenParamList } from 'app/screens/app-screen'
import { makeStyles } from 'app/styles'
Expand Down Expand Up @@ -60,17 +60,12 @@ const useStyles = makeStyles(({ spacing, palette, typography }) => ({
padding: spacing(6)
},
startConversationTitle: {
fontSize: typography.fontSize.xxl,
fontFamily: typography.fontByWeight.bold,
textAlign: 'center',
lineHeight: typography.fontSize.xxl * 1.3,
color: palette.neutral
lineHeight: typography.fontSize.xxl * 1.3
},
connect: {
fontSize: typography.fontSize.medium,
textAlign: 'center',
lineHeight: typography.fontSize.medium * 1.3,
color: palette.neutral,
marginTop: spacing(2)
},
writeMessageButton: {
Expand All @@ -83,10 +78,12 @@ const ChatsEmpty = ({ onPress }: { onPress: () => void }) => {
const styles = useStyles()
return (
<View style={styles.startConversationContainer}>
<Text style={styles.startConversationTitle}>
<Text style={styles.startConversationTitle} fontSize='xxl' weight='bold'>
{messages.startConversation}
</Text>
<Text style={styles.connect}>{messages.connect}</Text>
<Text style={styles.connect} fontSize='medium'>
{messages.connect}
</Text>
<Button
title={messages.writeMessage}
renderIcon={() => <IconCompose fill={white} />}
Expand Down
Loading

0 comments on commit 9700a7c

Please sign in to comment.