Compare commits

...

4 Commits

Author SHA1 Message Date
Ansh Nanda 582f8edf27 fix up store review after follows 2023-11-16 21:25:22 -08:00
Ansh Nanda e522f69b1e add store review prompt based on number of sessions 2023-11-16 15:02:22 -08:00
Ansh Nanda 6aa865ea41 Merge branch 'main' into store-reviews 2023-11-16 13:56:31 -08:00
Ansh Nanda 91b4fb03bb install expo-store-review and expo-linking 2023-11-16 13:56:16 -08:00
10 changed files with 142 additions and 0 deletions
+3
View File
@@ -37,6 +37,7 @@ module.exports = function () {
'Used for profile pictures, posts, and other kinds of content',
},
associatedDomains: ['applinks:bsky.app', 'applinks:staging.bsky.app'],
appStoreUrl: 'https://apps.apple.com/app/bluesky-social/id6444370199',
},
androidStatusBar: {
barStyle: 'dark-content',
@@ -63,6 +64,8 @@ module.exports = function () {
category: ['BROWSABLE', 'DEFAULT'],
},
],
playStoreUrl:
'https://play.google.com/store/apps/details?id=xyz.blueskyweb.app',
},
web: {
favicon: './assets/favicon.png',
+2
View File
@@ -97,12 +97,14 @@
"expo-image": "~1.3.2",
"expo-image-manipulator": "~11.5.0",
"expo-image-picker": "~14.5.0",
"expo-linking": "~5.0.2",
"expo-localization": "~14.3.0",
"expo-media-library": "~15.4.1",
"expo-notifications": "~0.20.1",
"expo-sharing": "~11.5.0",
"expo-splash-screen": "~0.20.5",
"expo-status-bar": "~1.6.0",
"expo-store-review": "~6.4.0",
"expo-system-ui": "~2.4.0",
"expo-updates": "~0.18.12",
"fast-text-encoding": "^1.0.6",
+6
View File
@@ -37,6 +37,7 @@ import * as persisted from '#/state/persisted'
import {i18n} from '@lingui/core'
import {I18nProvider} from '@lingui/react'
import {messages} from './locale/locales/en/messages'
import {listenSessionChangeForStoreReview} from './lib/store-review'
i18n.load('en', messages)
i18n.activate('en')
@@ -55,9 +56,14 @@ function InnerApp() {
listenSessionDropped(() => {
Toast.show('Sorry! Your session expired. Please log in again.')
})
const lForStoreReview = listenSessionChangeForStoreReview()
const account = persisted.get('session').currentAccount
resumeSession(account)
return () => {
lForStoreReview() // cleanup
}
}, [resumeSession])
// show nothing prior to init
+79
View File
@@ -0,0 +1,79 @@
import * as StoreReview from 'expo-store-review'
import * as persisted from '#/state/persisted'
import {AppState} from 'react-native'
import {isWeb} from '#/platform/detection'
import {logger} from '#/logger'
async function askForStoreReivew() {
if (isWeb) return
if (await StoreReview.hasAction()) {
await StoreReview.requestReview()
}
}
async function askForStoreReviewWithDelay() {
if (isWeb) return
const {lastPromptedAt, numSessions, numFollowed} =
persisted.get('storeReview')
const now = new Date()
const oneWeek = 1000 * 60 * 60 * 24 * 7
// don't prompt if we've already prompted in the last week
if (lastPromptedAt && now.getTime() - lastPromptedAt.getTime() < oneWeek) {
return
}
// prompt if user has had 100 sessions or followed 50 people
if (numSessions >= 100 || numFollowed >= 50) {
setTimeout(() => {
askForStoreReivew().then(() => {
persisted
.write('storeReview', {
completed: true,
lastPromptedAt: now,
numSessions: numSessions,
numFollowed: numFollowed,
})
.catch(e => {
logger.error('error writing store review', {error: String(e)})
})
})
}, 5000) // delay asking for 5 seconds
return
}
}
export async function incrementStoreReviewFollowed() {
if (isWeb) return
const {numFollowed, ...others} = persisted.get('storeReview')
await persisted.write('storeReview', {
numFollowed: numFollowed + 1,
...others,
})
askForStoreReviewWithDelay()
}
export async function incrementStoreReviewSessions() {
if (isWeb) return
const {numSessions, ...others} = persisted.get('storeReview')
await persisted.write('storeReview', {
numSessions: numSessions + 1,
...others,
})
askForStoreReviewWithDelay()
}
export function listenSessionChangeForStoreReview() {
// sets up AppState listener
const l = AppState.addEventListener('change', () => {
if (AppState.currentState === 'active') {
incrementStoreReviewSessions()
}
})
return () => {
l.remove()
}
}
+6
View File
@@ -106,6 +106,12 @@ export function transform(legacy: Partial<LegacySchema>): Schema {
onboarding: {
step: legacy.onboarding?.step || defaults.onboarding.step,
},
storeReview: {
completed: false,
lastPromptedAt: undefined,
numSessions: 0,
numFollowed: 0,
},
}
}
+12
View File
@@ -39,6 +39,12 @@ export const schema = z.object({
onboarding: z.object({
step: z.string(),
}),
storeReview: z.object({
lastPromptedAt: z.date().optional(),
completed: z.boolean(),
numSessions: z.number(),
numFollowed: z.number(),
}),
})
export type Schema = z.infer<typeof schema>
@@ -67,4 +73,10 @@ export const defaults: Schema = {
onboarding: {
step: 'Home',
},
storeReview: {
lastPromptedAt: undefined,
completed: false,
numSessions: 0,
numFollowed: 0,
},
}
+2
View File
@@ -8,6 +8,7 @@ import {
useProfileUnfollowMutation,
} from '#/state/queries/profile'
import {Shadow} from '#/state/cache/types'
import {incrementStoreReviewFollowed} from '#/lib/store-review'
export function FollowButton({
unfollowedType = 'inverted',
@@ -29,6 +30,7 @@ export function FollowButton({
}
try {
await followMutation.mutateAsync({did: profile.did})
incrementStoreReviewFollowed()
} catch (e: any) {
Toast.show(`An issue occurred, please try again.`)
}
+2
View File
@@ -54,6 +54,7 @@ import {s, colors} from 'lib/styles'
import {logger} from '#/logger'
import {useSession} from '#/state/session'
import {Shadow} from '#/state/cache/types'
import {incrementStoreReviewFollowed} from '#/lib/store-review'
interface Props {
profile: Shadow<AppBskyActorDefs.ProfileViewDetailed>
@@ -166,6 +167,7 @@ function ProfileHeaderLoaded({
profile.displayName || profile.handle,
)}`,
)
incrementStoreReviewFollowed()
} catch (e: any) {
logger.error('Failed to follow', {error: String(e)})
Toast.show(`There was an issue! ${e.toString()}`)
@@ -30,6 +30,7 @@ import {
useProfileFollowMutation,
useProfileUnfollowMutation,
} from '#/state/queries/profile'
import {incrementStoreReviewFollowed} from '#/lib/store-review'
const OUTER_PADDING = 10
const INNER_PADDING = 14
@@ -218,6 +219,7 @@ function SuggestedFollow({
try {
track('ProfileHeader:SuggestedFollowFollowed')
await followMutation.mutateAsync({did: profile.did})
incrementStoreReviewFollowed()
} catch (e: any) {
Toast.show('An issue occurred, please try again.')
}
+28
View File
@@ -5905,6 +5905,11 @@
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb"
integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==
"@types/qs@^6.9.7":
version "6.9.10"
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.10.tgz#0af26845b5067e1c9a622658a51f60a3934d51e8"
integrity sha512-3Gnx08Ns1sEoCrWssEgTSJs/rsT2vhGP+Ja9cnnk9k4ALxinORlQneLXFeFKOTJMOeZUFD1s7w+w2AphTpvzZw==
"@types/range-parser@*":
version "1.2.4"
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc"
@@ -9855,6 +9860,17 @@ expo-keep-awake@~12.3.0:
resolved "https://registry.yarnpkg.com/expo-keep-awake/-/expo-keep-awake-12.3.0.tgz#c42449ae19c993274ddc43aafa618792b6aec408"
integrity sha512-ujiJg1p9EdCOYS05jh5PtUrfiZnK0yyLy+UewzqrjUqIT8eAGMQbkfOn3C3fHE7AKd5AefSMzJnS3lYZcZYHDw==
expo-linking@~5.0.2:
version "5.0.2"
resolved "https://registry.yarnpkg.com/expo-linking/-/expo-linking-5.0.2.tgz#273c9dfec0c5542a13638bd422ef9acbf4638bc5"
integrity sha512-SPQus0+tYGx9c69Uw4wmdo3rkKX8vRT1vyJz/mvkpSlZN986s0NmP/V0M5vDv5Zv2qZzVdqJyuITFe0Pg5aI+A==
dependencies:
"@types/qs" "^6.9.7"
expo-constants "~14.4.2"
invariant "^2.2.4"
qs "^6.11.0"
url-parse "^1.5.9"
expo-localization@~14.3.0:
version "14.3.0"
resolved "https://registry.yarnpkg.com/expo-localization/-/expo-localization-14.3.0.tgz#a7614114079658000f46c7e3029703c8508e0678"
@@ -9936,6 +9952,11 @@ expo-status-bar@~1.6.0:
resolved "https://registry.yarnpkg.com/expo-status-bar/-/expo-status-bar-1.6.0.tgz#e79ffdb9a84d2e0ec9a0dc7392d9ab364fefa9cf"
integrity sha512-e//Oi2WPdomMlMDD3skE4+1ZarKCJ/suvcB4Jo/nO427niKug5oppcPNYO+csR6y3ZglGuypS+3pp/hJ+Xp6fQ==
expo-store-review@~6.4.0:
version "6.4.0"
resolved "https://registry.yarnpkg.com/expo-store-review/-/expo-store-review-6.4.0.tgz#2a74a025aa64a218f9f0b0a0fec0b3d2a99b6be2"
integrity sha512-aD06KSOO9syeecaP9NfJO++FzmfQjg49HY7qeUQ9r826YqswW/FPAcnXY0RJLhfJTqeAPRSl/xzPLZA5vwdqLQ==
expo-structured-headers@~3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/expo-structured-headers/-/expo-structured-headers-3.3.0.tgz#9f0b041a1d243a22a4a23d9eb19f02ace3c5258c"
@@ -16162,6 +16183,13 @@ qs@6.11.0:
dependencies:
side-channel "^1.0.4"
qs@^6.11.0:
version "6.11.2"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.2.tgz#64bea51f12c1f5da1bc01496f48ffcff7c69d7d9"
integrity sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==
dependencies:
side-channel "^1.0.4"
query-string@^7.1.3:
version "7.1.3"
resolved "https://registry.yarnpkg.com/query-string/-/query-string-7.1.3.tgz#a1cf90e994abb113a325804a972d98276fe02328"