Commiting
This commit is contained in:
parent
fb612f60c8
commit
b4e370d3d3
|
@ -1,8 +1,8 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::BaseController < ApplicationController
|
class Api::BaseController < ApplicationController
|
||||||
DEFAULT_STATUSES_LIMIT = 18
|
DEFAULT_STATUSES_LIMIT = 20
|
||||||
DEFAULT_ACCOUNTS_LIMIT = 40
|
DEFAULT_ACCOUNTS_LIMIT = 20
|
||||||
|
|
||||||
include RateLimitHeaders
|
include RateLimitHeaders
|
||||||
|
|
||||||
|
@ -82,8 +82,8 @@ class Api::BaseController < ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_empty
|
def render_empty_success(message = nil)
|
||||||
render json: {}, status: 200
|
render json: { success: true, error: false, message: message }, status: 200
|
||||||
end
|
end
|
||||||
|
|
||||||
def authorize_if_got_token!(*scopes)
|
def authorize_if_got_token!(*scopes)
|
||||||
|
|
|
@ -27,7 +27,7 @@ class Api::V1::FiltersController < Api::BaseController
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
@filter.destroy!
|
@filter.destroy!
|
||||||
render_empty
|
render_empty_success
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -14,12 +14,12 @@ class Api::V1::FollowRequestsController < Api::BaseController
|
||||||
def authorize
|
def authorize
|
||||||
AuthorizeFollowService.new.call(account, current_account)
|
AuthorizeFollowService.new.call(account, current_account)
|
||||||
NotifyService.new.call(current_account, Follow.find_by(account: account, target_account: current_account))
|
NotifyService.new.call(current_account, Follow.find_by(account: account, target_account: current_account))
|
||||||
render_empty
|
render_empty_success
|
||||||
end
|
end
|
||||||
|
|
||||||
def reject
|
def reject
|
||||||
RejectFollowService.new.call(account, current_account)
|
RejectFollowService.new.call(account, current_account)
|
||||||
render_empty
|
render_empty_success
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -19,29 +19,26 @@ class Api::V1::Groups::AccountsController < Api::BaseController
|
||||||
def create
|
def create
|
||||||
authorize @group, :join?
|
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
|
render json: { error: true, message: 'Unable to join group. Incorrect password.' }, status: 422
|
||||||
end
|
else
|
||||||
|
|
||||||
if @group.is_private
|
if @group.is_private
|
||||||
@group.join_requests << current_account
|
@group.join_requests << current_account
|
||||||
else
|
else
|
||||||
@group.accounts << current_account
|
@group.accounts << current_account
|
||||||
|
|
||||||
if current_user.allows_group_in_home_feed?
|
|
||||||
current_user.force_regeneration!
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
render json: @group, serializer: REST::GroupRelationshipSerializer, relationships: relationships
|
render json: @group, serializer: REST::GroupRelationshipSerializer, relationships: relationships
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
authorize @group, :update_account?
|
authorize @group, :update_account?
|
||||||
|
|
||||||
@account = @group.accounts.find(params[:account_id])
|
@account = @group.accounts.find(params[:account_id])
|
||||||
GroupAccount.where(group: @group, account: @account).update(group_account_params)
|
GroupAccount.where(group: @group, account: @account).update(group_account_params)
|
||||||
render_empty
|
render_empty_success
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
@ -51,9 +48,6 @@ class Api::V1::Groups::AccountsController < Api::BaseController
|
||||||
else
|
else
|
||||||
authorize @group, :leave?
|
authorize @group, :leave?
|
||||||
GroupAccount.where(group: @group, account_id: current_account.id).destroy_all
|
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
|
end
|
||||||
|
|
||||||
render json: @group, serializer: REST::GroupRelationshipSerializer, relationships: relationships
|
render json: @group, serializer: REST::GroupRelationshipSerializer, relationships: relationships
|
||||||
|
|
|
@ -11,24 +11,28 @@ class Api::V1::Groups::PinsController < Api::BaseController
|
||||||
def create
|
def create
|
||||||
authorize @group, :update?
|
authorize @group, :update?
|
||||||
|
|
||||||
|
pin = GroupPinnedStatus.find_by(group: @group, status: @status)
|
||||||
|
if pin.nil?
|
||||||
GroupPinnedStatus.create!(group: @group, status: @status)
|
GroupPinnedStatus.create!(group: @group, status: @status)
|
||||||
render json: @status, serializer: REST::StatusSerializer
|
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
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
# is status pinned by user of group?
|
render json: @status, serializer: REST::StatusGroupPinnedSerializer, group_id: @group.id
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
authorize @group, :update?
|
authorize @group, :update?
|
||||||
|
|
||||||
pin = GroupPinnedStatus.find_by(group: @group, status: @status)
|
pin = GroupPinnedStatus.find_by(group: @group, status: @status)
|
||||||
|
|
||||||
if pin
|
if pin
|
||||||
pin.destroy!
|
pin.destroy!
|
||||||
end
|
end
|
||||||
|
|
||||||
render json: @status, serializer: REST::StatusSerializer
|
render json: @status, serializer: REST::StatusGroupPinnedSerializer, group_id: @group.id
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -23,7 +23,7 @@ class Api::V1::Groups::RemovedAccountsController < Api::BaseController
|
||||||
@account = @group.accounts.find(params[:account_id])
|
@account = @group.accounts.find(params[:account_id])
|
||||||
@group.removed_accounts << @account
|
@group.removed_accounts << @account
|
||||||
GroupAccount.where(group: @group, account: @account).destroy_all
|
GroupAccount.where(group: @group, account: @account).destroy_all
|
||||||
render_empty
|
render_empty_success
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
@ -31,7 +31,7 @@ class Api::V1::Groups::RemovedAccountsController < Api::BaseController
|
||||||
|
|
||||||
@account = @group.removed_accounts.find(params[:account_id])
|
@account = @group.removed_accounts.find(params[:account_id])
|
||||||
GroupRemovedAccount.where(group: @group, account: @account).destroy_all
|
GroupRemovedAccount.where(group: @group, account: @account).destroy_all
|
||||||
render_empty
|
render_empty_success
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -16,12 +16,12 @@ class Api::V1::GroupsController < Api::BaseController
|
||||||
@groups = Group.where(id: @groupIds).limit(150).all
|
@groups = Group.where(id: @groupIds).limit(150).all
|
||||||
when 'new'
|
when 'new'
|
||||||
if !current_user
|
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
|
end
|
||||||
@groups = Group.where(is_archived: false).limit(24).order('created_at DESC').all
|
@groups = Group.where(is_archived: false).limit(24).order('created_at DESC').all
|
||||||
when 'member'
|
when 'member'
|
||||||
if !current_user
|
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
|
end
|
||||||
@groups = Group.joins(:group_accounts).where(is_archived: false, group_accounts: { account: current_account }).order('group_accounts.id DESC').all
|
@groups = Group.joins(:group_accounts).where(is_archived: false, group_accounts: { account: current_account }).order('group_accounts.id DESC').all
|
||||||
when 'admin'
|
when 'admin'
|
||||||
|
@ -36,7 +36,7 @@ class Api::V1::GroupsController < Api::BaseController
|
||||||
|
|
||||||
def by_category
|
def by_category
|
||||||
if !current_user
|
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
|
end
|
||||||
|
|
||||||
@groupCategory = nil
|
@groupCategory = nil
|
||||||
|
@ -54,7 +54,7 @@ class Api::V1::GroupsController < Api::BaseController
|
||||||
|
|
||||||
def by_tag
|
def by_tag
|
||||||
if !current_user
|
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
|
end
|
||||||
|
|
||||||
@groups = []
|
@groups = []
|
||||||
|
@ -94,7 +94,7 @@ class Api::V1::GroupsController < Api::BaseController
|
||||||
|
|
||||||
@group.is_archived = true
|
@group.is_archived = true
|
||||||
@group.save!
|
@group.save!
|
||||||
render_empty
|
render_empty_success
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy_status
|
def destroy_status
|
||||||
|
@ -102,7 +102,7 @@ class Api::V1::GroupsController < Api::BaseController
|
||||||
|
|
||||||
status = Status.find(params[:status_id])
|
status = Status.find(params[:status_id])
|
||||||
GroupUnlinkStatusService.new.call(current_account, @group, status)
|
GroupUnlinkStatusService.new.call(current_account, @group, status)
|
||||||
render_empty
|
render_empty_success
|
||||||
end
|
end
|
||||||
|
|
||||||
def approve_status
|
def approve_status
|
||||||
|
@ -110,7 +110,7 @@ class Api::V1::GroupsController < Api::BaseController
|
||||||
|
|
||||||
status = Status.find(params[:status_id])
|
status = Status.find(params[:status_id])
|
||||||
GroupApproveStatusService.new.call(current_account, @group, status)
|
GroupApproveStatusService.new.call(current_account, @group, status)
|
||||||
render_empty
|
render_empty_success
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -21,12 +21,12 @@ class Api::V1::Lists::AccountsController < Api::BaseController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
render_empty
|
render_empty_success
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
ListAccount.where(list: @list, account_id: account_ids).destroy_all
|
ListAccount.where(list: @list, account_id: account_ids).destroy_all
|
||||||
render_empty
|
render_empty_success
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -28,7 +28,7 @@ class Api::V1::ListsController < Api::BaseController
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
@list.destroy!
|
@list.destroy!
|
||||||
render_empty
|
render_empty_success
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -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
|
|
@ -21,12 +21,12 @@ class Api::V1::NotificationsController < Api::BaseController
|
||||||
|
|
||||||
def clear
|
def clear
|
||||||
current_account.notifications.delete_all
|
current_account.notifications.delete_all
|
||||||
render_empty
|
render_empty_success
|
||||||
end
|
end
|
||||||
|
|
||||||
def mark_read
|
def mark_read
|
||||||
current_account.notifications.find(params[:id]).mark_read!
|
current_account.notifications.find(params[:id]).mark_read!
|
||||||
render_empty
|
render_empty_success
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -26,7 +26,7 @@ class Api::V1::ScheduledStatusesController < Api::BaseController
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
@status.destroy!
|
@status.destroy!
|
||||||
render_empty
|
render_empty_success
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -9,14 +9,15 @@ class Api::V1::Statuses::BookmarksController < Api::BaseController
|
||||||
def create
|
def create
|
||||||
if current_user.account.is_pro
|
if current_user.account.is_pro
|
||||||
@status = bookmarked_status
|
@status = bookmarked_status
|
||||||
render json: @status, serializer: REST::StatusSerializer
|
render json: @status, serializer: REST::StatusBookmarkedSerializer
|
||||||
else
|
else
|
||||||
render json: { error: 'You need to be a GabPRO member to access this' }, status: 422
|
render json: { error: 'You need to be a GabPRO member to access this' }, status: 422
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
# is status bookmarked by user?
|
@status = requested_status
|
||||||
|
render json: @status, serializer: REST::StatusBookmarkedSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
@ -27,7 +28,7 @@ class Api::V1::Statuses::BookmarksController < Api::BaseController
|
||||||
bookmark = StatusBookmark.find_by!(account: current_user.account, status: @status)
|
bookmark = StatusBookmark.find_by!(account: current_user.account, status: @status)
|
||||||
bookmark.destroy!
|
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
|
else
|
||||||
render json: { error: 'You need to be a GabPRO member to access this' }, status: 422
|
render json: { error: 'You need to be a GabPRO member to access this' }, status: 422
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,7 +8,6 @@ class Api::V1::Statuses::FavouritesController < Api::BaseController
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@status = favourited_status
|
@status = favourited_status
|
||||||
puts "tilly -- status: " + @status.inspect
|
|
||||||
render json: @status, serializer: REST::StatusStatSerializer
|
render json: @status, serializer: REST::StatusStatSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -18,7 +17,10 @@ class Api::V1::Statuses::FavouritesController < Api::BaseController
|
||||||
|
|
||||||
UnfavouriteWorker.perform_async(current_user.account_id, @status.id)
|
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
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -8,12 +8,17 @@ class Api::V1::Statuses::PinsController < Api::BaseController
|
||||||
before_action :set_status
|
before_action :set_status
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
pin = StatusPin.find_by(account: current_account, status: @status)
|
||||||
|
if pin.nil?
|
||||||
StatusPin.create!(account: current_account, status: @status)
|
StatusPin.create!(account: current_account, status: @status)
|
||||||
render json: @status, serializer: REST::StatusSerializer
|
render json: @status, serializer: REST::StatusPinnedSerializer
|
||||||
|
else
|
||||||
|
return render json: { error: 'Status is already pinned' }, status: 500
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
# is status pinned by user?
|
render json: @status, serializer: REST::StatusPinnedSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
@ -23,7 +28,7 @@ class Api::V1::Statuses::PinsController < Api::BaseController
|
||||||
pin.destroy!
|
pin.destroy!
|
||||||
end
|
end
|
||||||
|
|
||||||
render json: @status, serializer: REST::StatusSerializer
|
render json: @status, serializer: REST::StatusPinnedSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::Statuses::RepostedByAccountsController < Api::BaseController
|
class Api::V1::Statuses::RebloggedByAccountsController < Api::BaseController
|
||||||
include Authorization
|
include Authorization
|
||||||
|
|
||||||
before_action -> { authorize_if_got_token! :read, :'read:accounts' }
|
before_action -> { authorize_if_got_token! :read, :'read:accounts' }
|
||||||
|
@ -36,13 +36,13 @@ class Api::V1::Statuses::RepostedByAccountsController < Api::BaseController
|
||||||
|
|
||||||
def next_path
|
def next_path
|
||||||
if records_continue?
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
def prev_path
|
def prev_path
|
||||||
unless @accounts.empty?
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -7,22 +7,25 @@ class Api::V1::Statuses::ReblogsController < Api::BaseController
|
||||||
before_action :require_user!
|
before_action :require_user!
|
||||||
|
|
||||||
def create
|
def create
|
||||||
if !current_user.account.local? || !status_for_reblog.local
|
@relog = status_for_reblog
|
||||||
return render json: { error: 'Invalid action' }, status: 422
|
ReblogService.new.call(current_user.account, @relog, reblog_params)
|
||||||
end
|
render json: @relog, serializer: REST::StatusStatSerializer
|
||||||
|
|
||||||
@status = ReblogService.new.call(current_user.account, status_for_reblog, reblog_params)
|
|
||||||
render json: @status, serializer: REST::StatusSerializer
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
@status = status_for_destroy.reblog
|
@my_relog = status_for_destroy
|
||||||
@reblogs_map = { @status.id => false }
|
@original_status = @my_relog.reblog
|
||||||
|
|
||||||
authorize status_for_destroy, :unreblog?
|
authorize @my_relog, :unreblog?
|
||||||
RemovalWorker.perform_async(status_for_destroy.id)
|
|
||||||
|
|
||||||
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
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -23,7 +23,7 @@ class Api::V1::SuggestionsController < Api::BaseController
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
PotentialFriendshipTracker.remove(current_account.id, params[:id])
|
PotentialFriendshipTracker.remove(current_account.id, params[:id])
|
||||||
render_empty
|
render_empty_success
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,7 +7,7 @@ class Api::Web::SettingsController < Api::Web::BaseController
|
||||||
setting.data = params[:data]
|
setting.data = params[:data]
|
||||||
setting.save!
|
setting.save!
|
||||||
|
|
||||||
render_empty
|
render_empty_success
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -66,6 +66,7 @@ module SignatureVerification
|
||||||
|
|
||||||
return account unless verify_signature(account, signature, compare_signed_string).nil?
|
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}"
|
@signature_verification_failure_reason = "Verification failed for #{account.username}@#{account.domain} #{account.uri}"
|
||||||
@signed_request_account = nil
|
@signed_request_account = nil
|
||||||
end
|
end
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -33,20 +33,17 @@ export const fetchBookmarkedStatuses = () => (dispatch, getState) => {
|
||||||
|
|
||||||
const fetchBookmarkedStatusesRequest = () => ({
|
const fetchBookmarkedStatusesRequest = () => ({
|
||||||
type: BOOKMARKED_STATUSES_FETCH_REQUEST,
|
type: BOOKMARKED_STATUSES_FETCH_REQUEST,
|
||||||
skipLoading: true,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const fetchBookmarkedStatusesSuccess = (statuses, next) => ({
|
const fetchBookmarkedStatusesSuccess = (statuses, next) => ({
|
||||||
type: BOOKMARKED_STATUSES_FETCH_SUCCESS,
|
type: BOOKMARKED_STATUSES_FETCH_SUCCESS,
|
||||||
statuses,
|
statuses,
|
||||||
next,
|
next,
|
||||||
skipLoading: true,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const fetchBookmarkedStatusesFail = (error) => ({
|
const fetchBookmarkedStatusesFail = (error) => ({
|
||||||
type: BOOKMARKED_STATUSES_FETCH_FAIL,
|
type: BOOKMARKED_STATUSES_FETCH_FAIL,
|
||||||
error,
|
error,
|
||||||
skipLoading: true,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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 })
|
||||||
|
}
|
|
@ -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,
|
||||||
|
})
|
|
@ -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,
|
||||||
|
})
|
|
@ -19,6 +19,7 @@ import {
|
||||||
import { defineMessages } from 'react-intl'
|
import { defineMessages } from 'react-intl'
|
||||||
import { openModal, closeModal } from './modal'
|
import { openModal, closeModal } from './modal'
|
||||||
import {
|
import {
|
||||||
|
MODAL_COMPOSE,
|
||||||
STATUS_EXPIRATION_OPTION_5_MINUTES,
|
STATUS_EXPIRATION_OPTION_5_MINUTES,
|
||||||
STATUS_EXPIRATION_OPTION_60_MINUTES,
|
STATUS_EXPIRATION_OPTION_60_MINUTES,
|
||||||
STATUS_EXPIRATION_OPTION_6_HOURS,
|
STATUS_EXPIRATION_OPTION_6_HOURS,
|
||||||
|
@ -90,19 +91,43 @@ const messages = defineMessages({
|
||||||
uploadErrorPoll: { id: 'upload_error.poll', defaultMessage: 'File upload not allowed with polls.' },
|
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 (history !== null) {
|
||||||
if (!getState().getIn(['compose', 'mounted']) && window.innerWidth < COMPOSE_PANEL_BREAKPOINT) {
|
dispatch(updateTagHistory(history))
|
||||||
routerHistory.push('/posts/new')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function changeCompose(text, markdown, replyId, isStandalone, caretPosition) {
|
/**
|
||||||
return function (dispatch, getState) {
|
*
|
||||||
|
*/
|
||||||
|
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)
|
||||||
|
|
||||||
|
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 reduxReplyToId = getState().getIn(['compose', 'in_reply_to'])
|
||||||
const existingText = getState().getIn(['compose', 'text']).trim()
|
const existingText = getState().getIn(['compose', 'text']).trim()
|
||||||
const isModalOpen = getState().getIn(['modal', 'modalType']) === 'COMPOSE' || isStandalone
|
const isModalOpen = getState().getIn(['modal', 'modalType']) === MODAL_COMPOSE || isStandalone
|
||||||
|
|
||||||
let status
|
let status
|
||||||
if (!!replyId) {
|
if (!!replyId) {
|
||||||
|
@ -116,7 +141,7 @@ export function changeCompose(text, markdown, replyId, isStandalone, caretPositi
|
||||||
if (existingText.length === 0 && text.trim().length > 0) {
|
if (existingText.length === 0 && text.trim().length > 0) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: COMPOSE_REPLY,
|
type: COMPOSE_REPLY,
|
||||||
status: status,
|
status,
|
||||||
text: text,
|
text: text,
|
||||||
})
|
})
|
||||||
} else if (existingText.length > 0 && text.trim().length > 0) {
|
} else if (existingText.length > 0 && text.trim().length > 0) {
|
||||||
|
@ -126,7 +151,7 @@ export function changeCompose(text, markdown, replyId, isStandalone, caretPositi
|
||||||
onConfirm: () => {
|
onConfirm: () => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: COMPOSE_REPLY,
|
type: COMPOSE_REPLY,
|
||||||
status: status,
|
status,
|
||||||
})
|
})
|
||||||
dispatch({
|
dispatch({
|
||||||
type: COMPOSE_CHANGE,
|
type: COMPOSE_CHANGE,
|
||||||
|
@ -180,67 +205,74 @@ export function changeCompose(text, markdown, replyId, isStandalone, caretPositi
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
export function replyCompose(status, router, showModal) {
|
/**
|
||||||
return (dispatch) => {
|
*
|
||||||
|
*/
|
||||||
|
export const replyCompose = (status, router, showModal) => (dispatch) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: COMPOSE_REPLY,
|
type: COMPOSE_REPLY,
|
||||||
status: status,
|
status,
|
||||||
});
|
})
|
||||||
|
|
||||||
if (isMobile(window.innerWidth)) {
|
if (isMobile(window.innerWidth)) {
|
||||||
router.history.push('/compose')
|
router.history.push('/compose')
|
||||||
} else {
|
} else {
|
||||||
if (showModal) {
|
if (showModal) {
|
||||||
dispatch(openModal('COMPOSE'));
|
dispatch(openModal(MODAL_COMPOSE))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export function quoteCompose(status, router) {
|
/**
|
||||||
return (dispatch) => {
|
*
|
||||||
|
*/
|
||||||
|
export const quoteCompose = (status, router) => (dispatch) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: COMPOSE_QUOTE,
|
type: COMPOSE_QUOTE,
|
||||||
status: status,
|
status,
|
||||||
});
|
})
|
||||||
|
|
||||||
if (isMobile(window.innerWidth)) {
|
if (isMobile(window.innerWidth)) {
|
||||||
router.history.push('/compose')
|
router.history.push('/compose')
|
||||||
} else {
|
} else {
|
||||||
dispatch(openModal('COMPOSE'));
|
dispatch(openModal(MODAL_COMPOSE))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export function cancelReplyCompose() {
|
/**
|
||||||
return {
|
*
|
||||||
|
*/
|
||||||
|
export const cancelReplyCompose = () => ({
|
||||||
type: COMPOSE_REPLY_CANCEL,
|
type: COMPOSE_REPLY_CANCEL,
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
export function resetCompose() {
|
/**
|
||||||
return {
|
*
|
||||||
|
*/
|
||||||
|
export const resetCompose = () => ({
|
||||||
type: COMPOSE_RESET,
|
type: COMPOSE_RESET,
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
export function mentionCompose(account) {
|
/**
|
||||||
return (dispatch) => {
|
*
|
||||||
|
*/
|
||||||
|
export const mentionCompose = (account) => (dispatch) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: COMPOSE_MENTION,
|
type: COMPOSE_MENTION,
|
||||||
account: account,
|
account: account,
|
||||||
});
|
})
|
||||||
|
|
||||||
dispatch(openModal('COMPOSE'));
|
dispatch(openModal(MODAL_COMPOSE))
|
||||||
};
|
}
|
||||||
};
|
|
||||||
|
|
||||||
export function handleComposeSubmit(dispatch, getState, response, status) {
|
/**
|
||||||
if (!dispatch || !getState) return;
|
*
|
||||||
|
*/
|
||||||
|
export const 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) {
|
if (isScheduledStatus) {
|
||||||
// dispatch(showAlertForError({
|
// dispatch(showAlertForError({
|
||||||
// response: {
|
// response: {
|
||||||
|
@ -248,38 +280,40 @@ export function handleComposeSubmit(dispatch, getState, response, status) {
|
||||||
// status: 200,
|
// status: 200,
|
||||||
// statusText: 'Successfully scheduled status',
|
// statusText: 'Successfully scheduled status',
|
||||||
// }
|
// }
|
||||||
// }));
|
// }))
|
||||||
dispatch(submitComposeSuccess({ ...response.data }));
|
dispatch(submitComposeSuccess({ ...response.data }))
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch(insertIntoTagHistory(response.data.tags, status));
|
dispatch(insertIntoTagHistory(response.data.tags, status))
|
||||||
dispatch(submitComposeSuccess({ ...response.data }));
|
dispatch(submitComposeSuccess({ ...response.data }))
|
||||||
|
|
||||||
// To make the app more responsive, immediately push the status into the timeline
|
// To make the app more responsive, immediately push the status into the timeline
|
||||||
// : todo : push into comment, reload parent status, etc.
|
// : todo : push into comment, reload parent status, etc.
|
||||||
const insertIfOnline = timelineId => {
|
const insertIfOnline = (timelineId) => {
|
||||||
const timeline = getState().getIn(['timelines', timelineId]);
|
const timeline = getState().getIn(['timelines', timelineId])
|
||||||
|
|
||||||
if (timeline && timeline.get('items').size > 0 && timeline.getIn(['items', 0]) !== null && timeline.get('online')) {
|
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') {
|
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 status = getState().getIn(['compose', 'text'], '')
|
||||||
let markdown = getState().getIn(['compose', 'markdown'], '');
|
let markdown = getState().getIn(['compose', 'markdown'], '')
|
||||||
const media = getState().getIn(['compose', 'media_attachments']);
|
const media = getState().getIn(['compose', 'media_attachments'])
|
||||||
const isPrivateGroup = !!groupId ? getState().getIn(['groups', groupId, 'is_private'], false) : false
|
const isPrivateGroup = !!groupId ? getState().getIn(['groups', groupId, 'is_private'], false) : false
|
||||||
|
|
||||||
const replacer = (match) => {
|
const replacer = (match) => {
|
||||||
|
@ -298,19 +332,19 @@ export function submitCompose(groupId, replyToId = null, router, isStandalone, a
|
||||||
|
|
||||||
const inReplyToId = getState().getIn(['compose', 'in_reply_to'], null) || replyToId
|
const inReplyToId = getState().getIn(['compose', 'in_reply_to'], null) || replyToId
|
||||||
|
|
||||||
dispatch(submitComposeRequest());
|
dispatch(submitComposeRequest())
|
||||||
dispatch(closeModal());
|
dispatch(closeModal())
|
||||||
|
|
||||||
const id = getState().getIn(['compose', 'id']);
|
const id = getState().getIn(['compose', 'id'])
|
||||||
const endpoint = id === null
|
const endpoint = id === null
|
||||||
? '/api/v1/statuses'
|
? '/api/v1/statuses'
|
||||||
: `/api/v1/statuses/${id}`;
|
: `/api/v1/statuses/${id}`
|
||||||
const method = id === null ? 'post' : 'put';
|
const method = id === null ? 'post' : 'put'
|
||||||
|
|
||||||
let scheduled_at = getState().getIn(['compose', 'scheduled_at'], null);
|
let scheduled_at = getState().getIn(['compose', 'scheduled_at'], null)
|
||||||
if (scheduled_at !== null) scheduled_at = moment.utc(scheduled_at).toDate();
|
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) {
|
||||||
if (expires_at === STATUS_EXPIRATION_OPTION_5_MINUTES) {
|
if (expires_at === STATUS_EXPIRATION_OPTION_5_MINUTES) {
|
||||||
|
@ -351,243 +385,220 @@ export function submitCompose(groupId, replyToId = null, router, isStandalone, a
|
||||||
headers: {
|
headers: {
|
||||||
'Idempotency-Key': getState().getIn(['compose', 'idempotencyKey']),
|
'Idempotency-Key': getState().getIn(['compose', 'idempotencyKey']),
|
||||||
},
|
},
|
||||||
}).then(function (response) {
|
}).then((response) => {
|
||||||
handleComposeSubmit(dispatch, getState, response, status);
|
handleComposeSubmit(dispatch, getState, response, status)
|
||||||
}).catch(function (error) {
|
}).catch((error) => {
|
||||||
dispatch(submitComposeFail(error));
|
dispatch(submitComposeFail(error))
|
||||||
});
|
})
|
||||||
};
|
}
|
||||||
};
|
|
||||||
|
|
||||||
export function submitComposeRequest() {
|
const submitComposeRequest = () => ({
|
||||||
return {
|
|
||||||
type: COMPOSE_SUBMIT_REQUEST,
|
type: COMPOSE_SUBMIT_REQUEST,
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
export function submitComposeSuccess(status) {
|
const submitComposeSuccess = (status) => ({
|
||||||
return {
|
|
||||||
type: COMPOSE_SUBMIT_SUCCESS,
|
type: COMPOSE_SUBMIT_SUCCESS,
|
||||||
status: status,
|
status,
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
export function clearCompose() {
|
const submitComposeFail = (error) => ({
|
||||||
return {
|
|
||||||
type: COMPOSE_CLEAR,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export function submitComposeFail(error) {
|
|
||||||
return {
|
|
||||||
type: COMPOSE_SUBMIT_FAIL,
|
type: COMPOSE_SUBMIT_FAIL,
|
||||||
error: error,
|
error,
|
||||||
}
|
})
|
||||||
}
|
|
||||||
|
|
||||||
export function uploadCompose(files) {
|
/**
|
||||||
return function (dispatch, getState) {
|
*
|
||||||
|
*/
|
||||||
|
export const uploadCompose = (files) => (dispatch, getState) => {
|
||||||
if (!me) return
|
if (!me) return
|
||||||
|
|
||||||
const uploadLimit = 4
|
const uploadLimit = 4
|
||||||
const media = getState().getIn(['compose', 'media_attachments'])
|
const media = getState().getIn(['compose', 'media_attachments'])
|
||||||
const pending = getState().getIn(['compose', 'pending_media_attachments'])
|
const pending = getState().getIn(['compose', 'pending_media_attachments'])
|
||||||
const progress = new Array(files.length).fill(0);
|
const progress = new Array(files.length).fill(0)
|
||||||
let total = Array.from(files).reduce((a, v) => a + v.size, 0);
|
let total = Array.from(files).reduce((a, v) => a + v.size, 0)
|
||||||
|
|
||||||
if (files.length + media.size + pending > uploadLimit) {
|
if (files.length + media.size + pending > uploadLimit) {
|
||||||
// dispatch(showAlert(undefined, messages.uploadErrorLimit));
|
// dispatch(showAlert(undefined, messages.uploadErrorLimit))
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getState().getIn(['compose', 'poll'])) {
|
if (getState().getIn(['compose', 'poll'])) {
|
||||||
// dispatch(showAlert(undefined, messages.uploadErrorPoll));
|
// dispatch(showAlert(undefined, messages.uploadErrorPoll))
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch(uploadComposeRequest());
|
dispatch(uploadComposeRequest())
|
||||||
|
|
||||||
for (const [i, f] of Array.from(files).entries()) {
|
for (const [i, f] of Array.from(files).entries()) {
|
||||||
if (media.size + i > 3) break;
|
if (media.size + i > 3) break
|
||||||
|
|
||||||
resizeImage(f).then((file) => {
|
resizeImage(f).then((file) => {
|
||||||
const data = new FormData();
|
const data = new FormData()
|
||||||
data.append('file', file);
|
data.append('file', file)
|
||||||
// Account for disparity in size of original image and resized data
|
// Account for disparity in size of original image and resized data
|
||||||
total += file.size - f.size;
|
total += file.size - f.size
|
||||||
|
|
||||||
return api(getState).post('/api/v1/media', data, {
|
return api(getState).post('/api/v1/media', data, {
|
||||||
onUploadProgress: function({ loaded }){
|
onUploadProgress: ({ loaded }) => {
|
||||||
progress[i] = loaded;
|
progress[i] = loaded
|
||||||
dispatch(uploadComposeProgress(progress.reduce((a, v) => a + v, 0), total));
|
dispatch(uploadComposeProgress(progress.reduce((a, v) => a + v, 0), total))
|
||||||
},
|
},
|
||||||
}).then(({ data }) => dispatch(uploadComposeSuccess(data)));
|
}).then(({ data }) => dispatch(uploadComposeSuccess(data)))
|
||||||
}).catch(error => dispatch(uploadComposeFail(error, true)));
|
}).catch((error) => dispatch(uploadComposeFail(error, true)))
|
||||||
};
|
}
|
||||||
};
|
}
|
||||||
};
|
|
||||||
|
|
||||||
export function changeUploadCompose(id, params) {
|
const uploadComposeRequest = () => ({
|
||||||
return (dispatch, getState) => {
|
|
||||||
if (!me) return;
|
|
||||||
|
|
||||||
dispatch(changeUploadComposeRequest());
|
|
||||||
|
|
||||||
api(getState).put(`/api/v1/media/${id}`, params).then(response => {
|
|
||||||
dispatch(changeUploadComposeSuccess(response.data));
|
|
||||||
}).catch(error => {
|
|
||||||
dispatch(changeUploadComposeFail(id, error));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
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,
|
type: COMPOSE_UPLOAD_REQUEST,
|
||||||
skipLoading: true,
|
})
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export function uploadComposeProgress(loaded, total) {
|
const uploadComposeProgress = (loaded, total) => ({
|
||||||
return {
|
|
||||||
type: COMPOSE_UPLOAD_PROGRESS,
|
type: COMPOSE_UPLOAD_PROGRESS,
|
||||||
loaded: loaded,
|
loaded: loaded,
|
||||||
total: total,
|
total: total,
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
export function uploadComposeSuccess(media) {
|
const uploadComposeSuccess = (media) => ({
|
||||||
return {
|
|
||||||
type: COMPOSE_UPLOAD_SUCCESS,
|
type: COMPOSE_UPLOAD_SUCCESS,
|
||||||
media: media,
|
media: media,
|
||||||
skipLoading: true,
|
})
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export function uploadComposeFail(error) {
|
const uploadComposeFail = (error) => ({
|
||||||
return {
|
|
||||||
type: COMPOSE_UPLOAD_FAIL,
|
type: COMPOSE_UPLOAD_FAIL,
|
||||||
error: error,
|
error,
|
||||||
skipLoading: true,
|
})
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export function undoUploadCompose(media_id) {
|
/**
|
||||||
return {
|
*
|
||||||
|
*/
|
||||||
|
export const changeUploadCompose = (id, params) => (dispatch, getState) => {
|
||||||
|
if (!me) return
|
||||||
|
|
||||||
|
dispatch(changeUploadComposeRequest())
|
||||||
|
|
||||||
|
api(getState).put(`/api/v1/media/${id}`, params).then((response) => {
|
||||||
|
dispatch(changeUploadComposeSuccess(response.data))
|
||||||
|
}).catch((error) => {
|
||||||
|
dispatch(changeUploadComposeFail(id, error))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const changeUploadComposeRequest = () => ({
|
||||||
|
type: COMPOSE_UPLOAD_CHANGE_REQUEST,
|
||||||
|
})
|
||||||
|
|
||||||
|
const changeUploadComposeSuccess = (media) => ({
|
||||||
|
type: COMPOSE_UPLOAD_CHANGE_SUCCESS,
|
||||||
|
media: media,
|
||||||
|
})
|
||||||
|
|
||||||
|
const changeUploadComposeFail = (error, decrement = false) => ({
|
||||||
|
type: COMPOSE_UPLOAD_CHANGE_FAIL,
|
||||||
|
error,
|
||||||
|
decrement: decrement,
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export const undoUploadCompose = (media_id) => ({
|
||||||
type: COMPOSE_UPLOAD_UNDO,
|
type: COMPOSE_UPLOAD_UNDO,
|
||||||
media_id: media_id,
|
media_id: media_id,
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
export function clearComposeSuggestions() {
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export const clearComposeSuggestions = () => {
|
||||||
if (cancelFetchComposeSuggestionsAccounts) {
|
if (cancelFetchComposeSuggestionsAccounts) {
|
||||||
cancelFetchComposeSuggestionsAccounts();
|
cancelFetchComposeSuggestionsAccounts()
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: COMPOSE_SUGGESTIONS_CLEAR,
|
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) => {
|
const fetchComposeSuggestionsAccounts = throttle((dispatch, getState, token) => {
|
||||||
if (cancelFetchComposeSuggestionsAccounts) {
|
if (cancelFetchComposeSuggestionsAccounts) {
|
||||||
cancelFetchComposeSuggestionsAccounts();
|
cancelFetchComposeSuggestionsAccounts()
|
||||||
}
|
}
|
||||||
|
|
||||||
api(getState).get('/api/v1/accounts/search', {
|
api(getState).get('/api/v1/accounts/search', {
|
||||||
cancelToken: new CancelToken(cancel => {
|
cancelToken: new CancelToken(cancel => {
|
||||||
cancelFetchComposeSuggestionsAccounts = cancel;
|
cancelFetchComposeSuggestionsAccounts = cancel
|
||||||
}),
|
}),
|
||||||
params: {
|
params: {
|
||||||
q: token.slice(1),
|
q: token.slice(1),
|
||||||
resolve: false,
|
resolve: false,
|
||||||
limit: 4,
|
limit: 4,
|
||||||
},
|
},
|
||||||
}).then(response => {
|
}).then((response) => {
|
||||||
dispatch(importFetchedAccounts(response.data));
|
dispatch(importFetchedAccounts(response.data))
|
||||||
dispatch(readyComposeSuggestionsAccounts(token, response.data));
|
dispatch(readyComposeSuggestionsAccounts(token, response.data))
|
||||||
}).catch(error => {
|
}).catch((error) => {
|
||||||
if (!isCancel(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 fetchComposeSuggestionsEmojis = (dispatch, getState, token) => {
|
||||||
const results = emojiSearch(token.replace(':', ''), { maxResults: 5 });
|
const results = emojiSearch(token.replace(':', ''), { maxResults: 5 })
|
||||||
dispatch(readyComposeSuggestionsEmojis(token, results));
|
dispatch(readyComposeSuggestionsEmojis(token, results))
|
||||||
};
|
}
|
||||||
|
|
||||||
const fetchComposeSuggestionsTags = (dispatch, getState, token) => {
|
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;
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export function readyComposeSuggestionsEmojis(token, emojis) {
|
const readyComposeSuggestionsEmojis = (token, emojis) => ({
|
||||||
return {
|
|
||||||
type: COMPOSE_SUGGESTIONS_READY,
|
type: COMPOSE_SUGGESTIONS_READY,
|
||||||
token,
|
token,
|
||||||
emojis,
|
emojis,
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
export const readyComposeSuggestionsAccounts = (token, accounts) => ({
|
const readyComposeSuggestionsAccounts = (token, accounts) => ({
|
||||||
type: COMPOSE_SUGGESTIONS_READY,
|
type: COMPOSE_SUGGESTIONS_READY,
|
||||||
token,
|
token,
|
||||||
accounts,
|
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) {
|
if (typeof suggestion === 'object' && suggestion.id) {
|
||||||
completion = suggestion.native || suggestion.colons;
|
completion = suggestion.native || suggestion.colons
|
||||||
startPosition = position - 1;
|
startPosition = position - 1
|
||||||
|
|
||||||
dispatch(useEmoji(suggestion));
|
dispatch(useEmoji(suggestion))
|
||||||
} else if (suggestion[0] === '#') {
|
} else if (suggestion[0] === '#') {
|
||||||
completion = suggestion;
|
completion = suggestion
|
||||||
startPosition = position - 1;
|
startPosition = position - 1
|
||||||
} else {
|
} else {
|
||||||
completion = getState().getIn(['accounts', suggestion, 'acct']);
|
completion = getState().getIn(['accounts', suggestion, 'acct'])
|
||||||
startPosition = position;
|
startPosition = position
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
|
@ -596,138 +607,131 @@ export function selectComposeSuggestion(position, token, suggestion, path) {
|
||||||
token,
|
token,
|
||||||
completion,
|
completion,
|
||||||
path,
|
path,
|
||||||
});
|
})
|
||||||
};
|
}
|
||||||
};
|
|
||||||
|
|
||||||
export function updateSuggestionTags(token) {
|
/**
|
||||||
return {
|
*
|
||||||
|
*/
|
||||||
|
export const updateSuggestionTags = (token) => ({
|
||||||
type: COMPOSE_SUGGESTION_TAGS_UPDATE,
|
type: COMPOSE_SUGGESTION_TAGS_UPDATE,
|
||||||
token,
|
token,
|
||||||
};
|
})
|
||||||
}
|
|
||||||
|
|
||||||
export function updateTagHistory(tags) {
|
/**
|
||||||
return {
|
*
|
||||||
|
*/
|
||||||
|
export const updateTagHistory = (tags) => ({
|
||||||
type: COMPOSE_TAG_HISTORY_UPDATE,
|
type: COMPOSE_TAG_HISTORY_UPDATE,
|
||||||
tags,
|
tags,
|
||||||
};
|
})
|
||||||
}
|
|
||||||
|
|
||||||
export function hydrateCompose() {
|
/**
|
||||||
return (dispatch, getState) => {
|
*
|
||||||
const me = getState().getIn(['meta', 'me']);
|
*/
|
||||||
const history = tagHistory.get(me);
|
export const mountCompose = () => ({
|
||||||
|
|
||||||
if (history !== null) {
|
|
||||||
dispatch(updateTagHistory(history));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
names.push(...intersectedOldHistory.toJS());
|
|
||||||
|
|
||||||
const newHistory = names.slice(0, 1000);
|
|
||||||
|
|
||||||
tagHistory.set(me, newHistory);
|
|
||||||
dispatch(updateTagHistory(newHistory));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function mountCompose() {
|
|
||||||
return {
|
|
||||||
type: COMPOSE_MOUNT,
|
type: COMPOSE_MOUNT,
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
export function unmountCompose() {
|
/**
|
||||||
return {
|
*
|
||||||
|
*/
|
||||||
|
export const unmountCompose = () => ({
|
||||||
type: COMPOSE_UNMOUNT,
|
type: COMPOSE_UNMOUNT,
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
export function changeComposeSensitivity() {
|
/**
|
||||||
return {
|
*
|
||||||
|
*/
|
||||||
|
export const clearCompose = () => ({
|
||||||
|
type: COMPOSE_CLEAR,
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export const changeComposeSensitivity = () => ({
|
||||||
type: COMPOSE_SENSITIVITY_CHANGE,
|
type: COMPOSE_SENSITIVITY_CHANGE,
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
export function changeComposeSpoilerness() {
|
/**
|
||||||
return {
|
*
|
||||||
|
*/
|
||||||
|
export const changeComposeSpoilerness = () => ({
|
||||||
type: COMPOSE_SPOILERNESS_CHANGE,
|
type: COMPOSE_SPOILERNESS_CHANGE,
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
export function changeComposeSpoilerText(text) {
|
/**
|
||||||
return {
|
*
|
||||||
|
*/
|
||||||
|
export const changeComposeSpoilerText = (text) => ({
|
||||||
type: COMPOSE_SPOILER_TEXT_CHANGE,
|
type: COMPOSE_SPOILER_TEXT_CHANGE,
|
||||||
text,
|
text,
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
export function changeComposeVisibility(value) {
|
/**
|
||||||
return {
|
*
|
||||||
|
*/
|
||||||
|
export const changeComposeVisibility = (value) => ({
|
||||||
type: COMPOSE_VISIBILITY_CHANGE,
|
type: COMPOSE_VISIBILITY_CHANGE,
|
||||||
value,
|
value,
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
export function insertEmojiCompose(emoji, needsSpace) {
|
/**
|
||||||
return {
|
*
|
||||||
|
*/
|
||||||
|
export const insertEmojiCompose = (emoji, needsSpace) => ({
|
||||||
type: COMPOSE_EMOJI_INSERT,
|
type: COMPOSE_EMOJI_INSERT,
|
||||||
emoji,
|
emoji,
|
||||||
needsSpace,
|
needsSpace,
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
export function changeComposing(value) {
|
/**
|
||||||
return {
|
*
|
||||||
|
*/
|
||||||
|
export const changeComposing = (value) => ({
|
||||||
type: COMPOSE_COMPOSING_CHANGE,
|
type: COMPOSE_COMPOSING_CHANGE,
|
||||||
value,
|
value,
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
export function addPoll() {
|
/**
|
||||||
return {
|
*
|
||||||
|
*/
|
||||||
|
export const addPoll = () => ({
|
||||||
type: COMPOSE_POLL_ADD,
|
type: COMPOSE_POLL_ADD,
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
export function removePoll() {
|
/**
|
||||||
return {
|
*
|
||||||
|
*/
|
||||||
|
export const removePoll = () => ({
|
||||||
type: COMPOSE_POLL_REMOVE,
|
type: COMPOSE_POLL_REMOVE,
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
export function addPollOption(title) {
|
/**
|
||||||
return {
|
*
|
||||||
|
*/
|
||||||
|
export const addPollOption = (title) => ({
|
||||||
type: COMPOSE_POLL_OPTION_ADD,
|
type: COMPOSE_POLL_OPTION_ADD,
|
||||||
title,
|
title,
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
export function changePollOption(index, title) {
|
/**
|
||||||
return {
|
*
|
||||||
|
*/
|
||||||
|
export const changePollOption = (index, title) => ({
|
||||||
type: COMPOSE_POLL_OPTION_CHANGE,
|
type: COMPOSE_POLL_OPTION_CHANGE,
|
||||||
index,
|
index,
|
||||||
title,
|
title,
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
export function removePollOption(index) {
|
/**
|
||||||
return {
|
*
|
||||||
|
*/
|
||||||
|
export const removePollOption = (index) => ({
|
||||||
type: COMPOSE_POLL_OPTION_REMOVE,
|
type: COMPOSE_POLL_OPTION_REMOVE,
|
||||||
index,
|
index,
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
|
@ -16,17 +16,14 @@ export const fetchCustomEmojis = () => (dispatch, getState) => {
|
||||||
|
|
||||||
const fetchCustomEmojisRequest = () => ({
|
const fetchCustomEmojisRequest = () => ({
|
||||||
type: CUSTOM_EMOJIS_FETCH_REQUEST,
|
type: CUSTOM_EMOJIS_FETCH_REQUEST,
|
||||||
skipLoading: true,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const fetchCustomEmojisSuccess = (custom_emojis) => ({
|
const fetchCustomEmojisSuccess = (custom_emojis) => ({
|
||||||
type: CUSTOM_EMOJIS_FETCH_SUCCESS,
|
type: CUSTOM_EMOJIS_FETCH_SUCCESS,
|
||||||
custom_emojis,
|
custom_emojis,
|
||||||
skipLoading: true,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const fetchCustomEmojisFail = (error) => ({
|
const fetchCustomEmojisFail = (error) => ({
|
||||||
type: CUSTOM_EMOJIS_FETCH_FAIL,
|
type: CUSTOM_EMOJIS_FETCH_FAIL,
|
||||||
error,
|
error,
|
||||||
skipLoading: true,
|
|
||||||
})
|
})
|
||||||
|
|
|
@ -33,20 +33,17 @@ export const fetchFavoritedStatuses = () => (dispatch, getState) => {
|
||||||
|
|
||||||
const fetchFavoritedStatusesRequest = () => ({
|
const fetchFavoritedStatusesRequest = () => ({
|
||||||
type: FAVORITED_STATUSES_FETCH_REQUEST,
|
type: FAVORITED_STATUSES_FETCH_REQUEST,
|
||||||
skipLoading: true,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const fetchFavoritedStatusesSuccess = (statuses, next) => ({
|
const fetchFavoritedStatusesSuccess = (statuses, next) => ({
|
||||||
type: FAVORITED_STATUSES_FETCH_SUCCESS,
|
type: FAVORITED_STATUSES_FETCH_SUCCESS,
|
||||||
statuses,
|
statuses,
|
||||||
next,
|
next,
|
||||||
skipLoading: true,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const fetchFavoritedStatusesFail = (error) => ({
|
const fetchFavoritedStatusesFail = (error) => ({
|
||||||
type: FAVORITED_STATUSES_FETCH_FAIL,
|
type: FAVORITED_STATUSES_FETCH_FAIL,
|
||||||
error,
|
error,
|
||||||
skipLoading: true,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -23,18 +23,15 @@ export const fetchFilters = () => (dispatch, getState) => {
|
||||||
|
|
||||||
const fetchFiltersRequest = () => ({
|
const fetchFiltersRequest = () => ({
|
||||||
type: FILTERS_FETCH_REQUEST,
|
type: FILTERS_FETCH_REQUEST,
|
||||||
skipLoading: true,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const fetchFiltersSuccess = (filters) => ({
|
const fetchFiltersSuccess = (filters) => ({
|
||||||
type: FILTERS_FETCH_SUCCESS,
|
type: FILTERS_FETCH_SUCCESS,
|
||||||
filters,
|
filters,
|
||||||
skipLoading: true,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const fetchFiltersFail = (err) => ({
|
const fetchFiltersFail = (err) => ({
|
||||||
type: FILTERS_FETCH_FAIL,
|
type: FILTERS_FETCH_FAIL,
|
||||||
err,
|
err,
|
||||||
skipLoading: true,
|
|
||||||
skipAlert: true,
|
skipAlert: true,
|
||||||
})
|
})
|
File diff suppressed because it is too large
Load Diff
|
@ -14,7 +14,10 @@ export const STATUSES_IMPORT = 'STATUSES_IMPORT'
|
||||||
export const POLLS_IMPORT = 'POLLS_IMPORT'
|
export const POLLS_IMPORT = 'POLLS_IMPORT'
|
||||||
export const ACCOUNT_FETCH_FAIL_FOR_USERNAME_LOOKUP = 'ACCOUNT_FETCH_FAIL_FOR_USERNAME_LOOKUP'
|
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)) {
|
if (array.every(element => element.id !== object.id)) {
|
||||||
array.push(object);
|
array.push(object);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,20 +5,26 @@ import { expandSpoilers } from '../../initial_state'
|
||||||
|
|
||||||
const domParser = new DOMParser()
|
const domParser = new DOMParser()
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
const makeEmojiMap = record => record.emojis.reduce((obj, emoji) => {
|
const makeEmojiMap = record => record.emojis.reduce((obj, emoji) => {
|
||||||
obj[`:${emoji.shortcode}:`] = emoji;
|
obj[`:${emoji.shortcode}:`] = emoji
|
||||||
return obj;
|
return obj
|
||||||
}, {});
|
}, {})
|
||||||
|
|
||||||
export function normalizeAccount(account) {
|
/**
|
||||||
account = { ...account };
|
*
|
||||||
|
*/
|
||||||
|
export const normalizeAccount = (account) => {
|
||||||
|
account = { ...account }
|
||||||
|
|
||||||
const emojiMap = makeEmojiMap(account);
|
const emojiMap = makeEmojiMap(account)
|
||||||
const displayName = account.display_name.trim().length === 0 ? account.username : account.display_name;
|
const displayName = account.display_name.trim().length === 0 ? account.username : account.display_name
|
||||||
|
|
||||||
account.display_name_html = emojify(escapeTextContentForBrowser(displayName), emojiMap);
|
account.display_name_html = emojify(escapeTextContentForBrowser(displayName), emojiMap)
|
||||||
account.display_name_plain = emojify(escapeTextContentForBrowser(displayName), emojiMap, true);
|
account.display_name_plain = emojify(escapeTextContentForBrowser(displayName), emojiMap, true)
|
||||||
account.note_emojified = emojify(account.note, emojiMap);
|
account.note_emojified = emojify(account.note, emojiMap)
|
||||||
account.note_plain = unescapeHTML(account.note)
|
account.note_plain = unescapeHTML(account.note)
|
||||||
|
|
||||||
if (account.fields) {
|
if (account.fields) {
|
||||||
|
@ -27,67 +33,73 @@ export function normalizeAccount(account) {
|
||||||
name_emojified: emojify(escapeTextContentForBrowser(pair.name)),
|
name_emojified: emojify(escapeTextContentForBrowser(pair.name)),
|
||||||
value_emojified: emojify(pair.value, emojiMap),
|
value_emojified: emojify(pair.value, emojiMap),
|
||||||
value_plain: unescapeHTML(pair.value),
|
value_plain: unescapeHTML(pair.value),
|
||||||
}));
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (account.moved) {
|
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) {
|
if (status.reblog && status.reblog.id) {
|
||||||
normalStatus.reblog = status.reblog.id;
|
normalStatus.reblog = status.reblog.id
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status.quote && status.quote.id) {
|
if (status.quote && status.quote.id) {
|
||||||
normalStatus.quote = status.quote.id;
|
normalStatus.quote = status.quote.id
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status.poll && status.poll.id) {
|
if (status.poll && status.poll.id) {
|
||||||
normalStatus.poll = status.poll.id;
|
normalStatus.poll = status.poll.id
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!!status.group || !!status.group_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
|
// Only calculate these values when status first encountered
|
||||||
// Otherwise keep the ones already in the reducer
|
// Otherwise keep the ones already in the reducer
|
||||||
if (normalOldStatus && normalOldStatus.get('content') === normalStatus.content && normalOldStatus.get('spoiler_text') === normalStatus.spoiler_text) {
|
if (normalOldStatus && normalOldStatus.get('content') === normalStatus.content && normalOldStatus.get('spoiler_text') === normalStatus.spoiler_text) {
|
||||||
normalStatus.search_index = normalOldStatus.get('search_index');
|
normalStatus.search_index = normalOldStatus.get('search_index')
|
||||||
normalStatus.contentHtml = normalOldStatus.get('contentHtml');
|
normalStatus.contentHtml = normalOldStatus.get('contentHtml')
|
||||||
normalStatus.spoilerHtml = normalOldStatus.get('spoilerHtml');
|
normalStatus.spoilerHtml = normalOldStatus.get('spoilerHtml')
|
||||||
normalStatus.hidden = normalOldStatus.get('hidden');
|
normalStatus.hidden = normalOldStatus.get('hidden')
|
||||||
} else {
|
} else {
|
||||||
const spoilerText = normalStatus.spoiler_text || '';
|
const spoilerText = normalStatus.spoiler_text || ''
|
||||||
const searchContent = [spoilerText, status.content].join('\n\n').replace(/<br\s*\/?>/g, '\n').replace(/<\/p><p>/g, '\n\n');
|
const searchContent = [spoilerText, status.content].join('\n\n').replace(/<br\s*\/?>/g, '\n').replace(/<\/p><p>/g, '\n\n')
|
||||||
const emojiMap = makeEmojiMap(normalStatus);
|
const emojiMap = makeEmojiMap(normalStatus)
|
||||||
const theContent = !!normalStatus.rich_content ? normalStatus.rich_content : normalStatus.content;
|
const theContent = !!normalStatus.rich_content ? normalStatus.rich_content : normalStatus.content
|
||||||
|
|
||||||
normalStatus.search_index = domParser.parseFromString(searchContent, 'text/html').documentElement.textContent;
|
normalStatus.search_index = domParser.parseFromString(searchContent, 'text/html').documentElement.textContent
|
||||||
normalStatus.contentHtml = emojify(theContent, emojiMap, false, true);
|
normalStatus.contentHtml = emojify(theContent, emojiMap, false, true)
|
||||||
normalStatus.spoilerHtml = emojify(escapeTextContentForBrowser(spoilerText), emojiMap);
|
normalStatus.spoilerHtml = emojify(escapeTextContentForBrowser(spoilerText), emojiMap)
|
||||||
normalStatus.hidden = expandSpoilers ? false : spoilerText.length > 0 || normalStatus.sensitive;
|
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,
|
...option,
|
||||||
title_emojified: emojify(escapeTextContentForBrowser(option.title), emojiMap),
|
title_emojified: emojify(escapeTextContentForBrowser(option.title), emojiMap),
|
||||||
}));
|
}))
|
||||||
|
|
||||||
return normalPoll;
|
return normalPoll
|
||||||
}
|
}
|
|
@ -1,5 +1,9 @@
|
||||||
import api from '../api'
|
import api, { getLinks } from '../api'
|
||||||
import { importFetchedAccounts, importFetchedStatus } from './importer'
|
import {
|
||||||
|
importFetchedAccounts,
|
||||||
|
importFetchedStatus,
|
||||||
|
} from './importer'
|
||||||
|
import { fetchRelationships } from './accounts'
|
||||||
import { updateStatusStats } from './statuses'
|
import { updateStatusStats } from './statuses'
|
||||||
import { me } from '../initial_state'
|
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_SUCCESS = 'REPOSTS_FETCH_SUCCESS'
|
||||||
export const REPOSTS_FETCH_FAIL = 'REPOSTS_FETCH_FAIL'
|
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_REQUEST = 'PIN_REQUEST'
|
||||||
export const PIN_SUCCESS = 'PIN_SUCCESS'
|
export const PIN_SUCCESS = 'PIN_SUCCESS'
|
||||||
export const PIN_FAIL = 'PIN_FAIL'
|
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_SUCCESS = 'UNPIN_SUCCESS'
|
||||||
export const UNPIN_FAIL = 'UNPIN_FAIL'
|
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_REQUEST = 'BOOKMARK_REQUEST'
|
||||||
export const BOOKMARK_SUCCESS = 'BOOKMARK_SUCCESS'
|
export const BOOKMARK_SUCCESS = 'BOOKMARK_SUCCESS'
|
||||||
export const BOOKMARK_FAIL = 'BOOKMARK_FAIL'
|
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_SUCCESS = 'UNBOOKMARK_SUCCESS'
|
||||||
export const UNBOOKMARK_FAIL = 'UNBOOKMARK_FAIL'
|
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_REQUEST = 'LIKES_FETCH_REQUEST'
|
||||||
export const LIKES_FETCH_SUCCESS = 'LIKES_FETCH_SUCCESS'
|
export const LIKES_FETCH_SUCCESS = 'LIKES_FETCH_SUCCESS'
|
||||||
export const LIKES_FETCH_FAIL = 'LIKES_FETCH_FAIL'
|
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) => {
|
export const repost = (status) => (dispatch, getState) => {
|
||||||
if (!me) return
|
if (!me || !status) return
|
||||||
|
|
||||||
dispatch(repostRequest(status))
|
dispatch(repostRequest(status))
|
||||||
|
|
||||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/reblog`).then((response) => {
|
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
|
dispatch(updateStatusStats(response.data))
|
||||||
// interested in how the original is modified, hence passing it skipping the wrapper
|
|
||||||
dispatch(importFetchedStatus(response.data.reblog))
|
|
||||||
dispatch(repostSuccess(status))
|
dispatch(repostSuccess(status))
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
dispatch(repostFail(status, error))
|
dispatch(repostFail(status, error))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const repostRequest = (status) => ({
|
const repostRequest = (status) => ({
|
||||||
type: REPOST_REQUEST,
|
type: REPOST_REQUEST,
|
||||||
status: status,
|
status,
|
||||||
skipLoading: true,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export const repostSuccess = (status) => ({
|
const repostSuccess = (status) => ({
|
||||||
type: REPOST_SUCCESS,
|
type: REPOST_SUCCESS,
|
||||||
status: status,
|
status,
|
||||||
skipLoading: true,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export const repostFail = (status, error) => ({
|
const repostFail = (status, error) => ({
|
||||||
type: REPOST_FAIL,
|
type: REPOST_FAIL,
|
||||||
status: status,
|
status,
|
||||||
error: error,
|
error,
|
||||||
skipLoading: true,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @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) => {
|
export const unrepost = (status) => (dispatch, getState) => {
|
||||||
if (!me) return
|
if (!me || !status) return
|
||||||
|
|
||||||
dispatch(unrepostRequest(status))
|
dispatch(unrepostRequest(status))
|
||||||
|
|
||||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/unreblog`).then((response) => {
|
api(getState).post(`/api/v1/statuses/${status.get('id')}/unreblog`).then((response) => {
|
||||||
dispatch(importFetchedStatus(response.data))
|
dispatch(updateStatusStats(response.data))
|
||||||
dispatch(unrepostSuccess(status))
|
dispatch(unrepostSuccess(status))
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
dispatch(unrepostFail(status, error))
|
dispatch(unrepostFail(status, error))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const unrepostRequest = (status) => ({
|
const unrepostRequest = (status) => ({
|
||||||
type: UNREPOST_REQUEST,
|
type: UNREPOST_REQUEST,
|
||||||
status: status,
|
status,
|
||||||
skipLoading: true,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export const unrepostSuccess = (status) => ({
|
const unrepostSuccess = (status) => ({
|
||||||
type: UNREPOST_SUCCESS,
|
type: UNREPOST_SUCCESS,
|
||||||
status: status,
|
status,
|
||||||
skipLoading: true,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export const unrepostFail = (status, error) => ({
|
const unrepostFail = (status, error) => ({
|
||||||
type: UNREPOST_FAIL,
|
type: UNREPOST_FAIL,
|
||||||
status: status,
|
status,
|
||||||
error: error,
|
error,
|
||||||
skipLoading: true,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @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) => {
|
export const favorite = (status) => (dispatch, getState) => {
|
||||||
if (!me) return
|
if (!me || !status) return
|
||||||
|
|
||||||
dispatch(favoriteRequest(status))
|
dispatch(favoriteRequest(status))
|
||||||
|
|
||||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/favourite`).then((response) => {
|
api(getState).post(`/api/v1/statuses/${status.get('id')}/favourite`).then((response) => {
|
||||||
dispatch(updateStatusStats(response.data))
|
dispatch(updateStatusStats(response.data))
|
||||||
dispatch(favoriteSuccess(status))
|
dispatch(favoriteSuccess(response.data))
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
dispatch(favoriteFail(status, error))
|
dispatch(favoriteFail(status, error))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const favoriteRequest = (status) => ({
|
const favoriteRequest = (status) => ({
|
||||||
type: FAVORITE_REQUEST,
|
type: FAVORITE_REQUEST,
|
||||||
status: status,
|
status,
|
||||||
skipLoading: true,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export const favoriteSuccess = (status) => ({
|
const favoriteSuccess = (data) => ({
|
||||||
type: FAVORITE_SUCCESS,
|
type: FAVORITE_SUCCESS,
|
||||||
status: status,
|
data,
|
||||||
skipLoading: true,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export const favoriteFail = (status, error) => ({
|
const favoriteFail = (status, error) => ({
|
||||||
type: FAVORITE_FAIL,
|
type: FAVORITE_FAIL,
|
||||||
status: status,
|
status,
|
||||||
error: error,
|
error,
|
||||||
skipLoading: true,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @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) => {
|
export const unfavorite = (status) => (dispatch, getState) => {
|
||||||
if (!me) return
|
if (!me || !status) return
|
||||||
|
|
||||||
dispatch(unfavoriteRequest(status))
|
dispatch(unfavoriteRequest(status))
|
||||||
|
|
||||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/unfavourite`).then((response) => {
|
api(getState).post(`/api/v1/statuses/${status.get('id')}/unfavourite`).then((response) => {
|
||||||
dispatch(importFetchedStatus(response.data))
|
dispatch(updateStatusStats(response.data))
|
||||||
dispatch(unfavoriteSuccess(status))
|
dispatch(unfavoriteSuccess(status))
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
dispatch(unfavoriteFail(status, error))
|
dispatch(unfavoriteFail(status, error))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const unfavoriteRequest = (status) => ({
|
const unfavoriteRequest = (status) => ({
|
||||||
type: UNFAVORITE_REQUEST,
|
type: UNFAVORITE_REQUEST,
|
||||||
status: status,
|
status,
|
||||||
skipLoading: true,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export const unfavoriteSuccess = (status) => ({
|
const unfavoriteSuccess = (status) => ({
|
||||||
type: UNFAVORITE_SUCCESS,
|
type: UNFAVORITE_SUCCESS,
|
||||||
status: status,
|
status,
|
||||||
skipLoading: true,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export const unfavoriteFail = (status, error) => ({
|
const unfavoriteFail = (status, error) => ({
|
||||||
type: UNFAVORITE_FAIL,
|
type: UNFAVORITE_FAIL,
|
||||||
status: 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,
|
|
||||||
error,
|
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) => {
|
export const pin = (status) => (dispatch, getState) => {
|
||||||
if (!me) return
|
if (!me || !status) return
|
||||||
|
|
||||||
dispatch(pinRequest(status))
|
dispatch(pinRequest(status))
|
||||||
|
|
||||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/pin`).then((response) => {
|
api(getState).post(`/api/v1/statuses/${status.get('id')}/pin`).then((response) => {
|
||||||
dispatch(importFetchedStatus(response.data))
|
dispatch(updateStatusStats(response.data))
|
||||||
dispatch(pinSuccess(status))
|
dispatch(pinSuccess(status))
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
dispatch(pinFail(status, error))
|
dispatch(pinFail(status, error))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const pinRequest = (status) => ({
|
const pinRequest = (status) => ({
|
||||||
type: PIN_REQUEST,
|
type: PIN_REQUEST,
|
||||||
status,
|
status,
|
||||||
skipLoading: true,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export const pinSuccess = (status) => ({
|
const pinSuccess = (status) => ({
|
||||||
type: PIN_SUCCESS,
|
type: PIN_SUCCESS,
|
||||||
status,
|
status,
|
||||||
skipLoading: true,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export const pinFail = (status, error) => ({
|
const pinFail = (status, error) => ({
|
||||||
type: PIN_FAIL,
|
type: PIN_FAIL,
|
||||||
status,
|
status,
|
||||||
error,
|
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) => {
|
export const unpin = (status) => (dispatch, getState) => {
|
||||||
if (!me) return
|
if (!me || !status) return
|
||||||
|
|
||||||
dispatch(unpinRequest(status))
|
dispatch(unpinRequest(status))
|
||||||
|
|
||||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/unpin`).then((response) => {
|
api(getState).post(`/api/v1/statuses/${status.get('id')}/unpin`).then((response) => {
|
||||||
dispatch(importFetchedStatus(response.data))
|
dispatch(updateStatusStats(response.data))
|
||||||
dispatch(unpinSuccess(status))
|
dispatch(unpinSuccess(status, response.data.account_id))
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
dispatch(unpinFail(status, error))
|
dispatch(unpinFail(status, error))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const unpinRequest = (status) => ({
|
const unpinRequest = (status) => ({
|
||||||
type: UNPIN_REQUEST,
|
type: UNPIN_REQUEST,
|
||||||
status,
|
status,
|
||||||
skipLoading: true,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export const unpinSuccess = (status) => ({
|
const unpinSuccess = (status, accountId) => ({
|
||||||
type: UNPIN_SUCCESS,
|
type: UNPIN_SUCCESS,
|
||||||
|
accountId,
|
||||||
status,
|
status,
|
||||||
skipLoading: true,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export const unpinFail = (status, error) => ({
|
const unpinFail = (status, error) => ({
|
||||||
type: UNPIN_FAIL,
|
type: UNPIN_FAIL,
|
||||||
status,
|
status,
|
||||||
error,
|
error,
|
||||||
skipLoading: true,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @description Check if a status is pinned to the current user account.
|
||||||
|
* @param {String} statusId
|
||||||
*/
|
*/
|
||||||
export const fetchLikes = (id) => (dispatch, getState) => {
|
export const isPin = (statusId) => (dispatch, getState) => {
|
||||||
dispatch(fetchLikesRequest(id))
|
if (!me || !statusId) return
|
||||||
|
|
||||||
api(getState).get(`/api/v1/statuses/${id}/favourited_by`).then((response) => {
|
dispatch(isPinRequest(statusId))
|
||||||
dispatch(importFetchedAccounts(response.data))
|
|
||||||
dispatch(fetchLikesSuccess(id, response.data))
|
api(getState).get(`/api/v1/statuses/${statusId}/pin`).then((response) => {
|
||||||
|
dispatch(updateStatusStats(response.data))
|
||||||
|
dispatch(isPinSuccess(statusId))
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
dispatch(fetchLikesFail(id, error))
|
dispatch(isPinFail(statusId, error))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fetchLikesRequest = (id) => ({
|
const isPinRequest = (statusId) => ({
|
||||||
type: LIKES_FETCH_REQUEST,
|
type: IS_PIN_REQUEST,
|
||||||
id,
|
statusId,
|
||||||
})
|
})
|
||||||
|
|
||||||
export const fetchLikesSuccess = (id, accounts) => ({
|
const isPinSuccess = (statusId) => ({
|
||||||
type: LIKES_FETCH_SUCCESS,
|
type: IS_PIN_SUCCESS,
|
||||||
id,
|
statusId,
|
||||||
accounts,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export const fetchLikesFail = (id, error) => ({
|
const isPinFail = (statusId, error) => ({
|
||||||
type: LIKES_FETCH_FAIL,
|
type: IS_PIN_FAIL,
|
||||||
|
statusId,
|
||||||
error,
|
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) => {
|
export const bookmark = (status) => (dispatch, getState) => {
|
||||||
|
if (!me || !status) return
|
||||||
|
|
||||||
dispatch(bookmarkRequest(status))
|
dispatch(bookmarkRequest(status))
|
||||||
|
|
||||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/bookmark`).then((response) => {
|
api(getState).post(`/api/v1/statuses/${status.get('id')}/bookmark`).then((response) => {
|
||||||
dispatch(importFetchedStatus(response.data))
|
dispatch(updateStatusStats(response.data))
|
||||||
dispatch(bookmarkSuccess(status, response.data))
|
dispatch(bookmarkSuccess(status))
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
dispatch(bookmarkFail(status, error))
|
dispatch(bookmarkFail(status, error))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const bookmarkRequest = (status) => ({
|
const bookmarkRequest = (status) => ({
|
||||||
type: BOOKMARK_REQUEST,
|
type: BOOKMARK_REQUEST,
|
||||||
status: status,
|
status,
|
||||||
})
|
})
|
||||||
|
|
||||||
export const bookmarkSuccess = (status, response) => ({
|
const bookmarkSuccess = (status) => ({
|
||||||
type: BOOKMARK_SUCCESS,
|
type: BOOKMARK_SUCCESS,
|
||||||
status: status,
|
status,
|
||||||
response: response,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export const bookmarkFail = (status, error) => ({
|
const bookmarkFail = (status, error) => ({
|
||||||
type: BOOKMARK_FAIL,
|
type: BOOKMARK_FAIL,
|
||||||
status: status,
|
status,
|
||||||
error: error,
|
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) => {
|
export const unbookmark = (status) => (dispatch, getState) => {
|
||||||
|
if (!me || !status) return
|
||||||
|
|
||||||
dispatch(unbookmarkRequest(status))
|
dispatch(unbookmarkRequest(status))
|
||||||
|
|
||||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/unbookmark`).then((response) => {
|
api(getState).post(`/api/v1/statuses/${status.get('id')}/unbookmark`).then((response) => {
|
||||||
dispatch(importFetchedStatus(response.data))
|
dispatch(updateStatusStats(response.data))
|
||||||
dispatch(unbookmarkSuccess(status, response.data))
|
dispatch(unbookmarkSuccess(status))
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
dispatch(unbookmarkFail(status, error))
|
dispatch(unbookmarkFail(status, error))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const unbookmarkRequest = (status) => ({
|
const unbookmarkRequest = (status) => ({
|
||||||
type: UNBOOKMARK_REQUEST,
|
type: UNBOOKMARK_REQUEST,
|
||||||
status: status,
|
status,
|
||||||
})
|
})
|
||||||
|
|
||||||
export const unbookmarkSuccess = (status, response) => ({
|
const unbookmarkSuccess = (status) => ({
|
||||||
type: UNBOOKMARK_SUCCESS,
|
type: UNBOOKMARK_SUCCESS,
|
||||||
status: status,
|
status,
|
||||||
response: response,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export const unbookmarkFail = (status, error) => ({
|
const unbookmarkFail = (status, error) => ({
|
||||||
type: UNBOOKMARK_FAIL,
|
type: UNBOOKMARK_FAIL,
|
||||||
status: status,
|
status,
|
||||||
error: error,
|
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,
|
||||||
})
|
})
|
|
@ -1,5 +1,6 @@
|
||||||
import api, { getLinks } from '../api'
|
import api, { getLinks } from '../api'
|
||||||
import IntlMessageFormat from 'intl-messageformat'
|
import IntlMessageFormat from 'intl-messageformat'
|
||||||
|
import noop from 'lodash.noop'
|
||||||
import { fetchRelationships } from './accounts'
|
import { fetchRelationships } from './accounts'
|
||||||
import {
|
import {
|
||||||
importFetchedAccount,
|
importFetchedAccount,
|
||||||
|
@ -49,8 +50,6 @@ const excludeTypesFromFilter = filter => {
|
||||||
return allTypes.filterNot(item => item === filter).toJS()
|
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
|
if (!me) return
|
||||||
|
|
||||||
const onlyVerified = getState().getIn(['notifications', 'filter', 'onlyVerified'])
|
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,
|
type: NOTIFICATIONS_EXPAND_REQUEST,
|
||||||
skipLoading: !isLoadingMore,
|
skipLoading: !isLoadingMore,
|
||||||
})
|
})
|
||||||
|
|
||||||
export const expandNotificationsSuccess = (notifications, next, isLoadingMore) => ({
|
const expandNotificationsSuccess = (notifications, next, isLoadingMore) => ({
|
||||||
type: NOTIFICATIONS_EXPAND_SUCCESS,
|
type: NOTIFICATIONS_EXPAND_SUCCESS,
|
||||||
notifications,
|
notifications,
|
||||||
next,
|
next,
|
||||||
skipLoading: !isLoadingMore,
|
skipLoading: !isLoadingMore,
|
||||||
})
|
})
|
||||||
|
|
||||||
export const expandNotificationsFail = (error, isLoadingMore) => ({
|
const expandNotificationsFail = (error, isLoadingMore) => ({
|
||||||
type: NOTIFICATIONS_EXPAND_FAIL,
|
type: NOTIFICATIONS_EXPAND_FAIL,
|
||||||
error,
|
error,
|
||||||
skipLoading: !isLoadingMore,
|
skipLoading: !isLoadingMore,
|
||||||
|
|
|
@ -1,15 +1,23 @@
|
||||||
import api from '../api'
|
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_SUCCESS = 'STATUS_REVISIONS_SUCCESS'
|
||||||
export const STATUS_REVISIONS_LOAD_FAIL = 'STATUS_REVISIONS_FAIL'
|
export const STATUS_REVISIONS_LOAD_FAIL = 'STATUS_REVISIONS_FAIL'
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
export const loadStatusRevisions = (statusId) => (dispatch, getState) => {
|
export const loadStatusRevisions = (statusId) => (dispatch, getState) => {
|
||||||
|
dispatch(loadStatusRevisionsRequest())
|
||||||
api(getState).get(`/api/v1/statuses/${statusId}/revisions`)
|
api(getState).get(`/api/v1/statuses/${statusId}/revisions`)
|
||||||
.then(res => dispatch(loadStatusRevisionsSuccess(res.data)))
|
.then(res => dispatch(loadStatusRevisionsSuccess(res.data)))
|
||||||
.catch(() => dispatch(loadStatusRevisionsFail()))
|
.catch(() => dispatch(loadStatusRevisionsFail()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const loadStatusRevisionsRequest = () => ({
|
||||||
|
type: STATUS_REVISIONS_LOAD_REQUEST,
|
||||||
|
})
|
||||||
|
|
||||||
const loadStatusRevisionsSuccess = (data) => ({
|
const loadStatusRevisionsSuccess = (data) => ({
|
||||||
type: STATUS_REVISIONS_LOAD_SUCCESS,
|
type: STATUS_REVISIONS_LOAD_SUCCESS,
|
||||||
revisions: data,
|
revisions: data,
|
||||||
|
|
|
@ -1,304 +1,292 @@
|
||||||
import api from '../api';
|
import api from '../api'
|
||||||
import openDB from '../storage/db';
|
import openDB from '../storage/db'
|
||||||
import { evictStatus } from '../storage/modifier';
|
import { evictStatus } from '../storage/modifier'
|
||||||
import { deleteFromTimelines } from './timelines';
|
import { deleteFromTimelines } from './timelines'
|
||||||
import { importFetchedStatus, importFetchedStatuses, importAccount, importStatus } from './importer';
|
import { importFetchedStatus, importFetchedStatuses, importAccount, importStatus } from './importer'
|
||||||
import { openModal } from './modal';
|
import { openModal } from './modal'
|
||||||
import { me } from '../initial_state';
|
import { me } from '../initial_state'
|
||||||
|
|
||||||
export const STATUS_FETCH_REQUEST = 'STATUS_FETCH_REQUEST';
|
export const STATUS_FETCH_REQUEST = 'STATUS_FETCH_REQUEST'
|
||||||
export const STATUS_FETCH_SUCCESS = 'STATUS_FETCH_SUCCESS';
|
export const STATUS_FETCH_SUCCESS = 'STATUS_FETCH_SUCCESS'
|
||||||
export const STATUS_FETCH_FAIL = 'STATUS_FETCH_FAIL';
|
export const STATUS_FETCH_FAIL = 'STATUS_FETCH_FAIL'
|
||||||
|
|
||||||
export const STATUS_DELETE_REQUEST = 'STATUS_DELETE_REQUEST';
|
export const STATUS_DELETE_REQUEST = 'STATUS_DELETE_REQUEST'
|
||||||
export const STATUS_DELETE_SUCCESS = 'STATUS_DELETE_SUCCESS';
|
export const STATUS_DELETE_SUCCESS = 'STATUS_DELETE_SUCCESS'
|
||||||
export const STATUS_DELETE_FAIL = 'STATUS_DELETE_FAIL';
|
export const STATUS_DELETE_FAIL = 'STATUS_DELETE_FAIL'
|
||||||
|
|
||||||
export const CONTEXT_FETCH_REQUEST = 'CONTEXT_FETCH_REQUEST';
|
export const CONTEXT_FETCH_REQUEST = 'CONTEXT_FETCH_REQUEST'
|
||||||
export const CONTEXT_FETCH_SUCCESS = 'CONTEXT_FETCH_SUCCESS';
|
export const CONTEXT_FETCH_SUCCESS = 'CONTEXT_FETCH_SUCCESS'
|
||||||
export const CONTEXT_FETCH_FAIL = 'CONTEXT_FETCH_FAIL';
|
export const CONTEXT_FETCH_FAIL = 'CONTEXT_FETCH_FAIL'
|
||||||
|
|
||||||
export const COMMENTS_FETCH_REQUEST = 'COMMENTS_FETCH_REQUEST';
|
export const COMMENTS_FETCH_REQUEST = 'COMMENTS_FETCH_REQUEST'
|
||||||
export const COMMENTS_FETCH_SUCCESS = 'COMMENTS_FETCH_SUCCESS';
|
export const COMMENTS_FETCH_SUCCESS = 'COMMENTS_FETCH_SUCCESS'
|
||||||
export const COMMENTS_FETCH_FAIL = 'COMMENTS_FETCH_FAIL';
|
export const COMMENTS_FETCH_FAIL = 'COMMENTS_FETCH_FAIL'
|
||||||
|
|
||||||
export const STATUS_REVEAL = 'STATUS_REVEAL';
|
export const STATUS_REVEAL = 'STATUS_REVEAL'
|
||||||
export const STATUS_HIDE = 'STATUS_HIDE';
|
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 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) {
|
function getFromDB(dispatch, getState, accountIndex, index, id) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const request = index.get(id);
|
const request = index.get(id)
|
||||||
|
|
||||||
request.onerror = reject;
|
request.onerror = reject
|
||||||
|
|
||||||
request.onsuccess = () => {
|
request.onsuccess = () => {
|
||||||
const promises = [];
|
const promises = []
|
||||||
|
|
||||||
if (!request.result) {
|
if (!request.result) {
|
||||||
reject();
|
reject()
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch(importStatus(request.result));
|
dispatch(importStatus(request.result))
|
||||||
|
|
||||||
if (getState().getIn(['accounts', request.result.account], null) === null) {
|
if (getState().getIn(['accounts', request.result.account], null) === null) {
|
||||||
promises.push(new Promise((accountResolve, accountReject) => {
|
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 = () => {
|
accountRequest.onsuccess = () => {
|
||||||
if (!request.result) {
|
if (!request.result) {
|
||||||
accountReject();
|
accountReject()
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch(importAccount(accountRequest.result));
|
dispatch(importAccount(accountRequest.result))
|
||||||
accountResolve();
|
accountResolve()
|
||||||
};
|
}
|
||||||
}));
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.result.reblog && getState().getIn(['statuses', request.result.reblog], null) === null) {
|
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) {
|
dispatch(fetchStatusRequest(id, skipLoading))
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatch(fetchStatusRequest(id, skipLoading));
|
openDB().then((db) => {
|
||||||
|
const transaction = db.transaction(['accounts', 'statuses'], 'read')
|
||||||
openDB().then(db => {
|
const accountIndex = transaction.objectStore('accounts').index('id')
|
||||||
const transaction = db.transaction(['accounts', 'statuses'], 'read');
|
const index = transaction.objectStore('statuses').index('id')
|
||||||
const accountIndex = transaction.objectStore('accounts').index('id');
|
|
||||||
const index = transaction.objectStore('statuses').index('id');
|
|
||||||
|
|
||||||
return getFromDB(dispatch, getState, accountIndex, index, id).then(() => {
|
return getFromDB(dispatch, getState, accountIndex, index, id).then(() => {
|
||||||
db.close();
|
db.close()
|
||||||
}, error => {
|
}, (error) => {
|
||||||
db.close();
|
db.close()
|
||||||
throw error;
|
throw error
|
||||||
});
|
})
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
dispatch(fetchStatusSuccess(skipLoading));
|
dispatch(fetchStatusSuccess(skipLoading))
|
||||||
}, () => api(getState).get(`/api/v1/statuses/${id}`).then(response => {
|
}, () => api(getState).get(`/api/v1/statuses/${id}`).then((response) => {
|
||||||
dispatch(importFetchedStatus(response.data));
|
dispatch(importFetchedStatus(response.data))
|
||||||
dispatch(fetchStatusSuccess(skipLoading));
|
dispatch(fetchStatusSuccess(skipLoading))
|
||||||
})).catch(error => {
|
})).catch((error) => {
|
||||||
dispatch(fetchStatusFail(id, error, skipLoading));
|
dispatch(fetchStatusFail(id, error, skipLoading))
|
||||||
});
|
})
|
||||||
};
|
}
|
||||||
};
|
|
||||||
|
|
||||||
export function fetchStatusSuccess(skipLoading) {
|
const fetchStatusRequest = (id, skipLoading) => ({
|
||||||
return {
|
type: STATUS_FETCH_REQUEST,
|
||||||
|
id,
|
||||||
|
skipLoading,
|
||||||
|
})
|
||||||
|
|
||||||
|
const fetchStatusSuccess = (skipLoading) => ({
|
||||||
type: STATUS_FETCH_SUCCESS,
|
type: STATUS_FETCH_SUCCESS,
|
||||||
skipLoading,
|
skipLoading,
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
export function fetchStatusFail(id, error, skipLoading) {
|
const fetchStatusFail = (id, error, skipLoading) => ({
|
||||||
return {
|
|
||||||
type: STATUS_FETCH_FAIL,
|
type: STATUS_FETCH_FAIL,
|
||||||
id,
|
id,
|
||||||
error,
|
error,
|
||||||
skipLoading,
|
skipLoading,
|
||||||
skipAlert: true,
|
skipAlert: true,
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
export function editStatus(status) {
|
/**
|
||||||
return dispatch => {
|
*
|
||||||
|
*/
|
||||||
|
export const editStatus = (status) => (dispatch) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: STATUS_EDIT,
|
type: STATUS_EDIT,
|
||||||
status,
|
status,
|
||||||
});
|
})
|
||||||
|
|
||||||
dispatch(openModal('COMPOSE'));
|
dispatch(openModal('COMPOSE'))
|
||||||
};
|
}
|
||||||
};
|
|
||||||
|
|
||||||
export function deleteStatus(id, routerHistory) {
|
/**
|
||||||
return (dispatch, getState) => {
|
*
|
||||||
if (!me) return;
|
*/
|
||||||
|
export const deleteStatus = (id, routerHistory) => (dispatch, getState) => {
|
||||||
|
if (!me) return
|
||||||
|
|
||||||
let status = getState().getIn(['statuses', id]);
|
let status = getState().getIn(['statuses', id])
|
||||||
|
|
||||||
if (status.get('poll')) {
|
if (status.get('poll')) {
|
||||||
status = status.set('poll', getState().getIn(['polls', status.get('poll')]));
|
status = status.set('poll', getState().getIn(['polls', status.get('poll')]))
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch(deleteStatusRequest(id));
|
dispatch(deleteStatusRequest(id))
|
||||||
|
|
||||||
api(getState).delete(`/api/v1/statuses/${id}`).then(response => {
|
api(getState).delete(`/api/v1/statuses/${id}`).then((response) => {
|
||||||
evictStatus(id);
|
evictStatus(id)
|
||||||
dispatch(deleteStatusSuccess(id));
|
dispatch(deleteStatusSuccess(id))
|
||||||
dispatch(deleteFromTimelines(id));
|
dispatch(deleteFromTimelines(id))
|
||||||
}).catch(error => {
|
}).catch((error) => {
|
||||||
dispatch(deleteStatusFail(id, error));
|
dispatch(deleteStatusFail(id, error))
|
||||||
});
|
})
|
||||||
};
|
}
|
||||||
};
|
|
||||||
|
|
||||||
export function deleteStatusRequest(id) {
|
const deleteStatusRequest = (id) => ({
|
||||||
return {
|
|
||||||
type: STATUS_DELETE_REQUEST,
|
type: STATUS_DELETE_REQUEST,
|
||||||
id: id,
|
id: id,
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
export function deleteStatusSuccess(id) {
|
const deleteStatusSuccess = (id) => ({
|
||||||
return {
|
|
||||||
type: STATUS_DELETE_SUCCESS,
|
type: STATUS_DELETE_SUCCESS,
|
||||||
id: id,
|
id: id,
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
export function deleteStatusFail(id, error) {
|
const deleteStatusFail = (id, error) => ({
|
||||||
return {
|
|
||||||
type: STATUS_DELETE_FAIL,
|
type: STATUS_DELETE_FAIL,
|
||||||
id: id,
|
id: id,
|
||||||
error: error,
|
error,
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
export function fetchContext(id, ensureIsReply) {
|
/**
|
||||||
return (dispatch, getState) => {
|
*
|
||||||
|
*/
|
||||||
|
export const fetchContext = (id, ensureIsReply) => (dispatch, getState) => {
|
||||||
if (ensureIsReply) {
|
if (ensureIsReply) {
|
||||||
const isReply = !!getState().getIn(['statuses', id, 'in_reply_to_id'], null)
|
const isReply = !!getState().getIn(['statuses', id, 'in_reply_to_id'], null)
|
||||||
if (!isReply) return;
|
if (!isReply) return
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch(fetchContextRequest(id));
|
dispatch(fetchContextRequest(id))
|
||||||
|
|
||||||
api(getState).get(`/api/v1/statuses/${id}/context`).then(response => {
|
api(getState).get(`/api/v1/statuses/${id}/context`).then((response) => {
|
||||||
dispatch(importFetchedStatuses(response.data.ancestors.concat(response.data.descendants)));
|
dispatch(importFetchedStatuses(response.data.ancestors.concat(response.data.descendants)))
|
||||||
dispatch(fetchContextSuccess(id, response.data.ancestors, response.data.descendants));
|
dispatch(fetchContextSuccess(id, response.data.ancestors, response.data.descendants))
|
||||||
|
}).catch((error) => {
|
||||||
}).catch(error => {
|
|
||||||
if (error.response && error.response.status === 404) {
|
if (error.response && error.response.status === 404) {
|
||||||
dispatch(deleteFromTimelines(id));
|
dispatch(deleteFromTimelines(id))
|
||||||
|
}
|
||||||
|
dispatch(fetchContextFail(id, error))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch(fetchContextFail(id, error));
|
/**
|
||||||
});
|
*
|
||||||
};
|
*/
|
||||||
};
|
const fetchContextRequest = (id) => ({
|
||||||
|
|
||||||
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,
|
type: CONTEXT_FETCH_REQUEST,
|
||||||
id,
|
id,
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
export function fetchContextSuccess(id, ancestors, descendants) {
|
const fetchContextSuccess = (id, ancestors, descendants) => ({
|
||||||
return {
|
|
||||||
type: CONTEXT_FETCH_SUCCESS,
|
type: CONTEXT_FETCH_SUCCESS,
|
||||||
id,
|
id,
|
||||||
ancestors,
|
ancestors,
|
||||||
descendants,
|
descendants,
|
||||||
statuses: ancestors.concat(descendants),
|
statuses: ancestors.concat(descendants),
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
export function fetchContextFail(id, error) {
|
const fetchContextFail = (id, error) => ({
|
||||||
return {
|
|
||||||
type: CONTEXT_FETCH_FAIL,
|
type: CONTEXT_FETCH_FAIL,
|
||||||
id,
|
id,
|
||||||
error,
|
error,
|
||||||
skipAlert: true,
|
skipAlert: true,
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
export function fetchCommentsRequest(id) {
|
/**
|
||||||
return {
|
*
|
||||||
|
*/
|
||||||
|
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(fetchCommentsFail(id, error))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchCommentsRequest = (id) => ({
|
||||||
type: COMMENTS_FETCH_REQUEST,
|
type: COMMENTS_FETCH_REQUEST,
|
||||||
id,
|
id,
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
export function fetchCommentsSuccess(id, descendants) {
|
const fetchCommentsSuccess = (id, descendants) => ({
|
||||||
return {
|
|
||||||
type: COMMENTS_FETCH_SUCCESS,
|
type: COMMENTS_FETCH_SUCCESS,
|
||||||
id,
|
id,
|
||||||
descendants,
|
descendants,
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
export function fetchCommentsFail(id, error) {
|
const fetchCommentsFail = (id, error) => ({
|
||||||
return {
|
|
||||||
type: COMMENTS_FETCH_FAIL,
|
type: COMMENTS_FETCH_FAIL,
|
||||||
id,
|
id,
|
||||||
error,
|
error,
|
||||||
skipAlert: true,
|
skipAlert: true,
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
export function hideStatus(ids) {
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export const hideStatus = (ids) => {
|
||||||
if (!Array.isArray(ids)) {
|
if (!Array.isArray(ids)) {
|
||||||
ids = [ids];
|
ids = [ids]
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: STATUS_HIDE,
|
type: STATUS_HIDE,
|
||||||
ids,
|
ids,
|
||||||
};
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
export function revealStatus(ids) {
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export const revealStatus = (ids) => {
|
||||||
if (!Array.isArray(ids)) {
|
if (!Array.isArray(ids)) {
|
||||||
ids = [ids];
|
ids = [ids]
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: STATUS_REVEAL,
|
type: STATUS_REVEAL,
|
||||||
ids,
|
ids,
|
||||||
};
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
export function updateStatusStats(data) {
|
/**
|
||||||
return {
|
*
|
||||||
|
*/
|
||||||
|
export const updateStatusStats = (data) => ({
|
||||||
type: UPDATE_STATUS_STATS,
|
type: UPDATE_STATUS_STATS,
|
||||||
data,
|
data,
|
||||||
};
|
})
|
||||||
};
|
|
|
@ -71,3 +71,20 @@ export const connectStatusUpdateStream = () => {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const connectUserStream = () => connectTimelineStream('home', 'user')
|
export const connectUserStream = () => connectTimelineStream('home', 'user')
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export const connectMessageStream = () => {
|
||||||
|
|
||||||
|
return connectStream('chat_messages', null, (dispatch, getState) => {
|
||||||
|
|
||||||
|
return {
|
||||||
|
onConnect() {},
|
||||||
|
onDisconnect() {},
|
||||||
|
onReceive (data) {
|
||||||
|
//
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
|
@ -44,20 +44,17 @@ const fetchSuggestions = (suggestionType, dispatch, getState, unlimited = false)
|
||||||
|
|
||||||
const fetchSuggestionsRequest = (suggestionType) => ({
|
const fetchSuggestionsRequest = (suggestionType) => ({
|
||||||
type: SUGGESTIONS_FETCH_REQUEST,
|
type: SUGGESTIONS_FETCH_REQUEST,
|
||||||
skipLoading: true,
|
|
||||||
suggestionType,
|
suggestionType,
|
||||||
})
|
})
|
||||||
|
|
||||||
const fetchSuggestionsSuccess = (accounts, suggestionType) => ({
|
const fetchSuggestionsSuccess = (accounts, suggestionType) => ({
|
||||||
type: SUGGESTIONS_FETCH_SUCCESS,
|
type: SUGGESTIONS_FETCH_SUCCESS,
|
||||||
skipLoading: true,
|
|
||||||
accounts,
|
accounts,
|
||||||
suggestionType
|
suggestionType
|
||||||
})
|
})
|
||||||
|
|
||||||
const fetchSuggestionsFail = (error, suggestionType) => ({
|
const fetchSuggestionsFail = (error, suggestionType) => ({
|
||||||
type: SUGGESTIONS_FETCH_FAIL,
|
type: SUGGESTIONS_FETCH_FAIL,
|
||||||
skipLoading: true,
|
|
||||||
skipAlert: true,
|
skipAlert: true,
|
||||||
error,
|
error,
|
||||||
suggestionType,
|
suggestionType,
|
||||||
|
|
|
@ -1,107 +1,115 @@
|
||||||
import { Map as ImmutableMap, List as ImmutableList, toJS } from 'immutable';
|
import { Map as ImmutableMap, List as ImmutableList, toJS } from 'immutable'
|
||||||
import { importFetchedStatus, importFetchedStatuses } from './importer';
|
import noop from 'lodash.noop'
|
||||||
import api, { getLinks } from '../api';
|
import { importFetchedStatus, importFetchedStatuses } from './importer'
|
||||||
|
import api, { getLinks } from '../api'
|
||||||
import { fetchRelationships } from './accounts'
|
import { fetchRelationships } from './accounts'
|
||||||
|
|
||||||
export const TIMELINE_UPDATE = 'TIMELINE_UPDATE';
|
export const TIMELINE_UPDATE = 'TIMELINE_UPDATE'
|
||||||
export const TIMELINE_DELETE = 'TIMELINE_DELETE';
|
export const TIMELINE_DELETE = 'TIMELINE_DELETE'
|
||||||
export const TIMELINE_CLEAR = 'TIMELINE_CLEAR';
|
export const TIMELINE_CLEAR = 'TIMELINE_CLEAR'
|
||||||
export const TIMELINE_UPDATE_QUEUE = 'TIMELINE_UPDATE_QUEUE';
|
export const TIMELINE_UPDATE_QUEUE = 'TIMELINE_UPDATE_QUEUE'
|
||||||
export const TIMELINE_DEQUEUE = 'TIMELINE_DEQUEUE';
|
export const TIMELINE_DEQUEUE = 'TIMELINE_DEQUEUE'
|
||||||
export const TIMELINE_SCROLL_TOP = 'TIMELINE_SCROLL_TOP';
|
export const TIMELINE_SCROLL_TOP = 'TIMELINE_SCROLL_TOP'
|
||||||
|
|
||||||
export const TIMELINE_EXPAND_REQUEST = 'TIMELINE_EXPAND_REQUEST';
|
export const TIMELINE_EXPAND_REQUEST = 'TIMELINE_EXPAND_REQUEST'
|
||||||
export const TIMELINE_EXPAND_SUCCESS = 'TIMELINE_EXPAND_SUCCESS';
|
export const TIMELINE_EXPAND_SUCCESS = 'TIMELINE_EXPAND_SUCCESS'
|
||||||
export const TIMELINE_EXPAND_FAIL = 'TIMELINE_EXPAND_FAIL';
|
export const TIMELINE_EXPAND_FAIL = 'TIMELINE_EXPAND_FAIL'
|
||||||
|
|
||||||
export const TIMELINE_CONNECT = 'TIMELINE_CONNECT';
|
export const TIMELINE_CONNECT = 'TIMELINE_CONNECT'
|
||||||
export const TIMELINE_DISCONNECT = 'TIMELINE_DISCONNECT';
|
export const TIMELINE_DISCONNECT = 'TIMELINE_DISCONNECT'
|
||||||
|
|
||||||
export const MAX_QUEUED_ITEMS = 40;
|
export const MAX_QUEUED_ITEMS = 40
|
||||||
|
|
||||||
export function updateTimeline(timeline, status, accept) {
|
const parseTags = (tags = {}, mode) => {
|
||||||
return dispatch => {
|
return (tags[mode] || []).map((tag) => tag.value)
|
||||||
if (typeof accept === 'function' && !accept(status)) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch(importFetchedStatus(status));
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export const updateTimeline = (timeline, status, accept) => (dispatch) => {
|
||||||
|
if (typeof accept === 'function' && !accept(status)) return
|
||||||
|
|
||||||
|
dispatch(importFetchedStatus(status))
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: TIMELINE_UPDATE,
|
type: TIMELINE_UPDATE,
|
||||||
timeline,
|
timeline,
|
||||||
status,
|
status,
|
||||||
});
|
})
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export function updateTimelineQueue(timeline, status, accept) {
|
|
||||||
return dispatch => {
|
|
||||||
if (typeof accept === 'function' && !accept(status)) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export const updateTimelineQueue = (timeline, status, accept) => (dispatch) => {
|
||||||
|
if (typeof accept === 'function' && !accept(status)) return
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: TIMELINE_UPDATE_QUEUE,
|
type: TIMELINE_UPDATE_QUEUE,
|
||||||
timeline,
|
timeline,
|
||||||
status,
|
status,
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
export function forceDequeueTimeline(timeline) {
|
/**
|
||||||
return (dispatch) => {
|
*
|
||||||
|
*/
|
||||||
|
export const forceDequeueTimeline = (timeline) => (dispatch) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: TIMELINE_DEQUEUE,
|
type: TIMELINE_DEQUEUE,
|
||||||
timeline,
|
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);
|
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;
|
let shouldDispatchDequeue = true
|
||||||
|
|
||||||
if (totalQueuedItemsCount === 0) {
|
if (totalQueuedItemsCount === 0) return
|
||||||
return;
|
|
||||||
} else if (totalQueuedItemsCount > 0 && totalQueuedItemsCount <= MAX_QUEUED_ITEMS) {
|
|
||||||
queuedItems.forEach(status => {
|
if (totalQueuedItemsCount > 0 && totalQueuedItemsCount <= MAX_QUEUED_ITEMS) {
|
||||||
dispatch(updateTimeline(timeline, status.toJS(), null));
|
queuedItems.forEach((status) => {
|
||||||
});
|
dispatch(updateTimeline(timeline, status.toJS(), null))
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
if (typeof expandFunc === 'function') {
|
if (typeof expandFunc === 'function') {
|
||||||
dispatch(clearTimeline(timeline));
|
dispatch(clearTimeline(timeline))
|
||||||
expandFunc();
|
expandFunc()
|
||||||
} else {
|
} else {
|
||||||
if (timeline === 'home') {
|
if (timeline === 'home') {
|
||||||
dispatch(clearTimeline(timeline));
|
dispatch(clearTimeline(timeline))
|
||||||
dispatch(expandHomeTimeline(optionalExpandArgs));
|
dispatch(expandHomeTimeline(optionalExpandArgs))
|
||||||
} else if (timeline === 'community') {
|
} else if (timeline === 'community') {
|
||||||
dispatch(clearTimeline(timeline));
|
dispatch(clearTimeline(timeline))
|
||||||
dispatch(expandCommunityTimeline(optionalExpandArgs));
|
dispatch(expandCommunityTimeline(optionalExpandArgs))
|
||||||
} else {
|
} else {
|
||||||
shouldDispatchDequeue = false;
|
shouldDispatchDequeue = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!shouldDispatchDequeue) return;
|
if (!shouldDispatchDequeue) return
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: TIMELINE_DEQUEUE,
|
type: TIMELINE_DEQUEUE,
|
||||||
timeline,
|
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')]);
|
export const deleteFromTimelines = (id) => (dispatch, getState) => {
|
||||||
const reblogOf = getState().getIn(['statuses', id, 'reblog'], null);
|
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({
|
dispatch({
|
||||||
type: TIMELINE_DELETE,
|
type: TIMELINE_DELETE,
|
||||||
|
@ -109,25 +117,23 @@ export function deleteFromTimelines(id) {
|
||||||
accountId,
|
accountId,
|
||||||
references,
|
references,
|
||||||
reblogOf,
|
reblogOf,
|
||||||
});
|
})
|
||||||
};
|
}
|
||||||
};
|
|
||||||
|
|
||||||
export function clearTimeline(timeline) {
|
/**
|
||||||
return (dispatch) => {
|
*
|
||||||
dispatch({ type: TIMELINE_CLEAR, timeline });
|
*/
|
||||||
};
|
export const clearTimeline = (timeline) => (dispatch) => {
|
||||||
};
|
dispatch({
|
||||||
|
type: TIMELINE_CLEAR,
|
||||||
|
timeline
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const noOp = () => { };
|
/**
|
||||||
|
*
|
||||||
const parseTags = (tags = {}, mode) => {
|
*/
|
||||||
return (tags[mode] || []).map((tag) => {
|
export const expandTimeline = (timelineId, path, params = {}, done = noop) => (dispatch, getState) => {
|
||||||
return tag.value;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const expandTimeline = (timelineId, path, params = {}, done = noOp) => (dispatch, getState) => {
|
|
||||||
const timeline = getState().getIn(['timelines', timelineId], ImmutableMap())
|
const timeline = getState().getIn(['timelines', timelineId], ImmutableMap())
|
||||||
const isLoadingMore = !!params.max_id
|
const isLoadingMore = !!params.max_id
|
||||||
|
|
||||||
|
@ -156,37 +162,13 @@ 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);
|
const expandTimelineRequest = (timeline, isLoadingMore) => ({
|
||||||
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) => {
|
|
||||||
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,
|
type: TIMELINE_EXPAND_REQUEST,
|
||||||
timeline,
|
timeline,
|
||||||
skipLoading: !isLoadingMore,
|
skipLoading: !isLoadingMore,
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
export function expandTimelineSuccess(timeline, statuses, next, partial, isLoadingRecent, isLoadingMore) {
|
const expandTimelineSuccess = (timeline, statuses, next, partial, isLoadingRecent, isLoadingMore) => ({
|
||||||
return {
|
|
||||||
type: TIMELINE_EXPAND_SUCCESS,
|
type: TIMELINE_EXPAND_SUCCESS,
|
||||||
timeline,
|
timeline,
|
||||||
statuses,
|
statuses,
|
||||||
|
@ -194,36 +176,165 @@ export function expandTimelineSuccess(timeline, statuses, next, partial, isLoadi
|
||||||
partial,
|
partial,
|
||||||
isLoadingRecent,
|
isLoadingRecent,
|
||||||
skipLoading: !isLoadingMore,
|
skipLoading: !isLoadingMore,
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
export function expandTimelineFail(timeline, error, isLoadingMore) {
|
const expandTimelineFail = (timeline, error, isLoadingMore) => ({
|
||||||
return {
|
|
||||||
type: TIMELINE_EXPAND_FAIL,
|
type: TIMELINE_EXPAND_FAIL,
|
||||||
timeline,
|
timeline,
|
||||||
error,
|
error,
|
||||||
skipLoading: !isLoadingMore,
|
skipLoading: !isLoadingMore,
|
||||||
};
|
})
|
||||||
};
|
|
||||||
|
|
||||||
export function connectTimeline(timeline) {
|
/**
|
||||||
return {
|
*
|
||||||
type: TIMELINE_CONNECT,
|
*/
|
||||||
timeline,
|
export const scrollTopTimeline = (timeline, top) => ({
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export function disconnectTimeline(timeline) {
|
|
||||||
return {
|
|
||||||
type: TIMELINE_DISCONNECT,
|
|
||||||
timeline,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export function scrollTopTimeline(timeline, top) {
|
|
||||||
return {
|
|
||||||
type: TIMELINE_SCROLL_TOP,
|
type: TIMELINE_SCROLL_TOP,
|
||||||
timeline,
|
timeline,
|
||||||
top,
|
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)
|
||||||
|
}
|
||||||
|
|
|
@ -80,7 +80,7 @@ class Account extends ImmutablePureComponent {
|
||||||
</Button>
|
</Button>
|
||||||
) : <AccountActionButton account={account} isSmall />
|
) : <AccountActionButton account={account} isSmall />
|
||||||
|
|
||||||
const avatarSize = compact ? 42 : 52
|
const avatarSize = compact ? 40 : 52
|
||||||
const dismissBtn = !showDismiss ? null : (
|
const dismissBtn = !showDismiss ? null : (
|
||||||
<Button
|
<Button
|
||||||
isNarrow
|
isNarrow
|
||||||
|
|
|
@ -230,7 +230,7 @@ const mapDispatchToProps = (dispatch) => ({
|
||||||
onOpenStatusOptions(targetRef, status) {
|
onOpenStatusOptions(targetRef, status) {
|
||||||
dispatch(openPopover('STATUS_OPTIONS', {
|
dispatch(openPopover('STATUS_OPTIONS', {
|
||||||
targetRef,
|
targetRef,
|
||||||
status,
|
statusId: status.get('id'),
|
||||||
position: 'top',
|
position: 'top',
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
|
|
|
@ -126,7 +126,7 @@ const messages = defineMessages({
|
||||||
down: { id: 'keyboard_shortcuts.down', defaultMessage: 'move down in the list' },
|
down: { id: 'keyboard_shortcuts.down', defaultMessage: 'move down in the list' },
|
||||||
column: { id: 'keyboard_shortcuts.column', defaultMessage: 'focus a status in one of the columns' },
|
column: { id: 'keyboard_shortcuts.column', defaultMessage: 'focus a status in one of the columns' },
|
||||||
compose: { id: 'keyboard_shortcuts.compose', defaultMessage: 'focus the compose textarea' },
|
compose: { id: 'keyboard_shortcuts.compose', defaultMessage: 'focus the compose textarea' },
|
||||||
gab: { id: 'keyboard_shortcuts.toot', defaultMessage: 'start a brand new gab' },
|
gab: { id: 'keyboard_shortcuts.gab', defaultMessage: 'start a brand new gab' },
|
||||||
back: { id: 'keyboard_shortcuts.back', defaultMessage: 'navigate back' },
|
back: { id: 'keyboard_shortcuts.back', defaultMessage: 'navigate back' },
|
||||||
search: { id: 'keyboard_shortcuts.search', defaultMessage: 'focus search' },
|
search: { id: 'keyboard_shortcuts.search', defaultMessage: 'focus search' },
|
||||||
unfocus: { id: 'keyboard_shortcuts.unfocus', defaultMessage: 'un-focus compose textarea/search' },
|
unfocus: { id: 'keyboard_shortcuts.unfocus', defaultMessage: 'un-focus compose textarea/search' },
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { connect } from 'react-redux'
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import { defineMessages, injectIntl } from 'react-intl'
|
import { defineMessages, injectIntl } from 'react-intl'
|
||||||
import { fetchGroups } from '../../actions/groups'
|
import { fetchGroupsByTab } from '../../actions/groups'
|
||||||
import PanelLayout from './panel_layout'
|
import PanelLayout from './panel_layout'
|
||||||
import GroupListItem from '../group_list_item'
|
import GroupListItem from '../group_list_item'
|
||||||
import ScrollableList from '../scrollable_list'
|
import ScrollableList from '../scrollable_list'
|
||||||
|
@ -26,13 +26,13 @@ class GroupsPanel extends ImmutablePureComponent {
|
||||||
|
|
||||||
componentDidUpdate(prevProps, prevState, snapshot) {
|
componentDidUpdate(prevProps, prevState, snapshot) {
|
||||||
if (!prevState.fetched && this.state.fetched) {
|
if (!prevState.fetched && this.state.fetched) {
|
||||||
this.props.onFetchGroups(this.props.groupType)
|
this.props.onFetchGroupsByTab(this.props.groupType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
if (!this.props.isLazy) {
|
if (!this.props.isLazy) {
|
||||||
this.props.onFetchGroups(this.props.groupType)
|
this.props.onFetchGroupsByTab(this.props.groupType)
|
||||||
this.setState({ fetched: true })
|
this.setState({ fetched: true })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ const mapStateToProps = (state, { groupType }) => ({
|
||||||
})
|
})
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
onFetchGroups: (type) => dispatch(fetchGroups(type))
|
onFetchGroupsByTab: (type) => dispatch(fetchGroupsByTab(type))
|
||||||
})
|
})
|
||||||
|
|
||||||
GroupsPanel.propTypes = {
|
GroupsPanel.propTypes = {
|
||||||
|
|
|
@ -5,13 +5,16 @@ import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl'
|
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl'
|
||||||
import { me, isStaff, boostModal, deleteModal } from '../../initial_state'
|
import { me, isStaff, boostModal, deleteModal } from '../../initial_state'
|
||||||
|
import { makeGetStatus } from '../../selectors'
|
||||||
import {
|
import {
|
||||||
repost,
|
repost,
|
||||||
unrepost,
|
unrepost,
|
||||||
pin,
|
pin,
|
||||||
unpin,
|
unpin,
|
||||||
|
isPin,
|
||||||
bookmark,
|
bookmark,
|
||||||
unbookmark,
|
unbookmark,
|
||||||
|
isBookmark,
|
||||||
} from '../../actions/interactions';
|
} from '../../actions/interactions';
|
||||||
import {
|
import {
|
||||||
deleteStatus,
|
deleteStatus,
|
||||||
|
@ -24,6 +27,7 @@ import {
|
||||||
groupRemoveStatus,
|
groupRemoveStatus,
|
||||||
pinGroupStatus,
|
pinGroupStatus,
|
||||||
unpinGroupStatus,
|
unpinGroupStatus,
|
||||||
|
isPinnedGroupStatus,
|
||||||
} from '../../actions/groups'
|
} from '../../actions/groups'
|
||||||
import { initReport } from '../../actions/reports'
|
import { initReport } from '../../actions/reports'
|
||||||
import { openModal } from '../../actions/modal'
|
import { openModal } from '../../actions/modal'
|
||||||
|
@ -51,11 +55,23 @@ class StatusOptionsPopover extends ImmutablePureComponent {
|
||||||
]
|
]
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
const {
|
||||||
|
status,
|
||||||
|
statusId,
|
||||||
|
groupRelationships,
|
||||||
|
} = this.props
|
||||||
|
|
||||||
|
if (status.get('pinnable')) {
|
||||||
|
this.props.fetchIsPin(statusId)
|
||||||
|
}
|
||||||
|
this.props.fetchIsBookmark(statusId)
|
||||||
|
|
||||||
|
if (!!status.get('group')) {
|
||||||
|
this.props.fetchIsPinnedGroupStatus(status.getIn(['group', 'id'], null), statusId)
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.props.groupRelationships && this.props.groupId) {
|
if (!this.props.groupRelationships && this.props.groupId) {
|
||||||
this.props.onFetchGroupRelationships(this.props.groupId)
|
this.props.onFetchGroupRelationships(this.props.groupId)
|
||||||
// : todo :
|
|
||||||
// check if pin
|
|
||||||
// check if bookmark
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,11 +147,15 @@ class StatusOptionsPopover extends ImmutablePureComponent {
|
||||||
isXS,
|
isXS,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
|
if (!status) return <div />
|
||||||
|
|
||||||
const mutingConversation = status.get('muted')
|
const mutingConversation = status.get('muted')
|
||||||
const publicStatus = ['public', 'unlisted'].includes(status.get('visibility'))
|
const publicStatus = ['public', 'unlisted'].includes(status.get('visibility'))
|
||||||
const isReply = !!status.get('in_reply_to_id')
|
const isReply = !!status.get('in_reply_to_id')
|
||||||
const withGroupAdmin = !!groupRelationships ? (groupRelationships.get('admin') || groupRelationships.get('moderator')) : false
|
const withGroupAdmin = !!groupRelationships ? (groupRelationships.get('admin') || groupRelationships.get('moderator')) : false
|
||||||
|
|
||||||
|
console.log("publicStatus:", status, publicStatus)
|
||||||
|
|
||||||
let menu = []
|
let menu = []
|
||||||
|
|
||||||
if (me) {
|
if (me) {
|
||||||
|
@ -296,13 +316,15 @@ const messages = defineMessages({
|
||||||
share: { id: 'status.share_gab', defaultMessage: 'Share gab' },
|
share: { id: 'status.share_gab', defaultMessage: 'Share gab' },
|
||||||
})
|
})
|
||||||
|
|
||||||
const mapStateToProps = (state, { status }) => {
|
const mapStateToProps = (state, { statusId }) => {
|
||||||
if (!me) return null
|
if (!me) return null
|
||||||
|
|
||||||
|
const status = statusId ? makeGetStatus()(state, { id: statusId }) : undefined
|
||||||
const groupId = status ? status.getIn(['group', 'id']) : undefined
|
const groupId = status ? status.getIn(['group', 'id']) : undefined
|
||||||
const groupRelationships = state.getIn(['group_relationships', groupId])
|
const groupRelationships = state.getIn(['group_relationships', groupId])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
status,
|
||||||
groupId,
|
groupId,
|
||||||
groupRelationships,
|
groupRelationships,
|
||||||
isPro: state.getIn(['accounts', me, 'is_pro']),
|
isPro: state.getIn(['accounts', me, 'is_pro']),
|
||||||
|
@ -311,6 +333,18 @@ const mapStateToProps = (state, { status }) => {
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
|
||||||
|
fetchIsPin(statusId) {
|
||||||
|
dispatch(isPin(statusId))
|
||||||
|
},
|
||||||
|
|
||||||
|
fetchIsBookmark(statusId) {
|
||||||
|
dispatch(isBookmark(statusId))
|
||||||
|
},
|
||||||
|
|
||||||
|
fetchIsPinnedGroupStatus(groupId, statusId) {
|
||||||
|
dispatch(isPinnedGroupStatus(groupId, statusId))
|
||||||
|
},
|
||||||
|
|
||||||
onPin(status) {
|
onPin(status) {
|
||||||
dispatch(closePopover())
|
dispatch(closePopover())
|
||||||
|
|
||||||
|
@ -440,7 +474,8 @@ const mapDispatchToProps = (dispatch) => ({
|
||||||
})
|
})
|
||||||
|
|
||||||
StatusOptionsPopover.propTypes = {
|
StatusOptionsPopover.propTypes = {
|
||||||
status: ImmutablePropTypes.map.isRequired,
|
status: ImmutablePropTypes.map,
|
||||||
|
statusId: PropTypes.string.isRequired,
|
||||||
groupRelationships: ImmutablePropTypes.map,
|
groupRelationships: ImmutablePropTypes.map,
|
||||||
groupId: PropTypes.string,
|
groupId: PropTypes.string,
|
||||||
onQuote: PropTypes.func.isRequired,
|
onQuote: PropTypes.func.isRequired,
|
||||||
|
@ -454,6 +489,9 @@ StatusOptionsPopover.propTypes = {
|
||||||
onFetchGroupRelationships: PropTypes.func.isRequired,
|
onFetchGroupRelationships: PropTypes.func.isRequired,
|
||||||
onOpenProUpgradeModal: PropTypes.func.isRequired,
|
onOpenProUpgradeModal: PropTypes.func.isRequired,
|
||||||
onClosePopover: PropTypes.func.isRequired,
|
onClosePopover: PropTypes.func.isRequired,
|
||||||
|
fetchIsPinnedGroupStatus: PropTypes.func.isRequired,
|
||||||
|
fetchIsBookmark: PropTypes.func.isRequired,
|
||||||
|
fetchIsPin: PropTypes.func.isRequired,
|
||||||
isXS: PropTypes.bool,
|
isXS: PropTypes.bool,
|
||||||
isPro: PropTypes.bool,
|
isPro: PropTypes.bool,
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { CX } from '../constants'
|
||||||
|
|
||||||
class StatusActionBar extends ImmutablePureComponent {
|
class StatusActionBar extends ImmutablePureComponent {
|
||||||
|
|
||||||
updateOnProps = ['status']
|
// updateOnProps = ['status']
|
||||||
|
|
||||||
handleShareClick = () => {
|
handleShareClick = () => {
|
||||||
this.props.onShare(this.shareButton, this.props.status)
|
this.props.onShare(this.shareButton, this.props.status)
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { connect } from 'react-redux'
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import { Set as ImmutableSet } from 'immutable';
|
import { Set as ImmutableSet } from 'immutable';
|
||||||
import noop from 'lodash/noop';
|
import noop from 'lodash.noop'
|
||||||
import { toggleStatusReport } from '../actions/reports';
|
import { toggleStatusReport } from '../actions/reports';
|
||||||
import { MediaGallery, Video } from '../features/ui/util/async_components';
|
import { MediaGallery, Video } from '../features/ui/util/async_components';
|
||||||
import Bundle from '../features/ui/util/bundle';
|
import Bundle from '../features/ui/util/bundle';
|
||||||
|
|
|
@ -216,7 +216,7 @@ const mapDispatchToProps = (dispatch) => ({
|
||||||
onOpenStatusOptionsPopover(targetRef, status) {
|
onOpenStatusOptionsPopover(targetRef, status) {
|
||||||
dispatch(openPopover('STATUS_OPTIONS', {
|
dispatch(openPopover('STATUS_OPTIONS', {
|
||||||
targetRef,
|
targetRef,
|
||||||
status,
|
statusId: status.get('id'),
|
||||||
position: 'left-start',
|
position: 'left-start',
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import { fetchGroups } from '../../actions/groups'
|
import { fetchGroupsByTab } from '../../actions/groups'
|
||||||
import GroupCollectionItem from '../group_collection_item'
|
import GroupCollectionItem from '../group_collection_item'
|
||||||
import TimelineInjectionLayout from './timeline_injection_layout'
|
import TimelineInjectionLayout from './timeline_injection_layout'
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ class FeaturedGroupsInjection extends ImmutablePureComponent {
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
if (!this.props.isFetched) {
|
if (!this.props.isFetched) {
|
||||||
this.props.onFetchGroups('featured')
|
this.props.onFetchGroupsByTap('featured')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,14 +59,14 @@ const mapStateToProps = (state) => ({
|
||||||
})
|
})
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
onFetchGroups: (tab) => dispatch(fetchGroups(tab)),
|
onFetchGroupsByTap: (tab) => dispatch(fetchGroupsByTab(tab)),
|
||||||
})
|
})
|
||||||
|
|
||||||
FeaturedGroupsInjection.propTypes = {
|
FeaturedGroupsInjection.propTypes = {
|
||||||
groupIds: ImmutablePropTypes.list,
|
groupIds: ImmutablePropTypes.list,
|
||||||
isFetched: PropTypes.bool.isRequired,
|
isFetched: PropTypes.bool.isRequired,
|
||||||
isLoading: PropTypes.bool.isRequired,
|
isLoading: PropTypes.bool.isRequired,
|
||||||
onFetchGroups: PropTypes.func.isRequired,
|
onFetchGroupsByTab: PropTypes.func.isRequired,
|
||||||
injectionId: PropTypes.string.isRequired,
|
injectionId: PropTypes.string.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -134,6 +134,8 @@ export const GROUP_TIMELINE_SORTING_TYPE_NEWEST = 'newest'
|
||||||
export const GROUP_TIMELINE_SORTING_TYPE_RECENT_ACTIVITY = 'recent'
|
export const GROUP_TIMELINE_SORTING_TYPE_RECENT_ACTIVITY = 'recent'
|
||||||
export const GROUP_TIMELINE_SORTING_TYPE_TOP = 'top'
|
export const GROUP_TIMELINE_SORTING_TYPE_TOP = 'top'
|
||||||
|
|
||||||
|
export const ACCEPTED_GROUP_TABS = ['new', 'featured', 'member', 'admin']
|
||||||
|
|
||||||
export const GROUP_TIMELINE_SORTING_TYPE_TOP_OPTION_TODAY = 'today'
|
export const GROUP_TIMELINE_SORTING_TYPE_TOP_OPTION_TODAY = 'today'
|
||||||
export const GROUP_TIMELINE_SORTING_TYPE_TOP_OPTION_WEEKLY = 'weekly'
|
export const GROUP_TIMELINE_SORTING_TYPE_TOP_OPTION_WEEKLY = 'weekly'
|
||||||
export const GROUP_TIMELINE_SORTING_TYPE_TOP_OPTION_MONTHLY = 'monthly'
|
export const GROUP_TIMELINE_SORTING_TYPE_TOP_OPTION_MONTHLY = 'monthly'
|
||||||
|
|
|
@ -11,6 +11,7 @@ import Account from '../components/account'
|
||||||
import Block from '../components/block'
|
import Block from '../components/block'
|
||||||
import BlockHeading from '../components/block_heading'
|
import BlockHeading from '../components/block_heading'
|
||||||
import ScrollableList from '../components/scrollable_list'
|
import ScrollableList from '../components/scrollable_list'
|
||||||
|
import AccountPlaceholder from '../components/placeholder/account_placeholder'
|
||||||
|
|
||||||
class Blocks extends ImmutablePureComponent {
|
class Blocks extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
@ -40,16 +41,19 @@ class Blocks extends ImmutablePureComponent {
|
||||||
onLoadMore={this.handleLoadMore}
|
onLoadMore={this.handleLoadMore}
|
||||||
hasMore={hasMore}
|
hasMore={hasMore}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
|
showLoading={isLoading}
|
||||||
emptyMessage={emptyMessage}
|
emptyMessage={emptyMessage}
|
||||||
|
placeholderComponent={AccountPlaceholder}
|
||||||
|
placeholderCount={3}
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
accountIds && accountIds.map((id) =>
|
accountIds && accountIds.map((id) => (
|
||||||
<Account
|
<Account
|
||||||
key={`blocked-accounts-${id}`}
|
key={`blocked-accounts-${id}`}
|
||||||
id={id}
|
id={id}
|
||||||
compact
|
compact
|
||||||
/>
|
/>
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
</ScrollableList>
|
</ScrollableList>
|
||||||
</Block>
|
</Block>
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { connect } from 'react-redux'
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import { injectIntl, defineMessages } from 'react-intl'
|
import { injectIntl, defineMessages } from 'react-intl'
|
||||||
import { fetchGroups } from '../actions/groups'
|
import { fetchGroupsByTab } from '../actions/groups'
|
||||||
import { openPopover } from '../actions/popover'
|
import { openPopover } from '../actions/popover'
|
||||||
import { POPOVER_GROUP_LIST_SORT_OPTIONS } from '../constants'
|
import { POPOVER_GROUP_LIST_SORT_OPTIONS } from '../constants'
|
||||||
import Block from '../components/block'
|
import Block from '../components/block'
|
||||||
|
@ -16,12 +16,12 @@ import GroupListItem from '../components/group_list_item'
|
||||||
class GroupsCollection extends ImmutablePureComponent {
|
class GroupsCollection extends ImmutablePureComponent {
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
this.props.onFetchGroups(this.props.activeTab)
|
this.props.onFetchGroupsByTab(this.props.activeTab)
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(oldProps) {
|
componentDidUpdate(oldProps) {
|
||||||
if (this.props.activeTab && this.props.activeTab !== oldProps.activeTab) {
|
if (this.props.activeTab && this.props.activeTab !== oldProps.activeTab) {
|
||||||
this.props.onFetchGroups(this.props.activeTab)
|
this.props.onFetchGroupsByTab(this.props.activeTab)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ const mapStateToProps = (state, { activeTab }) => ({
|
||||||
})
|
})
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
onFetchGroups: (tab) => dispatch(fetchGroups(tab)),
|
onFetchGroupsByTab: (tab) => dispatch(fetchGroupsByTab(tab)),
|
||||||
onOpenSortPopover(tab, targetRef) {
|
onOpenSortPopover(tab, targetRef) {
|
||||||
dispatch(openPopover(POPOVER_GROUP_LIST_SORT_OPTIONS, {
|
dispatch(openPopover(POPOVER_GROUP_LIST_SORT_OPTIONS, {
|
||||||
targetRef,
|
targetRef,
|
||||||
|
|
|
@ -11,7 +11,7 @@ import {
|
||||||
} from '../constants'
|
} from '../constants'
|
||||||
import { me } from '../initial_state'
|
import { me } from '../initial_state'
|
||||||
import { saveShownOnboarding } from '../actions/settings'
|
import { saveShownOnboarding } from '../actions/settings'
|
||||||
import { fetchGroups } from '../actions/groups'
|
import { fetchGroupsByTab } from '../actions/groups'
|
||||||
import { saveUserProfileInformation } from '../actions/user'
|
import { saveUserProfileInformation } from '../actions/user'
|
||||||
import { makeGetAccount } from '../selectors'
|
import { makeGetAccount } from '../selectors'
|
||||||
import Button from '../components/button'
|
import Button from '../components/button'
|
||||||
|
@ -414,7 +414,7 @@ const mapStateToProps = (state) => ({
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
onSaveShownOnboarding: () => dispatch(saveShownOnboarding()),
|
onSaveShownOnboarding: () => dispatch(saveShownOnboarding()),
|
||||||
onFetchFeaturedGroups: () => dispatch(fetchGroups('featured')),
|
onFetchFeaturedGroups: () => dispatch(fetchGroupsByTab('featured')),
|
||||||
onSaveUserProfileInformation(data) {
|
onSaveUserProfileInformation(data) {
|
||||||
dispatch(saveUserProfileInformation(data))
|
dispatch(saveUserProfileInformation(data))
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,45 +4,65 @@ import { connect } from 'react-redux'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import { FormattedMessage } from 'react-intl'
|
import { FormattedMessage } from 'react-intl'
|
||||||
import { fetchLikes } from '../actions/interactions'
|
import debounce from 'lodash.debounce'
|
||||||
|
import { fetchLikes, expandLikes } from '../actions/interactions'
|
||||||
import { fetchStatus } from '../actions/statuses'
|
import { fetchStatus } from '../actions/statuses'
|
||||||
import { makeGetStatus } from '../selectors'
|
import { makeGetStatus } from '../selectors'
|
||||||
import Account from '../components/account'
|
import Account from '../components/account'
|
||||||
import ColumnIndicator from '../components/column_indicator'
|
import ColumnIndicator from '../components/column_indicator'
|
||||||
import ScrollableList from '../components/scrollable_list'
|
import ScrollableList from '../components/scrollable_list'
|
||||||
|
import AccountPlaceholder from '../components/placeholder/account_placeholder'
|
||||||
|
|
||||||
class StatusLikes extends ImmutablePureComponent {
|
class StatusLikes extends ImmutablePureComponent {
|
||||||
|
|
||||||
componentWillMount () {
|
componentWillMount () {
|
||||||
this.props.dispatch(fetchLikes(this.props.statusId))
|
this.props.dispatch(fetchLikes(this.props.statusId))
|
||||||
this.props.dispatch(fetchStatus(this.props.statusId))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
if (nextProps.statusId !== this.props.statusId && nextProps.statusId) {
|
if (nextProps.statusId !== this.props.statusId && nextProps.statusId) {
|
||||||
this.props.dispatch(fetchLikes(nextProps.statusId))
|
this.props.dispatch(fetchLikes(nextProps.statusId))
|
||||||
this.props.dispatch(fetchStatus(nextProps.statusId))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleLoadMore = debounce(() => {
|
||||||
|
this.props.dispatch(expandLikes(this.props.statusId))
|
||||||
|
}, 300, { leading: true })
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { accountIds, status } = this.props
|
const {
|
||||||
|
accountIds,
|
||||||
|
isLoading,
|
||||||
|
hasMore,
|
||||||
|
list,
|
||||||
|
statusId,
|
||||||
|
} = this.props
|
||||||
|
|
||||||
if (!accountIds) {
|
if (!statusId) {
|
||||||
return <ColumnIndicator type='loading' />
|
|
||||||
} else if (!status) {
|
|
||||||
return <ColumnIndicator type='missing' />
|
return <ColumnIndicator type='missing' />
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const accountIdCount = !!accountIds ? accountIds.count() : 0
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScrollableList
|
<ScrollableList
|
||||||
scrollKey='likes'
|
scrollKey='likes'
|
||||||
emptyMessage={<FormattedMessage id='status.likes.empty' defaultMessage='No one has liked this gab yet. When someone does, they will show up here.' />}
|
emptyMessage={<FormattedMessage id='status.likes.empty' defaultMessage='No one has liked this gab yet. When someone does, they will show up here.' />}
|
||||||
|
onLoadMore={this.handleLoadMore}
|
||||||
|
hasMore={hasMore}
|
||||||
|
isLoading={isLoading && accountIdCount === 0}
|
||||||
|
showLoading={isLoading && accountIdCount === 0}
|
||||||
|
placeholderComponent={AccountPlaceholder}
|
||||||
|
placeholderCount={3}
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
accountIds.map(id =>
|
accountIdCount > 0 && accountIds.map((id) => (
|
||||||
<Account key={id} id={id} />
|
<Account
|
||||||
)
|
compact
|
||||||
|
key={`liked-by-${id}`}
|
||||||
|
id={id}
|
||||||
|
/>
|
||||||
|
))
|
||||||
}
|
}
|
||||||
</ScrollableList>
|
</ScrollableList>
|
||||||
)
|
)
|
||||||
|
@ -52,23 +72,16 @@ class StatusLikes extends ImmutablePureComponent {
|
||||||
|
|
||||||
const mapStateToProps = (state, props) => {
|
const mapStateToProps = (state, props) => {
|
||||||
const statusId = props.params ? props.params.statusId : props.statusId
|
const statusId = props.params ? props.params.statusId : props.statusId
|
||||||
|
|
||||||
const getStatus = makeGetStatus()
|
|
||||||
const status = getStatus(state, {
|
|
||||||
id: statusId
|
|
||||||
})
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
status,
|
accountIds: state.getIn(['user_lists', 'liked_by', statusId, 'items']),
|
||||||
statusId,
|
hasMore: !!state.getIn(['user_lists', 'liked_by', statusId, 'next']),
|
||||||
accountIds: state.getIn(['user_lists', 'liked_by', statusId]),
|
isLoading: state.getIn(['user_lists', 'liked_by', statusId, 'isLoading']),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusLikes.propTypes = {
|
StatusLikes.propTypes = {
|
||||||
accountIds: ImmutablePropTypes.list,
|
accountIds: ImmutablePropTypes.list,
|
||||||
dispatch: PropTypes.func.isRequired,
|
dispatch: PropTypes.func.isRequired,
|
||||||
status: ImmutablePropTypes.map,
|
|
||||||
statusId: PropTypes.string.isRequired,
|
statusId: PropTypes.string.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,45 +4,65 @@ import { connect } from 'react-redux'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import { FormattedMessage } from 'react-intl'
|
import { FormattedMessage } from 'react-intl'
|
||||||
import { fetchReposts } from '../actions/interactions'
|
import debounce from 'lodash.debounce'
|
||||||
|
import { fetchReposts, expandReposts } from '../actions/interactions'
|
||||||
import { fetchStatus } from '../actions/statuses'
|
import { fetchStatus } from '../actions/statuses'
|
||||||
import { makeGetStatus } from '../selectors'
|
import { makeGetStatus } from '../selectors'
|
||||||
import Account from '../components/account'
|
import Account from '../components/account'
|
||||||
import ColumnIndicator from '../components/column_indicator'
|
import ColumnIndicator from '../components/column_indicator'
|
||||||
import ScrollableList from '../components/scrollable_list'
|
import ScrollableList from '../components/scrollable_list'
|
||||||
|
import AccountPlaceholder from '../components/placeholder/account_placeholder'
|
||||||
|
|
||||||
class StatusReposts extends ImmutablePureComponent {
|
class StatusReposts extends ImmutablePureComponent {
|
||||||
|
|
||||||
componentWillMount () {
|
componentWillMount () {
|
||||||
this.props.dispatch(fetchReposts(this.props.statusId))
|
this.props.dispatch(fetchReposts(this.props.statusId))
|
||||||
this.props.dispatch(fetchStatus(this.props.statusId))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
if (nextProps.statusId !== this.props.statusId && nextProps.statusId) {
|
if (nextProps.statusId !== this.props.statusId && nextProps.statusId) {
|
||||||
this.props.dispatch(fetchReposts(nextProps.statusId))
|
this.props.dispatch(fetchReposts(nextProps.statusId))
|
||||||
this.props.dispatch(fetchStatus(nextProps.statusId))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleLoadMore = debounce(() => {
|
||||||
|
this.props.dispatch(expandReposts(this.props.statusId))
|
||||||
|
}, 300, { leading: true })
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { accountIds, status } = this.props
|
const {
|
||||||
|
accountIds,
|
||||||
|
isLoading,
|
||||||
|
hasMore,
|
||||||
|
list,
|
||||||
|
statusId,
|
||||||
|
} = this.props
|
||||||
|
|
||||||
if (!accountIds) {
|
if (!statusId) {
|
||||||
return <ColumnIndicator type='loading' />
|
|
||||||
} else if (!status) {
|
|
||||||
return <ColumnIndicator type='missing' />
|
return <ColumnIndicator type='missing' />
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const accountIdCount = !!accountIds ? accountIds.count() : 0
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScrollableList
|
<ScrollableList
|
||||||
scrollKey='reposts'
|
scrollKey='reposts'
|
||||||
emptyMessage={<FormattedMessage id='status.reposts.empty' defaultMessage='No one has reposted this gab yet. When someone does, they will show up here.' />}
|
emptyMessage={<FormattedMessage id='status.reposts.empty' defaultMessage='No one has reposted this gab yet. When someone does, they will show up here.' />}
|
||||||
|
onLoadMore={this.handleLoadMore}
|
||||||
|
hasMore={hasMore}
|
||||||
|
isLoading={isLoading && accountIdCount === 0}
|
||||||
|
showLoading={isLoading && accountIdCount === 0}
|
||||||
|
placeholderComponent={AccountPlaceholder}
|
||||||
|
placeholderCount={3}
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
accountIds.map(id =>
|
accountIdCount > 0 && accountIds.map((id) => (
|
||||||
<Account key={id} id={id} />
|
<Account
|
||||||
)
|
compact
|
||||||
|
key={`reposted-by-${id}`}
|
||||||
|
id={id}
|
||||||
|
/>
|
||||||
|
))
|
||||||
}
|
}
|
||||||
</ScrollableList>
|
</ScrollableList>
|
||||||
)
|
)
|
||||||
|
@ -52,24 +72,16 @@ class StatusReposts extends ImmutablePureComponent {
|
||||||
|
|
||||||
const mapStateToProps = (state, props) => {
|
const mapStateToProps = (state, props) => {
|
||||||
const statusId = props.params ? props.params.statusId : props.statusId
|
const statusId = props.params ? props.params.statusId : props.statusId
|
||||||
|
|
||||||
const getStatus = makeGetStatus()
|
|
||||||
const status = getStatus(state, {
|
|
||||||
id: statusId,
|
|
||||||
// username: props.params.username,
|
|
||||||
})
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
status,
|
accountIds: state.getIn(['user_lists', 'reblogged_by', statusId, 'items']),
|
||||||
statusId,
|
hasMore: !!state.getIn(['user_lists', 'reblogged_by', statusId, 'next']),
|
||||||
accountIds: state.getIn(['user_lists', 'reblogged_by', statusId]),
|
isLoading: state.getIn(['user_lists', 'reblogged_by', statusId, 'isLoading']),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusReposts.propTypes = {
|
StatusReposts.propTypes = {
|
||||||
accountIds: ImmutablePropTypes.list,
|
accountIds: ImmutablePropTypes.list,
|
||||||
dispatch: PropTypes.func.isRequired,
|
dispatch: PropTypes.func.isRequired,
|
||||||
status: ImmutablePropTypes.map,
|
|
||||||
statusId: PropTypes.string.isRequired,
|
statusId: PropTypes.string.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,6 @@ import {
|
||||||
AccountTimeline,
|
AccountTimeline,
|
||||||
Assets,
|
Assets,
|
||||||
BlockedAccounts,
|
BlockedAccounts,
|
||||||
BlockedDomains,
|
|
||||||
BookmarkedStatuses,
|
BookmarkedStatuses,
|
||||||
CommunityTimeline,
|
CommunityTimeline,
|
||||||
Compose,
|
Compose,
|
||||||
|
|
|
@ -77,6 +77,7 @@ export function ListTimelineSettingsModal() { return import(/* webpackChunkName:
|
||||||
export function MediaGallery() { return import(/* webpackChunkName: "components/media_gallery" */'../../../components/media_gallery') }
|
export function MediaGallery() { return import(/* webpackChunkName: "components/media_gallery" */'../../../components/media_gallery') }
|
||||||
export function MediaGalleryPanel() { return import(/* webpackChunkName: "components/media_gallery_panel" */'../../../components/panel/media_gallery_panel') }
|
export function MediaGalleryPanel() { return import(/* webpackChunkName: "components/media_gallery_panel" */'../../../components/panel/media_gallery_panel') }
|
||||||
export function MediaModal() { return import(/* webpackChunkName: "components/media_modal" */'../../../components/modal/media_modal') }
|
export function MediaModal() { return import(/* webpackChunkName: "components/media_modal" */'../../../components/modal/media_modal') }
|
||||||
|
export function Messages() { return import(/* webpackChunkName: "features/messages" */'../../messages') }
|
||||||
export function Mutes() { return import(/* webpackChunkName: "features/mutes" */'../../mutes') }
|
export function Mutes() { return import(/* webpackChunkName: "features/mutes" */'../../mutes') }
|
||||||
export function MuteModal() { return import(/* webpackChunkName: "modals/mute_modal" */'../../../components/modal/mute_modal') }
|
export function MuteModal() { return import(/* webpackChunkName: "modals/mute_modal" */'../../../components/modal/mute_modal') }
|
||||||
export function NavSettingsPopover() { return import(/* webpackChunkName: "modals/nav_settings_popover" */'../../../components/popover/nav_settings_popover') }
|
export function NavSettingsPopover() { return import(/* webpackChunkName: "modals/nav_settings_popover" */'../../../components/popover/nav_settings_popover') }
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
|
import noop from 'lodash.noop'
|
||||||
import {
|
import {
|
||||||
fetchBundleRequest,
|
fetchBundleRequest,
|
||||||
fetchBundleSuccess,
|
fetchBundleSuccess,
|
||||||
|
@ -8,7 +9,6 @@ import {
|
||||||
} from '../../../actions/bundles'
|
} from '../../../actions/bundles'
|
||||||
|
|
||||||
const emptyComponent = () => null
|
const emptyComponent = () => null
|
||||||
const noop = () => { }
|
|
||||||
|
|
||||||
class Bundle extends React.PureComponent {
|
class Bundle extends React.PureComponent {
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ const defaultFailSuffix = 'FAIL';
|
||||||
|
|
||||||
export default function errorsMiddleware() {
|
export default function errorsMiddleware() {
|
||||||
return ({ dispatch }) => next => action => {
|
return ({ dispatch }) => next => action => {
|
||||||
|
// : todo : use skipAlert!
|
||||||
if (action.type && !action.skipAlert) {
|
if (action.type && !action.skipAlert) {
|
||||||
const isFail = new RegExp(`${defaultFailSuffix}$`, 'g');
|
const isFail = new RegExp(`${defaultFailSuffix}$`, 'g');
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ export default function loadingBarMiddleware(config = {}) {
|
||||||
const promiseTypeSuffixes = config.promiseTypeSuffixes || defaultTypeSuffixes
|
const promiseTypeSuffixes = config.promiseTypeSuffixes || defaultTypeSuffixes
|
||||||
|
|
||||||
return ({ dispatch }) => next => (action) => {
|
return ({ dispatch }) => next => (action) => {
|
||||||
if (action.type && !action.skipLoading) {
|
if (action.type && action.type.indexOf('TIMELINE') > -1) {
|
||||||
const [PENDING, FULFILLED, REJECTED] = promiseTypeSuffixes
|
const [PENDING, FULFILLED, REJECTED] = promiseTypeSuffixes
|
||||||
|
|
||||||
const isPending = new RegExp(`${PENDING}$`, 'g')
|
const isPending = new RegExp(`${PENDING}$`, 'g')
|
||||||
|
|
|
@ -18,7 +18,7 @@ class MessagesPage extends React.PureComponent {
|
||||||
title={title}
|
title={title}
|
||||||
>
|
>
|
||||||
<PageTitle path={title} />
|
<PageTitle path={title} />
|
||||||
{children}
|
|
||||||
</MessagesLayout>
|
</MessagesLayout>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
import {
|
||||||
|
MESSAGE_INPUT_CHANGE,
|
||||||
|
MESSAGE_INPUT_RESET,
|
||||||
|
MESSAGE_SEND_REQUEST,
|
||||||
|
MESSAGE_SEND_SUCCESS,
|
||||||
|
MESSAGE_SEND_FAIL,
|
||||||
|
MESSAGE_DELETE_REQUEST,
|
||||||
|
MESSAGE_DELETE_SUCCESS,
|
||||||
|
MESSAGE_DELETE_FAIL,
|
||||||
|
} from '../actions/lists'
|
||||||
|
import { Map as ImmutableMap, fromJS } from 'immutable'
|
||||||
|
|
||||||
|
const initialState = ImmutableMap({
|
||||||
|
text: '',
|
||||||
|
conversationId: null,
|
||||||
|
idempotencyKey: null,
|
||||||
|
})
|
||||||
|
|
||||||
|
const normalizeList = (state, list) => state.set(list.id, fromJS(list))
|
||||||
|
|
||||||
|
const normalizeLists = (state, lists) => {
|
||||||
|
lists.forEach(list => {
|
||||||
|
state = normalizeList(state, list)
|
||||||
|
})
|
||||||
|
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function lists(state = initialState, action) {
|
||||||
|
switch(action.type) {
|
||||||
|
case LIST_FETCH_SUCCESS:
|
||||||
|
case LIST_CREATE_SUCCESS:
|
||||||
|
case LIST_UPDATE_SUCCESS:
|
||||||
|
return normalizeList(state, action.list);
|
||||||
|
case LISTS_FETCH_SUCCESS:
|
||||||
|
return normalizeLists(state, action.lists);
|
||||||
|
case LIST_DELETE_SUCCESS:
|
||||||
|
case LIST_FETCH_FAIL:
|
||||||
|
return state.set(action.id, false);
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
import {
|
||||||
|
REPOST_REQUEST,
|
||||||
|
UNREPOST_REQUEST,
|
||||||
|
REPOST_FAIL,
|
||||||
|
FAVORITE_REQUEST,
|
||||||
|
FAVORITE_FAIL,
|
||||||
|
UNFAVORITE_REQUEST,
|
||||||
|
} from '../actions/interactions';
|
||||||
|
import {
|
||||||
|
STATUS_REVEAL,
|
||||||
|
STATUS_HIDE,
|
||||||
|
UPDATE_STATUS_STATS,
|
||||||
|
} from '../actions/statuses';
|
||||||
|
import { TIMELINE_DELETE } from '../actions/timelines';
|
||||||
|
import { STATUS_IMPORT, STATUSES_IMPORT } from '../actions/importer';
|
||||||
|
import { Map as ImmutableMap, fromJS } from 'immutable';
|
||||||
|
|
||||||
|
const importStatus = (state, status) => state.set(status.id, fromJS(status));
|
||||||
|
|
||||||
|
const importStatuses = (state, statuses) =>
|
||||||
|
state.withMutations(mutable => statuses.forEach(status => importStatus(mutable, status)));
|
||||||
|
|
||||||
|
const deleteStatus = (state, id, references) => {
|
||||||
|
references.forEach(ref => {
|
||||||
|
state = deleteStatus(state, ref[0], []);
|
||||||
|
});
|
||||||
|
|
||||||
|
return state.delete(id);
|
||||||
|
};
|
||||||
|
|
||||||
|
const initialState = ImmutableMap();
|
||||||
|
|
||||||
|
export default function statuses(state = initialState, action) {
|
||||||
|
switch(action.type) {
|
||||||
|
case STATUS_IMPORT:
|
||||||
|
return importStatus(state, action.status);
|
||||||
|
case STATUSES_IMPORT:
|
||||||
|
return importStatuses(state, action.statuses);
|
||||||
|
case FAVORITE_REQUEST:
|
||||||
|
return state.setIn([action.status.get('id'), 'favourited'], true);
|
||||||
|
case FAVORITE_FAIL:
|
||||||
|
return state.get(action.status.get('id')) === undefined ? state : state.setIn([action.status.get('id'), 'favourited'], false);
|
||||||
|
case UNFAVORITE_REQUEST:
|
||||||
|
return state.setIn([action.status.get('id'), 'favourited'], false);
|
||||||
|
case REPOST_REQUEST:
|
||||||
|
return state.setIn([action.status.get('id'), 'reblogged'], true);
|
||||||
|
case UNREPOST_REQUEST:
|
||||||
|
return state.setIn([action.status.get('id'), 'reblogged'], false);
|
||||||
|
case REPOST_FAIL:
|
||||||
|
return state.get(action.status.get('id')) === undefined ? state : state.setIn([action.status.get('id'), 'reblogged'], false);
|
||||||
|
case STATUS_REVEAL:
|
||||||
|
return state.withMutations((map) => {
|
||||||
|
action.ids.forEach(id => {
|
||||||
|
if (!(state.get(id) === undefined)) {
|
||||||
|
map.setIn([id, 'hidden'], false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
case STATUS_HIDE:
|
||||||
|
return state.withMutations((map) => {
|
||||||
|
action.ids.forEach(id => {
|
||||||
|
if (!(state.get(id) === undefined)) {
|
||||||
|
map.setIn([id, 'hidden'], true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
case TIMELINE_DELETE:
|
||||||
|
return deleteStatus(state, action.id, action.references);
|
||||||
|
case UPDATE_STATUS_STATS:
|
||||||
|
const { status_id } = action.data
|
||||||
|
return state.withMutations((map) => {
|
||||||
|
if (action.data.favourited !== undefined) map.setIn([status_id, 'favourited'], action.data.favourited)
|
||||||
|
if (action.data.favourites_count !== undefined) map.setIn([status_id, 'favourites_count'], action.data.favourites_count)
|
||||||
|
if (action.data.reblogged !== undefined) map.setIn([status_id, 'reblogged'], action.data.reblogged)
|
||||||
|
if (action.data.reblogs_count !== undefined) map.setIn([status_id, 'reblogs_count'], action.data.reblogs_count)
|
||||||
|
if (action.data.replies_count !== undefined) map.setIn([status_id, 'replies_count'], action.data.replies_count)
|
||||||
|
if (action.data.pinned !== undefined) map.setIn([status_id, 'pinned'], action.data.pinned)
|
||||||
|
if (action.data.pinned_by_group !== undefined) map.setIn([status_id, 'pinned_by_group'], action.data.pinned_by_group)
|
||||||
|
if (action.data.bookmarked !== undefined) map.setIn([status_id, 'bookmarked'], action.data.bookmarked)
|
||||||
|
})
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
};
|
|
@ -21,11 +21,10 @@ import {
|
||||||
GROUP_TIMELINE_SORTING_TYPE_TOP,
|
GROUP_TIMELINE_SORTING_TYPE_TOP,
|
||||||
GROUP_TIMELINE_SORTING_TYPE_NEWEST,
|
GROUP_TIMELINE_SORTING_TYPE_NEWEST,
|
||||||
GROUP_TIMELINE_SORTING_TYPE_TOP_OPTION_TODAY,
|
GROUP_TIMELINE_SORTING_TYPE_TOP_OPTION_TODAY,
|
||||||
|
ACCEPTED_GROUP_TABS,
|
||||||
} from '../constants'
|
} from '../constants'
|
||||||
import slugify from '../utils/slugify'
|
import slugify from '../utils/slugify'
|
||||||
|
|
||||||
const tabs = ['new', 'featured', 'member', 'admin']
|
|
||||||
|
|
||||||
const initialState = ImmutableMap({
|
const initialState = ImmutableMap({
|
||||||
sortByValue: GROUP_TIMELINE_SORTING_TYPE_NEWEST,
|
sortByValue: GROUP_TIMELINE_SORTING_TYPE_NEWEST,
|
||||||
sortByTopValue: '',
|
sortByTopValue: '',
|
||||||
|
|
|
@ -8,7 +8,7 @@ const normalizeRelationships = (state, relationships) => {
|
||||||
state = normalizeRelationship(state, relationship);
|
state = normalizeRelationship(state, relationship);
|
||||||
});
|
});
|
||||||
|
|
||||||
return state;
|
return state
|
||||||
};
|
};
|
||||||
|
|
||||||
const initialState = ImmutableMap();
|
const initialState = ImmutableMap();
|
||||||
|
|
|
@ -30,7 +30,7 @@ export default function groups(state = initialState, action) {
|
||||||
case GROUPS_FETCH_SUCCESS:
|
case GROUPS_FETCH_SUCCESS:
|
||||||
return normalizeGroups(state, action.groups)
|
return normalizeGroups(state, action.groups)
|
||||||
case GROUP_FETCH_FAIL:
|
case GROUP_FETCH_FAIL:
|
||||||
return state.set(action.id, false)
|
return state.set(action.groupId, false)
|
||||||
default:
|
default:
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,9 @@ import { combineReducers } from 'redux-immutable'
|
||||||
import { loadingBarReducer } from 'react-redux-loading-bar'
|
import { loadingBarReducer } from 'react-redux-loading-bar'
|
||||||
import accounts from './accounts'
|
import accounts from './accounts'
|
||||||
import accounts_counters from './accounts_counters'
|
import accounts_counters from './accounts_counters'
|
||||||
|
import chat_compose from './chat_compose'
|
||||||
|
import chat_conversations from './chat_conversations'
|
||||||
|
import chat_messages from './chat_messages'
|
||||||
import compose from './compose'
|
import compose from './compose'
|
||||||
import contexts from './contexts'
|
import contexts from './contexts'
|
||||||
import custom_emojis from './custom_emojis'
|
import custom_emojis from './custom_emojis'
|
||||||
|
@ -46,6 +49,8 @@ import user_lists from './user_lists'
|
||||||
const reducers = {
|
const reducers = {
|
||||||
accounts,
|
accounts,
|
||||||
accounts_counters,
|
accounts_counters,
|
||||||
|
chat_conversations,
|
||||||
|
chat_messages,
|
||||||
compose,
|
compose,
|
||||||
contexts,
|
contexts,
|
||||||
custom_emojis,
|
custom_emojis,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable'
|
import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable'
|
||||||
import {
|
import {
|
||||||
STATUS_REVISIONS_LOAD,
|
STATUS_REVISIONS_LOAD_REQUEST,
|
||||||
STATUS_REVISIONS_LOAD_SUCCESS,
|
STATUS_REVISIONS_LOAD_SUCCESS,
|
||||||
STATUS_REVISIONS_LOAD_FAIL
|
STATUS_REVISIONS_LOAD_FAIL
|
||||||
} from '../actions/status_revisions'
|
} from '../actions/status_revisions'
|
||||||
|
@ -13,15 +13,17 @@ const initialState = ImmutableMap({
|
||||||
|
|
||||||
export default function statusRevisions(state = initialState, action) {
|
export default function statusRevisions(state = initialState, action) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case STATUS_REVISIONS_LOAD:
|
case STATUS_REVISIONS_LOAD_REQUEST:
|
||||||
return initialState
|
return state.withMutations((mutable) => {
|
||||||
|
mutable.set('loading', true)
|
||||||
|
})
|
||||||
case STATUS_REVISIONS_LOAD_SUCCESS:
|
case STATUS_REVISIONS_LOAD_SUCCESS:
|
||||||
return state.withMutations(mutable => {
|
return state.withMutations((mutable) => {
|
||||||
mutable.set('loading', false)
|
mutable.set('loading', false)
|
||||||
mutable.set('revisions', fromJS(action.revisions).reverse())
|
mutable.set('revisions', fromJS(action.revisions).reverse())
|
||||||
})
|
})
|
||||||
case STATUS_REVISIONS_LOAD_FAIL:
|
case STATUS_REVISIONS_LOAD_FAIL:
|
||||||
return state.withMutations(mutable => {
|
return state.withMutations((mutable) => {
|
||||||
mutable.set('loading', false)
|
mutable.set('loading', false)
|
||||||
mutable.set('error', action.error)
|
mutable.set('error', action.error)
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import {
|
import {
|
||||||
REPOST_REQUEST,
|
REPOST_REQUEST,
|
||||||
|
UNREPOST_REQUEST,
|
||||||
REPOST_FAIL,
|
REPOST_FAIL,
|
||||||
FAVORITE_REQUEST,
|
FAVORITE_REQUEST,
|
||||||
FAVORITE_FAIL,
|
FAVORITE_FAIL,
|
||||||
|
@ -43,10 +44,12 @@ export default function statuses(state = initialState, action) {
|
||||||
return state.setIn([action.status.get('id'), 'favourited'], false);
|
return state.setIn([action.status.get('id'), 'favourited'], false);
|
||||||
case REPOST_REQUEST:
|
case REPOST_REQUEST:
|
||||||
return state.setIn([action.status.get('id'), 'reblogged'], true);
|
return state.setIn([action.status.get('id'), 'reblogged'], true);
|
||||||
|
case UNREPOST_REQUEST:
|
||||||
|
return state.setIn([action.status.get('id'), 'reblogged'], false);
|
||||||
case REPOST_FAIL:
|
case REPOST_FAIL:
|
||||||
return state.get(action.status.get('id')) === undefined ? state : state.setIn([action.status.get('id'), 'reblogged'], false);
|
return state.get(action.status.get('id')) === undefined ? state : state.setIn([action.status.get('id'), 'reblogged'], false);
|
||||||
case STATUS_REVEAL:
|
case STATUS_REVEAL:
|
||||||
return state.withMutations(map => {
|
return state.withMutations((map) => {
|
||||||
action.ids.forEach(id => {
|
action.ids.forEach(id => {
|
||||||
if (!(state.get(id) === undefined)) {
|
if (!(state.get(id) === undefined)) {
|
||||||
map.setIn([id, 'hidden'], false);
|
map.setIn([id, 'hidden'], false);
|
||||||
|
@ -54,7 +57,7 @@ export default function statuses(state = initialState, action) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
case STATUS_HIDE:
|
case STATUS_HIDE:
|
||||||
return state.withMutations(map => {
|
return state.withMutations((map) => {
|
||||||
action.ids.forEach(id => {
|
action.ids.forEach(id => {
|
||||||
if (!(state.get(id) === undefined)) {
|
if (!(state.get(id) === undefined)) {
|
||||||
map.setIn([id, 'hidden'], true);
|
map.setIn([id, 'hidden'], true);
|
||||||
|
@ -64,8 +67,17 @@ export default function statuses(state = initialState, action) {
|
||||||
case TIMELINE_DELETE:
|
case TIMELINE_DELETE:
|
||||||
return deleteStatus(state, action.id, action.references);
|
return deleteStatus(state, action.id, action.references);
|
||||||
case UPDATE_STATUS_STATS:
|
case UPDATE_STATUS_STATS:
|
||||||
// : todo :
|
const { status_id } = action.data
|
||||||
return state;
|
return state.withMutations((map) => {
|
||||||
|
if (action.data.favourited !== undefined) map.setIn([status_id, 'favourited'], action.data.favourited)
|
||||||
|
if (action.data.favourites_count !== undefined) map.setIn([status_id, 'favourites_count'], action.data.favourites_count)
|
||||||
|
if (action.data.reblogged !== undefined) map.setIn([status_id, 'reblogged'], action.data.reblogged)
|
||||||
|
if (action.data.reblogs_count !== undefined) map.setIn([status_id, 'reblogs_count'], action.data.reblogs_count)
|
||||||
|
if (action.data.replies_count !== undefined) map.setIn([status_id, 'replies_count'], action.data.replies_count)
|
||||||
|
if (action.data.pinned !== undefined) map.setIn([status_id, 'pinned'], action.data.pinned)
|
||||||
|
if (action.data.pinned_by_group !== undefined) map.setIn([status_id, 'pinned_by_group'], action.data.pinned_by_group)
|
||||||
|
if (action.data.bookmarked !== undefined) map.setIn([status_id, 'bookmarked'], action.data.bookmarked)
|
||||||
|
})
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable'
|
||||||
|
import compareId from '../utils/compare_id'
|
||||||
import {
|
import {
|
||||||
TIMELINE_UPDATE,
|
TIMELINE_UPDATE,
|
||||||
TIMELINE_DELETE,
|
TIMELINE_DELETE,
|
||||||
|
@ -11,17 +13,19 @@ import {
|
||||||
TIMELINE_DEQUEUE,
|
TIMELINE_DEQUEUE,
|
||||||
MAX_QUEUED_ITEMS,
|
MAX_QUEUED_ITEMS,
|
||||||
TIMELINE_SCROLL_TOP,
|
TIMELINE_SCROLL_TOP,
|
||||||
} from '../actions/timelines';
|
} from '../actions/timelines'
|
||||||
import {
|
import {
|
||||||
ACCOUNT_BLOCK_SUCCESS,
|
ACCOUNT_BLOCK_SUCCESS,
|
||||||
ACCOUNT_MUTE_SUCCESS,
|
ACCOUNT_MUTE_SUCCESS,
|
||||||
ACCOUNT_UNFOLLOW_SUCCESS,
|
ACCOUNT_UNFOLLOW_SUCCESS,
|
||||||
} from '../actions/accounts';
|
} from '../actions/accounts'
|
||||||
import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable';
|
import {
|
||||||
import compareId from '../utils/compare_id';
|
GROUP_REMOVE_STATUS_SUCCESS,
|
||||||
import { GROUP_REMOVE_STATUS_SUCCESS } from '../actions/groups';
|
GROUP_UNPIN_STATUS_SUCCESS,
|
||||||
|
} from '../actions/groups'
|
||||||
|
import { UNPIN_SUCCESS } from '../actions/interactions'
|
||||||
|
|
||||||
const initialState = ImmutableMap();
|
const initialState = ImmutableMap()
|
||||||
|
|
||||||
const initialTimeline = ImmutableMap({
|
const initialTimeline = ImmutableMap({
|
||||||
unread: 0,
|
unread: 0,
|
||||||
|
@ -33,14 +37,14 @@ const initialTimeline = ImmutableMap({
|
||||||
items: ImmutableList(),
|
items: ImmutableList(),
|
||||||
queuedItems: ImmutableList(), //max= MAX_QUEUED_ITEMS
|
queuedItems: ImmutableList(), //max= MAX_QUEUED_ITEMS
|
||||||
totalQueuedItemsCount: 0, //used for queuedItems overflow for MAX_QUEUED_ITEMS+
|
totalQueuedItemsCount: 0, //used for queuedItems overflow for MAX_QUEUED_ITEMS+
|
||||||
});
|
})
|
||||||
|
|
||||||
const expandNormalizedTimeline = (state, timeline, statuses, next, isPartial, isLoadingRecent) => {
|
const expandNormalizedTimeline = (state, timeline, statuses, next, isPartial, isLoadingRecent) => {
|
||||||
return state.update(timeline, initialTimeline, map => map.withMutations(mMap => {
|
return state.update(timeline, initialTimeline, map => map.withMutations((mMap) => {
|
||||||
mMap.set('isLoading', false);
|
mMap.set('isLoading', false)
|
||||||
mMap.set('isPartial', isPartial);
|
mMap.set('isPartial', isPartial)
|
||||||
|
|
||||||
if (!next && !isLoadingRecent) mMap.set('hasMore', false);
|
if (!next && !isLoadingRecent) mMap.set('hasMore', false)
|
||||||
|
|
||||||
if (!statuses.isEmpty()) {
|
if (!statuses.isEmpty()) {
|
||||||
mMap.update('items', ImmutableList(), oldIds => {
|
mMap.update('items', ImmutableList(), oldIds => {
|
||||||
|
@ -160,8 +164,16 @@ const filterTimeline = (timeline, state, relationship, statuses) =>
|
||||||
));
|
));
|
||||||
|
|
||||||
const removeStatusFromGroup = (state, groupId, statusId) => {
|
const removeStatusFromGroup = (state, groupId, statusId) => {
|
||||||
return state.updateIn([`group:${groupId}`, 'items'], list => list.filterNot(item => item === statusId));
|
return state.updateIn([`group:${groupId}`, 'items'], list => list.filterNot(item => item === statusId))
|
||||||
};
|
}
|
||||||
|
|
||||||
|
const removeStatusFromGroupPins = (state, groupId, statusId) => {
|
||||||
|
return state.updateIn([`group:${groupId}:pinned`, 'items'], list => list.filterNot(item => item === statusId))
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeStatusFromAccountPins = (state, accountId, statusId) => {
|
||||||
|
return state.updateIn([`account:${accountId}:pinned`, 'items'], list => list.filterNot(item => item === statusId))
|
||||||
|
}
|
||||||
|
|
||||||
export default function timelines(state = initialState, action) {
|
export default function timelines(state = initialState, action) {
|
||||||
switch(action.type) {
|
switch(action.type) {
|
||||||
|
@ -201,10 +213,14 @@ export default function timelines(state = initialState, action) {
|
||||||
action.timeline,
|
action.timeline,
|
||||||
initialTimeline,
|
initialTimeline,
|
||||||
map => map.set('online', false).update('items', items => items.first() ? items.unshift(null) : items)
|
map => map.set('online', false).update('items', items => items.first() ? items.unshift(null) : items)
|
||||||
);
|
)
|
||||||
|
case UNPIN_SUCCESS:
|
||||||
|
return removeStatusFromAccountPins(state, action.accountId, action.status.get('id'))
|
||||||
case GROUP_REMOVE_STATUS_SUCCESS:
|
case GROUP_REMOVE_STATUS_SUCCESS:
|
||||||
return removeStatusFromGroup(state, action.groupId, action.id)
|
return removeStatusFromGroup(state, action.groupId, action.statusId)
|
||||||
|
case GROUP_UNPIN_STATUS_SUCCESS:
|
||||||
|
return removeStatusFromGroupPins(state, action.groupId, action.statusId)
|
||||||
default:
|
default:
|
||||||
return state;
|
return state
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
|
@ -23,8 +23,18 @@ import {
|
||||||
FOLLOW_REQUEST_REJECT_SUCCESS,
|
FOLLOW_REQUEST_REJECT_SUCCESS,
|
||||||
} from '../actions/accounts'
|
} from '../actions/accounts'
|
||||||
import {
|
import {
|
||||||
|
REPOSTS_FETCH_REQUEST,
|
||||||
REPOSTS_FETCH_SUCCESS,
|
REPOSTS_FETCH_SUCCESS,
|
||||||
|
REPOSTS_FETCH_FAIL,
|
||||||
|
REPOSTS_EXPAND_REQUEST,
|
||||||
|
REPOSTS_EXPAND_SUCCESS,
|
||||||
|
REPOSTS_EXPAND_FAIL,
|
||||||
|
LIKES_FETCH_REQUEST,
|
||||||
LIKES_FETCH_SUCCESS,
|
LIKES_FETCH_SUCCESS,
|
||||||
|
LIKES_FETCH_FAIL,
|
||||||
|
LIKES_EXPAND_REQUEST,
|
||||||
|
LIKES_EXPAND_SUCCESS,
|
||||||
|
LIKES_EXPAND_FAIL,
|
||||||
} from '../actions/interactions'
|
} from '../actions/interactions'
|
||||||
import {
|
import {
|
||||||
BLOCKS_FETCH_REQUEST,
|
BLOCKS_FETCH_REQUEST,
|
||||||
|
@ -52,6 +62,7 @@ import {
|
||||||
GROUP_JOIN_REQUESTS_EXPAND_SUCCESS,
|
GROUP_JOIN_REQUESTS_EXPAND_SUCCESS,
|
||||||
GROUP_JOIN_REQUESTS_APPROVE_SUCCESS,
|
GROUP_JOIN_REQUESTS_APPROVE_SUCCESS,
|
||||||
GROUP_JOIN_REQUESTS_REJECT_SUCCESS,
|
GROUP_JOIN_REQUESTS_REJECT_SUCCESS,
|
||||||
|
GROUP_REMOVED_ACCOUNTS_CREATE_SUCCESS,
|
||||||
} from '../actions/groups'
|
} from '../actions/groups'
|
||||||
|
|
||||||
const initialState = ImmutableMap({
|
const initialState = ImmutableMap({
|
||||||
|
@ -119,11 +130,27 @@ export default function userLists(state = initialState, action) {
|
||||||
case FOLLOWING_EXPAND_FAIL:
|
case FOLLOWING_EXPAND_FAIL:
|
||||||
return state.setIn(['following', action.id, 'isLoading'], false);
|
return state.setIn(['following', action.id, 'isLoading'], false);
|
||||||
|
|
||||||
|
case REPOSTS_FETCH_REQUEST:
|
||||||
|
case REPOSTS_EXPAND_REQUEST:
|
||||||
|
return state.setIn(['reblogged_by', action.statusId, 'isLoading'], true)
|
||||||
case REPOSTS_FETCH_SUCCESS:
|
case REPOSTS_FETCH_SUCCESS:
|
||||||
return state.setIn(['reblogged_by', action.id], ImmutableList(action.accounts.map(item => item.id)));
|
return normalizeList(state, 'reblogged_by', action.statusId, action.accounts, action.next)
|
||||||
|
case REPOSTS_EXPAND_SUCCESS:
|
||||||
|
return appendToList(state, 'reblogged_by', action.statusId, action.accounts, action.next)
|
||||||
|
case REPOSTS_FETCH_FAIL:
|
||||||
|
case REPOSTS_EXPAND_FAIL:
|
||||||
|
return setListFailed(state, 'reblogged_by', action.statusId)
|
||||||
|
|
||||||
|
case LIKES_FETCH_REQUEST:
|
||||||
|
case LIKES_EXPAND_REQUEST:
|
||||||
|
return state.setIn(['liked_by', action.statusId, 'isLoading'], true)
|
||||||
case LIKES_FETCH_SUCCESS:
|
case LIKES_FETCH_SUCCESS:
|
||||||
return state.setIn(['liked_by', action.id], ImmutableList(action.accounts.map(item => item.id)));
|
return normalizeList(state, 'liked_by', action.statusId, action.accounts, action.next)
|
||||||
|
case LIKES_EXPAND_SUCCESS:
|
||||||
|
return appendToList(state, 'liked_by', action.statusId, action.accounts, action.next)
|
||||||
|
case LIKES_FETCH_FAIL:
|
||||||
|
case LIKES_EXPAND_FAIL:
|
||||||
|
return setListFailed(state, 'liked_by', action.statusId)
|
||||||
|
|
||||||
case FOLLOW_REQUESTS_FETCH_SUCCESS:
|
case FOLLOW_REQUESTS_FETCH_SUCCESS:
|
||||||
return normalizeList(state, 'follow_requests', me, action.accounts, action.next);
|
return normalizeList(state, 'follow_requests', me, action.accounts, action.next);
|
||||||
|
@ -162,21 +189,24 @@ export default function userLists(state = initialState, action) {
|
||||||
return setListFailed(state, 'mutes', me)
|
return setListFailed(state, 'mutes', me)
|
||||||
|
|
||||||
case GROUP_MEMBERS_FETCH_SUCCESS:
|
case GROUP_MEMBERS_FETCH_SUCCESS:
|
||||||
return normalizeList(state, 'groups', action.id, action.accounts, action.next);
|
return normalizeList(state, 'groups', action.groupId, action.accounts, action.next);
|
||||||
case GROUP_MEMBERS_EXPAND_SUCCESS:
|
case GROUP_MEMBERS_EXPAND_SUCCESS:
|
||||||
return appendToList(state, 'groups', action.id, action.accounts, action.next);
|
return appendToList(state, 'groups', action.groupId, action.accounts, action.next);
|
||||||
|
|
||||||
|
case GROUP_REMOVED_ACCOUNTS_CREATE_SUCCESS:
|
||||||
|
return state.updateIn(['groups', action.groupId, 'items'], list => list.filterNot(item => item === action.accountId));
|
||||||
|
|
||||||
case GROUP_REMOVED_ACCOUNTS_FETCH_SUCCESS:
|
case GROUP_REMOVED_ACCOUNTS_FETCH_SUCCESS:
|
||||||
return normalizeList(state, 'group_removed_accounts', action.id, action.accounts, action.next);
|
return normalizeList(state, 'group_removed_accounts', action.groupId, action.accounts, action.next);
|
||||||
case GROUP_REMOVED_ACCOUNTS_EXPAND_SUCCESS:
|
case GROUP_REMOVED_ACCOUNTS_EXPAND_SUCCESS:
|
||||||
return appendToList(state, 'group_removed_accounts', action.id, action.accounts, action.next);
|
return appendToList(state, 'group_removed_accounts', action.groupId, action.accounts, action.next);
|
||||||
case GROUP_REMOVED_ACCOUNTS_REMOVE_SUCCESS:
|
case GROUP_REMOVED_ACCOUNTS_REMOVE_SUCCESS:
|
||||||
return state.updateIn(['group_removed_accounts', action.groupId, 'items'], list => list.filterNot(item => item === action.id));
|
return state.updateIn(['group_removed_accounts', action.groupId, 'items'], list => list.filterNot(item => item === action.accountId));
|
||||||
|
|
||||||
case GROUP_JOIN_REQUESTS_FETCH_SUCCESS:
|
case GROUP_JOIN_REQUESTS_FETCH_SUCCESS:
|
||||||
return normalizeList(state, 'group_join_requests', action.id, action.accounts, action.next);
|
return normalizeList(state, 'group_join_requests', action.groupId, action.accounts, action.next);
|
||||||
case GROUP_JOIN_REQUESTS_EXPAND_SUCCESS:
|
case GROUP_JOIN_REQUESTS_EXPAND_SUCCESS:
|
||||||
return appendToList(state, 'group_join_requests', action.id, action.accounts, action.next);
|
return appendToList(state, 'group_join_requests', action.groupId, action.accounts, action.next);
|
||||||
case GROUP_JOIN_REQUESTS_APPROVE_SUCCESS:
|
case GROUP_JOIN_REQUESTS_APPROVE_SUCCESS:
|
||||||
case GROUP_JOIN_REQUESTS_REJECT_SUCCESS:
|
case GROUP_JOIN_REQUESTS_REJECT_SUCCESS:
|
||||||
return state.updateIn(['group_join_requests', action.groupId, 'items'], list => list.filterNot(item => item === action.accountId));
|
return state.updateIn(['group_join_requests', action.groupId, 'items'], list => list.filterNot(item => item === action.accountId));
|
||||||
|
|
|
@ -124,7 +124,7 @@ export const makeGetStatus = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
console.log("group:", group)
|
// console.log("group:", group)
|
||||||
|
|
||||||
//Find ancestor status
|
//Find ancestor status
|
||||||
|
|
||||||
|
|
|
@ -31,15 +31,3 @@ delegate(document, '.media-spoiler-hide-button', 'click', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
delegate(document, '#domain_block_severity', 'change', ({ target }) => {
|
|
||||||
const rejectMediaDiv = document.querySelector('.input.with_label.domain_block_reject_media');
|
|
||||||
const rejectReportsDiv = document.querySelector('.input.with_label.domain_block_reject_reports');
|
|
||||||
|
|
||||||
if (rejectMediaDiv) {
|
|
||||||
rejectMediaDiv.style.display = (target.value === 'suspend') ? 'none' : 'block';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rejectReportsDiv) {
|
|
||||||
rejectReportsDiv.style.display = (target.value === 'suspend') ? 'none' : 'block';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ class SortingQueryBuilder < BaseService
|
||||||
query = Status.unscoped.without_replies
|
query = Status.unscoped.without_replies
|
||||||
query = query.joins(:status_stat).order(top_order) unless ['newest'].include? sort_type
|
query = query.joins(:status_stat).order(top_order) unless ['newest'].include? sort_type
|
||||||
query = query.where('statuses.created_at > ?', date_limit)
|
query = query.where('statuses.created_at > ?', date_limit)
|
||||||
query = query.where(group: @group) unless group.nil?
|
query = query.where(group: group) unless group.nil?
|
||||||
query = query.where('statuses.id > ? AND statuses.id <> ?', max_id, max_id) unless max_id.nil? || max_id.empty?
|
query = query.where('statuses.id > ? AND statuses.id <> ?', max_id, max_id) unless max_id.nil? || max_id.empty?
|
||||||
query = query.limit(20)
|
query = query.limit(20)
|
||||||
|
|
||||||
|
|
|
@ -148,7 +148,7 @@ module AccountInteractions
|
||||||
end
|
end
|
||||||
|
|
||||||
def bookmarked?(status)
|
def bookmarked?(status)
|
||||||
status_bookmarks.where(account: self).exists?
|
status_bookmarks.where(account: self, status: status).exists?
|
||||||
end
|
end
|
||||||
|
|
||||||
def reblogged?(status)
|
def reblogged?(status)
|
||||||
|
|
|
@ -72,6 +72,10 @@ class Group < ApplicationRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def has_password?
|
||||||
|
return !!self.password && self.password.gsub(/\s+/, "").length > 1 && self.password.to_s != "null"
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_password
|
def set_password
|
||||||
|
|
|
@ -13,4 +13,3 @@ class GroupRelationshipsPresenter
|
||||||
@requested = Group.requested_map(@group_ids, @current_account_id)
|
@requested = Group.requested_map(@group_ids, @current_account_id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class StatusRelationshipsPresenter
|
class StatusRelationshipsPresenter
|
||||||
attr_reader :reblogs_map, :favourites_map, :group_pins_map
|
attr_reader :reblogs_map, :favourites_map
|
||||||
|
|
||||||
def initialize(statuses, current_account_id = nil, **options)
|
def initialize(statuses, current_account_id = nil, **options)
|
||||||
if current_account_id.nil?
|
if current_account_id.nil?
|
||||||
|
|
|
@ -13,7 +13,7 @@ class REST::GroupSerializer < ActiveModel::Serializer
|
||||||
end
|
end
|
||||||
|
|
||||||
def has_password
|
def has_password
|
||||||
return !!object.password && object.password.gsub(/\s+/, "").length > 1 && object.password.to_s != "null"
|
object.has_password?
|
||||||
end
|
end
|
||||||
|
|
||||||
def password
|
def password
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class REST::StatusBookmarkedSerializer < ActiveModel::Serializer
|
||||||
|
attributes :status_id, :account_id, :bookmarked
|
||||||
|
|
||||||
|
def status_id
|
||||||
|
object.id.to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def account_id
|
||||||
|
current_user.account.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def bookmarked
|
||||||
|
if !current_user.nil?
|
||||||
|
current_user.account.bookmarked?(object)
|
||||||
|
else
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,22 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class REST::StatusGroupPinnedSerializer < ActiveModel::Serializer
|
||||||
|
attributes :status_id, :group_id, :pinned_by_group
|
||||||
|
|
||||||
|
def status_id
|
||||||
|
object.id.to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def group_id
|
||||||
|
instance_options[:group_id]
|
||||||
|
end
|
||||||
|
|
||||||
|
def pinned_by_group
|
||||||
|
if !current_user.nil? || !group_id
|
||||||
|
!GroupPinnedStatus.where(status_id: status_id, group_id: group_id).empty?
|
||||||
|
else
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,22 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class REST::StatusPinnedSerializer < ActiveModel::Serializer
|
||||||
|
attributes :status_id, :account_id, :pinned
|
||||||
|
|
||||||
|
def status_id
|
||||||
|
object.id.to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def account_id
|
||||||
|
current_user.account.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def pinned
|
||||||
|
if !current_user.nil?
|
||||||
|
current_user.account.pinned?(object)
|
||||||
|
else
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -3,7 +3,7 @@
|
||||||
class REST::StatusSerializer < ActiveModel::Serializer
|
class REST::StatusSerializer < ActiveModel::Serializer
|
||||||
attributes :id, :created_at, :revised_at, :in_reply_to_id, :in_reply_to_account_id,
|
attributes :id, :created_at, :revised_at, :in_reply_to_id, :in_reply_to_account_id,
|
||||||
:sensitive, :spoiler_text, :visibility, :language,
|
:sensitive, :spoiler_text, :visibility, :language,
|
||||||
:url, :replies_count, :reblogs_count,
|
:url, :replies_count, :reblogs_count, :pinnable, :pinnable_by_group,
|
||||||
:favourites_count, :quote_of_id, :expires_at, :has_quote
|
:favourites_count, :quote_of_id, :expires_at, :has_quote
|
||||||
|
|
||||||
attribute :favourited, if: :current_user?
|
attribute :favourited, if: :current_user?
|
||||||
|
@ -32,6 +32,7 @@ class REST::StatusSerializer < ActiveModel::Serializer
|
||||||
has_one :preloadable_poll, key: :poll, serializer: REST::PollSerializer
|
has_one :preloadable_poll, key: :poll, serializer: REST::PollSerializer
|
||||||
|
|
||||||
def id
|
def id
|
||||||
|
# puts "tilly instance:" + instance_options.inspect
|
||||||
object.id.to_s
|
object.id.to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -134,22 +135,14 @@ class REST::StatusSerializer < ActiveModel::Serializer
|
||||||
end
|
end
|
||||||
|
|
||||||
def bookmarked
|
def bookmarked
|
||||||
if instance_options && instance_options[:relationships]
|
return
|
||||||
instance_options[:relationships].bookmarks_map[object.id] || false
|
|
||||||
else
|
|
||||||
current_user.account.bookmarked?(object)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def pinned
|
def pinned
|
||||||
if instance_options && instance_options[:relationships]
|
return
|
||||||
instance_options[:relationships].pins_map[object.id] || false
|
|
||||||
else
|
|
||||||
current_user.account.pinned?(object)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def pinnable?
|
def pinnable
|
||||||
current_user? &&
|
current_user? &&
|
||||||
current_user.account_id == object.account_id &&
|
current_user.account_id == object.account_id &&
|
||||||
!object.reblog? &&
|
!object.reblog? &&
|
||||||
|
@ -157,14 +150,10 @@ class REST::StatusSerializer < ActiveModel::Serializer
|
||||||
end
|
end
|
||||||
|
|
||||||
def pinned_by_group
|
def pinned_by_group
|
||||||
if instance_options && instance_options[:relationships]
|
return
|
||||||
instance_options[:relationships].group_pins_map[object.id] || false
|
|
||||||
else
|
|
||||||
false
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def pinnable_by_group?
|
def pinnable_by_group
|
||||||
if object.group_id?
|
if object.group_id?
|
||||||
true
|
true
|
||||||
else
|
else
|
||||||
|
|
|
@ -34,6 +34,14 @@ class REST::StatusStatSerializer < ActiveModel::Serializer
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def reblogs_count
|
||||||
|
if instance_options && instance_options[:unreblog]
|
||||||
|
object.reblogs_count - 1
|
||||||
|
else
|
||||||
|
object.reblogs_count
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def current_user?
|
def current_user?
|
||||||
!current_user.nil?
|
!current_user.nil?
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
class GroupPinnedStatusValidator < ActiveModel::Validator
|
class GroupPinnedStatusValidator < ActiveModel::Validator
|
||||||
def validate(groupPin)
|
def validate(groupPin)
|
||||||
groupPin.errors.add(:base, I18n.t('statuses.group_pin_errors.reblog')) if groupPin.status.reblog?
|
groupPin.errors.add(:base, I18n.t('statuses.group_pin_errors.reblog')) if groupPin.status.reblog?
|
||||||
groupPin.errors.add(:base, I18n.t('statuses.pin_errors.ungrouped')) unless groupPin.status.group_id
|
groupPin.errors.add(:base, I18n.t('statuses.group_pin_errors.ungrouped')) unless groupPin.status.group_id
|
||||||
groupPin.errors.add(:base, I18n.t('statuses.pin_errors.notGroupStatus')) if groupPin.status.group_id != groupPin.group.id
|
groupPin.errors.add(:base, I18n.t('statuses.group_pin_errors.notGroupStatus')) if groupPin.status.group_id != groupPin.group.id
|
||||||
groupPin.errors.add(:base, I18n.t('statuses.group_pin_errors.limit')) if groupPin.group.group_pinned_statuses.count >= 4
|
groupPin.errors.add(:base, I18n.t('statuses.group_pin_errors.limit')) if groupPin.group.group_pinned_statuses.count >= 4
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,4 +16,4 @@ nl:
|
||||||
status:
|
status:
|
||||||
attributes:
|
attributes:
|
||||||
reblog:
|
reblog:
|
||||||
taken: van toot bestaat al
|
taken: van gab bestaat al
|
||||||
|
|
|
@ -414,7 +414,7 @@ ar:
|
||||||
disabled: لا أحد
|
disabled: لا أحد
|
||||||
title: المستخدِمون المصرح لهم لإرسال الدعوات
|
title: المستخدِمون المصرح لهم لإرسال الدعوات
|
||||||
show_known_fediverse_at_about_page:
|
show_known_fediverse_at_about_page:
|
||||||
desc_html: عند التثبت ، سوف تظهر toots من جميع fediverse المعروفة على عرض مسبق. وإلا فإنه سيعرض فقط toots المحلية.
|
desc_html: عند التثبت ، سوف تظهر gabs من جميع fediverse المعروفة على عرض مسبق. وإلا فإنه سيعرض فقط gabs المحلية.
|
||||||
title: إظهار الفيديفرس الموحَّد في خيط المُعايَنة
|
title: إظهار الفيديفرس الموحَّد في خيط المُعايَنة
|
||||||
show_staff_badge:
|
show_staff_badge:
|
||||||
desc_html: عرض شارة الموظفين على صفحة المستخدم
|
desc_html: عرض شارة الموظفين على صفحة المستخدم
|
||||||
|
|
|
@ -34,10 +34,10 @@ ast:
|
||||||
people_followed_by: Persones a les que sigue %{name}
|
people_followed_by: Persones a les que sigue %{name}
|
||||||
people_who_follow: Persones que siguen a %{name}
|
people_who_follow: Persones que siguen a %{name}
|
||||||
posts:
|
posts:
|
||||||
one: Toot
|
one: Gab
|
||||||
other: Toots
|
other: Gabs
|
||||||
posts_tab_heading: Toots
|
posts_tab_heading: Gabs
|
||||||
posts_with_replies: Toots y rempuestes
|
posts_with_replies: Gabs y rempuestes
|
||||||
reserved_username: El nome d'usuariu ta acutáu
|
reserved_username: El nome d'usuariu ta acutáu
|
||||||
roles:
|
roles:
|
||||||
bot: Robó
|
bot: Robó
|
||||||
|
@ -165,7 +165,7 @@ ast:
|
||||||
exports:
|
exports:
|
||||||
archive_takeout:
|
archive_takeout:
|
||||||
date: Data
|
date: Data
|
||||||
hint_html: Pues solicitar un archivu colos tos <strong>toots y ficheros xubíos</strong>. Los datos esportaos van tar nel formatu ActivityPub, llexible pa cualesquier software que seya compatible. Pues solicitar un archivu cada 7 díes.
|
hint_html: Pues solicitar un archivu colos tos <strong>gabs y ficheros xubíos</strong>. Los datos esportaos van tar nel formatu ActivityPub, llexible pa cualesquier software que seya compatible. Pues solicitar un archivu cada 7 díes.
|
||||||
request: Solicitar l'archivu
|
request: Solicitar l'archivu
|
||||||
size: Tamañu
|
size: Tamañu
|
||||||
blocks: Xente que bloquiesti
|
blocks: Xente que bloquiesti
|
||||||
|
@ -238,7 +238,7 @@ ast:
|
||||||
reblog:
|
reblog:
|
||||||
body: "%{name} compartió'l to estáu:"
|
body: "%{name} compartió'l to estáu:"
|
||||||
subject: "%{name} compartió'l to estáu"
|
subject: "%{name} compartió'l to estáu"
|
||||||
title: Compartición nueva de toot
|
title: Compartición nueva de gab
|
||||||
number:
|
number:
|
||||||
human:
|
human:
|
||||||
decimal_units:
|
decimal_units:
|
||||||
|
@ -309,13 +309,13 @@ ast:
|
||||||
video:
|
video:
|
||||||
one: "%{count} videu"
|
one: "%{count} videu"
|
||||||
other: "%{count} vídeos"
|
other: "%{count} vídeos"
|
||||||
boosted_from_html: Compartióse'l toot dende %{acct_link}
|
boosted_from_html: Compartióse'l gab dende %{acct_link}
|
||||||
language_detection: Deteutala automáticamente
|
language_detection: Deteutala automáticamente
|
||||||
pin_errors:
|
pin_errors:
|
||||||
limit: Yá fixesti'l númberu máxiumu de toots
|
limit: Yá fixesti'l númberu máxiumu de gabs
|
||||||
ownership: Nun pue fixase'l toot d'otra persona
|
ownership: Nun pue fixase'l gab d'otra persona
|
||||||
private: Nun puen fixase los toots que nun seyan públicos
|
private: Nun puen fixase los gabs que nun seyan públicos
|
||||||
reblog: Nun pue fixase un toot compartíu
|
reblog: Nun pue fixase un gab compartíu
|
||||||
show_more: Amosar más
|
show_more: Amosar más
|
||||||
title: "%{name}: «%{quote}»"
|
title: "%{name}: «%{quote}»"
|
||||||
visibilities:
|
visibilities:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
ca:
|
ca:
|
||||||
about:
|
about:
|
||||||
about_hashtag_html: Aquests són toots públics etiquetats amb <strong>#%{hashtag}</strong>. Pots interactuar amb ells si tens un compte a qualsevol lloc del fediverse.
|
about_hashtag_html: Aquests són gabs públics etiquetats amb <strong>#%{hashtag}</strong>. Pots interactuar amb ells si tens un compte a qualsevol lloc del fediverse.
|
||||||
about_gabsocial_html: Gab Social és una xarxa social basada en protocols web oberts i en programari lliure i de codi obert. Està descentralitzat com el correu electrònic.
|
about_gabsocial_html: Gab Social és una xarxa social basada en protocols web oberts i en programari lliure i de codi obert. Està descentralitzat com el correu electrònic.
|
||||||
about_this: Quant a
|
about_this: Quant a
|
||||||
active_count_after: actiu
|
active_count_after: actiu
|
||||||
|
@ -59,10 +59,10 @@ ca:
|
||||||
pin_errors:
|
pin_errors:
|
||||||
following: Has d'estar seguint la persona que vulguis avalar
|
following: Has d'estar seguint la persona que vulguis avalar
|
||||||
posts:
|
posts:
|
||||||
one: Toot
|
one: Gab
|
||||||
other: Toots
|
other: Gabs
|
||||||
posts_tab_heading: Toots
|
posts_tab_heading: Gabs
|
||||||
posts_with_replies: Toots i respostes
|
posts_with_replies: Gabs i respostes
|
||||||
reserved_username: El nom d'usuari està reservat
|
reserved_username: El nom d'usuari està reservat
|
||||||
roles:
|
roles:
|
||||||
admin: Administrador
|
admin: Administrador
|
||||||
|
@ -214,7 +214,7 @@ ca:
|
||||||
unsuspend_account: "%{name} ha llevat la suspensió del compte de %{target}"
|
unsuspend_account: "%{name} ha llevat la suspensió del compte de %{target}"
|
||||||
update_custom_emoji: "%{name} ha actualitzat l'emoji %{target}"
|
update_custom_emoji: "%{name} ha actualitzat l'emoji %{target}"
|
||||||
update_status: "%{name} estat actualitzat per %{target}"
|
update_status: "%{name} estat actualitzat per %{target}"
|
||||||
deleted_status: "(toot suprimit)"
|
deleted_status: "(gab suprimit)"
|
||||||
title: Registre d'auditoria
|
title: Registre d'auditoria
|
||||||
custom_emojis:
|
custom_emojis:
|
||||||
by_domain: Domini
|
by_domain: Domini
|
||||||
|
@ -339,11 +339,11 @@ ca:
|
||||||
relays:
|
relays:
|
||||||
add_new: Afegiu un nou relay
|
add_new: Afegiu un nou relay
|
||||||
delete: Esborra
|
delete: Esborra
|
||||||
description_html: Un <strong>relay de federació</strong> és un servidor intermediari que intercanvia grans volums de toots públics entre servidors que es subscriuen i publiquen en ell. <strong>Pot ajudar a servidors petits i mitjans a descobrir contingut del fedivers</strong>, no fent necessari que els usuaris locals manualment segueixin altres persones de servidors remots.
|
description_html: Un <strong>relay de federació</strong> és un servidor intermediari que intercanvia grans volums de gabs públics entre servidors que es subscriuen i publiquen en ell. <strong>Pot ajudar a servidors petits i mitjans a descobrir contingut del fedivers</strong>, no fent necessari que els usuaris locals manualment segueixin altres persones de servidors remots.
|
||||||
disable: Inhabilita
|
disable: Inhabilita
|
||||||
disabled: Desactivat
|
disabled: Desactivat
|
||||||
enable: Activat
|
enable: Activat
|
||||||
enable_hint: Una vegada habilitat el teu servidor es subscriurà a tots els toots públics d'aquest relay i començarà a enviar-hi tots els toots públics d'aquest servidor.
|
enable_hint: Una vegada habilitat el teu servidor es subscriurà a tots els gabs públics d'aquest relay i començarà a enviar-hi tots els gabs públics d'aquest servidor.
|
||||||
enabled: Activat
|
enabled: Activat
|
||||||
inbox_url: URL del Relay
|
inbox_url: URL del Relay
|
||||||
pending: S'està esperant l'aprovació del relay
|
pending: S'està esperant l'aprovació del relay
|
||||||
|
@ -426,7 +426,7 @@ ca:
|
||||||
open: Qualsevol pot registrar-se
|
open: Qualsevol pot registrar-se
|
||||||
title: Mode de registres
|
title: Mode de registres
|
||||||
show_known_fediverse_at_about_page:
|
show_known_fediverse_at_about_page:
|
||||||
desc_html: Quan s'activa, mostrarà tots els toots de tot el fedivers conegut en vista prèvia. En cas contrari, només es mostraran toots locals.
|
desc_html: Quan s'activa, mostrarà tots els gabs de tot el fedivers conegut en vista prèvia. En cas contrari, només es mostraran gabs locals.
|
||||||
title: Mostra el fedivers conegut en vista prèvia de la línia de temps
|
title: Mostra el fedivers conegut en vista prèvia de la línia de temps
|
||||||
show_staff_badge:
|
show_staff_badge:
|
||||||
desc_html: Mostra una insígnia de personal en la pàgina d'usuari
|
desc_html: Mostra una insígnia de personal en la pàgina d'usuari
|
||||||
|
@ -596,7 +596,7 @@ ca:
|
||||||
archive_takeout:
|
archive_takeout:
|
||||||
date: Data
|
date: Data
|
||||||
download: Descarrega l’arxiu
|
download: Descarrega l’arxiu
|
||||||
hint_html: Pots sol·licitar un arxiu dels teus <strong>toots i dels fitxers multimèdia pujats</strong>. Les dades exportades tindran el format ActivityPub, llegible per qualsevol programari compatible. Pots sol·licitar un arxiu cada 7 dies.
|
hint_html: Pots sol·licitar un arxiu dels teus <strong>gabs i dels fitxers multimèdia pujats</strong>. Les dades exportades tindran el format ActivityPub, llegible per qualsevol programari compatible. Pots sol·licitar un arxiu cada 7 dies.
|
||||||
in_progress: Compilant el teu arxiu...
|
in_progress: Compilant el teu arxiu...
|
||||||
request: Sol·licita el teu arxiu
|
request: Sol·licita el teu arxiu
|
||||||
size: Tamany
|
size: Tamany
|
||||||
|
@ -652,8 +652,8 @@ ca:
|
||||||
i_am_html: Sóc %{username} a %{service}.
|
i_am_html: Sóc %{username} a %{service}.
|
||||||
identity: Identitat
|
identity: Identitat
|
||||||
inactive: Inactiu
|
inactive: Inactiu
|
||||||
publicize_checkbox: 'I tooteja això:'
|
publicize_checkbox: 'I gab això:'
|
||||||
publicize_toot: 'Està provat! Sóc %{username} a %{service}: %{url}'
|
publicize_gab: 'Està provat! Sóc %{username} a %{service}: %{url}'
|
||||||
status: Estat de verificació
|
status: Estat de verificació
|
||||||
view_proof: Veure la prova
|
view_proof: Veure la prova
|
||||||
imports:
|
imports:
|
||||||
|
@ -796,20 +796,20 @@ ca:
|
||||||
remote_interaction:
|
remote_interaction:
|
||||||
favourite:
|
favourite:
|
||||||
proceed: Procedir a afavorir
|
proceed: Procedir a afavorir
|
||||||
prompt: 'Vols marcar com a favorit aquest toot:'
|
prompt: 'Vols marcar com a favorit aquest gab:'
|
||||||
reblog:
|
reblog:
|
||||||
proceed: Procedir a impulsar
|
proceed: Procedir a impulsar
|
||||||
prompt: 'Vols impulsar aquest toot:'
|
prompt: 'Vols impulsar aquest gab:'
|
||||||
reply:
|
reply:
|
||||||
proceed: Procedir a respondre
|
proceed: Procedir a respondre
|
||||||
prompt: 'Vols respondre a aquest toot:'
|
prompt: 'Vols respondre a aquest gab:'
|
||||||
remote_unfollow:
|
remote_unfollow:
|
||||||
error: Error
|
error: Error
|
||||||
title: Títol
|
title: Títol
|
||||||
unfollowed: Sense seguir
|
unfollowed: Sense seguir
|
||||||
scheduled_statuses:
|
scheduled_statuses:
|
||||||
over_daily_limit: Has superat el límit de %{limit} toots programats per a aquell dia
|
over_daily_limit: Has superat el límit de %{limit} gabs programats per a aquell dia
|
||||||
over_total_limit: Has superat el limit de %{limit} toots programats
|
over_total_limit: Has superat el limit de %{limit} gabs programats
|
||||||
too_soon: La data programada ha de ser futura
|
too_soon: La data programada ha de ser futura
|
||||||
sessions:
|
sessions:
|
||||||
activity: Última activitat
|
activity: Última activitat
|
||||||
|
@ -889,9 +889,9 @@ ca:
|
||||||
open_in_web: Obre en la web
|
open_in_web: Obre en la web
|
||||||
over_character_limit: Límit de caràcters de %{max} superat
|
over_character_limit: Límit de caràcters de %{max} superat
|
||||||
pin_errors:
|
pin_errors:
|
||||||
limit: Ja has fixat el màxim nombre de toots
|
limit: Ja has fixat el màxim nombre de gabs
|
||||||
ownership: No es pot fixar el toot d'algú altre
|
ownership: No es pot fixar el gab d'algú altre
|
||||||
private: No es pot fixar el toot no públic
|
private: No es pot fixar el gab no públic
|
||||||
reblog: No es pot fixar un impuls
|
reblog: No es pot fixar un impuls
|
||||||
poll:
|
poll:
|
||||||
total_votes:
|
total_votes:
|
||||||
|
@ -909,7 +909,7 @@ ca:
|
||||||
unlisted: No llistat
|
unlisted: No llistat
|
||||||
unlisted_long: Tothom ho pot veure, però no es mostra en la història federada
|
unlisted_long: Tothom ho pot veure, però no es mostra en la història federada
|
||||||
stream_entries:
|
stream_entries:
|
||||||
pinned: Toot fixat
|
pinned: Gab fixat
|
||||||
reblogged: ha impulsat
|
reblogged: ha impulsat
|
||||||
sensitive_content: Contingut sensible
|
sensitive_content: Contingut sensible
|
||||||
terms:
|
terms:
|
||||||
|
@ -919,8 +919,8 @@ ca:
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li><em>Informació bàsica del compte</em>: Si et registres en aquest servidor, se´t pot demanar que introdueixis un nom d'usuari, una adreça de correu electrònic i una contrasenya. També pots introduir informació de perfil addicional, com ara un nom de visualització i una biografia, i carregar una imatge de perfil i de capçalera. El nom d'usuari, el nom de visualització, la biografia, la imatge de perfil i la imatge de capçalera sempre apareixen públicament.</li>
|
<li><em>Informació bàsica del compte</em>: Si et registres en aquest servidor, se´t pot demanar que introdueixis un nom d'usuari, una adreça de correu electrònic i una contrasenya. També pots introduir informació de perfil addicional, com ara un nom de visualització i una biografia, i carregar una imatge de perfil i de capçalera. El nom d'usuari, el nom de visualització, la biografia, la imatge de perfil i la imatge de capçalera sempre apareixen públicament.</li>
|
||||||
<li><em>Publicacions, seguiment i altra informació pública</em>: La llista de persones que segueixes s'enumeren públicament i el mateix passa amb els teus seguidors. Quan envies un missatge, la data i l'hora s'emmagatzemen, així com l'aplicació que va enviar el missatge. Els missatges poden contenir multimèdia, com ara imatges i vídeos. Els toots públics i no llistats estan disponibles públicament. En quan tinguis un toot en el teu perfil, aquest també és informació pública. Les teves entrades es lliuren als teus seguidors que en alguns casos significa que es lliuren a diferents servidors en els quals s'hi emmagatzemen còpies. Quan suprimeixes publicacions, també es lliuraran als teus seguidors. L'acció d'impulsar o marcar com a favorit una publicació sempre és pública.</li>
|
<li><em>Publicacions, seguiment i altra informació pública</em>: La llista de persones que segueixes s'enumeren públicament i el mateix passa amb els teus seguidors. Quan envies un missatge, la data i l'hora s'emmagatzemen, així com l'aplicació que va enviar el missatge. Els missatges poden contenir multimèdia, com ara imatges i vídeos. Els gabs públics i no llistats estan disponibles públicament. En quan tinguis un gab en el teu perfil, aquest també és informació pública. Les teves entrades es lliuren als teus seguidors que en alguns casos significa que es lliuren a diferents servidors en els quals s'hi emmagatzemen còpies. Quan suprimeixes publicacions, també es lliuraran als teus seguidors. L'acció d'impulsar o marcar com a favorit una publicació sempre és pública.</li>
|
||||||
<li><em>Toots directes i per a només seguidors</em>: Totes les publicacions s'emmagatzemen i processen al servidor. Els toots per a només seguidors només es lliuren als teus seguidors i als usuaris que s'esmenten en ells i els toots directes només es lliuren als usuaris esmentats. En alguns casos, significa que es lliuren a diferents servidors i s'hi emmagatzemen còpies. Fem un esforç de bona fe per limitar l'accés a aquestes publicacions només a les persones autoritzades, però és possible que altres servidors no ho facin. Per tant, és important revisar els servidors als quals pertanyen els teus seguidors. Pots canviar la opció de aprovar o rebutjar els nous seguidors manualment a la configuració. <em>Tingues en compte que els operadors del servidor i qualsevol servidor receptor poden visualitzar aquests missatges</em> i els destinataris poden fer una captura de pantalla, copiar-los o tornar-los a compartir. <em>No comparteixis cap informació perillosa a Gab Social.</em></li>
|
<li><em>Gabs directes i per a només seguidors</em>: Totes les publicacions s'emmagatzemen i processen al servidor. Els gabs per a només seguidors només es lliuren als teus seguidors i als usuaris que s'esmenten en ells i els gabs directes només es lliuren als usuaris esmentats. En alguns casos, significa que es lliuren a diferents servidors i s'hi emmagatzemen còpies. Fem un esforç de bona fe per limitar l'accés a aquestes publicacions només a les persones autoritzades, però és possible que altres servidors no ho facin. Per tant, és important revisar els servidors als quals pertanyen els teus seguidors. Pots canviar la opció de aprovar o rebutjar els nous seguidors manualment a la configuració. <em>Tingues en compte que els operadors del servidor i qualsevol servidor receptor poden visualitzar aquests missatges</em> i els destinataris poden fer una captura de pantalla, copiar-los o tornar-los a compartir. <em>No comparteixis cap informació perillosa a Gab Social.</em></li>
|
||||||
<li><em>IPs i altres metadades</em>: Quan inicies sessió registrem l'adreça IP en que l'has iniciat, així com el nom de l'aplicació o navegador. Totes les sessions registrades estan disponibles per a la teva revisió i revocació a la configuració. L'última adreça IP utilitzada s'emmagatzema durant un màxim de 12 mesos. També podrem conservar els registres que inclouen l'adreça IP de cada sol·licitud al nostre servidor.</li>
|
<li><em>IPs i altres metadades</em>: Quan inicies sessió registrem l'adreça IP en que l'has iniciat, així com el nom de l'aplicació o navegador. Totes les sessions registrades estan disponibles per a la teva revisió i revocació a la configuració. L'última adreça IP utilitzada s'emmagatzema durant un màxim de 12 mesos. També podrem conservar els registres que inclouen l'adreça IP de cada sol·licitud al nostre servidor.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
@ -971,7 +971,7 @@ ca:
|
||||||
|
|
||||||
<p>No venem, comercialitzem ni transmetem a tercers la teva informació d'identificació personal. Això no inclou tercers de confiança que ens ajuden a operar el nostre lloc, a dur a terme el nostre servei o a servir-te, sempre que aquestes parts acceptin mantenir confidencial aquesta informació. També podem publicar la teva informació quan creiem que l'alliberament és apropiat per complir amb la llei, fer complir les polítiques del nostre lloc o protegir els nostres drets o altres drets, propietat o seguretat.</p>
|
<p>No venem, comercialitzem ni transmetem a tercers la teva informació d'identificació personal. Això no inclou tercers de confiança que ens ajuden a operar el nostre lloc, a dur a terme el nostre servei o a servir-te, sempre que aquestes parts acceptin mantenir confidencial aquesta informació. També podem publicar la teva informació quan creiem que l'alliberament és apropiat per complir amb la llei, fer complir les polítiques del nostre lloc o protegir els nostres drets o altres drets, propietat o seguretat.</p>
|
||||||
|
|
||||||
<p>Els altres servidors de la teva xarxa poden descarregar contingut públic. Els teus toots públics i per a només seguidors es lliuren als servidors on resideixen els teus seguidors i els missatges directes s'envien als servidors dels destinataris, sempre que aquests seguidors o destinataris resideixin en un servidor diferent d'aquest.</p>
|
<p>Els altres servidors de la teva xarxa poden descarregar contingut públic. Els teus gabs públics i per a només seguidors es lliuren als servidors on resideixen els teus seguidors i els missatges directes s'envien als servidors dels destinataris, sempre que aquests seguidors o destinataris resideixin en un servidor diferent d'aquest.</p>
|
||||||
|
|
||||||
<p>Quan autoritzes una aplicació a utilitzar el teu compte, segons l'abast dels permisos que aprovis, pot accedir a la teva informació de perfil pública, a la teva llista de seguits, als teus seguidors, a les teves llistes, a totes les teves publicacions i als teus favorits. Les aplicacions mai no poden accedir a la teva adreça de correu electrònic o contrasenya.</p>
|
<p>Quan autoritzes una aplicació a utilitzar el teu compte, segons l'abast dels permisos que aprovis, pot accedir a la teva informació de perfil pública, a la teva llista de seguits, als teus seguidors, a les teves llistes, a totes les teves publicacions i als teus favorits. Les aplicacions mai no poden accedir a la teva adreça de correu electrònic o contrasenya.</p>
|
||||||
|
|
||||||
|
@ -1028,7 +1028,7 @@ ca:
|
||||||
explanation:
|
explanation:
|
||||||
disable: Mentre el teu compte estigui congelat les dades romandran intactes però no pots dur a terme cap acció fins que no estigui desbloquejat.
|
disable: Mentre el teu compte estigui congelat les dades romandran intactes però no pots dur a terme cap acció fins que no estigui desbloquejat.
|
||||||
silence: Mentre el teu compte estigui limitat només les persones que ja et segueixen veuen les teves dades en aquest servidor i pots ser exclòs de diverses llistes públiques. No obstant això, d'altres encara poden seguir-te manualment.
|
silence: Mentre el teu compte estigui limitat només les persones que ja et segueixen veuen les teves dades en aquest servidor i pots ser exclòs de diverses llistes públiques. No obstant això, d'altres encara poden seguir-te manualment.
|
||||||
suspend: El teu compte s'ha suspès i tots els teus toots i fitxers multimèdia penjats s'han eliminat irreversiblement d'aquest servidor i dels servidors on tenies seguidors.
|
suspend: El teu compte s'ha suspès i tots els teus gabs i fitxers multimèdia penjats s'han eliminat irreversiblement d'aquest servidor i dels servidors on tenies seguidors.
|
||||||
review_server_policies: Revisa les polítiques del servidor
|
review_server_policies: Revisa les polítiques del servidor
|
||||||
subject:
|
subject:
|
||||||
disable: S'ha congelat el teu compte %{acct}
|
disable: S'ha congelat el teu compte %{acct}
|
||||||
|
|
|
@ -653,7 +653,7 @@ co:
|
||||||
identity: Identità
|
identity: Identità
|
||||||
inactive: Inattiva
|
inactive: Inattiva
|
||||||
publicize_checkbox: 'È mandà stu statutu:'
|
publicize_checkbox: 'È mandà stu statutu:'
|
||||||
publicize_toot: 'Hè pruvata! Sò %{username} nant’à %{service}: %{url}'
|
publicize_gab: 'Hè pruvata! Sò %{username} nant’à %{service}: %{url}'
|
||||||
status: Statutu di a verificazione
|
status: Statutu di a verificazione
|
||||||
view_proof: Vede a prova
|
view_proof: Vede a prova
|
||||||
imports:
|
imports:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
cs:
|
cs:
|
||||||
about:
|
about:
|
||||||
about_hashtag_html: Tohle jsou veřejné tooty označené hashtagem <strong>#%{hashtag}</strong>. Pokud máte účet kdekoliv ve fedivesmíru, můžete s nimi interagovat.
|
about_hashtag_html: Tohle jsou veřejné gabs označené hashtagem <strong>#%{hashtag}</strong>. Pokud máte účet kdekoliv ve fedivesmíru, můžete s nimi interagovat.
|
||||||
about_gabsocial_html: Gab Social je sociální síť založená na otevřených webových protokolech a svobodném, otevřeném softwaru. Je decentralizovaná jako e-mail.
|
about_gabsocial_html: Gab Social je sociální síť založená na otevřených webových protokolech a svobodném, otevřeném softwaru. Je decentralizovaná jako e-mail.
|
||||||
about_this: O tomto serveru
|
about_this: O tomto serveru
|
||||||
active_count_after: aktivních
|
active_count_after: aktivních
|
||||||
|
@ -30,9 +30,9 @@ cs:
|
||||||
server_stats: 'Statistika serveru:'
|
server_stats: 'Statistika serveru:'
|
||||||
source_code: Zdrojový kód
|
source_code: Zdrojový kód
|
||||||
status_count_after:
|
status_count_after:
|
||||||
few: tooty
|
few: gab
|
||||||
one: toot
|
one: Gab
|
||||||
other: tootů
|
other: gab
|
||||||
status_count_before: Kteří napsali
|
status_count_before: Kteří napsali
|
||||||
tagline: Sociální síť, která bojuje za svobodu slova, osobní svobodu a volný tok informací online. Všichni jsou vítáni.
|
tagline: Sociální síť, která bojuje za svobodu slova, osobní svobodu a volný tok informací online. Všichni jsou vítáni.
|
||||||
terms: Podmínky používání
|
terms: Podmínky používání
|
||||||
|
@ -62,11 +62,11 @@ cs:
|
||||||
pin_errors:
|
pin_errors:
|
||||||
following: Musíte již sledovat osobu, kterou chcete podpořit
|
following: Musíte již sledovat osobu, kterou chcete podpořit
|
||||||
posts:
|
posts:
|
||||||
few: Tooty
|
few: Gabs
|
||||||
one: Toot
|
one: Gab
|
||||||
other: Tootů
|
other: Gabs
|
||||||
posts_tab_heading: Tooty
|
posts_tab_heading: Gabs
|
||||||
posts_with_replies: Tooty a odpovědi
|
posts_with_replies: Gabs a odpovědi
|
||||||
reserved_username: Toto uživatelské jméno je rezervováno
|
reserved_username: Toto uživatelské jméno je rezervováno
|
||||||
roles:
|
roles:
|
||||||
admin: Administrátor
|
admin: Administrátor
|
||||||
|
@ -175,7 +175,7 @@ cs:
|
||||||
targeted_reports: Nahlášeni ostatními
|
targeted_reports: Nahlášeni ostatními
|
||||||
silence: Utišit
|
silence: Utišit
|
||||||
silenced: Utišen/a
|
silenced: Utišen/a
|
||||||
statuses: Tooty
|
statuses: Gabs
|
||||||
subscribe: Odebírat
|
subscribe: Odebírat
|
||||||
suspended: Pozastaven/a
|
suspended: Pozastaven/a
|
||||||
title: Účty
|
title: Účty
|
||||||
|
@ -199,7 +199,7 @@ cs:
|
||||||
destroy_custom_emoji: "%{name} zničil/a emoji %{target}"
|
destroy_custom_emoji: "%{name} zničil/a emoji %{target}"
|
||||||
destroy_domain_block: "%{name} odblokoval/a doménu %{target}"
|
destroy_domain_block: "%{name} odblokoval/a doménu %{target}"
|
||||||
destroy_email_domain_block: "%{name} odebral/a e-mailovou doménu %{target} z černé listiny"
|
destroy_email_domain_block: "%{name} odebral/a e-mailovou doménu %{target} z černé listiny"
|
||||||
destroy_status: "%{name} odstranil/a toot uživatele %{target}"
|
destroy_status: "%{name} odstranil/a gab uživatele %{target}"
|
||||||
disable_2fa_user: "%{name} vypnul/a dvoufázové ověřování pro uživatele %{target}"
|
disable_2fa_user: "%{name} vypnul/a dvoufázové ověřování pro uživatele %{target}"
|
||||||
disable_custom_emoji: "%{name} zakázal/a emoji %{target}"
|
disable_custom_emoji: "%{name} zakázal/a emoji %{target}"
|
||||||
disable_user: "%{name} zakázal/a přihlašování pro uživatele %{target}"
|
disable_user: "%{name} zakázal/a přihlašování pro uživatele %{target}"
|
||||||
|
@ -217,8 +217,8 @@ cs:
|
||||||
unsilence_account: "%{name} odtišil/a účet uživatele %{target}"
|
unsilence_account: "%{name} odtišil/a účet uživatele %{target}"
|
||||||
unsuspend_account: "%{name} zrušil/a pozastavení účtu uživatele %{target}"
|
unsuspend_account: "%{name} zrušil/a pozastavení účtu uživatele %{target}"
|
||||||
update_custom_emoji: "%{name} aktualizoval/a emoji %{target}"
|
update_custom_emoji: "%{name} aktualizoval/a emoji %{target}"
|
||||||
update_status: "%{name} aktualizoval/a toot uživatele %{target}"
|
update_status: "%{name} aktualizoval/a gab uživatele %{target}"
|
||||||
deleted_status: "(smazaný toot)"
|
deleted_status: "(smazaný gab)"
|
||||||
title: Záznam auditu
|
title: Záznam auditu
|
||||||
custom_emojis:
|
custom_emojis:
|
||||||
by_domain: Doména
|
by_domain: Doména
|
||||||
|
@ -345,11 +345,11 @@ cs:
|
||||||
relays:
|
relays:
|
||||||
add_new: Přidat nový most
|
add_new: Přidat nový most
|
||||||
delete: Smazat
|
delete: Smazat
|
||||||
description_html: "<strong>Federovací most</strong> je přechodný server, který vyměňuje velká množství veřejných tootů mezi servery, které z něj odebírají a publikují na něj. <strong>Může pomoci malým a středně velkým serverům objevovat obsah z fedivesmíru</strong>, což by jinak vyžadovalo, aby místní uživatelé manuálně sledovali jiné lidi na vzdálených serverech."
|
description_html: "<strong>Federovací most</strong> je přechodný server, který vyměňuje velká množství veřejných gab mezi servery, které z něj odebírají a publikují na něj. <strong>Může pomoci malým a středně velkým serverům objevovat obsah z fedivesmíru</strong>, což by jinak vyžadovalo, aby místní uživatelé manuálně sledovali jiné lidi na vzdálených serverech."
|
||||||
disable: Zakázat
|
disable: Zakázat
|
||||||
disabled: Zakázáno
|
disabled: Zakázáno
|
||||||
enable: Povolit
|
enable: Povolit
|
||||||
enable_hint: Je-li tohle povoleno, začne váš server odebírat všechny veřejné tooty z tohoto mostu a odesílat na něj své vlastní veřejné tooty.
|
enable_hint: Je-li tohle povoleno, začne váš server odebírat všechny veřejné gabs z tohoto mostu a odesílat na něj své vlastní veřejné gabs.
|
||||||
enabled: Povoleno
|
enabled: Povoleno
|
||||||
inbox_url: URL mostu
|
inbox_url: URL mostu
|
||||||
pending: Čekám na souhlas mostu
|
pending: Čekám na souhlas mostu
|
||||||
|
@ -392,7 +392,7 @@ cs:
|
||||||
updated_at: Aktualizováno
|
updated_at: Aktualizováno
|
||||||
settings:
|
settings:
|
||||||
activity_api_enabled:
|
activity_api_enabled:
|
||||||
desc_html: Počty lokálně publikovaných tootů, aktivních uživatelů a nových registrací, v týdenních intervalech
|
desc_html: Počty lokálně publikovaných gab, aktivních uživatelů a nových registrací, v týdenních intervalech
|
||||||
title: Publikovat hromadné statistiky o uživatelské aktivitě
|
title: Publikovat hromadné statistiky o uživatelské aktivitě
|
||||||
bootstrap_timeline_accounts:
|
bootstrap_timeline_accounts:
|
||||||
desc_html: Je-li uživatelských jmen více, oddělujte je čárkami. Lze zadat pouze místní a odemknuté účty. Je-li tohle prázdné, jsou výchozí hodnotou všichni místní administrátoři.
|
desc_html: Je-li uživatelských jmen více, oddělujte je čárkami. Lze zadat pouze místní a odemknuté účty. Je-li tohle prázdné, jsou výchozí hodnotou všichni místní administrátoři.
|
||||||
|
@ -432,7 +432,7 @@ cs:
|
||||||
open: Kdokoliv se může registrovat
|
open: Kdokoliv se může registrovat
|
||||||
title: Režim registrací
|
title: Režim registrací
|
||||||
show_known_fediverse_at_about_page:
|
show_known_fediverse_at_about_page:
|
||||||
desc_html: Je-li tohle zapnuto, zobrazí se v náhledu tooty z celého známého fedivesmíru. Jinak budou zobrazeny pouze místní tooty.
|
desc_html: Je-li tohle zapnuto, zobrazí se v náhledu gabs z celého známého fedivesmíru. Jinak budou zobrazeny pouze místní gabs.
|
||||||
title: Zobrazit na náhledu časové osy celý známý fedivesmír
|
title: Zobrazit na náhledu časové osy celý známý fedivesmír
|
||||||
show_staff_badge:
|
show_staff_badge:
|
||||||
desc_html: Zobrazit na stránce uživatele odznak člena personálu
|
desc_html: Zobrazit na stránce uživatele odznak člena personálu
|
||||||
|
@ -467,8 +467,8 @@ cs:
|
||||||
media:
|
media:
|
||||||
title: Média
|
title: Média
|
||||||
no_media: Žádná média
|
no_media: Žádná média
|
||||||
no_status_selected: Nebyly změněny žádné tooty, neboť žádné nebyly vybrány
|
no_status_selected: Nebyly změněny žádné gabs, neboť žádné nebyly vybrány
|
||||||
title: Tooty účtu
|
title: Gabs účtu
|
||||||
with_media: S médii
|
with_media: S médii
|
||||||
subscriptions:
|
subscriptions:
|
||||||
callback_url: Zpáteční URL
|
callback_url: Zpáteční URL
|
||||||
|
@ -506,7 +506,7 @@ cs:
|
||||||
settings: 'Změnit volby e-mailu: %{link}'
|
settings: 'Změnit volby e-mailu: %{link}'
|
||||||
view: 'Zobrazit:'
|
view: 'Zobrazit:'
|
||||||
view_profile: Zobrazit profil
|
view_profile: Zobrazit profil
|
||||||
view_status: Zobrazit toot
|
view_status: Zobrazit gab
|
||||||
applications:
|
applications:
|
||||||
created: Aplikace úspěšně vytvořena
|
created: Aplikace úspěšně vytvořena
|
||||||
destroyed: Aplikace úspěšně smazána
|
destroyed: Aplikace úspěšně smazána
|
||||||
|
@ -603,7 +603,7 @@ cs:
|
||||||
archive_takeout:
|
archive_takeout:
|
||||||
date: Datum
|
date: Datum
|
||||||
download: Stáhnout svůj archiv
|
download: Stáhnout svůj archiv
|
||||||
hint_html: Můžete si vyžádat archiv vašich <strong>tootů a nahraných médií</strong>. Exportovaná data budou ve formátu ActivityPub a budou čitelná kterýmkoliv kompatibilním softwarem. Archiv si můžete vyžádat každých 7 dní.
|
hint_html: Můžete si vyžádat archiv vašich <strong>gab a nahraných médií</strong>. Exportovaná data budou ve formátu ActivityPub a budou čitelná kterýmkoliv kompatibilním softwarem. Archiv si můžete vyžádat každých 7 dní.
|
||||||
in_progress: Kompiluji váš archiv…
|
in_progress: Kompiluji váš archiv…
|
||||||
request: Vyžádat svůj archiv
|
request: Vyžádat svůj archiv
|
||||||
size: Velikost
|
size: Velikost
|
||||||
|
@ -660,8 +660,8 @@ cs:
|
||||||
i_am_html: Na %{service} jsem %{username}.
|
i_am_html: Na %{service} jsem %{username}.
|
||||||
identity: Identita
|
identity: Identita
|
||||||
inactive: Neaktivní
|
inactive: Neaktivní
|
||||||
publicize_checkbox: 'A tootnout tohle:'
|
publicize_checkbox: 'A gab tohle:'
|
||||||
publicize_toot: 'Je to dokázáno! Na %{service} jsem %{username}: %{url}'
|
publicize_gab: 'Je to dokázáno! Na %{service} jsem %{username}: %{url}'
|
||||||
status: Stav ověření
|
status: Stav ověření
|
||||||
view_proof: Zobrazit důkaz
|
view_proof: Zobrazit důkaz
|
||||||
imports:
|
imports:
|
||||||
|
@ -707,7 +707,7 @@ cs:
|
||||||
limit: Dosáhl/a jste maximálního počtu seznamů
|
limit: Dosáhl/a jste maximálního počtu seznamů
|
||||||
media_attachments:
|
media_attachments:
|
||||||
validations:
|
validations:
|
||||||
images_and_video: K tootu, který již obsahuje obrázky, nelze připojit video
|
images_and_video: K gab, který již obsahuje obrázky, nelze připojit video
|
||||||
too_many: Nelze připojit více než 4 soubory
|
too_many: Nelze připojit více než 4 soubory
|
||||||
migrations:
|
migrations:
|
||||||
acct: přezdívka@doména nového účtu
|
acct: přezdívka@doména nového účtu
|
||||||
|
@ -731,8 +731,8 @@ cs:
|
||||||
other: "%{count} nových oznámení od vaší poslední návštěvy"
|
other: "%{count} nových oznámení od vaší poslední návštěvy"
|
||||||
title: Ve vaší nepřítomnosti…
|
title: Ve vaší nepřítomnosti…
|
||||||
favourite:
|
favourite:
|
||||||
body: 'Váš toot si oblíbil/a %{name}:'
|
body: 'Váš gab si oblíbil/a %{name}:'
|
||||||
subject: "%{name} si oblíbil/a váš toot"
|
subject: "%{name} si oblíbil/a váš gab"
|
||||||
title: Nové oblíbení
|
title: Nové oblíbení
|
||||||
follow:
|
follow:
|
||||||
body: "%{name} vás nyní sleduje!"
|
body: "%{name} vás nyní sleduje!"
|
||||||
|
@ -749,8 +749,8 @@ cs:
|
||||||
subject: Byl/a jste zmíněn/a uživatelem %{name}
|
subject: Byl/a jste zmíněn/a uživatelem %{name}
|
||||||
title: Nová zmínka
|
title: Nová zmínka
|
||||||
reblog:
|
reblog:
|
||||||
body: 'Váš toot byl repostnutý uživatelem %{name}:'
|
body: 'Váš gab byl repostnutý uživatelem %{name}:'
|
||||||
subject: "%{name} repostnul/a váš toot"
|
subject: "%{name} repostnul/a váš gab"
|
||||||
title: Nový repost
|
title: Nový repost
|
||||||
number:
|
number:
|
||||||
human:
|
human:
|
||||||
|
@ -807,20 +807,20 @@ cs:
|
||||||
remote_interaction:
|
remote_interaction:
|
||||||
favourite:
|
favourite:
|
||||||
proceed: Pokračovat k oblíbení
|
proceed: Pokračovat k oblíbení
|
||||||
prompt: 'Chcete si oblíbit tento toot:'
|
prompt: 'Chcete si oblíbit tento gab:'
|
||||||
reblog:
|
reblog:
|
||||||
proceed: Pokračovat k repostnutí
|
proceed: Pokračovat k repostnutí
|
||||||
prompt: 'Chcete repostnout tento toot:'
|
prompt: 'Chcete repostnout tento gab:'
|
||||||
reply:
|
reply:
|
||||||
proceed: Pokračovat k odpovězení
|
proceed: Pokračovat k odpovězení
|
||||||
prompt: 'Chcete odpovědět na tento toot:'
|
prompt: 'Chcete odpovědět na tento gab:'
|
||||||
remote_unfollow:
|
remote_unfollow:
|
||||||
error: Chyba
|
error: Chyba
|
||||||
title: Nadpis
|
title: Nadpis
|
||||||
unfollowed: Už nesledujete
|
unfollowed: Už nesledujete
|
||||||
scheduled_statuses:
|
scheduled_statuses:
|
||||||
over_daily_limit: Překročil/a jste limit %{limit} plánovaných tootů pro tento den
|
over_daily_limit: Překročil/a jste limit %{limit} plánovaných gab pro tento den
|
||||||
over_total_limit: Překročil/a jste limit %{limit} plánovaných tootů
|
over_total_limit: Překročil/a jste limit %{limit} plánovaných gab
|
||||||
too_soon: Plánované datum musí být v budoucnosti
|
too_soon: Plánované datum musí být v budoucnosti
|
||||||
sessions:
|
sessions:
|
||||||
activity: Nejnovější aktivita
|
activity: Nejnovější aktivita
|
||||||
|
@ -903,9 +903,9 @@ cs:
|
||||||
open_in_web: Otevřít na webu
|
open_in_web: Otevřít na webu
|
||||||
over_character_limit: limit %{max} znaků byl překročen
|
over_character_limit: limit %{max} znaků byl překročen
|
||||||
pin_errors:
|
pin_errors:
|
||||||
limit: Už jste si připnul/a maximální počet tootů
|
limit: Už jste si připnul/a maximální počet gab
|
||||||
ownership: Nelze připnout toot někoho jiného
|
ownership: Nelze připnout gab někoho jiného
|
||||||
private: Nelze připnout neveřejné tooty
|
private: Nelze připnout neveřejné gabs
|
||||||
reblog: Nelze připnout repost
|
reblog: Nelze připnout repost
|
||||||
poll:
|
poll:
|
||||||
total_votes:
|
total_votes:
|
||||||
|
@ -924,7 +924,7 @@ cs:
|
||||||
unlisted: Neuvedené
|
unlisted: Neuvedené
|
||||||
unlisted_long: Všichni mohou vidět, ale nebudou zahrnuty ve veřejných časových osách
|
unlisted_long: Všichni mohou vidět, ale nebudou zahrnuty ve veřejných časových osách
|
||||||
stream_entries:
|
stream_entries:
|
||||||
pinned: Připnutý toot
|
pinned: Připnutý gab
|
||||||
reblogged: repostnul/a
|
reblogged: repostnul/a
|
||||||
sensitive_content: Citlivý obsah
|
sensitive_content: Citlivý obsah
|
||||||
terms:
|
terms:
|
||||||
|
@ -1042,8 +1042,8 @@ cs:
|
||||||
warning:
|
warning:
|
||||||
explanation:
|
explanation:
|
||||||
disable: Zatímco je váš účet zmražen, zůstávají data vašeho účtu nedotčená, ale nemůžete vykonávat žádné akce, dokud nebude odemčen.
|
disable: Zatímco je váš účet zmražen, zůstávají data vašeho účtu nedotčená, ale nemůžete vykonávat žádné akce, dokud nebude odemčen.
|
||||||
silence: Zatímco je váš účet omezen, mohou vaše tooty na tomto serveru vidět pouze lidé, kteří váš již sledují, a můžete být vyloučen/a z různých veřejných výpisů. Ostatní vás však pořád mohou manuálně sledovat.
|
silence: Zatímco je váš účet omezen, mohou vaše gabs na tomto serveru vidět pouze lidé, kteří váš již sledují, a můžete být vyloučen/a z různých veřejných výpisů. Ostatní vás však pořád mohou manuálně sledovat.
|
||||||
suspend: Váš účet byl pozastaven a všechny vaše tooty a vaše nahrané mediální soubory byly nenávratně odstraněny z tohoto serveru a serverů, na kterých jste měl/a sledující.
|
suspend: Váš účet byl pozastaven a všechny vaše gabs a vaše nahrané mediální soubory byly nenávratně odstraněny z tohoto serveru a serverů, na kterých jste měl/a sledující.
|
||||||
review_server_policies: Posoudit politiku serveru
|
review_server_policies: Posoudit politiku serveru
|
||||||
subject:
|
subject:
|
||||||
disable: Váš účet %{acct} byl zmražen
|
disable: Váš účet %{acct} byl zmražen
|
||||||
|
|
|
@ -653,7 +653,7 @@ de:
|
||||||
identity: Identität
|
identity: Identität
|
||||||
inactive: Inaktiv
|
inactive: Inaktiv
|
||||||
publicize_checkbox: 'Und poste das:'
|
publicize_checkbox: 'Und poste das:'
|
||||||
publicize_toot: 'Es ist offiziell! Ich bin %{username} auf %{service}: %{url}'
|
publicize_gab: 'Es ist offiziell! Ich bin %{username} auf %{service}: %{url}'
|
||||||
status: Verifizierungsstatus
|
status: Verifizierungsstatus
|
||||||
view_proof: Zeige Nachweis
|
view_proof: Zeige Nachweis
|
||||||
imports:
|
imports:
|
||||||
|
|
|
@ -127,11 +127,11 @@ cs:
|
||||||
read:notifications: vidět vaše oznámení
|
read:notifications: vidět vaše oznámení
|
||||||
read:reports: vidět vaše nahlášení
|
read:reports: vidět vaše nahlášení
|
||||||
read:search: vyhledávat za vás
|
read:search: vyhledávat za vás
|
||||||
read:statuses: vidět všechny tooty
|
read:statuses: vidět všechny gabs
|
||||||
write: měnit všechna data vašeho účtu
|
write: měnit všechna data vašeho účtu
|
||||||
write:accounts: měnit váš profil
|
write:accounts: měnit váš profil
|
||||||
write:blocks: blokovat účty a domény
|
write:blocks: blokovat účty a domény
|
||||||
write:favourites: oblibovat si tooty
|
write:favourites: oblibovat si gabs
|
||||||
write:filters: vytvářet filtry
|
write:filters: vytvářet filtry
|
||||||
write:follows: sledovat lidi
|
write:follows: sledovat lidi
|
||||||
write:lists: vytvářet seznamy
|
write:lists: vytvářet seznamy
|
||||||
|
@ -139,4 +139,4 @@ cs:
|
||||||
write:mutes: skrývat lidi a konverzace
|
write:mutes: skrývat lidi a konverzace
|
||||||
write:notifications: vymazávat vaše oznámení
|
write:notifications: vymazávat vaše oznámení
|
||||||
write:reports: nahlašovat jiné uživatele
|
write:reports: nahlašovat jiné uživatele
|
||||||
write:statuses: publikovat tooty
|
write:statuses: publikovat gabs
|
||||||
|
|
|
@ -126,13 +126,13 @@ nl:
|
||||||
read:lists: zie jouw lijsten
|
read:lists: zie jouw lijsten
|
||||||
read:mutes: zie jouw genegeerde gebruikers
|
read:mutes: zie jouw genegeerde gebruikers
|
||||||
read:notifications: zie jouw meldingen
|
read:notifications: zie jouw meldingen
|
||||||
read:reports: zie jouw gerapporteerde toots
|
read:reports: zie jouw gerapporteerde gabs
|
||||||
read:search: namens jou zoeken
|
read:search: namens jou zoeken
|
||||||
read:statuses: zie alle toots
|
read:statuses: zie alle gabs
|
||||||
write: alle gegevens van jouw account bewerken
|
write: alle gegevens van jouw account bewerken
|
||||||
write:accounts: jouw profiel bewerken
|
write:accounts: jouw profiel bewerken
|
||||||
write:blocks: accounts en domeinen blokkeren
|
write:blocks: accounts en domeinen blokkeren
|
||||||
write:favourites: toots als favoriet markeren
|
write:favourites: gabs als favoriet markeren
|
||||||
write:filters: filters aanmaken
|
write:filters: filters aanmaken
|
||||||
write:follows: mensen volgen
|
write:follows: mensen volgen
|
||||||
write:lists: lijsten aanmaken
|
write:lists: lijsten aanmaken
|
||||||
|
@ -140,4 +140,4 @@ nl:
|
||||||
write:mutes: mensen en gesprekken negeren
|
write:mutes: mensen en gesprekken negeren
|
||||||
write:notifications: meldingen verwijderen
|
write:notifications: meldingen verwijderen
|
||||||
write:reports: andere mensen rapporteren
|
write:reports: andere mensen rapporteren
|
||||||
write:statuses: toots publiceren
|
write:statuses: gabs publiceren
|
||||||
|
|
|
@ -681,7 +681,7 @@ en:
|
||||||
identity: Identity
|
identity: Identity
|
||||||
inactive: Inactive
|
inactive: Inactive
|
||||||
publicize_checkbox: 'And gab this:'
|
publicize_checkbox: 'And gab this:'
|
||||||
publicize_toot: 'I am %{username} on %{service}: %{url}'
|
publicize_gab: 'I am %{username} on %{service}: %{url}'
|
||||||
status: Verification status
|
status: Verification status
|
||||||
view_proof: View proof
|
view_proof: View proof
|
||||||
imports:
|
imports:
|
||||||
|
|
|
@ -649,7 +649,7 @@ eo:
|
||||||
identity: Identeco
|
identity: Identeco
|
||||||
inactive: Malaktiva
|
inactive: Malaktiva
|
||||||
publicize_checkbox: 'And gab this:'
|
publicize_checkbox: 'And gab this:'
|
||||||
publicize_toot: 'It is proven! I am %{username} on %{service}: %{url}'
|
publicize_gab: 'It is proven! I am %{username} on %{service}: %{url}'
|
||||||
status: Confirmo statuso
|
status: Confirmo statuso
|
||||||
view_proof: Vidi pruvo
|
view_proof: Vidi pruvo
|
||||||
imports:
|
imports:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
es:
|
es:
|
||||||
about:
|
about:
|
||||||
about_hashtag_html: Estos son toots públicos etiquetados con <strong>#%{hashtag}</strong>. Puedes interactuar con ellos si tienes una cuenta en cualquier parte del fediverso.
|
about_hashtag_html: Estos son gabs públicos etiquetados con <strong>#%{hashtag}</strong>. Puedes interactuar con ellos si tienes una cuenta en cualquier parte del fediverso.
|
||||||
about_gabsocial_html: Gab Social es un servidor de red social <em>libre y de código abierto</em>. Una alternativa <em>descentralizada</em> a plataformas comerciales, que evita el riesgo de que una única compañía monopolice tu comunicación. Cualquiera puede ejecutar Gab Social y participar sin problemas en la <em>red social</em>.
|
about_gabsocial_html: Gab Social es un servidor de red social <em>libre y de código abierto</em>. Una alternativa <em>descentralizada</em> a plataformas comerciales, que evita el riesgo de que una única compañía monopolice tu comunicación. Cualquiera puede ejecutar Gab Social y participar sin problemas en la <em>red social</em>.
|
||||||
about_this: Acerca de esta instancia
|
about_this: Acerca de esta instancia
|
||||||
administered_by: 'Administrado por:'
|
administered_by: 'Administrado por:'
|
||||||
|
@ -48,10 +48,10 @@ es:
|
||||||
pin_errors:
|
pin_errors:
|
||||||
following: Debes estar siguiendo a la persona a la que quieres aprobar
|
following: Debes estar siguiendo a la persona a la que quieres aprobar
|
||||||
posts:
|
posts:
|
||||||
one: Toot
|
one: Gab
|
||||||
other: Toots
|
other: Gabs
|
||||||
posts_tab_heading: Toots
|
posts_tab_heading: Gabs
|
||||||
posts_with_replies: Toots con respuestas
|
posts_with_replies: Gabs con respuestas
|
||||||
reserved_username: El nombre de usuario está reservado
|
reserved_username: El nombre de usuario está reservado
|
||||||
roles:
|
roles:
|
||||||
admin: Administrador
|
admin: Administrador
|
||||||
|
@ -289,11 +289,11 @@ es:
|
||||||
relays:
|
relays:
|
||||||
add_new: Añadir un nuevo relés
|
add_new: Añadir un nuevo relés
|
||||||
delete: Borrar
|
delete: Borrar
|
||||||
description_html: Un <strong>relés de federation</strong> es un servidor intermedio que intercambia grandes volúmenes de toots públicos entre servidores que se suscriben y publican en él. <strong>Puede ayudar a servidores pequeños y medianos a descubir contenido del fediverso</strong>, que de otra manera requeriría que los usuarios locales siguiesen manialmente a personas de servidores remotos.
|
description_html: Un <strong>relés de federation</strong> es un servidor intermedio que intercambia grandes volúmenes de gabs públicos entre servidores que se suscriben y publican en él. <strong>Puede ayudar a servidores pequeños y medianos a descubir contenido del fediverso</strong>, que de otra manera requeriría que los usuarios locales siguiesen manialmente a personas de servidores remotos.
|
||||||
disable: Deshabilitar
|
disable: Deshabilitar
|
||||||
disabled: Deshabilitado
|
disabled: Deshabilitado
|
||||||
enable: Hablitar
|
enable: Hablitar
|
||||||
enable_hint: Una vez conectado, tu servidor se suscribirá a todos los toots públicos de este relés, y comenzará a enviar los toots públicos de este servidor hacia él.
|
enable_hint: Una vez conectado, tu servidor se suscribirá a todos los gabs públicos de este relés, y comenzará a enviar los gabs públicos de este servidor hacia él.
|
||||||
enabled: Habilitado
|
enabled: Habilitado
|
||||||
inbox_url: URL del relés
|
inbox_url: URL del relés
|
||||||
pending: Esperando la aprobación del relés
|
pending: Esperando la aprobación del relés
|
||||||
|
@ -367,7 +367,7 @@ es:
|
||||||
disabled: Nadie
|
disabled: Nadie
|
||||||
title: Permitir invitaciones de
|
title: Permitir invitaciones de
|
||||||
show_known_fediverse_at_about_page:
|
show_known_fediverse_at_about_page:
|
||||||
desc_html: Cuando esté activado, se mostrarán toots de todo el fediverso conocido en la vista previa. En otro caso, se mostrarán solamente toots locales.
|
desc_html: Cuando esté activado, se mostrarán gabs de todo el fediverso conocido en la vista previa. En otro caso, se mostrarán solamente gabs locales.
|
||||||
title: Mostrar fediverso conocido en la vista previa de la historia
|
title: Mostrar fediverso conocido en la vista previa de la historia
|
||||||
show_staff_badge:
|
show_staff_badge:
|
||||||
desc_html: Mostrar un parche de staff en la página de un usuario
|
desc_html: Mostrar un parche de staff en la página de un usuario
|
||||||
|
@ -503,7 +503,7 @@ es:
|
||||||
archive_takeout:
|
archive_takeout:
|
||||||
date: Fecha
|
date: Fecha
|
||||||
download: Descargar tu archivo
|
download: Descargar tu archivo
|
||||||
hint_html: Puedes solicitar un archivo de tus <strong>toots y materiales subidos</strong>. Los datos exportados estarán en formato ActivityPub, legibles por cualquier software compatible.
|
hint_html: Puedes solicitar un archivo de tus <strong>gabs y materiales subidos</strong>. Los datos exportados estarán en formato ActivityPub, legibles por cualquier software compatible.
|
||||||
in_progress: Recopilando tu archivo...
|
in_progress: Recopilando tu archivo...
|
||||||
request: Solicitar tu archivo
|
request: Solicitar tu archivo
|
||||||
size: Tamaño
|
size: Tamaño
|
||||||
|
@ -615,8 +615,8 @@ es:
|
||||||
subject: Fuiste mencionado por %{name}
|
subject: Fuiste mencionado por %{name}
|
||||||
title: Nueva mención
|
title: Nueva mención
|
||||||
reblog:
|
reblog:
|
||||||
body: "%{name} ha retooteado tu estado:"
|
body: "%{name} ha reposted tu estado:"
|
||||||
subject: "%{name} ha retooteado tu estado"
|
subject: "%{name} ha reposted tu estado"
|
||||||
title: Nueva difusión
|
title: Nueva difusión
|
||||||
number:
|
number:
|
||||||
human:
|
human:
|
||||||
|
@ -722,8 +722,8 @@ es:
|
||||||
over_character_limit: Límite de caracteres de %{max} superado
|
over_character_limit: Límite de caracteres de %{max} superado
|
||||||
pin_errors:
|
pin_errors:
|
||||||
limit: Ya has fijado el número máximo de publicaciones
|
limit: Ya has fijado el número máximo de publicaciones
|
||||||
ownership: El toot de alguien más no puede fijarse
|
ownership: El gab de alguien más no puede fijarse
|
||||||
private: Los toots no-públicos no pueden fijarse
|
private: Los gabs no-públicos no pueden fijarse
|
||||||
reblog: Un repost no puede fijarse
|
reblog: Un repost no puede fijarse
|
||||||
show_more: Mostrar más
|
show_more: Mostrar más
|
||||||
sign_in_to_participate: Regístrate para participar en la conversación
|
sign_in_to_participate: Regístrate para participar en la conversación
|
||||||
|
@ -736,8 +736,8 @@ es:
|
||||||
unlisted: Público, pero no mostrar en la historia federada
|
unlisted: Público, pero no mostrar en la historia federada
|
||||||
unlisted_long: Todos pueden ver, pero no está listado en las líneas de tiempo públicas
|
unlisted_long: Todos pueden ver, pero no está listado en las líneas de tiempo públicas
|
||||||
stream_entries:
|
stream_entries:
|
||||||
pinned: Toot fijado
|
pinned: Gab fijado
|
||||||
reblogged: retooteado
|
reblogged: reposted
|
||||||
sensitive_content: Contenido sensible
|
sensitive_content: Contenido sensible
|
||||||
terms:
|
terms:
|
||||||
title: Términos del Servicio y Políticas de Privacidad de %{instance}
|
title: Términos del Servicio y Políticas de Privacidad de %{instance}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
eu:
|
eu:
|
||||||
about:
|
about:
|
||||||
about_hashtag_html: Hauek <strong>#%{hashtag}</strong> traola duten toot publikoak dira. Fedibertsoko edozein kontu baduzu harremanetan jarri zaitezke.
|
about_hashtag_html: Hauek <strong>#%{hashtag}</strong> traola duten gab publikoak dira. Fedibertsoko edozein kontu baduzu harremanetan jarri zaitezke.
|
||||||
about_gabsocial_html: Gab Social web protokolo ireki eta libreak darabiltzan gizarte sare bat da. E-mail sarea bezala deszentralizatua da.
|
about_gabsocial_html: Gab Social web protokolo ireki eta libreak darabiltzan gizarte sare bat da. E-mail sarea bezala deszentralizatua da.
|
||||||
about_this: Honi buruz
|
about_this: Honi buruz
|
||||||
administered_by: 'Administratzailea(k):'
|
administered_by: 'Administratzailea(k):'
|
||||||
|
@ -48,10 +48,10 @@ eu:
|
||||||
pin_errors:
|
pin_errors:
|
||||||
following: Onetsi nahi duzun pertsona aurretik jarraitu behar duzu
|
following: Onetsi nahi duzun pertsona aurretik jarraitu behar duzu
|
||||||
posts:
|
posts:
|
||||||
one: Toot
|
one: Gab
|
||||||
other: Toot
|
other: Gab
|
||||||
posts_tab_heading: Tootak
|
posts_tab_heading: Gabs
|
||||||
posts_with_replies: Toot eta erantzunak
|
posts_with_replies: Gabs eta erantzunak
|
||||||
reserved_username: Erabiltzaile-izena erreserbatuta dago
|
reserved_username: Erabiltzaile-izena erreserbatuta dago
|
||||||
roles:
|
roles:
|
||||||
admin: Administratzailea
|
admin: Administratzailea
|
||||||
|
@ -316,11 +316,11 @@ eu:
|
||||||
relays:
|
relays:
|
||||||
add_new: Gehitu hari berria
|
add_new: Gehitu hari berria
|
||||||
delete: Ezabatu
|
delete: Ezabatu
|
||||||
description_html: "<strong>Federazio errele</strong> bat zerbitzari tartekari bat da, bertara harpidetutako eta bertan argitaratzen duten zerbitzarien artean toot publiko kopuru handiak banatzen ditu. <strong>Zerbitzari txiki eta ertainei Fedibertsoko edukia aurkitzen laguntzen die</strong>, bestela erabiltzaile lokalek eskuz jarraitu beharko lituzkete urruneko zerbitzarietako erabiltzaileak."
|
description_html: "<strong>Federazio errele</strong> bat zerbitzari tartekari bat da, bertara harpidetutako eta bertan argitaratzen duten zerbitzarien artean gab publiko kopuru handiak banatzen ditu. <strong>Zerbitzari txiki eta ertainei Fedibertsoko edukia aurkitzen laguntzen die</strong>, bestela erabiltzaile lokalek eskuz jarraitu beharko lituzkete urruneko zerbitzarietako erabiltzaileak."
|
||||||
disable: Desgaitu
|
disable: Desgaitu
|
||||||
disabled: Desgaituta
|
disabled: Desgaituta
|
||||||
enable: Gaitu
|
enable: Gaitu
|
||||||
enable_hint: Behin gaituta, zure zerbitzaria errele honetako toot publiko guztietara harpidetuko da, eta zerbitzari honetako toot publikoak errelera bidaltzen hasiko da.
|
enable_hint: Behin gaituta, zure zerbitzaria errele honetako gab publiko guztietara harpidetuko da, eta zerbitzari honetako gab publikoak errelera bidaltzen hasiko da.
|
||||||
enabled: Gaituta
|
enabled: Gaituta
|
||||||
inbox_url: Errelearen URLa
|
inbox_url: Errelearen URLa
|
||||||
pending: Erreleak onartzearen zain
|
pending: Erreleak onartzearen zain
|
||||||
|
@ -397,7 +397,7 @@ eu:
|
||||||
disabled: Inor ez
|
disabled: Inor ez
|
||||||
title: Baimendu hauen gobidapenak
|
title: Baimendu hauen gobidapenak
|
||||||
show_known_fediverse_at_about_page:
|
show_known_fediverse_at_about_page:
|
||||||
desc_html: Txandakatzean, fedibertsu ezagun osoko toot-ak bistaratuko ditu aurrebistan. Bestela, toot lokalak besterik ez ditu erakutsiko.
|
desc_html: Txandakatzean, fedibertsu ezagun osoko gab-ak bistaratuko ditu aurrebistan. Bestela, gab lokalak besterik ez ditu erakutsiko.
|
||||||
title: Erakutsi fedibertsu ezagun osoko denbora-lerroa aurrebistan
|
title: Erakutsi fedibertsu ezagun osoko denbora-lerroa aurrebistan
|
||||||
show_staff_badge:
|
show_staff_badge:
|
||||||
desc_html: Erakutsi langile banda erabiltzailearen orrian
|
desc_html: Erakutsi langile banda erabiltzailearen orrian
|
||||||
|
@ -557,7 +557,7 @@ eu:
|
||||||
archive_takeout:
|
archive_takeout:
|
||||||
date: Data
|
date: Data
|
||||||
download: Deskargatu zure artxiboa
|
download: Deskargatu zure artxiboa
|
||||||
hint_html: Zure <strong>toot eta igotako multimedia</strong>ren artxibo bat eskatu dezakezu. Esportatutako datuak ActivityPub formatua izango dute, bateragarria den edozein programarekin irakurtzeko. Artxiboa 7 egunetan behin eska dezakezu.
|
hint_html: Zure <strong>gab eta igotako multimedia</strong>ren artxibo bat eskatu dezakezu. Esportatutako datuak ActivityPub formatua izango dute, bateragarria den edozein programarekin irakurtzeko. Artxiboa 7 egunetan behin eska dezakezu.
|
||||||
in_progress: Zure artxiboa biltzen...
|
in_progress: Zure artxiboa biltzen...
|
||||||
request: Eskatu zure artxiboa
|
request: Eskatu zure artxiboa
|
||||||
size: Tamaina
|
size: Tamaina
|
||||||
|
@ -712,20 +712,20 @@ eu:
|
||||||
remote_interaction:
|
remote_interaction:
|
||||||
favourite:
|
favourite:
|
||||||
proceed: Bihurtu gogoko
|
proceed: Bihurtu gogoko
|
||||||
prompt: 'Toot hau gogoko bihurtu nahi duzu:'
|
prompt: 'Gab hau gogoko bihurtu nahi duzu:'
|
||||||
reblog:
|
reblog:
|
||||||
proceed: Eman bultzada
|
proceed: Eman bultzada
|
||||||
prompt: 'Toot honi bultzada eman nahi diozu:'
|
prompt: 'Gab honi bultzada eman nahi diozu:'
|
||||||
reply:
|
reply:
|
||||||
proceed: Ekin erantzuteari
|
proceed: Ekin erantzuteari
|
||||||
prompt: 'Toot honi erantzun nahi diozu:'
|
prompt: 'Gab honi erantzun nahi diozu:'
|
||||||
remote_unfollow:
|
remote_unfollow:
|
||||||
error: Errorea
|
error: Errorea
|
||||||
title: Izenburua
|
title: Izenburua
|
||||||
unfollowed: Jarraitzeari utzita
|
unfollowed: Jarraitzeari utzita
|
||||||
scheduled_statuses:
|
scheduled_statuses:
|
||||||
over_daily_limit: Egun horretarako programatutako toot kopuruaren muga gainditu duzu (%{limit})
|
over_daily_limit: Egun horretarako programatutako gab kopuruaren muga gainditu duzu (%{limit})
|
||||||
over_total_limit: Programatutako toot kopuruaren muga gainditu duzu (%{limit})
|
over_total_limit: Programatutako gab kopuruaren muga gainditu duzu (%{limit})
|
||||||
too_soon: Programatutako data etorkizunean egon behar du
|
too_soon: Programatutako data etorkizunean egon behar du
|
||||||
sessions:
|
sessions:
|
||||||
activity: Azken jarduera
|
activity: Azken jarduera
|
||||||
|
@ -798,9 +798,9 @@ eu:
|
||||||
open_in_web: Ireki web-ean
|
open_in_web: Ireki web-ean
|
||||||
over_character_limit: "%{max}eko karaktere muga gaindituta"
|
over_character_limit: "%{max}eko karaktere muga gaindituta"
|
||||||
pin_errors:
|
pin_errors:
|
||||||
limit: Gehienez finkatu daitekeen toot kopurua finkatu duzu jada
|
limit: Gehienez finkatu daitekeen gab kopurua finkatu duzu jada
|
||||||
ownership: Ezin duzu beste norbaiten toot bat finkatu
|
ownership: Ezin duzu beste norbaiten gab bat finkatu
|
||||||
private: Ezin dira publikoak ez diren toot-ak finkatu
|
private: Ezin dira publikoak ez diren gab-ak finkatu
|
||||||
reblog: Bultzada bat ezin da finkatu
|
reblog: Bultzada bat ezin da finkatu
|
||||||
show_more: Erakutsi gehiago
|
show_more: Erakutsi gehiago
|
||||||
sign_in_to_participate: Eman izena elkarrizketan parte hartzeko
|
sign_in_to_participate: Eman izena elkarrizketan parte hartzeko
|
||||||
|
@ -813,7 +813,7 @@ eu:
|
||||||
unlisted: Zerrendatu gabea
|
unlisted: Zerrendatu gabea
|
||||||
unlisted_long: Edonork ikusi dezake, baina ez da denbora-lerro publikoetan agertzen
|
unlisted_long: Edonork ikusi dezake, baina ez da denbora-lerro publikoetan agertzen
|
||||||
stream_entries:
|
stream_entries:
|
||||||
pinned: Finkatutako toot-a
|
pinned: Finkatutako gab-a
|
||||||
reblogged: "(r)en bultzada"
|
reblogged: "(r)en bultzada"
|
||||||
sensitive_content: 'Kontuz: Eduki hunkigarria'
|
sensitive_content: 'Kontuz: Eduki hunkigarria'
|
||||||
terms:
|
terms:
|
||||||
|
@ -931,8 +931,8 @@ eu:
|
||||||
warning:
|
warning:
|
||||||
explanation:
|
explanation:
|
||||||
disable: Zure kontua izoztuta dagoen bitartean, zure kontua bere horretan dirau, baina ezin duzu ekintzarik burutu desblokeatzen den arte.
|
disable: Zure kontua izoztuta dagoen bitartean, zure kontua bere horretan dirau, baina ezin duzu ekintzarik burutu desblokeatzen den arte.
|
||||||
silence: Zure kontua murriztua dagoen bitartean, jada zu jarraitzen zaituztenak besterik ez dituzte zure Toot-ak ikusiko zerbitzari honetan, eta agian zerrenda publikoetatik kenduko zaizu. Hala ere besteek oraindik zu jarraitu zaitzakete.
|
silence: Zure kontua murriztua dagoen bitartean, jada zu jarraitzen zaituztenak besterik ez dituzte zure Gab-ak ikusiko zerbitzari honetan, eta agian zerrenda publikoetatik kenduko zaizu. Hala ere besteek oraindik zu jarraitu zaitzakete.
|
||||||
suspend: Zure kontua kanporatua izan da, zure toot guztiak eta multimedia fitxategiak behin betiko ezabatu dira zerbitzari honetatik, eta zure jarraitzaileen zerbitzarietatik.
|
suspend: Zure kontua kanporatua izan da, zure gab guztiak eta multimedia fitxategiak behin betiko ezabatu dira zerbitzari honetatik, eta zure jarraitzaileen zerbitzarietatik.
|
||||||
review_server_policies: Berrikusi zerbitzariko politikak
|
review_server_policies: Berrikusi zerbitzariko politikak
|
||||||
subject:
|
subject:
|
||||||
disable: Zure %{acct} kontua izoztu da
|
disable: Zure %{acct} kontua izoztu da
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue