about summary refs log tree commit diff
path: root/src/state/models/ui/my-feeds.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/state/models/ui/my-feeds.ts')
-rw-r--r--src/state/models/ui/my-feeds.ts157
1 files changed, 157 insertions, 0 deletions
diff --git a/src/state/models/ui/my-feeds.ts b/src/state/models/ui/my-feeds.ts
new file mode 100644
index 000000000..f9ad06f77
--- /dev/null
+++ b/src/state/models/ui/my-feeds.ts
@@ -0,0 +1,157 @@
+import {makeAutoObservable} from 'mobx'
+import {FeedsDiscoveryModel} from '../discovery/feeds'
+import {CustomFeedModel} from '../feeds/custom-feed'
+import {RootStoreModel} from '../root-store'
+
+export type MyFeedsItem =
+  | {
+      _reactKey: string
+      type: 'spinner'
+    }
+  | {
+      _reactKey: string
+      type: 'discover-feeds-loading'
+    }
+  | {
+      _reactKey: string
+      type: 'error'
+      error: string
+    }
+  | {
+      _reactKey: string
+      type: 'saved-feeds-header'
+    }
+  | {
+      _reactKey: string
+      type: 'saved-feed'
+      feed: CustomFeedModel
+    }
+  | {
+      _reactKey: string
+      type: 'saved-feeds-load-more'
+    }
+  | {
+      _reactKey: string
+      type: 'discover-feeds-header'
+    }
+  | {
+      _reactKey: string
+      type: 'discover-feeds-no-results'
+    }
+  | {
+      _reactKey: string
+      type: 'discover-feed'
+      feed: CustomFeedModel
+    }
+
+export class MyFeedsUIModel {
+  discovery: FeedsDiscoveryModel
+
+  constructor(public rootStore: RootStoreModel) {
+    makeAutoObservable(this)
+    this.discovery = new FeedsDiscoveryModel(this.rootStore)
+  }
+
+  get saved() {
+    return this.rootStore.me.savedFeeds
+  }
+
+  get isRefreshing() {
+    return !this.saved.isLoading && this.saved.isRefreshing
+  }
+
+  get isLoading() {
+    return this.saved.isLoading || this.discovery.isLoading
+  }
+
+  async setup() {
+    if (!this.saved.hasLoaded) {
+      await this.saved.refresh()
+    }
+    if (!this.discovery.hasLoaded) {
+      await this.discovery.refresh()
+    }
+  }
+
+  async refresh() {
+    return Promise.all([this.saved.refresh(), this.discovery.refresh()])
+  }
+
+  async loadMore() {
+    return this.discovery.loadMore()
+  }
+
+  get items() {
+    let items: MyFeedsItem[] = []
+
+    items.push({
+      _reactKey: '__saved_feeds_header__',
+      type: 'saved-feeds-header',
+    })
+    if (this.saved.isLoading) {
+      items.push({
+        _reactKey: '__saved_feeds_loading__',
+        type: 'spinner',
+      })
+    } else if (this.saved.hasError) {
+      items.push({
+        _reactKey: '__saved_feeds_error__',
+        type: 'error',
+        error: this.saved.error,
+      })
+    } else {
+      const savedSorted = this.saved.all
+        .slice()
+        .sort((a, b) => a.displayName.localeCompare(b.displayName))
+      items = items.concat(
+        savedSorted.map(feed => ({
+          _reactKey: `saved-${feed.uri}`,
+          type: 'saved-feed',
+          feed,
+        })),
+      )
+      items.push({
+        _reactKey: '__saved_feeds_load_more__',
+        type: 'saved-feeds-load-more',
+      })
+    }
+
+    items.push({
+      _reactKey: '__discover_feeds_header__',
+      type: 'discover-feeds-header',
+    })
+    if (this.discovery.isLoading && !this.discovery.hasContent) {
+      items.push({
+        _reactKey: '__discover_feeds_loading__',
+        type: 'discover-feeds-loading',
+      })
+    } else if (this.discovery.hasError) {
+      items.push({
+        _reactKey: '__discover_feeds_error__',
+        type: 'error',
+        error: this.discovery.error,
+      })
+    } else if (this.discovery.isEmpty) {
+      items.push({
+        _reactKey: '__discover_feeds_no_results__',
+        type: 'discover-feeds-no-results',
+      })
+    } else {
+      items = items.concat(
+        this.discovery.feeds.map(feed => ({
+          _reactKey: `discover-${feed.uri}`,
+          type: 'discover-feed',
+          feed,
+        })),
+      )
+      if (this.discovery.isLoading) {
+        items.push({
+          _reactKey: '__discover_feeds_loading_more__',
+          type: 'spinner',
+        })
+      }
+    }
+
+    return items
+  }
+}