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

Commit

Permalink
[C-1003] Native Account Sagas (#1890)
Browse files Browse the repository at this point in the history
* Split account sagas into mobile specific logic

* Fix type error

* Put back reachability code

* Address pr comments
  • Loading branch information
sliptype committed Sep 9, 2022
1 parent a0a202b commit bd9e726
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 124 deletions.
10 changes: 8 additions & 2 deletions packages/common/src/store/account/slice.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import { keyBy } from 'lodash'

import { User } from 'models'
import { Nullable } from 'utils/typeUtils'

import { ID } from '../../models/Identifiers'
Expand Down Expand Up @@ -138,7 +139,11 @@ const slice = createSlice({
showPushNotificationConfirmation: () => {},
resetAccount: () => {
return initialState
}
},
signedIn: (
_state,
_action: PayloadAction<{ account: User; isSignUp: boolean }>
) => {}
}
})

Expand All @@ -165,7 +170,8 @@ export const {
instagramLogin,
twitterLogin,
showPushNotificationConfirmation,
resetAccount
resetAccount,
signedIn
} = slice.actions

export const reducer = slice.reducer
Expand Down
79 changes: 79 additions & 0 deletions packages/mobile/src/store/account/sagas.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { accountActions, getContext } from '@audius/common'
import accountSagas from 'common/store/account/sagas'
import { updateProfileAsync } from 'common/store/profile/sagas'
import { takeEvery, call } from 'typed-redux-saga'
const { signedIn } = accountActions

export const RESET_REQUIRED_KEY = 'password-reset-required'
export const ENTROPY_KEY = 'hedgehog-entropy-key'
export const IS_MOBILE_USER_KEY = 'is-mobile-user'

// TODO
// Account recovery coming in following pr
// function* watchAccountRecovery() {
// yield takeEvery(
// MessageType.ACCOUNT_RECOVERY,
// function* ({ login, warning, email }: any) {
// let entropy: Nullable<string> = null
// let isSameAccount = false

// if (login) {
// entropy = atob(login)
// const oldEntropy = window.localStorage.getItem(ENTROPY_KEY)
// window.localStorage.setItem(ENTROPY_KEY, entropy ?? '')
// isSameAccount = oldEntropy === entropy
// }

// if (warning === 'RECOVERY_DO_NOT_SHARE' && email) {
// window.localStorage.setItem(RESET_REQUIRED_KEY, email)
// }

// // If it's not the same account,
// // reload webview to reload libs
// // with the new entropy
// if (!isSameAccount) {
// new ReloadMessage().send()
// } else {
// yield put(setNeedsAccountRecovery())
// }
// }
// )
// }

// When successfully signed in
function* onSignedIn({
payload: { account, isSignUp }
}: ReturnType<typeof signedIn>) {
const audiusBackendInstance = yield* getContext('audiusBackendInstance')
const localStorage = yield* getContext('localStorage')
const isMobileUser = yield* call(localStorage.getItem, IS_MOBILE_USER_KEY)
if (!isMobileUser || isMobileUser !== 'true') {
try {
// Legacy method to update whether a user has signed in on
// native mobile. Used in identity service for notification indexing
yield call(audiusBackendInstance.updateUserEvent, {
hasSignedInNativeMobile: true
})
// Updates the user metadata with an event `is_mobile_user` set to true
// if the account is being fetched from a mobile context
yield call(updateProfileAsync, {
metadata: { ...account, events: { is_mobile_user: true } }
})

yield call(localStorage.setItem, IS_MOBILE_USER_KEY, 'true')
} catch (e) {
console.error(e)
// Do nothing. A retry on the next session will suffice.
}
}
}

function* watchSignedIn() {
yield* takeEvery(signedIn.type, onSignedIn)
}

const sagas = () => {
return [...accountSagas(), watchSignedIn]
}

export default sagas
2 changes: 1 addition & 1 deletion packages/mobile/src/store/sagas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
vipDiscordModalSagas
} from '@audius/common'
import analyticsSagas from 'audius-client/src/common/store/analytics/sagas'
import accountSagas from 'common/store/account/sagas'
import addToPlaylistSagas from 'common/store/add-to-playlist/sagas'
import backendSagas, { setupBackend } from 'common/store/backend/sagas'
import collectionsSagas from 'common/store/cache/collections/sagas'
Expand Down Expand Up @@ -52,6 +51,7 @@ import topSupportersPageSagas from 'common/store/user-list/top-supporters/sagas'
import walletSagas from 'common/store/wallet/sagas'
import { all, fork } from 'typed-redux-saga'

import accountSagas from './account/sagas'
import initKeyboardEvents from './keyboard/sagas'
import notificationsSagas from './notifications/sagas'
import oauthSagas from './oauth/sagas'
Expand Down
86 changes: 0 additions & 86 deletions packages/web/src/common/store/account/mobileSagas.ts

This file was deleted.

23 changes: 10 additions & 13 deletions packages/web/src/common/store/account/sagas.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,8 @@ import { waitForBackendSetup } from 'common/store/backend/sagas'
import { retrieveCollections } from 'common/store/cache/collections/utils'
import { addPlaylistsNotInLibrary } from 'common/store/playlist-library/sagas'
import { updateProfileAsync } from 'common/store/profile/sagas'
import { SignedIn } from 'services/native-mobile-interface/lifecycle'

