[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

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. // posts.ts
  2. // Copyright (C) 2020 Dwayne Harris
  3. // This program is free software: you can redistribute it and/or modify
  4. // it under the terms of the GNU General Public License as published by
  5. // the Free Software Foundation, either version 3 of the License, or
  6. // (at your option) any later version.
  7. // This program is distributed in the hope that it will be useful,
  8. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. // GNU General Public License for more details.
  11. // You should have received a copy of the GNU General Public License
  12. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  13. import { apiFetch } from '../api'
  14. import { setEntities } from '../actions/entities'
  15. import { listSet, listAppend } from '../actions/lists'
  16. import { startRequest, finishRequest } from '../actions/requests'
  17. import { objectToQuerystring } from '../utils'
  18. import { normalize } from '../utils/normalization'
  19. import { AppThunkAction, Entity, RequestKey, EntityType, User, Post, Attachment, EntityListKey } from '../types'
  20. interface CreatePostResponse {
  21. id: string
  22. }
  23. interface CreatePostOptions {
  24. installation: string
  25. visible: boolean
  26. text?: string
  27. cover?: string
  28. attachments: Attachment[]
  29. data?: object
  30. parent?: string
  31. }
  32. export const createPost = (options: CreatePostOptions): AppThunkAction<string> => {
  33. return async dispatch => {
  34. const { installation, visible, text, cover, attachments, data, parent } = options
  35. dispatch(startRequest(RequestKey.CreatePost))
  36. try {
  37. const post = await apiFetch<CreatePostResponse>({
  38. path: `/v1/post`,
  39. method: 'post',
  40. body: {
  41. installation,
  42. visible,
  43. text,
  44. cover,
  45. attachments,
  46. data,
  47. parent,
  48. },
  49. })
  50. dispatch(finishRequest(RequestKey.CreatePost, true))
  51. return post.id
  52. } catch (err) {
  53. dispatch(finishRequest(RequestKey.CreatePost, false))
  54. throw err
  55. }
  56. }
  57. }
  58. interface FetchPostResponse {
  59. post: Post,
  60. parents: Post[],
  61. children: Post[],
  62. users: User[],
  63. }
  64. export const fetchPost = (id: string): AppThunkAction => {
  65. return async dispatch => {
  66. dispatch(startRequest(RequestKey.FetchPost))
  67. try {
  68. const response = await apiFetch<FetchPostResponse>({
  69. path: `/v1/post/${id}`
  70. })
  71. const parents = normalize(response.parents.map(p => ({
  72. ...p,
  73. user: response.users.find(u => u.id === p.userId),
  74. userId: undefined,
  75. })), EntityType.Post)
  76. dispatch(setEntities(parents.entities))
  77. dispatch(listSet(`post:${id}:parents`, parents.keys))
  78. const children = normalize(response.children.map(p => ({
  79. ...p,
  80. user: response.users.find(u => u.id === p.userId),
  81. userId: undefined,
  82. })), EntityType.Post)
  83. dispatch(setEntities(children.entities))
  84. dispatch(listSet(`post:${id}:children`, children.keys))
  85. const post: Entity = {
  86. ...response.post,
  87. user: response.users.find(u => u.id === response.post.userId),
  88. userId: undefined,
  89. }
  90. const posts = normalize([post], EntityType.Post)
  91. dispatch(setEntities(posts.entities))
  92. dispatch(finishRequest(RequestKey.FetchPost, true))
  93. } catch (err) {
  94. dispatch(finishRequest(RequestKey.FetchPost, false))
  95. throw err
  96. }
  97. }
  98. }
  99. interface TimelineResponse {
  100. posts: Post[]
  101. continuation?: string
  102. }
  103. export const fetchTimeline = (continuation?: string): AppThunkAction => async dispatch => {
  104. dispatch(startRequest(RequestKey.FetchTimeline))
  105. try {
  106. const response = await apiFetch<TimelineResponse>({
  107. path: `/v1/timeline?${objectToQuerystring({ continuation })}`,
  108. })
  109. const posts = normalize(response.posts, EntityType.Post)
  110. dispatch(setEntities(posts.entities))
  111. if (continuation) {
  112. dispatch(listAppend(EntityListKey.Timeline, posts.keys, response.continuation))
  113. } else {
  114. dispatch(listSet(EntityListKey.Timeline, posts.keys, response.continuation))
  115. }
  116. dispatch(finishRequest(RequestKey.FetchTimeline, true))
  117. } catch (err) {
  118. dispatch(finishRequest(RequestKey.FetchTimeline, false))
  119. throw err
  120. }
  121. }
  122. interface UserPostsResponse {
  123. user: User
  124. posts: Post[]
  125. continuation?: string
  126. }
  127. export const fetchUserPosts = (id: string, continuation?: string): AppThunkAction => async dispatch => {
  128. dispatch(startRequest(RequestKey.FetchUserPosts))
  129. try {
  130. const response = await apiFetch<UserPostsResponse>({
  131. path: `/v1/user/${id}/posts`,
  132. })
  133. const posts = normalize(response.posts.map(p => ({
  134. ...p,
  135. user: response.user,
  136. })), EntityType.Post)
  137. dispatch(setEntities(posts.entities))
  138. if (continuation) {
  139. dispatch(listAppend(`user:${id}:posts`, posts.keys, response.continuation))
  140. } else {
  141. dispatch(listSet(`user:${id}:posts`, posts.keys, response.continuation))
  142. }
  143. dispatch(finishRequest(RequestKey.FetchUserPosts, true))
  144. } catch (err) {
  145. dispatch(finishRequest(RequestKey.FetchUserPosts, false))
  146. throw err
  147. }
  148. }