Skip to content

Commit

Permalink
[C-4316, C-4317] SSR work to render webplayer and track page for web (#…
Browse files Browse the repository at this point in the history
…8268)

Co-authored-by: sliptype <sliptype@gmail.com>
  • Loading branch information
Kyle-Shanks and sliptype committed Apr 30, 2024
1 parent 7417a40 commit 909db7c
Show file tree
Hide file tree
Showing 55 changed files with 1,748 additions and 95 deletions.
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"./schemas": "./src/schemas/index.ts",
"./services": "./src/services/index.ts",
"./store": "./src/store/index.ts",
"./serverStore": "./src/serverStore/index.ts",
"./utils": "./src/utils/index.ts"
},
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion packages/common/src/api/library.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { full } from '@audius/sdk'
import { AudiusQueryContextType, createApi } from '~/audius-query'
import { UserCollectionMetadata } from '~/models/Collection'
import { Kind } from '~/models/Kind'
import { makeActivity } from '~/services/audius-api-client/ResponseAdapter'
import { makeActivity } from '~/services/audius-api-client'
import { APIActivityV2 } from '~/services/audius-api-client/types'
import { encodeHashId } from '~/utils/hashIds'
import { removeNullable } from '~/utils/typeUtils'
Expand Down
8 changes: 2 additions & 6 deletions packages/common/src/hooks/useGatedContent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,8 @@ import { getAccountUser } from '~/store/account/selectors'
import { cacheTracksSelectors, cacheUsersSelectors } from '~/store/cache'
import { gatedContentSelectors } from '~/store/gated-content'
import { CommonState } from '~/store/reducers'
import {
Nullable,
isContentCollection,
isContentTrack,
removeNullable
} from '~/utils'
import { isContentCollection, isContentTrack } from '~/utils/contentTypeUtils'
import { Nullable, removeNullable } from '~/utils/typeUtils'

const { getTrack } = cacheTracksSelectors
const { getUser, getUsers } = cacheUsersSelectors
Expand Down
11 changes: 7 additions & 4 deletions packages/common/src/models/SsrPageProps.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { full as FullSdk } from '@audius/sdk'
// import type { full as FullSdk } from '@audius/sdk'

export type SsrPageProps = {
track?: FullSdk.TrackFull
user?: FullSdk.UserFull
collection?: FullSdk.PlaylistFull
// track?: FullSdk.TrackFull
// user?: FullSdk.UserFull
// collection?: FullSdk.PlaylistFull
track?: any
user?: any
collection?: any
error?: { isErrorPageOpen: boolean }
}
1 change: 1 addition & 0 deletions packages/common/src/serverStore/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './serverReducers'
48 changes: 48 additions & 0 deletions packages/common/src/serverStore/serverReducers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { History } from 'history'
import { combineReducers } from 'redux'
import type { Storage } from 'redux-persist'

import account from '~/store/account/slice'
import collectionsReducer from '~/store/cache/collections/reducer'
import { asCache } from '~/store/cache/reducer'
import tracksReducer from '~/store/cache/tracks/reducer'
import usersReducer from '~/store/cache/users/reducer'
// import collection from '~/store/pages/collection/reducer'
// import profileReducer from '~/store/pages/profile/reducer'
import track from '~/store/pages/track/reducer'
import theme from '~/store/ui/theme/slice'

import { Kind, SsrPageProps } from '../models'

