Update saved feeds to use preferences

zio/stable
Paul Frazee 2023-05-18 14:39:04 -05:00
parent acea0e074d
commit 5537d19e55
8 changed files with 68 additions and 50 deletions

View File

@ -38,7 +38,7 @@ export class CustomFeedModel {
}
get isSaved() {
return this.data.viewer?.saved
return this.rootStore.preferences.savedFeeds.includes(this.uri)
}
get isLiked() {
@ -49,23 +49,11 @@ export class CustomFeedModel {
// =
async save() {
await this.rootStore.agent.app.bsky.feed.saveFeed({
feed: this.uri,
})
runInAction(() => {
this.data.viewer = this.data.viewer || {}
this.data.viewer.saved = true
})
await this.rootStore.preferences.addSavedFeed(this.uri)
}
async unsave() {
await this.rootStore.agent.app.bsky.feed.unsaveFeed({
feed: this.uri,
})
runInAction(() => {
this.data.viewer = this.data.viewer || {}
this.data.viewer.saved = false
})
await this.rootStore.preferences.removeSavedFeed(this.uri)
}
async like() {
@ -82,7 +70,7 @@ export class CustomFeedModel {
}
async unlike() {
if (!this.data.viewer.like) {
if (!this.data.viewer?.like) {
return
}
try {

View File

@ -135,7 +135,7 @@ export class ImageModel implements RNImage {
// Only for mobile
async crop() {
try {
const cropped = await openCropper({
const cropped = await openCropper(this.rootStore, {
mediaType: 'photo',
path: this.path,
freeStyleCropEnabled: true,

View File

@ -46,6 +46,7 @@ export class PreferencesModel {
contentLanguages: string[] =
deviceLocales?.map?.(locale => locale.languageCode) || []
contentLabels = new LabelPreferencesModel()
savedFeeds: string[] = []
pinnedFeeds: string[] = []
constructor(public rootStore: RootStoreModel) {
@ -56,6 +57,7 @@ export class PreferencesModel {
return {
contentLanguages: this.contentLanguages,
contentLabels: this.contentLabels,
savedFeeds: this.savedFeeds,
pinnedFeeds: this.pinnedFeeds,
}
}
@ -75,6 +77,13 @@ export class PreferencesModel {
// default to the device languages
this.contentLanguages = deviceLocales.map(locale => locale.languageCode)
}
if (
hasProp(v, 'savedFeeds') &&
Array.isArray(v.savedFeeds) &&
typeof v.savedFeeds.every(item => typeof item === 'string')
) {
this.savedFeeds = v.savedFeeds
}
if (
hasProp(v, 'pinnedFeeds') &&
Array.isArray(v.pinnedFeeds) &&
@ -106,10 +115,11 @@ export class PreferencesModel {
pref.visibility as LabelPreference
}
} else if (
AppBskyActorDefs.isPinnedFeedsPref(pref) &&
AppBskyActorDefs.validatePinnedFeedsPref(pref).success
AppBskyActorDefs.isSavedFeedsPref(pref) &&
AppBskyActorDefs.validateSavedFeedsPref(pref).success
) {
this.pinnedFeeds = pref.feeds
this.savedFeeds = pref.saved
this.pinnedFeeds = pref.pinned
}
}
})
@ -220,38 +230,57 @@ export class PreferencesModel {
return res
}
async setPinnedFeeds(v: string[]) {
const old = this.pinnedFeeds
this.pinnedFeeds = v
async setSavedFeeds(saved: string[], pinned: string[]) {
const oldSaved = this.savedFeeds
const oldPinned = this.pinnedFeeds
this.savedFeeds = saved
this.pinnedFeeds = pinned
try {
await this.update((prefs: AppBskyActorDefs.Preferences) => {
const existing = prefs.find(
pref =>
AppBskyActorDefs.isPinnedFeedsPref(pref) &&
AppBskyActorDefs.validatePinnedFeedsPref(pref).success,
AppBskyActorDefs.isSavedFeedsPref(pref) &&
AppBskyActorDefs.validateSavedFeedsPref(pref).success,
)
if (existing) {
existing.feeds = v
existing.saved = saved
existing.pinned = pinned
} else {
prefs.push({
$type: 'app.bsky.actor.defs#pinnedFeedsPref',
feeds: v,
$type: 'app.bsky.actor.defs#savedFeedsPref',
saved,
pinned,
})
}
})
} catch (e) {
runInAction(() => {
this.pinnedFeeds = old
this.savedFeeds = oldSaved
this.pinnedFeeds = oldPinned
})
throw e
}
}
async addSavedFeed(v: string) {
return this.setSavedFeeds([...this.savedFeeds, v], this.pinnedFeeds)
}
async removeSavedFeed(v: string) {
return this.setSavedFeeds(
this.savedFeeds.filter(uri => uri !== v),
this.pinnedFeeds.filter(uri => uri !== v),
)
}
async addPinnedFeed(v: string) {
return this.setPinnedFeeds([...this.pinnedFeeds, v])
return this.setSavedFeeds(this.savedFeeds, [...this.pinnedFeeds, v])
}
async removePinnedFeed(v: string) {
return this.setPinnedFeeds(this.pinnedFeeds.filter(uri => uri !== v))
return this.setSavedFeeds(
this.savedFeeds,
this.pinnedFeeds.filter(uri => uri !== v),
)
}
}

View File

@ -5,8 +5,6 @@ import {bundleAsync} from 'lib/async/bundle'
import {cleanError} from 'lib/strings/errors'
import {CustomFeedModel} from '../feeds/custom-feed'
const PAGE_SIZE = 100
export class SavedFeedsModel {
// state
isLoading = false
@ -69,16 +67,15 @@ export class SavedFeedsModel {
try {
let feeds: AppBskyFeedDefs.GeneratorView[] = []
let cursor
for (let i = 0; i < 100; i++) {
const res = await this.rootStore.agent.app.bsky.feed.getSavedFeeds({
limit: PAGE_SIZE,
cursor,
for (
let i = 0;
i < this.rootStore.preferences.savedFeeds.length;
i += 25
) {
const res = await this.rootStore.agent.app.bsky.feed.getFeedGenerators({
feeds: this.rootStore.preferences.savedFeeds.slice(i, 25),
})
feeds = feeds.concat(res.data.feeds)
cursor = res.data.cursor
if (!cursor) {
break
}
}
runInAction(() => {
this.feeds = feeds.map(f => new CustomFeedModel(this.rootStore, f))
@ -127,7 +124,8 @@ export class SavedFeedsModel {
}
async reorderPinnedFeeds(feeds: CustomFeedModel[]) {
return this.rootStore.preferences.setPinnedFeeds(
return this.rootStore.preferences.setSavedFeeds(
this.rootStore.preferences.savedFeeds,
feeds.filter(feed => this.isPinned(feed)).map(feed => feed.uri),
)
}
@ -151,7 +149,10 @@ export class SavedFeedsModel {
pinned[index] = pinned[index + 1]
pinned[index + 1] = temp
}
await this.rootStore.preferences.setPinnedFeeds(pinned)
await this.rootStore.preferences.setSavedFeeds(
this.rootStore.preferences.savedFeeds,
pinned,
)
}
// state transitions

View File

@ -119,7 +119,7 @@ export type Modal =
// Moderation
| ReportAccountModal
| ReportPostModal
| CreateMuteListModal
| CreateOrEditMuteListModal
| ListAddRemoveUserModal
// Posts

View File

@ -40,7 +40,7 @@ export const CustomFeed = observer(
const navigation = useNavigation<NavigationProp>()
const onToggleSaved = React.useCallback(async () => {
if (item.data.viewer?.saved) {
if (item.isSaved) {
store.shell.openModal({
name: 'confirm',
title: 'Remove from my feeds',

View File

@ -121,7 +121,7 @@ const Container = observer(
}: {
children: React.ReactNode
hideOnScroll: boolean
showBorder: boolean
showBorder?: boolean
}) => {
const store = useStores()
const pal = usePalette('default')

View File

@ -27,6 +27,10 @@ export function ImageHider({
setOverride(false)
}, [setOverride])
if (moderation.behavior === ModerationBehaviorCode.Hide) {
return null
}
if (moderation.behavior !== ModerationBehaviorCode.WarnImages) {
return (
<View testID={testID} style={style}>
@ -35,10 +39,6 @@ export function ImageHider({
)
}
if (moderation.behavior === ModerationBehaviorCode.Hide) {
return null
}
return (
<View style={[styles.container, containerStyle]}>
<View testID={testID} style={style}>