diff --git a/app/controllers/api/base_controller.rb b/app/controllers/api/base_controller.rb
index 260909cc..b65ba69f 100644
--- a/app/controllers/api/base_controller.rb
+++ b/app/controllers/api/base_controller.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
class Api::BaseController < ApplicationController
- DEFAULT_STATUSES_LIMIT = 18
- DEFAULT_ACCOUNTS_LIMIT = 40
+ DEFAULT_STATUSES_LIMIT = 20
+ DEFAULT_ACCOUNTS_LIMIT = 20
include RateLimitHeaders
@@ -82,8 +82,8 @@ class Api::BaseController < ApplicationController
end
end
- def render_empty
- render json: {}, status: 200
+ def render_empty_success(message = nil)
+ render json: { success: true, error: false, message: message }, status: 200
end
def authorize_if_got_token!(*scopes)
diff --git a/app/controllers/api/v1/filters_controller.rb b/app/controllers/api/v1/filters_controller.rb
index b0ace3af..e1806af3 100644
--- a/app/controllers/api/v1/filters_controller.rb
+++ b/app/controllers/api/v1/filters_controller.rb
@@ -27,7 +27,7 @@ class Api::V1::FiltersController < Api::BaseController
def destroy
@filter.destroy!
- render_empty
+ render_empty_success
end
private
diff --git a/app/controllers/api/v1/follow_requests_controller.rb b/app/controllers/api/v1/follow_requests_controller.rb
index e6888154..665a1427 100644
--- a/app/controllers/api/v1/follow_requests_controller.rb
+++ b/app/controllers/api/v1/follow_requests_controller.rb
@@ -14,12 +14,12 @@ class Api::V1::FollowRequestsController < Api::BaseController
def authorize
AuthorizeFollowService.new.call(account, current_account)
NotifyService.new.call(current_account, Follow.find_by(account: account, target_account: current_account))
- render_empty
+ render_empty_success
end
def reject
RejectFollowService.new.call(account, current_account)
- render_empty
+ render_empty_success
end
private
diff --git a/app/controllers/api/v1/groups/accounts_controller.rb b/app/controllers/api/v1/groups/accounts_controller.rb
index 0ca8795d..ba8a5611 100644
--- a/app/controllers/api/v1/groups/accounts_controller.rb
+++ b/app/controllers/api/v1/groups/accounts_controller.rb
@@ -19,21 +19,18 @@ class Api::V1::Groups::AccountsController < Api::BaseController
def create
authorize @group, :join?
- if !@group.password.nil?
+ if @group.has_password?
+ # use the groups/password_controller to join group with password
render json: { error: true, message: 'Unable to join group. Incorrect password.' }, status: 422
- end
-
- if @group.is_private
- @group.join_requests << current_account
else
- @group.accounts << current_account
-
- if current_user.allows_group_in_home_feed?
- current_user.force_regeneration!
+ if @group.is_private
+ @group.join_requests << current_account
+ else
+ @group.accounts << current_account
end
- end
- render json: @group, serializer: REST::GroupRelationshipSerializer, relationships: relationships
+ render json: @group, serializer: REST::GroupRelationshipSerializer, relationships: relationships
+ end
end
def update
@@ -41,7 +38,7 @@ class Api::V1::Groups::AccountsController < Api::BaseController
@account = @group.accounts.find(params[:account_id])
GroupAccount.where(group: @group, account: @account).update(group_account_params)
- render_empty
+ render_empty_success
end
def destroy
@@ -51,9 +48,6 @@ class Api::V1::Groups::AccountsController < Api::BaseController
else
authorize @group, :leave?
GroupAccount.where(group: @group, account_id: current_account.id).destroy_all
- if current_user.allows_group_in_home_feed?
- current_user.force_regeneration!
- end
end
render json: @group, serializer: REST::GroupRelationshipSerializer, relationships: relationships
diff --git a/app/controllers/api/v1/groups/pins_controller.rb b/app/controllers/api/v1/groups/pins_controller.rb
index 051897f3..349453c1 100644
--- a/app/controllers/api/v1/groups/pins_controller.rb
+++ b/app/controllers/api/v1/groups/pins_controller.rb
@@ -10,25 +10,29 @@ class Api::V1::Groups::PinsController < Api::BaseController
def create
authorize @group, :update?
-
- GroupPinnedStatus.create!(group: @group, status: @status)
- render json: @status, serializer: REST::StatusSerializer
+
+ pin = GroupPinnedStatus.find_by(group: @group, status: @status)
+ if pin.nil?
+ GroupPinnedStatus.create!(group: @group, status: @status)
+ render json: @status, serializer: REST::StatusGroupPinnedSerializer, group_id: @group.id
+ else
+ return render json: { error: 'Status is already pinned to group' }, status: 500
+ end
end
def show
- # is status pinned by user of group?
+ render json: @status, serializer: REST::StatusGroupPinnedSerializer, group_id: @group.id
end
def destroy
authorize @group, :update?
pin = GroupPinnedStatus.find_by(group: @group, status: @status)
-
if pin
pin.destroy!
end
- render json: @status, serializer: REST::StatusSerializer
+ render json: @status, serializer: REST::StatusGroupPinnedSerializer, group_id: @group.id
end
private
diff --git a/app/controllers/api/v1/groups/removed_accounts_controller.rb b/app/controllers/api/v1/groups/removed_accounts_controller.rb
index d6cba234..be26db5e 100644
--- a/app/controllers/api/v1/groups/removed_accounts_controller.rb
+++ b/app/controllers/api/v1/groups/removed_accounts_controller.rb
@@ -23,7 +23,7 @@ class Api::V1::Groups::RemovedAccountsController < Api::BaseController
@account = @group.accounts.find(params[:account_id])
@group.removed_accounts << @account
GroupAccount.where(group: @group, account: @account).destroy_all
- render_empty
+ render_empty_success
end
def destroy
@@ -31,7 +31,7 @@ class Api::V1::Groups::RemovedAccountsController < Api::BaseController
@account = @group.removed_accounts.find(params[:account_id])
GroupRemovedAccount.where(group: @group, account: @account).destroy_all
- render_empty
+ render_empty_success
end
private
diff --git a/app/controllers/api/v1/groups_controller.rb b/app/controllers/api/v1/groups_controller.rb
index bd8261bb..c56de41a 100644
--- a/app/controllers/api/v1/groups_controller.rb
+++ b/app/controllers/api/v1/groups_controller.rb
@@ -16,12 +16,12 @@ class Api::V1::GroupsController < Api::BaseController
@groups = Group.where(id: @groupIds).limit(150).all
when 'new'
if !current_user
- render json: { error: 'This method requires an authenticated user' }, status: 422
+ return render json: { error: 'This method requires an authenticated user' }, status: 422
end
@groups = Group.where(is_archived: false).limit(24).order('created_at DESC').all
when 'member'
if !current_user
- render json: { error: 'This method requires an authenticated user' }, status: 422
+ return render json: { error: 'This method requires an authenticated user' }, status: 422
end
@groups = Group.joins(:group_accounts).where(is_archived: false, group_accounts: { account: current_account }).order('group_accounts.id DESC').all
when 'admin'
@@ -36,7 +36,7 @@ class Api::V1::GroupsController < Api::BaseController
def by_category
if !current_user
- render json: { error: 'This method requires an authenticated user' }, status: 422
+ return render json: { error: 'This method requires an authenticated user' }, status: 422
end
@groupCategory = nil
@@ -54,7 +54,7 @@ class Api::V1::GroupsController < Api::BaseController
def by_tag
if !current_user
- render json: { error: 'This method requires an authenticated user' }, status: 422
+ return render json: { error: 'This method requires an authenticated user' }, status: 422
end
@groups = []
@@ -94,7 +94,7 @@ class Api::V1::GroupsController < Api::BaseController
@group.is_archived = true
@group.save!
- render_empty
+ render_empty_success
end
def destroy_status
@@ -102,7 +102,7 @@ class Api::V1::GroupsController < Api::BaseController
status = Status.find(params[:status_id])
GroupUnlinkStatusService.new.call(current_account, @group, status)
- render_empty
+ render_empty_success
end
def approve_status
@@ -110,7 +110,7 @@ class Api::V1::GroupsController < Api::BaseController
status = Status.find(params[:status_id])
GroupApproveStatusService.new.call(current_account, @group, status)
- render_empty
+ render_empty_success
end
private
diff --git a/app/controllers/api/v1/lists/accounts_controller.rb b/app/controllers/api/v1/lists/accounts_controller.rb
index 23078263..d6a282ff 100644
--- a/app/controllers/api/v1/lists/accounts_controller.rb
+++ b/app/controllers/api/v1/lists/accounts_controller.rb
@@ -21,12 +21,12 @@ class Api::V1::Lists::AccountsController < Api::BaseController
end
end
- render_empty
+ render_empty_success
end
def destroy
ListAccount.where(list: @list, account_id: account_ids).destroy_all
- render_empty
+ render_empty_success
end
private
diff --git a/app/controllers/api/v1/lists_controller.rb b/app/controllers/api/v1/lists_controller.rb
index 054172be..1a7ad326 100644
--- a/app/controllers/api/v1/lists_controller.rb
+++ b/app/controllers/api/v1/lists_controller.rb
@@ -28,7 +28,7 @@ class Api::V1::ListsController < Api::BaseController
def destroy
@list.destroy!
- render_empty
+ render_empty_success
end
private
diff --git a/app/controllers/api/v1/messages/chats_controller.rb b/app/controllers/api/v1/messages/chats_controller.rb
new file mode 100644
index 00000000..e69de29b
diff --git a/app/controllers/api/v1/messages/converations_controller.rb b/app/controllers/api/v1/messages/converations_controller.rb
new file mode 100644
index 00000000..e69de29b
diff --git a/app/controllers/api/v1/messages_controller.rb b/app/controllers/api/v1/messages_controller.rb
new file mode 100644
index 00000000..207a991d
--- /dev/null
+++ b/app/controllers/api/v1/messages_controller.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+class Api::V1::AccountsController < Api::BaseController
+ before_action -> { authorize_if_got_token! :read, :'read:accounts' }, except: [:create, :follow, :unfollow, :block, :unblock, :mute, :unmute]
+ before_action -> { doorkeeper_authorize! :follow, :'write:follows' }, only: [:follow, :unfollow]
+ before_action -> { doorkeeper_authorize! :follow, :'write:mutes' }, only: [:mute, :unmute]
+ before_action -> { doorkeeper_authorize! :follow, :'write:blocks' }, only: [:block, :unblock]
+ before_action -> { doorkeeper_authorize! :write, :'write:accounts' }, only: [:create]
+
+ before_action :require_user!, except: [:show, :create]
+ before_action :set_account, except: [:create]
+ before_action :check_account_suspension, only: [:show]
+
+ def show
+ #
+ end
+
+ def create
+ #
+ end
+
+ def block
+ BlockMessengerService.new.call(current_user.account, @account)
+ render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
+ end
+
+ def mute
+ MuteMessengerService.new.call(current_user.account, @account, notifications: truthy_param?(:notifications))
+ render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
+ end
+
+ def unblock
+ UnblockMessengerService.new.call(current_user.account, @account)
+ render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
+ end
+
+ def unmute
+ UnmuteMessegerService.new.call(current_user.account, @account)
+ render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
+ end
+
+ private
+
+ def set_account
+ @account = Account.find(params[:id])
+ end
+
+ def relationships(**options)
+ AccountRelationshipsPresenter.new([@account.id], current_user.account_id, options)
+ end
+
+ def check_account_suspension
+ gone if @account.suspended?
+ end
+
+ def account_params
+ params.permit(:username, :email, :password, :agreement, :locale)
+ end
+end
diff --git a/app/controllers/api/v1/notifications_controller.rb b/app/controllers/api/v1/notifications_controller.rb
index 727f693b..f2e01cf5 100644
--- a/app/controllers/api/v1/notifications_controller.rb
+++ b/app/controllers/api/v1/notifications_controller.rb
@@ -21,12 +21,12 @@ class Api::V1::NotificationsController < Api::BaseController
def clear
current_account.notifications.delete_all
- render_empty
+ render_empty_success
end
def mark_read
current_account.notifications.find(params[:id]).mark_read!
- render_empty
+ render_empty_success
end
private
diff --git a/app/controllers/api/v1/scheduled_statuses_controller.rb b/app/controllers/api/v1/scheduled_statuses_controller.rb
index 9950296f..3c102848 100644
--- a/app/controllers/api/v1/scheduled_statuses_controller.rb
+++ b/app/controllers/api/v1/scheduled_statuses_controller.rb
@@ -26,7 +26,7 @@ class Api::V1::ScheduledStatusesController < Api::BaseController
def destroy
@status.destroy!
- render_empty
+ render_empty_success
end
private
diff --git a/app/controllers/api/v1/statuses/bookmarks_controller.rb b/app/controllers/api/v1/statuses/bookmarks_controller.rb
index 8a5625ed..7a3bcadc 100644
--- a/app/controllers/api/v1/statuses/bookmarks_controller.rb
+++ b/app/controllers/api/v1/statuses/bookmarks_controller.rb
@@ -9,14 +9,15 @@ class Api::V1::Statuses::BookmarksController < Api::BaseController
def create
if current_user.account.is_pro
@status = bookmarked_status
- render json: @status, serializer: REST::StatusSerializer
+ render json: @status, serializer: REST::StatusBookmarkedSerializer
else
render json: { error: 'You need to be a GabPRO member to access this' }, status: 422
end
end
def show
- # is status bookmarked by user?
+ @status = requested_status
+ render json: @status, serializer: REST::StatusBookmarkedSerializer
end
def destroy
@@ -27,7 +28,7 @@ class Api::V1::Statuses::BookmarksController < Api::BaseController
bookmark = StatusBookmark.find_by!(account: current_user.account, status: @status)
bookmark.destroy!
- render json: @status, serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new([@status], current_user&.account_id, bookmarks_map: @bookmarks_map)
+ render json: @status, serializer: REST::StatusBookmarkedSerializer
else
render json: { error: 'You need to be a GabPRO member to access this' }, status: 422
end
diff --git a/app/controllers/api/v1/statuses/favourites_controller.rb b/app/controllers/api/v1/statuses/favourites_controller.rb
index 4f52942f..96582d6d 100644
--- a/app/controllers/api/v1/statuses/favourites_controller.rb
+++ b/app/controllers/api/v1/statuses/favourites_controller.rb
@@ -8,7 +8,6 @@ class Api::V1::Statuses::FavouritesController < Api::BaseController
def create
@status = favourited_status
- puts "tilly -- status: " + @status.inspect
render json: @status, serializer: REST::StatusStatSerializer
end
@@ -18,7 +17,10 @@ class Api::V1::Statuses::FavouritesController < Api::BaseController
UnfavouriteWorker.perform_async(current_user.account_id, @status.id)
- render json: @status, serializer: REST::StatusStatSerializer, unfavourite: true, relationships: StatusRelationshipsPresenter.new([@status], current_user&.account_id, favourites_map: @favourites_map)
+ render json: @status,
+ serializer: REST::StatusStatSerializer,
+ unfavourite: true,
+ relationships: StatusRelationshipsPresenter.new([@status], current_user&.account_id, favourites_map: @favourites_map)
end
private
diff --git a/app/controllers/api/v1/statuses/pins_controller.rb b/app/controllers/api/v1/statuses/pins_controller.rb
index fba194da..c3c4784a 100644
--- a/app/controllers/api/v1/statuses/pins_controller.rb
+++ b/app/controllers/api/v1/statuses/pins_controller.rb
@@ -8,12 +8,17 @@ class Api::V1::Statuses::PinsController < Api::BaseController
before_action :set_status
def create
- StatusPin.create!(account: current_account, status: @status)
- render json: @status, serializer: REST::StatusSerializer
+ pin = StatusPin.find_by(account: current_account, status: @status)
+ if pin.nil?
+ StatusPin.create!(account: current_account, status: @status)
+ render json: @status, serializer: REST::StatusPinnedSerializer
+ else
+ return render json: { error: 'Status is already pinned' }, status: 500
+ end
end
def show
- # is status pinned by user?
+ render json: @status, serializer: REST::StatusPinnedSerializer
end
def destroy
@@ -23,7 +28,7 @@ class Api::V1::Statuses::PinsController < Api::BaseController
pin.destroy!
end
- render json: @status, serializer: REST::StatusSerializer
+ render json: @status, serializer: REST::StatusPinnedSerializer
end
private
diff --git a/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb b/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb
index f897650d..c69839ae 100644
--- a/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb
+++ b/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class Api::V1::Statuses::RepostedByAccountsController < Api::BaseController
+class Api::V1::Statuses::RebloggedByAccountsController < Api::BaseController
include Authorization
before_action -> { authorize_if_got_token! :read, :'read:accounts' }
@@ -36,13 +36,13 @@ class Api::V1::Statuses::RepostedByAccountsController < Api::BaseController
def next_path
if records_continue?
- api_v1_status_reposted_by_index_url pagination_params(max_id: pagination_max_id)
+ api_v1_status_reblogged_by_index_url pagination_params(max_id: pagination_max_id)
end
end
def prev_path
unless @accounts.empty?
- api_v1_status_reposted_by_index_url pagination_params(since_id: pagination_since_id)
+ api_v1_status_reblogged_by_index_url pagination_params(since_id: pagination_since_id)
end
end
diff --git a/app/controllers/api/v1/statuses/reblogs_controller.rb b/app/controllers/api/v1/statuses/reblogs_controller.rb
index fe492fd0..9e17dfd9 100644
--- a/app/controllers/api/v1/statuses/reblogs_controller.rb
+++ b/app/controllers/api/v1/statuses/reblogs_controller.rb
@@ -7,22 +7,25 @@ class Api::V1::Statuses::ReblogsController < Api::BaseController
before_action :require_user!
def create
- if !current_user.account.local? || !status_for_reblog.local
- return render json: { error: 'Invalid action' }, status: 422
- end
-
- @status = ReblogService.new.call(current_user.account, status_for_reblog, reblog_params)
- render json: @status, serializer: REST::StatusSerializer
+ @relog = status_for_reblog
+ ReblogService.new.call(current_user.account, @relog, reblog_params)
+ render json: @relog, serializer: REST::StatusStatSerializer
end
def destroy
- @status = status_for_destroy.reblog
- @reblogs_map = { @status.id => false }
+ @my_relog = status_for_destroy
+ @original_status = @my_relog.reblog
- authorize status_for_destroy, :unreblog?
- RemovalWorker.perform_async(status_for_destroy.id)
+ authorize @my_relog, :unreblog?
- render json: @status, serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new([@status], current_user&.account_id, reblogs_map: @reblogs_map)
+ RemovalWorker.perform_async(@my_relog.id)
+
+ @reblogs_map = { @original_status.id => false }
+
+ render json: @original_status,
+ serializer: REST::StatusStatSerializer,
+ unreblog: true,
+ relationships: StatusRelationshipsPresenter.new([@original_status], current_user&.account_id, reblogs_map: @reblogs_map)
end
private
diff --git a/app/controllers/api/v1/suggestions_controller.rb b/app/controllers/api/v1/suggestions_controller.rb
index 6ebec322..61b534be 100644
--- a/app/controllers/api/v1/suggestions_controller.rb
+++ b/app/controllers/api/v1/suggestions_controller.rb
@@ -23,7 +23,7 @@ class Api::V1::SuggestionsController < Api::BaseController
def destroy
PotentialFriendshipTracker.remove(current_account.id, params[:id])
- render_empty
+ render_empty_success
end
end
diff --git a/app/controllers/api/web/settings_controller.rb b/app/controllers/api/web/settings_controller.rb
index 3d65e46e..21a28273 100644
--- a/app/controllers/api/web/settings_controller.rb
+++ b/app/controllers/api/web/settings_controller.rb
@@ -7,7 +7,7 @@ class Api::Web::SettingsController < Api::Web::BaseController
setting.data = params[:data]
setting.save!
- render_empty
+ render_empty_success
end
private
diff --git a/app/controllers/concerns/signature_verification.rb b/app/controllers/concerns/signature_verification.rb
index fb2166ff..65265b15 100644
--- a/app/controllers/concerns/signature_verification.rb
+++ b/app/controllers/concerns/signature_verification.rb
@@ -66,6 +66,7 @@ module SignatureVerification
return account unless verify_signature(account, signature, compare_signed_string).nil?
+ # : todo :
@signature_verification_failure_reason = "Verification failed for #{account.username}@#{account.domain} #{account.uri}"
@signed_request_account = nil
end
diff --git a/app/javascript/gabsocial/actions/accounts.js b/app/javascript/gabsocial/actions/accounts.js
index 38c1d563..dd752a25 100644
--- a/app/javascript/gabsocial/actions/accounts.js
+++ b/app/javascript/gabsocial/actions/accounts.js
@@ -1,766 +1,674 @@
-import api, { getLinks } from '../api';
-import openDB from '../storage/db';
+import api, { getLinks } from '../api'
+import openDB from '../storage/db'
import {
importAccount,
importFetchedAccount,
importFetchedAccounts,
importErrorWhileFetchingAccountByUsername,
-} from './importer';
-import { me } from '../initial_state';
+} from './importer'
+import { me } from '../initial_state'
-export const ACCOUNT_FETCH_REQUEST = 'ACCOUNT_FETCH_REQUEST';
-export const ACCOUNT_FETCH_SUCCESS = 'ACCOUNT_FETCH_SUCCESS';
-export const ACCOUNT_FETCH_FAIL = 'ACCOUNT_FETCH_FAIL';
+export const ACCOUNT_FETCH_REQUEST = 'ACCOUNT_FETCH_REQUEST'
+export const ACCOUNT_FETCH_SUCCESS = 'ACCOUNT_FETCH_SUCCESS'
+export const ACCOUNT_FETCH_FAIL = 'ACCOUNT_FETCH_FAIL'
-export const ACCOUNT_FOLLOW_REQUEST = 'ACCOUNT_FOLLOW_REQUEST';
-export const ACCOUNT_FOLLOW_SUCCESS = 'ACCOUNT_FOLLOW_SUCCESS';
-export const ACCOUNT_FOLLOW_FAIL = 'ACCOUNT_FOLLOW_FAIL';
+export const ACCOUNT_FOLLOW_REQUEST = 'ACCOUNT_FOLLOW_REQUEST'
+export const ACCOUNT_FOLLOW_SUCCESS = 'ACCOUNT_FOLLOW_SUCCESS'
+export const ACCOUNT_FOLLOW_FAIL = 'ACCOUNT_FOLLOW_FAIL'
-export const ACCOUNT_UNFOLLOW_REQUEST = 'ACCOUNT_UNFOLLOW_REQUEST';
-export const ACCOUNT_UNFOLLOW_SUCCESS = 'ACCOUNT_UNFOLLOW_SUCCESS';
-export const ACCOUNT_UNFOLLOW_FAIL = 'ACCOUNT_UNFOLLOW_FAIL';
+export const ACCOUNT_UNFOLLOW_REQUEST = 'ACCOUNT_UNFOLLOW_REQUEST'
+export const ACCOUNT_UNFOLLOW_SUCCESS = 'ACCOUNT_UNFOLLOW_SUCCESS'
+export const ACCOUNT_UNFOLLOW_FAIL = 'ACCOUNT_UNFOLLOW_FAIL'
-export const ACCOUNT_BLOCK_REQUEST = 'ACCOUNT_BLOCK_REQUEST';
-export const ACCOUNT_BLOCK_SUCCESS = 'ACCOUNT_BLOCK_SUCCESS';
-export const ACCOUNT_BLOCK_FAIL = 'ACCOUNT_BLOCK_FAIL';
+export const ACCOUNT_BLOCK_SUCCESS = 'ACCOUNT_BLOCK_SUCCESS'
+export const ACCOUNT_BLOCK_FAIL = 'ACCOUNT_BLOCK_FAIL'
-export const ACCOUNT_UNBLOCK_REQUEST = 'ACCOUNT_UNBLOCK_REQUEST';
-export const ACCOUNT_UNBLOCK_SUCCESS = 'ACCOUNT_UNBLOCK_SUCCESS';
-export const ACCOUNT_UNBLOCK_FAIL = 'ACCOUNT_UNBLOCK_FAIL';
+export const ACCOUNT_UNBLOCK_REQUEST = 'ACCOUNT_UNBLOCK_REQUEST'
+export const ACCOUNT_UNBLOCK_SUCCESS = 'ACCOUNT_UNBLOCK_SUCCESS'
+export const ACCOUNT_UNBLOCK_FAIL = 'ACCOUNT_UNBLOCK_FAIL'
-export const ACCOUNT_MUTE_REQUEST = 'ACCOUNT_MUTE_REQUEST';
-export const ACCOUNT_MUTE_SUCCESS = 'ACCOUNT_MUTE_SUCCESS';
-export const ACCOUNT_MUTE_FAIL = 'ACCOUNT_MUTE_FAIL';
+export const ACCOUNT_MUTE_REQUEST = 'ACCOUNT_MUTE_REQUEST'
+export const ACCOUNT_MUTE_SUCCESS = 'ACCOUNT_MUTE_SUCCESS'
+export const ACCOUNT_MUTE_FAIL = 'ACCOUNT_MUTE_FAIL'
-export const ACCOUNT_UNMUTE_REQUEST = 'ACCOUNT_UNMUTE_REQUEST';
-export const ACCOUNT_UNMUTE_SUCCESS = 'ACCOUNT_UNMUTE_SUCCESS';
-export const ACCOUNT_UNMUTE_FAIL = 'ACCOUNT_UNMUTE_FAIL';
+export const ACCOUNT_UNMUTE_REQUEST = 'ACCOUNT_UNMUTE_REQUEST'
+export const ACCOUNT_UNMUTE_SUCCESS = 'ACCOUNT_UNMUTE_SUCCESS'
+export const ACCOUNT_UNMUTE_FAIL = 'ACCOUNT_UNMUTE_FAIL'
-export const FOLLOWERS_FETCH_REQUEST = 'FOLLOWERS_FETCH_REQUEST';
-export const FOLLOWERS_FETCH_SUCCESS = 'FOLLOWERS_FETCH_SUCCESS';
-export const FOLLOWERS_FETCH_FAIL = 'FOLLOWERS_FETCH_FAIL';
+export const FOLLOWERS_FETCH_REQUEST = 'FOLLOWERS_FETCH_REQUEST'
+export const FOLLOWERS_FETCH_SUCCESS = 'FOLLOWERS_FETCH_SUCCESS'
+export const FOLLOWERS_FETCH_FAIL = 'FOLLOWERS_FETCH_FAIL'
-export const FOLLOWERS_EXPAND_REQUEST = 'FOLLOWERS_EXPAND_REQUEST';
-export const FOLLOWERS_EXPAND_SUCCESS = 'FOLLOWERS_EXPAND_SUCCESS';
-export const FOLLOWERS_EXPAND_FAIL = 'FOLLOWERS_EXPAND_FAIL';
+export const FOLLOWERS_EXPAND_REQUEST = 'FOLLOWERS_EXPAND_REQUEST'
+export const FOLLOWERS_EXPAND_SUCCESS = 'FOLLOWERS_EXPAND_SUCCESS'
+export const FOLLOWERS_EXPAND_FAIL = 'FOLLOWERS_EXPAND_FAIL'
-export const FOLLOWING_FETCH_REQUEST = 'FOLLOWING_FETCH_REQUEST';
-export const FOLLOWING_FETCH_SUCCESS = 'FOLLOWING_FETCH_SUCCESS';
-export const FOLLOWING_FETCH_FAIL = 'FOLLOWING_FETCH_FAIL';
+export const FOLLOWING_FETCH_REQUEST = 'FOLLOWING_FETCH_REQUEST'
+export const FOLLOWING_FETCH_SUCCESS = 'FOLLOWING_FETCH_SUCCESS'
+export const FOLLOWING_FETCH_FAIL = 'FOLLOWING_FETCH_FAIL'
-export const FOLLOWING_EXPAND_REQUEST = 'FOLLOWING_EXPAND_REQUEST';
-export const FOLLOWING_EXPAND_SUCCESS = 'FOLLOWING_EXPAND_SUCCESS';
-export const FOLLOWING_EXPAND_FAIL = 'FOLLOWING_EXPAND_FAIL';
+export const FOLLOWING_EXPAND_REQUEST = 'FOLLOWING_EXPAND_REQUEST'
+export const FOLLOWING_EXPAND_SUCCESS = 'FOLLOWING_EXPAND_SUCCESS'
+export const FOLLOWING_EXPAND_FAIL = 'FOLLOWING_EXPAND_FAIL'
-export const RELATIONSHIPS_FETCH_REQUEST = 'RELATIONSHIPS_FETCH_REQUEST';
-export const RELATIONSHIPS_FETCH_SUCCESS = 'RELATIONSHIPS_FETCH_SUCCESS';
-export const RELATIONSHIPS_FETCH_FAIL = 'RELATIONSHIPS_FETCH_FAIL';
+export const RELATIONSHIPS_FETCH_REQUEST = 'RELATIONSHIPS_FETCH_REQUEST'
+export const RELATIONSHIPS_FETCH_SUCCESS = 'RELATIONSHIPS_FETCH_SUCCESS'
+export const RELATIONSHIPS_FETCH_FAIL = 'RELATIONSHIPS_FETCH_FAIL'
-export const FOLLOW_REQUESTS_FETCH_REQUEST = 'FOLLOW_REQUESTS_FETCH_REQUEST';
-export const FOLLOW_REQUESTS_FETCH_SUCCESS = 'FOLLOW_REQUESTS_FETCH_SUCCESS';
-export const FOLLOW_REQUESTS_FETCH_FAIL = 'FOLLOW_REQUESTS_FETCH_FAIL';
+export const FOLLOW_REQUESTS_FETCH_REQUEST = 'FOLLOW_REQUESTS_FETCH_REQUEST'
+export const FOLLOW_REQUESTS_FETCH_SUCCESS = 'FOLLOW_REQUESTS_FETCH_SUCCESS'
+export const FOLLOW_REQUESTS_FETCH_FAIL = 'FOLLOW_REQUESTS_FETCH_FAIL'
-export const FOLLOW_REQUESTS_EXPAND_REQUEST = 'FOLLOW_REQUESTS_EXPAND_REQUEST';
-export const FOLLOW_REQUESTS_EXPAND_SUCCESS = 'FOLLOW_REQUESTS_EXPAND_SUCCESS';
-export const FOLLOW_REQUESTS_EXPAND_FAIL = 'FOLLOW_REQUESTS_EXPAND_FAIL';
+export const FOLLOW_REQUESTS_EXPAND_REQUEST = 'FOLLOW_REQUESTS_EXPAND_REQUEST'
+export const FOLLOW_REQUESTS_EXPAND_SUCCESS = 'FOLLOW_REQUESTS_EXPAND_SUCCESS'
+export const FOLLOW_REQUESTS_EXPAND_FAIL = 'FOLLOW_REQUESTS_EXPAND_FAIL'
-export const FOLLOW_REQUEST_AUTHORIZE_REQUEST = 'FOLLOW_REQUEST_AUTHORIZE_REQUEST';
-export const FOLLOW_REQUEST_AUTHORIZE_SUCCESS = 'FOLLOW_REQUEST_AUTHORIZE_SUCCESS';
-export const FOLLOW_REQUEST_AUTHORIZE_FAIL = 'FOLLOW_REQUEST_AUTHORIZE_FAIL';
+export const FOLLOW_REQUEST_AUTHORIZE_REQUEST = 'FOLLOW_REQUEST_AUTHORIZE_REQUEST'
+export const FOLLOW_REQUEST_AUTHORIZE_SUCCESS = 'FOLLOW_REQUEST_AUTHORIZE_SUCCESS'
+export const FOLLOW_REQUEST_AUTHORIZE_FAIL = 'FOLLOW_REQUEST_AUTHORIZE_FAIL'
-export const FOLLOW_REQUEST_REJECT_REQUEST = 'FOLLOW_REQUEST_REJECT_REQUEST';
-export const FOLLOW_REQUEST_REJECT_SUCCESS = 'FOLLOW_REQUEST_REJECT_SUCCESS';
-export const FOLLOW_REQUEST_REJECT_FAIL = 'FOLLOW_REQUEST_REJECT_FAIL';
+export const FOLLOW_REQUEST_REJECT_REQUEST = 'FOLLOW_REQUEST_REJECT_REQUEST'
+export const FOLLOW_REQUEST_REJECT_SUCCESS = 'FOLLOW_REQUEST_REJECT_SUCCESS'
+export const FOLLOW_REQUEST_REJECT_FAIL = 'FOLLOW_REQUEST_REJECT_FAIL'
+/**
+ *
+ */
function getFromDB(dispatch, getState, index, id) {
return new Promise((resolve, reject) => {
- const request = index.get(id);
+ const request = index.get(id)
- request.onerror = reject;
+ request.onerror = reject
request.onsuccess = () => {
if (!request.result) {
- reject();
- return;
+ reject()
+ return
}
- dispatch(importAccount(request.result));
- resolve(request.result.moved && getFromDB(dispatch, getState, index, request.result.moved));
- };
- });
+ dispatch(importAccount(request.result))
+ resolve(request.result.moved && getFromDB(dispatch, getState, index, request.result.moved))
+ }
+ })
}
-export function fetchAccount(id) {
- return (dispatch, getState) => {
- if (id === -1 || getState().getIn(['accounts', id], null) !== null) {
- return;
- }
-
- dispatch(fetchRelationships([id]));
- dispatch(fetchAccountRequest(id));
-
- openDB().then(db => getFromDB(
- dispatch,
- getState,
- db.transaction('accounts', 'read').objectStore('accounts').index('id'),
- id
- ).then(() => db.close(), error => {
- db.close();
- throw error;
- })).catch(() => api(getState).get(`/api/v1/accounts/${id}`).then(response => {
- dispatch(importFetchedAccount(response.data));
- })).then(() => {
- dispatch(fetchAccountSuccess());
- }).catch(error => {
- dispatch(fetchAccountFail(id, error));
- });
- };
-};
-
-export function fetchAccountByUsername(username) {
- return (dispatch, getState) => {
- if (!username) {
- return;
- }
-
- api(getState).get(`/api/v1/account_by_username/${username}`).then(response => {
- dispatch(importFetchedAccount(response.data))
- dispatch(fetchRelationships([response.data.id]))
- }).then(() => {
- dispatch(fetchAccountSuccess());
- }).catch(error => {
- dispatch(fetchAccountFail(null, error));
- dispatch(importErrorWhileFetchingAccountByUsername(username));
- });
- };
-};
-
-export function fetchAccountRequest(id) {
- return {
- type: ACCOUNT_FETCH_REQUEST,
- id,
- };
-};
-
-export function fetchAccountSuccess() {
- return {
- type: ACCOUNT_FETCH_SUCCESS,
- };
-};
-
-export function fetchAccountFail(id, error) {
- return {
- type: ACCOUNT_FETCH_FAIL,
- id,
- error,
- skipAlert: true,
- };
-};
-
-export function followAccount(id, reblogs = true) {
- return (dispatch, getState) => {
- if (!me) return;
-
- const alreadyFollowing = getState().getIn(['relationships', id, 'following']);
- const locked = getState().getIn(['accounts', id, 'locked'], false);
-
- dispatch(followAccountRequest(id, locked));
-
- api(getState).post(`/api/v1/accounts/${id}/follow`, { reblogs }).then(response => {
- dispatch(followAccountSuccess(response.data, alreadyFollowing));
- }).catch(error => {
- dispatch(followAccountFail(error, locked));
- });
- };
-};
-
-export function unfollowAccount(id) {
- return (dispatch, getState) => {
- if (!me) return;
-
- dispatch(unfollowAccountRequest(id));
-
- api(getState).post(`/api/v1/accounts/${id}/unfollow`).then(response => {
- dispatch(unfollowAccountSuccess(response.data, getState().get('statuses')));
- }).catch(error => {
- dispatch(unfollowAccountFail(error));
- });
- };
-};
-
-export function followAccountRequest(id, locked) {
- return {
- type: ACCOUNT_FOLLOW_REQUEST,
- id,
- locked,
- skipLoading: true,
- };
-};
-
-export function followAccountSuccess(relationship, alreadyFollowing) {
- return {
- type: ACCOUNT_FOLLOW_SUCCESS,
- relationship,
- alreadyFollowing,
- skipLoading: true,
- };
-};
-
-export function followAccountFail(error, locked) {
- return {
- type: ACCOUNT_FOLLOW_FAIL,
- error,
- locked,
- skipLoading: true,
- };
-};
-
-export function unfollowAccountRequest(id) {
- return {
- type: ACCOUNT_UNFOLLOW_REQUEST,
- id,
- skipLoading: true,
- };
-};
-
-export function unfollowAccountSuccess(relationship, statuses) {
- return {
- type: ACCOUNT_UNFOLLOW_SUCCESS,
- relationship,
- statuses,
- skipLoading: true,
- };
-};
-
-export function unfollowAccountFail(error) {
- return {
- type: ACCOUNT_UNFOLLOW_FAIL,
- error,
- skipLoading: true,
- };
-};
-
-export function blockAccount(id) {
- return (dispatch, getState) => {
- if (!me) return;
-
- dispatch(blockAccountRequest(id));
-
- api(getState).post(`/api/v1/accounts/${id}/block`).then(response => {
- // Pass in entire statuses map so we can use it to filter stuff in different parts of the reducers
- dispatch(blockAccountSuccess(response.data, getState().get('statuses')));
- }).catch(error => {
- dispatch(blockAccountFail(id, error));
- });
- };
-};
-
-export function unblockAccount(id) {
- return (dispatch, getState) => {
- if (!me) return;
-
- dispatch(unblockAccountRequest(id));
-
- api(getState).post(`/api/v1/accounts/${id}/unblock`).then(response => {
- dispatch(unblockAccountSuccess(response.data));
- }).catch(error => {
- dispatch(unblockAccountFail(id, error));
- });
- };
-};
-
-export function blockAccountRequest(id) {
- return {
- type: ACCOUNT_BLOCK_REQUEST,
- id,
- };
-};
-
-export function blockAccountSuccess(relationship, statuses) {
- return {
- type: ACCOUNT_BLOCK_SUCCESS,
- relationship,
- statuses,
- };
-};
-
-export function blockAccountFail(error) {
- return {
- type: ACCOUNT_BLOCK_FAIL,
- error,
- };
-};
-
-export function unblockAccountRequest(id) {
- return {
- type: ACCOUNT_UNBLOCK_REQUEST,
- id,
- };
-};
-
-export function unblockAccountSuccess(relationship) {
- return {
- type: ACCOUNT_UNBLOCK_SUCCESS,
- relationship,
- };
-};
-
-export function unblockAccountFail(error) {
- return {
- type: ACCOUNT_UNBLOCK_FAIL,
- error,
- };
-};
-
-
-export function muteAccount(id, notifications) {
- return (dispatch, getState) => {
- if (!me) return;
-
- dispatch(muteAccountRequest(id));
-
- api(getState).post(`/api/v1/accounts/${id}/mute`, { notifications }).then(response => {
- // Pass in entire statuses map so we can use it to filter stuff in different parts of the reducers
- dispatch(muteAccountSuccess(response.data, getState().get('statuses')));
- }).catch(error => {
- dispatch(muteAccountFail(id, error));
- });
- };
-};
-
-export function unmuteAccount(id) {
- return (dispatch, getState) => {
- if (!me) return;
-
- dispatch(unmuteAccountRequest(id));
-
- api(getState).post(`/api/v1/accounts/${id}/unmute`).then(response => {
- dispatch(unmuteAccountSuccess(response.data));
- }).catch(error => {
- dispatch(unmuteAccountFail(id, error));
- });
- };
-};
-
-export function muteAccountRequest(id) {
- return {
- type: ACCOUNT_MUTE_REQUEST,
- id,
- };
-};
-
-export function muteAccountSuccess(relationship, statuses) {
- return {
- type: ACCOUNT_MUTE_SUCCESS,
- relationship,
- statuses,
- };
-};
-
-export function muteAccountFail(error) {
- return {
- type: ACCOUNT_MUTE_FAIL,
- error,
- };
-};
-
-export function unmuteAccountRequest(id) {
- return {
- type: ACCOUNT_UNMUTE_REQUEST,
- id,
- };
-};
-
-export function unmuteAccountSuccess(relationship) {
- return {
- type: ACCOUNT_UNMUTE_SUCCESS,
- relationship,
- };
-};
-
-export function unmuteAccountFail(error) {
- return {
- type: ACCOUNT_UNMUTE_FAIL,
- error,
- };
-};
-
-
-export function fetchFollowers(id) {
- return (dispatch, getState) => {
- if (!me) return;
-
- dispatch(fetchFollowersRequest(id));
-
- api(getState).get(`/api/v1/accounts/${id}/followers`).then(response => {
- const next = getLinks(response).refs.find(link => link.rel === 'next');
-
- dispatch(importFetchedAccounts(response.data));
- dispatch(fetchFollowersSuccess(id, response.data, next ? next.uri : null));
- dispatch(fetchRelationships(response.data.map(item => item.id)));
- }).catch(error => {
- dispatch(fetchFollowersFail(id, error));
- });
- };
-};
-
-export function fetchFollowersRequest(id) {
- return {
- type: FOLLOWERS_FETCH_REQUEST,
- id,
- };
-};
-
-export function fetchFollowersSuccess(id, accounts, next) {
- return {
- type: FOLLOWERS_FETCH_SUCCESS,
- id,
- accounts,
- next,
- };
-};
-
-export function fetchFollowersFail(id, error) {
- return {
- type: FOLLOWERS_FETCH_FAIL,
- id,
- error,
- };
-};
-
-export function expandFollowers(id) {
- return (dispatch, getState) => {
- if (!me) return;
-
- const url = getState().getIn(['user_lists', 'followers', id, 'next']);
- const isLoading = getState().getIn(['user_lists', 'followers', id, 'isLoading']);
-
- if (url === null || isLoading) return
-
- dispatch(expandFollowersRequest(id));
-
- api(getState).get(url).then(response => {
- const next = getLinks(response).refs.find(link => link.rel === 'next');
-
- dispatch(importFetchedAccounts(response.data));
- dispatch(expandFollowersSuccess(id, response.data, next ? next.uri : null));
- dispatch(fetchRelationships(response.data.map(item => item.id)));
- }).catch((error) => {
- dispatch(expandFollowersFail(id, error));
- });
- };
-};
-
-export function expandFollowersRequest(id) {
- return {
- type: FOLLOWERS_EXPAND_REQUEST,
- id,
- };
-};
-
-export function expandFollowersSuccess(id, accounts, next) {
- return {
- type: FOLLOWERS_EXPAND_SUCCESS,
- id,
- accounts,
- next,
- };
-};
-
-export function expandFollowersFail(id, error) {
- return {
- type: FOLLOWERS_EXPAND_FAIL,
- id,
- error,
- };
-};
-
-export function fetchFollowing(id) {
- return (dispatch, getState) => {
- if (!me) return;
-
- dispatch(fetchFollowingRequest(id));
-
- api(getState).get(`/api/v1/accounts/${id}/following`).then(response => {
- const next = getLinks(response).refs.find(link => link.rel === 'next');
-
- dispatch(importFetchedAccounts(response.data));
- dispatch(fetchFollowingSuccess(id, response.data, next ? next.uri : null));
- dispatch(fetchRelationships(response.data.map(item => item.id)));
- }).catch(error => {
- dispatch(fetchFollowingFail(id, error));
- });
- };
-};
-
-export function fetchFollowingRequest(id) {
- return {
- type: FOLLOWING_FETCH_REQUEST,
- id,
- };
-};
-
-export function fetchFollowingSuccess(id, accounts, next) {
- return {
- type: FOLLOWING_FETCH_SUCCESS,
- id,
- accounts,
- next,
- };
-};
-
-export function fetchFollowingFail(id, error) {
- return {
- type: FOLLOWING_FETCH_FAIL,
- id,
- error,
- };
-};
-
-export function expandFollowing(id) {
- return (dispatch, getState) => {
- if (!me) return;
-
- const url = getState().getIn(['user_lists', 'following', id, 'next']);
- const isLoading = getState().getIn(['user_lists', 'following', id, 'isLoading']);
-
- if (url === null || isLoading) return
-
- dispatch(expandFollowingRequest(id));
-
- api(getState).get(url).then(response => {
- const next = getLinks(response).refs.find(link => link.rel === 'next');
-
- dispatch(importFetchedAccounts(response.data));
- dispatch(expandFollowingSuccess(id, response.data, next ? next.uri : null));
- dispatch(fetchRelationships(response.data.map(item => item.id)));
- }).catch(error => {
- dispatch(expandFollowingFail(id, error));
- });
- };
-};
-
-export function expandFollowingRequest(id) {
- return {
- type: FOLLOWING_EXPAND_REQUEST,
- id,
- };
-};
-
-export function expandFollowingSuccess(id, accounts, next) {
- return {
- type: FOLLOWING_EXPAND_SUCCESS,
- id,
- accounts,
- next,
- };
-};
-
-export function expandFollowingFail(id, error) {
- return {
- type: FOLLOWING_EXPAND_FAIL,
- id,
- error,
- };
-};
-
-export function fetchRelationships(accountIds) {
- return (dispatch, getState) => {
- if (!me) return;
-
- const loadedRelationships = getState().get('relationships');
- let newAccountIds = accountIds.filter((id) => {
- if (id === me) return false
- return loadedRelationships.get(id, null) === null
- })
-
- if (newAccountIds.length === 0) {
- return;
- } else if (newAccountIds.length == 1) {
- const firstId = newAccountIds[0]
- if (me === firstId) return;
- }
-
- // Unique
- newAccountIds = Array.from(new Set(newAccountIds))
-
- dispatch(fetchRelationshipsRequest(newAccountIds));
-
- api(getState).get(`/api/v1/accounts/relationships?${newAccountIds.map(id => `id[]=${id}`).join('&')}`).then(response => {
- dispatch(fetchRelationshipsSuccess(response.data));
- }).catch(error => {
- dispatch(fetchRelationshipsFail(error));
- });
- };
-};
-
-export function fetchRelationshipsRequest(ids) {
- return {
- type: RELATIONSHIPS_FETCH_REQUEST,
- ids,
- skipLoading: true,
- };
-};
-
-export function fetchRelationshipsSuccess(relationships) {
- return {
- type: RELATIONSHIPS_FETCH_SUCCESS,
- relationships,
- skipLoading: true,
- };
-};
-
-export function fetchRelationshipsFail(error) {
- return {
- type: RELATIONSHIPS_FETCH_FAIL,
- error,
- skipLoading: true,
- };
-};
-
-export function fetchFollowRequests() {
- return (dispatch, getState) => {
- if (!me) return;
-
- dispatch(fetchFollowRequestsRequest());
-
- api(getState).get('/api/v1/follow_requests').then(response => {
- const next = getLinks(response).refs.find(link => link.rel === 'next');
- dispatch(importFetchedAccounts(response.data));
- dispatch(fetchFollowRequestsSuccess(response.data, next ? next.uri : null));
- }).catch(error => dispatch(fetchFollowRequestsFail(error)));
- };
-};
-
-export function fetchFollowRequestsRequest() {
- return {
- type: FOLLOW_REQUESTS_FETCH_REQUEST,
- };
-};
-
-export function fetchFollowRequestsSuccess(accounts, next) {
- return {
- type: FOLLOW_REQUESTS_FETCH_SUCCESS,
- accounts,
- next,
- };
-};
-
-export function fetchFollowRequestsFail(error) {
- return {
- type: FOLLOW_REQUESTS_FETCH_FAIL,
- error,
- };
-};
-
-export function expandFollowRequests() {
- return (dispatch, getState) => {
- if (!me) return;
-
- const url = getState().getIn(['user_lists', 'follow_requests', me, 'next']);
- const isLoading = getState().getIn(['user_lists', 'follow_requests', me, 'isLoading']);
-
- if (url === null || isLoading) return
-
- dispatch(expandFollowRequestsRequest());
-
- api(getState).get(url).then(response => {
- const next = getLinks(response).refs.find(link => link.rel === 'next');
- dispatch(importFetchedAccounts(response.data));
- dispatch(expandFollowRequestsSuccess(response.data, next ? next.uri : null));
- }).catch(error => dispatch(expandFollowRequestsFail(error)));
- };
-};
-
-export function expandFollowRequestsRequest() {
- return {
- type: FOLLOW_REQUESTS_EXPAND_REQUEST,
- };
-};
-
-export function expandFollowRequestsSuccess(accounts, next) {
- return {
- type: FOLLOW_REQUESTS_EXPAND_SUCCESS,
- accounts,
- next,
- };
-};
-
-export function expandFollowRequestsFail(error) {
- return {
- type: FOLLOW_REQUESTS_EXPAND_FAIL,
- error,
- };
-};
-
-export function authorizeFollowRequest(id) {
- return (dispatch, getState) => {
- if (!me) return;
-
- dispatch(authorizeFollowRequestRequest(id));
-
- api(getState)
- .post(`/api/v1/follow_requests/${id}/authorize`)
- .then(() => dispatch(authorizeFollowRequestSuccess(id)))
- .catch(error => dispatch(authorizeFollowRequestFail(id, error)));
- };
-};
-
-export function authorizeFollowRequestRequest(id) {
- return {
- type: FOLLOW_REQUEST_AUTHORIZE_REQUEST,
- id,
- };
-};
-
-export function authorizeFollowRequestSuccess(id) {
- return {
- type: FOLLOW_REQUEST_AUTHORIZE_SUCCESS,
- id,
- };
-};
-
-export function authorizeFollowRequestFail(id, error) {
- return {
- type: FOLLOW_REQUEST_AUTHORIZE_FAIL,
- id,
- error,
- };
-};
-
-
-export function rejectFollowRequest(id) {
- return (dispatch, getState) => {
- if (!me) return;
-
- dispatch(rejectFollowRequestRequest(id));
-
- api(getState)
- .post(`/api/v1/follow_requests/${id}/reject`)
- .then(() => dispatch(rejectFollowRequestSuccess(id)))
- .catch(error => dispatch(rejectFollowRequestFail(id, error)));
- };
-};
-
-export function rejectFollowRequestRequest(id) {
- return {
- type: FOLLOW_REQUEST_REJECT_REQUEST,
- id,
- };
-};
-
-export function rejectFollowRequestSuccess(id) {
- return {
- type: FOLLOW_REQUEST_REJECT_SUCCESS,
- id,
- };
-};
-
-export function rejectFollowRequestFail(id, error) {
- return {
- type: FOLLOW_REQUEST_REJECT_FAIL,
- id,
- error,
- };
-};
+/**
+ *
+ */
+export const fetchAccount = (id) => (dispatch, getState) => {
+ if (id === -1 || getState().getIn(['accounts', id], null) !== null) return
+
+ dispatch(fetchRelationships([id]))
+ dispatch(fetchAccountRequest(id))
+
+ openDB().then((db) => getFromDB(
+ dispatch,
+ getState,
+ db.transaction('accounts', 'read').objectStore('accounts').index('id'),
+ id
+ ).then(() => db.close(), (error) => {
+ db.close()
+ throw error
+ })).catch(() => api(getState).get(`/api/v1/accounts/${id}`).then((response) => {
+ dispatch(importFetchedAccount(response.data))
+ })).then(() => {
+ dispatch(fetchAccountSuccess())
+ }).catch((error) => {
+ dispatch(fetchAccountFail(id, error))
+ })
+}
+
+/**
+ *
+ */
+export const fetchAccountByUsername = (username) => (dispatch, getState) => {
+ if (!username) return
+
+ api(getState).get(`/api/v1/account_by_username/${username}`).then((response) => {
+ dispatch(importFetchedAccount(response.data))
+ dispatch(fetchRelationships([response.data.id]))
+ }).then(() => {
+ dispatch(fetchAccountSuccess())
+ }).catch((error) => {
+ dispatch(fetchAccountFail(null, error))
+ dispatch(importErrorWhileFetchingAccountByUsername(username))
+ })
+}
+
+const fetchAccountRequest = (id) => ({
+ type: ACCOUNT_FETCH_REQUEST,
+ id,
+})
+
+const fetchAccountSuccess = () => ({
+ type: ACCOUNT_FETCH_SUCCESS,
+})
+
+const fetchAccountFail = (id, error) => ({
+ type: ACCOUNT_FETCH_FAIL,
+ id,
+ error,
+ skipAlert: true,
+})
+
+/**
+ *
+ */
+export const followAccount = (id, reblogs = true) => (dispatch, getState) => {
+ if (!me) return
+
+ const alreadyFollowing = getState().getIn(['relationships', id, 'following'])
+ const locked = getState().getIn(['accounts', id, 'locked'], false)
+
+ dispatch(followAccountRequest(id, locked))
+
+ api(getState).post(`/api/v1/accounts/${id}/follow`, { reblogs }).then((response) => {
+ dispatch(followAccountSuccess(response.data, alreadyFollowing))
+ }).catch((error) => {
+ dispatch(followAccountFail(error, locked))
+ })
+}
+
+const followAccountRequest = (id, locked) => ({
+ type: ACCOUNT_FOLLOW_REQUEST,
+ id,
+ locked,
+})
+
+const followAccountSuccess = (relationship, alreadyFollowing) => ({
+ type: ACCOUNT_FOLLOW_SUCCESS,
+ relationship,
+ alreadyFollowing,
+})
+
+const followAccountFail = (error, locked) => ({
+ type: ACCOUNT_FOLLOW_FAIL,
+ error,
+ locked,
+})
+
+/**
+ *
+ */
+export const unfollowAccount = (id) => (dispatch, getState) => {
+ if (!me) return
+
+ dispatch(unfollowAccountRequest(id))
+
+ api(getState).post(`/api/v1/accounts/${id}/unfollow`).then((response) => {
+ dispatch(unfollowAccountSuccess(response.data, getState().get('statuses')))
+ }).catch((error) => {
+ dispatch(unfollowAccountFail(error))
+ })
+}
+
+const unfollowAccountRequest = (id) => ({
+ type: ACCOUNT_UNFOLLOW_REQUEST,
+ id,
+})
+
+const unfollowAccountSuccess = (relationship, statuses) => ({
+ type: ACCOUNT_UNFOLLOW_SUCCESS,
+ relationship,
+ statuses,
+})
+
+const unfollowAccountFail = (error) => ({
+ type: ACCOUNT_UNFOLLOW_FAIL,
+ error,
+})
+
+/**
+ *
+ */
+export const blockAccount = (id) => (dispatch, getState) => {
+ if (!me) return
+
+ dispatch(blockAccountRequest(id))
+
+ api(getState).post(`/api/v1/accounts/${id}/block`).then((response) => {
+ // : todo : remove gay stuff like passing entire status below:
+ // Pass in entire statuses map so we can use it to filter stuff in different parts of the reducers
+ dispatch(blockAccountSuccess(response.data, getState().get('statuses')))
+ }).catch((error) => {
+ dispatch(blockAccountFail(id, error))
+ })
+}
+
+const blockAccountRequest = (id) => ({
+ type: ACCOUNT_BLOCK_REQUEST,
+ id,
+})
+
+const blockAccountSuccess = (relationship, statuses) => ({
+ type: ACCOUNT_BLOCK_SUCCESS,
+ relationship,
+ statuses,
+})
+
+const blockAccountFail = (error) => ({
+ type: ACCOUNT_BLOCK_FAIL,
+ error,
+})
+
+/**
+ *
+ */
+export const unblockAccount = (id) => (dispatch, getState) => {
+ if (!me) return
+
+ dispatch(unblockAccountRequest(id))
+
+ api(getState).post(`/api/v1/accounts/${id}/unblock`).then((response) => {
+ dispatch(unblockAccountSuccess(response.data))
+ }).catch((error) => {
+ dispatch(unblockAccountFail(id, error))
+ })
+}
+
+const unblockAccountRequest = (id) => ({
+ type: ACCOUNT_UNBLOCK_REQUEST,
+ id,
+})
+
+const unblockAccountSuccess = (relationship) => ({
+ type: ACCOUNT_UNBLOCK_SUCCESS,
+ relationship,
+})
+
+const unblockAccountFail = (error) => ({
+ type: ACCOUNT_UNBLOCK_FAIL,
+ error,
+})
+
+/**
+ *
+ */
+export const muteAccount = (id, notifications) => (dispatch, getState) => {
+ if (!me) return
+
+ dispatch(muteAccountRequest(id))
+
+ api(getState).post(`/api/v1/accounts/${id}/mute`, { notifications }).then((response) => {
+ // Pass in entire statuses map so we can use it to filter stuff in different parts of the reducers
+ dispatch(muteAccountSuccess(response.data, getState().get('statuses')))
+ }).catch((error) => {
+ dispatch(muteAccountFail(id, error))
+ })
+}
+
+const muteAccountRequest = (id) => ({
+ type: ACCOUNT_MUTE_REQUEST,
+ id,
+})
+
+const muteAccountSuccess = (relationship, statuses) => ({
+ type: ACCOUNT_MUTE_SUCCESS,
+ relationship,
+ statuses,
+})
+
+const muteAccountFail = (error) => ({
+ type: ACCOUNT_MUTE_FAIL,
+ error,
+})
+
+/**
+ *
+ */
+export const unmuteAccount = (id) => (dispatch, getState) => {
+ if (!me) return
+
+ dispatch(unmuteAccountRequest(id))
+
+ api(getState).post(`/api/v1/accounts/${id}/unmute`).then((response) => {
+ dispatch(unmuteAccountSuccess(response.data))
+ }).catch((error) => {
+ dispatch(unmuteAccountFail(id, error))
+ })
+}
+
+const unmuteAccountRequest = (id) => ({
+ type: ACCOUNT_UNMUTE_REQUEST,
+ id,
+})
+
+const unmuteAccountSuccess = (relationship) => ({
+ type: ACCOUNT_UNMUTE_SUCCESS,
+ relationship,
+})
+
+const unmuteAccountFail = (error) => ({
+ type: ACCOUNT_UNMUTE_FAIL,
+ error,
+})
+
+/**
+ *
+ */
+export const fetchFollowers = (id) => (dispatch, getState) => {
+ if (!me) return
+
+ dispatch(fetchFollowersRequest(id))
+
+ api(getState).get(`/api/v1/accounts/${id}/followers`).then((response) => {
+ const next = getLinks(response).refs.find(link => link.rel === 'next')
+
+ dispatch(importFetchedAccounts(response.data))
+ dispatch(fetchFollowersSuccess(id, response.data, next ? next.uri : null))
+ dispatch(fetchRelationships(response.data.map(item => item.id)))
+ }).catch((error) => {
+ dispatch(fetchFollowersFail(id, error))
+ })
+}
+
+const fetchFollowersRequest = (id) => ({
+ type: FOLLOWERS_FETCH_REQUEST,
+ id,
+})
+
+const fetchFollowersSuccess = (id, accounts, next) => ({
+ type: FOLLOWERS_FETCH_SUCCESS,
+ id,
+ accounts,
+ next,
+})
+
+const fetchFollowersFail = (id, error) => ({
+ type: FOLLOWERS_FETCH_FAIL,
+ id,
+ error,
+})
+
+/**
+ *
+ */
+export const expandFollowers = (id) => (dispatch, getState) => {
+ if (!me) return
+
+ const url = getState().getIn(['user_lists', 'followers', id, 'next'])
+ const isLoading = getState().getIn(['user_lists', 'followers', id, 'isLoading'])
+
+ if (url === null || isLoading) return
+
+ dispatch(expandFollowersRequest(id))
+
+ api(getState).get(url).then((response) => {
+ const next = getLinks(response).refs.find(link => link.rel === 'next')
+
+ dispatch(importFetchedAccounts(response.data))
+ dispatch(expandFollowersSuccess(id, response.data, next ? next.uri : null))
+ dispatch(fetchRelationships(response.data.map(item => item.id)))
+ }).catch((error) => {
+ dispatch(expandFollowersFail(id, error))
+ })
+}
+
+const expandFollowersRequest = (id) => ({
+ type: FOLLOWERS_EXPAND_REQUEST,
+ id,
+})
+
+const expandFollowersSuccess = (id, accounts, next) => ({
+ type: FOLLOWERS_EXPAND_SUCCESS,
+ id,
+ accounts,
+ next,
+})
+
+const expandFollowersFail = (id, error) => ({
+ type: FOLLOWERS_EXPAND_FAIL,
+ id,
+ error,
+})
+
+/**
+ *
+ */
+export const fetchFollowing = (id) => (dispatch, getState) => {
+ if (!me) return
+
+ dispatch(fetchFollowingRequest(id))
+
+ api(getState).get(`/api/v1/accounts/${id}/following`).then((response) => {
+ const next = getLinks(response).refs.find(link => link.rel === 'next')
+
+ dispatch(importFetchedAccounts(response.data))
+ dispatch(fetchFollowingSuccess(id, response.data, next ? next.uri : null))
+ dispatch(fetchRelationships(response.data.map(item => item.id)))
+ }).catch((error) => {
+ dispatch(fetchFollowingFail(id, error))
+ })
+}
+
+const fetchFollowingRequest = (id) => ({
+ type: FOLLOWING_FETCH_REQUEST,
+ id,
+})
+
+const fetchFollowingSuccess = (id, accounts, next) => ({
+ type: FOLLOWING_FETCH_SUCCESS,
+ id,
+ accounts,
+ next,
+})
+
+const fetchFollowingFail = (id, error) => ({
+ type: FOLLOWING_FETCH_FAIL,
+ id,
+ error,
+})
+
+/**
+ *
+ */
+export const expandFollowing = (id) => (dispatch, getState) => {
+ if (!me) return
+
+ const url = getState().getIn(['user_lists', 'following', id, 'next'])
+ const isLoading = getState().getIn(['user_lists', 'following', id, 'isLoading'])
+
+ if (url === null || isLoading) return
+
+ dispatch(expandFollowingRequest(id))
+
+ api(getState).get(url).then((response) => {
+ const next = getLinks(response).refs.find(link => link.rel === 'next')
+
+ dispatch(importFetchedAccounts(response.data))
+ dispatch(expandFollowingSuccess(id, response.data, next ? next.uri : null))
+ dispatch(fetchRelationships(response.data.map(item => item.id)))
+ }).catch((error) => {
+ dispatch(expandFollowingFail(id, error))
+ })
+}
+
+const expandFollowingRequest = (id) => ({
+ type: FOLLOWING_EXPAND_REQUEST,
+ id,
+})
+
+const expandFollowingSuccess = (id, accounts, next) => ({
+ type: FOLLOWING_EXPAND_SUCCESS,
+ id,
+ accounts,
+ next,
+})
+
+const expandFollowingFail = (id, error) => ({
+ type: FOLLOWING_EXPAND_FAIL,
+ id,
+ error,
+})
+
+/**
+ *
+ */
+export const fetchRelationships = (accountIds) => (dispatch, getState) => {
+ if (!me) return
+
+ const loadedRelationships = getState().get('relationships')
+ let newAccountIds = accountIds.filter((id) => {
+ if (id === me) return false
+ return loadedRelationships.get(id, null) === null
+ })
+
+ if (newAccountIds.length === 0) return
+
+ if (newAccountIds.length == 1) {
+ const firstId = newAccountIds[0]
+ if (me === firstId) return
+ }
+
+ // Unique
+ newAccountIds = Array.from(new Set(newAccountIds))
+
+ dispatch(fetchRelationshipsRequest(newAccountIds))
+
+ api(getState).get(`/api/v1/accounts/relationships?${newAccountIds.map(id => `id[]=${id}`).join('&')}`).then((response) => {
+ dispatch(fetchRelationshipsSuccess(response.data))
+ }).catch((error) => {
+ dispatch(fetchRelationshipsFail(error))
+ })
+}
+
+const fetchRelationshipsRequest = (ids) => ({
+ type: RELATIONSHIPS_FETCH_REQUEST,
+ ids,
+})
+
+const fetchRelationshipsSuccess = (relationships) => ({
+ type: RELATIONSHIPS_FETCH_SUCCESS,
+ relationships,
+})
+
+const fetchRelationshipsFail = (error) => ({
+ type: RELATIONSHIPS_FETCH_FAIL,
+ error,
+})
+
+/**
+ *
+ */
+export const fetchFollowRequests = () => (dispatch, getState) => {
+ if (!me) return
+
+ dispatch(fetchFollowRequestsRequest())
+
+ api(getState).get('/api/v1/follow_requests').then((response) => {
+ const next = getLinks(response).refs.find(link => link.rel === 'next')
+ dispatch(importFetchedAccounts(response.data))
+ dispatch(fetchFollowRequestsSuccess(response.data, next ? next.uri : null))
+ }).catch((error) => dispatch(fetchFollowRequestsFail(error)))
+}
+
+const fetchFollowRequestsRequest = () => ({
+ type: FOLLOW_REQUESTS_FETCH_REQUEST,
+})
+
+const fetchFollowRequestsSuccess = (accounts, next) => ({
+ type: FOLLOW_REQUESTS_FETCH_SUCCESS,
+ accounts,
+ next,
+})
+
+const fetchFollowRequestsFail = (error) => ({
+ type: FOLLOW_REQUESTS_FETCH_FAIL,
+ error,
+})
+
+/**
+ *
+ */
+export const expandFollowRequests = () => (dispatch, getState) => {
+ if (!me) return
+
+ const url = getState().getIn(['user_lists', 'follow_requests', me, 'next'])
+ const isLoading = getState().getIn(['user_lists', 'follow_requests', me, 'isLoading'])
+
+ if (url === null || isLoading) return
+
+ dispatch(expandFollowRequestsRequest())
+
+ api(getState).get(url).then((response) => {
+ const next = getLinks(response).refs.find(link => link.rel === 'next')
+ dispatch(importFetchedAccounts(response.data))
+ dispatch(expandFollowRequestsSuccess(response.data, next ? next.uri : null))
+ }).catch((error) => dispatch(expandFollowRequestsFail(error)))
+}
+
+const expandFollowRequestsRequest = () => ({
+ type: FOLLOW_REQUESTS_EXPAND_REQUEST,
+})
+
+const expandFollowRequestsSuccess = (accounts, next) => ({
+ type: FOLLOW_REQUESTS_EXPAND_SUCCESS,
+ accounts,
+ next,
+})
+
+const expandFollowRequestsFail = (error) => ({
+ type: FOLLOW_REQUESTS_EXPAND_FAIL,
+ error,
+})
+
+/**
+ *
+ */
+export const authorizeFollowRequest = (id) => (dispatch, getState) => {
+ if (!me) return
+
+ dispatch(authorizeFollowRequestRequest(id))
+
+ api(getState)
+ .post(`/api/v1/follow_requests/${id}/authorize`)
+ .then(() => dispatch(authorizeFollowRequestSuccess(id)))
+ .catch((error) => dispatch(authorizeFollowRequestFail(id, error)))
+}
+
+const authorizeFollowRequestRequest = (id) => ({
+ type: FOLLOW_REQUEST_AUTHORIZE_REQUEST,
+ id,
+})
+
+const authorizeFollowRequestSuccess = (id) => ({
+ type: FOLLOW_REQUEST_AUTHORIZE_SUCCESS,
+ id,
+})
+
+const authorizeFollowRequestFail = (id, error) => ({
+ type: FOLLOW_REQUEST_AUTHORIZE_FAIL,
+ id,
+ error,
+})
+
+/**
+ *
+ */
+export const rejectFollowRequest = (id) => (dispatch, getState) => {
+ if (!me) return
+
+ dispatch(rejectFollowRequestRequest(id))
+
+ api(getState)
+ .post(`/api/v1/follow_requests/${id}/reject`)
+ .then(() => dispatch(rejectFollowRequestSuccess(id)))
+ .catch((error) => dispatch(rejectFollowRequestFail(id, error)))
+}
+
+const rejectFollowRequestRequest = (id) => ({
+ type: FOLLOW_REQUEST_REJECT_REQUEST,
+ id,
+})
+
+const rejectFollowRequestSuccess = (id) => ({
+ type: FOLLOW_REQUEST_REJECT_SUCCESS,
+ id,
+})
+
+const rejectFollowRequestFail = (id, error) => ({
+ type: FOLLOW_REQUEST_REJECT_FAIL,
+ id,
+ error,
+})
diff --git a/app/javascript/gabsocial/actions/bookmarks.js b/app/javascript/gabsocial/actions/bookmarks.js
index 3c41d2ff..3af513a9 100644
--- a/app/javascript/gabsocial/actions/bookmarks.js
+++ b/app/javascript/gabsocial/actions/bookmarks.js
@@ -33,20 +33,17 @@ export const fetchBookmarkedStatuses = () => (dispatch, getState) => {
const fetchBookmarkedStatusesRequest = () => ({
type: BOOKMARKED_STATUSES_FETCH_REQUEST,
- skipLoading: true,
})
const fetchBookmarkedStatusesSuccess = (statuses, next) => ({
type: BOOKMARKED_STATUSES_FETCH_SUCCESS,
statuses,
next,
- skipLoading: true,
})
const fetchBookmarkedStatusesFail = (error) => ({
type: BOOKMARKED_STATUSES_FETCH_FAIL,
error,
- skipLoading: true,
})
/**
diff --git a/app/javascript/gabsocial/actions/chat_compose.js b/app/javascript/gabsocial/actions/chat_compose.js
new file mode 100644
index 00000000..ac85f788
--- /dev/null
+++ b/app/javascript/gabsocial/actions/chat_compose.js
@@ -0,0 +1,28 @@
+import api from '../api'
+import { me } from '../initial_state'
+
+export const MESSAGE_INPUT_CHANGE = 'MESSAGE_INPUT_CHANGE'
+export const MESSAGE_INPUT_RESET = 'MESSAGE_INPUT_RESET'
+
+/**
+ *
+ */
+export const messageInputChange = (text) => (dispatch, getState) => {
+ if (!me) return
+
+ //Ensure has conversation
+ const conversationId = getState().getIn(['chat_conversations', 'current', 'conversation_id'], null)
+ if (!conversationId) return
+
+ dispatch({
+ type: MESSAGE_INPUT_CHANGE,
+ text,
+ })
+}
+
+/**
+ *
+ */
+export const messageInputReset = (dispatch) => {
+ dispatch({ type: MESSAGE_INPUT_RESET })
+}
diff --git a/app/javascript/gabsocial/actions/chat_conversations.js b/app/javascript/gabsocial/actions/chat_conversations.js
new file mode 100644
index 00000000..6263209f
--- /dev/null
+++ b/app/javascript/gabsocial/actions/chat_conversations.js
@@ -0,0 +1,189 @@
+import api, { getLinks } from '../api'
+import { fetchRelationships } from './accounts'
+import { importFetchedAccounts } from './importer'
+import { me } from '../initial_state'
+
+export const CONVERSATION_BLOCKS_FETCH_REQUEST = 'CONVERSATION_BLOCKS_FETCH_REQUEST'
+export const CONVERSATION_BLOCKS_FETCH_SUCCESS = 'CONVERSATION_BLOCKS_FETCH_SUCCESS'
+export const CONVERSATION_BLOCKS_FETCH_FAIL = 'CONVERSATION_BLOCKS_FETCH_FAIL'
+
+export const CONVERSATION_BLOCKS_EXPAND_REQUEST = 'CONVERSATION_BLOCKS_EXPAND_REQUEST'
+export const CONVERSATION_BLOCKS_EXPAND_SUCCESS = 'CONVERSATION_BLOCKS_EXPAND_SUCCESS'
+export const CONVERSATION_BLOCKS_EXPAND_FAIL = 'CONVERSATION_BLOCKS_EXPAND_FAIL'
+
+export const BLOCK_MESSAGER_REQUEST = 'BLOCK_MESSAGER_REQUEST'
+export const BLOCK_MESSAGER_SUCCESS = 'BLOCK_MESSAGER_SUCCESS'
+export const BLOCK_MESSAGER_FAIL = 'BLOCK_MESSAGER_FAIL'
+
+export const UNBLOCK_MESSAGER_REQUEST = 'UNBLOCK_MESSAGER_REQUEST'
+export const UNBLOCK_MESSAGER_SUCCESS = 'UNBLOCK_MESSAGER_SUCCESS'
+export const UNBLOCK_MESSAGER_FAIL = 'UNBLOCK_MESSAGER_FAIL'
+
+//
+
+export const CONVERSATION_MUTES_FETCH_REQUEST = 'CONVERSATION_MUTES_FETCH_REQUEST'
+export const CONVERSATION_MUTES_FETCH_SUCCESS = 'CONVERSATION_MUTES_FETCH_SUCCESS'
+export const CONVERSATION_MUTES_FETCH_FAIL = 'CONVERSATION_MUTES_FETCH_FAIL'
+
+export const CONVERSATION_MUTES_EXPAND_REQUEST = 'CONVERSATION_MUTES_EXPAND_REQUEST'
+export const CONVERSATION_MUTES_EXPAND_SUCCESS = 'CONVERSATION_MUTES_EXPAND_SUCCESS'
+export const CONVERSATION_MUTES_EXPAND_FAIL = 'CONVERSATION_MUTES_EXPAND_FAIL'
+
+export const MUTE_MESSAGER_REQUEST = 'BLOCK_MESSAGER_REQUEST'
+export const MUTE_MESSAGER_SUCCESS = 'BLOCK_MESSAGER_SUCCESS'
+export const MUTE_MESSAGER_FAIL = 'BLOCK_MESSAGER_FAIL'
+
+export const UNMUTE_MESSAGER_REQUEST = 'UNMUTE_MESSAGER_REQUEST'
+export const UNMUTE_MESSAGER_SUCCESS = 'UNMUTE_MESSAGER_SUCCESS'
+export const UNMUTE_MESSAGER_FAIL = 'UNMUTE_MESSAGER_FAIL'
+
+//
+
+export const CONVERSATION_REQUEST_APPROVE_SUCCESS = 'CONVERSATION_REQUEST_APPROVE_SUCCESS'
+export const CONVERSATION_REQUEST_APPROVE_FAIL = 'CONVERSATION_REQUEST_APPROVE_FAIL'
+
+export const CONVERSATION_REQUEST_REJECT_SUCCESS = 'CONVERSATION_REQUEST_REJECT_SUCCESS'
+export const CONVERSATION_REQUEST_REJECT_FAIL = 'CONVERSATION_REQUEST_REJECT_FAIL'
+
+export const CONVERSATION_DELETE_REQUEST = 'CONVERSATION_DELETE_REQUEST'
+export const CONVERSATION_DELETE_SUCCESS = 'CONVERSATION_DELETE_SUCCESS'
+export const CONVERSATION_DELETE_FAIL = 'CONVERSATION_DELETE_FAIL'
+
+//
+
+export const CONVERSATIONS_FETCH_REQUEST = 'CONVERSATIONS_FETCH_REQUEST'
+export const CONVERSATIONS_FETCH_SUCCESS = 'CONVERSATIONS_FETCH_SUCCESS'
+export const CONVERSATIONS_FETCH_FAIL = 'CONVERSATIONS_FETCH_FAIL'
+
+export const CONVERSATIONS_EXPAND_REQUEST = 'CONVERSATIONS_EXPAND_REQUEST'
+export const CONVERSATIONS_EXPAND_SUCCESS = 'CONVERSATIONS_EXPAND_SUCCESS'
+export const CONVERSATIONS_EXPAND_FAIL = 'CONVERSATIONS_EXPAND_FAIL'
+
+/**
+ *
+ */
+export const blockMessenger = (accountId) => (dispatch, getState) => {
+ if (!accountId) return
+
+ dispatch(blockMessengerRequest(accountId))
+
+ api(getState).post(`/api/v1/messages/accounts/${accountId}/block`).then((response) => {
+ dispatch(blockMessengerSuccess(response.data))
+ }).catch((error) => {
+ dispatch(blockMessengerFail(accountId, error))
+ })
+}
+
+const blockMessengerRequest = (accountId) => ({
+ type: BLOCK_MESSAGER_REQUEST,
+ accountId,
+})
+
+const blockMessengerSuccess = (data) => ({
+ type: BLOCK_MESSAGER_REQUEST,
+ data,
+})
+
+const blockMessengerFail = (accountId, error) => ({
+ type: BLOCK_MESSAGER_REQUEST,
+ accountId,
+ error,
+})
+
+/**
+ *
+ */
+export const unblockMessenger = (accountId) => (dispatch, getState) => {
+ if (!accountId) return
+
+ dispatch(unblockMessengerRequest(accountId))
+
+ api(getState).post(`/api/v1/messages/accounts/${accountId}/unblock`).then((response) => {
+ dispatch(unblockMessengerSuccess(response.data))
+ }).catch((error) => {
+ dispatch(unblockMessengerFail(accountId, error))
+ })
+}
+
+const unblockMessengerRequest = (accountId) => ({
+ type: UNBLOCK_MESSAGER_REQUEST,
+ accountId,
+})
+
+const blockMessengerSuccess = (data) => ({
+ type: UNBLOCK_MESSAGER_REQUEST,
+ data,
+})
+
+const blockMessengerFail = (accountId, error) => ({
+ type: UNBLOCK_MESSAGER_REQUEST,
+ accountId,
+ error,
+})
+
+/**
+ *
+ */
+export const fetchBlocks = () => (dispatch, getState) => {
+ if (!me) return
+
+ dispatch(fetchBlocksRequest())
+
+ api(getState).get('/api/v1/blocks').then(response => {
+ const next = getLinks(response).refs.find(link => link.rel === 'next')
+ dispatch(importFetchedAccounts(response.data))
+ dispatch(fetchBlocksSuccess(response.data, next ? next.uri : null))
+ dispatch(fetchRelationships(response.data.map(item => item.id)))
+ }).catch(error => dispatch(fetchBlocksFail(error)))
+}
+
+export const fetchBlocksRequest = () => ({
+ type: BLOCKS_FETCH_REQUEST,
+})
+
+export const fetchBlocksSuccess = (accounts, next) => ({
+ type: BLOCKS_FETCH_SUCCESS,
+ accounts,
+ next,
+})
+
+export const fetchBlocksFail = (error) => ({
+ type: BLOCKS_FETCH_FAIL,
+ error,
+})
+
+/**
+ *
+ */
+export const expandBlocks = () => (dispatch, getState) => {
+ if (!me) return
+
+ const url = getState().getIn(['user_lists', 'blocks', me, 'next'])
+ const isLoading = getState().getIn(['user_lists', 'blocks', me, 'isLoading'])
+
+ if (url === null || isLoading) return
+
+ dispatch(expandBlocksRequest())
+
+ api(getState).get(url).then(response => {
+ const next = getLinks(response).refs.find(link => link.rel === 'next')
+ dispatch(importFetchedAccounts(response.data))
+ dispatch(expandBlocksSuccess(response.data, next ? next.uri : null))
+ dispatch(fetchRelationships(response.data.map(item => item.id)))
+ }).catch(error => dispatch(expandBlocksFail(error)))
+}
+
+export const expandBlocksRequest = () => ({
+ type: BLOCKS_EXPAND_REQUEST,
+})
+
+export const expandBlocksSuccess = (accounts, next) => ({
+ type: BLOCKS_EXPAND_SUCCESS,
+ accounts,
+ next,
+})
+
+export const expandBlocksFail = (error) => ({
+ type: BLOCKS_EXPAND_FAIL,
+ error,
+})
diff --git a/app/javascript/gabsocial/actions/chat_messages.js b/app/javascript/gabsocial/actions/chat_messages.js
new file mode 100644
index 00000000..e65912c9
--- /dev/null
+++ b/app/javascript/gabsocial/actions/chat_messages.js
@@ -0,0 +1,86 @@
+import api from '../api'
+import { me } from '../initial_state'
+
+export const MESSAGE_SEND_REQUEST = 'MESSAGE_SEND_REQUEST'
+export const MESSAGE_SEND_SUCCESS = 'MESSAGE_SEND_SUCCESS'
+export const MESSAGE_SEND_FAIL = 'MESSAGE_SEND_FAIL'
+
+export const MESSAGE_DELETE_REQUEST = 'MESSAGE_DELETE_REQUEST'
+export const MESSAGE_DELETE_SUCCESS = 'MESSAGE_DELETE_SUCCESS'
+export const MESSAGE_DELETE_FAIL = 'MESSAGE_DELETE_FAIL'
+
+/**
+ *
+ */
+const sendMessage = (text, conversationId) => (dispatch, getState) => {
+ if (!me) return
+
+ // : todo :
+ // let text = getState().getIn(['chat_messages', 'text'], '')
+ // let conversationId = getState().getIn(['chat_messags', 'conversation_id'], '')
+
+ dispatch(sendMessageRequest())
+
+ api(getState).put('/api/v1/messages/chat', {
+ text,
+ conversationId,
+ }, {
+ headers: {
+ 'Idempotency-Key': getState().getIn(['compose', 'idempotencyKey']),
+ },
+ }).then((response) => {
+ sendMessageSuccess(response)
+ }).catch((error) => {
+ dispatch(sendMessageFail(error))
+ })
+}
+
+const sendMessageRequest = (text, conversationId) => ({
+ type: MESSAGE_SEND_REQUEST,
+ text,
+ conversationId,
+})
+
+const sendMessageSuccess = () => ({
+ type: MESSAGE_SEND_SUCCESS,
+})
+
+const sendMessageFail = (error) => ({
+ type: MESSAGE_SEND_FAIL,
+ error,
+})
+
+/**
+ *
+ */
+const deleteMessage = (messageId) => (dispatch, getState) => {
+ if (!me || !messageId) return
+
+ // : todo :
+
+ dispatch(sendMessageRequest())
+
+ api(getState).delete(`/api/v1/messages/chat/${messageId}`, {}, {
+ headers: {
+ 'Idempotency-Key': getState().getIn(['compose', 'idempotencyKey']),
+ },
+ }).then((response) => {
+ sendMessageSuccess(response)
+ }).catch((error) => {
+ dispatch(sendMessageFail(error))
+ })
+}
+
+const deleteMessageRequest = (messageId) => ({
+ type: MESSAGE_DELETE_REQUEST,
+ messageId,
+})
+
+const deleteMessageSuccess = () => ({
+ type: MESSAGE_DELETE_SUCCESS,
+})
+
+const deleteMessageFail = (error) => ({
+ type: MESSAGE_DELETE_FAIL,
+ error,
+})
\ No newline at end of file
diff --git a/app/javascript/gabsocial/actions/compose.js b/app/javascript/gabsocial/actions/compose.js
index fe9e4d80..91eb47bb 100644
--- a/app/javascript/gabsocial/actions/compose.js
+++ b/app/javascript/gabsocial/actions/compose.js
@@ -19,6 +19,7 @@ import {
import { defineMessages } from 'react-intl'
import { openModal, closeModal } from './modal'
import {
+ MODAL_COMPOSE,
STATUS_EXPIRATION_OPTION_5_MINUTES,
STATUS_EXPIRATION_OPTION_60_MINUTES,
STATUS_EXPIRATION_OPTION_6_HOURS,
@@ -57,18 +58,18 @@ export const COMPOSE_TAG_HISTORY_UPDATE = 'COMPOSE_TAG_HISTORY_UPDATE'
export const COMPOSE_MOUNT = 'COMPOSE_MOUNT'
export const COMPOSE_UNMOUNT = 'COMPOSE_UNMOUNT'
-export const COMPOSE_SENSITIVITY_CHANGE = 'COMPOSE_SENSITIVITY_CHANGE'
-export const COMPOSE_SPOILERNESS_CHANGE = 'COMPOSE_SPOILERNESS_CHANGE'
+export const COMPOSE_SENSITIVITY_CHANGE = 'COMPOSE_SENSITIVITY_CHANGE'
+export const COMPOSE_SPOILERNESS_CHANGE = 'COMPOSE_SPOILERNESS_CHANGE'
export const COMPOSE_SPOILER_TEXT_CHANGE = 'COMPOSE_SPOILER_TEXT_CHANGE'
-export const COMPOSE_VISIBILITY_CHANGE = 'COMPOSE_VISIBILITY_CHANGE'
-export const COMPOSE_LISTABILITY_CHANGE = 'COMPOSE_LISTABILITY_CHANGE'
-export const COMPOSE_COMPOSING_CHANGE = 'COMPOSE_COMPOSING_CHANGE'
+export const COMPOSE_VISIBILITY_CHANGE = 'COMPOSE_VISIBILITY_CHANGE'
+export const COMPOSE_LISTABILITY_CHANGE = 'COMPOSE_LISTABILITY_CHANGE'
+export const COMPOSE_COMPOSING_CHANGE = 'COMPOSE_COMPOSING_CHANGE'
export const COMPOSE_EMOJI_INSERT = 'COMPOSE_EMOJI_INSERT'
-export const COMPOSE_UPLOAD_CHANGE_REQUEST = 'COMPOSE_UPLOAD_UPDATE_REQUEST'
-export const COMPOSE_UPLOAD_CHANGE_SUCCESS = 'COMPOSE_UPLOAD_UPDATE_SUCCESS'
-export const COMPOSE_UPLOAD_CHANGE_FAIL = 'COMPOSE_UPLOAD_UPDATE_FAIL'
+export const COMPOSE_UPLOAD_CHANGE_REQUEST = 'COMPOSE_UPLOAD_UPDATE_REQUEST'
+export const COMPOSE_UPLOAD_CHANGE_SUCCESS = 'COMPOSE_UPLOAD_UPDATE_SUCCESS'
+export const COMPOSE_UPLOAD_CHANGE_FAIL = 'COMPOSE_UPLOAD_UPDATE_FAIL'
export const COMPOSE_POLL_ADD = 'COMPOSE_POLL_ADD'
export const COMPOSE_POLL_REMOVE = 'COMPOSE_POLL_REMOVE'
@@ -90,157 +91,188 @@ const messages = defineMessages({
uploadErrorPoll: { id: 'upload_error.poll', defaultMessage: 'File upload not allowed with polls.' },
})
-const COMPOSE_PANEL_BREAKPOINT = 600 + (285 * 1) + (10 * 1)
+/**
+ *
+ */
+export const hydrateCompose = () => (dispatch, getState) => {
+ const me = getState().getIn(['meta', 'me'])
+ const history = tagHistory.get(me)
-export const ensureComposeIsVisible = (getState, routerHistory) => {
- if (!getState().getIn(['compose', 'mounted']) && window.innerWidth < COMPOSE_PANEL_BREAKPOINT) {
- routerHistory.push('/posts/new')
+ if (history !== null) {
+ dispatch(updateTagHistory(history))
}
}
-export function changeCompose(text, markdown, replyId, isStandalone, caretPosition) {
- return function (dispatch, getState) {
- const reduxReplyToId = getState().getIn(['compose', 'in_reply_to'])
- const existingText = getState().getIn(['compose', 'text']).trim()
- const isModalOpen = getState().getIn(['modal', 'modalType']) === 'COMPOSE' || isStandalone
+/**
+ *
+ */
+const insertIntoTagHistory = (recognizedTags, text) => (dispatch, getState) => {
+ const state = getState()
+ const oldHistory = state.getIn(['compose', 'tagHistory'])
+ const me = state.getIn(['meta', 'me'])
+ const names = recognizedTags.map(tag => text.match(new RegExp(`#${tag.name}`, 'i'))[0].slice(1))
+ const intersectedOldHistory = oldHistory.filter(name => names.findIndex(newName => newName.toLowerCase() === name.toLowerCase()) === -1)
- let status
- if (!!replyId) {
- status = getState().getIn(['statuses', replyId])
- status = makeGetStatus()(getState(), {
- id: status.get('id')
+ names.push(...intersectedOldHistory.toJS())
+
+ const newHistory = names.slice(0, 1000)
+
+ tagHistory.set(me, newHistory)
+ dispatch(updateTagHistory(newHistory))
+}
+
+/**
+ *
+ */
+export const changeCompose = (text, markdown, replyId, isStandalone, caretPosition) => (dispatch, getState) => {
+ const reduxReplyToId = getState().getIn(['compose', 'in_reply_to'])
+ const existingText = getState().getIn(['compose', 'text']).trim()
+ const isModalOpen = getState().getIn(['modal', 'modalType']) === MODAL_COMPOSE || isStandalone
+
+ let status
+ if (!!replyId) {
+ status = getState().getIn(['statuses', replyId])
+ status = makeGetStatus()(getState(), {
+ id: status.get('id')
+ })
+ }
+
+ if (!!replyId && replyId !== reduxReplyToId && !isModalOpen) {
+ if (existingText.length === 0 && text.trim().length > 0) {
+ dispatch({
+ type: COMPOSE_REPLY,
+ status,
+ text: text,
+ })
+ } else if (existingText.length > 0 && text.trim().length > 0) {
+ dispatch(openModal('CONFIRM', {
+ message: ,
+ confirm: ,
+ onConfirm: () => {
+ dispatch({
+ type: COMPOSE_REPLY,
+ status,
+ })
+ dispatch({
+ type: COMPOSE_CHANGE,
+ text: text,
+ markdown: markdown,
+ caretPosition: caretPosition,
+ })
+ }
+ }))
+ } else {
+ dispatch({
+ type: COMPOSE_REPLY_CANCEL,
})
}
-
- if (!!replyId && replyId !== reduxReplyToId && !isModalOpen) {
- if (existingText.length === 0 && text.trim().length > 0) {
- dispatch({
- type: COMPOSE_REPLY,
- status: status,
- text: text,
- })
- } else if (existingText.length > 0 && text.trim().length > 0) {
- dispatch(openModal('CONFIRM', {
- message: ,
- confirm: ,
- onConfirm: () => {
- dispatch({
- type: COMPOSE_REPLY,
- status: status,
- })
- dispatch({
- type: COMPOSE_CHANGE,
- text: text,
- markdown: markdown,
- caretPosition: caretPosition,
- })
- }
- }))
- } else {
- dispatch({
- type: COMPOSE_REPLY_CANCEL,
- })
- }
- } else if (!replyId && !!reduxReplyToId && !isModalOpen) {
- if (existingText.length === 0 && text.trim().length > 0) {
- dispatch({
- type: COMPOSE_REPLY_CANCEL,
- })
- dispatch({
- type: COMPOSE_CHANGE,
- text: text,
- markdown: markdown,
- caretPosition: caretPosition,
- })
- } else if (existingText.length > 0 && text.trim().length > 0) {
- dispatch(openModal('CONFIRM', {
- message: ,
- confirm: ,
- onConfirm: () => {
- dispatch({
- type: COMPOSE_REPLY_CANCEL,
- })
- dispatch({
- type: COMPOSE_CHANGE,
- text: text,
- markdown: markdown,
- caretPosition: caretPosition,
- })
- },
- }))
- } else {
- //
- }
- } else {
+ } else if (!replyId && !!reduxReplyToId && !isModalOpen) {
+ if (existingText.length === 0 && text.trim().length > 0) {
+ dispatch({
+ type: COMPOSE_REPLY_CANCEL,
+ })
dispatch({
type: COMPOSE_CHANGE,
text: text,
markdown: markdown,
caretPosition: caretPosition,
})
+ } else if (existingText.length > 0 && text.trim().length > 0) {
+ dispatch(openModal('CONFIRM', {
+ message: ,
+ confirm: ,
+ onConfirm: () => {
+ dispatch({
+ type: COMPOSE_REPLY_CANCEL,
+ })
+ dispatch({
+ type: COMPOSE_CHANGE,
+ text: text,
+ markdown: markdown,
+ caretPosition: caretPosition,
+ })
+ },
+ }))
+ } else {
+ //
+ }
+ } else {
+ dispatch({
+ type: COMPOSE_CHANGE,
+ text: text,
+ markdown: markdown,
+ caretPosition: caretPosition,
+ })
+ }
+}
+
+/**
+ *
+ */
+export const replyCompose = (status, router, showModal) => (dispatch) => {
+ dispatch({
+ type: COMPOSE_REPLY,
+ status,
+ })
+
+ if (isMobile(window.innerWidth)) {
+ router.history.push('/compose')
+ } else {
+ if (showModal) {
+ dispatch(openModal(MODAL_COMPOSE))
}
}
}
-export function replyCompose(status, router, showModal) {
- return (dispatch) => {
- dispatch({
- type: COMPOSE_REPLY,
- status: status,
- });
+/**
+ *
+ */
+export const quoteCompose = (status, router) => (dispatch) => {
+ dispatch({
+ type: COMPOSE_QUOTE,
+ status,
+ })
- if (isMobile(window.innerWidth)) {
- router.history.push('/compose')
- } else {
- if (showModal) {
- dispatch(openModal('COMPOSE'));
- }
- }
- };
-};
+ if (isMobile(window.innerWidth)) {
+ router.history.push('/compose')
+ } else {
+ dispatch(openModal(MODAL_COMPOSE))
+ }
+}
-export function quoteCompose(status, router) {
- return (dispatch) => {
- dispatch({
- type: COMPOSE_QUOTE,
- status: status,
- });
+/**
+ *
+ */
+export const cancelReplyCompose = () => ({
+ type: COMPOSE_REPLY_CANCEL,
+})
- if (isMobile(window.innerWidth)) {
- router.history.push('/compose')
- } else {
- dispatch(openModal('COMPOSE'));
- }
- };
-};
+/**
+ *
+ */
+export const resetCompose = () => ({
+ type: COMPOSE_RESET,
+})
-export function cancelReplyCompose() {
- return {
- type: COMPOSE_REPLY_CANCEL,
- };
-};
+/**
+ *
+ */
+export const mentionCompose = (account) => (dispatch) => {
+ dispatch({
+ type: COMPOSE_MENTION,
+ account: account,
+ })
-export function resetCompose() {
- return {
- type: COMPOSE_RESET,
- };
-};
+ dispatch(openModal(MODAL_COMPOSE))
+}
-export function mentionCompose(account) {
- return (dispatch) => {
- dispatch({
- type: COMPOSE_MENTION,
- account: account,
- });
+/**
+ *
+ */
+export const handleComposeSubmit = (dispatch, getState, response, status) => {
+ if (!dispatch || !getState) return
- dispatch(openModal('COMPOSE'));
- };
-};
-
-export function handleComposeSubmit(dispatch, getState, response, status) {
- if (!dispatch || !getState) return;
-
- const isScheduledStatus = response.data.scheduled_at !== undefined;
+ const isScheduledStatus = response.data.scheduled_at !== undefined
if (isScheduledStatus) {
// dispatch(showAlertForError({
// response: {
@@ -248,486 +280,458 @@ export function handleComposeSubmit(dispatch, getState, response, status) {
// status: 200,
// statusText: 'Successfully scheduled status',
// }
- // }));
- dispatch(submitComposeSuccess({ ...response.data }));
- return;
+ // }))
+ dispatch(submitComposeSuccess({ ...response.data }))
+ return
}
- dispatch(insertIntoTagHistory(response.data.tags, status));
- dispatch(submitComposeSuccess({ ...response.data }));
+ dispatch(insertIntoTagHistory(response.data.tags, status))
+ dispatch(submitComposeSuccess({ ...response.data }))
// To make the app more responsive, immediately push the status into the timeline
// : todo : push into comment, reload parent status, etc.
- const insertIfOnline = timelineId => {
- const timeline = getState().getIn(['timelines', timelineId]);
+ const insertIfOnline = (timelineId) => {
+ const timeline = getState().getIn(['timelines', timelineId])
if (timeline && timeline.get('items').size > 0 && timeline.getIn(['items', 0]) !== null && timeline.get('online')) {
- dispatch(updateTimeline(timelineId, { ...response.data }));
+ dispatch(updateTimeline(timelineId, { ...response.data }))
}
- };
+ }
if (response.data.visibility === 'public') {
- insertIfOnline('home');
+ insertIfOnline('home')
}
}
-export function submitCompose(groupId, replyToId = null, router, isStandalone, autoJoinGroup) {
- return function (dispatch, getState) {
- if (!me) return;
+/**
+ *
+ */
+export const submitCompose = (groupId, replyToId = null, router, isStandalone, autoJoinGroup) => (dispatch, getState) => {
+ if (!me) return
- if (autoJoinGroup) dispatch(joinGroup(groupId))
+ if (autoJoinGroup) dispatch(joinGroup(groupId))
- let status = getState().getIn(['compose', 'text'], '');
- let markdown = getState().getIn(['compose', 'markdown'], '');
- const media = getState().getIn(['compose', 'media_attachments']);
- const isPrivateGroup = !!groupId ? getState().getIn(['groups', groupId, 'is_private'], false) : false
+ let status = getState().getIn(['compose', 'text'], '')
+ let markdown = getState().getIn(['compose', 'markdown'], '')
+ const media = getState().getIn(['compose', 'media_attachments'])
+ const isPrivateGroup = !!groupId ? getState().getIn(['groups', groupId, 'is_private'], false) : false
- const replacer = (match) => {
- const hasProtocol = match.startsWith('https://') || match.startsWith('http://')
- //Make sure not a remote mention like @someone@somewhere.com
- if (!hasProtocol) {
- if (status.indexOf(`@${match}`) > -1) return match
- }
- return hasProtocol ? match : `http://${match}`
+ const replacer = (match) => {
+ const hasProtocol = match.startsWith('https://') || match.startsWith('http://')
+ //Make sure not a remote mention like @someone@somewhere.com
+ if (!hasProtocol) {
+ if (status.indexOf(`@${match}`) > -1) return match
}
+ return hasProtocol ? match : `http://${match}`
+ }
- // : hack :
- //Prepend http:// to urls in status that don't have protocol
- status = `${status}`.replace(urlRegex, replacer)
- markdown = !!markdown ? `${markdown}`.replace(urlRegex, replacer) : undefined
+ // : hack :
+ //Prepend http:// to urls in status that don't have protocol
+ status = `${status}`.replace(urlRegex, replacer)
+ markdown = !!markdown ? `${markdown}`.replace(urlRegex, replacer) : undefined
- const inReplyToId = getState().getIn(['compose', 'in_reply_to'], null) || replyToId
+ const inReplyToId = getState().getIn(['compose', 'in_reply_to'], null) || replyToId
- dispatch(submitComposeRequest());
- dispatch(closeModal());
+ dispatch(submitComposeRequest())
+ dispatch(closeModal())
- const id = getState().getIn(['compose', 'id']);
- const endpoint = id === null
- ? '/api/v1/statuses'
- : `/api/v1/statuses/${id}`;
- const method = id === null ? 'post' : 'put';
+ const id = getState().getIn(['compose', 'id'])
+ const endpoint = id === null
+ ? '/api/v1/statuses'
+ : `/api/v1/statuses/${id}`
+ const method = id === null ? 'post' : 'put'
- let scheduled_at = getState().getIn(['compose', 'scheduled_at'], null);
- if (scheduled_at !== null) scheduled_at = moment.utc(scheduled_at).toDate();
+ let scheduled_at = getState().getIn(['compose', 'scheduled_at'], null)
+ if (scheduled_at !== null) scheduled_at = moment.utc(scheduled_at).toDate()
- let expires_at = getState().getIn(['compose', 'expires_at'], null);
+ let expires_at = getState().getIn(['compose', 'expires_at'], null)
- if (expires_at) {
- if (expires_at === STATUS_EXPIRATION_OPTION_5_MINUTES) {
- expires_at = moment.utc().add('5', 'minute').toDate()
- } else if (expires_at === STATUS_EXPIRATION_OPTION_60_MINUTES) {
- expires_at = moment.utc().add('60', 'minute').toDate()
- } else if (expires_at === STATUS_EXPIRATION_OPTION_6_HOURS) {
- expires_at = moment.utc().add('6', 'hour').toDate()
- } else if (expires_at === STATUS_EXPIRATION_OPTION_24_HOURS) {
- expires_at = moment.utc().add('24', 'hour').toDate()
- } else if (expires_at === STATUS_EXPIRATION_OPTION_3_DAYS) {
- expires_at = moment.utc().add('3', 'day').toDate()
- } else if (expires_at === STATUS_EXPIRATION_OPTION_7_DAYS) {
- expires_at = moment.utc().add('7', 'day').toDate()
- }
+ if (expires_at) {
+ if (expires_at === STATUS_EXPIRATION_OPTION_5_MINUTES) {
+ expires_at = moment.utc().add('5', 'minute').toDate()
+ } else if (expires_at === STATUS_EXPIRATION_OPTION_60_MINUTES) {
+ expires_at = moment.utc().add('60', 'minute').toDate()
+ } else if (expires_at === STATUS_EXPIRATION_OPTION_6_HOURS) {
+ expires_at = moment.utc().add('6', 'hour').toDate()
+ } else if (expires_at === STATUS_EXPIRATION_OPTION_24_HOURS) {
+ expires_at = moment.utc().add('24', 'hour').toDate()
+ } else if (expires_at === STATUS_EXPIRATION_OPTION_3_DAYS) {
+ expires_at = moment.utc().add('3', 'day').toDate()
+ } else if (expires_at === STATUS_EXPIRATION_OPTION_7_DAYS) {
+ expires_at = moment.utc().add('7', 'day').toDate()
}
+ }
- if (isMobile(window.innerWidth) && router && isStandalone) {
- router.history.goBack()
- }
+ if (isMobile(window.innerWidth) && router && isStandalone) {
+ router.history.goBack()
+ }
- api(getState)[method](endpoint, {
- status,
- markdown,
- expires_at,
- scheduled_at,
- autoJoinGroup,
- isPrivateGroup,
- in_reply_to_id: inReplyToId,
- quote_of_id: getState().getIn(['compose', 'quote_of_id'], null),
- media_ids: media.map(item => item.get('id')),
- sensitive: getState().getIn(['compose', 'sensitive']),
- spoiler_text: getState().getIn(['compose', 'spoiler_text'], ''),
- visibility: getState().getIn(['compose', 'privacy']),
- poll: getState().getIn(['compose', 'poll'], null),
- group_id: groupId || null,
- }, {
- headers: {
- 'Idempotency-Key': getState().getIn(['compose', 'idempotencyKey']),
- },
- }).then(function (response) {
- handleComposeSubmit(dispatch, getState, response, status);
- }).catch(function (error) {
- dispatch(submitComposeFail(error));
- });
- };
-};
+ api(getState)[method](endpoint, {
+ status,
+ markdown,
+ expires_at,
+ scheduled_at,
+ autoJoinGroup,
+ isPrivateGroup,
+ in_reply_to_id: inReplyToId,
+ quote_of_id: getState().getIn(['compose', 'quote_of_id'], null),
+ media_ids: media.map(item => item.get('id')),
+ sensitive: getState().getIn(['compose', 'sensitive']),
+ spoiler_text: getState().getIn(['compose', 'spoiler_text'], ''),
+ visibility: getState().getIn(['compose', 'privacy']),
+ poll: getState().getIn(['compose', 'poll'], null),
+ group_id: groupId || null,
+ }, {
+ headers: {
+ 'Idempotency-Key': getState().getIn(['compose', 'idempotencyKey']),
+ },
+ }).then((response) => {
+ handleComposeSubmit(dispatch, getState, response, status)
+ }).catch((error) => {
+ dispatch(submitComposeFail(error))
+ })
+}
-export function submitComposeRequest() {
- return {
- type: COMPOSE_SUBMIT_REQUEST,
- };
-};
+const submitComposeRequest = () => ({
+ type: COMPOSE_SUBMIT_REQUEST,
+})
-export function submitComposeSuccess(status) {
- return {
- type: COMPOSE_SUBMIT_SUCCESS,
- status: status,
- };
-};
+const submitComposeSuccess = (status) => ({
+ type: COMPOSE_SUBMIT_SUCCESS,
+ status,
+})
-export function clearCompose() {
- return {
- type: COMPOSE_CLEAR,
- };
-};
+const submitComposeFail = (error) => ({
+ type: COMPOSE_SUBMIT_FAIL,
+ error,
+})
-export function submitComposeFail(error) {
- return {
- type: COMPOSE_SUBMIT_FAIL,
- error: error,
+/**
+ *
+ */
+export const uploadCompose = (files) => (dispatch, getState) => {
+ if (!me) return
+
+ const uploadLimit = 4
+ const media = getState().getIn(['compose', 'media_attachments'])
+ const pending = getState().getIn(['compose', 'pending_media_attachments'])
+ const progress = new Array(files.length).fill(0)
+ let total = Array.from(files).reduce((a, v) => a + v.size, 0)
+
+ if (files.length + media.size + pending > uploadLimit) {
+ // dispatch(showAlert(undefined, messages.uploadErrorLimit))
+ return
+ }
+
+ if (getState().getIn(['compose', 'poll'])) {
+ // dispatch(showAlert(undefined, messages.uploadErrorPoll))
+ return
+ }
+
+ dispatch(uploadComposeRequest())
+
+ for (const [i, f] of Array.from(files).entries()) {
+ if (media.size + i > 3) break
+
+ resizeImage(f).then((file) => {
+ const data = new FormData()
+ data.append('file', file)
+ // Account for disparity in size of original image and resized data
+ total += file.size - f.size
+
+ return api(getState).post('/api/v1/media', data, {
+ onUploadProgress: ({ loaded }) => {
+ progress[i] = loaded
+ dispatch(uploadComposeProgress(progress.reduce((a, v) => a + v, 0), total))
+ },
+ }).then(({ data }) => dispatch(uploadComposeSuccess(data)))
+ }).catch((error) => dispatch(uploadComposeFail(error, true)))
}
}
-export function uploadCompose(files) {
- return function (dispatch, getState) {
- if (!me) return
+const uploadComposeRequest = () => ({
+ type: COMPOSE_UPLOAD_REQUEST,
+})
- const uploadLimit = 4
- const media = getState().getIn(['compose', 'media_attachments'])
- const pending = getState().getIn(['compose', 'pending_media_attachments'])
- const progress = new Array(files.length).fill(0);
- let total = Array.from(files).reduce((a, v) => a + v.size, 0);
+const uploadComposeProgress = (loaded, total) => ({
+ type: COMPOSE_UPLOAD_PROGRESS,
+ loaded: loaded,
+ total: total,
+})
- if (files.length + media.size + pending > uploadLimit) {
- // dispatch(showAlert(undefined, messages.uploadErrorLimit));
- return;
- }
+const uploadComposeSuccess = (media) => ({
+ type: COMPOSE_UPLOAD_SUCCESS,
+ media: media,
+})
- if (getState().getIn(['compose', 'poll'])) {
- // dispatch(showAlert(undefined, messages.uploadErrorPoll));
- return;
- }
+const uploadComposeFail = (error) => ({
+ type: COMPOSE_UPLOAD_FAIL,
+ error,
+})
- dispatch(uploadComposeRequest());
+/**
+ *
+ */
+export const changeUploadCompose = (id, params) => (dispatch, getState) => {
+ if (!me) return
- for (const [i, f] of Array.from(files).entries()) {
- if (media.size + i > 3) break;
+ dispatch(changeUploadComposeRequest())
- resizeImage(f).then((file) => {
- const data = new FormData();
- data.append('file', file);
- // Account for disparity in size of original image and resized data
- total += file.size - f.size;
+ api(getState).put(`/api/v1/media/${id}`, params).then((response) => {
+ dispatch(changeUploadComposeSuccess(response.data))
+ }).catch((error) => {
+ dispatch(changeUploadComposeFail(id, error))
+ })
+}
- return api(getState).post('/api/v1/media', data, {
- onUploadProgress: function({ loaded }){
- progress[i] = loaded;
- dispatch(uploadComposeProgress(progress.reduce((a, v) => a + v, 0), total));
- },
- }).then(({ data }) => dispatch(uploadComposeSuccess(data)));
- }).catch(error => dispatch(uploadComposeFail(error, true)));
- };
- };
-};
+const changeUploadComposeRequest = () => ({
+ type: COMPOSE_UPLOAD_CHANGE_REQUEST,
+})
-export function changeUploadCompose(id, params) {
- return (dispatch, getState) => {
- if (!me) return;
+const changeUploadComposeSuccess = (media) => ({
+ type: COMPOSE_UPLOAD_CHANGE_SUCCESS,
+ media: media,
+})
- dispatch(changeUploadComposeRequest());
+const changeUploadComposeFail = (error, decrement = false) => ({
+ type: COMPOSE_UPLOAD_CHANGE_FAIL,
+ error,
+ decrement: decrement,
+})
- api(getState).put(`/api/v1/media/${id}`, params).then(response => {
- dispatch(changeUploadComposeSuccess(response.data));
- }).catch(error => {
- dispatch(changeUploadComposeFail(id, error));
- });
- };
-};
+/**
+ *
+ */
+export const undoUploadCompose = (media_id) => ({
+ type: COMPOSE_UPLOAD_UNDO,
+ media_id: media_id,
+})
-export function changeUploadComposeRequest() {
- return {
- type: COMPOSE_UPLOAD_CHANGE_REQUEST,
- skipLoading: true,
- };
-};
-export function changeUploadComposeSuccess(media) {
- return {
- type: COMPOSE_UPLOAD_CHANGE_SUCCESS,
- media: media,
- skipLoading: true,
- };
-};
-
-export function changeUploadComposeFail(error, decrement = false) {
- return {
- type: COMPOSE_UPLOAD_CHANGE_FAIL,
- error: error,
- decrement: decrement,
- skipLoading: true,
- };
-};
-
-export function uploadComposeRequest() {
- return {
- type: COMPOSE_UPLOAD_REQUEST,
- skipLoading: true,
- };
-};
-
-export function uploadComposeProgress(loaded, total) {
- return {
- type: COMPOSE_UPLOAD_PROGRESS,
- loaded: loaded,
- total: total,
- };
-};
-
-export function uploadComposeSuccess(media) {
- return {
- type: COMPOSE_UPLOAD_SUCCESS,
- media: media,
- skipLoading: true,
- };
-};
-
-export function uploadComposeFail(error) {
- return {
- type: COMPOSE_UPLOAD_FAIL,
- error: error,
- skipLoading: true,
- };
-};
-
-export function undoUploadCompose(media_id) {
- return {
- type: COMPOSE_UPLOAD_UNDO,
- media_id: media_id,
- };
-};
-
-export function clearComposeSuggestions() {
+/**
+ *
+ */
+export const clearComposeSuggestions = () => {
if (cancelFetchComposeSuggestionsAccounts) {
- cancelFetchComposeSuggestionsAccounts();
+ cancelFetchComposeSuggestionsAccounts()
}
+
return {
type: COMPOSE_SUGGESTIONS_CLEAR,
- };
-};
+ }
+}
+
+/**
+ *
+ */
+export const fetchComposeSuggestions = (token) => (dispatch, getState) => {
+ switch (token[0]) {
+ case ':':
+ fetchComposeSuggestionsEmojis(dispatch, getState, token)
+ break
+ case '#':
+ fetchComposeSuggestionsTags(dispatch, getState, token)
+ break
+ default:
+ fetchComposeSuggestionsAccounts(dispatch, getState, token)
+ break
+ }
+}
const fetchComposeSuggestionsAccounts = throttle((dispatch, getState, token) => {
if (cancelFetchComposeSuggestionsAccounts) {
- cancelFetchComposeSuggestionsAccounts();
+ cancelFetchComposeSuggestionsAccounts()
}
+
api(getState).get('/api/v1/accounts/search', {
cancelToken: new CancelToken(cancel => {
- cancelFetchComposeSuggestionsAccounts = cancel;
+ cancelFetchComposeSuggestionsAccounts = cancel
}),
params: {
q: token.slice(1),
resolve: false,
limit: 4,
},
- }).then(response => {
- dispatch(importFetchedAccounts(response.data));
- dispatch(readyComposeSuggestionsAccounts(token, response.data));
- }).catch(error => {
+ }).then((response) => {
+ dispatch(importFetchedAccounts(response.data))
+ dispatch(readyComposeSuggestionsAccounts(token, response.data))
+ }).catch((error) => {
if (!isCancel(error)) {
- // dispatch(showAlertForError(error));
+ // dispatch(showAlertForError(error))
}
- });
-}, 200, { leading: true, trailing: true });
+ })
+}, 200, { leading: true, trailing: true })
const fetchComposeSuggestionsEmojis = (dispatch, getState, token) => {
- const results = emojiSearch(token.replace(':', ''), { maxResults: 5 });
- dispatch(readyComposeSuggestionsEmojis(token, results));
-};
+ const results = emojiSearch(token.replace(':', ''), { maxResults: 5 })
+ dispatch(readyComposeSuggestionsEmojis(token, results))
+}
const fetchComposeSuggestionsTags = (dispatch, getState, token) => {
- dispatch(updateSuggestionTags(token));
-};
+ dispatch(updateSuggestionTags(token))
+}
-export function fetchComposeSuggestions(token) {
- return (dispatch, getState) => {
- switch (token[0]) {
- case ':':
- fetchComposeSuggestionsEmojis(dispatch, getState, token);
- break;
- case '#':
- fetchComposeSuggestionsTags(dispatch, getState, token);
- break;
- default:
- fetchComposeSuggestionsAccounts(dispatch, getState, token);
- break;
- }
- };
-};
+const readyComposeSuggestionsEmojis = (token, emojis) => ({
+ type: COMPOSE_SUGGESTIONS_READY,
+ token,
+ emojis,
+})
-export function readyComposeSuggestionsEmojis(token, emojis) {
- return {
- type: COMPOSE_SUGGESTIONS_READY,
- token,
- emojis,
- };
-};
-
-export const readyComposeSuggestionsAccounts = (token, accounts) => ({
+const readyComposeSuggestionsAccounts = (token, accounts) => ({
type: COMPOSE_SUGGESTIONS_READY,
token,
accounts,
})
-export function selectComposeSuggestion(position, token, suggestion, path) {
- return (dispatch, getState) => {
- let completion, startPosition;
+/**
+ *
+ */
+export const selectComposeSuggestion = (position, token, suggestion, path) => (dispatch, getState) => {
+ let completion, startPosition
- if (typeof suggestion === 'object' && suggestion.id) {
- completion = suggestion.native || suggestion.colons;
- startPosition = position - 1;
+ if (typeof suggestion === 'object' && suggestion.id) {
+ completion = suggestion.native || suggestion.colons
+ startPosition = position - 1
- dispatch(useEmoji(suggestion));
- } else if (suggestion[0] === '#') {
- completion = suggestion;
- startPosition = position - 1;
- } else {
- completion = getState().getIn(['accounts', suggestion, 'acct']);
- startPosition = position;
- }
+ dispatch(useEmoji(suggestion))
+ } else if (suggestion[0] === '#') {
+ completion = suggestion
+ startPosition = position - 1
+ } else {
+ completion = getState().getIn(['accounts', suggestion, 'acct'])
+ startPosition = position
+ }
- dispatch({
- type: COMPOSE_SUGGESTION_SELECT,
- position: startPosition,
- token,
- completion,
- path,
- });
- };
-};
-
-export function updateSuggestionTags(token) {
- return {
- type: COMPOSE_SUGGESTION_TAGS_UPDATE,
+ dispatch({
+ type: COMPOSE_SUGGESTION_SELECT,
+ position: startPosition,
token,
- };
+ completion,
+ path,
+ })
}
-export function updateTagHistory(tags) {
- return {
- type: COMPOSE_TAG_HISTORY_UPDATE,
- tags,
- };
-}
+/**
+ *
+ */
+export const updateSuggestionTags = (token) => ({
+ type: COMPOSE_SUGGESTION_TAGS_UPDATE,
+ token,
+})
-export function hydrateCompose() {
- return (dispatch, getState) => {
- const me = getState().getIn(['meta', 'me']);
- const history = tagHistory.get(me);
+/**
+ *
+ */
+export const updateTagHistory = (tags) => ({
+ type: COMPOSE_TAG_HISTORY_UPDATE,
+ tags,
+})
- if (history !== null) {
- dispatch(updateTagHistory(history));
- }
- };
-}
+/**
+ *
+ */
+export const mountCompose = () => ({
+ type: COMPOSE_MOUNT,
+})
-function insertIntoTagHistory(recognizedTags, text) {
- return (dispatch, getState) => {
- const state = getState();
- const oldHistory = state.getIn(['compose', 'tagHistory']);
- const me = state.getIn(['meta', 'me']);
- const names = recognizedTags.map(tag => text.match(new RegExp(`#${tag.name}`, 'i'))[0].slice(1));
- const intersectedOldHistory = oldHistory.filter(name => names.findIndex(newName => newName.toLowerCase() === name.toLowerCase()) === -1);
+/**
+ *
+ */
+export const unmountCompose = () => ({
+ type: COMPOSE_UNMOUNT,
+})
- names.push(...intersectedOldHistory.toJS());
+/**
+ *
+ */
+export const clearCompose = () => ({
+ type: COMPOSE_CLEAR,
+})
- const newHistory = names.slice(0, 1000);
+/**
+ *
+ */
+export const changeComposeSensitivity = () => ({
+ type: COMPOSE_SENSITIVITY_CHANGE,
+})
- tagHistory.set(me, newHistory);
- dispatch(updateTagHistory(newHistory));
- };
-}
+/**
+ *
+ */
+export const changeComposeSpoilerness = () => ({
+ type: COMPOSE_SPOILERNESS_CHANGE,
+})
-export function mountCompose() {
- return {
- type: COMPOSE_MOUNT,
- };
-};
+/**
+ *
+ */
+export const changeComposeSpoilerText = (text) => ({
+ type: COMPOSE_SPOILER_TEXT_CHANGE,
+ text,
+})
-export function unmountCompose() {
- return {
- type: COMPOSE_UNMOUNT,
- };
-};
+/**
+ *
+ */
+export const changeComposeVisibility = (value) => ({
+ type: COMPOSE_VISIBILITY_CHANGE,
+ value,
+})
-export function changeComposeSensitivity() {
- return {
- type: COMPOSE_SENSITIVITY_CHANGE,
- };
-};
+/**
+ *
+ */
+export const insertEmojiCompose = (emoji, needsSpace) => ({
+ type: COMPOSE_EMOJI_INSERT,
+ emoji,
+ needsSpace,
+})
-export function changeComposeSpoilerness() {
- return {
- type: COMPOSE_SPOILERNESS_CHANGE,
- };
-};
+/**
+ *
+ */
+export const changeComposing = (value) => ({
+ type: COMPOSE_COMPOSING_CHANGE,
+ value,
+})
-export function changeComposeSpoilerText(text) {
- return {
- type: COMPOSE_SPOILER_TEXT_CHANGE,
- text,
- };
-};
+/**
+ *
+ */
+export const addPoll = () => ({
+ type: COMPOSE_POLL_ADD,
+})
-export function changeComposeVisibility(value) {
- return {
- type: COMPOSE_VISIBILITY_CHANGE,
- value,
- };
-};
+/**
+ *
+ */
+export const removePoll = () => ({
+ type: COMPOSE_POLL_REMOVE,
+})
-export function insertEmojiCompose(emoji, needsSpace) {
- return {
- type: COMPOSE_EMOJI_INSERT,
- emoji,
- needsSpace,
- };
-};
+/**
+ *
+ */
+export const addPollOption = (title) => ({
+ type: COMPOSE_POLL_OPTION_ADD,
+ title,
+})
-export function changeComposing(value) {
- return {
- type: COMPOSE_COMPOSING_CHANGE,
- value,
- };
-};
+/**
+ *
+ */
+export const changePollOption = (index, title) => ({
+ type: COMPOSE_POLL_OPTION_CHANGE,
+ index,
+ title,
+})
-export function addPoll() {
- return {
- type: COMPOSE_POLL_ADD,
- };
-};
-
-export function removePoll() {
- return {
- type: COMPOSE_POLL_REMOVE,
- };
-};
-
-export function addPollOption(title) {
- return {
- type: COMPOSE_POLL_OPTION_ADD,
- title,
- };
-};
-
-export function changePollOption(index, title) {
- return {
- type: COMPOSE_POLL_OPTION_CHANGE,
- index,
- title,
- };
-};
-
-export function removePollOption(index) {
- return {
- type: COMPOSE_POLL_OPTION_REMOVE,
- index,
- };
-};
+/**
+ *
+ */
+export const removePollOption = (index) => ({
+ type: COMPOSE_POLL_OPTION_REMOVE,
+ index,
+})
/**
*
diff --git a/app/javascript/gabsocial/actions/custom_emojis.js b/app/javascript/gabsocial/actions/custom_emojis.js
index 486e271e..7cc9256a 100644
--- a/app/javascript/gabsocial/actions/custom_emojis.js
+++ b/app/javascript/gabsocial/actions/custom_emojis.js
@@ -16,17 +16,14 @@ export const fetchCustomEmojis = () => (dispatch, getState) => {
const fetchCustomEmojisRequest = () => ({
type: CUSTOM_EMOJIS_FETCH_REQUEST,
- skipLoading: true,
})
const fetchCustomEmojisSuccess = (custom_emojis) => ({
type: CUSTOM_EMOJIS_FETCH_SUCCESS,
custom_emojis,
- skipLoading: true,
})
const fetchCustomEmojisFail = (error) => ({
type: CUSTOM_EMOJIS_FETCH_FAIL,
error,
- skipLoading: true,
})
diff --git a/app/javascript/gabsocial/actions/favorites.js b/app/javascript/gabsocial/actions/favorites.js
index a1648cbd..271967aa 100644
--- a/app/javascript/gabsocial/actions/favorites.js
+++ b/app/javascript/gabsocial/actions/favorites.js
@@ -33,20 +33,17 @@ export const fetchFavoritedStatuses = () => (dispatch, getState) => {
const fetchFavoritedStatusesRequest = () => ({
type: FAVORITED_STATUSES_FETCH_REQUEST,
- skipLoading: true,
})
const fetchFavoritedStatusesSuccess = (statuses, next) => ({
type: FAVORITED_STATUSES_FETCH_SUCCESS,
statuses,
next,
- skipLoading: true,
})
const fetchFavoritedStatusesFail = (error) => ({
type: FAVORITED_STATUSES_FETCH_FAIL,
error,
- skipLoading: true,
})
/**
diff --git a/app/javascript/gabsocial/actions/filters.js b/app/javascript/gabsocial/actions/filters.js
index 01559de0..bb831b3d 100644
--- a/app/javascript/gabsocial/actions/filters.js
+++ b/app/javascript/gabsocial/actions/filters.js
@@ -23,18 +23,15 @@ export const fetchFilters = () => (dispatch, getState) => {
const fetchFiltersRequest = () => ({
type: FILTERS_FETCH_REQUEST,
- skipLoading: true,
})
const fetchFiltersSuccess = (filters) => ({
type: FILTERS_FETCH_SUCCESS,
filters,
- skipLoading: true,
})
const fetchFiltersFail = (err) => ({
type: FILTERS_FETCH_FAIL,
err,
- skipLoading: true,
skipAlert: true,
})
\ No newline at end of file
diff --git a/app/javascript/gabsocial/actions/groups.js b/app/javascript/gabsocial/actions/groups.js
index 1f9d5590..b247daa8 100644
--- a/app/javascript/gabsocial/actions/groups.js
+++ b/app/javascript/gabsocial/actions/groups.js
@@ -2,58 +2,60 @@ import {
Map as ImmutableMap,
List as ImmutableList,
} from 'immutable'
-import api, { getLinks } from '../api';
-import { me } from '../initial_state';
-import { importFetchedAccounts } from './importer';
-import { fetchRelationships } from './accounts';
+import api, { getLinks } from '../api'
+import { me } from '../initial_state'
+import { importFetchedAccounts } from './importer'
+import { fetchRelationships } from './accounts'
+import { updateStatusStats } from './statuses'
import {
+ ACCEPTED_GROUP_TABS,
GROUP_LIST_SORTING_TYPE_ALPHABETICAL,
GROUP_LIST_SORTING_TYPE_MOST_POPULAR,
} from '../constants'
-export const GROUP_FETCH_REQUEST = 'GROUP_FETCH_REQUEST';
-export const GROUP_FETCH_SUCCESS = 'GROUP_FETCH_SUCCESS';
-export const GROUP_FETCH_FAIL = 'GROUP_FETCH_FAIL';
+export const GROUP_FETCH_REQUEST = 'GROUP_FETCH_REQUEST'
+export const GROUP_FETCH_SUCCESS = 'GROUP_FETCH_SUCCESS'
+export const GROUP_FETCH_FAIL = 'GROUP_FETCH_FAIL'
-export const GROUP_RELATIONSHIPS_FETCH_REQUEST = 'GROUP_RELATIONSHIPS_FETCH_REQUEST';
-export const GROUP_RELATIONSHIPS_FETCH_SUCCESS = 'GROUP_RELATIONSHIPS_FETCH_SUCCESS';
-export const GROUP_RELATIONSHIPS_FETCH_FAIL = 'GROUP_RELATIONSHIPS_FETCH_FAIL';
+export const GROUP_RELATIONSHIPS_FETCH_REQUEST = 'GROUP_RELATIONSHIPS_FETCH_REQUEST'
+export const GROUP_RELATIONSHIPS_FETCH_SUCCESS = 'GROUP_RELATIONSHIPS_FETCH_SUCCESS'
+export const GROUP_RELATIONSHIPS_FETCH_FAIL = 'GROUP_RELATIONSHIPS_FETCH_FAIL'
-export const GROUPS_FETCH_REQUEST = 'GROUPS_FETCH_REQUEST';
-export const GROUPS_FETCH_SUCCESS = 'GROUPS_FETCH_SUCCESS';
-export const GROUPS_FETCH_FAIL = 'GROUPS_FETCH_FAIL';
+export const GROUPS_FETCH_REQUEST = 'GROUPS_FETCH_REQUEST'
+export const GROUPS_FETCH_SUCCESS = 'GROUPS_FETCH_SUCCESS'
+export const GROUPS_FETCH_FAIL = 'GROUPS_FETCH_FAIL'
-export const GROUP_JOIN_REQUEST = 'GROUP_JOIN_REQUEST';
-export const GROUP_JOIN_SUCCESS = 'GROUP_JOIN_SUCCESS';
-export const GROUP_JOIN_FAIL = 'GROUP_JOIN_FAIL';
+export const GROUP_JOIN_REQUEST = 'GROUP_JOIN_REQUEST'
+export const GROUP_JOIN_SUCCESS = 'GROUP_JOIN_SUCCESS'
+export const GROUP_JOIN_FAIL = 'GROUP_JOIN_FAIL'
-export const GROUP_LEAVE_REQUEST = 'GROUP_LEAVE_REQUEST';
-export const GROUP_LEAVE_SUCCESS = 'GROUP_LEAVE_SUCCESS';
-export const GROUP_LEAVE_FAIL = 'GROUP_LEAVE_FAIL';
+export const GROUP_LEAVE_REQUEST = 'GROUP_LEAVE_REQUEST'
+export const GROUP_LEAVE_SUCCESS = 'GROUP_LEAVE_SUCCESS'
+export const GROUP_LEAVE_FAIL = 'GROUP_LEAVE_FAIL'
-export const GROUP_MEMBERS_FETCH_REQUEST = 'GROUP_MEMBERS_FETCH_REQUEST';
-export const GROUP_MEMBERS_FETCH_SUCCESS = 'GROUP_MEMBERS_FETCH_SUCCESS';
-export const GROUP_MEMBERS_FETCH_FAIL = 'GROUP_MEMBERS_FETCH_FAIL';
+export const GROUP_MEMBERS_FETCH_REQUEST = 'GROUP_MEMBERS_FETCH_REQUEST'
+export const GROUP_MEMBERS_FETCH_SUCCESS = 'GROUP_MEMBERS_FETCH_SUCCESS'
+export const GROUP_MEMBERS_FETCH_FAIL = 'GROUP_MEMBERS_FETCH_FAIL'
-export const GROUP_MEMBERS_EXPAND_REQUEST = 'GROUP_MEMBERS_EXPAND_REQUEST';
-export const GROUP_MEMBERS_EXPAND_SUCCESS = 'GROUP_MEMBERS_EXPAND_SUCCESS';
-export const GROUP_MEMBERS_EXPAND_FAIL = 'GROUP_MEMBERS_EXPAND_FAIL';
+export const GROUP_MEMBERS_EXPAND_REQUEST = 'GROUP_MEMBERS_EXPAND_REQUEST'
+export const GROUP_MEMBERS_EXPAND_SUCCESS = 'GROUP_MEMBERS_EXPAND_SUCCESS'
+export const GROUP_MEMBERS_EXPAND_FAIL = 'GROUP_MEMBERS_EXPAND_FAIL'
-export const GROUP_REMOVED_ACCOUNTS_FETCH_REQUEST = 'GROUP_REMOVED_ACCOUNTS_FETCH_REQUEST';
-export const GROUP_REMOVED_ACCOUNTS_FETCH_SUCCESS = 'GROUP_REMOVED_ACCOUNTS_FETCH_SUCCESS';
-export const GROUP_REMOVED_ACCOUNTS_FETCH_FAIL = 'GROUP_REMOVED_ACCOUNTS_FETCH_FAIL';
+export const GROUP_REMOVED_ACCOUNTS_FETCH_REQUEST = 'GROUP_REMOVED_ACCOUNTS_FETCH_REQUEST'
+export const GROUP_REMOVED_ACCOUNTS_FETCH_SUCCESS = 'GROUP_REMOVED_ACCOUNTS_FETCH_SUCCESS'
+export const GROUP_REMOVED_ACCOUNTS_FETCH_FAIL = 'GROUP_REMOVED_ACCOUNTS_FETCH_FAIL'
-export const GROUP_REMOVED_ACCOUNTS_EXPAND_REQUEST = 'GROUP_REMOVED_ACCOUNTS_EXPAND_REQUEST';
-export const GROUP_REMOVED_ACCOUNTS_EXPAND_SUCCESS = 'GROUP_REMOVED_ACCOUNTS_EXPAND_SUCCESS';
-export const GROUP_REMOVED_ACCOUNTS_EXPAND_FAIL = 'GROUP_REMOVED_ACCOUNTS_EXPAND_FAIL';
+export const GROUP_REMOVED_ACCOUNTS_EXPAND_REQUEST = 'GROUP_REMOVED_ACCOUNTS_EXPAND_REQUEST'
+export const GROUP_REMOVED_ACCOUNTS_EXPAND_SUCCESS = 'GROUP_REMOVED_ACCOUNTS_EXPAND_SUCCESS'
+export const GROUP_REMOVED_ACCOUNTS_EXPAND_FAIL = 'GROUP_REMOVED_ACCOUNTS_EXPAND_FAIL'
-export const GROUP_REMOVED_ACCOUNTS_REMOVE_REQUEST = 'GROUP_REMOVED_ACCOUNTS_REMOVE_REQUEST';
-export const GROUP_REMOVED_ACCOUNTS_REMOVE_SUCCESS = 'GROUP_REMOVED_ACCOUNTS_REMOVE_SUCCESS';
-export const GROUP_REMOVED_ACCOUNTS_REMOVE_FAIL = 'GROUP_REMOVED_ACCOUNTS_REMOVE_FAIL';
+export const GROUP_REMOVED_ACCOUNTS_REMOVE_REQUEST = 'GROUP_REMOVED_ACCOUNTS_REMOVE_REQUEST'
+export const GROUP_REMOVED_ACCOUNTS_REMOVE_SUCCESS = 'GROUP_REMOVED_ACCOUNTS_REMOVE_SUCCESS'
+export const GROUP_REMOVED_ACCOUNTS_REMOVE_FAIL = 'GROUP_REMOVED_ACCOUNTS_REMOVE_FAIL'
-export const GROUP_REMOVED_ACCOUNTS_CREATE_REQUEST = 'GROUP_REMOVED_ACCOUNTS_CREATE_REQUEST';
-export const GROUP_REMOVED_ACCOUNTS_CREATE_SUCCESS = 'GROUP_REMOVED_ACCOUNTS_CREATE_SUCCESS';
-export const GROUP_REMOVED_ACCOUNTS_CREATE_FAIL = 'GROUP_REMOVED_ACCOUNTS_CREATE_FAIL';
+export const GROUP_REMOVED_ACCOUNTS_CREATE_REQUEST = 'GROUP_REMOVED_ACCOUNTS_CREATE_REQUEST'
+export const GROUP_REMOVED_ACCOUNTS_CREATE_SUCCESS = 'GROUP_REMOVED_ACCOUNTS_CREATE_SUCCESS'
+export const GROUP_REMOVED_ACCOUNTS_CREATE_FAIL = 'GROUP_REMOVED_ACCOUNTS_CREATE_FAIL'
export const GROUP_JOIN_REQUESTS_FETCH_REQUEST = 'GROUP_JOIN_REQUESTS_FETCH_REQUEST'
export const GROUP_JOIN_REQUESTS_FETCH_SUCCESS = 'GROUP_JOIN_REQUESTS_FETCH_SUCCESS'
@@ -69,18 +71,18 @@ export const GROUP_JOIN_REQUESTS_APPROVE_FAIL = 'GROUP_JOIN_REQUESTS_APPROVE_FAI
export const GROUP_JOIN_REQUESTS_REJECT_SUCCESS = 'GROUP_JOIN_REQUESTS_REJECT_SUCCESS'
export const GROUP_JOIN_REQUESTS_REJECT_FAIL = 'GROUP_JOIN_REQUESTS_REJECT_FAIL'
-export const GROUP_REMOVE_STATUS_REQUEST = 'GROUP_REMOVE_STATUS_REQUEST';
-export const GROUP_REMOVE_STATUS_SUCCESS = 'GROUP_REMOVE_STATUS_SUCCESS';
-export const GROUP_REMOVE_STATUS_FAIL = 'GROUP_REMOVE_STATUS_FAIL';
+export const GROUP_REMOVE_STATUS_REQUEST = 'GROUP_REMOVE_STATUS_REQUEST'
+export const GROUP_REMOVE_STATUS_SUCCESS = 'GROUP_REMOVE_STATUS_SUCCESS'
+export const GROUP_REMOVE_STATUS_FAIL = 'GROUP_REMOVE_STATUS_FAIL'
-export const GROUP_UPDATE_ROLE_REQUEST = 'GROUP_UPDATE_ROLE_REQUEST';
-export const GROUP_UPDATE_ROLE_SUCCESS = 'GROUP_UPDATE_ROLE_SUCCESS';
-export const GROUP_UPDATE_ROLE_FAIL = 'GROUP_UPDATE_ROLE_FAIL';
+export const GROUP_UPDATE_ROLE_REQUEST = 'GROUP_UPDATE_ROLE_REQUEST'
+export const GROUP_UPDATE_ROLE_SUCCESS = 'GROUP_UPDATE_ROLE_SUCCESS'
+export const GROUP_UPDATE_ROLE_FAIL = 'GROUP_UPDATE_ROLE_FAIL'
-export const GROUP_CHECK_PASSWORD_RESET = 'GROUP_CHECK_PASSWORD_RESET';
-export const GROUP_CHECK_PASSWORD_REQUEST = 'GROUP_CHECK_PASSWORD_REQUEST';
-export const GROUP_CHECK_PASSWORD_SUCCESS = 'GROUP_CHECK_PASSWORD_SUCCESS';
-export const GROUP_CHECK_PASSWORD_FAIL = 'GROUP_CHECK_PASSWORD_FAIL';
+export const GROUP_CHECK_PASSWORD_RESET = 'GROUP_CHECK_PASSWORD_RESET'
+export const GROUP_CHECK_PASSWORD_REQUEST = 'GROUP_CHECK_PASSWORD_REQUEST'
+export const GROUP_CHECK_PASSWORD_SUCCESS = 'GROUP_CHECK_PASSWORD_SUCCESS'
+export const GROUP_CHECK_PASSWORD_FAIL = 'GROUP_CHECK_PASSWORD_FAIL'
export const GROUP_PIN_STATUS_REQUEST = 'GROUP_PIN_STATUS_REQUEST'
export const GROUP_PIN_STATUS_SUCCESS = 'GROUP_PIN_STATUS_SUCCESS'
@@ -90,6 +92,10 @@ export const GROUP_UNPIN_STATUS_REQUEST = 'GROUP_UNPIN_STATUS_REQUEST'
export const GROUP_UNPIN_STATUS_SUCCESS = 'GROUP_UNPIN_STATUS_SUCCESS'
export const GROUP_UNPIN_STATUS_FAIL = 'GROUP_UNPIN_STATUS_FAIL'
+export const IS_PINNED_GROUP_STATUS_REQUEST = 'IS_PINNED_GROUP_STATUS_REQUEST'
+export const IS_PINNED_GROUP_STATUS_SUCCESS = 'IS_PINNED_GROUP_STATUS_SUCCESS'
+export const IS_PINNED_GROUP_STATUS_FAIL = 'IS_PINNED_GROUP_STATUS_FAIL'
+
export const GROUPS_BY_CATEGORY_FETCH_REQUEST = 'GROUPS_BY_CATEGORY_FETCH_REQUEST'
export const GROUPS_BY_CATEGORY_FETCH_SUCCESS = 'GROUPS_BY_CATEGORY_FETCH_SUCCESS'
export const GROUPS_BY_CATEGORY_FETCH_FAIL = 'GROUPS_BY_CATEGORY_FETCH_FAIL'
@@ -103,6 +109,10 @@ export const GROUP_TIMELINE_TOP_SORT = 'GROUP_TIMELINE_TOP_SORT'
export const GROUP_SORT = 'GROUP_SORT'
+/**
+ * @description Import a group into redux
+ * @param {ImmutableMap} group
+ */
export const importGroup = (group) => (dispatch) => {
dispatch(fetchGroupSuccess(group))
}
@@ -112,83 +122,85 @@ export const importGroups = (groups) => (dispatch) => {
groups.map((group) => dispatch(fetchGroupSuccess(group)))
}
-export const fetchGroup = (id) => (dispatch, getState) => {
- dispatch(fetchGroupRelationships([id]));
+/**
+ * @description Fetch a group with the given groupId
+ * @param {string} groupId
+ */
+export const fetchGroup = (groupId) => (dispatch, getState) => {
+ if (!groupId) return
- if (getState().getIn(['groups', id])) {
- return;
- }
+ dispatch(fetchGroupRelationships([groupId]))
- dispatch(fetchGroupRequest(id));
+ // Check if exists already
+ if (getState().getIn(['groups', groupId])) return
- api(getState).get(`/api/v1/groups/${id}`)
- .then(({ data }) => dispatch(fetchGroupSuccess(data)))
- .catch(err => dispatch(fetchGroupFail(id, err)));
-};
+ dispatch(fetchGroupRequest(groupId))
-export const fetchGroupRequest = id => ({
+ api(getState).get(`/api/v1/groups/${groupId}`)
+ .then((response) => dispatch(fetchGroupSuccess(response.data)))
+ .catch((err) => dispatch(fetchGroupFail(groupId, err)))
+}
+
+const fetchGroupRequest = (groupId) => ({
type: GROUP_FETCH_REQUEST,
- id,
-});
+ groupId,
+})
-export const fetchGroupSuccess = group => ({
+const fetchGroupSuccess = (group) => ({
type: GROUP_FETCH_SUCCESS,
group,
-});
+})
-export const fetchGroupFail = (id, error) => ({
+const fetchGroupFail = (groupId, error) => ({
type: GROUP_FETCH_FAIL,
- id,
+ groupId,
error,
-});
+})
-export function fetchGroupRelationships(groupIds) {
- return (dispatch, getState) => {
- if (!me) return;
+/**
+ * @description Fetch relationships for the given groupIds and current user. For example
+ * if the current user is a member, admin, mod or not.
+ * @param {Array} groupIds
+ */
+export const fetchGroupRelationships = (groupIds) => (dispatch, getState) => {
+ if (!me || !Array.isArray(groupIds)) return
- const loadedRelationships = getState().get('group_relationships');
- const newGroupIds = groupIds.filter(id => loadedRelationships.get(id, null) === null);
+ const loadedRelationships = getState().get('group_relationships')
+ const newGroupIds = groupIds.filter((id) => loadedRelationships.get(id, null) === null)
- if (newGroupIds.length === 0) {
- return;
- }
+ if (newGroupIds.length === 0) return
- dispatch(fetchGroupRelationshipsRequest(newGroupIds));
+ dispatch(fetchGroupRelationshipsRequest(newGroupIds))
- api(getState).get(`/api/v1/groups/${newGroupIds[0]}/relationships?${newGroupIds.map(id => `id[]=${id}`).join('&')}`).then(response => {
- dispatch(fetchGroupRelationshipsSuccess(response.data));
- }).catch(error => {
- dispatch(fetchGroupRelationshipsFail(error));
- });
- };
-};
+ api(getState).get(`/api/v1/groups/${newGroupIds[0]}/relationships?${newGroupIds.map(id => `id[]=${id}`).join('&')}`).then((response) => {
+ dispatch(fetchGroupRelationshipsSuccess(response.data))
+ }).catch((error) => {
+ dispatch(fetchGroupRelationshipsFail(error))
+ })
+}
-export function fetchGroupRelationshipsRequest(ids) {
- return {
- type: GROUP_RELATIONSHIPS_FETCH_REQUEST,
- ids,
- skipLoading: true,
- };
-};
+const fetchGroupRelationshipsRequest = (groupIds) => ({
+ type: GROUP_RELATIONSHIPS_FETCH_REQUEST,
+ groupIds,
+})
-export function fetchGroupRelationshipsSuccess(relationships) {
- return {
- type: GROUP_RELATIONSHIPS_FETCH_SUCCESS,
- relationships,
- skipLoading: true,
- };
-};
+const fetchGroupRelationshipsSuccess = (relationships) => ({
+ type: GROUP_RELATIONSHIPS_FETCH_SUCCESS,
+ relationships,
+})
-export function fetchGroupRelationshipsFail(error) {
- return {
- type: GROUP_RELATIONSHIPS_FETCH_FAIL,
- error,
- skipLoading: true,
- };
-};
+const fetchGroupRelationshipsFail = (error) => ({
+ type: GROUP_RELATIONSHIPS_FETCH_FAIL,
+ error,
+})
-export const fetchGroups = (tab) => (dispatch, getState) => {
- if (!me && tab !== 'featured') return
+/**
+ * @description Fetch all groups (limited uniquely per tab, non paginated) by tab. Import
+ * groups and fetch relationships for each if tab !== member.
+ * @param {String} tab
+ */
+export const fetchGroupsByTab = (tab) => (dispatch, getState) => {
+ if (!me && tab !== 'featured' || ACCEPTED_GROUP_TABS.indexOf(tab) === -1) return
// Don't refetch or fetch when loading
const isLoading = getState().getIn(['group_lists', tab, 'isLoading'])
@@ -198,32 +210,41 @@ export const fetchGroups = (tab) => (dispatch, getState) => {
dispatch(fetchGroupsRequest(tab))
- api(getState).get('/api/v1/groups?tab=' + tab)
- .then(({ data }) => {
- dispatch(fetchGroupsSuccess(data, tab))
- dispatch(fetchGroupRelationships(data.map(item => item.id)))
+ api(getState).get(`/api/v1/groups?tab=${tab}`)
+ .then((response) => {
+ dispatch(fetchGroupsSuccess(response.data, tab))
+ if (tab !== 'member') {
+ dispatch(fetchGroupRelationships(response.data.map(item => item.id)))
+ }
})
.catch((err) => dispatch(fetchGroupsFail(err, tab)))
}
-export const fetchGroupsRequest = (tab) => ({
+const fetchGroupsRequest = (tab) => ({
type: GROUPS_FETCH_REQUEST,
tab,
-});
+})
export const fetchGroupsSuccess = (groups, tab) => ({
type: GROUPS_FETCH_SUCCESS,
groups,
tab,
-});
+})
-export const fetchGroupsFail = (error, tab) => ({
+const fetchGroupsFail = (error, tab) => ({
type: GROUPS_FETCH_FAIL,
error,
tab,
-});
+})
+/**
+ * @description Fetch all groups (limited to 100, non paginated) by category. Import groups
+ * and fetch relationships for each.
+ * @param {String} category
+ */
export const fetchGroupsByCategory = (category) => (dispatch, getState) => {
+ if (!category) return
+
// Don't refetch or fetch when loading
const isLoading = getState().getIn(['group_lists', 'by_category', category, 'isLoading'], false)
@@ -232,31 +253,38 @@ export const fetchGroupsByCategory = (category) => (dispatch, getState) => {
dispatch(fetchGroupsByCategoryRequest(category))
api(getState).get(`/api/v1/groups/_/category/${category}`)
- .then(({ data }) => {
- dispatch(fetchGroupsByCategorySuccess(data, category))
- dispatch(fetchGroupRelationships(data.map(item => item.id)))
+ .then((response) => {
+ dispatch(fetchGroupsByCategorySuccess(response.data, category))
+ dispatch(fetchGroupRelationships(response.data.map(item => item.id)))
})
.catch((err) => dispatch(fetchGroupsByCategoryFail(err, category)))
}
-export const fetchGroupsByCategoryRequest = (category) => ({
+const fetchGroupsByCategoryRequest = (category) => ({
type: GROUPS_BY_CATEGORY_FETCH_REQUEST,
category,
})
-export const fetchGroupsByCategorySuccess = (groups, category) => ({
+const fetchGroupsByCategorySuccess = (groups, category) => ({
type: GROUPS_BY_CATEGORY_FETCH_SUCCESS,
groups,
category,
})
-export const fetchGroupsByCategoryFail = (error, category) => ({
+const fetchGroupsByCategoryFail = (error, category) => ({
type: GROUPS_BY_CATEGORY_FETCH_FAIL,
error,
category,
})
+/**
+ * @description Fetch all groups (limited to 100, non paginated) by tag. Import groups
+ * and fetch relationships for each.
+ * @param {String} tag
+ */
export const fetchGroupsByTag = (tag) => (dispatch, getState) => {
+ if (!tag) return
+
// Don't refetch or fetch when loading
const isLoading = getState().getIn(['group_lists', 'by_tag', tag, 'isLoading'], false)
@@ -265,9 +293,9 @@ export const fetchGroupsByTag = (tag) => (dispatch, getState) => {
dispatch(fetchGroupsByTagRequest(tag))
api(getState).get(`/api/v1/groups/_/tag/${tag}`)
- .then(({ data }) => {
- dispatch(fetchGroupsByTagSuccess(data, tag))
- dispatch(fetchGroupRelationships(data.map(item => item.id)))
+ .then((response) => {
+ dispatch(fetchGroupsByTagSuccess(response.data, tag))
+ dispatch(fetchGroupRelationships(response.data.map(item => item.id)))
})
.catch((err) => dispatch(fetchGroupsByTagFail(err, tag)))
}
@@ -289,539 +317,498 @@ export const fetchGroupsByTagFail = (error, tag) => ({
tag,
})
-export function joinGroup(id) {
- return (dispatch, getState) => {
- if (!me) return;
-
- dispatch(joinGroupRequest(id));
-
- api(getState).post(`/api/v1/groups/${id}/accounts`).then(response => {
- dispatch(joinGroupSuccess(response.data));
- }).catch(error => {
- dispatch(joinGroupFail(id, error));
- });
- };
-};
-
-export function leaveGroup(id) {
- return (dispatch, getState) => {
- if (!me) return;
-
- dispatch(leaveGroupRequest(id));
-
- api(getState).delete(`/api/v1/groups/${id}/accounts`).then(response => {
- dispatch(leaveGroupSuccess(response.data));
- }).catch(error => {
- dispatch(leaveGroupFail(id, error));
- });
- };
-};
-
-export function joinGroupRequest(id) {
- return {
- type: GROUP_JOIN_REQUEST,
- id,
- };
-};
-
-export function joinGroupSuccess(relationship) {
- return {
- type: GROUP_JOIN_SUCCESS,
- relationship
- };
-};
-
-export function joinGroupFail(error) {
- return {
- type: GROUP_JOIN_FAIL,
- error,
- };
-};
-
-export function leaveGroupRequest(id) {
- return {
- type: GROUP_LEAVE_REQUEST,
- id,
- };
-};
-
-export function leaveGroupSuccess(relationship) {
- return {
- type: GROUP_LEAVE_SUCCESS,
- relationship,
- };
-};
-
-export function leaveGroupFail(error) {
- return {
- type: GROUP_LEAVE_FAIL,
- error,
- };
-};
-
-export function fetchMembers(id) {
- return (dispatch, getState) => {
- if (!me) return;
-
- dispatch(fetchMembersRequest(id));
-
- api(getState).get(`/api/v1/groups/${id}/accounts`).then(response => {
- const next = getLinks(response).refs.find(link => link.rel === 'next');
-
- dispatch(importFetchedAccounts(response.data));
- dispatch(fetchMembersSuccess(id, response.data, next ? next.uri : null));
- dispatch(fetchRelationships(response.data.map(item => item.id)));
- }).catch(error => {
- dispatch(fetchMembersFail(id, error));
- });
- };
-};
-
-export function fetchMembersRequest(id) {
- return {
- type: GROUP_MEMBERS_FETCH_REQUEST,
- id,
- };
-};
-
-export function fetchMembersSuccess(id, accounts, next) {
- return {
- type: GROUP_MEMBERS_FETCH_SUCCESS,
- id,
- accounts,
- next,
- };
-};
-
-export function fetchMembersFail(id, error) {
- return {
- type: GROUP_MEMBERS_FETCH_FAIL,
- id,
- error,
- };
-};
-
-export function expandMembers(id) {
- return (dispatch, getState) => {
- if (!me) return;
-
- const url = getState().getIn(['user_lists', 'groups', id, 'next'])
- const isLoading = getState().getIn(['user_lists', 'groups', id, 'isLoading'])
-
- if (url === null || isLoading) return
-
- dispatch(expandMembersRequest(id));
-
- api(getState).get(url).then(response => {
- const next = getLinks(response).refs.find(link => link.rel === 'next');
-
- dispatch(importFetchedAccounts(response.data));
- dispatch(expandMembersSuccess(id, response.data, next ? next.uri : null));
- dispatch(fetchRelationships(response.data.map(item => item.id)));
- }).catch(error => {
- dispatch(expandMembersFail(id, error));
- });
- };
-};
-
-export function expandMembersRequest(id) {
- return {
- type: GROUP_MEMBERS_EXPAND_REQUEST,
- id,
- };
-};
-
-export function expandMembersSuccess(id, accounts, next) {
- return {
- type: GROUP_MEMBERS_EXPAND_SUCCESS,
- id,
- accounts,
- next,
- };
-};
-
-export function expandMembersFail(id, error) {
- return {
- type: GROUP_MEMBERS_EXPAND_FAIL,
- id,
- error,
- };
-};
-
-export function fetchRemovedAccounts(id) {
- return (dispatch, getState) => {
- if (!me) return;
-
- dispatch(fetchRemovedAccountsRequest(id));
-
- api(getState).get(`/api/v1/groups/${id}/removed_accounts`).then(response => {
- const next = getLinks(response).refs.find(link => link.rel === 'next');
-
- dispatch(importFetchedAccounts(response.data));
- dispatch(fetchRemovedAccountsSuccess(id, response.data, next ? next.uri : null));
- dispatch(fetchRelationships(response.data.map(item => item.id)));
- }).catch(error => {
- dispatch(fetchRemovedAccountsFail(id, error));
- });
- };
-};
-
-export function fetchRemovedAccountsRequest(id) {
- return {
- type: GROUP_REMOVED_ACCOUNTS_FETCH_REQUEST,
- id,
- };
-};
-
-export function fetchRemovedAccountsSuccess(id, accounts, next) {
- return {
- type: GROUP_REMOVED_ACCOUNTS_FETCH_SUCCESS,
- id,
- accounts,
- next,
- };
-};
-
-export function fetchRemovedAccountsFail(id, error) {
- return {
- type: GROUP_REMOVED_ACCOUNTS_FETCH_FAIL,
- id,
- error,
- };
-};
-
-export function expandRemovedAccounts(id) {
- return (dispatch, getState) => {
- if (!me) return;
-
- const url = getState().getIn(['user_lists', 'group_removed_accounts', id, 'next']);
- const isLoading = getState().getIn(['user_lists', 'group_removed_accounts', id, 'isLoading'])
-
- if (url === null || isLoading) return
-
- dispatch(expandRemovedAccountsRequest(id));
-
- api(getState).get(url).then(response => {
- const next = getLinks(response).refs.find(link => link.rel === 'next');
-
- dispatch(importFetchedAccounts(response.data));
- dispatch(expandRemovedAccountsSuccess(id, response.data, next ? next.uri : null));
- dispatch(fetchRelationships(response.data.map(item => item.id)));
- }).catch(error => {
- dispatch(expandRemovedAccountsFail(id, error));
- });
- };
-};
-
-export function expandRemovedAccountsRequest(id) {
- return {
- type: GROUP_REMOVED_ACCOUNTS_EXPAND_REQUEST,
- id,
- };
-};
-
-export function expandRemovedAccountsSuccess(id, accounts, next) {
- return {
- type: GROUP_REMOVED_ACCOUNTS_EXPAND_SUCCESS,
- id,
- accounts,
- next,
- };
-};
-
-export function expandRemovedAccountsFail(id, error) {
- return {
- type: GROUP_REMOVED_ACCOUNTS_EXPAND_FAIL,
- id,
- error,
- };
-};
-
-export function removeRemovedAccount(groupId, id) {
- return (dispatch, getState) => {
- if (!me) return;
-
- dispatch(removeRemovedAccountRequest(groupId, id));
-
- api(getState).delete(`/api/v1/groups/${groupId}/removed_accounts?account_id=${id}`).then(response => {
- dispatch(removeRemovedAccountSuccess(groupId, id));
- }).catch(error => {
- dispatch(removeRemovedAccountFail(groupId, id, error));
- });
- };
-};
-
-export function removeRemovedAccountRequest(groupId, id) {
- return {
- type: GROUP_REMOVED_ACCOUNTS_REMOVE_REQUEST,
- groupId,
- id,
- };
-};
-
-export function removeRemovedAccountSuccess(groupId, id) {
- return {
- type: GROUP_REMOVED_ACCOUNTS_REMOVE_SUCCESS,
- groupId,
- id,
- };
-};
-
-export function removeRemovedAccountFail(groupId, id, error) {
- return {
- type: GROUP_REMOVED_ACCOUNTS_REMOVE_FAIL,
- groupId,
- id,
- error,
- };
-};
-
-export function createRemovedAccount(groupId, id) {
- return (dispatch, getState) => {
- if (!me) return;
-
- dispatch(createRemovedAccountRequest(groupId, id));
-
- api(getState).post(`/api/v1/groups/${groupId}/removed_accounts?account_id=${id}`).then(response => {
- dispatch(createRemovedAccountSuccess(groupId, id));
- }).catch(error => {
- dispatch(createRemovedAccountFail(groupId, id, error));
- });
- };
-};
-
-export function createRemovedAccountRequest(groupId, id) {
- return {
- type: GROUP_REMOVED_ACCOUNTS_CREATE_REQUEST,
- groupId,
- id,
- };
-};
-
-export function createRemovedAccountSuccess(groupId, id) {
- return {
- type: GROUP_REMOVED_ACCOUNTS_CREATE_SUCCESS,
- groupId,
- id,
- };
-};
-
-export function createRemovedAccountFail(groupId, id, error) {
- return {
- type: GROUP_REMOVED_ACCOUNTS_CREATE_FAIL,
- groupId,
- id,
- error,
- };
-};
-
-export function groupRemoveStatus(groupId, id) {
- return (dispatch, getState) => {
- if (!me) return;
-
- dispatch(groupRemoveStatusRequest(groupId, id));
-
- api(getState).delete(`/api/v1/groups/${groupId}/statuses/${id}`).then(response => {
- dispatch(groupRemoveStatusSuccess(groupId, id));
- }).catch(error => {
- dispatch(groupRemoveStatusFail(groupId, id, error));
- });
- };
-};
-
-export function groupRemoveStatusRequest(groupId, id) {
- return {
- type: GROUP_REMOVE_STATUS_REQUEST,
- groupId,
- id,
- };
-};
-
-export function groupRemoveStatusSuccess(groupId, id) {
- return {
- type: GROUP_REMOVE_STATUS_SUCCESS,
- groupId,
- id,
- };
-};
-
-export function groupRemoveStatusFail(groupId, id, error) {
- return {
- type: GROUP_REMOVE_STATUS_FAIL,
- groupId,
- id,
- error,
- };
-};
-
-export function updateRole(groupId, id, role) {
- return (dispatch, getState) => {
- if (!me) return;
-
- dispatch(updateRoleRequest(groupId, id));
-
- api(getState).patch(`/api/v1/groups/${groupId}/accounts?account_id=${id}`, { role }).then(response => {
- dispatch(updateRoleSuccess(groupId, id));
- }).catch(error => {
- dispatch(updateRoleFail(groupId, id, error));
- });
- };
-};
-
-export function updateRoleRequest(groupId, id) {
- return {
- type: GROUP_REMOVED_ACCOUNTS_CREATE_REQUEST,
- groupId,
- id,
- };
-};
-
-export function updateRoleSuccess(groupId, id) {
- return {
- type: GROUP_REMOVED_ACCOUNTS_CREATE_SUCCESS,
- groupId,
- id,
- };
-};
-
-export function updateRoleFail(groupId, id, error) {
- return {
- type: GROUP_REMOVED_ACCOUNTS_CREATE_FAIL,
- groupId,
- id,
- error,
- };
-};
-
-export function checkGroupPassword(groupId, password) {
- return (dispatch, getState) => {
- if (!me) return
-
- dispatch(checkGroupPasswordRequest())
-
- api(getState).post(`/api/v1/groups/${groupId}/password`, { password }).then((response) => {
- dispatch(joinGroupSuccess(response.data))
- dispatch(checkGroupPasswordSuccess())
- }).catch(error => {
- dispatch(checkGroupPasswordFail(error))
- })
- }
+/**
+ * @description Join group with the given groupId and return group relationships
+ * @param {String} groupId
+ */
+export const joinGroup = (groupId) => (dispatch, getState) => {
+ if (!me || !groupId) return
+
+ dispatch(joinGroupRequest(groupId))
+
+ api(getState).post(`/api/v1/groups/${groupId}/accounts`).then((response) => {
+ dispatch(joinGroupSuccess(response.data))
+ }).catch((error) => {
+ dispatch(joinGroupFail(groupId, error))
+ })
}
-export function checkGroupPasswordReset() {
- return {
- type: GROUP_CHECK_PASSWORD_RESET,
- }
+const joinGroupRequest = (groupId) => ({
+ type: GROUP_JOIN_REQUEST,
+ groupId,
+})
+
+const joinGroupSuccess = (relationship) => ({
+ type: GROUP_JOIN_SUCCESS,
+ relationship
+})
+
+const joinGroupFail = (error) => ({
+ type: GROUP_JOIN_FAIL,
+ error,
+})
+
+/**
+ * @description Leave group with the given groupId and return group relationships
+ * @param {String} groupId
+ */
+export const leaveGroup = (groupId) => (dispatch, getState) => {
+ if (!me || !groupId) return
+
+ dispatch(leaveGroupRequest(groupId))
+
+ api(getState).delete(`/api/v1/groups/${groupId}/accounts`).then((response) => {
+ dispatch(leaveGroupSuccess(response.data))
+ }).catch((error) => {
+ dispatch(leaveGroupFail(groupId, error))
+ })
}
-export function checkGroupPasswordRequest() {
- return {
- type: GROUP_CHECK_PASSWORD_REQUEST,
- }
+const leaveGroupRequest = (groupId) => ({
+ type: GROUP_LEAVE_REQUEST,
+ groupId,
+})
+
+const leaveGroupSuccess = (relationship) => ({
+ type: GROUP_LEAVE_SUCCESS,
+ relationship,
+})
+
+const leaveGroupFail = (error) => ({
+ type: GROUP_LEAVE_FAIL,
+ error,
+})
+
+/**
+ * @description Fetch members for the given groupId and imports paginated accounts
+ * and sets in user_lists reducer.
+ * @param {String} groupId
+ */
+export const fetchMembers = (groupId) => (dispatch, getState) => {
+ if (!me || !groupId) return
+
+ dispatch(fetchMembersRequest(groupId))
+
+ api(getState).get(`/api/v1/groups/${groupId}/accounts`).then((response) => {
+ const next = getLinks(response).refs.find(link => link.rel === 'next')
+
+ dispatch(importFetchedAccounts(response.data))
+ dispatch(fetchMembersSuccess(groupId, response.data, next ? next.uri : null))
+ dispatch(fetchRelationships(response.data.map(item => item.id)))
+ }).catch((error) => {
+ dispatch(fetchMembersFail(groupId, error))
+ })
}
-export function checkGroupPasswordSuccess() {
- return {
- type: GROUP_CHECK_PASSWORD_SUCCESS,
- }
+const fetchMembersRequest = (groupId) => ({
+ type: GROUP_MEMBERS_FETCH_REQUEST,
+ groupId,
+})
+
+const fetchMembersSuccess = (groupId, accounts, next) => ({
+ type: GROUP_MEMBERS_FETCH_SUCCESS,
+ groupId,
+ accounts,
+ next,
+})
+
+const fetchMembersFail = (groupId, error) => ({
+ type: GROUP_MEMBERS_FETCH_FAIL,
+ groupId,
+ error,
+})
+
+/**
+ * @description Expand members for the given groupId and imports paginated accounts
+ * and sets in user_lists reducer.
+ * @param {String} groupId
+ */
+export const expandMembers = (groupId) => (dispatch, getState) => {
+ if (!me || !groupId) return
+
+ const url = getState().getIn(['user_lists', 'groups', groupId, 'next'])
+ const isLoading = getState().getIn(['user_lists', 'groups', groupId, 'isLoading'])
+
+ if (url === null || isLoading) return
+
+ dispatch(expandMembersRequest(groupId))
+
+ api(getState).get(url).then((response) => {
+ const next = getLinks(response).refs.find(link => link.rel === 'next')
+
+ dispatch(importFetchedAccounts(response.data))
+ dispatch(expandMembersSuccess(groupId, response.data, next ? next.uri : null))
+ dispatch(fetchRelationships(response.data.map(item => item.id)))
+ }).catch((error) => {
+ dispatch(expandMembersFail(groupId, error))
+ })
}
-export function checkGroupPasswordFail(error) {
- return {
- type: GROUP_CHECK_PASSWORD_FAIL,
- error,
- }
+const expandMembersRequest = (groupId) => ({
+ type: GROUP_MEMBERS_EXPAND_REQUEST,
+ groupId,
+})
+``
+const expandMembersSuccess = (groupId, accounts, next) => ({
+ type: GROUP_MEMBERS_EXPAND_SUCCESS,
+ groupId,
+ accounts,
+ next,
+})
+
+const expandMembersFail = (groupId, error) => ({
+ type: GROUP_MEMBERS_EXPAND_FAIL,
+ groupId,
+ error,
+})
+
+/**
+ * @description Fetch removed accounts for the given groupId and imports paginated
+ * accounts and sets in user_lists reducer.
+ * @param {String} groupId
+ */
+export const fetchRemovedAccounts = (groupId) => (dispatch, getState) => {
+ if (!me || !groupId) return
+
+ dispatch(fetchRemovedAccountsRequest(groupId))
+
+ api(getState).get(`/api/v1/groups/${groupId}/removed_accounts`).then((response) => {
+ const next = getLinks(response).refs.find(link => link.rel === 'next')
+
+ dispatch(importFetchedAccounts(response.data))
+ dispatch(fetchRemovedAccountsSuccess(groupId, response.data, next ? next.uri : null))
+ dispatch(fetchRelationships(response.data.map(item => item.id)))
+ }).catch((error) => {
+ dispatch(fetchRemovedAccountsFail(groupId, error))
+ })
}
-export function fetchJoinRequests(id) {
- return (dispatch, getState) => {
- if (!me) return
+const fetchRemovedAccountsRequest = (groupId) => ({
+ type: GROUP_REMOVED_ACCOUNTS_FETCH_REQUEST,
+ groupId,
+})
- dispatch(fetchJoinRequestsRequest(id))
+const fetchRemovedAccountsSuccess = (groupId, accounts, next) => ({
+ type: GROUP_REMOVED_ACCOUNTS_FETCH_SUCCESS,
+ groupId,
+ accounts,
+ next,
+})
- api(getState).get(`/api/v1/groups/${id}/join_requests`).then((response) => {
- const next = getLinks(response).refs.find(link => link.rel === 'next')
+const fetchRemovedAccountsFail = (groupId, error) => ({
+ type: GROUP_REMOVED_ACCOUNTS_FETCH_FAIL,
+ groupId,
+ error,
+})
- dispatch(importFetchedAccounts(response.data))
- dispatch(fetchJoinRequestsSuccess(id, response.data, next ? next.uri : null))
- dispatch(fetchRelationships(response.data.map(item => item.id)))
- }).catch((error) => {
- dispatch(fetchJoinRequestsFail(id, error))
- })
- }
+/**
+ * @description Expand likes for the given statusId and imports paginated accounts
+ * and sets in user_lists reducer.
+ * @param {String} statusId
+ */
+export const expandRemovedAccounts = (groupId) => (dispatch, getState) => {
+ if (!me || !groupId) return
+
+ const url = getState().getIn(['user_lists', 'group_removed_accounts', groupId, 'next'])
+ const isLoading = getState().getIn(['user_lists', 'group_removed_accounts', groupId, 'isLoading'])
+
+ if (url === null || isLoading) return
+
+ dispatch(expandRemovedAccountsRequest(groupId))
+
+ api(getState).get(url).then((response) => {
+ const next = getLinks(response).refs.find(link => link.rel === 'next')
+
+ dispatch(importFetchedAccounts(response.data))
+ dispatch(expandRemovedAccountsSuccess(groupId, response.data, next ? next.uri : null))
+ dispatch(fetchRelationships(response.data.map(item => item.id)))
+ }).catch((error) => {
+ dispatch(expandRemovedAccountsFail(groupId, error))
+ })
}
-export function fetchJoinRequestsRequest(id) {
- return {
- type: GROUP_JOIN_REQUESTS_FETCH_REQUEST,
- id,
- }
+const expandRemovedAccountsRequest = (groupId) => ({
+ type: GROUP_REMOVED_ACCOUNTS_EXPAND_REQUEST,
+ groupId,
+})
+
+const expandRemovedAccountsSuccess = (groupId, accounts, next) => ({
+ type: GROUP_REMOVED_ACCOUNTS_EXPAND_SUCCESS,
+ groupId,
+ accounts,
+ next,
+})
+
+const expandRemovedAccountsFail = (groupId, error) => ({
+ type: GROUP_REMOVED_ACCOUNTS_EXPAND_FAIL,
+ groupId,
+ error,
+})
+
+/**
+ * @description Remove a "removed account" from a group with the given groupId and accountId.
+ * @param {String} groupId
+ * @param {String} accountId
+ */
+export const removeRemovedAccount = (groupId, accountId) => (dispatch, getState) => {
+ if (!me || !groupId || !accountId) return
+
+ dispatch(removeRemovedAccountRequest(groupId, accountId))
+
+ api(getState).delete(`/api/v1/groups/${groupId}/removed_accounts?account_id=${accountId}`).then((response) => {
+ dispatch(removeRemovedAccountSuccess(groupId, accountId))
+ }).catch((error) => {
+ dispatch(removeRemovedAccountFail(groupId, accountId, error))
+ })
}
-export function fetchJoinRequestsSuccess(id, accounts, next) {
- return {
- type: GROUP_JOIN_REQUESTS_FETCH_SUCCESS,
- id,
- accounts,
- next,
- }
+const removeRemovedAccountRequest = (groupId, accountId) => ({
+ type: GROUP_REMOVED_ACCOUNTS_REMOVE_REQUEST,
+ groupId,
+ accountId,
+})
+
+const removeRemovedAccountSuccess = (groupId, accountId) => ({
+ type: GROUP_REMOVED_ACCOUNTS_REMOVE_SUCCESS,
+ groupId,
+ accountId,
+})
+
+const removeRemovedAccountFail = (groupId, accountId, error) => ({
+ type: GROUP_REMOVED_ACCOUNTS_REMOVE_FAIL,
+ groupId,
+ accountId,
+ error,
+})
+
+/**
+ * @description Remove an account with given accountId from group with given groupId
+ * @param {String} groupId
+ * @param {String} accountId
+ */
+export const createRemovedAccount = (groupId, accountId) => (dispatch, getState) => {
+ if (!me) return
+
+ dispatch(createRemovedAccountRequest(groupId, accountId))
+
+ api(getState).post(`/api/v1/groups/${groupId}/removed_accounts?account_id=${accountId}`).then((response) => {
+ dispatch(createRemovedAccountSuccess(groupId, accountId))
+ }).catch((error) => {
+ dispatch(createRemovedAccountFail(groupId, accountId, error))
+ })
}
-export function fetchJoinRequestsFail(id, error) {
- return {
- type: GROUP_JOIN_REQUESTS_FETCH_FAIL,
- id,
- error,
- }
+const createRemovedAccountRequest = (groupId, accountId) => ({
+ type: GROUP_REMOVED_ACCOUNTS_CREATE_REQUEST,
+ groupId,
+ accountId,
+})
+
+const createRemovedAccountSuccess = (groupId, accountId) => ({
+ type: GROUP_REMOVED_ACCOUNTS_CREATE_SUCCESS,
+ groupId,
+ accountId,
+})
+
+const createRemovedAccountFail = (groupId, accountId, error) => ({
+ type: GROUP_REMOVED_ACCOUNTS_CREATE_FAIL,
+ groupId,
+ accountId,
+ error,
+})
+
+/**
+ * @description Remove a status from a group with given groupId and statusId. Then
+ * remove the status from the group timeline on success.
+ * @param {String} groupId
+ * @param {String} statusId
+ */
+export const groupRemoveStatus = (groupId, statusId) => (dispatch, getState) => {
+ if (!me || !groupId || !statusId) return
+
+ dispatch(groupRemoveStatusRequest(groupId, statusId))
+
+ api(getState).delete(`/api/v1/groups/${groupId}/statuses/${statusId}`).then((response) => {
+ dispatch(groupRemoveStatusSuccess(groupId, statusId))
+ }).catch((error) => {
+ dispatch(groupRemoveStatusFail(groupId, statusId, error))
+ })
}
-export function expandJoinRequests(id) {
- return (dispatch, getState) => {
- if (!me) return
+const groupRemoveStatusRequest = (groupId, statusId) => ({
+ type: GROUP_REMOVE_STATUS_REQUEST,
+ groupId,
+ statusId,
+})
- const url = getState().getIn(['user_lists', 'group_join_requests', id, 'next'])
- const isLoading = getState().getIn(['user_lists', 'group_join_requests', id, 'isLoading'])
+const groupRemoveStatusSuccess = (groupId, statusId) => ({
+ type: GROUP_REMOVE_STATUS_SUCCESS,
+ groupId,
+ statusId,
+})
- if (url === null || isLoading) return
+const groupRemoveStatusFail = (groupId, statusId, error) => ({
+ type: GROUP_REMOVE_STATUS_FAIL,
+ groupId,
+ statusId,
+ error,
+})
- dispatch(expandJoinRequestsRequest(id))
+/**
+ * @description Update role to admin, moderator for given accountId in given groupId
+ * @param {String} groupId
+ * @param {String} accountId
+ * @param {String} role
+ */
+export const updateRole = (groupId, accountId, role) => (dispatch, getState) => {
+ if (!me || !groupId || !accountId || !role) return
- api(getState).get(url).then(response => {
- const next = getLinks(response).refs.find(link => link.rel === 'next')
+ dispatch(updateRoleRequest(groupId, accountId))
- dispatch(importFetchedAccounts(response.data))
- dispatch(expandJoinRequestsSuccess(id, response.data, next ? next.uri : null))
- dispatch(fetchRelationships(response.data.map(item => item.id)))
- }).catch(error => {
- dispatch(expandJoinRequestsFail(id, error))
- })
- }
+ api(getState).patch(`/api/v1/groups/${groupId}/accounts?account_id=${accountId}`, { role }).then((response) => {
+ dispatch(updateRoleSuccess(groupId, accountId))
+ }).catch((error) => {
+ dispatch(updateRoleFail(groupId, accountId, error))
+ })
}
-export function expandJoinRequestsRequest(id) {
- return {
- type: GROUP_JOIN_REQUESTS_EXPAND_REQUEST,
- id,
- }
+const updateRoleRequest = (groupId, accountId) => ({
+ type: GROUP_UPDATE_ROLE_REQUEST,
+ groupId,
+ accountId,
+})
+
+const updateRoleSuccess = (groupId, accountId) => ({
+ type: GROUP_UPDATE_ROLE_SUCCESS,
+ groupId,
+ accountId,
+})
+
+const updateRoleFail = (groupId, accountId, error) => ({
+ type: GROUP_UPDATE_ROLE_FAIL,
+ groupId,
+ accountId,
+ error,
+})
+
+/**
+ * @description Reset the group password check map when group password model opens
+ */
+export const checkGroupPasswordReset = () => ({
+ type: GROUP_CHECK_PASSWORD_RESET,
+})
+
+/**
+ *
+ */
+export const checkGroupPassword = (groupId, password) => (dispatch, getState) => {
+ if (!me || !groupId) return
+
+ dispatch(checkGroupPasswordRequest())
+
+ api(getState).post(`/api/v1/groups/${groupId}/password`, { password }).then((response) => {
+ dispatch(joinGroupSuccess(response.data))
+ dispatch(checkGroupPasswordSuccess())
+ }).catch((error) => {
+ dispatch(checkGroupPasswordFail(error))
+ })
}
-export function expandJoinRequestsSuccess(id, accounts, next) {
- return {
- type: GROUP_JOIN_REQUESTS_EXPAND_SUCCESS,
- id,
- accounts,
- next,
- }
+const checkGroupPasswordRequest = () => ({
+ type: GROUP_CHECK_PASSWORD_REQUEST,
+})
+
+const checkGroupPasswordSuccess = () => ({
+ type: GROUP_CHECK_PASSWORD_SUCCESS,
+})
+
+export const checkGroupPasswordFail = (error) => ({
+ type: GROUP_CHECK_PASSWORD_FAIL,
+ error,
+})
+
+/**
+ *
+ */
+export const fetchJoinRequests = (id) => (dispatch, getState) => {
+ if (!me) return
+
+ dispatch(fetchJoinRequestsRequest(id))
+
+ api(getState).get(`/api/v1/groups/${id}/join_requests`).then((response) => {
+ const next = getLinks(response).refs.find(link => link.rel === 'next')
+
+ dispatch(importFetchedAccounts(response.data))
+ dispatch(fetchJoinRequestsSuccess(id, response.data, next ? next.uri : null))
+ dispatch(fetchRelationships(response.data.map(item => item.id)))
+ }).catch((error) => {
+ dispatch(fetchJoinRequestsFail(id, error))
+ })
}
-export function expandJoinRequestsFail(id, error) {
- return {
- type: GROUP_JOIN_REQUESTS_EXPAND_FAIL,
- id,
- error,
- }
+const fetchJoinRequestsRequest = (id) => ({
+ type: GROUP_JOIN_REQUESTS_FETCH_REQUEST,
+ id,
+})
+
+const fetchJoinRequestsSuccess = (id, accounts, next) => ({
+ type: GROUP_JOIN_REQUESTS_FETCH_SUCCESS,
+ id,
+ accounts,
+ next,
+})
+
+const fetchJoinRequestsFail = (id, error) => ({
+ type: GROUP_JOIN_REQUESTS_FETCH_FAIL,
+ id,
+ error,
+})
+
+/**
+ *
+ */
+export const expandJoinRequests = (id) => (dispatch, getState) => {
+ if (!me) return
+
+ const url = getState().getIn(['user_lists', 'group_join_requests', id, 'next'])
+ const isLoading = getState().getIn(['user_lists', 'group_join_requests', id, 'isLoading'])
+
+ if (url === null || isLoading) return
+
+ dispatch(expandJoinRequestsRequest(id))
+
+ api(getState).get(url).then((response) => {
+ const next = getLinks(response).refs.find(link => link.rel === 'next')
+
+ dispatch(importFetchedAccounts(response.data))
+ dispatch(expandJoinRequestsSuccess(id, response.data, next ? next.uri : null))
+ dispatch(fetchRelationships(response.data.map(item => item.id)))
+ }).catch((error) => {
+ dispatch(expandJoinRequestsFail(id, error))
+ })
}
+const expandJoinRequestsRequest = (id) => ({
+ type: GROUP_JOIN_REQUESTS_EXPAND_REQUEST,
+ id,
+})
+
+const expandJoinRequestsSuccess = (id, accounts, next) => ({
+ type: GROUP_JOIN_REQUESTS_EXPAND_SUCCESS,
+ id,
+ accounts,
+ next,
+})
+
+const expandJoinRequestsFail = (id, error) => ({
+ type: GROUP_JOIN_REQUESTS_EXPAND_FAIL,
+ id,
+ error,
+})
+
+/**
+ *
+ */
export const approveJoinRequest = (accountId, groupId) => (dispatch, getState) => {
if (!me) return
@@ -832,23 +819,22 @@ export const approveJoinRequest = (accountId, groupId) => (dispatch, getState) =
})
}
-export function approveJoinRequestSuccess(accountId, groupId) {
- return {
- type: GROUP_JOIN_REQUESTS_APPROVE_SUCCESS,
- accountId,
- groupId,
- }
-}
+const approveJoinRequestSuccess = (accountId, groupId) => ({
+ type: GROUP_JOIN_REQUESTS_APPROVE_SUCCESS,
+ accountId,
+ groupId,
+})
-export function approveJoinRequestFail(accountId, groupId, error) {
- return {
- type: GROUP_JOIN_REQUESTS_APPROVE_FAIL,
- accountId,
- groupId,
- error,
- }
-}
+const approveJoinRequestFail = (accountId, groupId, error) => ({
+ type: GROUP_JOIN_REQUESTS_APPROVE_FAIL,
+ accountId,
+ groupId,
+ error,
+})
+/**
+ *
+ */
export const rejectJoinRequest = (accountId, groupId) => (dispatch, getState) => {
if (!me) return
@@ -859,99 +845,125 @@ export const rejectJoinRequest = (accountId, groupId) => (dispatch, getState) =>
})
}
-export function rejectJoinRequestSuccess(accountId, groupId) {
- return {
- type: GROUP_JOIN_REQUESTS_REJECT_SUCCESS,
- accountId,
- groupId,
- }
+const rejectJoinRequestSuccess = (accountId, groupId) => ({
+ type: GROUP_JOIN_REQUESTS_REJECT_SUCCESS,
+ accountId,
+ groupId,
+})
+
+const rejectJoinRequestFail = (accountId, groupId, error) => ({
+ type: GROUP_JOIN_REQUESTS_REJECT_FAIL,
+ accountId,
+ groupId,
+ error,
+})
+
+/**
+ *
+ */
+export const pinGroupStatus = (groupId, statusId) => (dispatch, getState) => {
+ if (!me || !groupId || !statusId) return
+
+ dispatch(pinGroupStatusRequest(groupId))
+
+ api(getState).post(`/api/v1/groups/${groupId}/pin`, { statusId }).then((response) => {
+ dispatch(updateStatusStats(response.data))
+ dispatch(pinGroupStatusSuccess(groupId, statusId))
+ }).catch((error) => {
+ dispatch(pinGroupStatusFail(groupId, statusId, error))
+ })
}
-export function rejectJoinRequestFail(accountId, groupId, error) {
- return {
- type: GROUP_JOIN_REQUESTS_REJECT_FAIL,
- accountId,
- groupId,
- error,
- }
+const pinGroupStatusRequest = (groupId) => ({
+ type: GROUP_PIN_STATUS_REQUEST,
+ groupId,
+})
+
+const pinGroupStatusSuccess = (groupId, statusId) => ({
+ type: GROUP_PIN_STATUS_SUCCESS,
+ groupId,
+ statusId,
+})
+
+const pinGroupStatusFail = (groupId, statusId, error) => ({
+ type: GROUP_PIN_STATUS_FAIL,
+ groupId,
+ statusId,
+ error,
+})
+
+/**
+ *
+ */
+export const unpinGroupStatus = (groupId, statusId) =>(dispatch, getState) => {
+ if (!me || !groupId || !statusId) return
+
+ dispatch(unpinGroupStatusRequest(groupId))
+
+ api(getState).post(`/api/v1/groups/${groupId}/unpin`, { statusId }).then((response) => {
+ dispatch(updateStatusStats(response.data))
+ dispatch(unpinGroupStatusSuccess(groupId, statusId))
+ }).catch((error) => {
+ dispatch(unpinGroupStatusFail(groupId, statusId, error))
+ })
}
-export function pinGroupStatus(groupId, statusId) {
- return (dispatch, getState) => {
- if (!me) return
+const unpinGroupStatusRequest = (groupId) => ({
+ type: GROUP_UNPIN_STATUS_REQUEST,
+ groupId,
+})
- dispatch(pinGroupStatusRequest(groupId))
+const unpinGroupStatusSuccess = (groupId, statusId) => ({
+ type: GROUP_UNPIN_STATUS_SUCCESS,
+ groupId,
+ statusId,
+})
- api(getState).post(`/api/v1/groups/${groupId}/pin`, { statusId }).then((response) => {
- dispatch(pinGroupStatusSuccess(groupId, statusId))
- }).catch((error) => {
- dispatch(pinGroupStatusFail(groupId, statusId, error))
- })
- }
+const unpinGroupStatusFail = (groupId, statusId, error) => ({
+ type: GROUP_UNPIN_STATUS_FAIL,
+ groupId,
+ statusId,
+ error,
+})
+
+
+/**
+ *
+ */
+export const isPinnedGroupStatus = (groupId, statusId) => (dispatch, getState) => {
+ if (!me || !groupId || !statusId) return
+
+ dispatch(isPinnedGroupStatusRequest(groupId, statusId))
+
+ api(getState).get(`/api/v1/groups/${groupId}/pin?statusId=${statusId}`).then((response) => {
+ dispatch(updateStatusStats(response.data))
+ }).catch((error) => {
+ dispatch(isPinnedGroupStatusFail(groupId, statusId, error))
+ })
}
-export function pinGroupStatusRequest(groupId) {
- return {
- type: GROUP_PIN_STATUS_REQUEST,
- groupId,
- }
-}
+const isPinnedGroupStatusRequest = (groupId, statusId) => ({
+ type: IS_PINNED_GROUP_STATUS_REQUEST,
+ groupId,
+ statusId,
+})
-export function pinGroupStatusSuccess(groupId, statusId) {
- return {
- type: GROUP_PIN_STATUS_SUCCESS,
- groupId,
- statusId,
- }
-}
+const isPinnedGroupStatusSuccess = (groupId, statusId) => ({
+ type: IS_PINNED_GROUP_STATUS_SUCCESS,
+ groupId,
+ statusId,
+})
-export function pinGroupStatusFail(groupId, statusId, error) {
- return {
- type: GROUP_PIN_STATUS_FAIL,
- groupId,
- statusId,
- error,
- }
-}
-
-export function unpinGroupStatus(groupId, statusId) {
- return (dispatch, getState) => {
- if (!me) return
-
- dispatch(unpinGroupStatusRequest(groupId))
-
- api(getState).post(`/api/v1/groups/${groupId}/unpin`, { statusId }).then((response) => {
- dispatch(unpinGroupStatusSuccess(groupId, statusId))
- }).catch((error) => {
- dispatch(unpinGroupStatusFail(groupId, statusId, error))
- })
- }
-}
-
-export function unpinGroupStatusRequest(groupId) {
- return {
- type: GROUP_UNPIN_STATUS_REQUEST,
- groupId,
- }
-}
-
-export function unpinGroupStatusSuccess(groupId, statusId) {
- return {
- type: GROUP_UNPIN_STATUS_SUCCESS,
- groupId,
- statusId,
- }
-}
-
-export function unpinGroupStatusFail(groupId, statusId, error) {
- return {
- type: GROUP_UNPIN_STATUS_FAIL,
- groupId,
- statusId,
- error,
- }
-}
+const isPinnedGroupStatusFail = (groupId, statusId, error) => ({
+ type: IS_PINNED_GROUP_STATUS_FAIL,
+ groupId,
+ statusId,
+ error,
+})
+/**
+ *
+ */
export const sortGroups = (tab, sortType) => (dispatch, getState) => {
const groupIdsByTab = getState().getIn(['group_lists', tab, 'items'], ImmutableList()).toJS()
const allGroups = getState().get('groups', ImmutableMap()).toJS()
@@ -974,16 +986,14 @@ export const sortGroups = (tab, sortType) => (dispatch, getState) => {
const sortedGroupsIdsByTab = groupsByTab.map((group) => group.id)
dispatch(groupsSort(tab, sortedGroupsIdsByTab))
-};
-
-export function groupsSort(tab, groupIds) {
- return {
- type: GROUP_SORT,
- tab,
- groupIds,
- }
}
+export const groupsSort = (tab, groupIds) =>({
+ type: GROUP_SORT,
+ tab,
+ groupIds,
+})
+
export const setGroupTimelineSort = (sortValue) => (dispatch) => {
dispatch({
type: GROUP_TIMELINE_SORT,
diff --git a/app/javascript/gabsocial/actions/importer/index.js b/app/javascript/gabsocial/actions/importer/index.js
index b9c1630f..c98a256b 100644
--- a/app/javascript/gabsocial/actions/importer/index.js
+++ b/app/javascript/gabsocial/actions/importer/index.js
@@ -14,7 +14,10 @@ export const STATUSES_IMPORT = 'STATUSES_IMPORT'
export const POLLS_IMPORT = 'POLLS_IMPORT'
export const ACCOUNT_FETCH_FAIL_FOR_USERNAME_LOOKUP = 'ACCOUNT_FETCH_FAIL_FOR_USERNAME_LOOKUP'
-function pushUnique(array, object) {
+/**
+ *
+ */
+const pushUnique = (array, object) => {
if (array.every(element => element.id !== object.id)) {
array.push(object);
}
diff --git a/app/javascript/gabsocial/actions/importer/normalizer.js b/app/javascript/gabsocial/actions/importer/normalizer.js
index 69c3c26d..7cdbcf12 100644
--- a/app/javascript/gabsocial/actions/importer/normalizer.js
+++ b/app/javascript/gabsocial/actions/importer/normalizer.js
@@ -5,20 +5,26 @@ import { expandSpoilers } from '../../initial_state'
const domParser = new DOMParser()
+/**
+ *
+ */
const makeEmojiMap = record => record.emojis.reduce((obj, emoji) => {
- obj[`:${emoji.shortcode}:`] = emoji;
- return obj;
-}, {});
+ obj[`:${emoji.shortcode}:`] = emoji
+ return obj
+}, {})
-export function normalizeAccount(account) {
- account = { ...account };
+/**
+ *
+ */
+export const normalizeAccount = (account) => {
+ account = { ...account }
- const emojiMap = makeEmojiMap(account);
- const displayName = account.display_name.trim().length === 0 ? account.username : account.display_name;
+ const emojiMap = makeEmojiMap(account)
+ const displayName = account.display_name.trim().length === 0 ? account.username : account.display_name
- account.display_name_html = emojify(escapeTextContentForBrowser(displayName), emojiMap);
- account.display_name_plain = emojify(escapeTextContentForBrowser(displayName), emojiMap, true);
- account.note_emojified = emojify(account.note, emojiMap);
+ account.display_name_html = emojify(escapeTextContentForBrowser(displayName), emojiMap)
+ account.display_name_plain = emojify(escapeTextContentForBrowser(displayName), emojiMap, true)
+ account.note_emojified = emojify(account.note, emojiMap)
account.note_plain = unescapeHTML(account.note)
if (account.fields) {
@@ -27,67 +33,73 @@ export function normalizeAccount(account) {
name_emojified: emojify(escapeTextContentForBrowser(pair.name)),
value_emojified: emojify(pair.value, emojiMap),
value_plain: unescapeHTML(pair.value),
- }));
+ }))
}
if (account.moved) {
- account.moved = account.moved.id;
+ account.moved = account.moved.id
}
- return account;
+ return account
}
-export function normalizeStatus(status, normalOldStatus) {
- const normalStatus = { ...status };
- normalStatus.account = status.account_id || status.account.id;
+/**
+ *
+ */
+export const normalizeStatus = (status, normalOldStatus) => {
+ const normalStatus = { ...status }
+ normalStatus.account = status.account_id || status.account.id
if (status.reblog && status.reblog.id) {
- normalStatus.reblog = status.reblog.id;
+ normalStatus.reblog = status.reblog.id
}
if (status.quote && status.quote.id) {
- normalStatus.quote = status.quote.id;
+ normalStatus.quote = status.quote.id
}
if (status.poll && status.poll.id) {
- normalStatus.poll = status.poll.id;
+ normalStatus.poll = status.poll.id
}
if (!!status.group || !!status.group_id) {
- normalStatus.group = status.group_id || status.group.id;
+ normalStatus.group = status.group_id || status.group.id
}
// Only calculate these values when status first encountered
// Otherwise keep the ones already in the reducer
if (normalOldStatus && normalOldStatus.get('content') === normalStatus.content && normalOldStatus.get('spoiler_text') === normalStatus.spoiler_text) {
- normalStatus.search_index = normalOldStatus.get('search_index');
- normalStatus.contentHtml = normalOldStatus.get('contentHtml');
- normalStatus.spoilerHtml = normalOldStatus.get('spoilerHtml');
- normalStatus.hidden = normalOldStatus.get('hidden');
+ normalStatus.search_index = normalOldStatus.get('search_index')
+ normalStatus.contentHtml = normalOldStatus.get('contentHtml')
+ normalStatus.spoilerHtml = normalOldStatus.get('spoilerHtml')
+ normalStatus.hidden = normalOldStatus.get('hidden')
} else {
- const spoilerText = normalStatus.spoiler_text || '';
- const searchContent = [spoilerText, status.content].join('\n\n').replace(/
/g, '\n').replace(/<\/p>
/g, '\n\n');
- const emojiMap = makeEmojiMap(normalStatus);
- const theContent = !!normalStatus.rich_content ? normalStatus.rich_content : normalStatus.content;
+ const spoilerText = normalStatus.spoiler_text || ''
+ const searchContent = [spoilerText, status.content].join('\n\n').replace(/
/g, '\n').replace(/<\/p>
/g, '\n\n')
+ const emojiMap = makeEmojiMap(normalStatus)
+ const theContent = !!normalStatus.rich_content ? normalStatus.rich_content : normalStatus.content
- normalStatus.search_index = domParser.parseFromString(searchContent, 'text/html').documentElement.textContent;
- normalStatus.contentHtml = emojify(theContent, emojiMap, false, true);
- normalStatus.spoilerHtml = emojify(escapeTextContentForBrowser(spoilerText), emojiMap);
- normalStatus.hidden = expandSpoilers ? false : spoilerText.length > 0 || normalStatus.sensitive;
+ normalStatus.search_index = domParser.parseFromString(searchContent, 'text/html').documentElement.textContent
+ normalStatus.contentHtml = emojify(theContent, emojiMap, false, true)
+ normalStatus.spoilerHtml = emojify(escapeTextContentForBrowser(spoilerText), emojiMap)
+ normalStatus.hidden = expandSpoilers ? false : spoilerText.length > 0 || normalStatus.sensitive
}
- return normalStatus;
+ return normalStatus
}
-export function normalizePoll(poll) {
- const normalPoll = { ...poll };
+/**
+ *
+ */
+export const normalizePoll = (poll) => {
+ const normalPoll = { ...poll }
- const emojiMap = makeEmojiMap(normalPoll);
+ const emojiMap = makeEmojiMap(normalPoll)
- normalPoll.options = poll.options.map(option => ({
+ normalPoll.options = poll.options.map((option) => ({
...option,
title_emojified: emojify(escapeTextContentForBrowser(option.title), emojiMap),
- }));
+ }))
- return normalPoll;
+ return normalPoll
}
\ No newline at end of file
diff --git a/app/javascript/gabsocial/actions/interactions.js b/app/javascript/gabsocial/actions/interactions.js
index 657ee262..2dd2d01a 100644
--- a/app/javascript/gabsocial/actions/interactions.js
+++ b/app/javascript/gabsocial/actions/interactions.js
@@ -1,5 +1,9 @@
-import api from '../api'
-import { importFetchedAccounts, importFetchedStatus } from './importer'
+import api, { getLinks } from '../api'
+import {
+ importFetchedAccounts,
+ importFetchedStatus,
+} from './importer'
+import { fetchRelationships } from './accounts'
import { updateStatusStats } from './statuses'
import { me } from '../initial_state'
@@ -23,6 +27,10 @@ export const REPOSTS_FETCH_REQUEST = 'REPOSTS_FETCH_REQUEST'
export const REPOSTS_FETCH_SUCCESS = 'REPOSTS_FETCH_SUCCESS'
export const REPOSTS_FETCH_FAIL = 'REPOSTS_FETCH_FAIL'
+export const REPOSTS_EXPAND_REQUEST = 'REPOSTS_EXPAND_REQUEST'
+export const REPOSTS_EXPAND_SUCCESS = 'REPOSTS_EXPAND_SUCCESS'
+export const REPOSTS_EXPAND_FAIL = 'REPOSTS_EXPAND_FAIL'
+
export const PIN_REQUEST = 'PIN_REQUEST'
export const PIN_SUCCESS = 'PIN_SUCCESS'
export const PIN_FAIL = 'PIN_FAIL'
@@ -31,6 +39,10 @@ export const UNPIN_REQUEST = 'UNPIN_REQUEST'
export const UNPIN_SUCCESS = 'UNPIN_SUCCESS'
export const UNPIN_FAIL = 'UNPIN_FAIL'
+export const IS_PIN_REQUEST = 'IS_PIN_REQUEST'
+export const IS_PIN_SUCCESS = 'IS_PIN_SUCCESS'
+export const IS_PIN_FAIL = 'IS_PIN_FAIL'
+
export const BOOKMARK_REQUEST = 'BOOKMARK_REQUEST'
export const BOOKMARK_SUCCESS = 'BOOKMARK_SUCCESS'
export const BOOKMARK_FAIL = 'BOOKMARK_FAIL'
@@ -39,342 +51,512 @@ export const UNBOOKMARK_REQUEST = 'UNBOOKMARK_REQUEST'
export const UNBOOKMARK_SUCCESS = 'UNBOOKMARK_SUCCESS'
export const UNBOOKMARK_FAIL = 'UNBOOKMARK_FAIL'
+export const IS_BOOKMARK_REQUEST = 'IS_BOOKMARK_REQUEST'
+export const IS_BOOKMARK_SUCCESS = 'IS_BOOKMARK_SUCCESS'
+export const IS_BOOKMARK_FAIL = 'IS_BOOKMARK_FAIL'
+
export const LIKES_FETCH_REQUEST = 'LIKES_FETCH_REQUEST'
export const LIKES_FETCH_SUCCESS = 'LIKES_FETCH_SUCCESS'
export const LIKES_FETCH_FAIL = 'LIKES_FETCH_FAIL'
+export const LIKES_EXPAND_REQUEST = 'LIKES_EXPAND_REQUEST'
+export const LIKES_EXPAND_SUCCESS = 'LIKES_EXPAND_SUCCESS'
+export const LIKES_EXPAND_FAIL = 'LIKES_EXPAND_FAIL'
+
/**
- *
+ * @description Repost the given status. Set status to status.reblogged:true and
+ * increment status.reblogs_count by 1 on success.
+ * @param {ImmutableMap} status
*/
export const repost = (status) => (dispatch, getState) => {
- if (!me) return
+ if (!me || !status) return
dispatch(repostRequest(status))
api(getState).post(`/api/v1/statuses/${status.get('id')}/reblog`).then((response) => {
- // The reblog API method returns a new status wrapped around the original. In this case we are only
- // interested in how the original is modified, hence passing it skipping the wrapper
- dispatch(importFetchedStatus(response.data.reblog))
+ dispatch(updateStatusStats(response.data))
dispatch(repostSuccess(status))
}).catch((error) => {
dispatch(repostFail(status, error))
})
}
-export const repostRequest = (status) => ({
+const repostRequest = (status) => ({
type: REPOST_REQUEST,
- status: status,
- skipLoading: true,
+ status,
})
-export const repostSuccess = (status) => ({
+const repostSuccess = (status) => ({
type: REPOST_SUCCESS,
- status: status,
- skipLoading: true,
+ status,
})
-export const repostFail = (status, error) => ({
+const repostFail = (status, error) => ({
type: REPOST_FAIL,
- status: status,
- error: error,
- skipLoading: true,
+ status,
+ error,
})
/**
- *
+ * @description Unrepost the given status. Set status to status.reblogged:false and
+ * decrement status.reblogs_count by 1 on success.
+ * @param {ImmutableMap} status
*/
export const unrepost = (status) => (dispatch, getState) => {
- if (!me) return
+ if (!me || !status) return
dispatch(unrepostRequest(status))
api(getState).post(`/api/v1/statuses/${status.get('id')}/unreblog`).then((response) => {
- dispatch(importFetchedStatus(response.data))
+ dispatch(updateStatusStats(response.data))
dispatch(unrepostSuccess(status))
}).catch((error) => {
dispatch(unrepostFail(status, error))
})
}
-export const unrepostRequest = (status) => ({
+const unrepostRequest = (status) => ({
type: UNREPOST_REQUEST,
- status: status,
- skipLoading: true,
+ status,
})
-export const unrepostSuccess = (status) => ({
+const unrepostSuccess = (status) => ({
type: UNREPOST_SUCCESS,
- status: status,
- skipLoading: true,
+ status,
})
-export const unrepostFail = (status, error) => ({
+const unrepostFail = (status, error) => ({
type: UNREPOST_FAIL,
- status: status,
- error: error,
- skipLoading: true,
+ status,
+ error,
})
/**
- *
+ * @description Favorite the given status. Set status to status.favourited:true and
+ * increment status.favourites_count by 1 on success.
+ * @param {ImmutableMap} status
*/
export const favorite = (status) => (dispatch, getState) => {
- if (!me) return
+ if (!me || !status) return
dispatch(favoriteRequest(status))
api(getState).post(`/api/v1/statuses/${status.get('id')}/favourite`).then((response) => {
dispatch(updateStatusStats(response.data))
- dispatch(favoriteSuccess(status))
+ dispatch(favoriteSuccess(response.data))
}).catch((error) => {
dispatch(favoriteFail(status, error))
})
}
-export const favoriteRequest = (status) => ({
+const favoriteRequest = (status) => ({
type: FAVORITE_REQUEST,
- status: status,
- skipLoading: true,
+ status,
})
-export const favoriteSuccess = (status) => ({
+const favoriteSuccess = (data) => ({
type: FAVORITE_SUCCESS,
- status: status,
- skipLoading: true,
+ data,
})
-export const favoriteFail = (status, error) => ({
+const favoriteFail = (status, error) => ({
type: FAVORITE_FAIL,
- status: status,
- error: error,
- skipLoading: true,
+ status,
+ error,
})
/**
- *
+ * @description Unfavorite the given status. Set status to status.favourited:false and
+ * decrement status.favourites_count by 1 on success.
+ * @param {ImmutableMap} status
*/
export const unfavorite = (status) => (dispatch, getState) => {
- if (!me) return
+ if (!me || !status) return
dispatch(unfavoriteRequest(status))
api(getState).post(`/api/v1/statuses/${status.get('id')}/unfavourite`).then((response) => {
- dispatch(importFetchedStatus(response.data))
+ dispatch(updateStatusStats(response.data))
dispatch(unfavoriteSuccess(status))
}).catch((error) => {
dispatch(unfavoriteFail(status, error))
})
}
-export const unfavoriteRequest = (status) => ({
+const unfavoriteRequest = (status) => ({
type: UNFAVORITE_REQUEST,
- status: status,
- skipLoading: true,
+ status,
})
-export const unfavoriteSuccess = (status) => ({
+const unfavoriteSuccess = (status) => ({
type: UNFAVORITE_SUCCESS,
- status: status,
- skipLoading: true,
+ status,
})
-export const unfavoriteFail = (status, error) => ({
+const unfavoriteFail = (status, error) => ({
type: UNFAVORITE_FAIL,
- status: status,
- error: error,
- skipLoading: true,
-})
-
-/**
- *
- */
-export const fetchReposts = (id) => (dispatch, getState) => {
- if (!me) return
-
- dispatch(fetchRepostsRequest(id))
-
- api(getState).get(`/api/v1/statuses/${id}/reblogged_by`).then((response) => {
- dispatch(importFetchedAccounts(response.data))
- dispatch(fetchRepostsSuccess(id, response.data))
- }).catch((error) => {
- dispatch(fetchRepostsFail(id, error))
- })
-}
-
-export const fetchRepostsRequest = (id) => ({
- type: REPOSTS_FETCH_REQUEST,
- id,
-})
-
-export const fetchRepostsSuccess = (id, accounts) => ({
- type: REPOSTS_FETCH_SUCCESS,
- id,
- accounts,
-})
-
-export const fetchRepostsFail = (id, error) => ({
- type: REPOSTS_FETCH_FAIL,
+ status,
error,
})
/**
- *
+ * @description Pin the given status to your profile. Set status to status.pinned:true
+ * on success.
+ * @param {ImmutableMap} status
*/
export const pin = (status) => (dispatch, getState) => {
- if (!me) return
+ if (!me || !status) return
dispatch(pinRequest(status))
api(getState).post(`/api/v1/statuses/${status.get('id')}/pin`).then((response) => {
- dispatch(importFetchedStatus(response.data))
+ dispatch(updateStatusStats(response.data))
dispatch(pinSuccess(status))
}).catch((error) => {
dispatch(pinFail(status, error))
})
}
-export const pinRequest = (status) => ({
+const pinRequest = (status) => ({
type: PIN_REQUEST,
status,
- skipLoading: true,
})
-export const pinSuccess = (status) => ({
+const pinSuccess = (status) => ({
type: PIN_SUCCESS,
status,
- skipLoading: true,
})
-export const pinFail = (status, error) => ({
+const pinFail = (status, error) => ({
type: PIN_FAIL,
status,
error,
- skipLoading: true,
})
/**
- *
+ * @description Unpin the given status from your profile. Set status to status.pinned:false
+ * on success and remove from account pins in timeline reducer.
+ * @param {ImmutableMap} status
*/
export const unpin = (status) => (dispatch, getState) => {
- if (!me) return
+ if (!me || !status) return
dispatch(unpinRequest(status))
api(getState).post(`/api/v1/statuses/${status.get('id')}/unpin`).then((response) => {
- dispatch(importFetchedStatus(response.data))
- dispatch(unpinSuccess(status))
+ dispatch(updateStatusStats(response.data))
+ dispatch(unpinSuccess(status, response.data.account_id))
}).catch((error) => {
dispatch(unpinFail(status, error))
})
}
-export const unpinRequest = (status) => ({
+const unpinRequest = (status) => ({
type: UNPIN_REQUEST,
status,
- skipLoading: true,
})
-export const unpinSuccess = (status) => ({
+const unpinSuccess = (status, accountId) => ({
type: UNPIN_SUCCESS,
+ accountId,
status,
- skipLoading: true,
})
-export const unpinFail = (status, error) => ({
+const unpinFail = (status, error) => ({
type: UNPIN_FAIL,
status,
error,
- skipLoading: true,
})
/**
- *
+ * @description Check if a status is pinned to the current user account.
+ * @param {String} statusId
*/
-export const fetchLikes = (id) => (dispatch, getState) => {
- dispatch(fetchLikesRequest(id))
+export const isPin = (statusId) => (dispatch, getState) => {
+ if (!me || !statusId) return
- api(getState).get(`/api/v1/statuses/${id}/favourited_by`).then((response) => {
- dispatch(importFetchedAccounts(response.data))
- dispatch(fetchLikesSuccess(id, response.data))
+ dispatch(isPinRequest(statusId))
+
+ api(getState).get(`/api/v1/statuses/${statusId}/pin`).then((response) => {
+ dispatch(updateStatusStats(response.data))
+ dispatch(isPinSuccess(statusId))
}).catch((error) => {
- dispatch(fetchLikesFail(id, error))
+ dispatch(isPinFail(statusId, error))
})
}
-export const fetchLikesRequest = (id) => ({
- type: LIKES_FETCH_REQUEST,
- id,
+const isPinRequest = (statusId) => ({
+ type: IS_PIN_REQUEST,
+ statusId,
})
-export const fetchLikesSuccess = (id, accounts) => ({
- type: LIKES_FETCH_SUCCESS,
- id,
- accounts,
+const isPinSuccess = (statusId) => ({
+ type: IS_PIN_SUCCESS,
+ statusId,
})
-export const fetchLikesFail = (id, error) => ({
- type: LIKES_FETCH_FAIL,
+const isPinFail = (statusId, error) => ({
+ type: IS_PIN_FAIL,
+ statusId,
error,
})
/**
- *
+ * @description Bookmark the given status in your profile if PRO. Set status to
+ * status.bookmarked:true on success.
+ * @param {ImmutableMap} status
*/
export const bookmark = (status) => (dispatch, getState) => {
+ if (!me || !status) return
+
dispatch(bookmarkRequest(status))
api(getState).post(`/api/v1/statuses/${status.get('id')}/bookmark`).then((response) => {
- dispatch(importFetchedStatus(response.data))
- dispatch(bookmarkSuccess(status, response.data))
+ dispatch(updateStatusStats(response.data))
+ dispatch(bookmarkSuccess(status))
}).catch((error) => {
dispatch(bookmarkFail(status, error))
})
}
-export const bookmarkRequest = (status) => ({
+const bookmarkRequest = (status) => ({
type: BOOKMARK_REQUEST,
- status: status,
+ status,
})
-export const bookmarkSuccess = (status, response) => ({
+const bookmarkSuccess = (status) => ({
type: BOOKMARK_SUCCESS,
- status: status,
- response: response,
+ status,
})
-export const bookmarkFail = (status, error) => ({
+const bookmarkFail = (status, error) => ({
type: BOOKMARK_FAIL,
- status: status,
- error: error,
+ status,
+ error,
})
/**
- *
+ * @description Unbookmark the given status in your profile if PRO. Set status to
+ * status.bookmarked:false on success.
+ * @param {ImmutableMap} status
*/
export const unbookmark = (status) => (dispatch, getState) => {
+ if (!me || !status) return
+
dispatch(unbookmarkRequest(status))
api(getState).post(`/api/v1/statuses/${status.get('id')}/unbookmark`).then((response) => {
- dispatch(importFetchedStatus(response.data))
- dispatch(unbookmarkSuccess(status, response.data))
+ dispatch(updateStatusStats(response.data))
+ dispatch(unbookmarkSuccess(status))
}).catch((error) => {
dispatch(unbookmarkFail(status, error))
})
}
-export const unbookmarkRequest = (status) => ({
+const unbookmarkRequest = (status) => ({
type: UNBOOKMARK_REQUEST,
- status: status,
+ status,
})
-export const unbookmarkSuccess = (status, response) => ({
+const unbookmarkSuccess = (status) => ({
type: UNBOOKMARK_SUCCESS,
- status: status,
- response: response,
+ status,
})
-export const unbookmarkFail = (status, error) => ({
+const unbookmarkFail = (status, error) => ({
type: UNBOOKMARK_FAIL,
- status: status,
- error: error,
-})
\ No newline at end of file
+ status,
+ error,
+})
+
+/**
+ * @description Check if a status is bookmarked to the current user account.
+ * @param {String} statusId
+ */
+export const isBookmark = (statusId) => (dispatch, getState) => {
+ if (!me || !statusId) return
+
+ dispatch(isBookmarkRequest(statusId))
+
+ api(getState).get(`/api/v1/statuses/${statusId}/bookmark`).then((response) => {
+ dispatch(updateStatusStats(response.data))
+ dispatch(isBookmarkSuccess(statusId))
+ }).catch((error) => {
+ dispatch(isBookmarkFail(statusId, error))
+ })
+}
+
+const isBookmarkRequest = (statusId) => ({
+ type: IS_BOOKMARK_REQUEST,
+ statusId,
+})
+
+const isBookmarkSuccess = (statusId) => ({
+ type: IS_BOOKMARK_SUCCESS,
+ statusId,
+})
+
+const isBookmarkFail = (statusId, error) => ({
+ type: IS_BOOKMARK_FAIL,
+ statusId,
+ error,
+})
+
+/**
+ * @description Fetch reposts for the given statusId and imports paginated accounts
+ * and sets in user_lists reducer.
+ * @param {String} statusId
+ */
+export const fetchReposts = (statusId) => (dispatch, getState) => {
+ if (!me || !statusId) return
+
+ dispatch(fetchRepostsRequest(statusId))
+
+ api(getState).get(`/api/v1/statuses/${statusId}/reblogged_by`).then((response) => {
+ const next = getLinks(response).refs.find(link => link.rel === 'next')
+ dispatch(importFetchedAccounts(response.data))
+ dispatch(fetchRepostsSuccess(statusId, response.data, next ? next.uri : null))
+ dispatch(fetchRelationships(response.data.map(item => item.id)))
+ }).catch((error) => {
+ dispatch(fetchRepostsFail(statusId, error))
+ })
+}
+
+const fetchRepostsRequest = (statusId) => ({
+ type: REPOSTS_FETCH_REQUEST,
+ statusId,
+})
+
+const fetchRepostsSuccess = (statusId, accounts, next) => ({
+ type: REPOSTS_FETCH_SUCCESS,
+ statusId,
+ accounts,
+ next,
+})
+
+const fetchRepostsFail = (statusId, error) => ({
+ type: REPOSTS_FETCH_FAIL,
+ statusId,
+ error,
+})
+
+/**
+ * @description Expand reposts for the given statusId and imports paginated accounts
+ * and sets in user_lists reducer.
+ * @param {String} statusId
+ */
+export const expandReposts = (statusId) => (dispatch, getState) => {
+ if (!me || !statusId) return
+
+ const url = getState().getIn(['user_lists', 'reblogged_by', statusId, 'next'])
+ const isLoading = getState().getIn(['user_lists', 'reblogged_by', statusId, 'isLoading'])
+
+ if (url === null || isLoading) return
+
+ dispatch(expandRepostsRequest(statusId))
+
+ api(getState).get(url).then(response => {
+ const next = getLinks(response).refs.find(link => link.rel === 'next')
+ dispatch(importFetchedAccounts(response.data))
+ dispatch(expandRepostsSuccess(statusId, response.data, next ? next.uri : null))
+ dispatch(fetchRelationships(response.data.map(item => item.id)))
+ }).catch(error => dispatch(expandRepostsFail(error)))
+}
+
+const expandRepostsRequest = (statusId) => ({
+ type: REPOSTS_EXPAND_REQUEST,
+ statusId,
+})
+
+const expandRepostsSuccess = (statusId, accounts, next) => ({
+ type: REPOSTS_EXPAND_SUCCESS,
+ statusId,
+ accounts,
+ next,
+})
+
+const expandRepostsFail = (statusId, error) => ({
+ type: REPOSTS_EXPAND_FAIL,
+ statusId,
+ error,
+})
+
+
+/**
+ * @description Fetch likes for the given statusId and imports paginated accounts
+ * and sets in user_lists reducer.
+ * @param {String} statusId
+ */
+export const fetchLikes = (statusId) => (dispatch, getState) => {
+ if (!me || !statusId) return
+
+ dispatch(fetchLikesRequest(statusId))
+
+ api(getState).get(`/api/v1/statuses/${statusId}/favourited_by`).then((response) => {
+ const next = getLinks(response).refs.find(link => link.rel === 'next')
+ dispatch(importFetchedAccounts(response.data))
+ dispatch(fetchLikesSuccess(statusId, response.data, next ? next.uri : null))
+ dispatch(fetchRelationships(response.data.map(item => item.id)))
+ }).catch((error) => {
+ dispatch(fetchLikesFail(statusId, error))
+ })
+}
+
+const fetchLikesRequest = (statusId) => ({
+ type: LIKES_FETCH_REQUEST,
+ statusId,
+})
+
+const fetchLikesSuccess = (statusId, accounts, next) => ({
+ type: LIKES_FETCH_SUCCESS,
+ statusId,
+ accounts,
+ next,
+})
+
+const fetchLikesFail = (statusId, error) => ({
+ type: LIKES_FETCH_FAIL,
+ statusId,
+ error,
+})
+
+/**
+ * @description Expand likes for the given statusId and imports paginated accounts
+ * and sets in user_lists reducer.
+ * @param {String} statusId
+ */
+export const expandLikes = (statusId) => (dispatch, getState) => {
+ if (!me || !statusId) return
+
+ const url = getState().getIn(['user_lists', 'liked_by', statusId, 'next'])
+ const isLoading = getState().getIn(['user_lists', 'liked_by', statusId, 'isLoading'])
+
+ if (url === null || isLoading) return
+
+ dispatch(expandLikesRequest(statusId))
+
+ api(getState).get(url).then(response => {
+ const next = getLinks(response).refs.find(link => link.rel === 'next')
+ dispatch(importFetchedAccounts(response.data))
+ dispatch(expandLikesSuccess(statusId, response.data, next ? next.uri : null))
+ dispatch(fetchRelationships(response.data.map(item => item.id)))
+ }).catch(error => dispatch(expandLikesFail(error)))
+}
+
+const expandLikesRequest = (statusId) => ({
+ type: LIKES_EXPAND_REQUEST,
+ statusId,
+})
+
+const expandLikesSuccess = (statusId, accounts, next) => ({
+ type: LIKES_EXPAND_SUCCESS,
+ statusId,
+ accounts,
+ next,
+})
+
+const expandLikesFail = (statusId, error) => ({
+ type: LIKES_EXPAND_FAIL,
+ statusId,
+ error,
+})
diff --git a/app/javascript/gabsocial/actions/notifications.js b/app/javascript/gabsocial/actions/notifications.js
index 99f584b3..5a3d737f 100644
--- a/app/javascript/gabsocial/actions/notifications.js
+++ b/app/javascript/gabsocial/actions/notifications.js
@@ -1,5 +1,6 @@
import api, { getLinks } from '../api'
import IntlMessageFormat from 'intl-messageformat'
+import noop from 'lodash.noop'
import { fetchRelationships } from './accounts'
import {
importFetchedAccount,
@@ -49,8 +50,6 @@ const excludeTypesFromFilter = filter => {
return allTypes.filterNot(item => item === filter).toJS()
}
-const noOp = () => {}
-
/**
*
*/
@@ -159,7 +158,7 @@ export const dequeueNotifications = () => (dispatch, getState) => {
/**
*
*/
-export const expandNotifications = ({ maxId } = {}, done = noOp) => (dispatch, getState) => {
+export const expandNotifications = ({ maxId } = {}, done = noop) => (dispatch, getState) => {
if (!me) return
const onlyVerified = getState().getIn(['notifications', 'filter', 'onlyVerified'])
@@ -204,19 +203,19 @@ export const expandNotifications = ({ maxId } = {}, done = noOp) => (dispatch, g
})
}
-export const expandNotificationsRequest = (isLoadingMore) => ({
+const expandNotificationsRequest = (isLoadingMore) => ({
type: NOTIFICATIONS_EXPAND_REQUEST,
skipLoading: !isLoadingMore,
})
-export const expandNotificationsSuccess = (notifications, next, isLoadingMore) => ({
+const expandNotificationsSuccess = (notifications, next, isLoadingMore) => ({
type: NOTIFICATIONS_EXPAND_SUCCESS,
notifications,
next,
skipLoading: !isLoadingMore,
})
-export const expandNotificationsFail = (error, isLoadingMore) => ({
+const expandNotificationsFail = (error, isLoadingMore) => ({
type: NOTIFICATIONS_EXPAND_FAIL,
error,
skipLoading: !isLoadingMore,
diff --git a/app/javascript/gabsocial/actions/status_revisions.js b/app/javascript/gabsocial/actions/status_revisions.js
index 6425a381..081fe0ba 100644
--- a/app/javascript/gabsocial/actions/status_revisions.js
+++ b/app/javascript/gabsocial/actions/status_revisions.js
@@ -1,15 +1,23 @@
import api from '../api'
-export const STATUS_REVISIONS_LOAD = 'STATUS_REVISIONS_LOAD'
+export const STATUS_REVISIONS_LOAD_REQUEST = 'STATUS_REVISIONS_LOAD_REQUEST'
export const STATUS_REVISIONS_LOAD_SUCCESS = 'STATUS_REVISIONS_SUCCESS'
export const STATUS_REVISIONS_LOAD_FAIL = 'STATUS_REVISIONS_FAIL'
+/**
+ *
+ */
export const loadStatusRevisions = (statusId) => (dispatch, getState) => {
+ dispatch(loadStatusRevisionsRequest())
api(getState).get(`/api/v1/statuses/${statusId}/revisions`)
.then(res => dispatch(loadStatusRevisionsSuccess(res.data)))
.catch(() => dispatch(loadStatusRevisionsFail()))
}
+const loadStatusRevisionsRequest = () => ({
+ type: STATUS_REVISIONS_LOAD_REQUEST,
+})
+
const loadStatusRevisionsSuccess = (data) => ({
type: STATUS_REVISIONS_LOAD_SUCCESS,
revisions: data,
diff --git a/app/javascript/gabsocial/actions/statuses.js b/app/javascript/gabsocial/actions/statuses.js
index 3c9074ae..008b29df 100644
--- a/app/javascript/gabsocial/actions/statuses.js
+++ b/app/javascript/gabsocial/actions/statuses.js
@@ -1,304 +1,292 @@
-import api from '../api';
-import openDB from '../storage/db';
-import { evictStatus } from '../storage/modifier';
-import { deleteFromTimelines } from './timelines';
-import { importFetchedStatus, importFetchedStatuses, importAccount, importStatus } from './importer';
-import { openModal } from './modal';
-import { me } from '../initial_state';
+import api from '../api'
+import openDB from '../storage/db'
+import { evictStatus } from '../storage/modifier'
+import { deleteFromTimelines } from './timelines'
+import { importFetchedStatus, importFetchedStatuses, importAccount, importStatus } from './importer'
+import { openModal } from './modal'
+import { me } from '../initial_state'
-export const STATUS_FETCH_REQUEST = 'STATUS_FETCH_REQUEST';
-export const STATUS_FETCH_SUCCESS = 'STATUS_FETCH_SUCCESS';
-export const STATUS_FETCH_FAIL = 'STATUS_FETCH_FAIL';
+export const STATUS_FETCH_REQUEST = 'STATUS_FETCH_REQUEST'
+export const STATUS_FETCH_SUCCESS = 'STATUS_FETCH_SUCCESS'
+export const STATUS_FETCH_FAIL = 'STATUS_FETCH_FAIL'
-export const STATUS_DELETE_REQUEST = 'STATUS_DELETE_REQUEST';
-export const STATUS_DELETE_SUCCESS = 'STATUS_DELETE_SUCCESS';
-export const STATUS_DELETE_FAIL = 'STATUS_DELETE_FAIL';
+export const STATUS_DELETE_REQUEST = 'STATUS_DELETE_REQUEST'
+export const STATUS_DELETE_SUCCESS = 'STATUS_DELETE_SUCCESS'
+export const STATUS_DELETE_FAIL = 'STATUS_DELETE_FAIL'
-export const CONTEXT_FETCH_REQUEST = 'CONTEXT_FETCH_REQUEST';
-export const CONTEXT_FETCH_SUCCESS = 'CONTEXT_FETCH_SUCCESS';
-export const CONTEXT_FETCH_FAIL = 'CONTEXT_FETCH_FAIL';
+export const CONTEXT_FETCH_REQUEST = 'CONTEXT_FETCH_REQUEST'
+export const CONTEXT_FETCH_SUCCESS = 'CONTEXT_FETCH_SUCCESS'
+export const CONTEXT_FETCH_FAIL = 'CONTEXT_FETCH_FAIL'
-export const COMMENTS_FETCH_REQUEST = 'COMMENTS_FETCH_REQUEST';
-export const COMMENTS_FETCH_SUCCESS = 'COMMENTS_FETCH_SUCCESS';
-export const COMMENTS_FETCH_FAIL = 'COMMENTS_FETCH_FAIL';
+export const COMMENTS_FETCH_REQUEST = 'COMMENTS_FETCH_REQUEST'
+export const COMMENTS_FETCH_SUCCESS = 'COMMENTS_FETCH_SUCCESS'
+export const COMMENTS_FETCH_FAIL = 'COMMENTS_FETCH_FAIL'
-export const STATUS_REVEAL = 'STATUS_REVEAL';
-export const STATUS_HIDE = 'STATUS_HIDE';
+export const STATUS_REVEAL = 'STATUS_REVEAL'
+export const STATUS_HIDE = 'STATUS_HIDE'
-export const STATUS_EDIT = 'STATUS_EDIT';
+export const STATUS_EDIT = 'STATUS_EDIT'
export const UPDATE_STATUS_STATS = 'UPDATE_STATUS_STATS'
-export function fetchStatusRequest(id, skipLoading) {
- return {
- type: STATUS_FETCH_REQUEST,
- id,
- skipLoading,
- };
-};
-
+/**
+ *
+ */
function getFromDB(dispatch, getState, accountIndex, index, id) {
return new Promise((resolve, reject) => {
- const request = index.get(id);
+ const request = index.get(id)
- request.onerror = reject;
+ request.onerror = reject
request.onsuccess = () => {
- const promises = [];
+ const promises = []
if (!request.result) {
- reject();
- return;
+ reject()
+ return
}
- dispatch(importStatus(request.result));
+ dispatch(importStatus(request.result))
if (getState().getIn(['accounts', request.result.account], null) === null) {
promises.push(new Promise((accountResolve, accountReject) => {
- const accountRequest = accountIndex.get(request.result.account);
+ const accountRequest = accountIndex.get(request.result.account)
- accountRequest.onerror = accountReject;
+ accountRequest.onerror = accountReject
accountRequest.onsuccess = () => {
if (!request.result) {
- accountReject();
- return;
+ accountReject()
+ return
}
- dispatch(importAccount(accountRequest.result));
- accountResolve();
- };
- }));
+ dispatch(importAccount(accountRequest.result))
+ accountResolve()
+ }
+ }))
}
if (request.result.reblog && getState().getIn(['statuses', request.result.reblog], null) === null) {
- promises.push(getFromDB(dispatch, getState, accountIndex, index, request.result.reblog));
+ promises.push(getFromDB(dispatch, getState, accountIndex, index, request.result.reblog))
}
- resolve(Promise.all(promises));
- };
- });
+ resolve(Promise.all(promises))
+ }
+ })
}
-export function fetchStatus(id) {
- return (dispatch, getState) => {
- const skipLoading = getState().getIn(['statuses', id], null) !== null;
+/**
+ *
+ */
+export const fetchStatus = (id) => (dispatch, getState) => {
+ const skipLoading = getState().getIn(['statuses', id], null) !== null
+ if (skipLoading) return
- if (skipLoading) {
- return;
+ dispatch(fetchStatusRequest(id, skipLoading))
+
+ openDB().then((db) => {
+ const transaction = db.transaction(['accounts', 'statuses'], 'read')
+ const accountIndex = transaction.objectStore('accounts').index('id')
+ const index = transaction.objectStore('statuses').index('id')
+
+ return getFromDB(dispatch, getState, accountIndex, index, id).then(() => {
+ db.close()
+ }, (error) => {
+ db.close()
+ throw error
+ })
+ }).then(() => {
+ dispatch(fetchStatusSuccess(skipLoading))
+ }, () => api(getState).get(`/api/v1/statuses/${id}`).then((response) => {
+ dispatch(importFetchedStatus(response.data))
+ dispatch(fetchStatusSuccess(skipLoading))
+ })).catch((error) => {
+ dispatch(fetchStatusFail(id, error, skipLoading))
+ })
+}
+
+const fetchStatusRequest = (id, skipLoading) => ({
+ type: STATUS_FETCH_REQUEST,
+ id,
+ skipLoading,
+})
+
+const fetchStatusSuccess = (skipLoading) => ({
+ type: STATUS_FETCH_SUCCESS,
+ skipLoading,
+})
+
+const fetchStatusFail = (id, error, skipLoading) => ({
+ type: STATUS_FETCH_FAIL,
+ id,
+ error,
+ skipLoading,
+ skipAlert: true,
+})
+
+/**
+ *
+ */
+export const editStatus = (status) => (dispatch) => {
+ dispatch({
+ type: STATUS_EDIT,
+ status,
+ })
+
+ dispatch(openModal('COMPOSE'))
+}
+
+/**
+ *
+ */
+export const deleteStatus = (id, routerHistory) => (dispatch, getState) => {
+ if (!me) return
+
+ let status = getState().getIn(['statuses', id])
+
+ if (status.get('poll')) {
+ status = status.set('poll', getState().getIn(['polls', status.get('poll')]))
+ }
+
+ dispatch(deleteStatusRequest(id))
+
+ api(getState).delete(`/api/v1/statuses/${id}`).then((response) => {
+ evictStatus(id)
+ dispatch(deleteStatusSuccess(id))
+ dispatch(deleteFromTimelines(id))
+ }).catch((error) => {
+ dispatch(deleteStatusFail(id, error))
+ })
+}
+
+const deleteStatusRequest = (id) => ({
+ type: STATUS_DELETE_REQUEST,
+ id: id,
+})
+
+const deleteStatusSuccess = (id) => ({
+ type: STATUS_DELETE_SUCCESS,
+ id: id,
+})
+
+const deleteStatusFail = (id, error) => ({
+ type: STATUS_DELETE_FAIL,
+ id: id,
+ error,
+})
+
+/**
+ *
+ */
+export const fetchContext = (id, ensureIsReply) => (dispatch, getState) => {
+ if (ensureIsReply) {
+ const isReply = !!getState().getIn(['statuses', id, 'in_reply_to_id'], null)
+ if (!isReply) return
+ }
+
+ dispatch(fetchContextRequest(id))
+
+ api(getState).get(`/api/v1/statuses/${id}/context`).then((response) => {
+ dispatch(importFetchedStatuses(response.data.ancestors.concat(response.data.descendants)))
+ dispatch(fetchContextSuccess(id, response.data.ancestors, response.data.descendants))
+ }).catch((error) => {
+ if (error.response && error.response.status === 404) {
+ dispatch(deleteFromTimelines(id))
+ }
+ dispatch(fetchContextFail(id, error))
+ })
+}
+
+/**
+ *
+ */
+const fetchContextRequest = (id) => ({
+ type: CONTEXT_FETCH_REQUEST,
+ id,
+})
+
+const fetchContextSuccess = (id, ancestors, descendants) => ({
+ type: CONTEXT_FETCH_SUCCESS,
+ id,
+ ancestors,
+ descendants,
+ statuses: ancestors.concat(descendants),
+})
+
+const fetchContextFail = (id, error) => ({
+ type: CONTEXT_FETCH_FAIL,
+ id,
+ error,
+ skipAlert: true,
+})
+
+/**
+ *
+ */
+export const fetchComments = (id) => (dispatch, getState) => {
+ dispatch(fetchCommentsRequest(id))
+
+ api(getState).get(`/api/v1/statuses/${id}/comments`).then((response) => {
+ dispatch(importFetchedStatuses(response.data.descendants))
+ dispatch(fetchCommentsSuccess(id, response.data.descendants))
+ }).catch((error) => {
+ if (error.response && error.response.status === 404) {
+ dispatch(deleteFromTimelines(id))
}
- dispatch(fetchStatusRequest(id, skipLoading));
+ dispatch(fetchCommentsFail(id, error))
+ })
+}
- openDB().then(db => {
- const transaction = db.transaction(['accounts', 'statuses'], 'read');
- const accountIndex = transaction.objectStore('accounts').index('id');
- const index = transaction.objectStore('statuses').index('id');
+const fetchCommentsRequest = (id) => ({
+ type: COMMENTS_FETCH_REQUEST,
+ id,
+})
- return getFromDB(dispatch, getState, accountIndex, index, id).then(() => {
- db.close();
- }, error => {
- db.close();
- throw error;
- });
- }).then(() => {
- dispatch(fetchStatusSuccess(skipLoading));
- }, () => api(getState).get(`/api/v1/statuses/${id}`).then(response => {
- dispatch(importFetchedStatus(response.data));
- dispatch(fetchStatusSuccess(skipLoading));
- })).catch(error => {
- dispatch(fetchStatusFail(id, error, skipLoading));
- });
- };
-};
+const fetchCommentsSuccess = (id, descendants) => ({
+ type: COMMENTS_FETCH_SUCCESS,
+ id,
+ descendants,
+})
-export function fetchStatusSuccess(skipLoading) {
- return {
- type: STATUS_FETCH_SUCCESS,
- skipLoading,
- };
-};
+const fetchCommentsFail = (id, error) => ({
+ type: COMMENTS_FETCH_FAIL,
+ id,
+ error,
+ skipAlert: true,
+})
-export function fetchStatusFail(id, error, skipLoading) {
- return {
- type: STATUS_FETCH_FAIL,
- id,
- error,
- skipLoading,
- skipAlert: true,
- };
-};
-
-export function editStatus(status) {
- return dispatch => {
- dispatch({
- type: STATUS_EDIT,
- status,
- });
-
- dispatch(openModal('COMPOSE'));
- };
-};
-
-export function deleteStatus(id, routerHistory) {
- return (dispatch, getState) => {
- if (!me) return;
-
- let status = getState().getIn(['statuses', id]);
-
- if (status.get('poll')) {
- status = status.set('poll', getState().getIn(['polls', status.get('poll')]));
- }
-
- dispatch(deleteStatusRequest(id));
-
- api(getState).delete(`/api/v1/statuses/${id}`).then(response => {
- evictStatus(id);
- dispatch(deleteStatusSuccess(id));
- dispatch(deleteFromTimelines(id));
- }).catch(error => {
- dispatch(deleteStatusFail(id, error));
- });
- };
-};
-
-export function deleteStatusRequest(id) {
- return {
- type: STATUS_DELETE_REQUEST,
- id: id,
- };
-};
-
-export function deleteStatusSuccess(id) {
- return {
- type: STATUS_DELETE_SUCCESS,
- id: id,
- };
-};
-
-export function deleteStatusFail(id, error) {
- return {
- type: STATUS_DELETE_FAIL,
- id: id,
- error: error,
- };
-};
-
-export function fetchContext(id, ensureIsReply) {
- return (dispatch, getState) => {
- if (ensureIsReply) {
- const isReply = !!getState().getIn(['statuses', id, 'in_reply_to_id'], null)
- if (!isReply) return;
- }
-
- dispatch(fetchContextRequest(id));
-
- api(getState).get(`/api/v1/statuses/${id}/context`).then(response => {
- dispatch(importFetchedStatuses(response.data.ancestors.concat(response.data.descendants)));
- dispatch(fetchContextSuccess(id, response.data.ancestors, response.data.descendants));
-
- }).catch(error => {
- if (error.response && error.response.status === 404) {
- dispatch(deleteFromTimelines(id));
- }
-
- dispatch(fetchContextFail(id, error));
- });
- };
-};
-
-export function fetchComments(id) {
- return (dispatch, getState) => {
- dispatch(fetchCommentsRequest(id));
-
- api(getState).get(`/api/v1/statuses/${id}/comments`).then(response => {
- dispatch(importFetchedStatuses(response.data.descendants));
- dispatch(fetchCommentsSuccess(id, response.data.descendants));
-
- }).catch(error => {
- if (error.response && error.response.status === 404) {
- dispatch(deleteFromTimelines(id));
- }
-
- dispatch(fetchCommentsFail(id, error));
- });
- };
-};
-
-export function fetchContextRequest(id) {
- return {
- type: CONTEXT_FETCH_REQUEST,
- id,
- };
-};
-
-export function fetchContextSuccess(id, ancestors, descendants) {
- return {
- type: CONTEXT_FETCH_SUCCESS,
- id,
- ancestors,
- descendants,
- statuses: ancestors.concat(descendants),
- };
-};
-
-export function fetchContextFail(id, error) {
- return {
- type: CONTEXT_FETCH_FAIL,
- id,
- error,
- skipAlert: true,
- };
-};
-
-export function fetchCommentsRequest(id) {
- return {
- type: COMMENTS_FETCH_REQUEST,
- id,
- };
-};
-
-export function fetchCommentsSuccess(id, descendants) {
- return {
- type: COMMENTS_FETCH_SUCCESS,
- id,
- descendants,
- };
-};
-
-export function fetchCommentsFail(id, error) {
- return {
- type: COMMENTS_FETCH_FAIL,
- id,
- error,
- skipAlert: true,
- };
-};
-
-export function hideStatus(ids) {
+/**
+ *
+ */
+export const hideStatus = (ids) => {
if (!Array.isArray(ids)) {
- ids = [ids];
+ ids = [ids]
}
return {
type: STATUS_HIDE,
ids,
- };
-};
+ }
+}
-export function revealStatus(ids) {
+/**
+ *
+ */
+export const revealStatus = (ids) => {
if (!Array.isArray(ids)) {
- ids = [ids];
+ ids = [ids]
}
return {
type: STATUS_REVEAL,
ids,
- };
-};
+ }
+}
-export function updateStatusStats(data) {
- return {
- type: UPDATE_STATUS_STATS,
- data,
- };
-};
\ No newline at end of file
+/**
+ *
+ */
+export const updateStatusStats = (data) => ({
+ type: UPDATE_STATUS_STATS,
+ data,
+})
\ No newline at end of file
diff --git a/app/javascript/gabsocial/actions/streaming.js b/app/javascript/gabsocial/actions/streaming.js
index 60c6ae42..e33caeb5 100644
--- a/app/javascript/gabsocial/actions/streaming.js
+++ b/app/javascript/gabsocial/actions/streaming.js
@@ -71,3 +71,20 @@ export const connectStatusUpdateStream = () => {
*
*/
export const connectUserStream = () => connectTimelineStream('home', 'user')
+
+/**
+ *
+ */
+export const connectMessageStream = () => {
+
+ return connectStream('chat_messages', null, (dispatch, getState) => {
+
+ return {
+ onConnect() {},
+ onDisconnect() {},
+ onReceive (data) {
+ //
+ },
+ }
+ })
+}
\ No newline at end of file
diff --git a/app/javascript/gabsocial/actions/suggestions.js b/app/javascript/gabsocial/actions/suggestions.js
index efc6a21b..8e4f66aa 100644
--- a/app/javascript/gabsocial/actions/suggestions.js
+++ b/app/javascript/gabsocial/actions/suggestions.js
@@ -44,20 +44,17 @@ const fetchSuggestions = (suggestionType, dispatch, getState, unlimited = false)
const fetchSuggestionsRequest = (suggestionType) => ({
type: SUGGESTIONS_FETCH_REQUEST,
- skipLoading: true,
suggestionType,
})
const fetchSuggestionsSuccess = (accounts, suggestionType) => ({
type: SUGGESTIONS_FETCH_SUCCESS,
- skipLoading: true,
accounts,
suggestionType
})
const fetchSuggestionsFail = (error, suggestionType) => ({
type: SUGGESTIONS_FETCH_FAIL,
- skipLoading: true,
skipAlert: true,
error,
suggestionType,
diff --git a/app/javascript/gabsocial/actions/timelines.js b/app/javascript/gabsocial/actions/timelines.js
index 560d4b92..af65ae18 100644
--- a/app/javascript/gabsocial/actions/timelines.js
+++ b/app/javascript/gabsocial/actions/timelines.js
@@ -1,133 +1,139 @@
-import { Map as ImmutableMap, List as ImmutableList, toJS } from 'immutable';
-import { importFetchedStatus, importFetchedStatuses } from './importer';
-import api, { getLinks } from '../api';
+import { Map as ImmutableMap, List as ImmutableList, toJS } from 'immutable'
+import noop from 'lodash.noop'
+import { importFetchedStatus, importFetchedStatuses } from './importer'
+import api, { getLinks } from '../api'
import { fetchRelationships } from './accounts'
-export const TIMELINE_UPDATE = 'TIMELINE_UPDATE';
-export const TIMELINE_DELETE = 'TIMELINE_DELETE';
-export const TIMELINE_CLEAR = 'TIMELINE_CLEAR';
-export const TIMELINE_UPDATE_QUEUE = 'TIMELINE_UPDATE_QUEUE';
-export const TIMELINE_DEQUEUE = 'TIMELINE_DEQUEUE';
-export const TIMELINE_SCROLL_TOP = 'TIMELINE_SCROLL_TOP';
+export const TIMELINE_UPDATE = 'TIMELINE_UPDATE'
+export const TIMELINE_DELETE = 'TIMELINE_DELETE'
+export const TIMELINE_CLEAR = 'TIMELINE_CLEAR'
+export const TIMELINE_UPDATE_QUEUE = 'TIMELINE_UPDATE_QUEUE'
+export const TIMELINE_DEQUEUE = 'TIMELINE_DEQUEUE'
+export const TIMELINE_SCROLL_TOP = 'TIMELINE_SCROLL_TOP'
-export const TIMELINE_EXPAND_REQUEST = 'TIMELINE_EXPAND_REQUEST';
-export const TIMELINE_EXPAND_SUCCESS = 'TIMELINE_EXPAND_SUCCESS';
-export const TIMELINE_EXPAND_FAIL = 'TIMELINE_EXPAND_FAIL';
+export const TIMELINE_EXPAND_REQUEST = 'TIMELINE_EXPAND_REQUEST'
+export const TIMELINE_EXPAND_SUCCESS = 'TIMELINE_EXPAND_SUCCESS'
+export const TIMELINE_EXPAND_FAIL = 'TIMELINE_EXPAND_FAIL'
-export const TIMELINE_CONNECT = 'TIMELINE_CONNECT';
-export const TIMELINE_DISCONNECT = 'TIMELINE_DISCONNECT';
+export const TIMELINE_CONNECT = 'TIMELINE_CONNECT'
+export const TIMELINE_DISCONNECT = 'TIMELINE_DISCONNECT'
-export const MAX_QUEUED_ITEMS = 40;
-
-export function updateTimeline(timeline, status, accept) {
- return dispatch => {
- if (typeof accept === 'function' && !accept(status)) {
- return;
- }
-
- dispatch(importFetchedStatus(status));
-
- dispatch({
- type: TIMELINE_UPDATE,
- timeline,
- status,
- });
- };
-};
-
-export function updateTimelineQueue(timeline, status, accept) {
- return dispatch => {
- if (typeof accept === 'function' && !accept(status)) {
- return;
- }
-
- dispatch({
- type: TIMELINE_UPDATE_QUEUE,
- timeline,
- status,
- });
- }
-};
-
-export function forceDequeueTimeline(timeline) {
- return (dispatch) => {
- dispatch({
- type: TIMELINE_DEQUEUE,
- timeline,
- })
- }
-}
-
-export function dequeueTimeline(timeline, expandFunc, optionalExpandArgs) {
- return (dispatch, getState) => {
- const queuedItems = getState().getIn(['timelines', timeline, 'queuedItems'], ImmutableList());
- const totalQueuedItemsCount = getState().getIn(['timelines', timeline, 'totalQueuedItemsCount'], 0);
-
- let shouldDispatchDequeue = true;
-
- if (totalQueuedItemsCount === 0) {
- return;
- } else if (totalQueuedItemsCount > 0 && totalQueuedItemsCount <= MAX_QUEUED_ITEMS) {
- queuedItems.forEach(status => {
- dispatch(updateTimeline(timeline, status.toJS(), null));
- });
- } else {
- if (typeof expandFunc === 'function') {
- dispatch(clearTimeline(timeline));
- expandFunc();
- } else {
- if (timeline === 'home') {
- dispatch(clearTimeline(timeline));
- dispatch(expandHomeTimeline(optionalExpandArgs));
- } else if (timeline === 'community') {
- dispatch(clearTimeline(timeline));
- dispatch(expandCommunityTimeline(optionalExpandArgs));
- } else {
- shouldDispatchDequeue = false;
- }
- }
- }
-
- if (!shouldDispatchDequeue) return;
-
- dispatch({
- type: TIMELINE_DEQUEUE,
- timeline,
- });
- }
-};
-
-export function deleteFromTimelines(id) {
- return (dispatch, getState) => {
- const accountId = getState().getIn(['statuses', id, 'account']);
- const references = getState().get('statuses').filter(status => status.get('reblog') === id).map(status => [status.get('id'), status.get('account')]);
- const reblogOf = getState().getIn(['statuses', id, 'reblog'], null);
-
- dispatch({
- type: TIMELINE_DELETE,
- id,
- accountId,
- references,
- reblogOf,
- });
- };
-};
-
-export function clearTimeline(timeline) {
- return (dispatch) => {
- dispatch({ type: TIMELINE_CLEAR, timeline });
- };
-};
-
-const noOp = () => { };
+export const MAX_QUEUED_ITEMS = 40
const parseTags = (tags = {}, mode) => {
- return (tags[mode] || []).map((tag) => {
- return tag.value;
- });
-};
+ return (tags[mode] || []).map((tag) => tag.value)
+}
-export const expandTimeline = (timelineId, path, params = {}, done = noOp) => (dispatch, getState) => {
+/**
+ *
+ */
+export const updateTimeline = (timeline, status, accept) => (dispatch) => {
+ if (typeof accept === 'function' && !accept(status)) return
+
+ dispatch(importFetchedStatus(status))
+
+ dispatch({
+ type: TIMELINE_UPDATE,
+ timeline,
+ status,
+ })
+}
+
+/**
+ *
+ */
+export const updateTimelineQueue = (timeline, status, accept) => (dispatch) => {
+ if (typeof accept === 'function' && !accept(status)) return
+
+ dispatch({
+ type: TIMELINE_UPDATE_QUEUE,
+ timeline,
+ status,
+ })
+}
+
+/**
+ *
+ */
+export const forceDequeueTimeline = (timeline) => (dispatch) => {
+ dispatch({
+ type: TIMELINE_DEQUEUE,
+ timeline,
+ })
+}
+
+/**
+ *
+ */
+export const dequeueTimeline = (timeline, expandFunc, optionalExpandArgs) => (dispatch, getState) => {
+ const queuedItems = getState().getIn(['timelines', timeline, 'queuedItems'], ImmutableList())
+ const totalQueuedItemsCount = getState().getIn(['timelines', timeline, 'totalQueuedItemsCount'], 0)
+
+ let shouldDispatchDequeue = true
+
+ if (totalQueuedItemsCount === 0) return
+
+
+ if (totalQueuedItemsCount > 0 && totalQueuedItemsCount <= MAX_QUEUED_ITEMS) {
+ queuedItems.forEach((status) => {
+ dispatch(updateTimeline(timeline, status.toJS(), null))
+ })
+ } else {
+ if (typeof expandFunc === 'function') {
+ dispatch(clearTimeline(timeline))
+ expandFunc()
+ } else {
+ if (timeline === 'home') {
+ dispatch(clearTimeline(timeline))
+ dispatch(expandHomeTimeline(optionalExpandArgs))
+ } else if (timeline === 'community') {
+ dispatch(clearTimeline(timeline))
+ dispatch(expandCommunityTimeline(optionalExpandArgs))
+ } else {
+ shouldDispatchDequeue = false
+ }
+ }
+ }
+
+ if (!shouldDispatchDequeue) return
+
+ dispatch({
+ type: TIMELINE_DEQUEUE,
+ timeline,
+ })
+}
+
+/**
+ *
+ */
+export const deleteFromTimelines = (id) => (dispatch, getState) => {
+ const accountId = getState().getIn(['statuses', id, 'account'])
+ const references = getState().get('statuses').filter(status => status.get('reblog') === id).map(status => [status.get('id'), status.get('account')])
+ const reblogOf = getState().getIn(['statuses', id, 'reblog'], null)
+
+ dispatch({
+ type: TIMELINE_DELETE,
+ id,
+ accountId,
+ references,
+ reblogOf,
+ })
+}
+
+/**
+ *
+ */
+export const clearTimeline = (timeline) => (dispatch) => {
+ dispatch({
+ type: TIMELINE_CLEAR,
+ timeline
+ })
+}
+
+/**
+ *
+ */
+export const expandTimeline = (timelineId, path, params = {}, done = noop) => (dispatch, getState) => {
const timeline = getState().getIn(['timelines', timelineId], ImmutableMap())
const isLoadingMore = !!params.max_id
@@ -156,74 +162,179 @@ export const expandTimeline = (timelineId, path, params = {}, done = noOp) => (d
})
}
-export const expandHomeTimeline = ({ maxId } = {}, done = noOp) => expandTimeline('home', '/api/v1/timelines/home', { max_id: maxId }, done);
-export const expandExploreTimeline = ({ maxId, sortBy } = {}, done = noOp) => expandTimeline('explore', '/api/v1/timelines/explore', { max_id: maxId, sort_by: sortBy }, done);
-export const expandProTimeline = ({ maxId } = {}, done = noOp) => expandTimeline('pro', '/api/v1/timelines/pro', { max_id: maxId }, done);
-export const expandCommunityTimeline = ({ maxId, onlyMedia } = {}, done = noOp) => expandTimeline(`community${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { max_id: maxId, only_media: !!onlyMedia }, done);
-export const expandAccountTimeline = (accountId, { maxId, withReplies, commentsOnly } = {}) => expandTimeline(`account:${accountId}${withReplies ? ':with_replies' : ''}${commentsOnly ? ':comments_only' : ''}`, `/api/v1/accounts/${accountId}/statuses`, { only_comments: commentsOnly, exclude_replies: (!withReplies && !commentsOnly), max_id: maxId });
-export const expandAccountFeaturedTimeline = accountId => expandTimeline(`account:${accountId}:pinned`, `/api/v1/accounts/${accountId}/statuses`, { pinned: true });
-export const expandAccountMediaTimeline = (accountId, { maxId, limit, mediaType } = {}) => expandTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, { max_id: maxId, only_media: true, limit: limit || 20, media_type: mediaType });
-export const expandListTimeline = (id, { maxId } = {}, done = noOp) => expandTimeline(`list:${id}`, `/api/v1/timelines/list/${id}`, { max_id: maxId }, done);
-export const expandGroupTimeline = (id, { sortBy, maxId, onlyMedia } = {}, done = noOp) => expandTimeline(`group:${id}`, `/api/v1/timelines/group/${id}`, { sort_by: sortBy, max_id: maxId, only_media: onlyMedia }, done);
-export const expandGroupFeaturedTimeline = (groupId, done = noOp) => expandTimeline(`group:${groupId}:pinned`, `/api/v1/timelines/group_pins/${groupId}`, {}, done);
-export const expandGroupCollectionTimeline = (collectionType, { sortBy, maxId } = {}, done = noOp) => expandTimeline(`group_collection:${collectionType}`, `/api/v1/timelines/group_collection/${collectionType}`, { sort_by: sortBy, max_id: maxId }, done);
-export const expandLinkTimeline = (linkId, { maxId } = {}, done = noOp) => expandTimeline(`link:${linkId}`, `/api/v1/timelines/preview_card/${linkId}`, { max_id: maxId }, done);
-export const expandHashtagTimeline = (hashtag, { maxId, tags } = {}, done = noOp) => {
+const expandTimelineRequest = (timeline, isLoadingMore) => ({
+ type: TIMELINE_EXPAND_REQUEST,
+ timeline,
+ skipLoading: !isLoadingMore,
+})
+
+const expandTimelineSuccess = (timeline, statuses, next, partial, isLoadingRecent, isLoadingMore) => ({
+ type: TIMELINE_EXPAND_SUCCESS,
+ timeline,
+ statuses,
+ next,
+ partial,
+ isLoadingRecent,
+ skipLoading: !isLoadingMore,
+})
+
+const expandTimelineFail = (timeline, error, isLoadingMore) => ({
+ type: TIMELINE_EXPAND_FAIL,
+ timeline,
+ error,
+ skipLoading: !isLoadingMore,
+})
+
+/**
+ *
+ */
+export const scrollTopTimeline = (timeline, top) => ({
+ type: TIMELINE_SCROLL_TOP,
+ timeline,
+ top,
+})
+
+/**
+ *
+ */
+export const connectTimeline = (timeline) => ({
+ type: TIMELINE_CONNECT,
+ timeline,
+})
+
+/**
+ *
+ */
+export const disconnectTimeline = (timeline) => ({
+ type: TIMELINE_DISCONNECT,
+ timeline,
+})
+
+/**
+ *
+ */
+export const expandHomeTimeline = ({ maxId } = {}, done = noop) => {
+ return expandTimeline('home', '/api/v1/timelines/home', {
+ max_id: maxId,
+ }, done)
+}
+
+/**
+ *
+ */
+export const expandExploreTimeline = ({ maxId, sortBy } = {}, done = noop) => {
+ return expandTimeline('explore', '/api/v1/timelines/explore', {
+ max_id: maxId,
+ sort_by: sortBy,
+ }, done)
+}
+
+/**
+ *
+ */
+export const expandProTimeline = ({ maxId } = {}, done = noop) => {
+ return expandTimeline('pro', '/api/v1/timelines/pro', {
+ max_id: maxId,
+ }, done)
+}
+
+/**
+ *
+ */
+export const expandCommunityTimeline = ({ maxId, onlyMedia } = {}, done = noop) => {
+ return expandTimeline(`community${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', {
+ max_id: maxId,
+ only_media: !!onlyMedia,
+ }, done)
+}
+
+/**
+ *
+ */
+export const expandAccountTimeline = (accountId, { maxId, withReplies, commentsOnly } = {}) => {
+ let key = `account:${accountId}${withReplies ? ':with_replies' : ''}${commentsOnly ? ':comments_only' : ''}`
+ return expandTimeline(key, `/api/v1/accounts/${accountId}/statuses`, {
+ only_comments: commentsOnly,
+ exclude_replies: (!withReplies && !commentsOnly),
+ max_id: maxId,
+ })
+}
+
+/**
+ *
+ */
+export const expandAccountFeaturedTimeline = (accountId) => {
+ return expandTimeline(`account:${accountId}:pinned`, `/api/v1/accounts/${accountId}/statuses`, {
+ pinned: true,
+ })
+}
+
+/**
+ *
+ */
+export const expandAccountMediaTimeline = (accountId, { maxId, limit, mediaType } = {}) => {
+ return expandTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, {
+ max_id: maxId,
+ only_media: true,
+ limit: limit || 20,
+ media_type: mediaType
+ })
+}
+
+/**
+ *
+ */
+export const expandListTimeline = (id, { maxId } = {}, done = noop) => {
+ return expandTimeline(`list:${id}`, `/api/v1/timelines/list/${id}`, {
+ max_id: maxId,
+ }, done)
+}
+
+/**
+ *
+ */
+export const expandGroupTimeline = (id, { sortBy, maxId, onlyMedia } = {}, done = noop) => {
+ return expandTimeline(`group:${id}`, `/api/v1/timelines/group/${id}`, {
+ sort_by: sortBy,
+ max_id: maxId,
+ only_media: onlyMedia
+ }, done)
+}
+
+/**
+ *
+ */
+export const expandGroupFeaturedTimeline = (groupId, done = noop) => {
+ return expandTimeline(`group:${groupId}:pinned`, `/api/v1/timelines/group_pins/${groupId}`, {}, done)
+}
+
+/**
+ *
+ */
+export const expandGroupCollectionTimeline = (collectionType, { sortBy, maxId } = {}, done = noop) => {
+ return expandTimeline(`group_collection:${collectionType}`, `/api/v1/timelines/group_collection/${collectionType}`, {
+ sort_by: sortBy,
+ max_id: maxId,
+ }, done)
+}
+
+/**
+ *
+ */
+export const expandLinkTimeline = (linkId, { maxId } = {}, done = noop) => {
+ return expandTimeline(`link:${linkId}`, `/api/v1/timelines/preview_card/${linkId}`, {
+ max_id: maxId,
+ }, done)
+}
+
+/**
+ *
+ */
+export const expandHashtagTimeline = (hashtag, { maxId, tags } = {}, done = noop) => {
return expandTimeline(`hashtag:${hashtag}`, `/api/v1/timelines/tag/${hashtag}`, {
max_id: maxId,
any: parseTags(tags, 'any'),
all: parseTags(tags, 'all'),
none: parseTags(tags, 'none'),
- }, done);
-};
-
-export function expandTimelineRequest(timeline, isLoadingMore) {
- return {
- type: TIMELINE_EXPAND_REQUEST,
- timeline,
- skipLoading: !isLoadingMore,
- };
-};
-
-export function expandTimelineSuccess(timeline, statuses, next, partial, isLoadingRecent, isLoadingMore) {
- return {
- type: TIMELINE_EXPAND_SUCCESS,
- timeline,
- statuses,
- next,
- partial,
- isLoadingRecent,
- skipLoading: !isLoadingMore,
- };
-};
-
-export function expandTimelineFail(timeline, error, isLoadingMore) {
- return {
- type: TIMELINE_EXPAND_FAIL,
- timeline,
- error,
- skipLoading: !isLoadingMore,
- };
-};
-
-export function connectTimeline(timeline) {
- return {
- type: TIMELINE_CONNECT,
- timeline,
- };
-};
-
-export function disconnectTimeline(timeline) {
- return {
- type: TIMELINE_DISCONNECT,
- timeline,
- };
-};
-
-export function scrollTopTimeline(timeline, top) {
- return {
- type: TIMELINE_SCROLL_TOP,
- timeline,
- top,
- };
-};
+ }, done)
+}
diff --git a/app/javascript/gabsocial/components/account.js b/app/javascript/gabsocial/components/account.js
index 3a771d74..45f17804 100644
--- a/app/javascript/gabsocial/components/account.js
+++ b/app/javascript/gabsocial/components/account.js
@@ -80,7 +80,7 @@ class Account extends ImmutablePureComponent {
) :
- const avatarSize = compact ? 42 : 52
+ const avatarSize = compact ? 40 : 52
const dismissBtn = !showDismiss ? null : (