diff options
Diffstat (limited to 'src/state')
-rw-r--r-- | src/state/lib/api.ts | 48 | ||||
-rw-r--r-- | src/state/models/feed-view.ts | 10 | ||||
-rw-r--r-- | src/state/models/me.ts | 13 | ||||
-rw-r--r-- | src/state/models/members-view.ts | 149 | ||||
-rw-r--r-- | src/state/models/memberships-view.ts | 127 | ||||
-rw-r--r-- | src/state/models/notifications-view.ts | 29 | ||||
-rw-r--r-- | src/state/models/profile-ui.ts | 43 | ||||
-rw-r--r-- | src/state/models/profile-view.ts | 8 | ||||
-rw-r--r-- | src/state/models/shell-ui.ts | 18 | ||||
-rw-r--r-- | src/state/models/suggested-invites-view.ts | 142 |
10 files changed, 7 insertions, 580 deletions
diff --git a/src/state/lib/api.ts b/src/state/lib/api.ts index e701ae6f5..8dc9ce5f5 100644 --- a/src/state/lib/api.ts +++ b/src/state/lib/api.ts @@ -216,54 +216,6 @@ export async function unfollow(store: RootStoreModel, followUri: string) { }) } -export async function inviteToScene( - store: RootStoreModel, - sceneDid: string, - subjectDid: string, - subjectDeclarationCid: string, -): Promise<string> { - const res = await store.api.app.bsky.graph.assertion.create( - { - did: sceneDid, - }, - { - subject: { - did: subjectDid, - declarationCid: subjectDeclarationCid, - }, - assertion: APP_BSKY_GRAPH.AssertMember, - createdAt: new Date().toISOString(), - }, - ) - return res.uri -} - -interface Confirmation { - originator: { - did: string - declarationCid: string - } - assertion: { - uri: string - cid: string - } -} -export async function acceptSceneInvite( - store: RootStoreModel, - details: Confirmation, -): Promise<string> { - const res = await store.api.app.bsky.graph.confirmation.create( - { - did: store.me.did || '', - }, - { - ...details, - createdAt: new Date().toISOString(), - }, - ) - return res.uri -} - interface FetchHandlerResponse { status: number headers: Record<string, string> diff --git a/src/state/models/feed-view.ts b/src/state/models/feed-view.ts index 5f2b9721e..c39daf874 100644 --- a/src/state/models/feed-view.ts +++ b/src/state/models/feed-view.ts @@ -6,7 +6,6 @@ import { AppBskyFeedGetAuthorFeed as GetAuthorFeed, } from '@atproto/api' type FeedViewPost = AppBskyFeedFeedViewPost.Main -type ReasonTrend = AppBskyFeedFeedViewPost.ReasonTrend type ReasonRepost = AppBskyFeedFeedViewPost.ReasonRepost type PostView = AppBskyFeedPost.View import {AtUri} from '../../third-party/uri' @@ -94,12 +93,6 @@ export class FeedItemModel { } } - get reasonTrend(): ReasonTrend | undefined { - if (this.reason?.$type === 'app.bsky.feed.feedViewPost#reasonTrend') { - return this.reason as ReasonTrend - } - } - async toggleUpvote() { const wasUpvoted = !!this.post.viewer.upvote const wasDownvoted = !!this.post.viewer.downvote @@ -494,10 +487,9 @@ export class FeedModel { private _updateAll(res: GetTimeline.Response | GetAuthorFeed.Response) { for (const item of res.data.feed) { const existingItem = this.feed.find( - // HACK: need to find the reposts and trends item, so we have to check for that -prf + // HACK: need to find the reposts' item, so we have to check for that -prf item2 => item.post.uri === item2.post.uri && - item.reason?.$trend === item2.reason?.$trend && // @ts-ignore todo item.reason?.by?.did === item2.reason?.by?.did, ) diff --git a/src/state/models/me.ts b/src/state/models/me.ts index 0ae52db8f..201ce04c7 100644 --- a/src/state/models/me.ts +++ b/src/state/models/me.ts @@ -1,7 +1,6 @@ import {makeAutoObservable, runInAction} from 'mobx' import {RootStoreModel} from './root-store' import {FeedModel} from './feed-view' -import {MembershipsViewModel} from './memberships-view' import {NotificationsViewModel} from './notifications-view' import {isObj, hasProp} from '../lib/type-guards' @@ -12,7 +11,6 @@ export class MeModel { description: string = '' avatar: string = '' notificationCount: number = 0 - memberships?: MembershipsViewModel mainFeed: FeedModel notifications: NotificationsViewModel @@ -35,7 +33,6 @@ export class MeModel { this.description = '' this.avatar = '' this.notificationCount = 0 - this.memberships = undefined } serialize(): unknown { @@ -99,13 +96,7 @@ export class MeModel { algorithm: 'reverse-chronological', }) this.notifications = new NotificationsViewModel(this.rootStore, {}) - this.memberships = new MembershipsViewModel(this.rootStore, { - actor: this.did, - }) await Promise.all([ - this.memberships?.setup().catch(e => { - this.rootStore.log.error('Failed to setup memberships model', e) - }), this.mainFeed.setup().catch(e => { this.rootStore.log.error('Failed to setup main feed model', e) }), @@ -133,8 +124,4 @@ export class MeModel { } }) } - - async refreshMemberships() { - return this.memberships?.refresh() - } } diff --git a/src/state/models/members-view.ts b/src/state/models/members-view.ts deleted file mode 100644 index 73295f479..000000000 --- a/src/state/models/members-view.ts +++ /dev/null @@ -1,149 +0,0 @@ -import {makeAutoObservable, runInAction} from 'mobx' -import { - AppBskyGraphGetMembers as GetMembers, - AppBskyActorRef as ActorRef, - APP_BSKY_GRAPH, -} from '@atproto/api' -import {AtUri} from '../../third-party/uri' -import {RootStoreModel} from './root-store' - -export type MemberItem = GetMembers.Member & { - _reactKey: string -} - -export class MembersViewModel { - // state - isLoading = false - isRefreshing = false - hasLoaded = false - error = '' - params: GetMembers.QueryParams - - // data - subject: ActorRef.WithInfo = { - did: '', - handle: '', - displayName: '', - declaration: {cid: '', actorType: ''}, - avatar: undefined, - } - members: MemberItem[] = [] - - constructor( - public rootStore: RootStoreModel, - params: GetMembers.QueryParams, - ) { - makeAutoObservable( - this, - { - rootStore: false, - params: false, - }, - {autoBind: true}, - ) - this.params = params - } - - get hasContent() { - return this.members.length !== 0 - } - - get hasError() { - return this.error !== '' - } - - get isEmpty() { - return this.hasLoaded && !this.hasContent - } - - isMember(did: string) { - return this.members.find(member => member.did === did) - } - - // public api - // = - - async setup() { - await this._fetch() - } - - async refresh() { - await this._fetch(true) - } - - async loadMore() { - // 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 - // = - - private _xLoading(isRefreshing = false) { - this.isLoading = true - this.isRefreshing = isRefreshing - this.error = '' - } - - private _xIdle(err?: any) { - this.isLoading = false - this.isRefreshing = false - this.hasLoaded = true - this.error = err ? err.toString() : '' - if (err) { - this.rootStore.log.error('Failed to fetch members', err) - } - } - - // loader functions - // = - - private async _fetch(isRefreshing = false) { - this._xLoading(isRefreshing) - try { - const res = await this.rootStore.api.app.bsky.graph.getMembers( - this.params, - ) - this._replaceAll(res) - this._xIdle() - } catch (e: any) { - this._xIdle(e) - } - } - - private _replaceAll(res: GetMembers.Response) { - 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.subject.avatar = res.data.subject.avatar - this.members.length = 0 - let counter = 0 - for (const item of res.data.members) { - this._append({_reactKey: `item-${counter++}`, ...item}) - } - } - - private _append(item: MemberItem) { - this.members.push(item) - } -} diff --git a/src/state/models/memberships-view.ts b/src/state/models/memberships-view.ts deleted file mode 100644 index 661b3f6ae..000000000 --- a/src/state/models/memberships-view.ts +++ /dev/null @@ -1,127 +0,0 @@ -import {makeAutoObservable} from 'mobx' -import { - AppBskyGraphGetMemberships as GetMemberships, - AppBskyActorRef as ActorRef, -} from '@atproto/api' -import {RootStoreModel} from './root-store' - -export type MembershipItem = GetMemberships.Membership & { - _reactKey: string -} - -export class MembershipsViewModel { - // state - isLoading = false - isRefreshing = false - hasLoaded = false - error = '' - params: GetMemberships.QueryParams - - // data - subject: ActorRef.WithInfo = { - did: '', - handle: '', - displayName: '', - declaration: {cid: '', actorType: ''}, - avatar: undefined, - } - memberships: MembershipItem[] = [] - - constructor( - public rootStore: RootStoreModel, - params: GetMemberships.QueryParams, - ) { - makeAutoObservable( - this, - { - rootStore: false, - params: false, - }, - {autoBind: true}, - ) - this.params = params - } - - get hasContent() { - return this.memberships.length !== 0 - } - - get hasError() { - return this.error !== '' - } - - get isEmpty() { - return this.hasLoaded && !this.hasContent - } - - isMemberOf(did: string) { - return !!this.memberships.find(m => m.did === did) - } - - // public api - // = - - async setup() { - await this._fetch() - } - - async refresh() { - await this._fetch(true) - } - - async loadMore() { - // TODO - } - - // state transitions - // = - - private _xLoading(isRefreshing = false) { - this.isLoading = true - this.isRefreshing = isRefreshing - this.error = '' - } - - private _xIdle(err?: any) { - this.isLoading = false - this.isRefreshing = false - this.hasLoaded = true - this.error = err ? err.toString() : '' - if (err) { - this.rootStore.log.error('Failed to fetch memberships', err) - } - } - - // loader functions - // = - - private async _fetch(isRefreshing = false) { - this._xLoading(isRefreshing) - try { - const res = await this.rootStore.api.app.bsky.graph.getMemberships( - this.params, - ) - this._replaceAll(res) - this._xIdle() - } catch (e: any) { - this._xIdle(e) - } - } - - private _replaceAll(res: GetMemberships.Response) { - 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.subject.avatar = res.data.subject.avatar - this.memberships.length = 0 - let counter = 0 - for (const item of res.data.memberships) { - this._append({_reactKey: `item-${counter++}`, ...item}) - } - } - - private _append(item: MembershipItem) { - this.memberships.push(item) - } -} diff --git a/src/state/models/notifications-view.ts b/src/state/models/notifications-view.ts index c169a995c..c4d2b2dfa 100644 --- a/src/state/models/notifications-view.ts +++ b/src/state/models/notifications-view.ts @@ -4,17 +4,15 @@ import { AppBskyActorRef as ActorRef, AppBskyFeedPost, AppBskyFeedRepost, - AppBskyFeedTrend, AppBskyFeedVote, AppBskyGraphAssertion, AppBskyGraphFollow, - APP_BSKY_GRAPH, } from '@atproto/api' import {RootStoreModel} from './root-store' import {PostThreadViewModel} from './post-thread-view' import {cleanError} from '../../lib/strings' -const UNGROUPABLE_REASONS = ['trend', 'assertion'] +const UNGROUPABLE_REASONS = ['assertion'] const PAGE_SIZE = 30 const MS_60MIN = 1e3 * 60 * 60 @@ -27,7 +25,6 @@ export interface GroupedNotification extends ListNotifications.Notification { type SupportedRecord = | AppBskyFeedPost.Record | AppBskyFeedRepost.Record - | AppBskyFeedTrend.Record | AppBskyFeedVote.Record | AppBskyGraphAssertion.Record | AppBskyGraphFollow.Record @@ -94,10 +91,6 @@ export class NotificationsViewItemModel { return this.reason === 'repost' } - get isTrend() { - return this.reason === 'trend' - } - get isMention() { return this.reason === 'mention' } @@ -115,26 +108,12 @@ export class NotificationsViewItemModel { } get needsAdditionalData() { - if ( - this.isUpvote || - this.isRepost || - this.isTrend || - this.isReply || - this.isMention - ) { + if (this.isUpvote || this.isRepost || this.isReply || this.isMention) { return !this.additionalPost } return false } - get isInvite() { - return ( - this.isAssertion && - AppBskyGraphAssertion.isRecord(this.record) && - this.record.assertion === APP_BSKY_GRAPH.AssertMember - ) - } - get subjectUri(): string { if (this.reasonSubject) { return this.reasonSubject @@ -142,7 +121,6 @@ export class NotificationsViewItemModel { const record = this.record if ( AppBskyFeedRepost.isRecord(record) || - AppBskyFeedTrend.isRecord(record) || AppBskyFeedVote.isRecord(record) ) { return record.subject.uri @@ -154,7 +132,6 @@ export class NotificationsViewItemModel { for (const ns of [ AppBskyFeedPost, AppBskyFeedRepost, - AppBskyFeedTrend, AppBskyFeedVote, AppBskyGraphAssertion, AppBskyGraphFollow, @@ -185,7 +162,7 @@ export class NotificationsViewItemModel { let postUri if (this.isReply || this.isMention) { postUri = this.uri - } else if (this.isUpvote || this.isRepost || this.isTrend) { + } else if (this.isUpvote || this.isRepost) { postUri = this.subjectUri } if (postUri) { diff --git a/src/state/models/profile-ui.ts b/src/state/models/profile-ui.ts index fb90fb694..55fb25061 100644 --- a/src/state/models/profile-ui.ts +++ b/src/state/models/profile-ui.ts @@ -1,24 +1,14 @@ import {makeAutoObservable} from 'mobx' import {RootStoreModel} from './root-store' import {ProfileViewModel} from './profile-view' -import {MembersViewModel} from './members-view' -import {MembershipsViewModel} from './memberships-view' import {FeedModel} from './feed-view' export enum Sections { Posts = 'Posts', PostsWithReplies = 'Posts & replies', - Scenes = 'Scenes', - Trending = 'Trending', - Members = 'Members', } -const USER_SELECTOR_ITEMS = [ - Sections.Posts, - Sections.PostsWithReplies, - Sections.Scenes, -] -const SCENE_SELECTOR_ITEMS = [Sections.Trending, Sections.Members] +const USER_SELECTOR_ITEMS = [Sections.Posts, Sections.PostsWithReplies] export interface ProfileUiParams { user: string @@ -28,8 +18,6 @@ export class ProfileUiModel { // data profile: ProfileViewModel feed: FeedModel - memberships: MembershipsViewModel - members: MembersViewModel // ui state selectedViewIndex = 0 @@ -51,24 +39,15 @@ export class ProfileUiModel { author: params.user, limit: 10, }) - this.memberships = new MembershipsViewModel(rootStore, {actor: params.user}) - this.members = new MembersViewModel(rootStore, {actor: params.user}) } - get currentView(): FeedModel | MembershipsViewModel | MembersViewModel { + get currentView(): FeedModel { if ( this.selectedView === Sections.Posts || - this.selectedView === Sections.PostsWithReplies || - this.selectedView === Sections.Trending + this.selectedView === Sections.PostsWithReplies ) { return this.feed } - if (this.selectedView === Sections.Scenes) { - return this.memberships - } - if (this.selectedView === Sections.Members) { - return this.members - } throw new Error(`Invalid selector value: ${this.selectedViewIndex}`) } @@ -85,15 +64,9 @@ export class ProfileUiModel { return this.profile.isUser } - get isScene() { - return this.profile.isScene - } - get selectorItems() { if (this.isUser) { return USER_SELECTOR_ITEMS - } else if (this.isScene) { - return SCENE_SELECTOR_ITEMS } else { return USER_SELECTOR_ITEMS } @@ -119,16 +92,6 @@ export class ProfileUiModel { .setup() .catch(err => this.rootStore.log.error('Failed to fetch feed', err)), ]) - if (this.isUser) { - await this.memberships - .setup() - .catch(err => this.rootStore.log.error('Failed to fetch members', err)) - } - if (this.isScene) { - await this.members - .setup() - .catch(err => this.rootStore.log.error('Failed to fetch members', err)) - } } async update() { diff --git a/src/state/models/profile-view.ts b/src/state/models/profile-view.ts index 2670627c3..a1535693c 100644 --- a/src/state/models/profile-view.ts +++ b/src/state/models/profile-view.ts @@ -13,11 +13,9 @@ import {RootStoreModel} from './root-store' import * as apilib from '../lib/api' export const ACTOR_TYPE_USER = 'app.bsky.system.actorUser' -export const ACTOR_TYPE_SCENE = 'app.bsky.system.actorScene' export class ProfileViewMyStateModel { follow?: string - member?: string muted?: boolean constructor() { @@ -47,7 +45,6 @@ export class ProfileViewModel { banner?: string followersCount: number = 0 followsCount: number = 0 - membersCount: number = 0 postsCount: number = 0 myState = new ProfileViewMyStateModel() @@ -85,10 +82,6 @@ export class ProfileViewModel { return this.declaration.actorType === ACTOR_TYPE_USER } - get isScene() { - return this.declaration.actorType === ACTOR_TYPE_SCENE - } - // public api // = @@ -216,7 +209,6 @@ export class ProfileViewModel { this.banner = res.data.banner this.followersCount = res.data.followersCount this.followsCount = res.data.followsCount - this.membersCount = res.data.membersCount this.postsCount = res.data.postsCount if (res.data.myState) { Object.assign(this.myState, res.data.myState) diff --git a/src/state/models/shell-ui.ts b/src/state/models/shell-ui.ts index 52d081680..1af74f56a 100644 --- a/src/state/models/shell-ui.ts +++ b/src/state/models/shell-ui.ts @@ -25,22 +25,6 @@ export class EditProfileModal { } } -export class CreateSceneModal { - name = 'create-scene' - - constructor() { - makeAutoObservable(this) - } -} - -export class InviteToSceneModal { - name = 'invite-to-scene' - - constructor(public profileView: ProfileViewModel) { - makeAutoObservable(this) - } -} - export class ServerInputModal { name = 'server-input' @@ -143,7 +127,6 @@ export class ShellUiModel { activeModal: | ConfirmModal | EditProfileModal - | CreateSceneModal | ServerInputModal | ReportPostModal | ReportAccountModal @@ -191,7 +174,6 @@ export class ShellUiModel { modal: | ConfirmModal | EditProfileModal - | CreateSceneModal | ServerInputModal | ReportPostModal | ReportAccountModal, diff --git a/src/state/models/suggested-invites-view.ts b/src/state/models/suggested-invites-view.ts deleted file mode 100644 index fadc956cc..000000000 --- a/src/state/models/suggested-invites-view.ts +++ /dev/null @@ -1,142 +0,0 @@ -import {makeAutoObservable, runInAction} from 'mobx' -import {RootStoreModel} from './root-store' -import {UserFollowsViewModel, FollowItem} from './user-follows-view' -import {GetAssertionsView} from './get-assertions-view' -import {APP_BSKY_SYSTEM, APP_BSKY_GRAPH} from '@atproto/api' - -export interface SuggestedInvitesViewParams { - sceneDid: string -} - -export class SuggestedInvitesView { - // state - isLoading = false - isRefreshing = false - hasLoaded = false - error = '' - params: SuggestedInvitesViewParams - sceneAssertionsView: GetAssertionsView - myFollowsView: UserFollowsViewModel - - // data - suggestions: FollowItem[] = [] - - constructor( - public rootStore: RootStoreModel, - params: SuggestedInvitesViewParams, - ) { - makeAutoObservable( - this, - { - rootStore: false, - params: false, - }, - {autoBind: true}, - ) - this.params = params - this.sceneAssertionsView = new GetAssertionsView(rootStore, { - author: params.sceneDid, - assertion: APP_BSKY_GRAPH.AssertMember, - }) - this.myFollowsView = new UserFollowsViewModel(rootStore, { - user: rootStore.me.did || '', - }) - } - - get hasContent() { - return this.suggestions.length > 0 - } - - get hasError() { - return this.error !== '' - } - - get isEmpty() { - return this.hasLoaded && !this.hasContent - } - - get unconfirmed() { - return this.sceneAssertionsView.unconfirmed - } - - // public api - // = - - async setup() { - await this._fetch(false) - } - - async refresh() { - await this._fetch(true) - } - - async loadMore() { - // TODO - } - - // state transitions - // = - - private _xLoading(isRefreshing = false) { - this.isLoading = true - this.isRefreshing = isRefreshing - this.error = '' - } - - private _xIdle(err?: any) { - this.isLoading = false - this.isRefreshing = false - this.hasLoaded = true - this.error = err ? err.toString() : '' - if (err) { - this.rootStore.log.error('Failed to fetch suggested invites', err) - } - } - - // loader functions - // = - - private async _fetch(isRefreshing = false) { - this._xLoading(isRefreshing) - try { - // TODO need to fetch all! - await this.sceneAssertionsView.setup() - } catch (e: any) { - this.rootStore.log.error( - 'Failed to fetch current scene members in suggested invites', - e, - ) - this._xIdle( - 'Failed to fetch the current scene members. Check your internet connection and try again.', - ) - return - } - try { - await this.myFollowsView.setup() - } catch (e: any) { - this.rootStore.log.error( - 'Failed to fetch current followers in suggested invites', - e, - ) - this._xIdle( - 'Failed to fetch the your current followers. Check your internet connection and try again.', - ) - return - } - - // collect all followed users that arent already in the scene - const newSuggestions: FollowItem[] = [] - for (const follow of this.myFollowsView.follows) { - if (follow.declaration.actorType !== APP_BSKY_SYSTEM.ActorUser) { - continue - } - if (!this.sceneAssertionsView.getBySubject(follow.did)) { - newSuggestions.push(follow) - } - } - runInAction(() => { - this.suggestions = newSuggestions - }) - this._xIdle() - } -} |