[APP-562] Persist 'copied' state of invite codes (#535)
* Persist 'copied' state of invite codes (close APP-562) * Dont show copied message if invite usedzio/stable
parent
e1fd50d014
commit
f33a355a1a
|
@ -4,6 +4,7 @@ import {RootStoreModel} from './root-store'
|
|||
import {isObj, hasProp, isStrArray} from 'lib/type-guards'
|
||||
|
||||
export class InvitedUsers {
|
||||
copiedInvites: string[] = []
|
||||
seenDids: string[] = []
|
||||
profiles: AppBskyActorDefs.ProfileViewDetailed[] = []
|
||||
|
||||
|
@ -20,13 +21,20 @@ export class InvitedUsers {
|
|||
}
|
||||
|
||||
serialize() {
|
||||
return {seenDids: this.seenDids}
|
||||
return {seenDids: this.seenDids, copiedInvites: this.copiedInvites}
|
||||
}
|
||||
|
||||
hydrate(v: unknown) {
|
||||
if (isObj(v) && hasProp(v, 'seenDids') && isStrArray(v.seenDids)) {
|
||||
this.seenDids = v.seenDids
|
||||
}
|
||||
if (
|
||||
isObj(v) &&
|
||||
hasProp(v, 'copiedInvites') &&
|
||||
isStrArray(v.copiedInvites)
|
||||
) {
|
||||
this.copiedInvites = v.copiedInvites
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
this.seenDids.push(did)
|
||||
this.profiles = this.profiles.filter(profile => profile.did !== did)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React from 'react'
|
||||
import {StyleSheet, TouchableOpacity, View} from 'react-native'
|
||||
import {observer} from 'mobx-react-lite'
|
||||
import {
|
||||
FontAwesomeIcon,
|
||||
FontAwesomeIconStyle,
|
||||
|
@ -82,46 +83,42 @@ export function Component({}: {}) {
|
|||
)
|
||||
}
|
||||
|
||||
function InviteCode({
|
||||
testID,
|
||||
code,
|
||||
used,
|
||||
}: {
|
||||
testID: string
|
||||
code: string
|
||||
used?: boolean
|
||||
}) {
|
||||
const pal = usePalette('default')
|
||||
const [wasCopied, setWasCopied] = React.useState(false)
|
||||
const InviteCode = observer(
|
||||
({testID, code, used}: {testID: string; code: string; used?: boolean}) => {
|
||||
const pal = usePalette('default')
|
||||
const store = useStores()
|
||||
|
||||
const onPress = React.useCallback(() => {
|
||||
Clipboard.setString(code)
|
||||
Toast.show('Copied to clipboard')
|
||||
setWasCopied(true)
|
||||
}, [code])
|
||||
const onPress = React.useCallback(() => {
|
||||
Clipboard.setString(code)
|
||||
Toast.show('Copied to clipboard')
|
||||
store.invitedUsers.setInviteCopied(code)
|
||||
}, [store, code])
|
||||
|
||||
return (
|
||||
<TouchableOpacity
|
||||
testID={testID}
|
||||
style={[styles.inviteCode, pal.border]}
|
||||
onPress={onPress}>
|
||||
<Text
|
||||
testID={`${testID}-code`}
|
||||
type={used ? 'md' : 'md-bold'}
|
||||
style={used ? [pal.textLight, styles.strikeThrough] : pal.text}>
|
||||
{code}
|
||||
</Text>
|
||||
{wasCopied ? (
|
||||
<Text style={pal.textLight}>Copied</Text>
|
||||
) : !used ? (
|
||||
<FontAwesomeIcon
|
||||
icon={['far', 'clone']}
|
||||
style={pal.text as FontAwesomeIconStyle}
|
||||
/>
|
||||
) : undefined}
|
||||
</TouchableOpacity>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<TouchableOpacity
|
||||
testID={testID}
|
||||
style={[styles.inviteCode, pal.border]}
|
||||
onPress={onPress}>
|
||||
<Text
|
||||
testID={`${testID}-code`}
|
||||
type={used ? 'md' : 'md-bold'}
|
||||
style={used ? [pal.textLight, styles.strikeThrough] : pal.text}>
|
||||
{code}
|
||||
</Text>
|
||||
<View style={styles.flex1} />
|
||||
{!used && store.invitedUsers.isInviteCopied(code) && (
|
||||
<Text style={[pal.textLight, styles.codeCopied]}>Copied</Text>
|
||||
)}
|
||||
{!used && (
|
||||
<FontAwesomeIcon
|
||||
icon={['far', 'clone']}
|
||||
style={pal.text as FontAwesomeIconStyle}
|
||||
/>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
|
@ -163,11 +160,13 @@ const styles = StyleSheet.create({
|
|||
inviteCode: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
borderBottomWidth: 1,
|
||||
paddingHorizontal: 20,
|
||||
paddingVertical: 14,
|
||||
},
|
||||
codeCopied: {
|
||||
marginRight: 8,
|
||||
},
|
||||
strikeThrough: {
|
||||
textDecorationLine: 'line-through',
|
||||
textDecorationStyle: 'solid',
|
||||
|
|
Loading…
Reference in New Issue