[ABANDONED] React/Redux front end for the Flexor social network.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

183 lines
5.6 KiB

// 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
}
}