Fix invite codes flash on desktop, use loading placeholder (#1591)
* Fix invite codes flashing untrue value before loaded * Add loading placeholder for right nav inviteszio/stable
parent
2ba0c6a711
commit
9278822088
|
@ -25,13 +25,13 @@ export class MeModel {
|
||||||
savedFeeds: SavedFeedsModel
|
savedFeeds: SavedFeedsModel
|
||||||
notifications: NotificationsFeedModel
|
notifications: NotificationsFeedModel
|
||||||
follows: MyFollowsCache
|
follows: MyFollowsCache
|
||||||
invites: ComAtprotoServerDefs.InviteCode[] = []
|
invites: ComAtprotoServerDefs.InviteCode[] | null = []
|
||||||
appPasswords: ComAtprotoServerListAppPasswords.AppPassword[] = []
|
appPasswords: ComAtprotoServerListAppPasswords.AppPassword[] = []
|
||||||
lastProfileStateUpdate = Date.now()
|
lastProfileStateUpdate = Date.now()
|
||||||
lastNotifsUpdate = Date.now()
|
lastNotifsUpdate = Date.now()
|
||||||
|
|
||||||
get invitesAvailable() {
|
get invitesAvailable() {
|
||||||
return this.invites.filter(isInviteAvailable).length
|
return this.invites?.filter(isInviteAvailable).length || null
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(public rootStore: RootStoreModel) {
|
constructor(public rootStore: RootStoreModel) {
|
||||||
|
@ -180,7 +180,9 @@ export class MeModel {
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.rootStore.log.error('Failed to fetch user invite codes', e)
|
this.rootStore.log.error('Failed to fetch user invite codes', e)
|
||||||
}
|
}
|
||||||
await this.rootStore.invitedUsers.fetch(this.invites)
|
if (this.invites) {
|
||||||
|
await this.rootStore.invitedUsers.fetch(this.invites)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,33 @@ export function Component({}: {}) {
|
||||||
store.shell.closeModal()
|
store.shell.closeModal()
|
||||||
}, [store])
|
}, [store])
|
||||||
|
|
||||||
|
if (store.me.invites === null) {
|
||||||
|
return (
|
||||||
|
<View style={[styles.container, pal.view]} testID="inviteCodesModal">
|
||||||
|
<Text type="title-xl" style={[styles.title, pal.text]}>
|
||||||
|
Error
|
||||||
|
</Text>
|
||||||
|
<Text type="lg" style={[styles.description, pal.text]}>
|
||||||
|
An error occurred while loading invite codes.
|
||||||
|
</Text>
|
||||||
|
<View style={styles.flex1} />
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
styles.btnContainer,
|
||||||
|
isTabletOrDesktop && styles.btnContainerDesktop,
|
||||||
|
]}>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
label="Done"
|
||||||
|
style={styles.btn}
|
||||||
|
labelStyle={styles.btnLabel}
|
||||||
|
onPress={onClose}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if (store.me.invites.length === 0) {
|
if (store.me.invites.length === 0) {
|
||||||
return (
|
return (
|
||||||
<View style={[styles.container, pal.view]} testID="inviteCodesModal">
|
<View style={[styles.container, pal.view]} testID="inviteCodesModal">
|
||||||
|
|
|
@ -322,37 +322,45 @@ export const SettingsScreen = withAuthRequired(
|
||||||
|
|
||||||
<View style={styles.spacer20} />
|
<View style={styles.spacer20} />
|
||||||
|
|
||||||
<Text type="xl-bold" style={[pal.text, styles.heading]}>
|
{store.me.invitesAvailable !== null && (
|
||||||
Invite a Friend
|
<>
|
||||||
</Text>
|
<Text type="xl-bold" style={[pal.text, styles.heading]}>
|
||||||
<TouchableOpacity
|
Invite a Friend
|
||||||
testID="inviteFriendBtn"
|
</Text>
|
||||||
style={[styles.linkCard, pal.view, isSwitching && styles.dimmed]}
|
<TouchableOpacity
|
||||||
onPress={isSwitching ? undefined : onPressInviteCodes}
|
testID="inviteFriendBtn"
|
||||||
accessibilityRole="button"
|
style={[
|
||||||
accessibilityLabel="Invite"
|
styles.linkCard,
|
||||||
accessibilityHint="Opens invite code list">
|
pal.view,
|
||||||
<View
|
isSwitching && styles.dimmed,
|
||||||
style={[
|
]}
|
||||||
styles.iconContainer,
|
onPress={isSwitching ? undefined : onPressInviteCodes}
|
||||||
store.me.invitesAvailable > 0 ? primaryBg : pal.btn,
|
accessibilityRole="button"
|
||||||
]}>
|
accessibilityLabel="Invite"
|
||||||
<FontAwesomeIcon
|
accessibilityHint="Opens invite code list">
|
||||||
icon="ticket"
|
<View
|
||||||
style={
|
style={[
|
||||||
(store.me.invitesAvailable > 0
|
styles.iconContainer,
|
||||||
? primaryText
|
store.me.invitesAvailable > 0 ? primaryBg : pal.btn,
|
||||||
: pal.text) as FontAwesomeIconStyle
|
]}>
|
||||||
}
|
<FontAwesomeIcon
|
||||||
/>
|
icon="ticket"
|
||||||
</View>
|
style={
|
||||||
<Text
|
(store.me.invitesAvailable > 0
|
||||||
type="lg"
|
? primaryText
|
||||||
style={store.me.invitesAvailable > 0 ? pal.link : pal.text}>
|
: pal.text) as FontAwesomeIconStyle
|
||||||
{formatCount(store.me.invitesAvailable)} invite{' '}
|
}
|
||||||
{pluralize(store.me.invitesAvailable, 'code')} available
|
/>
|
||||||
</Text>
|
</View>
|
||||||
</TouchableOpacity>
|
<Text
|
||||||
|
type="lg"
|
||||||
|
style={store.me.invitesAvailable > 0 ? pal.link : pal.text}>
|
||||||
|
{formatCount(store.me.invitesAvailable)} invite{' '}
|
||||||
|
{pluralize(store.me.invitesAvailable, 'code')} available
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
<View style={styles.spacer20} />
|
<View style={styles.spacer20} />
|
||||||
|
|
||||||
|
|
|
@ -426,32 +426,34 @@ const InviteCodes = observer(function InviteCodesImpl({
|
||||||
store.shell.openModal({name: 'invite-codes'})
|
store.shell.openModal({name: 'invite-codes'})
|
||||||
}, [store, track])
|
}, [store, track])
|
||||||
return (
|
return (
|
||||||
<TouchableOpacity
|
store.me.invitesAvailable !== null && (
|
||||||
testID="menuItemInviteCodes"
|
<TouchableOpacity
|
||||||
style={[styles.inviteCodes, style]}
|
testID="menuItemInviteCodes"
|
||||||
onPress={onPress}
|
style={[styles.inviteCodes, style]}
|
||||||
accessibilityRole="button"
|
onPress={onPress}
|
||||||
accessibilityLabel={
|
accessibilityRole="button"
|
||||||
invitesAvailable === 1
|
accessibilityLabel={
|
||||||
? 'Invite codes: 1 available'
|
invitesAvailable === 1
|
||||||
: `Invite codes: ${invitesAvailable} available`
|
? 'Invite codes: 1 available'
|
||||||
}
|
: `Invite codes: ${invitesAvailable} available`
|
||||||
accessibilityHint="Opens list of invite codes">
|
}
|
||||||
<FontAwesomeIcon
|
accessibilityHint="Opens list of invite codes">
|
||||||
icon="ticket"
|
<FontAwesomeIcon
|
||||||
style={[
|
icon="ticket"
|
||||||
styles.inviteCodesIcon,
|
style={[
|
||||||
store.me.invitesAvailable > 0 ? pal.link : pal.textLight,
|
styles.inviteCodesIcon,
|
||||||
]}
|
store.me.invitesAvailable > 0 ? pal.link : pal.textLight,
|
||||||
size={18}
|
]}
|
||||||
/>
|
size={18}
|
||||||
<Text
|
/>
|
||||||
type="lg-medium"
|
<Text
|
||||||
style={store.me.invitesAvailable > 0 ? pal.link : pal.textLight}>
|
type="lg-medium"
|
||||||
{formatCount(store.me.invitesAvailable)} invite{' '}
|
style={store.me.invitesAvailable > 0 ? pal.link : pal.textLight}>
|
||||||
{pluralize(store.me.invitesAvailable, 'code')}
|
{formatCount(store.me.invitesAvailable)} invite{' '}
|
||||||
</Text>
|
{pluralize(store.me.invitesAvailable, 'code')}
|
||||||
</TouchableOpacity>
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
)
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import {DesktopSearch} from './Search'
|
||||||
import {DesktopFeeds} from './Feeds'
|
import {DesktopFeeds} from './Feeds'
|
||||||
import {Text} from 'view/com/util/text/Text'
|
import {Text} from 'view/com/util/text/Text'
|
||||||
import {TextLink} from 'view/com/util/Link'
|
import {TextLink} from 'view/com/util/Link'
|
||||||
|
import {LoadingPlaceholder} from 'view/com/util/LoadingPlaceholder'
|
||||||
import {FEEDBACK_FORM_URL, HELP_DESK_URL} from 'lib/constants'
|
import {FEEDBACK_FORM_URL, HELP_DESK_URL} from 'lib/constants'
|
||||||
import {s} from 'lib/styles'
|
import {s} from 'lib/styles'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
|
@ -89,32 +90,41 @@ const InviteCodes = observer(function InviteCodesImpl() {
|
||||||
const onPress = React.useCallback(() => {
|
const onPress = React.useCallback(() => {
|
||||||
store.shell.openModal({name: 'invite-codes'})
|
store.shell.openModal({name: 'invite-codes'})
|
||||||
}, [store])
|
}, [store])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TouchableOpacity
|
<View style={[styles.separator, pal.border]}>
|
||||||
style={[styles.inviteCodes, pal.border]}
|
{store.me.invitesAvailable === null ? (
|
||||||
onPress={onPress}
|
<View style={[s.p10]}>
|
||||||
accessibilityRole="button"
|
<LoadingPlaceholder width={186} height={32} style={[styles.br40]} />
|
||||||
accessibilityLabel={
|
</View>
|
||||||
invitesAvailable === 1
|
) : (
|
||||||
? 'Invite codes: 1 available'
|
<TouchableOpacity
|
||||||
: `Invite codes: ${invitesAvailable} available`
|
style={[styles.inviteCodes]}
|
||||||
}
|
onPress={onPress}
|
||||||
accessibilityHint="Opens list of invite codes">
|
accessibilityRole="button"
|
||||||
<FontAwesomeIcon
|
accessibilityLabel={
|
||||||
icon="ticket"
|
invitesAvailable === 1
|
||||||
style={[
|
? 'Invite codes: 1 available'
|
||||||
styles.inviteCodesIcon,
|
: `Invite codes: ${invitesAvailable} available`
|
||||||
store.me.invitesAvailable > 0 ? pal.link : pal.textLight,
|
}
|
||||||
]}
|
accessibilityHint="Opens list of invite codes">
|
||||||
size={16}
|
<FontAwesomeIcon
|
||||||
/>
|
icon="ticket"
|
||||||
<Text
|
style={[
|
||||||
type="md-medium"
|
styles.inviteCodesIcon,
|
||||||
style={store.me.invitesAvailable > 0 ? pal.link : pal.textLight}>
|
store.me.invitesAvailable > 0 ? pal.link : pal.textLight,
|
||||||
{formatCount(store.me.invitesAvailable)} invite{' '}
|
]}
|
||||||
{pluralize(store.me.invitesAvailable, 'code')} available
|
size={16}
|
||||||
</Text>
|
/>
|
||||||
</TouchableOpacity>
|
<Text
|
||||||
|
type="md-medium"
|
||||||
|
style={store.me.invitesAvailable > 0 ? pal.link : pal.textLight}>
|
||||||
|
{formatCount(store.me.invitesAvailable)} invite{' '}
|
||||||
|
{pluralize(store.me.invitesAvailable, 'code')} available
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -131,16 +141,20 @@ const styles = StyleSheet.create({
|
||||||
|
|
||||||
message: {
|
message: {
|
||||||
paddingVertical: 18,
|
paddingVertical: 18,
|
||||||
paddingHorizontal: 10,
|
paddingHorizontal: 12,
|
||||||
},
|
},
|
||||||
messageLine: {
|
messageLine: {
|
||||||
marginBottom: 10,
|
marginBottom: 10,
|
||||||
},
|
},
|
||||||
|
|
||||||
inviteCodes: {
|
separator: {
|
||||||
borderTopWidth: 1,
|
borderTopWidth: 1,
|
||||||
paddingHorizontal: 16,
|
},
|
||||||
paddingVertical: 12,
|
br40: {borderRadius: 40},
|
||||||
|
|
||||||
|
inviteCodes: {
|
||||||
|
paddingHorizontal: 12,
|
||||||
|
paddingVertical: 16,
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue