[APP-562] Persist 'copied' state of invite codes (#535)

* Persist 'copied' state of invite codes (close APP-562)

* Dont show copied message if invite used
This commit is contained in:
Paul Frazee 2023-04-25 20:47:07 -05:00 committed by GitHub
parent e1fd50d014
commit f33a355a1a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 57 additions and 40 deletions

View file

@ -4,6 +4,7 @@ import {RootStoreModel} from './root-store'
import {isObj, hasProp, isStrArray} from 'lib/type-guards' import {isObj, hasProp, isStrArray} from 'lib/type-guards'
export class InvitedUsers { export class InvitedUsers {
copiedInvites: string[] = []
seenDids: string[] = [] seenDids: string[] = []
profiles: AppBskyActorDefs.ProfileViewDetailed[] = [] profiles: AppBskyActorDefs.ProfileViewDetailed[] = []
@ -20,13 +21,20 @@ export class InvitedUsers {
} }
serialize() { serialize() {
return {seenDids: this.seenDids} return {seenDids: this.seenDids, copiedInvites: this.copiedInvites}
} }
hydrate(v: unknown) { hydrate(v: unknown) {
if (isObj(v) && hasProp(v, 'seenDids') && isStrArray(v.seenDids)) { if (isObj(v) && hasProp(v, 'seenDids') && isStrArray(v.seenDids)) {
this.seenDids = v.seenDids this.seenDids = v.seenDids
} }
if (
isObj(v) &&
hasProp(v, 'copiedInvites') &&
isStrArray(v.copiedInvites)
) {
this.copiedInvites = v.copiedInvites
}
} }
async fetch(invites: ComAtprotoServerDefs.InviteCode[]) { async fetch(invites: ComAtprotoServerDefs.InviteCode[]) {
@ -63,6 +71,16 @@ export class InvitedUsers {
} }
} }
isInviteCopied(invite: string) {
return this.copiedInvites.includes(invite)
}
setInviteCopied(invite: string) {
if (!this.isInviteCopied(invite)) {
this.copiedInvites.push(invite)
}
}
markSeen(did: string) { markSeen(did: string) {
this.seenDids.push(did) this.seenDids.push(did)
this.profiles = this.profiles.filter(profile => profile.did !== did) this.profiles = this.profiles.filter(profile => profile.did !== did)

View file

@ -1,5 +1,6 @@
import React from 'react' import React from 'react'
import {StyleSheet, TouchableOpacity, View} from 'react-native' import {StyleSheet, TouchableOpacity, View} from 'react-native'
import {observer} from 'mobx-react-lite'
import { import {
FontAwesomeIcon, FontAwesomeIcon,
FontAwesomeIconStyle, FontAwesomeIconStyle,
@ -82,46 +83,42 @@ export function Component({}: {}) {
) )
} }
function InviteCode({ const InviteCode = observer(
testID, ({testID, code, used}: {testID: string; code: string; used?: boolean}) => {
code, const pal = usePalette('default')
used, const store = useStores()
}: {
testID: string
code: string
used?: boolean
}) {
const pal = usePalette('default')
const [wasCopied, setWasCopied] = React.useState(false)
const onPress = React.useCallback(() => { const onPress = React.useCallback(() => {
Clipboard.setString(code) Clipboard.setString(code)
Toast.show('Copied to clipboard') Toast.show('Copied to clipboard')
setWasCopied(true) store.invitedUsers.setInviteCopied(code)
}, [code]) }, [store, code])
return ( return (
<TouchableOpacity <TouchableOpacity
testID={testID} testID={testID}
style={[styles.inviteCode, pal.border]} style={[styles.inviteCode, pal.border]}
onPress={onPress}> onPress={onPress}>
<Text <Text
testID={`${testID}-code`} testID={`${testID}-code`}
type={used ? 'md' : 'md-bold'} type={used ? 'md' : 'md-bold'}
style={used ? [pal.textLight, styles.strikeThrough] : pal.text}> style={used ? [pal.textLight, styles.strikeThrough] : pal.text}>
{code} {code}
</Text> </Text>
{wasCopied ? ( <View style={styles.flex1} />
<Text style={pal.textLight}>Copied</Text> {!used && store.invitedUsers.isInviteCopied(code) && (
) : !used ? ( <Text style={[pal.textLight, styles.codeCopied]}>Copied</Text>
<FontAwesomeIcon )}
icon={['far', 'clone']} {!used && (
style={pal.text as FontAwesomeIconStyle} <FontAwesomeIcon
/> icon={['far', 'clone']}
) : undefined} style={pal.text as FontAwesomeIconStyle}
</TouchableOpacity> />
) )}
} </TouchableOpacity>
)
},
)
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
@ -163,11 +160,13 @@ const styles = StyleSheet.create({
inviteCode: { inviteCode: {
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
justifyContent: 'space-between',
borderBottomWidth: 1, borderBottomWidth: 1,
paddingHorizontal: 20, paddingHorizontal: 20,
paddingVertical: 14, paddingVertical: 14,
}, },
codeCopied: {
marginRight: 8,
},
strikeThrough: { strikeThrough: {
textDecorationLine: 'line-through', textDecorationLine: 'line-through',
textDecorationStyle: 'solid', textDecorationStyle: 'solid',