diff options
author | Paul Frazee <pfrazee@gmail.com> | 2022-11-11 13:28:23 -0600 |
---|---|---|
committer | Paul Frazee <pfrazee@gmail.com> | 2022-11-11 13:28:23 -0600 |
commit | fe52d19c485f4cdaec3b35ca31f5e9e7b44ff975 (patch) | |
tree | 5426c56dfd5740437f70972beab227d3e27adf33 | |
parent | 22849fb4fcd9b3acde8711051d74c35b6bb23fdb (diff) | |
download | voidsky-fe52d19c485f4cdaec3b35ca31f5e9e7b44ff975.tar.zst |
Add UI to remove members from scenes
-rw-r--r-- | src/state/models/members-view.ts | 32 | ||||
-rw-r--r-- | src/view/screens/Profile.tsx | 37 | ||||
-rw-r--r-- | todos.txt | 3 |
3 files changed, 69 insertions, 3 deletions
diff --git a/src/state/models/members-view.ts b/src/state/models/members-view.ts index 370b6b431..19101afca 100644 --- a/src/state/models/members-view.ts +++ b/src/state/models/members-view.ts @@ -1,5 +1,7 @@ -import {makeAutoObservable} from 'mobx' +import {makeAutoObservable, runInAction} from 'mobx' import * as GetMembers from '../../third-party/api/src/client/types/app/bsky/graph/getMembers' +import {APP_BSKY_GRAPH} from '../../third-party/api' +import {AtUri} from '../../third-party/uri' import {RootStoreModel} from './root-store' type Subject = GetMembers.OutputSchema['subject'] @@ -16,7 +18,12 @@ export class MembersViewModel { params: GetMembers.QueryParams // data - subject: Subject = {did: '', handle: '', displayName: ''} + subject: Subject = { + did: '', + handle: '', + displayName: '', + declaration: {cid: '', actorType: ''}, + } members: MemberItem[] = [] constructor( @@ -65,6 +72,26 @@ export class MembersViewModel { // TODO } + async removeMember(did: string) { + const assertsRes = await this.rootStore.api.app.bsky.graph.getAssertions({ + author: this.subject.did, + subject: did, + assertion: APP_BSKY_GRAPH.AssertMember, + }) + if (assertsRes.data.assertions.length < 1) { + throw new Error('Could not find membership record') + } + for (const assert of assertsRes.data.assertions) { + await this.rootStore.api.app.bsky.graph.assertion.delete({ + did: this.subject.did, + rkey: new AtUri(assert.uri).rkey, + }) + } + runInAction(() => { + this.members = this.members.filter(m => m.did !== did) + }) + } + // state transitions // = @@ -101,6 +128,7 @@ export class MembersViewModel { this.subject.did = res.data.subject.did this.subject.handle = res.data.subject.handle this.subject.displayName = res.data.subject.displayName + this.subject.declaration = res.data.subject.declaration this.members.length = 0 let counter = 0 for (const item of res.data.members) { diff --git a/src/view/screens/Profile.tsx b/src/view/screens/Profile.tsx index 7fb3a5fb7..5dbe29060 100644 --- a/src/view/screens/Profile.tsx +++ b/src/view/screens/Profile.tsx @@ -1,15 +1,19 @@ import React, {useEffect, useState, useMemo} from 'react' import {StyleSheet, Text, View} from 'react-native' import {observer} from 'mobx-react-lite' +import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {ViewSelector} from '../com/util/ViewSelector' import {ScreenParams} from '../routes' import {ProfileUiModel, Sections} from '../../state/models/profile-ui' +import {MembershipItem} from '../../state/models/memberships-view' import {useStores} from '../../state' +import {ConfirmModel} from '../../state/models/shell-ui' import {ProfileHeader} from '../com/profile/ProfileHeader' import {FeedItem} from '../com/posts/FeedItem' import {ProfileCard} from '../com/profile/ProfileCard' import {ErrorScreen} from '../com/util/ErrorScreen' import {ErrorMessage} from '../com/util/ErrorMessage' +import Toast from '../com/util/Toast' import {s, colors} from '../lib/styles' import {UserGroupIcon} from '../lib/icons' @@ -65,10 +69,28 @@ export const Profile = observer(({visible, params}: ScreenParams) => { const onPressTryAgain = () => { uiState.setup() } + const onPressRemoveMember = (membership: MembershipItem) => { + store.shell.openModal( + new ConfirmModel( + `Remove ${membership.displayName || membership.handle}?`, + `You'll be able to invite them again if you change your mind.`, + async () => { + await uiState.members.removeMember(membership.did) + Toast.show(`User removed`, { + duration: Toast.durations.LONG, + position: Toast.positions.TOP, + }) + }, + ), + ) + } // rendering // = + const isSceneCreator = + uiState.isScene && store.me.did === uiState.profile.creator + const renderHeader = () => { if (!uiState) { return <View /> @@ -155,11 +177,26 @@ export const Profile = observer(({visible, params}: ScreenParams) => { if (uiState.members.hasContent) { items = uiState.members.members.slice() renderItem = (item: any) => { + const shouldAdmin = isSceneCreator && item.did !== store.me.did + const renderButton = shouldAdmin + ? () => ( + <> + <FontAwesomeIcon + icon="user-xmark" + style={[s.mr5]} + size={14} + /> + <Text style={[s.fw400, s.f14]}>Remove</Text> + </> + ) + : undefined return ( <ProfileCard did={item.did} handle={item.handle} displayName={item.displayName} + renderButton={renderButton} + onPressButton={() => onPressRemoveMember(item)} /> ) } diff --git a/todos.txt b/todos.txt index 9f40fac75..11e5e7b92 100644 --- a/todos.txt +++ b/todos.txt @@ -18,9 +18,10 @@ Paul's todo list - User search - Use pagination to make sure there are suggestions - User profile + - User + - Invite to scene - Scene > Edit profile - > Remove member - Reply gating - Composer - View on post |