Handle post deletions by removing from active views (close #37)

zio/stable
Paul Frazee 2023-01-18 16:45:48 -06:00
parent ace0e6bfd9
commit ebc2033d18
7 changed files with 59 additions and 4 deletions

View File

@ -166,6 +166,7 @@ export class FeedItemModel {
did: this.post.author.did, did: this.post.author.did,
rkey: new AtUri(this.post.uri).rkey, rkey: new AtUri(this.post.uri).rkey,
}) })
this.rootStore.emitPostDeleted(this.post.uri)
} }
} }
@ -255,6 +256,14 @@ export class FeedModel {
this._loadPromise = undefined this._loadPromise = undefined
} }
/**
* Register any event listeners. Returns a cleanup function.
*/
registerListeners() {
const sub = this.rootStore.onPostDeleted(this.onPostDeleted.bind(this))
return () => sub.remove()
}
/** /**
* Reset and load * Reset and load
*/ */
@ -303,7 +312,7 @@ export class FeedModel {
} }
/** /**
* Check if new postrs are available * Check if new posts are available
*/ */
async checkForLatest() { async checkForLatest() {
if (this.hasNewLatest) { if (this.hasNewLatest) {
@ -322,6 +331,20 @@ export class FeedModel {
this.setHasNewLatest(hasNewLatest) this.setHasNewLatest(hasNewLatest)
} }
/**
* Removes posts from the feed upon deletion.
*/
onPostDeleted(uri: string) {
console.log('hit', uri)
let i
do {
i = this.feed.findIndex(item => item.post.uri === uri)
if (i !== -1) {
this.feed.splice(i, 1)
}
} while (i !== -1)
}
// state transitions // state transitions
// = // =

View File

@ -173,6 +173,7 @@ export class PostThreadViewPostModel {
did: this.post.author.did, did: this.post.author.did,
rkey: new AtUri(this.post.uri).rkey, rkey: new AtUri(this.post.uri).rkey,
}) })
this.rootStore.emitPostDeleted(this.post.uri)
} }
} }
@ -229,6 +230,14 @@ export class PostThreadViewModel {
} }
} }
/**
* Register any event listeners. Returns a cleanup function.
*/
registerListeners() {
const sub = this.rootStore.onPostDeleted(this.onPostDeleted.bind(this))
return () => sub.remove()
}
/** /**
* Reset and load * Reset and load
*/ */
@ -246,6 +255,13 @@ export class PostThreadViewModel {
this._load() this._load()
} }
/**
* Refreshes when posts are deleted
*/
onPostDeleted(_uri: string) {
this.refresh()
}
// state transitions // state transitions
// = // =

View File

@ -5,6 +5,7 @@
import {makeAutoObservable} from 'mobx' import {makeAutoObservable} from 'mobx'
import {sessionClient as AtpApi, SessionServiceClient} from '@atproto/api' import {sessionClient as AtpApi, SessionServiceClient} from '@atproto/api'
import {createContext, useContext} from 'react' import {createContext, useContext} from 'react'
import {DeviceEventEmitter, EmitterSubscription} from 'react-native'
import {isObj, hasProp} from '../lib/type-guards' import {isObj, hasProp} from '../lib/type-guards'
import {LogModel} from './log' import {LogModel} from './log'
import {SessionModel} from './session' import {SessionModel} from './session'
@ -102,6 +103,15 @@ export class RootStoreModel {
this.nav.clear() this.nav.clear()
this.me.clear() this.me.clear()
} }
onPostDeleted(handler: (uri: string) => void): EmitterSubscription {
return DeviceEventEmitter.addListener('post-deleted', handler)
}
emitPostDeleted(uri: string) {
console.log('emit')
DeviceEventEmitter.emit('post-deleted', uri)
}
} }
const throwawayInst = new RootStoreModel(AtpApi.service('http://localhost')) // this will be replaced by the loader, we just need to supply a value at init const throwawayInst = new RootStoreModel(AtpApi.service('http://localhost')) // this will be replaced by the loader, we just need to supply a value at init

View File

@ -102,7 +102,7 @@ export const PostThreadItem = observer(function PostThreadItem({
if (deleted) { if (deleted) {
return ( return (
<View style={[styles.outer, pal.view, s.p20, s.flexRow]}> <View style={[styles.outer, pal.border, pal.view, s.p20, s.flexRow]}>
<FontAwesomeIcon <FontAwesomeIcon
icon={['far', 'trash-can']} icon={['far', 'trash-can']}
style={{color: pal.colors.icon}} style={{color: pal.colors.icon}}

View File

@ -46,9 +46,11 @@ export const Home = observer(function Home({
) )
useEffect(() => { useEffect(() => {
const feedCleanup = store.me.mainFeed.registerListeners()
const pollInterval = setInterval(() => doPoll(), 15e3) const pollInterval = setInterval(() => doPoll(), 15e3)
const cleanup = () => { const cleanup = () => {
clearInterval(pollInterval) clearInterval(pollInterval)
feedCleanup()
} }
if (!visible) { if (!visible) {

View File

@ -25,8 +25,9 @@ export const PostThread = ({navIdx, visible, params}: ScreenParams) => {
} }
useEffect(() => { useEffect(() => {
let aborted = false let aborted = false
const threadCleanup = view.registerListeners()
if (!visible) { if (!visible) {
return return threadCleanup
} }
setTitle() setTitle()
store.shell.setMinimalShellMode(false) store.shell.setMinimalShellMode(false)
@ -44,6 +45,7 @@ export const PostThread = ({navIdx, visible, params}: ScreenParams) => {
} }
return () => { return () => {
aborted = true aborted = true
threadCleanup()
} }
}, [visible, store.nav, store.log, name]) }, [visible, store.nav, store.log, name])

View File

@ -31,8 +31,9 @@ export const Profile = observer(({navIdx, visible, params}: ScreenParams) => {
useEffect(() => { useEffect(() => {
let aborted = false let aborted = false
const feedCleanup = uiState.feed.registerListeners()
if (!visible) { if (!visible) {
return return feedCleanup
} }
if (hasSetup) { if (hasSetup) {
uiState.update() uiState.update()
@ -45,6 +46,7 @@ export const Profile = observer(({navIdx, visible, params}: ScreenParams) => {
} }
return () => { return () => {
aborted = true aborted = true
feedCleanup()
} }
}, [visible, params.name, store]) }, [visible, params.name, store])