/**
* A function that creates common reducers.
* @returns an object of all reducers to be used with `combineReducers`
*/
export const serverReducers = (
_storage: Storage,
ssrPageProps?: SsrPageProps,
_isServerSide?: boolean,
_history?: History
) => ({
account,

// Cache
// @ts-ignore
collections: asCache(collectionsReducer(ssrPageProps), Kind.COLLECTIONS),
// @ts-ignore
tracks: asCache(tracksReducer(ssrPageProps), Kind.TRACKS),
// @ts-ignore
users: asCache(usersReducer(ssrPageProps), Kind.USERS),

// UI
ui: combineReducers({
theme
}),

// Pages
pages: combineReducers({
// collection: collection(ssrPageProps),
// profile: profileReducer(ssrPageProps),
track: track(ssrPageProps)
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { IntKeys, StringKeys, RemoteConfigInstance } from '../remote-config'

import * as adapter from './ResponseAdapter'
import { processSearchResults } from './helper'
import { makeActivity } from './makeActivity'
import {
APIActivity,
APIBlockConfirmation,
Expand Down Expand Up @@ -1239,9 +1240,7 @@ export class AudiusAPIClient {

if (!response) return []

const adapted = response.data
.map(adapter.makeActivity)
.filter(removeNullable)
const adapted = response.data.map(makeActivity).filter(removeNullable)
return adapted
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { full } from '@audius/sdk'

import dayjs from '~/utils/dayjs'

import {
Expand All @@ -19,7 +17,6 @@ import { decodeHashId } from '../../utils/hashIds'
import { removeNullable } from '../../utils/typeUtils'

import {
APIActivity,
APIFavorite,
APIRemix,
APIRepost,
Expand All @@ -32,9 +29,7 @@ import {
APISearch,
APISearchTrack,
APISearchAutocomplete,
APISearchPlaylist,
APIActivityV2,
isApiActivityV2
APISearchPlaylist
} from './types'

export const makeUser = (
Expand Down Expand Up @@ -401,30 +396,6 @@ export const makePlaylist = (
return marshalled as unknown as UserCollectionMetadata
}

export const makeActivity = (
activity: APIActivity | APIActivityV2
): UserTrackMetadata | UserCollectionMetadata | undefined => {
if (isApiActivityV2(activity)) {
if (!activity.item) {
return undefined
}
if (activity.itemType === 'track') {
return makeTrack(full.TrackFullToJSON(activity.item as full.TrackFull))
} else if (activity.itemType === 'playlist') {
return makePlaylist(
full.PlaylistFullWithoutTracksToJSON(
activity.item as full.PlaylistFullWithoutTracks
)
)
}
return undefined
} else {
return activity.item_type === 'track'
? makeTrack(activity.item)
: makePlaylist(activity.item)
}
}

export const makeStemTrack = (stem: APIStem): StemTrackMetadata | undefined => {
const [id, parentId, ownerId] = [stem.id, stem.parent_id, stem.user_id].map(
decodeHashId
Expand Down
1 change: 1 addition & 0 deletions packages/common/src/services/audius-api-client/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './AudiusAPIClient'
export * as responseAdapter from './ResponseAdapter'
export { makeActivity } from './makeActivity'
export * from './types'
30 changes: 30 additions & 0 deletions packages/common/src/services/audius-api-client/makeActivity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { full } from '@audius/sdk'

import { UserTrackMetadata, UserCollectionMetadata } from '~/models'

import { makePlaylist, makeTrack } from './ResponseAdapter'
import { APIActivity, APIActivityV2, isApiActivityV2 } from './types'

export const makeActivity = (
activity: APIActivity | APIActivityV2
): UserTrackMetadata | UserCollectionMetadata | undefined => {
if (isApiActivityV2(activity)) {
if (!activity.item) {
return undefined
}
if (activity.itemType === 'track') {
return makeTrack(full.TrackFullToJSON(activity.item as full.TrackFull))
} else if (activity.itemType === 'playlist') {
return makePlaylist(
full.PlaylistFullWithoutTracksToJSON(
activity.item as full.PlaylistFullWithoutTracks
)
)
}
return undefined
} else {
return activity.item_type === 'track'
? makeTrack(activity.item)
: makePlaylist(activity.item)
}
}
5 changes: 3 additions & 2 deletions packages/common/src/services/explore/Explore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ import {
APIPlaylist,
APITrack,
AudiusAPIClient,
responseAdapter
responseAdapter,
makeActivity
} from '../audius-api-client'
import { AudiusBackend, AuthHeaders } from '../audius-backend'

Expand Down Expand Up @@ -110,7 +111,7 @@ export class Explore {
})
const activityData = history.data as APIActivityV2[]
const listenedToTracks = activityData
.map(responseAdapter.makeActivity)
.map(makeActivity)
.filter(removeNullable) as UserTrackMetadata[]

// Imperfect solution. Ideally we use an endpoint that gives us true/false
Expand Down
2 changes: 1 addition & 1 deletion packages/common/src/store/cache/collections/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import snakecaseKeys from 'snakecase-keys'

import { makePlaylist } from '~/services/audius-api-client/ResponseAdapter'
import { initialCacheState } from '~/store/cache/reducer'
import { makeUid } from '~/utils'
import { makeUid } from '~/utils/uid'

import {
Collection,
Expand Down
8 changes: 4 additions & 4 deletions packages/common/src/utils/timeUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ const MINUTES_PER_HOUR = 60
const SECONDS_PER_HOUR = SECONDS_PER_MINUTE * MINUTES_PER_HOUR
dayjs.extend(advancedFormat)

export const formatDateWithTimezoneOffset = (date: string): string => {
return dayjs.utc(date).local().format('M/D/YY')
}

export const formatSeconds = (seconds: number): string => {
const time = dayjs.duration(seconds, 'seconds')
if (seconds >= SECONDS_PER_HOUR) {
Expand Down Expand Up @@ -53,10 +57,6 @@ export const formatDate = (date: string, format?: string): string => {
return dayjs(date).format(dayjsFormat)
}

export const formatDateWithTimezoneOffset = (date: string): string => {
return dayjs.utc(date).local().format('M/D/YY')
}

export const utcToLocalTime = (date: string) => {
return dayjs.utc(date).local()
}
Expand Down
3 changes: 2 additions & 1 deletion packages/libs/src/sdk/services/EntityManager/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { EntityManager } from './EntityManager'
export { EntityManagerService, Action as EntityManagerAction } from './types'
export type { EntityManagerService } from './types'
export { Action as EntityManagerAction } from './types'
2 changes: 1 addition & 1 deletion packages/libs/src/sdk/services/Storage/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export { Storage } from './Storage'
export { StorageService } from './types'
export type { StorageService } from './types'
1 change: 1 addition & 0 deletions packages/libs/src/sdk/utils/web3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type Web3Type from 'web3'

declare global {
interface Window {
// @ts-ignore
Web3: Web3
}
}
Expand Down
1 change: 1 addition & 0 deletions packages/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@
"client-zip": "2.4.4",
"connected-react-router": "6.9.3",
"cross-fetch": "^4.0.0",
"dayjs": "1.10.7",
"electron-log": "5.0.3",
"electron-updater": "6.1.7",
"exif-parser": "0.1.12",
Expand Down
63 changes: 63 additions & 0 deletions packages/web/src/app/ServerReduxProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { ReactNode, useRef } from 'react'

import { Provider } from 'react-redux'
import { Persistor, persistStore } from 'redux-persist'
import { PersistGate } from 'redux-persist/integration/react'
import { PartialDeep } from 'type-fest'

import { useIsMobile } from 'hooks/useIsMobile'
import { configureStore } from 'store/configureServerStore'
import { AppState } from 'store/types'
import logger from 'utils/logger'

import { useSsrContext } from '../ssr/SsrContext'

import { useHistoryContext } from './HistoryProvider'

export const ServerReduxProvider = ({
children,
initialStoreState
}: {
children: ReactNode
// Sets up an initial store state
initialStoreState?: PartialDeep<AppState>
}) => {
const { pageProps, isServerSide } = useSsrContext()
const { history } = useHistoryContext()
const isMobile = useIsMobile()

const storeRef = useRef<ReturnType<typeof configureStore>>()
const persistorRef = useRef<Persistor>()

if (!storeRef.current) {
const store = configureStore(
history,
isMobile,
pageProps,
isServerSide,
initialStoreState
)
storeRef.current = store
const persistor = persistStore(store)
persistorRef.current = persistor

// Mount store to window for easy access
if (typeof window !== 'undefined') {
// @ts-ignore
window.store = store
}

// Set up logger on store
if (!isServerSide) {
logger(store)
}
}

return (
<Provider store={storeRef.current}>
<PersistGate loading={null} persistor={persistorRef.current!}>
{() => children}
</PersistGate>
</Provider>
)
}
11 changes: 9 additions & 2 deletions packages/web/src/app/ThemeProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import { ReactNode } from 'react'

import { Theme, SystemAppearance } from '@audius/common/models'
import { themeSelectors } from '@audius/common/store'
import { ThemeProvider as HarmonyThemeProvider } from '@audius/harmony'

import { AppState } from 'store/types'
import { useSelector } from 'utils/reducer'

const { getTheme, getSystemAppearance } = themeSelectors
const getBaseState = (state: AppState) => state.ui.theme

const getTheme = (state: AppState) => {
return getBaseState(state).theme
}

const getSystemAppearance = (state: AppState) => {
return getBaseState(state).systemAppearance
}

const selectHarmonyTheme = (state: AppState) => {
const theme = getTheme(state)
Expand Down

0 comments on commit 909db7c

Please sign in to comment.