import disconnectedWallets from './disconnected_wallet_fix.json'
import mobileSagas, { setHasSignedInOnMobile } from './mobileSagas'

const { getFeePayer } = solanaSelectors
const { fetchProfile } = profilePageActions
Expand All @@ -42,6 +40,7 @@ const {
} = accountSelectors

const {
signedIn,
unsubscribeBrowserPushNotifications,
showPushNotificationConfirmation,
fetchAccountSucceeded,
Expand All @@ -54,8 +53,6 @@ const {
addAccountPlaylist
} = accountActions

const NATIVE_MOBILE = process.env.REACT_APP_NATIVE_MOBILE

const IP_STORAGE_KEY = 'user-ip-timestamp'

/**
Expand Down Expand Up @@ -98,7 +95,7 @@ function* recordIPIfNotRecent(handle) {

// Tasks to be run on account successfully fetched, e.g.
// recording metrics, setting user data
function* onFetchAccount(account, isSignUp = false) {
function* onSignedIn({ payload: { account, isSignUp = false } }) {
const audiusBackendInstance = yield getContext('audiusBackendInstance')
const analytics = yield getContext('analytics')
const sentry = yield getContext('sentry')
Expand All @@ -115,10 +112,6 @@ function* onFetchAccount(account, isSignUp = false) {
yield put(showPushNotificationConfirmation())

yield fork(audiusBackendInstance.updateUserLocationTimezone)
if (NATIVE_MOBILE) {
yield fork(setHasSignedInOnMobile, account)
new SignedIn(account).send()
}

// Fetch the profile so we get everything we need to populate
// the left nav / other site-wide metadata.
Expand Down Expand Up @@ -249,9 +242,9 @@ export function* fetchAccountAsync({ fromSource = false, isSignUp = false }) {

yield call(recordIPIfNotRecent, account.handle)

// Cache the account and fire the onFetch callback. We're done.
// Cache the account and put the signedIn action. We're done.
yield call(cacheAccount, account)
yield call(onFetchAccount, account, isSignUp)
yield put(signedIn({ account, isSignUp }))
}

function* cacheAccount(account) {
Expand Down Expand Up @@ -379,6 +372,10 @@ function* watchFetchAccount() {
yield takeEvery(fetchAccount.type, fetchAccountAsync)
}

function* watchSignedIn() {
yield takeEvery(signedIn.type, onSignedIn)
}

function* watchTwitterLogin() {
yield takeEvery(twitterLogin.type, associateTwitterAccount)
}
Expand All @@ -400,13 +397,13 @@ function* watchAddAccountPlaylist() {
}

export default function sagas() {
const sagas = [
return [
watchFetchAccount,
watchSignedIn,
watchTwitterLogin,
watchInstagramLogin,
watchFetchSavedAlbums,
watchFetchSavedPlaylists,
watchAddAccountPlaylist
]
return NATIVE_MOBILE ? sagas.concat(mobileSagas()) : sagas
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { Modal } from '@audius/stems'
import { connect } from 'react-redux'
import { Dispatch } from 'redux'

import { RESET_REQUIRED_KEY } from 'common/store/account/mobileSagas'
import EnterPassword from 'components/sign-on/EnterPassword'
import { AppState } from 'store/types'
import { isMobile } from 'utils/clientUtil'
Expand All @@ -15,6 +14,8 @@ import { changePassword } from './store/actions'
import { getStatus } from './store/selectors'
const { getNeedsAccountRecovery } = accountSelectors

const RESET_REQUIRED_KEY = 'password-reset-required'

const messages = {
title: 'Reset Your Password',
continueLabel: 'Submit',
Expand Down
14 changes: 0 additions & 14 deletions packages/web/src/services/native-mobile-interface/lifecycle.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { User } from '@audius/common'

import { NativeMobileMessage } from './helpers'
import { MessageType } from './types'

Expand All @@ -8,15 +6,3 @@ export class RequestNetworkConnected extends NativeMobileMessage {
super(MessageType.REQUEST_NETWORK_CONNECTED, {})
}
}

export class SignedIn extends NativeMobileMessage {
constructor(account: User) {
super(MessageType.SIGNED_IN, { account })
}
}

export class FetchAccountFailed extends NativeMobileMessage {
constructor() {
super(MessageType.FETCH_ACCOUNT_FAILED)
}
}
8 changes: 1 addition & 7 deletions packages/web/src/store/sign-out/signOut.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { AudiusBackend, LocalStorage } from '@audius/common'

import { IS_MOBILE_USER_KEY } from 'common/store/account/mobileSagas'
import { removeHasRequestedBrowserPermission } from 'utils/browserNotifications'

import { clearTheme } from '../../utils/theme/theme'
Expand All @@ -10,12 +9,7 @@ const AUDIUS_USE_METAMASK = 'useMetaMask'
const BADGE_LOCAL_STORAGE_KEY = 'last_badge_tier'

const removeLocalStorageItems = async (localStorage: LocalStorage) => {
const items = [
AUDIUS_EVENTS,
AUDIUS_USE_METAMASK,
BADGE_LOCAL_STORAGE_KEY,
IS_MOBILE_USER_KEY
]
const items = [AUDIUS_EVENTS, AUDIUS_USE_METAMASK, BADGE_LOCAL_STORAGE_KEY]
return await Promise.all(items.map((k) => localStorage.removeItem(k)))
}

Expand Down

0 comments on commit bd9e726

Please sign in to comment.