diff options
Diffstat (limited to 'src/state/models')
-rw-r--r-- | src/state/models/_common.ts | 4 | ||||
-rw-r--r-- | src/state/models/feed-view.ts | 8 | ||||
-rw-r--r-- | src/state/models/me.ts | 11 | ||||
-rw-r--r-- | src/state/models/members-view.ts | 8 | ||||
-rw-r--r-- | src/state/models/memberships-view.ts | 14 | ||||
-rw-r--r-- | src/state/models/notifications-view.ts | 13 | ||||
-rw-r--r-- | src/state/models/post-thread-view.ts | 42 | ||||
-rw-r--r-- | src/state/models/post.ts | 6 | ||||
-rw-r--r-- | src/state/models/profile-view.ts | 30 | ||||
-rw-r--r-- | src/state/models/reposted-by-view.ts | 9 | ||||
-rw-r--r-- | src/state/models/session.ts | 1 | ||||
-rw-r--r-- | src/state/models/shell-ui.ts | 1 | ||||
-rw-r--r-- | src/state/models/suggested-actors-view.ts | 3 | ||||
-rw-r--r-- | src/state/models/user-autocomplete-view.ts | 6 | ||||
-rw-r--r-- | src/state/models/user-followers-view.ts | 8 | ||||
-rw-r--r-- | src/state/models/user-follows-view.ts | 8 | ||||
-rw-r--r-- | src/state/models/votes-view.ts | 15 |
17 files changed, 117 insertions, 70 deletions
diff --git a/src/state/models/_common.ts b/src/state/models/_common.ts deleted file mode 100644 index 459dd7602..000000000 --- a/src/state/models/_common.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface Declaration { - cid: string - actorType: string -} diff --git a/src/state/models/feed-view.ts b/src/state/models/feed-view.ts index 65248c575..514873d6b 100644 --- a/src/state/models/feed-view.ts +++ b/src/state/models/feed-view.ts @@ -1,6 +1,7 @@ import {makeAutoObservable, runInAction} from 'mobx' import {Record as PostRecord} from '../../third-party/api/src/client/types/app/bsky/feed/post' import * as GetTimeline from '../../third-party/api/src/client/types/app/bsky/feed/getTimeline' +import * as ActorRef from '../../third-party/api/src/client/types/app/bsky/actor/ref' import * as GetAuthorFeed from '../../third-party/api/src/client/types/app/bsky/feed/getAuthorFeed' import {PostThreadViewModel} from './post-thread-view' import {AtUri} from '../../third-party/uri' @@ -36,14 +37,15 @@ export class FeedItemModel implements GetTimeline.FeedItem { // data uri: string = '' cid: string = '' - author: GetTimeline.Actor = { + author: ActorRef.WithInfo = { did: '', handle: '', displayName: '', declaration: {cid: '', actorType: ''}, + avatar: undefined, } - repostedBy?: GetTimeline.Actor - trendedBy?: GetTimeline.Actor + repostedBy?: ActorRef.WithInfo + trendedBy?: ActorRef.WithInfo record: Record<string, unknown> = {} replyCount: number = 0 repostCount: number = 0 diff --git a/src/state/models/me.ts b/src/state/models/me.ts index 25b148c75..0a2651af1 100644 --- a/src/state/models/me.ts +++ b/src/state/models/me.ts @@ -9,6 +9,7 @@ export class MeModel { handle: string = '' displayName: string = '' description: string = '' + avatar: string = '' notificationCount: number = 0 memberships?: MembershipsViewModel notifications: NotificationsViewModel @@ -27,6 +28,7 @@ export class MeModel { this.handle = '' this.displayName = '' this.description = '' + this.avatar = '' this.notificationCount = 0 this.memberships = undefined } @@ -37,12 +39,13 @@ export class MeModel { handle: this.handle, displayName: this.displayName, description: this.description, + avatar: this.avatar, } } hydrate(v: unknown) { if (isObj(v)) { - let did, handle, displayName, description + let did, handle, displayName, description, avatar if (hasProp(v, 'did') && typeof v.did === 'string') { did = v.did } @@ -55,11 +58,15 @@ export class MeModel { if (hasProp(v, 'description') && typeof v.description === 'string') { description = v.description } + if (hasProp(v, 'avatar') && typeof v.avatar === 'string') { + avatar = v.avatar + } if (did && handle) { this.did = did this.handle = handle this.displayName = displayName || '' this.description = description || '' + this.avatar = avatar || '' } } } @@ -76,9 +83,11 @@ export class MeModel { if (profile?.data) { this.displayName = profile.data.displayName || '' this.description = profile.data.description || '' + this.avatar = profile.data.avatar || '' } else { this.displayName = '' this.description = '' + this.avatar = '' } }) this.memberships = new MembershipsViewModel(this.rootStore, { diff --git a/src/state/models/members-view.ts b/src/state/models/members-view.ts index ed89f7f4e..98d3368ac 100644 --- a/src/state/models/members-view.ts +++ b/src/state/models/members-view.ts @@ -1,11 +1,11 @@ import {makeAutoObservable, runInAction} from 'mobx' import * as GetMembers from '../../third-party/api/src/client/types/app/bsky/graph/getMembers' +import * as ActorRef from '../../third-party/api/src/client/types/app/bsky/actor/ref' import {APP_BSKY_GRAPH} from '../../third-party/api' import {AtUri} from '../../third-party/uri' import {RootStoreModel} from './root-store' -type Subject = GetMembers.OutputSchema['subject'] -export type MemberItem = GetMembers.OutputSchema['members'][number] & { +export type MemberItem = GetMembers.Member & { _reactKey: string } @@ -18,11 +18,12 @@ export class MembersViewModel { params: GetMembers.QueryParams // data - subject: Subject = { + subject: ActorRef.WithInfo = { did: '', handle: '', displayName: '', declaration: {cid: '', actorType: ''}, + avatar: undefined, } members: MemberItem[] = [] @@ -129,6 +130,7 @@ export class MembersViewModel { 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) { diff --git a/src/state/models/memberships-view.ts b/src/state/models/memberships-view.ts index b8186d323..57b2fd193 100644 --- a/src/state/models/memberships-view.ts +++ b/src/state/models/memberships-view.ts @@ -1,12 +1,11 @@ import {makeAutoObservable} from 'mobx' import * as GetMemberships from '../../third-party/api/src/client/types/app/bsky/graph/getMemberships' +import * as ActorRef from '../../third-party/api/src/client/types/app/bsky/actor/ref' import {RootStoreModel} from './root-store' -type Subject = GetMemberships.OutputSchema['subject'] -export type MembershipItem = - GetMemberships.OutputSchema['memberships'][number] & { - _reactKey: string - } +export type MembershipItem = GetMemberships.Membership & { + _reactKey: string +} export class MembershipsViewModel { // state @@ -17,11 +16,12 @@ export class MembershipsViewModel { params: GetMemberships.QueryParams // data - subject: Subject = { + subject: ActorRef.WithInfo = { did: '', handle: '', displayName: '', declaration: {cid: '', actorType: ''}, + avatar: undefined, } memberships: MembershipItem[] = [] @@ -107,6 +107,8 @@ export class MembershipsViewModel { 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) { diff --git a/src/state/models/notifications-view.ts b/src/state/models/notifications-view.ts index 808b7dee4..12bf3184d 100644 --- a/src/state/models/notifications-view.ts +++ b/src/state/models/notifications-view.ts @@ -1,8 +1,8 @@ import {makeAutoObservable, runInAction} from 'mobx' import * as ListNotifications from '../../third-party/api/src/client/types/app/bsky/notification/list' +import * as ActorRef from '../../third-party/api/src/client/types/app/bsky/actor/ref' import {RootStoreModel} from './root-store' import {PostThreadViewModel} from './post-thread-view' -import {Declaration} from './_common' import {hasProp} from '../lib/type-guards' import {APP_BSKY_GRAPH} from '../../third-party/api' import {cleanError} from '../../lib/strings' @@ -22,12 +22,11 @@ export class NotificationsViewItemModel implements GroupedNotification { // data uri: string = '' cid: string = '' - author: { - did: string - handle: string - displayName?: string - declaration: Declaration - } = {did: '', handle: '', declaration: {cid: '', actorType: ''}} + author: ActorRef.WithInfo = { + did: '', + handle: '', + declaration: {cid: '', actorType: ''}, + } reason: string = '' reasonSubject?: string record: any = {} diff --git a/src/state/models/post-thread-view.ts b/src/state/models/post-thread-view.ts index 5c0e0a4e8..a71587d87 100644 --- a/src/state/models/post-thread-view.ts +++ b/src/state/models/post-thread-view.ts @@ -1,10 +1,20 @@ import {makeAutoObservable, runInAction} from 'mobx' import {AppBskyFeedGetPostThread as GetPostThread} from '../../third-party/api' +import * as Embed from '../../third-party/api/src/client/types/app/bsky/feed/embed' +import * as ActorRef from '../../third-party/api/src/client/types/app/bsky/actor/ref' import {AtUri} from '../../third-party/uri' import _omit from 'lodash.omit' import {RootStoreModel} from './root-store' import * as apilib from '../lib/api' +type MaybePost = + | GetPostThread.Post + | GetPostThread.NotFoundPost + | { + $type: string + [k: string]: unknown + } + function* reactKeyGenerator(): Generator<string> { let counter = 0 while (true) { @@ -16,6 +26,7 @@ interface ReplyingTo { author: { handle: string displayName?: string + avatar?: string } text: string } @@ -40,19 +51,16 @@ export class PostThreadViewPostModel implements GetPostThread.Post { _isHighlightedPost = false // data + $type: string = '' uri: string = '' cid: string = '' - author: GetPostThread.User = { + author: ActorRef.WithInfo = { did: '', handle: '', - displayName: '', declaration: {cid: '', actorType: ''}, } record: Record<string, unknown> = {} - embed?: - | GetPostThread.RecordEmbed - | GetPostThread.ExternalEmbed - | GetPostThread.UnknownEmbed + embed?: Embed.Main = undefined parent?: PostThreadViewPostModel replyCount: number = 0 replies?: PostThreadViewPostModel[] @@ -106,6 +114,7 @@ export class PostThreadViewPostModel implements GetPostThread.Post { author: { handle: v.parent.author.handle, displayName: v.parent.author.displayName, + avatar: v.parent.author.avatar, }, text: (v.parent.record as OriginalRecord).text, } @@ -331,17 +340,30 @@ export class PostThreadViewModel { const thread = new PostThreadViewPostModel( this.rootStore, keyGen.next().value, - res.data.thread, + res.data.thread as GetPostThread.Post, ) thread._isHighlightedPost = true - thread.assignTreeModels(keyGen, res.data.thread) + thread.assignTreeModels(keyGen, res.data.thread as GetPostThread.Post) this.thread = thread } } -function sortThread(post: GetPostThread.Post) { +function sortThread(post: MaybePost) { + if (post.notFound) { + return + } + post = post as GetPostThread.Post if (post.replies) { - post.replies.sort((a: GetPostThread.Post, b: GetPostThread.Post) => { + post.replies.sort((a: MaybePost, b: MaybePost) => { + post = post as GetPostThread.Post + if (a.notFound) { + return 1 + } + if (b.notFound) { + return -1 + } + a = a as GetPostThread.Post + b = b as GetPostThread.Post const aIsByOp = a.author.did === post.author.did const bIsByOp = b.author.did === post.author.did if (aIsByOp && bIsByOp) { diff --git a/src/state/models/post.ts b/src/state/models/post.ts index c6dfaeacd..a3ed83e49 100644 --- a/src/state/models/post.ts +++ b/src/state/models/post.ts @@ -4,8 +4,6 @@ import {AtUri} from '../../third-party/uri' import {RootStoreModel} from './root-store' import {cleanError} from '../../lib/strings' -export type PostEntities = Post.Record['entities'] -export type PostReply = Post.Record['reply'] type RemoveIndex<T> = { [P in keyof T as string extends P ? never @@ -22,8 +20,8 @@ export class PostModel implements RemoveIndex<Post.Record> { // data text: string = '' - entities?: PostEntities - reply?: PostReply + entities?: Post.Entity[] + reply?: Post.ReplyRef createdAt: string = '' constructor(public rootStore: RootStoreModel, uri: string) { diff --git a/src/state/models/profile-view.ts b/src/state/models/profile-view.ts index 83389c82d..787e69e3f 100644 --- a/src/state/models/profile-view.ts +++ b/src/state/models/profile-view.ts @@ -1,9 +1,10 @@ import {makeAutoObservable, runInAction} from 'mobx' +import {Image as PickedImage} from 'react-native-image-crop-picker' import * as GetProfile from '../../third-party/api/src/client/types/app/bsky/actor/getProfile' import * as Profile from '../../third-party/api/src/client/types/app/bsky/actor/profile' +import {Main as DeclRef} from '../../third-party/api/src/client/types/app/bsky/system/declRef' import {Entity} from '../../third-party/api/src/client/types/app/bsky/feed/post' import {extractEntities} from '../../lib/strings' -import {Declaration} from './_common' import {RootStoreModel} from './root-store' import * as apilib from '../lib/api' @@ -30,13 +31,14 @@ export class ProfileViewModel { // data did: string = '' handle: string = '' - declaration: Declaration = { + declaration: DeclRef = { cid: '', actorType: '', } creator: string = '' displayName?: string description?: string + avatar?: string followersCount: number = 0 followsCount: number = 0 membersCount: number = 0 @@ -44,7 +46,6 @@ export class ProfileViewModel { myState = new ProfileViewMyStateModel() // TODO TEMP data to be implemented in the protocol - userAvatar: string | null = null userBanner: string | null = null // added data @@ -120,15 +121,27 @@ export class ProfileViewModel { } async updateProfile( - fn: (existing?: Profile.Record) => Profile.Record, - userAvatar: string | null, // TODO TEMP + updates: Profile.Record, + newUserAvatar: PickedImage | undefined, userBanner: string | null, // TODO TEMP ) { - // TODO TEMP add userBanner & userAvatar in the protocol when suported - this.userAvatar = userAvatar + // TODO TEMP add userBanner to the protocol when suported this.userBanner = userBanner - await apilib.updateProfile(this.rootStore, this.did, fn) + if (newUserAvatar) { + const res = await this.rootStore.api.com.atproto.blob.upload( + newUserAvatar.path, // this will be special-cased by the fetch monkeypatch in /src/state/lib/api.ts + { + encoding: newUserAvatar.mime, + }, + ) + updates.avatar = { + cid: res.data.cid, + mimeType: newUserAvatar.mime, + } + } + await this.rootStore.api.app.bsky.actor.updateProfile(updates) + await this.rootStore.me.load() await this.refresh() } @@ -173,6 +186,7 @@ export class ProfileViewModel { this.creator = res.data.creator this.displayName = res.data.displayName this.description = res.data.description + this.avatar = res.data.avatar this.followersCount = res.data.followersCount this.followsCount = res.data.followsCount this.membersCount = res.data.membersCount diff --git a/src/state/models/reposted-by-view.ts b/src/state/models/reposted-by-view.ts index 211a755dc..4c61bafdc 100644 --- a/src/state/models/reposted-by-view.ts +++ b/src/state/models/reposted-by-view.ts @@ -1,12 +1,10 @@ import {makeAutoObservable, runInAction} from 'mobx' import {AtUri} from '../../third-party/uri' import * as GetRepostedBy from '../../third-party/api/src/client/types/app/bsky/feed/getRepostedBy' +import {Main as DeclRef} from '../../third-party/api/src/client/types/app/bsky/system/declRef' import {RootStoreModel} from './root-store' -import {Declaration} from './_common' -type RepostedByItem = GetRepostedBy.OutputSchema['repostedBy'][number] - -export class RepostedByViewItemModel implements RepostedByItem { +export class RepostedByViewItemModel implements GetRepostedBy.RepostedBy { // ui state _reactKey: string = '' @@ -14,7 +12,8 @@ export class RepostedByViewItemModel implements RepostedByItem { did: string = '' handle: string = '' displayName: string = '' - declaration: Declaration = {cid: '', actorType: ''} + avatar?: string + declaration: DeclRef = {cid: '', actorType: ''} createdAt?: string indexedAt: string = '' diff --git a/src/state/models/session.ts b/src/state/models/session.ts index 1537d1316..feea6643a 100644 --- a/src/state/models/session.ts +++ b/src/state/models/session.ts @@ -30,7 +30,6 @@ export class SessionModel { rootStore: false, serialize: false, hydrate: false, - _connectPromise: false, }) } diff --git a/src/state/models/shell-ui.ts b/src/state/models/shell-ui.ts index b3fe5104f..6777aa7b1 100644 --- a/src/state/models/shell-ui.ts +++ b/src/state/models/shell-ui.ts @@ -58,6 +58,7 @@ export interface ComposerOptsPostRef { author: { handle: string displayName?: string + avatar?: string } } export interface ComposerOpts { diff --git a/src/state/models/suggested-actors-view.ts b/src/state/models/suggested-actors-view.ts index c0a1f7557..0901d5ecc 100644 --- a/src/state/models/suggested-actors-view.ts +++ b/src/state/models/suggested-actors-view.ts @@ -2,8 +2,7 @@ import {makeAutoObservable} from 'mobx' import * as GetSuggestions from '../../third-party/api/src/client/types/app/bsky/actor/getSuggestions' import {RootStoreModel} from './root-store' -type ResponseSuggestedActor = GetSuggestions.OutputSchema['actors'][number] -export type SuggestedActor = ResponseSuggestedActor & { +export type SuggestedActor = GetSuggestions.Actor & { _reactKey: string } diff --git a/src/state/models/user-autocomplete-view.ts b/src/state/models/user-autocomplete-view.ts index 3d53e5db7..b6afa40b2 100644 --- a/src/state/models/user-autocomplete-view.ts +++ b/src/state/models/user-autocomplete-view.ts @@ -11,8 +11,8 @@ export class UserAutocompleteViewModel { _searchPromise: Promise<any> | undefined // data - follows: GetFollows.OutputSchema['follows'] = [] - searchRes: SearchTypeahead.OutputSchema['users'] = [] + follows: GetFollows.Follow[] = [] + searchRes: SearchTypeahead.User[] = [] knownHandles: Set<string> = new Set() constructor(public rootStore: RootStoreModel) { @@ -34,11 +34,13 @@ export class UserAutocompleteViewModel { return this.searchRes.map(user => ({ handle: user.handle, displayName: user.displayName, + avatar: user.avatar, })) } return this.follows.map(follow => ({ handle: follow.handle, displayName: follow.displayName, + avatar: follow.avatar, })) } diff --git a/src/state/models/user-followers-view.ts b/src/state/models/user-followers-view.ts index b27201997..831dfc689 100644 --- a/src/state/models/user-followers-view.ts +++ b/src/state/models/user-followers-view.ts @@ -1,9 +1,9 @@ import {makeAutoObservable} from 'mobx' import * as GetFollowers from '../../third-party/api/src/client/types/app/bsky/graph/getFollowers' +import * as ActorRef from '../../third-party/api/src/client/types/app/bsky/actor/ref' import {RootStoreModel} from './root-store' -type Subject = GetFollowers.OutputSchema['subject'] -export type FollowerItem = GetFollowers.OutputSchema['followers'][number] & { +export type FollowerItem = GetFollowers.Follower & { _reactKey: string } @@ -16,10 +16,9 @@ export class UserFollowersViewModel { params: GetFollowers.QueryParams // data - subject: Subject = { + subject: ActorRef.WithInfo = { did: '', handle: '', - displayName: '', declaration: {cid: '', actorType: ''}, } followers: FollowerItem[] = [] @@ -102,6 +101,7 @@ export class UserFollowersViewModel { this.subject.did = res.data.subject.did this.subject.handle = res.data.subject.handle this.subject.displayName = res.data.subject.displayName + this.subject.avatar = res.data.subject.avatar this.followers.length = 0 let counter = 0 for (const item of res.data.followers) { diff --git a/src/state/models/user-follows-view.ts b/src/state/models/user-follows-view.ts index 13742c327..15af6abc5 100644 --- a/src/state/models/user-follows-view.ts +++ b/src/state/models/user-follows-view.ts @@ -1,9 +1,9 @@ import {makeAutoObservable} from 'mobx' import * as GetFollows from '../../third-party/api/src/client/types/app/bsky/graph/getFollows' +import * as ActorRef from '../../third-party/api/src/client/types/app/bsky/actor/ref' import {RootStoreModel} from './root-store' -type Subject = GetFollows.OutputSchema['subject'] -export type FollowItem = GetFollows.OutputSchema['follows'][number] & { +export type FollowItem = GetFollows.Follow & { _reactKey: string } @@ -16,10 +16,9 @@ export class UserFollowsViewModel { params: GetFollows.QueryParams // data - subject: Subject = { + subject: ActorRef.WithInfo = { did: '', handle: '', - displayName: '', declaration: {cid: '', actorType: ''}, } follows: FollowItem[] = [] @@ -102,6 +101,7 @@ export class UserFollowsViewModel { this.subject.did = res.data.subject.did this.subject.handle = res.data.subject.handle this.subject.displayName = res.data.subject.displayName + this.subject.avatar = res.data.subject.avatar this.follows.length = 0 let counter = 0 for (const item of res.data.follows) { diff --git a/src/state/models/votes-view.ts b/src/state/models/votes-view.ts index d70737021..6e9130e90 100644 --- a/src/state/models/votes-view.ts +++ b/src/state/models/votes-view.ts @@ -1,11 +1,10 @@ import {makeAutoObservable, runInAction} from 'mobx' import {AtUri} from '../../third-party/uri' import * as GetVotes from '../../third-party/api/src/client/types/app/bsky/feed/getVotes' +import * as ActorRef from '../../third-party/api/src/client/types/app/bsky/actor/ref' import {RootStoreModel} from './root-store' -type VoteItem = GetVotes.OutputSchema['votes'][number] - -export class VotesViewItemModel implements VoteItem { +export class VotesViewItemModel implements GetVotes.Vote { // ui state _reactKey: string = '' @@ -13,9 +12,13 @@ export class VotesViewItemModel implements VoteItem { direction: 'up' | 'down' = 'up' indexedAt: string = '' createdAt: string = '' - actor: GetVotes.Actor = {did: '', handle: ''} + actor: ActorRef.WithInfo = { + did: '', + handle: '', + declaration: {cid: '', actorType: ''}, + } - constructor(reactKey: string, v: VoteItem) { + constructor(reactKey: string, v: GetVotes.Vote) { makeAutoObservable(this) this._reactKey = reactKey Object.assign(this, v) @@ -127,7 +130,7 @@ export class VotesViewModel { } } - private _append(keyId: number, item: VoteItem) { + private _append(keyId: number, item: GetVotes.Vote) { this.votes.push(new VotesViewItemModel(`item-${keyId}`, item)) } } |