Finish the upvote/downvote implementation
parent
e650d98924
commit
1fbc4cf1f2
|
@ -50,21 +50,45 @@ export async function post(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function like(store: RootStoreModel, uri: string, cid: string) {
|
export async function upvote(store: RootStoreModel, uri: string, cid: string) {
|
||||||
return await store.api.app.bsky.feed.like.create(
|
return await store.api.app.bsky.feed.vote.create(
|
||||||
{did: store.me.did || ''},
|
{did: store.me.did || ''},
|
||||||
{
|
{
|
||||||
subject: {uri, cid},
|
subject: {uri, cid},
|
||||||
|
direction: 'up',
|
||||||
createdAt: new Date().toISOString(),
|
createdAt: new Date().toISOString(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function unlike(store: RootStoreModel, likeUri: string) {
|
export async function unupvote(store: RootStoreModel, upvoteUri: string) {
|
||||||
const likeUrip = new AtUri(likeUri)
|
const urip = new AtUri(upvoteUri)
|
||||||
return await store.api.app.bsky.feed.like.delete({
|
return await store.api.app.bsky.feed.vote.delete({
|
||||||
did: likeUrip.hostname,
|
did: urip.hostname,
|
||||||
rkey: likeUrip.rkey,
|
rkey: urip.rkey,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function downvote(
|
||||||
|
store: RootStoreModel,
|
||||||
|
uri: string,
|
||||||
|
cid: string,
|
||||||
|
) {
|
||||||
|
return await store.api.app.bsky.feed.vote.create(
|
||||||
|
{did: store.me.did || ''},
|
||||||
|
{
|
||||||
|
subject: {uri, cid},
|
||||||
|
direction: 'down',
|
||||||
|
createdAt: new Date().toISOString(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function undownvote(store: RootStoreModel, downvoteUri: string) {
|
||||||
|
const urip = new AtUri(downvoteUri)
|
||||||
|
return await store.api.app.bsky.feed.vote.delete({
|
||||||
|
did: urip.hostname,
|
||||||
|
rkey: urip.rkey,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,8 @@ import * as apilib from '../lib/api'
|
||||||
|
|
||||||
export class FeedItemMyStateModel {
|
export class FeedItemMyStateModel {
|
||||||
repost?: string
|
repost?: string
|
||||||
like?: string
|
upvote?: string
|
||||||
|
downvote?: string
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
makeAutoObservable(this)
|
makeAutoObservable(this)
|
||||||
|
@ -29,7 +30,8 @@ export class FeedItemModel implements GetTimeline.FeedItem {
|
||||||
| GetTimeline.UnknownEmbed
|
| GetTimeline.UnknownEmbed
|
||||||
replyCount: number = 0
|
replyCount: number = 0
|
||||||
repostCount: number = 0
|
repostCount: number = 0
|
||||||
likeCount: number = 0
|
upvoteCount: number = 0
|
||||||
|
downvoteCount: number = 0
|
||||||
indexedAt: string = ''
|
indexedAt: string = ''
|
||||||
myState = new FeedItemMyStateModel()
|
myState = new FeedItemMyStateModel()
|
||||||
|
|
||||||
|
@ -52,26 +54,53 @@ export class FeedItemModel implements GetTimeline.FeedItem {
|
||||||
this.embed = v.embed
|
this.embed = v.embed
|
||||||
this.replyCount = v.replyCount
|
this.replyCount = v.replyCount
|
||||||
this.repostCount = v.repostCount
|
this.repostCount = v.repostCount
|
||||||
this.likeCount = v.likeCount
|
this.upvoteCount = v.upvoteCount
|
||||||
|
this.downvoteCount = v.downvoteCount
|
||||||
this.indexedAt = v.indexedAt
|
this.indexedAt = v.indexedAt
|
||||||
if (v.myState) {
|
if (v.myState) {
|
||||||
this.myState.like = v.myState.like
|
this.myState.upvote = v.myState.upvote
|
||||||
|
this.myState.downvote = v.myState.downvote
|
||||||
this.myState.repost = v.myState.repost
|
this.myState.repost = v.myState.repost
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async toggleLike() {
|
async _clearVotes() {
|
||||||
if (this.myState.like) {
|
if (this.myState.upvote) {
|
||||||
await apilib.unlike(this.rootStore, this.myState.like)
|
await apilib.unupvote(this.rootStore, this.myState.upvote)
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
this.likeCount--
|
this.upvoteCount--
|
||||||
this.myState.like = undefined
|
this.myState.upvote = undefined
|
||||||
})
|
})
|
||||||
} else {
|
}
|
||||||
const res = await apilib.like(this.rootStore, this.uri, this.cid)
|
if (this.myState.downvote) {
|
||||||
|
await apilib.undownvote(this.rootStore, this.myState.downvote)
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
this.likeCount++
|
this.downvoteCount--
|
||||||
this.myState.like = res.uri
|
this.myState.downvote = undefined
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async toggleUpvote() {
|
||||||
|
const wasntUpvoted = !this.myState.upvote
|
||||||
|
await this._clearVotes()
|
||||||
|
if (wasntUpvoted) {
|
||||||
|
const res = await apilib.upvote(this.rootStore, this.uri, this.cid)
|
||||||
|
runInAction(() => {
|
||||||
|
this.upvoteCount++
|
||||||
|
this.myState.upvote = res.uri
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async toggleDownvote() {
|
||||||
|
const wasntDownvoted = !this.myState.downvote
|
||||||
|
await this._clearVotes()
|
||||||
|
if (wasntDownvoted) {
|
||||||
|
const res = await apilib.downvote(this.rootStore, this.uri, this.cid)
|
||||||
|
runInAction(() => {
|
||||||
|
this.downvoteCount++
|
||||||
|
this.myState.downvote = res.uri
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ export class MeModel {
|
||||||
this.did = sess.data.did || ''
|
this.did = sess.data.did || ''
|
||||||
this.handle = sess.data.handle
|
this.handle = sess.data.handle
|
||||||
const profile = await this.rootStore.api.app.bsky.actor.getProfile({
|
const profile = await this.rootStore.api.app.bsky.actor.getProfile({
|
||||||
user: this.did,
|
actor: this.did,
|
||||||
})
|
})
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
if (profile?.data) {
|
if (profile?.data) {
|
||||||
|
|
|
@ -57,8 +57,8 @@ export class NotificationsViewItemModel implements GroupedNotification {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get isLike() {
|
get isUpvote() {
|
||||||
return this.reason === 'like'
|
return this.reason === 'vote'
|
||||||
}
|
}
|
||||||
|
|
||||||
get isRepost() {
|
get isRepost() {
|
||||||
|
|
|
@ -13,8 +13,9 @@ function* reactKeyGenerator(): Generator<string> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PostThreadViewPostMyStateModel {
|
export class PostThreadViewPostMyStateModel {
|
||||||
like?: string
|
|
||||||
repost?: string
|
repost?: string
|
||||||
|
upvote?: string
|
||||||
|
downvote?: string
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
makeAutoObservable(this)
|
makeAutoObservable(this)
|
||||||
|
@ -40,7 +41,8 @@ export class PostThreadViewPostModel implements GetPostThread.Post {
|
||||||
replyCount: number = 0
|
replyCount: number = 0
|
||||||
replies?: PostThreadViewPostModel[]
|
replies?: PostThreadViewPostModel[]
|
||||||
repostCount: number = 0
|
repostCount: number = 0
|
||||||
likeCount: number = 0
|
upvoteCount: number = 0
|
||||||
|
downvoteCount: number = 0
|
||||||
indexedAt: string = ''
|
indexedAt: string = ''
|
||||||
myState = new PostThreadViewPostMyStateModel()
|
myState = new PostThreadViewPostMyStateModel()
|
||||||
|
|
||||||
|
@ -105,18 +107,43 @@ export class PostThreadViewPostModel implements GetPostThread.Post {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async toggleLike() {
|
async _clearVotes() {
|
||||||
if (this.myState.like) {
|
if (this.myState.upvote) {
|
||||||
await apilib.unlike(this.rootStore, this.myState.like)
|
await apilib.unupvote(this.rootStore, this.myState.upvote)
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
this.likeCount--
|
this.upvoteCount--
|
||||||
this.myState.like = undefined
|
this.myState.upvote = undefined
|
||||||
})
|
})
|
||||||
} else {
|
}
|
||||||
const res = await apilib.like(this.rootStore, this.uri, this.cid)
|
if (this.myState.downvote) {
|
||||||
|
await apilib.undownvote(this.rootStore, this.myState.downvote)
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
this.likeCount++
|
this.downvoteCount--
|
||||||
this.myState.like = res.uri
|
this.myState.downvote = undefined
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async toggleUpvote() {
|
||||||
|
const wasntUpvoted = !this.myState.upvote
|
||||||
|
await this._clearVotes()
|
||||||
|
if (wasntUpvoted) {
|
||||||
|
const res = await apilib.upvote(this.rootStore, this.uri, this.cid)
|
||||||
|
runInAction(() => {
|
||||||
|
this.upvoteCount++
|
||||||
|
this.myState.upvote = res.uri
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async toggleDownvote() {
|
||||||
|
const wasntDownvoted = !this.myState.downvote
|
||||||
|
await this._clearVotes()
|
||||||
|
if (wasntDownvoted) {
|
||||||
|
const res = await apilib.downvote(this.rootStore, this.uri, this.cid)
|
||||||
|
runInAction(() => {
|
||||||
|
this.downvoteCount++
|
||||||
|
this.myState.downvote = res.uri
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ export class ProfileUiModel {
|
||||||
},
|
},
|
||||||
{autoBind: true},
|
{autoBind: true},
|
||||||
)
|
)
|
||||||
this.profile = new ProfileViewModel(rootStore, {user: params.user})
|
this.profile = new ProfileViewModel(rootStore, {actor: params.user})
|
||||||
this.feed = new FeedModel(rootStore, 'author', {
|
this.feed = new FeedModel(rootStore, 'author', {
|
||||||
author: params.user,
|
author: params.user,
|
||||||
limit: 10,
|
limit: 10,
|
||||||
|
|
|
@ -1,45 +1,41 @@
|
||||||
import {makeAutoObservable, runInAction} from 'mobx'
|
import {makeAutoObservable, runInAction} from 'mobx'
|
||||||
import {AtUri} from '../../third-party/uri'
|
import {AtUri} from '../../third-party/uri'
|
||||||
import * as GetLikedBy from '../../third-party/api/src/client/types/app/bsky/feed/getLikedBy'
|
import * as GetVotes from '../../third-party/api/src/client/types/app/bsky/feed/getVotes'
|
||||||
import {RootStoreModel} from './root-store'
|
import {RootStoreModel} from './root-store'
|
||||||
|
|
||||||
type LikedByItem = GetLikedBy.OutputSchema['likedBy'][number]
|
type VoteItem = GetVotes.OutputSchema['votes'][number]
|
||||||
|
|
||||||
export class LikedByViewItemModel implements LikedByItem {
|
export class VotesViewItemModel implements VoteItem {
|
||||||
// ui state
|
// ui state
|
||||||
_reactKey: string = ''
|
_reactKey: string = ''
|
||||||
|
|
||||||
// data
|
// data
|
||||||
did: string = ''
|
direction: 'up' | 'down' = 'up'
|
||||||
handle: string = ''
|
|
||||||
displayName: string = ''
|
|
||||||
createdAt?: string
|
|
||||||
indexedAt: string = ''
|
indexedAt: string = ''
|
||||||
|
createdAt: string = ''
|
||||||
|
actor: GetVotes.Actor = {did: '', handle: ''}
|
||||||
|
|
||||||
constructor(reactKey: string, v: LikedByItem) {
|
constructor(reactKey: string, v: VoteItem) {
|
||||||
makeAutoObservable(this)
|
makeAutoObservable(this)
|
||||||
this._reactKey = reactKey
|
this._reactKey = reactKey
|
||||||
Object.assign(this, v)
|
Object.assign(this, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class LikedByViewModel {
|
export class VotesViewModel {
|
||||||
// state
|
// state
|
||||||
isLoading = false
|
isLoading = false
|
||||||
isRefreshing = false
|
isRefreshing = false
|
||||||
hasLoaded = false
|
hasLoaded = false
|
||||||
error = ''
|
error = ''
|
||||||
resolvedUri = ''
|
resolvedUri = ''
|
||||||
params: GetLikedBy.QueryParams
|
params: GetVotes.QueryParams
|
||||||
|
|
||||||
// data
|
// data
|
||||||
uri: string = ''
|
uri: string = ''
|
||||||
likedBy: LikedByViewItemModel[] = []
|
votes: VotesViewItemModel[] = []
|
||||||
|
|
||||||
constructor(
|
constructor(public rootStore: RootStoreModel, params: GetVotes.QueryParams) {
|
||||||
public rootStore: RootStoreModel,
|
|
||||||
params: GetLikedBy.QueryParams,
|
|
||||||
) {
|
|
||||||
makeAutoObservable(
|
makeAutoObservable(
|
||||||
this,
|
this,
|
||||||
{
|
{
|
||||||
|
@ -113,7 +109,7 @@ export class LikedByViewModel {
|
||||||
private async _fetch(isRefreshing = false) {
|
private async _fetch(isRefreshing = false) {
|
||||||
this._xLoading(isRefreshing)
|
this._xLoading(isRefreshing)
|
||||||
try {
|
try {
|
||||||
const res = await this.rootStore.api.app.bsky.feed.getLikedBy(
|
const res = await this.rootStore.api.app.bsky.feed.getVotes(
|
||||||
Object.assign({}, this.params, {uri: this.resolvedUri}),
|
Object.assign({}, this.params, {uri: this.resolvedUri}),
|
||||||
)
|
)
|
||||||
this._replaceAll(res)
|
this._replaceAll(res)
|
||||||
|
@ -123,15 +119,15 @@ export class LikedByViewModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _replaceAll(res: GetLikedBy.Response) {
|
private _replaceAll(res: GetVotes.Response) {
|
||||||
this.likedBy.length = 0
|
this.votes.length = 0
|
||||||
let counter = 0
|
let counter = 0
|
||||||
for (const item of res.data.likedBy) {
|
for (const item of res.data.votes) {
|
||||||
this._append(counter++, item)
|
this._append(counter++, item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _append(keyId: number, item: LikedByItem) {
|
private _append(keyId: number, item: VoteItem) {
|
||||||
this.likedBy.push(new LikedByViewItemModel(`item-${keyId}`, item))
|
this.votes.push(new VotesViewItemModel(`item-${keyId}`, item))
|
||||||
}
|
}
|
||||||
}
|
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -21,25 +21,27 @@ import * as ComAtprotoSessionRefresh from './types/com/atproto/session/refresh';
|
||||||
import * as ComAtprotoSyncGetRepo from './types/com/atproto/sync/getRepo';
|
import * as ComAtprotoSyncGetRepo from './types/com/atproto/sync/getRepo';
|
||||||
import * as ComAtprotoSyncGetRoot from './types/com/atproto/sync/getRoot';
|
import * as ComAtprotoSyncGetRoot from './types/com/atproto/sync/getRoot';
|
||||||
import * as ComAtprotoSyncUpdateRepo from './types/com/atproto/sync/updateRepo';
|
import * as ComAtprotoSyncUpdateRepo from './types/com/atproto/sync/updateRepo';
|
||||||
|
import * as AppBskyActorCreateScene from './types/app/bsky/actor/createScene';
|
||||||
import * as AppBskyActorGetProfile from './types/app/bsky/actor/getProfile';
|
import * as AppBskyActorGetProfile from './types/app/bsky/actor/getProfile';
|
||||||
|
import * as AppBskyActorGetSuggestions from './types/app/bsky/actor/getSuggestions';
|
||||||
|
import * as AppBskyActorProfile from './types/app/bsky/actor/profile';
|
||||||
import * as AppBskyActorSearch from './types/app/bsky/actor/search';
|
import * as AppBskyActorSearch from './types/app/bsky/actor/search';
|
||||||
import * as AppBskyActorSearchTypeahead from './types/app/bsky/actor/searchTypeahead';
|
import * as AppBskyActorSearchTypeahead from './types/app/bsky/actor/searchTypeahead';
|
||||||
import * as AppBskyActorProfile from './types/app/bsky/actor/profile';
|
|
||||||
import * as AppBskyActorUpdateProfile from './types/app/bsky/actor/updateProfile';
|
import * as AppBskyActorUpdateProfile from './types/app/bsky/actor/updateProfile';
|
||||||
import * as AppBskyFeedGetAuthorFeed from './types/app/bsky/feed/getAuthorFeed';
|
import * as AppBskyFeedGetAuthorFeed from './types/app/bsky/feed/getAuthorFeed';
|
||||||
import * as AppBskyFeedGetLikedBy from './types/app/bsky/feed/getLikedBy';
|
|
||||||
import * as AppBskyFeedGetPostThread from './types/app/bsky/feed/getPostThread';
|
import * as AppBskyFeedGetPostThread from './types/app/bsky/feed/getPostThread';
|
||||||
import * as AppBskyFeedGetRepostedBy from './types/app/bsky/feed/getRepostedBy';
|
import * as AppBskyFeedGetRepostedBy from './types/app/bsky/feed/getRepostedBy';
|
||||||
import * as AppBskyFeedGetTimeline from './types/app/bsky/feed/getTimeline';
|
import * as AppBskyFeedGetTimeline from './types/app/bsky/feed/getTimeline';
|
||||||
import * as AppBskyFeedLike from './types/app/bsky/feed/like';
|
import * as AppBskyFeedGetVotes from './types/app/bsky/feed/getVotes';
|
||||||
import * as AppBskyFeedMediaEmbed from './types/app/bsky/feed/mediaEmbed';
|
import * as AppBskyFeedMediaEmbed from './types/app/bsky/feed/mediaEmbed';
|
||||||
import * as AppBskyFeedPost from './types/app/bsky/feed/post';
|
import * as AppBskyFeedPost from './types/app/bsky/feed/post';
|
||||||
import * as AppBskyFeedRepost from './types/app/bsky/feed/repost';
|
import * as AppBskyFeedRepost from './types/app/bsky/feed/repost';
|
||||||
|
import * as AppBskyFeedVote from './types/app/bsky/feed/vote';
|
||||||
|
import * as AppBskyGraphAssertion from './types/app/bsky/graph/assertion';
|
||||||
|
import * as AppBskyGraphConfirmation from './types/app/bsky/graph/confirmation';
|
||||||
import * as AppBskyGraphFollow from './types/app/bsky/graph/follow';
|
import * as AppBskyGraphFollow from './types/app/bsky/graph/follow';
|
||||||
import * as AppBskyGraphGetFollowers from './types/app/bsky/graph/getFollowers';
|
import * as AppBskyGraphGetFollowers from './types/app/bsky/graph/getFollowers';
|
||||||
import * as AppBskyGraphGetFollows from './types/app/bsky/graph/getFollows';
|
import * as AppBskyGraphGetFollows from './types/app/bsky/graph/getFollows';
|
||||||
import * as AppBskyGraphInvite from './types/app/bsky/graph/invite';
|
|
||||||
import * as AppBskyGraphInviteAccept from './types/app/bsky/graph/inviteAccept';
|
|
||||||
import * as AppBskyNotificationGetCount from './types/app/bsky/notification/getCount';
|
import * as AppBskyNotificationGetCount from './types/app/bsky/notification/getCount';
|
||||||
import * as AppBskyNotificationList from './types/app/bsky/notification/list';
|
import * as AppBskyNotificationList from './types/app/bsky/notification/list';
|
||||||
import * as AppBskyNotificationUpdateSeen from './types/app/bsky/notification/updateSeen';
|
import * as AppBskyNotificationUpdateSeen from './types/app/bsky/notification/updateSeen';
|
||||||
|
@ -66,29 +68,35 @@ export * as ComAtprotoSessionRefresh from './types/com/atproto/session/refresh';
|
||||||
export * as ComAtprotoSyncGetRepo from './types/com/atproto/sync/getRepo';
|
export * as ComAtprotoSyncGetRepo from './types/com/atproto/sync/getRepo';
|
||||||
export * as ComAtprotoSyncGetRoot from './types/com/atproto/sync/getRoot';
|
export * as ComAtprotoSyncGetRoot from './types/com/atproto/sync/getRoot';
|
||||||
export * as ComAtprotoSyncUpdateRepo from './types/com/atproto/sync/updateRepo';
|
export * as ComAtprotoSyncUpdateRepo from './types/com/atproto/sync/updateRepo';
|
||||||
|
export * as AppBskyActorCreateScene from './types/app/bsky/actor/createScene';
|
||||||
export * as AppBskyActorGetProfile from './types/app/bsky/actor/getProfile';
|
export * as AppBskyActorGetProfile from './types/app/bsky/actor/getProfile';
|
||||||
|
export * as AppBskyActorGetSuggestions from './types/app/bsky/actor/getSuggestions';
|
||||||
|
export * as AppBskyActorProfile from './types/app/bsky/actor/profile';
|
||||||
export * as AppBskyActorSearch from './types/app/bsky/actor/search';
|
export * as AppBskyActorSearch from './types/app/bsky/actor/search';
|
||||||
export * as AppBskyActorSearchTypeahead from './types/app/bsky/actor/searchTypeahead';
|
export * as AppBskyActorSearchTypeahead from './types/app/bsky/actor/searchTypeahead';
|
||||||
export * as AppBskyActorProfile from './types/app/bsky/actor/profile';
|
|
||||||
export * as AppBskyActorUpdateProfile from './types/app/bsky/actor/updateProfile';
|
export * as AppBskyActorUpdateProfile from './types/app/bsky/actor/updateProfile';
|
||||||
export * as AppBskyFeedGetAuthorFeed from './types/app/bsky/feed/getAuthorFeed';
|
export * as AppBskyFeedGetAuthorFeed from './types/app/bsky/feed/getAuthorFeed';
|
||||||
export * as AppBskyFeedGetLikedBy from './types/app/bsky/feed/getLikedBy';
|
|
||||||
export * as AppBskyFeedGetPostThread from './types/app/bsky/feed/getPostThread';
|
export * as AppBskyFeedGetPostThread from './types/app/bsky/feed/getPostThread';
|
||||||
export * as AppBskyFeedGetRepostedBy from './types/app/bsky/feed/getRepostedBy';
|
export * as AppBskyFeedGetRepostedBy from './types/app/bsky/feed/getRepostedBy';
|
||||||
export * as AppBskyFeedGetTimeline from './types/app/bsky/feed/getTimeline';
|
export * as AppBskyFeedGetTimeline from './types/app/bsky/feed/getTimeline';
|
||||||
export * as AppBskyFeedLike from './types/app/bsky/feed/like';
|
export * as AppBskyFeedGetVotes from './types/app/bsky/feed/getVotes';
|
||||||
export * as AppBskyFeedMediaEmbed from './types/app/bsky/feed/mediaEmbed';
|
export * as AppBskyFeedMediaEmbed from './types/app/bsky/feed/mediaEmbed';
|
||||||
export * as AppBskyFeedPost from './types/app/bsky/feed/post';
|
export * as AppBskyFeedPost from './types/app/bsky/feed/post';
|
||||||
export * as AppBskyFeedRepost from './types/app/bsky/feed/repost';
|
export * as AppBskyFeedRepost from './types/app/bsky/feed/repost';
|
||||||
|
export * as AppBskyFeedVote from './types/app/bsky/feed/vote';
|
||||||
|
export * as AppBskyGraphAssertion from './types/app/bsky/graph/assertion';
|
||||||
|
export * as AppBskyGraphConfirmation from './types/app/bsky/graph/confirmation';
|
||||||
export * as AppBskyGraphFollow from './types/app/bsky/graph/follow';
|
export * as AppBskyGraphFollow from './types/app/bsky/graph/follow';
|
||||||
export * as AppBskyGraphGetFollowers from './types/app/bsky/graph/getFollowers';
|
export * as AppBskyGraphGetFollowers from './types/app/bsky/graph/getFollowers';
|
||||||
export * as AppBskyGraphGetFollows from './types/app/bsky/graph/getFollows';
|
export * as AppBskyGraphGetFollows from './types/app/bsky/graph/getFollows';
|
||||||
export * as AppBskyGraphInvite from './types/app/bsky/graph/invite';
|
|
||||||
export * as AppBskyGraphInviteAccept from './types/app/bsky/graph/inviteAccept';
|
|
||||||
export * as AppBskyNotificationGetCount from './types/app/bsky/notification/getCount';
|
export * as AppBskyNotificationGetCount from './types/app/bsky/notification/getCount';
|
||||||
export * as AppBskyNotificationList from './types/app/bsky/notification/list';
|
export * as AppBskyNotificationList from './types/app/bsky/notification/list';
|
||||||
export * as AppBskyNotificationUpdateSeen from './types/app/bsky/notification/updateSeen';
|
export * as AppBskyNotificationUpdateSeen from './types/app/bsky/notification/updateSeen';
|
||||||
export * as AppBskySystemDeclaration from './types/app/bsky/system/declaration';
|
export * as AppBskySystemDeclaration from './types/app/bsky/system/declaration';
|
||||||
|
export declare const APP_BSKY_GRAPH: {
|
||||||
|
AssertCreator: string;
|
||||||
|
AssertMember: string;
|
||||||
|
};
|
||||||
export declare const APP_BSKY_SYSTEM: {
|
export declare const APP_BSKY_SYSTEM: {
|
||||||
ActorScene: string;
|
ActorScene: string;
|
||||||
ActorUser: string;
|
ActorUser: string;
|
||||||
|
@ -187,7 +195,9 @@ export declare class ActorNS {
|
||||||
_service: ServiceClient;
|
_service: ServiceClient;
|
||||||
profile: ProfileRecord;
|
profile: ProfileRecord;
|
||||||
constructor(service: ServiceClient);
|
constructor(service: ServiceClient);
|
||||||
|
createScene(data?: AppBskyActorCreateScene.InputSchema, opts?: AppBskyActorCreateScene.CallOptions): Promise<AppBskyActorCreateScene.Response>;
|
||||||
getProfile(params?: AppBskyActorGetProfile.QueryParams, opts?: AppBskyActorGetProfile.CallOptions): Promise<AppBskyActorGetProfile.Response>;
|
getProfile(params?: AppBskyActorGetProfile.QueryParams, opts?: AppBskyActorGetProfile.CallOptions): Promise<AppBskyActorGetProfile.Response>;
|
||||||
|
getSuggestions(params?: AppBskyActorGetSuggestions.QueryParams, opts?: AppBskyActorGetSuggestions.CallOptions): Promise<AppBskyActorGetSuggestions.Response>;
|
||||||
search(params?: AppBskyActorSearch.QueryParams, opts?: AppBskyActorSearch.CallOptions): Promise<AppBskyActorSearch.Response>;
|
search(params?: AppBskyActorSearch.QueryParams, opts?: AppBskyActorSearch.CallOptions): Promise<AppBskyActorSearch.Response>;
|
||||||
searchTypeahead(params?: AppBskyActorSearchTypeahead.QueryParams, opts?: AppBskyActorSearchTypeahead.CallOptions): Promise<AppBskyActorSearchTypeahead.Response>;
|
searchTypeahead(params?: AppBskyActorSearchTypeahead.QueryParams, opts?: AppBskyActorSearchTypeahead.CallOptions): Promise<AppBskyActorSearchTypeahead.Response>;
|
||||||
updateProfile(data?: AppBskyActorUpdateProfile.InputSchema, opts?: AppBskyActorUpdateProfile.CallOptions): Promise<AppBskyActorUpdateProfile.Response>;
|
updateProfile(data?: AppBskyActorUpdateProfile.InputSchema, opts?: AppBskyActorUpdateProfile.CallOptions): Promise<AppBskyActorUpdateProfile.Response>;
|
||||||
|
@ -215,37 +225,16 @@ export declare class ProfileRecord {
|
||||||
}
|
}
|
||||||
export declare class FeedNS {
|
export declare class FeedNS {
|
||||||
_service: ServiceClient;
|
_service: ServiceClient;
|
||||||
like: LikeRecord;
|
|
||||||
mediaEmbed: MediaEmbedRecord;
|
mediaEmbed: MediaEmbedRecord;
|
||||||
post: PostRecord;
|
post: PostRecord;
|
||||||
repost: RepostRecord;
|
repost: RepostRecord;
|
||||||
|
vote: VoteRecord;
|
||||||
constructor(service: ServiceClient);
|
constructor(service: ServiceClient);
|
||||||
getAuthorFeed(params?: AppBskyFeedGetAuthorFeed.QueryParams, opts?: AppBskyFeedGetAuthorFeed.CallOptions): Promise<AppBskyFeedGetAuthorFeed.Response>;
|
getAuthorFeed(params?: AppBskyFeedGetAuthorFeed.QueryParams, opts?: AppBskyFeedGetAuthorFeed.CallOptions): Promise<AppBskyFeedGetAuthorFeed.Response>;
|
||||||
getLikedBy(params?: AppBskyFeedGetLikedBy.QueryParams, opts?: AppBskyFeedGetLikedBy.CallOptions): Promise<AppBskyFeedGetLikedBy.Response>;
|
|
||||||
getPostThread(params?: AppBskyFeedGetPostThread.QueryParams, opts?: AppBskyFeedGetPostThread.CallOptions): Promise<AppBskyFeedGetPostThread.Response>;
|
getPostThread(params?: AppBskyFeedGetPostThread.QueryParams, opts?: AppBskyFeedGetPostThread.CallOptions): Promise<AppBskyFeedGetPostThread.Response>;
|
||||||
getRepostedBy(params?: AppBskyFeedGetRepostedBy.QueryParams, opts?: AppBskyFeedGetRepostedBy.CallOptions): Promise<AppBskyFeedGetRepostedBy.Response>;
|
getRepostedBy(params?: AppBskyFeedGetRepostedBy.QueryParams, opts?: AppBskyFeedGetRepostedBy.CallOptions): Promise<AppBskyFeedGetRepostedBy.Response>;
|
||||||
getTimeline(params?: AppBskyFeedGetTimeline.QueryParams, opts?: AppBskyFeedGetTimeline.CallOptions): Promise<AppBskyFeedGetTimeline.Response>;
|
getTimeline(params?: AppBskyFeedGetTimeline.QueryParams, opts?: AppBskyFeedGetTimeline.CallOptions): Promise<AppBskyFeedGetTimeline.Response>;
|
||||||
}
|
getVotes(params?: AppBskyFeedGetVotes.QueryParams, opts?: AppBskyFeedGetVotes.CallOptions): Promise<AppBskyFeedGetVotes.Response>;
|
||||||
export declare class LikeRecord {
|
|
||||||
_service: ServiceClient;
|
|
||||||
constructor(service: ServiceClient);
|
|
||||||
list(params: Omit<ComAtprotoRepoListRecords.QueryParams, 'collection'>): Promise<{
|
|
||||||
cursor?: string;
|
|
||||||
records: {
|
|
||||||
uri: string;
|
|
||||||
value: AppBskyFeedLike.Record;
|
|
||||||
}[];
|
|
||||||
}>;
|
|
||||||
get(params: Omit<ComAtprotoRepoGetRecord.QueryParams, 'collection'>): Promise<{
|
|
||||||
uri: string;
|
|
||||||
cid: string;
|
|
||||||
value: AppBskyFeedLike.Record;
|
|
||||||
}>;
|
|
||||||
create(params: Omit<ComAtprotoRepoCreateRecord.InputSchema, 'collection' | 'record'>, record: AppBskyFeedLike.Record, headers?: Record<string, string>): Promise<{
|
|
||||||
uri: string;
|
|
||||||
cid: string;
|
|
||||||
}>;
|
|
||||||
delete(params: Omit<ComAtprotoRepoDeleteRecord.QueryParams, 'collection'>, headers?: Record<string, string>): Promise<void>;
|
|
||||||
}
|
}
|
||||||
export declare class MediaEmbedRecord {
|
export declare class MediaEmbedRecord {
|
||||||
_service: ServiceClient;
|
_service: ServiceClient;
|
||||||
|
@ -310,15 +299,78 @@ export declare class RepostRecord {
|
||||||
}>;
|
}>;
|
||||||
delete(params: Omit<ComAtprotoRepoDeleteRecord.QueryParams, 'collection'>, headers?: Record<string, string>): Promise<void>;
|
delete(params: Omit<ComAtprotoRepoDeleteRecord.QueryParams, 'collection'>, headers?: Record<string, string>): Promise<void>;
|
||||||
}
|
}
|
||||||
|
export declare class VoteRecord {
|
||||||
|
_service: ServiceClient;
|
||||||
|
constructor(service: ServiceClient);
|
||||||
|
list(params: Omit<ComAtprotoRepoListRecords.QueryParams, 'collection'>): Promise<{
|
||||||
|
cursor?: string;
|
||||||
|
records: {
|
||||||
|
uri: string;
|
||||||
|
value: AppBskyFeedVote.Record;
|
||||||
|
}[];
|
||||||
|
}>;
|
||||||
|
get(params: Omit<ComAtprotoRepoGetRecord.QueryParams, 'collection'>): Promise<{
|
||||||
|
uri: string;
|
||||||
|
cid: string;
|
||||||
|
value: AppBskyFeedVote.Record;
|
||||||
|
}>;
|
||||||
|
create(params: Omit<ComAtprotoRepoCreateRecord.InputSchema, 'collection' | 'record'>, record: AppBskyFeedVote.Record, headers?: Record<string, string>): Promise<{
|
||||||
|
uri: string;
|
||||||
|
cid: string;
|
||||||
|
}>;
|
||||||
|
delete(params: Omit<ComAtprotoRepoDeleteRecord.QueryParams, 'collection'>, headers?: Record<string, string>): Promise<void>;
|
||||||
|
}
|
||||||
export declare class GraphNS {
|
export declare class GraphNS {
|
||||||
_service: ServiceClient;
|
_service: ServiceClient;
|
||||||
|
assertion: AssertionRecord;
|
||||||
|
confirmation: ConfirmationRecord;
|
||||||
follow: FollowRecord;
|
follow: FollowRecord;
|
||||||
invite: InviteRecord;
|
|
||||||
inviteAccept: InviteAcceptRecord;
|
|
||||||
constructor(service: ServiceClient);
|
constructor(service: ServiceClient);
|
||||||
getFollowers(params?: AppBskyGraphGetFollowers.QueryParams, opts?: AppBskyGraphGetFollowers.CallOptions): Promise<AppBskyGraphGetFollowers.Response>;
|
getFollowers(params?: AppBskyGraphGetFollowers.QueryParams, opts?: AppBskyGraphGetFollowers.CallOptions): Promise<AppBskyGraphGetFollowers.Response>;
|
||||||
getFollows(params?: AppBskyGraphGetFollows.QueryParams, opts?: AppBskyGraphGetFollows.CallOptions): Promise<AppBskyGraphGetFollows.Response>;
|
getFollows(params?: AppBskyGraphGetFollows.QueryParams, opts?: AppBskyGraphGetFollows.CallOptions): Promise<AppBskyGraphGetFollows.Response>;
|
||||||
}
|
}
|
||||||
|
export declare class AssertionRecord {
|
||||||
|
_service: ServiceClient;
|
||||||
|
constructor(service: ServiceClient);
|
||||||
|
list(params: Omit<ComAtprotoRepoListRecords.QueryParams, 'collection'>): Promise<{
|
||||||
|
cursor?: string;
|
||||||
|
records: {
|
||||||
|
uri: string;
|
||||||
|
value: AppBskyGraphAssertion.Record;
|
||||||
|
}[];
|
||||||
|
}>;
|
||||||
|
get(params: Omit<ComAtprotoRepoGetRecord.QueryParams, 'collection'>): Promise<{
|
||||||
|
uri: string;
|
||||||
|
cid: string;
|
||||||
|
value: AppBskyGraphAssertion.Record;
|
||||||
|
}>;
|
||||||
|
create(params: Omit<ComAtprotoRepoCreateRecord.InputSchema, 'collection' | 'record'>, record: AppBskyGraphAssertion.Record, headers?: Record<string, string>): Promise<{
|
||||||
|
uri: string;
|
||||||
|
cid: string;
|
||||||
|
}>;
|
||||||
|
delete(params: Omit<ComAtprotoRepoDeleteRecord.QueryParams, 'collection'>, headers?: Record<string, string>): Promise<void>;
|
||||||
|
}
|
||||||
|
export declare class ConfirmationRecord {
|
||||||
|
_service: ServiceClient;
|
||||||
|
constructor(service: ServiceClient);
|
||||||
|
list(params: Omit<ComAtprotoRepoListRecords.QueryParams, 'collection'>): Promise<{
|
||||||
|
cursor?: string;
|
||||||
|
records: {
|
||||||
|
uri: string;
|
||||||
|
value: AppBskyGraphConfirmation.Record;
|
||||||
|
}[];
|
||||||
|
}>;
|
||||||
|
get(params: Omit<ComAtprotoRepoGetRecord.QueryParams, 'collection'>): Promise<{
|
||||||
|
uri: string;
|
||||||
|
cid: string;
|
||||||
|
value: AppBskyGraphConfirmation.Record;
|
||||||
|
}>;
|
||||||
|
create(params: Omit<ComAtprotoRepoCreateRecord.InputSchema, 'collection' | 'record'>, record: AppBskyGraphConfirmation.Record, headers?: Record<string, string>): Promise<{
|
||||||
|
uri: string;
|
||||||
|
cid: string;
|
||||||
|
}>;
|
||||||
|
delete(params: Omit<ComAtprotoRepoDeleteRecord.QueryParams, 'collection'>, headers?: Record<string, string>): Promise<void>;
|
||||||
|
}
|
||||||
export declare class FollowRecord {
|
export declare class FollowRecord {
|
||||||
_service: ServiceClient;
|
_service: ServiceClient;
|
||||||
constructor(service: ServiceClient);
|
constructor(service: ServiceClient);
|
||||||
|
@ -340,48 +392,6 @@ export declare class FollowRecord {
|
||||||
}>;
|
}>;
|
||||||
delete(params: Omit<ComAtprotoRepoDeleteRecord.QueryParams, 'collection'>, headers?: Record<string, string>): Promise<void>;
|
delete(params: Omit<ComAtprotoRepoDeleteRecord.QueryParams, 'collection'>, headers?: Record<string, string>): Promise<void>;
|
||||||
}
|
}
|
||||||
export declare class InviteRecord {
|
|
||||||
_service: ServiceClient;
|
|
||||||
constructor(service: ServiceClient);
|
|
||||||
list(params: Omit<ComAtprotoRepoListRecords.QueryParams, 'collection'>): Promise<{
|
|
||||||
cursor?: string;
|
|
||||||
records: {
|
|
||||||
uri: string;
|
|
||||||
value: AppBskyGraphInvite.Record;
|
|
||||||
}[];
|
|
||||||
}>;
|
|
||||||
get(params: Omit<ComAtprotoRepoGetRecord.QueryParams, 'collection'>): Promise<{
|
|
||||||
uri: string;
|
|
||||||
cid: string;
|
|
||||||
value: AppBskyGraphInvite.Record;
|
|
||||||
}>;
|
|
||||||
create(params: Omit<ComAtprotoRepoCreateRecord.InputSchema, 'collection' | 'record'>, record: AppBskyGraphInvite.Record, headers?: Record<string, string>): Promise<{
|
|
||||||
uri: string;
|
|
||||||
cid: string;
|
|
||||||
}>;
|
|
||||||
delete(params: Omit<ComAtprotoRepoDeleteRecord.QueryParams, 'collection'>, headers?: Record<string, string>): Promise<void>;
|
|
||||||
}
|
|
||||||
export declare class InviteAcceptRecord {
|
|
||||||
_service: ServiceClient;
|
|
||||||
constructor(service: ServiceClient);
|
|
||||||
list(params: Omit<ComAtprotoRepoListRecords.QueryParams, 'collection'>): Promise<{
|
|
||||||
cursor?: string;
|
|
||||||
records: {
|
|
||||||
uri: string;
|
|
||||||
value: AppBskyGraphInviteAccept.Record;
|
|
||||||
}[];
|
|
||||||
}>;
|
|
||||||
get(params: Omit<ComAtprotoRepoGetRecord.QueryParams, 'collection'>): Promise<{
|
|
||||||
uri: string;
|
|
||||||
cid: string;
|
|
||||||
value: AppBskyGraphInviteAccept.Record;
|
|
||||||
}>;
|
|
||||||
create(params: Omit<ComAtprotoRepoCreateRecord.InputSchema, 'collection' | 'record'>, record: AppBskyGraphInviteAccept.Record, headers?: Record<string, string>): Promise<{
|
|
||||||
uri: string;
|
|
||||||
cid: string;
|
|
||||||
}>;
|
|
||||||
delete(params: Omit<ComAtprotoRepoDeleteRecord.QueryParams, 'collection'>, headers?: Record<string, string>): Promise<void>;
|
|
||||||
}
|
|
||||||
export declare class NotificationNS {
|
export declare class NotificationNS {
|
||||||
_service: ServiceClient;
|
_service: ServiceClient;
|
||||||
constructor(service: ServiceClient);
|
constructor(service: ServiceClient);
|
||||||
|
|
|
@ -3,13 +3,13 @@ export declare const methodSchemaDict: Record<string, MethodSchema>;
|
||||||
export declare const methodSchemas: MethodSchema[];
|
export declare const methodSchemas: MethodSchema[];
|
||||||
export declare const ids: {
|
export declare const ids: {
|
||||||
AppBskyActorProfile: string;
|
AppBskyActorProfile: string;
|
||||||
AppBskyFeedLike: string;
|
|
||||||
AppBskyFeedMediaEmbed: string;
|
AppBskyFeedMediaEmbed: string;
|
||||||
AppBskyFeedPost: string;
|
AppBskyFeedPost: string;
|
||||||
AppBskyFeedRepost: string;
|
AppBskyFeedRepost: string;
|
||||||
|
AppBskyFeedVote: string;
|
||||||
|
AppBskyGraphAssertion: string;
|
||||||
|
AppBskyGraphConfirmation: string;
|
||||||
AppBskyGraphFollow: string;
|
AppBskyGraphFollow: string;
|
||||||
AppBskyGraphInvite: string;
|
|
||||||
AppBskyGraphInviteAccept: string;
|
|
||||||
AppBskySystemDeclaration: string;
|
AppBskySystemDeclaration: string;
|
||||||
};
|
};
|
||||||
export declare const recordSchemaDict: Record<string, RecordSchema>;
|
export declare const recordSchemaDict: Record<string, RecordSchema>;
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { Headers, XRPCError } from '@atproto/xrpc';
|
||||||
|
export interface QueryParams {
|
||||||
|
}
|
||||||
|
export interface CallOptions {
|
||||||
|
headers?: Headers;
|
||||||
|
qp?: QueryParams;
|
||||||
|
encoding: 'application/json';
|
||||||
|
}
|
||||||
|
export interface InputSchema {
|
||||||
|
handle: string;
|
||||||
|
recoveryKey?: string;
|
||||||
|
}
|
||||||
|
export interface OutputSchema {
|
||||||
|
handle: string;
|
||||||
|
did: string;
|
||||||
|
declarationCid: string;
|
||||||
|
}
|
||||||
|
export interface Response {
|
||||||
|
success: boolean;
|
||||||
|
headers: Headers;
|
||||||
|
data: OutputSchema;
|
||||||
|
}
|
||||||
|
export declare class InvalidHandleError extends XRPCError {
|
||||||
|
constructor(src: XRPCError);
|
||||||
|
}
|
||||||
|
export declare class HandleNotAvailableError extends XRPCError {
|
||||||
|
constructor(src: XRPCError);
|
||||||
|
}
|
||||||
|
export declare function toKnownErr(e: any): any;
|
|
@ -1,18 +1,23 @@
|
||||||
import { Headers } from '@atproto/xrpc';
|
import { Headers } from '@atproto/xrpc';
|
||||||
export interface QueryParams {
|
export interface QueryParams {
|
||||||
user: string;
|
actor: string;
|
||||||
}
|
}
|
||||||
export interface CallOptions {
|
export interface CallOptions {
|
||||||
headers?: Headers;
|
headers?: Headers;
|
||||||
}
|
}
|
||||||
export declare type InputSchema = undefined;
|
export declare type InputSchema = undefined;
|
||||||
|
export declare type ActorKnown = 'app.bsky.system.actorUser' | 'app.bsky.system.actorScene';
|
||||||
|
export declare type ActorUnknown = string;
|
||||||
export interface OutputSchema {
|
export interface OutputSchema {
|
||||||
did: string;
|
did: string;
|
||||||
handle: string;
|
handle: string;
|
||||||
|
actorType: ActorKnown | ActorUnknown;
|
||||||
|
creator: string;
|
||||||
displayName?: string;
|
displayName?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
followersCount: number;
|
followersCount: number;
|
||||||
followsCount: number;
|
followsCount: number;
|
||||||
|
membersCount: number;
|
||||||
postsCount: number;
|
postsCount: number;
|
||||||
myState?: {
|
myState?: {
|
||||||
follow?: string;
|
follow?: string;
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { Headers } from '@atproto/xrpc';
|
||||||
|
export interface QueryParams {
|
||||||
|
limit?: number;
|
||||||
|
cursor?: string;
|
||||||
|
}
|
||||||
|
export interface CallOptions {
|
||||||
|
headers?: Headers;
|
||||||
|
}
|
||||||
|
export declare type InputSchema = undefined;
|
||||||
|
export interface OutputSchema {
|
||||||
|
cursor?: string;
|
||||||
|
actors: {
|
||||||
|
did: string;
|
||||||
|
handle: string;
|
||||||
|
actorType: string;
|
||||||
|
displayName?: string;
|
||||||
|
description?: string;
|
||||||
|
indexedAt?: string;
|
||||||
|
myState?: {
|
||||||
|
follow?: string;
|
||||||
|
};
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
export interface Response {
|
||||||
|
success: boolean;
|
||||||
|
headers: Headers;
|
||||||
|
data: OutputSchema;
|
||||||
|
}
|
||||||
|
export declare function toKnownErr(e: any): any;
|
|
@ -21,11 +21,13 @@ export interface FeedItem {
|
||||||
embed?: RecordEmbed | ExternalEmbed | UnknownEmbed;
|
embed?: RecordEmbed | ExternalEmbed | UnknownEmbed;
|
||||||
replyCount: number;
|
replyCount: number;
|
||||||
repostCount: number;
|
repostCount: number;
|
||||||
likeCount: number;
|
upvoteCount: number;
|
||||||
|
downvoteCount: number;
|
||||||
indexedAt: string;
|
indexedAt: string;
|
||||||
myState?: {
|
myState?: {
|
||||||
repost?: string;
|
repost?: string;
|
||||||
like?: string;
|
upvote?: string;
|
||||||
|
downvote?: string;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
export interface User {
|
export interface User {
|
||||||
|
|
|
@ -19,12 +19,14 @@ export interface Post {
|
||||||
parent?: Post;
|
parent?: Post;
|
||||||
replyCount: number;
|
replyCount: number;
|
||||||
replies?: Post[];
|
replies?: Post[];
|
||||||
likeCount: number;
|
|
||||||
repostCount: number;
|
repostCount: number;
|
||||||
|
upvoteCount: number;
|
||||||
|
downvoteCount: number;
|
||||||
indexedAt: string;
|
indexedAt: string;
|
||||||
myState?: {
|
myState?: {
|
||||||
repost?: string;
|
repost?: string;
|
||||||
like?: string;
|
upvote?: string;
|
||||||
|
downvote?: string;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
export interface User {
|
export interface User {
|
||||||
|
|
|
@ -21,11 +21,13 @@ export interface FeedItem {
|
||||||
embed?: RecordEmbed | ExternalEmbed | UnknownEmbed;
|
embed?: RecordEmbed | ExternalEmbed | UnknownEmbed;
|
||||||
replyCount: number;
|
replyCount: number;
|
||||||
repostCount: number;
|
repostCount: number;
|
||||||
likeCount: number;
|
upvoteCount: number;
|
||||||
|
downvoteCount: number;
|
||||||
indexedAt: string;
|
indexedAt: string;
|
||||||
myState?: {
|
myState?: {
|
||||||
repost?: string;
|
repost?: string;
|
||||||
like?: string;
|
upvote?: string;
|
||||||
|
downvote?: string;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
export interface User {
|
export interface User {
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
import { Headers } from '@atproto/xrpc';
|
||||||
|
export interface QueryParams {
|
||||||
|
uri: string;
|
||||||
|
cid?: string;
|
||||||
|
direction?: string;
|
||||||
|
limit?: number;
|
||||||
|
before?: string;
|
||||||
|
}
|
||||||
|
export interface CallOptions {
|
||||||
|
headers?: Headers;
|
||||||
|
}
|
||||||
|
export declare type InputSchema = undefined;
|
||||||
|
export interface OutputSchema {
|
||||||
|
uri: string;
|
||||||
|
cid?: string;
|
||||||
|
cursor?: string;
|
||||||
|
votes: {
|
||||||
|
direction: 'up' | 'down';
|
||||||
|
indexedAt: string;
|
||||||
|
createdAt: string;
|
||||||
|
actor: Actor;
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
export interface Actor {
|
||||||
|
did: string;
|
||||||
|
handle: string;
|
||||||
|
displayName?: string;
|
||||||
|
}
|
||||||
|
export interface Response {
|
||||||
|
success: boolean;
|
||||||
|
headers: Headers;
|
||||||
|
data: OutputSchema;
|
||||||
|
}
|
||||||
|
export declare function toKnownErr(e: any): any;
|
|
@ -0,0 +1,11 @@
|
||||||
|
export interface Record {
|
||||||
|
subject: Subject;
|
||||||
|
direction: 'up' | 'down';
|
||||||
|
createdAt: string;
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
export interface Subject {
|
||||||
|
uri: string;
|
||||||
|
cid: string;
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
export interface Record {
|
||||||
|
assertion: string;
|
||||||
|
subject: {
|
||||||
|
did: string;
|
||||||
|
declarationCid: string;
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
createdAt: string;
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
export interface Record {
|
||||||
|
originator: {
|
||||||
|
did: string;
|
||||||
|
declarationCid: string;
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
assertion: {
|
||||||
|
uri: string;
|
||||||
|
cid: string;
|
||||||
|
[k: string]: unknown;
|
||||||
|
};
|
||||||
|
createdAt: string;
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
File diff suppressed because one or more lines are too long
|
@ -6,6 +6,7 @@ import {FontAwesomeIcon, Props} from '@fortawesome/react-native-fontawesome'
|
||||||
import {NotificationsViewItemModel} from '../../../state/models/notifications-view'
|
import {NotificationsViewItemModel} from '../../../state/models/notifications-view'
|
||||||
import {s, colors} from '../../lib/styles'
|
import {s, colors} from '../../lib/styles'
|
||||||
import {ago, pluralize} from '../../lib/strings'
|
import {ago, pluralize} from '../../lib/strings'
|
||||||
|
import {UpIconSolid} from '../../lib/icons'
|
||||||
import {UserAvatar} from '../util/UserAvatar'
|
import {UserAvatar} from '../util/UserAvatar'
|
||||||
import {PostText} from '../post/PostText'
|
import {PostText} from '../post/PostText'
|
||||||
import {Post} from '../post/Post'
|
import {Post} from '../post/Post'
|
||||||
|
@ -19,7 +20,7 @@ export const FeedItem = observer(function FeedItem({
|
||||||
item: NotificationsViewItemModel
|
item: NotificationsViewItemModel
|
||||||
}) {
|
}) {
|
||||||
const itemHref = useMemo(() => {
|
const itemHref = useMemo(() => {
|
||||||
if (item.isLike || item.isRepost) {
|
if (item.isUpvote || item.isRepost) {
|
||||||
const urip = new AtUri(item.subjectUri)
|
const urip = new AtUri(item.subjectUri)
|
||||||
return `/profile/${urip.host}/post/${urip.rkey}`
|
return `/profile/${urip.host}/post/${urip.rkey}`
|
||||||
} else if (item.isFollow) {
|
} else if (item.isFollow) {
|
||||||
|
@ -31,7 +32,7 @@ export const FeedItem = observer(function FeedItem({
|
||||||
return ''
|
return ''
|
||||||
}, [item])
|
}, [item])
|
||||||
const itemTitle = useMemo(() => {
|
const itemTitle = useMemo(() => {
|
||||||
if (item.isLike || item.isRepost) {
|
if (item.isUpvote || item.isRepost) {
|
||||||
return 'Post'
|
return 'Post'
|
||||||
} else if (item.isFollow) {
|
} else if (item.isFollow) {
|
||||||
return item.author.handle
|
return item.author.handle
|
||||||
|
@ -55,16 +56,16 @@ export const FeedItem = observer(function FeedItem({
|
||||||
}
|
}
|
||||||
|
|
||||||
let action = ''
|
let action = ''
|
||||||
let icon: Props['icon']
|
let icon: Props['icon'] | 'UpIconSolid'
|
||||||
let iconStyle: Props['style'] = []
|
let iconStyle: Props['style'] = []
|
||||||
if (item.isLike) {
|
if (item.isUpvote) {
|
||||||
action = 'liked your post'
|
action = 'upvoted your post'
|
||||||
icon = ['fas', 'heart']
|
icon = 'UpIconSolid'
|
||||||
iconStyle = [s.blue3]
|
iconStyle = [s.red3, {position: 'relative', top: -4}]
|
||||||
} else if (item.isRepost) {
|
} else if (item.isRepost) {
|
||||||
action = 'reposted your post'
|
action = 'reposted your post'
|
||||||
icon = 'retweet'
|
icon = 'retweet'
|
||||||
iconStyle = [s.blue3]
|
iconStyle = [s.green3]
|
||||||
} else if (item.isReply) {
|
} else if (item.isReply) {
|
||||||
action = 'replied to your post'
|
action = 'replied to your post'
|
||||||
icon = ['far', 'comment']
|
icon = ['far', 'comment']
|
||||||
|
@ -100,11 +101,15 @@ export const FeedItem = observer(function FeedItem({
|
||||||
title={itemTitle}>
|
title={itemTitle}>
|
||||||
<View style={styles.layout}>
|
<View style={styles.layout}>
|
||||||
<View style={styles.layoutIcon}>
|
<View style={styles.layoutIcon}>
|
||||||
<FontAwesomeIcon
|
{icon === 'UpIconSolid' ? (
|
||||||
icon={icon}
|
<UpIconSolid size={26} style={[styles.icon, ...iconStyle]} />
|
||||||
size={22}
|
) : (
|
||||||
style={[styles.icon, ...iconStyle]}
|
<FontAwesomeIcon
|
||||||
/>
|
icon={icon}
|
||||||
|
size={22}
|
||||||
|
style={[styles.icon, ...iconStyle]}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.layoutContent}>
|
<View style={styles.layoutContent}>
|
||||||
<View style={styles.avis}>
|
<View style={styles.avis}>
|
||||||
|
@ -150,7 +155,7 @@ export const FeedItem = observer(function FeedItem({
|
||||||
{ago(item.indexedAt)}
|
{ago(item.indexedAt)}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
{item.isLike || item.isRepost ? (
|
{item.isUpvote || item.isRepost ? (
|
||||||
<PostText uri={item.subjectUri} style={[s.gray5]} />
|
<PostText uri={item.subjectUri} style={[s.gray5]} />
|
||||||
) : (
|
) : (
|
||||||
<></>
|
<></>
|
||||||
|
|
|
@ -28,7 +28,8 @@ export const PostThreadItem = observer(function PostThreadItem({
|
||||||
}) {
|
}) {
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const record = item.record as unknown as PostType.Record
|
const record = item.record as unknown as PostType.Record
|
||||||
const hasEngagement = item.likeCount || item.repostCount
|
const hasEngagement =
|
||||||
|
item.upvoteCount || item.downvoteCount || item.repostCount
|
||||||
|
|
||||||
const itemHref = useMemo(() => {
|
const itemHref = useMemo(() => {
|
||||||
const urip = new AtUri(item.uri)
|
const urip = new AtUri(item.uri)
|
||||||
|
@ -37,11 +38,16 @@ export const PostThreadItem = observer(function PostThreadItem({
|
||||||
const itemTitle = `Post by ${item.author.handle}`
|
const itemTitle = `Post by ${item.author.handle}`
|
||||||
const authorHref = `/profile/${item.author.handle}`
|
const authorHref = `/profile/${item.author.handle}`
|
||||||
const authorTitle = item.author.handle
|
const authorTitle = item.author.handle
|
||||||
const likesHref = useMemo(() => {
|
const upvotesHref = useMemo(() => {
|
||||||
const urip = new AtUri(item.uri)
|
const urip = new AtUri(item.uri)
|
||||||
return `/profile/${item.author.handle}/post/${urip.rkey}/liked-by`
|
return `/profile/${item.author.handle}/post/${urip.rkey}/upvoted-by`
|
||||||
}, [item.uri, item.author.handle])
|
}, [item.uri, item.author.handle])
|
||||||
const likesTitle = 'Likes on this post'
|
const upvotesTitle = 'Upvotes on this post'
|
||||||
|
const downvotesHref = useMemo(() => {
|
||||||
|
const urip = new AtUri(item.uri)
|
||||||
|
return `/profile/${item.author.handle}/post/${urip.rkey}/downvoted-by`
|
||||||
|
}, [item.uri, item.author.handle])
|
||||||
|
const downvotesTitle = 'Downvotes on this post'
|
||||||
const repostsHref = useMemo(() => {
|
const repostsHref = useMemo(() => {
|
||||||
const urip = new AtUri(item.uri)
|
const urip = new AtUri(item.uri)
|
||||||
return `/profile/${item.author.handle}/post/${urip.rkey}/reposted-by`
|
return `/profile/${item.author.handle}/post/${urip.rkey}/reposted-by`
|
||||||
|
@ -59,10 +65,15 @@ export const PostThreadItem = observer(function PostThreadItem({
|
||||||
.toggleRepost()
|
.toggleRepost()
|
||||||
.catch(e => console.error('Failed to toggle repost', record, e))
|
.catch(e => console.error('Failed to toggle repost', record, e))
|
||||||
}
|
}
|
||||||
const onPressToggleLike = () => {
|
const onPressToggleUpvote = () => {
|
||||||
item
|
item
|
||||||
.toggleLike()
|
.toggleUpvote()
|
||||||
.catch(e => console.error('Failed to toggle like', record, e))
|
.catch(e => console.error('Failed to toggle upvote', record, e))
|
||||||
|
}
|
||||||
|
const onPressToggleDownvote = () => {
|
||||||
|
item
|
||||||
|
.toggleDownvote()
|
||||||
|
.catch(e => console.error('Failed to toggle downvote', record, e))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item._isHighlightedPost) {
|
if (item._isHighlightedPost) {
|
||||||
|
@ -135,16 +146,31 @@ export const PostThreadItem = observer(function PostThreadItem({
|
||||||
) : (
|
) : (
|
||||||
<></>
|
<></>
|
||||||
)}
|
)}
|
||||||
{item.likeCount ? (
|
{item.upvoteCount ? (
|
||||||
<Link
|
<Link
|
||||||
style={styles.expandedInfoItem}
|
style={styles.expandedInfoItem}
|
||||||
href={likesHref}
|
href={upvotesHref}
|
||||||
title={likesTitle}>
|
title={upvotesTitle}>
|
||||||
<Text style={[s.gray5, s.semiBold, s.f16]}>
|
<Text style={[s.gray5, s.semiBold, s.f16]}>
|
||||||
<Text style={[s.bold, s.black, s.f16]}>
|
<Text style={[s.bold, s.black, s.f16]}>
|
||||||
{item.likeCount}
|
{item.upvoteCount}
|
||||||
</Text>{' '}
|
</Text>{' '}
|
||||||
{pluralize(item.likeCount, 'like')}
|
{pluralize(item.upvoteCount, 'upvote')}
|
||||||
|
</Text>
|
||||||
|
</Link>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
|
{item.downvoteCount ? (
|
||||||
|
<Link
|
||||||
|
style={styles.expandedInfoItem}
|
||||||
|
href={downvotesHref}
|
||||||
|
title={downvotesTitle}>
|
||||||
|
<Text style={[s.gray5, s.semiBold, s.f16]}>
|
||||||
|
<Text style={[s.bold, s.black, s.f16]}>
|
||||||
|
{item.downvoteCount}
|
||||||
|
</Text>{' '}
|
||||||
|
{pluralize(item.downvoteCount, 'downvote')}
|
||||||
</Text>
|
</Text>
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
|
@ -158,12 +184,15 @@ export const PostThreadItem = observer(function PostThreadItem({
|
||||||
<PostCtrls
|
<PostCtrls
|
||||||
replyCount={item.replyCount}
|
replyCount={item.replyCount}
|
||||||
repostCount={item.repostCount}
|
repostCount={item.repostCount}
|
||||||
likeCount={item.likeCount}
|
upvoteCount={item.upvoteCount}
|
||||||
|
downvoteCount={item.downvoteCount}
|
||||||
isReposted={!!item.myState.repost}
|
isReposted={!!item.myState.repost}
|
||||||
isLiked={!!item.myState.like}
|
isUpvoted={!!item.myState.upvote}
|
||||||
|
isDownvoted={!!item.myState.downvote}
|
||||||
onPressReply={onPressReply}
|
onPressReply={onPressReply}
|
||||||
onPressToggleRepost={onPressToggleRepost}
|
onPressToggleRepost={onPressToggleRepost}
|
||||||
onPressToggleLike={onPressToggleLike}
|
onPressToggleUpvote={onPressToggleUpvote}
|
||||||
|
onPressToggleDownvote={onPressToggleDownvote}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
@ -260,12 +289,15 @@ export const PostThreadItem = observer(function PostThreadItem({
|
||||||
<PostCtrls
|
<PostCtrls
|
||||||
replyCount={item.replyCount}
|
replyCount={item.replyCount}
|
||||||
repostCount={item.repostCount}
|
repostCount={item.repostCount}
|
||||||
likeCount={item.likeCount}
|
upvoteCount={item.upvoteCount}
|
||||||
|
downvoteCount={item.downvoteCount}
|
||||||
isReposted={!!item.myState.repost}
|
isReposted={!!item.myState.repost}
|
||||||
isLiked={!!item.myState.like}
|
isUpvoted={!!item.myState.upvote}
|
||||||
|
isDownvoted={!!item.myState.downvote}
|
||||||
onPressReply={onPressReply}
|
onPressReply={onPressReply}
|
||||||
onPressToggleRepost={onPressToggleRepost}
|
onPressToggleRepost={onPressToggleRepost}
|
||||||
onPressToggleLike={onPressToggleLike}
|
onPressToggleUpvote={onPressToggleUpvote}
|
||||||
|
onPressToggleDownvote={onPressToggleDownvote}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
|
@ -2,27 +2,33 @@ import React, {useState, useEffect} from 'react'
|
||||||
import {observer} from 'mobx-react-lite'
|
import {observer} from 'mobx-react-lite'
|
||||||
import {ActivityIndicator, FlatList, StyleSheet, Text, View} from 'react-native'
|
import {ActivityIndicator, FlatList, StyleSheet, Text, View} from 'react-native'
|
||||||
import {
|
import {
|
||||||
LikedByViewModel,
|
VotesViewModel,
|
||||||
LikedByViewItemModel,
|
VotesViewItemModel,
|
||||||
} from '../../../state/models/liked-by-view'
|
} from '../../../state/models/votes-view'
|
||||||
import {Link} from '../util/Link'
|
import {Link} from '../util/Link'
|
||||||
import {UserAvatar} from '../util/UserAvatar'
|
import {UserAvatar} from '../util/UserAvatar'
|
||||||
import {useStores} from '../../../state'
|
import {useStores} from '../../../state'
|
||||||
import {s, colors} from '../../lib/styles'
|
import {s, colors} from '../../lib/styles'
|
||||||
|
|
||||||
export const PostLikedBy = observer(function PostLikedBy({uri}: {uri: string}) {
|
export const PostVotedBy = observer(function PostVotedBy({
|
||||||
|
uri,
|
||||||
|
direction,
|
||||||
|
}: {
|
||||||
|
uri: string
|
||||||
|
direction: 'up' | 'down'
|
||||||
|
}) {
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const [view, setView] = useState<LikedByViewModel | undefined>()
|
const [view, setView] = useState<VotesViewModel | undefined>()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (view?.params.uri === uri) {
|
if (view?.params.uri === uri) {
|
||||||
console.log('Liked by doing nothing')
|
console.log('Voted by doing nothing')
|
||||||
return // no change needed? or trigger refresh?
|
return // no change needed? or trigger refresh?
|
||||||
}
|
}
|
||||||
console.log('Fetching Liked by', uri)
|
console.log('Fetching voted by', uri)
|
||||||
const newView = new LikedByViewModel(store, {uri})
|
const newView = new VotesViewModel(store, {uri, direction})
|
||||||
setView(newView)
|
setView(newView)
|
||||||
newView.setup().catch(err => console.error('Failed to fetch liked by', err))
|
newView.setup().catch(err => console.error('Failed to fetch voted by', err))
|
||||||
}, [uri, view?.params.uri, store])
|
}, [uri, view?.params.uri, store])
|
||||||
|
|
||||||
// loading
|
// loading
|
||||||
|
@ -51,13 +57,13 @@ export const PostLikedBy = observer(function PostLikedBy({uri}: {uri: string}) {
|
||||||
|
|
||||||
// loaded
|
// loaded
|
||||||
// =
|
// =
|
||||||
const renderItem = ({item}: {item: LikedByViewItemModel}) => (
|
const renderItem = ({item}: {item: VotesViewItemModel}) => (
|
||||||
<LikedByItem item={item} />
|
<LikedByItem item={item} />
|
||||||
)
|
)
|
||||||
return (
|
return (
|
||||||
<View>
|
<View>
|
||||||
<FlatList
|
<FlatList
|
||||||
data={view.likedBy}
|
data={view.votes}
|
||||||
keyExtractor={item => item._reactKey}
|
keyExtractor={item => item._reactKey}
|
||||||
renderItem={renderItem}
|
renderItem={renderItem}
|
||||||
/>
|
/>
|
||||||
|
@ -65,23 +71,23 @@ export const PostLikedBy = observer(function PostLikedBy({uri}: {uri: string}) {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
const LikedByItem = ({item}: {item: LikedByViewItemModel}) => {
|
const LikedByItem = ({item}: {item: VotesViewItemModel}) => {
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
style={styles.outer}
|
style={styles.outer}
|
||||||
href={`/profile/${item.handle}`}
|
href={`/profile/${item.actor.handle}`}
|
||||||
title={item.handle}>
|
title={item.actor.handle}>
|
||||||
<View style={styles.layout}>
|
<View style={styles.layout}>
|
||||||
<View style={styles.layoutAvi}>
|
<View style={styles.layoutAvi}>
|
||||||
<UserAvatar
|
<UserAvatar
|
||||||
size={40}
|
size={40}
|
||||||
displayName={item.displayName}
|
displayName={item.actor.displayName}
|
||||||
handle={item.handle}
|
handle={item.actor.handle}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.layoutContent}>
|
<View style={styles.layoutContent}>
|
||||||
<Text style={[s.f15, s.bold]}>{item.displayName}</Text>
|
<Text style={[s.f15, s.bold]}>{item.actor.displayName}</Text>
|
||||||
<Text style={[s.f14, s.gray5]}>@{item.handle}</Text>
|
<Text style={[s.f14, s.gray5]}>@{item.actor.handle}</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</Link>
|
</Link>
|
|
@ -78,10 +78,15 @@ export const Post = observer(function Post({uri}: {uri: string}) {
|
||||||
.toggleRepost()
|
.toggleRepost()
|
||||||
.catch(e => console.error('Failed to toggle repost', record, e))
|
.catch(e => console.error('Failed to toggle repost', record, e))
|
||||||
}
|
}
|
||||||
const onPressToggleLike = () => {
|
const onPressToggleUpvote = () => {
|
||||||
item
|
item
|
||||||
.toggleLike()
|
.toggleUpvote()
|
||||||
.catch(e => console.error('Failed to toggle like', record, e))
|
.catch(e => console.error('Failed to toggle upvote', record, e))
|
||||||
|
}
|
||||||
|
const onPressToggleDownvote = () => {
|
||||||
|
item
|
||||||
|
.toggleDownvote()
|
||||||
|
.catch(e => console.error('Failed to toggle downvote', record, e))
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -129,12 +134,15 @@ export const Post = observer(function Post({uri}: {uri: string}) {
|
||||||
<PostCtrls
|
<PostCtrls
|
||||||
replyCount={item.replyCount}
|
replyCount={item.replyCount}
|
||||||
repostCount={item.repostCount}
|
repostCount={item.repostCount}
|
||||||
likeCount={item.likeCount}
|
upvoteCount={item.upvoteCount}
|
||||||
|
downvoteCount={item.downvoteCount}
|
||||||
isReposted={!!item.myState.repost}
|
isReposted={!!item.myState.repost}
|
||||||
isLiked={!!item.myState.like}
|
isUpvoted={!!item.myState.upvote}
|
||||||
|
isDownvoted={!!item.myState.downvote}
|
||||||
onPressReply={onPressReply}
|
onPressReply={onPressReply}
|
||||||
onPressToggleRepost={onPressToggleRepost}
|
onPressToggleRepost={onPressToggleRepost}
|
||||||
onPressToggleLike={onPressToggleLike}
|
onPressToggleUpvote={onPressToggleUpvote}
|
||||||
|
onPressToggleDownvote={onPressToggleDownvote}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
|
@ -48,10 +48,15 @@ export const FeedItem = observer(function FeedItem({
|
||||||
.toggleRepost()
|
.toggleRepost()
|
||||||
.catch(e => console.error('Failed to toggle repost', record, e))
|
.catch(e => console.error('Failed to toggle repost', record, e))
|
||||||
}
|
}
|
||||||
const onPressToggleLike = () => {
|
const onPressToggleUpvote = () => {
|
||||||
item
|
item
|
||||||
.toggleLike()
|
.toggleUpvote()
|
||||||
.catch(e => console.error('Failed to toggle like', record, e))
|
.catch(e => console.error('Failed to toggle upvote', record, e))
|
||||||
|
}
|
||||||
|
const onPressToggleDownvote = () => {
|
||||||
|
item
|
||||||
|
.toggleDownvote()
|
||||||
|
.catch(e => console.error('Failed to toggle downvote', record, e))
|
||||||
}
|
}
|
||||||
const onPressShare = (uri: string) => {
|
const onPressShare = (uri: string) => {
|
||||||
store.shell.openModal(new SharePostModel(uri))
|
store.shell.openModal(new SharePostModel(uri))
|
||||||
|
@ -129,12 +134,15 @@ export const FeedItem = observer(function FeedItem({
|
||||||
<PostCtrls
|
<PostCtrls
|
||||||
replyCount={item.replyCount}
|
replyCount={item.replyCount}
|
||||||
repostCount={item.repostCount}
|
repostCount={item.repostCount}
|
||||||
likeCount={item.likeCount}
|
upvoteCount={item.upvoteCount}
|
||||||
|
downvoteCount={item.downvoteCount}
|
||||||
isReposted={!!item.myState.repost}
|
isReposted={!!item.myState.repost}
|
||||||
isLiked={!!item.myState.like}
|
isUpvoted={!!item.myState.upvote}
|
||||||
|
isDownvoted={!!item.myState.downvote}
|
||||||
onPressReply={onPressReply}
|
onPressReply={onPressReply}
|
||||||
onPressToggleRepost={onPressToggleRepost}
|
onPressToggleRepost={onPressToggleRepost}
|
||||||
onPressToggleLike={onPressToggleLike}
|
onPressToggleUpvote={onPressToggleUpvote}
|
||||||
|
onPressToggleDownvote={onPressToggleDownvote}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
|
@ -7,12 +7,15 @@ import {s, colors} from '../../lib/styles'
|
||||||
interface PostCtrlsOpts {
|
interface PostCtrlsOpts {
|
||||||
replyCount: number
|
replyCount: number
|
||||||
repostCount: number
|
repostCount: number
|
||||||
likeCount: number
|
upvoteCount: number
|
||||||
|
downvoteCount: number
|
||||||
isReposted: boolean
|
isReposted: boolean
|
||||||
isLiked: boolean
|
isUpvoted: boolean
|
||||||
|
isDownvoted: boolean
|
||||||
onPressReply: () => void
|
onPressReply: () => void
|
||||||
onPressToggleRepost: () => void
|
onPressToggleRepost: () => void
|
||||||
onPressToggleLike: () => void
|
onPressToggleUpvote: () => void
|
||||||
|
onPressToggleDownvote: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export function PostCtrls(opts: PostCtrlsOpts) {
|
export function PostCtrls(opts: PostCtrlsOpts) {
|
||||||
|
@ -36,22 +39,27 @@ export function PostCtrls(opts: PostCtrlsOpts) {
|
||||||
{opts.repostCount}
|
{opts.repostCount}
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity style={styles.ctrl} onPress={opts.onPressToggleLike}>
|
<TouchableOpacity style={styles.ctrl} onPress={opts.onPressToggleUpvote}>
|
||||||
{opts.isLiked ? (
|
{opts.isUpvoted ? (
|
||||||
<UpIconSolid style={styles.ctrlIconUpvoted} size={18} />
|
<UpIconSolid style={styles.ctrlIconUpvoted} size={18} />
|
||||||
) : (
|
) : (
|
||||||
<UpIcon style={styles.ctrlIcon} size={18} />
|
<UpIcon style={styles.ctrlIcon} size={18} />
|
||||||
)}
|
)}
|
||||||
<Text style={opts.isLiked ? [s.bold, s.blue3, s.f13] : s.f13}>
|
<Text style={opts.isUpvoted ? [s.bold, s.red3, s.f13] : s.f13}>
|
||||||
{opts.likeCount}
|
{opts.upvoteCount}
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity style={styles.ctrl} onPress={opts.onPressToggleLike}>
|
<TouchableOpacity
|
||||||
{opts.isLiked ? (
|
style={styles.ctrl}
|
||||||
|
onPress={opts.onPressToggleDownvote}>
|
||||||
|
{opts.isDownvoted ? (
|
||||||
<DownIconSolid style={styles.ctrlIconDownvoted} size={18} />
|
<DownIconSolid style={styles.ctrlIconDownvoted} size={18} />
|
||||||
) : (
|
) : (
|
||||||
<DownIcon style={styles.ctrlIcon} size={18} />
|
<DownIcon style={styles.ctrlIcon} size={18} />
|
||||||
)}
|
)}
|
||||||
|
<Text style={opts.isDownvoted ? [s.bold, s.blue3, s.f13] : s.f13}>
|
||||||
|
{opts.downvoteCount}
|
||||||
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
|
@ -78,10 +86,10 @@ const styles = StyleSheet.create({
|
||||||
},
|
},
|
||||||
ctrlIconUpvoted: {
|
ctrlIconUpvoted: {
|
||||||
marginRight: 5,
|
marginRight: 5,
|
||||||
color: colors.blue3,
|
color: colors.red3,
|
||||||
},
|
},
|
||||||
ctrlIconDownvoted: {
|
ctrlIconDownvoted: {
|
||||||
marginRight: 5,
|
marginRight: 5,
|
||||||
color: colors.red3,
|
color: colors.blue3,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -31,7 +31,7 @@ export function UserInfoText({
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let aborted = false
|
let aborted = false
|
||||||
// TODO use caching to reduce loads
|
// TODO use caching to reduce loads
|
||||||
store.api.app.bsky.actor.getProfile({user: did}).then(
|
store.api.app.bsky.actor.getProfile({actor: did}).then(
|
||||||
v => {
|
v => {
|
||||||
if (aborted) return
|
if (aborted) return
|
||||||
setProfile(v.data)
|
setProfile(v.data)
|
||||||
|
|
|
@ -7,7 +7,8 @@ import {Search} from './screens/Search'
|
||||||
import {Notifications} from './screens/Notifications'
|
import {Notifications} from './screens/Notifications'
|
||||||
import {NotFound} from './screens/NotFound'
|
import {NotFound} from './screens/NotFound'
|
||||||
import {PostThread} from './screens/PostThread'
|
import {PostThread} from './screens/PostThread'
|
||||||
import {PostLikedBy} from './screens/PostLikedBy'
|
import {PostUpvotedBy} from './screens/PostUpvotedBy'
|
||||||
|
import {PostDownvotedBy} from './screens/PostDownvotedBy'
|
||||||
import {PostRepostedBy} from './screens/PostRepostedBy'
|
import {PostRepostedBy} from './screens/PostRepostedBy'
|
||||||
import {Profile} from './screens/Profile'
|
import {Profile} from './screens/Profile'
|
||||||
import {ProfileFollowers} from './screens/ProfileFollowers'
|
import {ProfileFollowers} from './screens/ProfileFollowers'
|
||||||
|
@ -42,9 +43,14 @@ export const routes: Route[] = [
|
||||||
r('/profile/(?<name>[^/]+)/post/(?<rkey>[^/]+)'),
|
r('/profile/(?<name>[^/]+)/post/(?<rkey>[^/]+)'),
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
PostLikedBy,
|
PostUpvotedBy,
|
||||||
'heart',
|
'heart',
|
||||||
r('/profile/(?<name>[^/]+)/post/(?<rkey>[^/]+)/liked-by'),
|
r('/profile/(?<name>[^/]+)/post/(?<rkey>[^/]+)/upvoted-by'),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
PostDownvotedBy,
|
||||||
|
'heart',
|
||||||
|
r('/profile/(?<name>[^/]+)/post/(?<rkey>[^/]+)/downvoted-by'),
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
PostRepostedBy,
|
PostRepostedBy,
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
import React, {useEffect} from 'react'
|
||||||
|
import {View} from 'react-native'
|
||||||
|
import {ViewHeader} from '../com/util/ViewHeader'
|
||||||
|
import {PostVotedBy as PostLikedByComponent} from '../com/post-thread/PostVotedBy'
|
||||||
|
import {ScreenParams} from '../routes'
|
||||||
|
import {useStores} from '../../state'
|
||||||
|
import {makeRecordUri} from '../lib/strings'
|
||||||
|
|
||||||
|
export const PostDownvotedBy = ({visible, params}: ScreenParams) => {
|
||||||
|
const store = useStores()
|
||||||
|
const {name, rkey} = params
|
||||||
|
const uri = makeRecordUri(name, 'app.bsky.feed.post', rkey)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (visible) {
|
||||||
|
store.nav.setTitle('Downvoted by')
|
||||||
|
}
|
||||||
|
}, [store, visible])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<ViewHeader title="Downvoted by" />
|
||||||
|
<PostLikedByComponent uri={uri} direction="down" />
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
|
@ -1,26 +1,26 @@
|
||||||
import React, {useEffect} from 'react'
|
import React, {useEffect} from 'react'
|
||||||
import {View} from 'react-native'
|
import {View} from 'react-native'
|
||||||
import {ViewHeader} from '../com/util/ViewHeader'
|
import {ViewHeader} from '../com/util/ViewHeader'
|
||||||
import {PostLikedBy as PostLikedByComponent} from '../com/post-thread/PostLikedBy'
|
import {PostVotedBy as PostLikedByComponent} from '../com/post-thread/PostVotedBy'
|
||||||
import {ScreenParams} from '../routes'
|
import {ScreenParams} from '../routes'
|
||||||
import {useStores} from '../../state'
|
import {useStores} from '../../state'
|
||||||
import {makeRecordUri} from '../lib/strings'
|
import {makeRecordUri} from '../lib/strings'
|
||||||
|
|
||||||
export const PostLikedBy = ({visible, params}: ScreenParams) => {
|
export const PostUpvotedBy = ({visible, params}: ScreenParams) => {
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const {name, rkey} = params
|
const {name, rkey} = params
|
||||||
const uri = makeRecordUri(name, 'app.bsky.feed.post', rkey)
|
const uri = makeRecordUri(name, 'app.bsky.feed.post', rkey)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
store.nav.setTitle('Liked by')
|
store.nav.setTitle('Upvoted by')
|
||||||
}
|
}
|
||||||
}, [store, visible])
|
}, [store, visible])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View>
|
<View>
|
||||||
<ViewHeader title="Liked by" />
|
<ViewHeader title="Upvoted by" />
|
||||||
<PostLikedByComponent uri={uri} />
|
<PostLikedByComponent uri={uri} direction="up" />
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
Loading…
Reference in New Issue