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 (
-