Update the view after a post is created

zio/stable
Paul Frazee 2022-10-04 11:33:32 -05:00
parent 0aaa406b17
commit 236c908058
9 changed files with 79 additions and 9 deletions

View File

@ -102,6 +102,7 @@ export class FeedViewModel {
params: GetFeedView.QueryParams params: GetFeedView.QueryParams
_loadPromise: Promise<void> | undefined _loadPromise: Promise<void> | undefined
_loadMorePromise: Promise<void> | undefined _loadMorePromise: Promise<void> | undefined
_loadLatestPromise: Promise<void> | undefined
_updatePromise: Promise<void> | undefined _updatePromise: Promise<void> | undefined
// data // data
@ -118,6 +119,7 @@ export class FeedViewModel {
params: false, params: false,
_loadPromise: false, _loadPromise: false,
_loadMorePromise: false, _loadMorePromise: false,
_loadLatestPromise: false,
_updatePromise: false, _updatePromise: false,
}, },
{autoBind: true}, {autoBind: true},
@ -180,6 +182,19 @@ export class FeedViewModel {
this._loadMorePromise = undefined this._loadMorePromise = undefined
} }
/**
* Load more posts to the start of the feed
*/
async loadLatest() {
if (this._loadLatestPromise) {
return this._loadLatestPromise
}
await this._pendingWork()
this._loadLatestPromise = this._loadLatest()
await this._loadLatestPromise
this._loadLatestPromise = undefined
}
/** /**
* Update content in-place * Update content in-place
*/ */
@ -219,6 +234,9 @@ export class FeedViewModel {
if (this._loadMorePromise) { if (this._loadMorePromise) {
await this._loadMorePromise await this._loadMorePromise
} }
if (this._loadLatestPromise) {
await this._loadLatestPromise
}
if (this._updatePromise) { if (this._updatePromise) {
await this._updatePromise await this._updatePromise
} }
@ -235,6 +253,17 @@ export class FeedViewModel {
} }
} }
private async _loadLatest() {
this._xLoading()
try {
const res = await this.rootStore.api.todo.social.getFeed(this.params)
this._prependAll(res)
this._xIdle()
} catch (e: any) {
this._xIdle(`Failed to load feed: ${e.toString()}`)
}
}
private async _loadMore() { private async _loadMore() {
this._xLoading() this._xLoading()
try { try {
@ -298,6 +327,23 @@ export class FeedViewModel {
this.feed.push(new FeedViewItemModel(this.rootStore, `item-${keyId}`, item)) this.feed.push(new FeedViewItemModel(this.rootStore, `item-${keyId}`, item))
} }
private _prependAll(res: GetFeedView.Response) {
let counter = this.feed.length
for (const item of res.data.feed) {
if (this.feed.find(item2 => item2.uri === item.uri)) {
return // stop here - we've hit a post we already ahve
}
this._prepend(counter++, item)
}
}
private _prepend(keyId: number, item: GetFeedView.FeedItem) {
// TODO: validate .record
this.feed.unshift(
new FeedViewItemModel(this.rootStore, `item-${keyId}`, item),
)
}
private _updateAll(res: GetFeedView.Response) { private _updateAll(res: GetFeedView.Response) {
for (const item of res.data.feed) { for (const item of res.data.feed) {
const existingItem = this.feed.find( const existingItem = this.feed.find(

View File

@ -34,11 +34,19 @@ export class SharePostModel {
} }
} }
export interface ComposePostModelOpts {
replyTo?: string
onPost?: () => void
}
export class ComposePostModel { export class ComposePostModel {
name = 'compose-post' name = 'compose-post'
replyTo?: string
onPost?: () => void
constructor(public replyTo?: string) { constructor(opts?: ComposePostModelOpts) {
makeAutoObservable(this) makeAutoObservable(this)
this.replyTo = opts?.replyTo
this.onPost = opts?.onPost
} }
} }

View File

@ -16,7 +16,13 @@ const WARNING_TEXT_LENGTH = 200
const DANGER_TEXT_LENGTH = 255 const DANGER_TEXT_LENGTH = 255
export const snapPoints = ['100%'] export const snapPoints = ['100%']
export function Component({replyTo}: {replyTo?: string}) { export function Component({
replyTo,
onPost,
}: {
replyTo?: string
onPost?: () => void
}) {
const store = useStores() const store = useStores()
const [error, setError] = useState('') const [error, setError] = useState('')
const [text, setText] = useState('') const [text, setText] = useState('')
@ -72,6 +78,7 @@ export function Component({replyTo}: {replyTo?: string}) {
) )
return return
} }
onPost?.()
store.shell.closeModal() store.shell.closeModal()
Toast.show(`Your ${replyTo ? 'reply' : 'post'} has been published`, { Toast.show(`Your ${replyTo ? 'reply' : 'post'} has been published`, {
duration: Toast.durations.LONG, duration: Toast.durations.LONG,

View File

@ -70,7 +70,11 @@ export const PostThread = observer(function PostThread({uri}: {uri: string}) {
// = // =
const posts = view.thread ? Array.from(flattenThread(view.thread)) : [] const posts = view.thread ? Array.from(flattenThread(view.thread)) : []
const renderItem = ({item}: {item: PostThreadViewPostModel}) => ( const renderItem = ({item}: {item: PostThreadViewPostModel}) => (
<PostThreadItem item={item} onPressShare={onPressShare} /> <PostThreadItem
item={item}
onPressShare={onPressShare}
onPostReply={onRefresh}
/>
) )
return ( return (
<FlatList <FlatList

View File

@ -20,9 +20,11 @@ const PARENT_REPLY_LINE_LENGTH = 8
export const PostThreadItem = observer(function PostThreadItem({ export const PostThreadItem = observer(function PostThreadItem({
item, item,
onPressShare, onPressShare,
onPostReply,
}: { }: {
item: PostThreadViewPostModel item: PostThreadViewPostModel
onPressShare: (_uri: string) => void onPressShare: (_uri: string) => void
onPostReply: () => void
}) { }) {
const store = useStores() const store = useStores()
const record = item.record as unknown as PostType.Record const record = item.record as unknown as PostType.Record
@ -47,7 +49,9 @@ export const PostThreadItem = observer(function PostThreadItem({
const repostsTitle = 'Reposts of this post' const repostsTitle = 'Reposts of this post'
const onPressReply = () => { const onPressReply = () => {
store.shell.openModal(new ComposePostModel(item.uri)) store.shell.openModal(
new ComposePostModel({replyTo: item.uri, onPost: onPostReply}),
)
} }
const onPressToggleRepost = () => { const onPressToggleRepost = () => {
item item

View File

@ -72,7 +72,7 @@ export const Post = observer(function Post({uri}: {uri: string}) {
replyHref = `/profile/${urip.hostname}/post/${urip.recordKey}` replyHref = `/profile/${urip.hostname}/post/${urip.recordKey}`
} }
const onPressReply = () => { const onPressReply = () => {
store.shell.openModal(new ComposePostModel(item.uri)) store.shell.openModal(new ComposePostModel({replyTo: item.uri}))
} }
const onPressToggleRepost = () => { const onPressToggleRepost = () => {
item item

View File

@ -40,7 +40,7 @@ export const FeedItem = observer(function FeedItem({
}, [record.reply]) }, [record.reply])
const onPressReply = () => { const onPressReply = () => {
store.shell.openModal(new ComposePostModel(item.uri)) store.shell.openModal(new ComposePostModel({replyTo: item.uri}))
} }
const onPressToggleRepost = () => { const onPressToggleRepost = () => {
item item

View File

@ -31,7 +31,10 @@ export const Home = observer(function Home({visible}: ScreenParams) {
}, [visible, store]) }, [visible, store])
const onComposePress = () => { const onComposePress = () => {
store.shell.openModal(new ComposePostModel()) store.shell.openModal(new ComposePostModel({onPost: onCreatePost}))
}
const onCreatePost = () => {
feedView?.loadLatest()
} }
return ( return (

View File

@ -9,8 +9,6 @@ Paul's todo list
- Private beta - Private beta
- Users list - Users list
- Firehose - Firehose
- Composer
- Update the view after creating a post
- Linking - Linking
- Web linking - Web linking
- App linking - App linking