|
|
// posts.ts
// Copyright (C) 2020 Dwayne Harris
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import { apiFetch } from '../api' import { setEntities } from '../actions/entities' import { listSet, listAppend } from '../actions/lists' import { startRequest, finishRequest } from '../actions/requests'
import { objectToQuerystring } from '../utils' import { normalize } from '../utils/normalization' import { AppThunkAction, Entity, RequestKey, EntityType, User, Post, Attachment, EntityListKey } from '../types'
interface CreatePostResponse { id: string }
interface CreatePostOptions { installation: string visible: boolean text?: string cover?: string attachments: Attachment[] data?: object parent?: string }
export const createPost = (options: CreatePostOptions): AppThunkAction<string> => { return async dispatch => { const { installation, visible, text, cover, attachments, data, parent } = options dispatch(startRequest(RequestKey.CreatePost))
try { const post = await apiFetch<CreatePostResponse>({ path: `/v1/post`, method: 'post', body: { installation, visible, text, cover, attachments, data, parent, }, })
dispatch(finishRequest(RequestKey.CreatePost, true)) return post.id } catch (err) { dispatch(finishRequest(RequestKey.CreatePost, false)) throw err } } }
interface FetchPostResponse { post: Post, parents: Post[], children: Post[], users: User[], }
export const fetchPost = (id: string): AppThunkAction => { return async dispatch => { dispatch(startRequest(RequestKey.FetchPost))
try { const response = await apiFetch<FetchPostResponse>({ path: `/v1/post/${id}` })
const parents = normalize(response.parents.map(p => ({ ...p, user: response.users.find(u => u.id === p.userId), userId: undefined, })), EntityType.Post)
dispatch(setEntities(parents.entities)) dispatch(listSet(`post:${id}:parents`, parents.keys))
const children = normalize(response.children.map(p => ({ ...p, user: response.users.find(u => u.id === p.userId), userId: undefined, })), EntityType.Post)
dispatch(setEntities(children.entities)) dispatch(listSet(`post:${id}:children`, children.keys))
const post: Entity = { ...response.post, user: response.users.find(u => u.id === response.post.userId), userId: undefined, }
const posts = normalize([post], EntityType.Post) dispatch(setEntities(posts.entities))
dispatch(finishRequest(RequestKey.FetchPost, true)) } catch (err) { dispatch(finishRequest(RequestKey.FetchPost, false)) throw err } } }
interface TimelineResponse { posts: Post[] continuation?: string }
export const fetchTimeline = (continuation?: string): AppThunkAction => async dispatch => { dispatch(startRequest(RequestKey.FetchTimeline))
try { const response = await apiFetch<TimelineResponse>({ path: `/v1/timeline?${objectToQuerystring({ continuation })}`, })
const posts = normalize(response.posts, EntityType.Post)
dispatch(setEntities(posts.entities)) if (continuation) { dispatch(listAppend(EntityListKey.Timeline, posts.keys, response.continuation)) } else { dispatch(listSet(EntityListKey.Timeline, posts.keys, response.continuation)) }
dispatch(finishRequest(RequestKey.FetchTimeline, true)) } catch (err) { dispatch(finishRequest(RequestKey.FetchTimeline, false)) throw err } }
interface UserPostsResponse { user: User posts: Post[] continuation?: string }
export const fetchUserPosts = (id: string, continuation?: string): AppThunkAction => async dispatch => { dispatch(startRequest(RequestKey.FetchUserPosts))
try { const response = await apiFetch<UserPostsResponse>({ path: `/v1/user/${id}/posts`, })
const posts = normalize(response.posts.map(p => ({ ...p, user: response.user, })), EntityType.Post)
dispatch(setEntities(posts.entities)) if (continuation) { dispatch(listAppend(`user:${id}:posts`, posts.keys, response.continuation)) } else { dispatch(listSet(`user:${id}:posts`, posts.keys, response.continuation)) }
dispatch(finishRequest(RequestKey.FetchUserPosts, true)) } catch (err) { dispatch(finishRequest(RequestKey.FetchUserPosts, false)) throw err } }
|