From 6fbea0a59edc504808676ae9fa3d6027f139f864 Mon Sep 17 00:00:00 2001
From: mgabdev <>
Date: Tue, 22 Dec 2020 01:36:38 -0500
Subject: [PATCH] Progress on little important things
removing .mov for now until we can figure out solution with videojs, added model to track username changes, got chat creation flow down, progress on bookmark collections, albums, filtering blocks/mutes from group, explore, collection timelines
---
.../api/v1/chat_conversation_controller.rb | 2 +-
.../api/v1/timelines/explore_controller.rb | 6 +-
.../timelines/group_collection_controller.rb | 6 +-
.../api/v1/timelines/group_controller.rb | 7 +-
app/controllers/empty_controller.rb | 7 +
.../settings/profiles_controller.rb | 11 +-
app/javascript/gabsocial/actions/albums.js | 247 ++++++++++++++++++
app/javascript/gabsocial/actions/bookmarks.js | 6 +-
.../actions/chat_conversation_accounts.js | 4 +-
.../gabsocial/actions/chat_conversations.js | 8 +-
.../gabsocial/actions/group_editor.js | 7 +-
.../gabsocial/components/hashtag_item.js | 63 -----
.../gabsocial/components/media_item.js | 4 +-
.../navigation_bar/chat_navigation_bar_xs.js | 7 +-
.../compose_navigation_bar_xs.js | 6 +-
.../components/panel/media_gallery_panel.js | 2 +-
app/javascript/gabsocial/components/poll.js | 1 +
.../gabsocial/components/profile_header.js | 25 +-
.../gabsocial/components/status_check_box.js | 1 +
.../gabsocial/components/status_media.js | 1 +
app/javascript/gabsocial/components/video.js | 6 +-
.../features/chat_conversation_create.js | 10 +-
app/javascript/gabsocial/features/deck.js | 2 +-
.../gabsocial/features/hashtag_timeline.js | 20 +-
.../components/chat_message_compose_form.js | 4 +-
.../components/chat_message_scrolling_list.js | 4 +-
.../gabsocial/features/messages_settings.js | 2 +-
.../reducers/chat_conversation_lists.js | 4 +
.../gabsocial/reducers/chat_conversations.js | 4 +-
app/models/account_username_change.rb | 18 ++
app/models/group.rb | 7 +-
app/models/media_attachment.rb | 7 +-
.../rest/media_attachment_serializer.rb | 2 +-
...2040559_create_account_username_changes.rb | 10 +
db/schema.rb | 12 +-
package.json | 1 -
yarn.lock | 7 -
37 files changed, 406 insertions(+), 135 deletions(-)
delete mode 100644 app/javascript/gabsocial/components/hashtag_item.js
create mode 100644 app/models/account_username_change.rb
create mode 100644 db/migrate/20201222040559_create_account_username_changes.rb
diff --git a/app/controllers/api/v1/chat_conversation_controller.rb b/app/controllers/api/v1/chat_conversation_controller.rb
index bc191e8e..302696d0 100644
--- a/app/controllers/api/v1/chat_conversation_controller.rb
+++ b/app/controllers/api/v1/chat_conversation_controller.rb
@@ -20,7 +20,7 @@ class Api::V1::ChatConversationController < Api::BaseController
def create
chat_conversation_account = find_or_create_conversation
- render json: chat_conversation_account, each_serializer: REST::ChatConversationAccountSerializer
+ render json: chat_conversation_account, serializer: REST::ChatConversationAccountSerializer
end
def mark_chat_conversation_read
diff --git a/app/controllers/api/v1/timelines/explore_controller.rb b/app/controllers/api/v1/timelines/explore_controller.rb
index a4fe635d..04e936ab 100644
--- a/app/controllers/api/v1/timelines/explore_controller.rb
+++ b/app/controllers/api/v1/timelines/explore_controller.rb
@@ -45,7 +45,11 @@ class Api::V1::Timelines::ExploreController < EmptyController
end
def explore_statuses
- SortingQueryBuilder.new.call(@sort_type, params[:max_id])
+ if current_account
+ SortingQueryBuilder.new.call(@sort_type, params[:max_id]).reject { |status| FeedManager.instance.filter?(:home, status, current_account.id) }
+ else
+ SortingQueryBuilder.new.call(@sort_type, params[:max_id])
+ end
end
def insert_pagination_headers
diff --git a/app/controllers/api/v1/timelines/group_collection_controller.rb b/app/controllers/api/v1/timelines/group_collection_controller.rb
index 780638b7..4ac4d955 100644
--- a/app/controllers/api/v1/timelines/group_collection_controller.rb
+++ b/app/controllers/api/v1/timelines/group_collection_controller.rb
@@ -70,7 +70,11 @@ class Api::V1::Timelines::GroupCollectionController < EmptyController
return []
end
- SortingQueryBuilder.new.call(@sort_type, params[:max_id], @groupIds)
+ if current_account
+ SortingQueryBuilder.new.call(@sort_type, params[:max_id], @groupIds).reject { |status| FeedManager.instance.filter?(:home, status, current_account.id) }
+ else
+ SortingQueryBuilder.new.call(@sort_type, params[:max_id], @groupIds)
+ end
end
def insert_pagination_headers
diff --git a/app/controllers/api/v1/timelines/group_controller.rb b/app/controllers/api/v1/timelines/group_controller.rb
index 489ddae3..7bcd7926 100644
--- a/app/controllers/api/v1/timelines/group_controller.rb
+++ b/app/controllers/api/v1/timelines/group_controller.rb
@@ -51,7 +51,12 @@ class Api::V1::Timelines::GroupController < Api::BaseController
end
def group_statuses
- SortingQueryBuilder.new.call(@sort_type, params[:max_id], @group)
+ if current_account
+ SortingQueryBuilder.new.call(@sort_type, params[:max_id], @group).reject { |status| FeedManager.instance.filter?(:home, status, current_account.id) }
+ else
+ SortingQueryBuilder.new.call(@sort_type, params[:max_id], @group)
+ end
+
end
def insert_pagination_headers
diff --git a/app/controllers/empty_controller.rb b/app/controllers/empty_controller.rb
index 20d28bab..45e4faf5 100644
--- a/app/controllers/empty_controller.rb
+++ b/app/controllers/empty_controller.rb
@@ -36,6 +36,13 @@ class EmptyController < ActionController::Base
protected
+ def set_pagination_headers(next_path = nil, prev_path = nil)
+ links = []
+ links << [next_path, [%w(rel next)]] if next_path
+ links << [prev_path, [%w(rel prev)]] if prev_path
+ response.headers['Link'] = LinkHeader.new(links) unless links.empty?
+ end
+
def current_user
nil
end
diff --git a/app/controllers/settings/profiles_controller.rb b/app/controllers/settings/profiles_controller.rb
index be90bda3..aa580d4e 100644
--- a/app/controllers/settings/profiles_controller.rb
+++ b/app/controllers/settings/profiles_controller.rb
@@ -24,11 +24,12 @@ class Settings::ProfilesController < Settings::BaseController
flash[:alert] = 'Unable to change username for your account. You are not GabPRO'
redirect_to settings_profile_path
else
- # : todo :
- # only allowed to change username once per day
- if params[:account][:username] && @account.username != params[:account][:username]
- Redis.current.set("username_change:#{account.id}", true)
- Redis.current.expire("username_change:#{account.id}", 24.huors.seconds)
+ if @account.username != params[:account][:username]
+ AccountUsernameChange.create!(
+ account: @account,
+ from_username: @account.username,
+ to_username: params[:account][:username]
+ )
end
if UpdateAccountService.new.call(@account, account_params)
diff --git a/app/javascript/gabsocial/actions/albums.js b/app/javascript/gabsocial/actions/albums.js
index 5d2bf8a0..e94b114e 100644
--- a/app/javascript/gabsocial/actions/albums.js
+++ b/app/javascript/gabsocial/actions/albums.js
@@ -11,6 +11,8 @@ export const ALBUMS_EXPAND_REQUEST = 'ALBUMS_EXPAND_REQUEST'
export const ALBUMS_EXPAND_SUCCESS = 'ALBUMS_EXPAND_SUCCESS'
export const ALBUMS_EXPAND_FAIL = 'ALBUMS_EXPAND_FAIL'
+//
+
export const ALBUM_CREATE_REQUEST = 'ALBUM_CREATE_REQUEST'
export const ALBUM_CREATE_SUCCESS = 'ALBUM_CREATE_SUCCESS'
export const ALBUM_CREATE_FAIL = 'ALBUM_CREATE_FAIL'
@@ -23,7 +25,252 @@ export const ALBUM_EDIT_REQUEST = 'ALBUM_EDIT_REQUEST'
export const ALBUM_EDIT_SUCCESS = 'ALBUM_EDIT_SUCCESS'
export const ALBUM_EDIT_FAIL = 'ALBUM_EDIT_FAIL'
+//
+
export const ALBUM_UPDATE_MEDIA_REQUEST = 'ALBUM_UPDATE_MEDIA_REQUEST'
export const ALBUM_UPDATE_MEDIA_SUCCESS = 'ALBUM_UPDATE_MEDIA_SUCCESS'
export const ALBUM_UPDATE_MEDIA_FAIL = 'ALBUM_UPDATE_MEDIA_FAIL'
+export const SET_ALBUM_COVER_REQUEST = 'SET_ALBUM_COVER_REQUEST'
+export const SET_ALBUM_COVER_SUCCESS = 'SET_ALBUM_COVER_SUCCESS'
+export const SET_ALBUM_COVER_FAIL = 'SET_ALBUM_COVER_FAIL'
+
+/**
+ *
+ */
+export const fetchAlbums = (accountId) => (dispatch, getState) => {
+ if (!accountId) return
+
+ if (getState().getIn(['album_lists', accountId, 'isLoading'])) {
+ return
+ }
+
+ dispatch(fetchAlbumsRequest(accountId))
+
+ api(getState).get(`/api/v1/albums/find_by_account/${accountId}`).then((response) => {
+ const next = getLinks(response).refs.find(link => link.rel === 'next')
+ dispatch(fetchAlbumsSuccess(response.data, accountId, next ? next.uri : null))
+ }).catch((error) => {
+ dispatch(fetchAlbumsFail(accountId, error))
+ })
+}
+
+const fetchAlbumsRequest = (accountId) => ({
+ type: ALBUMS_FETCH_REQUEST,
+ accountId,
+})
+
+const fetchAlbumsSuccess = (albums, accountId, next) => ({
+ type: ALBUMS_FETCH_SUCCESS,
+ albums,
+ accountId,
+ next,
+})
+
+const fetchAlbumsFail = (accountId, error) => ({
+ type: ALBUMS_FETCH_FAIL,
+ showToast: true,
+ accountId,
+ error,
+})
+
+/**
+ *
+ */
+export const expandAlbums = (accountId) => (dispatch, getState) => {
+ if (!me) return
+
+ const url = getState().getIn(['album_lists', accountId, 'next'], null)
+
+ if (url === null || getState().getIn(['album_lists', accountId, 'isLoading'])) {
+ return
+ }
+
+ dispatch(expandAlbumsRequest(accountId))
+
+ api(getState).get(url).then((response) => {
+ const next = getLinks(response).refs.find(link => link.rel === 'next')
+ dispatch(expandAlbumsSuccess(response.data, accountId, next ? next.uri : null))
+ }).catch((error) => {
+ dispatch(expandAlbumsFail(accountId, error))
+ })
+}
+
+const expandAlbumsRequest = (accountId) => ({
+ type: ALBUMS_EXPAND_REQUEST,
+ accountId,
+})
+
+const expandAlbumsSuccess = (statuses, accountId, next) => ({
+ type: ALBUMS_EXPAND_SUCCESS,
+ accountId,
+ statuses,
+ next,
+})
+
+const expandAlbumsFail = (accountId, error) => ({
+ type: ALBUMS_EXPAND_FAIL,
+ showToast: true,
+ accountId,
+ error,
+})
+
+
+/**
+ *
+ */
+export const createAlbum = (title, description, visibility) => (dispatch, getState) => {
+ if (!me || !title) return
+
+ dispatch(createAlbumRequest())
+
+ api(getState).post('/api/v1/albums', {
+ title,
+ description,
+ visibility,
+ }).then((response) => {
+ dispatch(createAlbumSuccess(response.data))
+ }).catch((error) => {
+ dispatch(createAlbumFail(error))
+ })
+}
+
+const createAlbumRequest = () => ({
+ type: ALBUM_CREATE_REQUEST,
+})
+
+const createAlbumSuccess = (bookmarkCollection) => ({
+ type: ALBUM_CREATE_SUCCESS,
+ bookmarkCollection,
+})
+
+const createAlbumFail = (error) => ({
+ type: ALBUM_CREATE_FAIL,
+ showToast: true,
+ error,
+})
+
+/**
+ *
+ */
+export const editAlbum = (albumId, title, description, visibility) => (dispatch, getState) => {
+ if (!me || !albumId || !title) return
+
+ dispatch(editAlbumRequest(albumId))
+
+ api(getState).put(`/api/v1/albums/${albumId}`, {
+ title,
+ description,
+ visibility,
+ }).then((response) => {
+ dispatch(editAlbumSuccess(response.data))
+ }).catch((error) => {
+ dispatch(editAlbumFail(error))
+ })
+}
+
+const editAlbumRequest = (albumId) => ({
+ type: ALBUM_EDIT_REQUEST,
+ albumId,
+})
+
+const editAlbumSuccess = (album) => ({
+ type: ALBUM_EDIT_SUCCESS,
+ album,
+})
+
+const editAlbumFail = (error) => ({
+ type: ALBUM_EDIT_FAIL,
+ showToast: true,
+ error,
+})
+
+/**
+ *
+ */
+export const removeAlbum = (albumId) => (dispatch, getState) => {
+ if (!me || !albumId) return
+
+ dispatch(removeAlbumRequest(albumId))
+
+ api(getState).delete(`/api/v1/albums/${albumId}`).then((response) => {
+ dispatch(removeAlbumSuccess(response.data))
+ }).catch((error) => {
+ dispatch(removeAlbumFail(error))
+ })
+}
+
+const removeAlbumRequest = (albumId) => ({
+ type: ALBUM_REMOVE_REQUEST,
+ albumId,
+})
+
+const removeAlbumSuccess = () => ({
+ type: ALBUM_REMOVE_SUCCESS,
+})
+
+const removeAlbumFail = (error) => ({
+ type: ALBUM_REMOVE_FAIL,
+ showToast: true,
+ error,
+})
+
+/**
+ *
+ */
+export const updateMediaAttachmentAlbum = (albumId, mediaAttachmentId) => (dispatch, getState) => {
+ if (!me || !albumId || !mediaAttachmentId) return
+
+ dispatch(updateMediaAttachmentAlbumRequest())
+
+ api(getState).post(`/api/v1/albums/${albumId}/update_status`, { statusId }).then((response) => {
+ dispatch(updateMediaAttachmentAlbumSuccess(response.data))
+ }).catch((error) => {
+ dispatch(updateMediaAlbumFail(error))
+ })
+}
+
+const updateMediaAttachmentAlbumRequest = () => ({
+ type: ALBUM_UPDATE_MEDIA_REQUEST,
+})
+
+const updateMediaAttachmentAlbumSuccess = (album) => ({
+ type: ALBUM_UPDATE_MEDIA_SUCCESS,
+ album,
+})
+
+const updateMediaAlbumFail = (error) => ({
+ type: ALBUM_UPDATE_MEDIA_FAIL,
+ showToast: true,
+ error,
+})
+
+/**
+ *
+ */
+export const setAlbumCover = (albumId, mediaAttachmentId) => (dispatch, getState) => {
+ if (!me || !albumId || !mediaAttachmentId) return
+
+ dispatch(setAlbumCoverRequest())
+
+ api(getState).post(`/api/v1/albums/${albumId}/set_cover`, { mediaAttachmentId }).then((response) => {
+ dispatch(setAlbumCoverSuccess(response.data))
+ }).catch((error) => {
+ dispatch(setAlbumCoverFail(error))
+ })
+}
+
+const setAlbumCoverRequest = () => ({
+ type: SET_ALBUM_COVER_REQUEST,
+})
+
+const setAlbumCoverSuccess = (album) => ({
+ type: SET_ALBUM_COVER_SUCCESS,
+ album,
+})
+
+const setAlbumCoverFail = (error) => ({
+ type: SET_ALBUM_COVER_FAIL,
+ showToast: true,
+ error,
+})
diff --git a/app/javascript/gabsocial/actions/bookmarks.js b/app/javascript/gabsocial/actions/bookmarks.js
index 99cc9a48..f6752b72 100644
--- a/app/javascript/gabsocial/actions/bookmarks.js
+++ b/app/javascript/gabsocial/actions/bookmarks.js
@@ -194,16 +194,16 @@ export const removeBookmarkCollection = (bookmarkCollectionId) => (dispatch, get
}
const removeBookmarkCollectionRequest = (bookmarkCollectionId) => ({
- type: BOOKMARK_COLLECTIONS_CREATE_REQUEST,
+ type: BOOKMARK_COLLECTIONS_REMOVE_REQUEST,
bookmarkCollectionId,
})
const removeBookmarkCollectionSuccess = () => ({
- type: BOOKMARK_COLLECTIONS_CREATE_SUCCESS,
+ type: BOOKMARK_COLLECTIONS_REMOVE_SUCCESS,
})
const removeBookmarkCollectionFail = (error) => ({
- type: BOOKMARK_COLLECTIONS_CREATE_FAIL,
+ type: BOOKMARK_COLLECTIONS_REMOVE_FAIL,
showToast: true,
error,
})
diff --git a/app/javascript/gabsocial/actions/chat_conversation_accounts.js b/app/javascript/gabsocial/actions/chat_conversation_accounts.js
index 2cb50a06..e2174e1a 100644
--- a/app/javascript/gabsocial/actions/chat_conversation_accounts.js
+++ b/app/javascript/gabsocial/actions/chat_conversation_accounts.js
@@ -41,7 +41,7 @@ export const blockChatMessenger = (accountId) => (dispatch, getState) => {
dispatch(blockChatMessengerRequest(accountId))
api(getState).post(`/api/v1/chat_conversation_accounts/_/block_messenger`, { account_id: accountId }).then((response) => {
- dispatch(blockChatMessengerSuccess(response.data))
+ dispatch(blockChatMessengerSuccess(response))
}).catch((error) => {
dispatch(blockChatMessengerFail(accountId, error))
})
@@ -74,7 +74,7 @@ export const unblockChatMessenger = (accountId) => (dispatch, getState) => {
dispatch(unblockChatMessengerRequest(accountId))
api(getState).post(`/api/v1/chat_conversation_accounts/_/unblock_messenger`, { account_id: accountId }).then((response) => {
- dispatch(unblockChatMessengerSuccess(response.data))
+ dispatch(unblockChatMessengerSuccess(response))
}).catch((error) => {
dispatch(unblockChatMessengerFail(accountId, error))
})
diff --git a/app/javascript/gabsocial/actions/chat_conversations.js b/app/javascript/gabsocial/actions/chat_conversations.js
index e2537650..5043a1af 100644
--- a/app/javascript/gabsocial/actions/chat_conversations.js
+++ b/app/javascript/gabsocial/actions/chat_conversations.js
@@ -1,6 +1,8 @@
import api, { getLinks } from '../api'
import debounce from 'lodash.debounce'
import { importFetchedAccounts } from './importer'
+import { closeModal } from './modal'
+import { setChatConversationSelected } from './chats'
import { me } from '../initial_state'
//
@@ -309,15 +311,17 @@ export const expandChatConversationMutedFail = (error) => ({
* @description Create a chat conversation with given accountId. May fail because of blocks.
* @param {String} accountId
*/
-export const createChatConversation = (accountId) => (dispatch, getState) => {
+export const createChatConversation = (accountId, routerHistory) => (dispatch, getState) => {
if (!me || !accountId) return
dispatch(createChatConversationRequest())
api(getState).post('/api/v1/chat_conversation', { account_id: accountId }).then((response) => {
dispatch(createChatConversationSuccess(response.data))
+ dispatch(closeModal())
+ dispatch(setChatConversationSelected(response.data.chat_conversation_id))
+ if (routerHistory) routerHistory.push(`/messages/${response.data.chat_conversation_id}`)
}).catch((error) => {
- console.log("error:", error)
dispatch(createChatConversationFail(error))
})
}
diff --git a/app/javascript/gabsocial/actions/group_editor.js b/app/javascript/gabsocial/actions/group_editor.js
index d2306a69..d61bfeed 100644
--- a/app/javascript/gabsocial/actions/group_editor.js
+++ b/app/javascript/gabsocial/actions/group_editor.js
@@ -88,6 +88,7 @@ const createGroup = (options, routerHistory) => (dispatch, getState) => {
}
}).then(({ data }) => {
dispatch(createGroupSuccess(data))
+ console.log("pushing routerHistory:", routerHistory)
routerHistory.push(`/groups/${data.id}`)
}).catch((err) => dispatch(createGroupFail(err)))
}
@@ -98,13 +99,13 @@ const createGroupRequest = (id) => ({
id,
})
-const createSuccess = (group) => ({
+const createGroupSuccess = (group) => ({
type: GROUP_CREATE_SUCCESS,
showToast: true,
group,
})
-const createFail = (error) => ({
+const createGroupFail = (error) => ({
type: GROUP_CREATE_FAIL,
showToast: true,
error,
@@ -138,7 +139,7 @@ const updateGroup = (groupId, options, routerHistory) => (dispatch, getState) =>
api(getState).put(`/api/v1/groups/${groupId}`, formData, {
headers: {
- 'Content-Type': 'multipart/form-data'
+ 'Content-Type': 'multipart/form-data',
}
}).then(({ data }) => {
dispatch(updateGroupSuccess(data))
diff --git a/app/javascript/gabsocial/components/hashtag_item.js b/app/javascript/gabsocial/components/hashtag_item.js
deleted file mode 100644
index e92814b2..00000000
--- a/app/javascript/gabsocial/components/hashtag_item.js
+++ /dev/null
@@ -1,63 +0,0 @@
-import React from 'react'
-import PropTypes from 'prop-types'
-import { Sparklines, SparklinesCurve } from 'react-sparklines'
-import { FormattedMessage } from 'react-intl'
-import ImmutablePropTypes from 'react-immutable-proptypes'
-import ImmutablePureComponent from 'react-immutable-pure-component'
-import { NavLink } from 'react-router-dom'
-import Button from './button'
-import Block from './block'
-import Text from './text'
-
-class HashtagItem extends ImmutablePureComponent {
-
- render() {
- const { hashtag, isCompact } = this.props
-
- if (!hashtag) return
-
- const count = hashtag.get('history').map((block) => {
- return parseInt(block.get('uses'))
- }).reduce((a, c) => a + c)
-
- return (
-