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

Support opaque id routes #10

Merged
merged 8 commits into from
Aug 27, 2020
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 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 package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"glsl-noise": "0.0.0",
"glsl-random": "0.0.4",
"glslify-loader": "^1.0.2",
"hashids": "^2.2.1",
"hex-rgb": "^1.0.0",
"history": "^4.7.2",
"hls.js": "^0.13.2",
Expand Down
7 changes: 7 additions & 0 deletions src/__mocks__/Hashids.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const mockDecode = jest.fn()

jest.mock('hashids', () => {
return jest.fn().mockImplementation(() => {
return { decode: mockDecode }
})
})
20 changes: 19 additions & 1 deletion src/containers/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,10 @@ import {
FOLLOWING_USERS_ROUTE,
FOLLOWERS_USERS_ROUTE,
TRENDING_GENRES,
APP_REDIRECT
APP_REDIRECT,
TRACK_ID_PAGE,
USER_ID_PAGE,
PLAYLIST_ID_PAGE
} from 'utils/route'
import 'utils/redirect'
import { isMobile, getClient } from 'utils/clientUtil'
Expand Down Expand Up @@ -704,6 +707,20 @@ class App extends Component {
render={() => <CollectionPage type='album' />}
/>

{/* Hash id routes */}
<Route
exact
path={USER_ID_PAGE}
render={props => (
<ProfilePage
{...props}
containerRef={this.state.mainContent}
/>
)}
/>
<Route exact path={TRACK_ID_PAGE} component={TrackPage} />
<Route exact path={PLAYLIST_ID_PAGE} component={CollectionPage} />

<Route exact path={TRACK_PAGE} component={TrackPage} />

<Route
Expand Down Expand Up @@ -741,6 +758,7 @@ class App extends Component {
isMobile={isMobileClient}
component={FollowersPage}
/>

<Route
exact
path={PROFILE_PAGE}
Expand Down
84 changes: 35 additions & 49 deletions src/containers/collection-page/CollectionPageProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { connect } from 'react-redux'
import { withRouter, RouteComponentProps } from 'react-router-dom'
import { UnregisterCallback } from 'history'
import { push as pushRoute, replace } from 'connected-react-router'
import { matchPath } from 'react-router'
import { AppState, Status, Kind } from 'store/types'
import { Dispatch } from 'redux'

Expand All @@ -26,7 +25,9 @@ import {
FEED_PAGE,
REPOSTING_USERS_ROUTE,
FAVORITING_USERS_ROUTE,
fullPlaylistPage
fullPlaylistPage,
playlistPage,
albumPage
} from 'utils/route'
import { setRepost } from 'containers/reposts-page/store/actions'
import { RepostType } from 'containers/reposts-page/store/types'
Expand Down Expand Up @@ -77,6 +78,7 @@ import {
} from 'store/application/ui/userListModal/types'
import { SmartCollection } from 'models/Collection'
import DeletedPage from 'containers/deleted-page/DeletedPage'
import { parseCollectionRoute } from 'utils/route/collectionRouteParser'

type OwnProps = {
type: CollectionsPageType
Expand Down Expand Up @@ -143,7 +145,7 @@ class CollectionPage extends Component<

componentDidUpdate(prevProps: CollectionPageProps) {
const {
collection: { userUid, metadata, status },
collection: { userUid, metadata, status, user },
smartCollection,
tracks,
location: { pathname },
Expand All @@ -156,12 +158,12 @@ class CollectionPage extends Component<

const { updatingRoute, initialOrder } = this.state

const routeParams = this.getRouteParams(pathname)
if (!routeParams) return
const params = parseCollectionRoute(pathname)
if (!params) return
if (status === Status.ERROR) {
if (
routeParams &&
routeParams.id === this.state.playlistId &&
params &&
params.collectionId === this.state.playlistId &&
metadata?.playlist_owner_id !== this.props.userId
) {
// Only route to not found page if still on the collection page and
Expand Down Expand Up @@ -215,17 +217,25 @@ class CollectionPage extends Component<
const {
raymondjacobson marked this conversation as resolved.
Show resolved Hide resolved
collection: { metadata: prevMetadata }
} = prevProps
if (
metadata &&
prevMetadata &&
metadata.playlist_name !== prevMetadata.playlist_name
) {
const routeParams = this.getRouteParams(pathname)
if (routeParams) {
const { id, name } = routeParams
if (metadata) {
const params = parseCollectionRoute(pathname)
if (params) {
const { collectionId, title, collectionType, handle } = params
const newCollectionName = formatUrlName(metadata.playlist_name)
if (newCollectionName !== name && id === metadata.playlist_id) {
const newPath = pathname.replace(name, newCollectionName)

if ((!title || !handle || !collectionType) && user) {
raymondjacobson marked this conversation as resolved.
Show resolved Hide resolved
const newPath = metadata.is_album
? albumPage(user.handle, metadata.playlist_name, collectionId)
: playlistPage(user.handle, metadata.playlist_name, collectionId)
this.props.replaceRoute(newPath)
} else if (
prevMetadata &&
metadata.playlist_name !== prevMetadata.playlist_name &&
title &&
newCollectionName !== title &&
collectionId === metadata.playlist_id
) {
const newPath = pathname.replace(title, newCollectionName)
this.props.replaceRoute(newPath)
}
}
Expand Down Expand Up @@ -270,16 +280,17 @@ class CollectionPage extends Component<
}

fetchCollection = (pathname: string, forceFetch = false) => {
const routeParams = this.getRouteParams(pathname)
if (routeParams) {
const { id, handle } = routeParams
if (forceFetch || id !== this.state.playlistId) {
const params = parseCollectionRoute(pathname)
if (params) {
const { handle, collectionId } = params
if (forceFetch || collectionId !== this.state.playlistId) {
this.resetCollection()
this.setState({ playlistId: id as number })
this.props.fetchCollection(handle, id as number)
this.setState({ playlistId: collectionId as number })
this.props.fetchCollection(handle, collectionId as number)
this.props.fetchTracks()
}
}

if (
this.props.smartCollection &&
this.props.smartCollection.playlist_contents
Expand All @@ -288,31 +299,6 @@ class CollectionPage extends Component<
}
}

getRouteParams = (pathname: string) => {
const match = matchPath<{
handle: string
collectionType: string
name: string
}>(pathname, {
path: '/:handle/:collectionType/:name',
exact: true
})
if (
!match ||
(match.params.collectionType !== 'playlist' &&
match.params.collectionType !== 'album')
) {
return null
}
const collectionType = match.params.collectionType
const nameParts = match.params.name.split('-')
const handleEncoded = match.params.handle
const handle = decodeURIComponent(handleEncoded)
const name = nameParts.slice(0, -1).join('-')
const id = this.maybeParseInt(nameParts[nameParts.length - 1])
return { id, name, handle, collectionType }
}

resetCollection = () => {
const {
collection: { collectionUid, userUid }
Expand Down Expand Up @@ -806,7 +792,7 @@ function makeMapStateToProps() {

function mapDispatchToProps(dispatch: Dispatch) {
return {
fetchCollection: (handle: string, id: number) =>
fetchCollection: (handle: string | null, id: number) =>
dispatch(collectionActions.fetchCollection(handle, id)),
fetchTracks: () =>
dispatch(tracksActions.fetchLineupMetadatas(0, 200, false, undefined)),
Expand Down
19 changes: 12 additions & 7 deletions src/containers/collection-page/store/sagas.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,28 +15,33 @@ function* watchFetchCollection() {
const collectionId = action.id
const handle = action.handle

const user = yield call(fetchUserByHandle, handle)
if (!user) {
yield put(collectionActions.fetchCollectionFailed())
let user
if (handle) {
user = yield call(fetchUserByHandle, handle)
if (!user) {
yield put(collectionActions.fetchCollectionFailed())
}
}
const userUid = makeUid(Kind.USERS, user.user_id)

// Retrieve collections and fetch nested tracks
const { collections, uids: collectionUids } = yield call(
retrieveCollections,
user.user_id,
user?.user_id ?? null,
[collectionId],
true
)

if (Object.values(collections).length === 0) {
yield put(collectionActions.fetchCollectionFailed(userUid))
yield put(collectionActions.fetchCollectionFailed())
}
const collection = collections[collectionId]
const userUid = makeUid(Kind.USERS, collection.playlist_owner_id)
const collectionUid = collectionUids[collectionId]
if (collection) {
yield put(
cacheActions.subscribe(Kind.USERS, [{ uid: userUid, id: user.user_id }])
cacheActions.subscribe(Kind.USERS, [
{ uid: userUid, id: collection.playlist_owner_id }
])
)
yield put(
collectionActions.fetchCollectionSucceeded(
Expand Down
Loading