Bluesky app fork with some witchin' additions 💫

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

+59 -4
+24 -1
src/state/models/feed-view.ts
··· 166 166 did: this.post.author.did, 167 167 rkey: new AtUri(this.post.uri).rkey, 168 168 }) 169 + this.rootStore.emitPostDeleted(this.post.uri) 169 170 } 170 171 } 171 172 ··· 256 257 } 257 258 258 259 /** 260 + * Register any event listeners. Returns a cleanup function. 261 + */ 262 + registerListeners() { 263 + const sub = this.rootStore.onPostDeleted(this.onPostDeleted.bind(this)) 264 + return () => sub.remove() 265 + } 266 + 267 + /** 259 268 * Reset and load 260 269 */ 261 270 async refresh() { ··· 303 312 } 304 313 305 314 /** 306 - * Check if new postrs are available 315 + * Check if new posts are available 307 316 */ 308 317 async checkForLatest() { 309 318 if (this.hasNewLatest) { ··· 320 329 (this.feed.length === 0 || receivedLatestUri !== currentLatestUri), 321 330 ) 322 331 this.setHasNewLatest(hasNewLatest) 332 + } 333 + 334 + /** 335 + * Removes posts from the feed upon deletion. 336 + */ 337 + onPostDeleted(uri: string) { 338 + console.log('hit', uri) 339 + let i 340 + do { 341 + i = this.feed.findIndex(item => item.post.uri === uri) 342 + if (i !== -1) { 343 + this.feed.splice(i, 1) 344 + } 345 + } while (i !== -1) 323 346 } 324 347 325 348 // state transitions
+16
src/state/models/post-thread-view.ts
··· 173 173 did: this.post.author.did, 174 174 rkey: new AtUri(this.post.uri).rkey, 175 175 }) 176 + this.rootStore.emitPostDeleted(this.post.uri) 176 177 } 177 178 } 178 179 ··· 230 231 } 231 232 232 233 /** 234 + * Register any event listeners. Returns a cleanup function. 235 + */ 236 + registerListeners() { 237 + const sub = this.rootStore.onPostDeleted(this.onPostDeleted.bind(this)) 238 + return () => sub.remove() 239 + } 240 + 241 + /** 233 242 * Reset and load 234 243 */ 235 244 async refresh() { ··· 244 253 // if the UI loses its place or has jarring re-arrangements, replace this 245 254 // with a more in-place update 246 255 this._load() 256 + } 257 + 258 + /** 259 + * Refreshes when posts are deleted 260 + */ 261 + onPostDeleted(_uri: string) { 262 + this.refresh() 247 263 } 248 264 249 265 // state transitions
+10
src/state/models/root-store.ts
··· 5 5 import {makeAutoObservable} from 'mobx' 6 6 import {sessionClient as AtpApi, SessionServiceClient} from '@atproto/api' 7 7 import {createContext, useContext} from 'react' 8 + import {DeviceEventEmitter, EmitterSubscription} from 'react-native' 8 9 import {isObj, hasProp} from '../lib/type-guards' 9 10 import {LogModel} from './log' 10 11 import {SessionModel} from './session' ··· 101 102 this.session.clear() 102 103 this.nav.clear() 103 104 this.me.clear() 105 + } 106 + 107 + onPostDeleted(handler: (uri: string) => void): EmitterSubscription { 108 + return DeviceEventEmitter.addListener('post-deleted', handler) 109 + } 110 + 111 + emitPostDeleted(uri: string) { 112 + console.log('emit') 113 + DeviceEventEmitter.emit('post-deleted', uri) 104 114 } 105 115 } 106 116
+1 -1
src/view/com/post-thread/PostThreadItem.tsx
··· 102 102 103 103 if (deleted) { 104 104 return ( 105 - <View style={[styles.outer, pal.view, s.p20, s.flexRow]}> 105 + <View style={[styles.outer, pal.border, pal.view, s.p20, s.flexRow]}> 106 106 <FontAwesomeIcon 107 107 icon={['far', 'trash-can']} 108 108 style={{color: pal.colors.icon}}
+2
src/view/screens/Home.tsx
··· 46 46 ) 47 47 48 48 useEffect(() => { 49 + const feedCleanup = store.me.mainFeed.registerListeners() 49 50 const pollInterval = setInterval(() => doPoll(), 15e3) 50 51 const cleanup = () => { 51 52 clearInterval(pollInterval) 53 + feedCleanup() 52 54 } 53 55 54 56 if (!visible) {
+3 -1
src/view/screens/PostThread.tsx
··· 25 25 } 26 26 useEffect(() => { 27 27 let aborted = false 28 + const threadCleanup = view.registerListeners() 28 29 if (!visible) { 29 - return 30 + return threadCleanup 30 31 } 31 32 setTitle() 32 33 store.shell.setMinimalShellMode(false) ··· 44 45 } 45 46 return () => { 46 47 aborted = true 48 + threadCleanup() 47 49 } 48 50 }, [visible, store.nav, store.log, name]) 49 51
+3 -1
src/view/screens/Profile.tsx
··· 31 31 32 32 useEffect(() => { 33 33 let aborted = false 34 + const feedCleanup = uiState.feed.registerListeners() 34 35 if (!visible) { 35 - return 36 + return feedCleanup 36 37 } 37 38 if (hasSetup) { 38 39 uiState.update() ··· 45 46 } 46 47 return () => { 47 48 aborted = true 49 + feedCleanup() 48 50 } 49 51 }, [visible, params.name, store]) 50 52