Commiting
This commit is contained in:
parent
fb612f60c8
commit
b4e370d3d3
|
@ -1,8 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::BaseController < ApplicationController
|
||||
DEFAULT_STATUSES_LIMIT = 18
|
||||
DEFAULT_ACCOUNTS_LIMIT = 40
|
||||
DEFAULT_STATUSES_LIMIT = 20
|
||||
DEFAULT_ACCOUNTS_LIMIT = 20
|
||||
|
||||
include RateLimitHeaders
|
||||
|
||||
|
@ -82,8 +82,8 @@ class Api::BaseController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def render_empty
|
||||
render json: {}, status: 200
|
||||
def render_empty_success(message = nil)
|
||||
render json: { success: true, error: false, message: message }, status: 200
|
||||
end
|
||||
|
||||
def authorize_if_got_token!(*scopes)
|
||||
|
|
|
@ -27,7 +27,7 @@ class Api::V1::FiltersController < Api::BaseController
|
|||
|
||||
def destroy
|
||||
@filter.destroy!
|
||||
render_empty
|
||||
render_empty_success
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -14,12 +14,12 @@ class Api::V1::FollowRequestsController < Api::BaseController
|
|||
def authorize
|
||||
AuthorizeFollowService.new.call(account, current_account)
|
||||
NotifyService.new.call(current_account, Follow.find_by(account: account, target_account: current_account))
|
||||
render_empty
|
||||
render_empty_success
|
||||
end
|
||||
|
||||
def reject
|
||||
RejectFollowService.new.call(account, current_account)
|
||||
render_empty
|
||||
render_empty_success
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -19,21 +19,18 @@ class Api::V1::Groups::AccountsController < Api::BaseController
|
|||
def create
|
||||
authorize @group, :join?
|
||||
|
||||
if !@group.password.nil?
|
||||
if @group.has_password?
|
||||
# use the groups/password_controller to join group with password
|
||||
render json: { error: true, message: 'Unable to join group. Incorrect password.' }, status: 422
|
||||
end
|
||||
|
||||
if @group.is_private
|
||||
@group.join_requests << current_account
|
||||
else
|
||||
@group.accounts << current_account
|
||||
|
||||
if current_user.allows_group_in_home_feed?
|
||||
current_user.force_regeneration!
|
||||
if @group.is_private
|
||||
@group.join_requests << current_account
|
||||
else
|
||||
@group.accounts << current_account
|
||||
end
|
||||
end
|
||||
|
||||
render json: @group, serializer: REST::GroupRelationshipSerializer, relationships: relationships
|
||||
render json: @group, serializer: REST::GroupRelationshipSerializer, relationships: relationships
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
|
@ -41,7 +38,7 @@ class Api::V1::Groups::AccountsController < Api::BaseController
|
|||
|
||||
@account = @group.accounts.find(params[:account_id])
|
||||
GroupAccount.where(group: @group, account: @account).update(group_account_params)
|
||||
render_empty
|
||||
render_empty_success
|
||||
end
|
||||
|
||||
def destroy
|
||||
|
@ -51,9 +48,6 @@ class Api::V1::Groups::AccountsController < Api::BaseController
|
|||
else
|
||||
authorize @group, :leave?
|
||||
GroupAccount.where(group: @group, account_id: current_account.id).destroy_all
|
||||
if current_user.allows_group_in_home_feed?
|
||||
current_user.force_regeneration!
|
||||
end
|
||||
end
|
||||
|
||||
render json: @group, serializer: REST::GroupRelationshipSerializer, relationships: relationships
|
||||
|
|
|
@ -10,25 +10,29 @@ class Api::V1::Groups::PinsController < Api::BaseController
|
|||
|
||||
def create
|
||||
authorize @group, :update?
|
||||
|
||||
GroupPinnedStatus.create!(group: @group, status: @status)
|
||||
render json: @status, serializer: REST::StatusSerializer
|
||||
|
||||
pin = GroupPinnedStatus.find_by(group: @group, status: @status)
|
||||
if pin.nil?
|
||||
GroupPinnedStatus.create!(group: @group, status: @status)
|
||||
render json: @status, serializer: REST::StatusGroupPinnedSerializer, group_id: @group.id
|
||||
else
|
||||
return render json: { error: 'Status is already pinned to group' }, status: 500
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
# is status pinned by user of group?
|
||||
render json: @status, serializer: REST::StatusGroupPinnedSerializer, group_id: @group.id
|
||||
end
|
||||
|
||||
def destroy
|
||||
authorize @group, :update?
|
||||
|
||||
pin = GroupPinnedStatus.find_by(group: @group, status: @status)
|
||||
|
||||
if pin
|
||||
pin.destroy!
|
||||
end
|
||||
|
||||
render json: @status, serializer: REST::StatusSerializer
|
||||
render json: @status, serializer: REST::StatusGroupPinnedSerializer, group_id: @group.id
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -23,7 +23,7 @@ class Api::V1::Groups::RemovedAccountsController < Api::BaseController
|
|||
@account = @group.accounts.find(params[:account_id])
|
||||
@group.removed_accounts << @account
|
||||
GroupAccount.where(group: @group, account: @account).destroy_all
|
||||
render_empty
|
||||
render_empty_success
|
||||
end
|
||||
|
||||
def destroy
|
||||
|
@ -31,7 +31,7 @@ class Api::V1::Groups::RemovedAccountsController < Api::BaseController
|
|||
|
||||
@account = @group.removed_accounts.find(params[:account_id])
|
||||
GroupRemovedAccount.where(group: @group, account: @account).destroy_all
|
||||
render_empty
|
||||
render_empty_success
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -16,12 +16,12 @@ class Api::V1::GroupsController < Api::BaseController
|
|||
@groups = Group.where(id: @groupIds).limit(150).all
|
||||
when 'new'
|
||||
if !current_user
|
||||
render json: { error: 'This method requires an authenticated user' }, status: 422
|
||||
return render json: { error: 'This method requires an authenticated user' }, status: 422
|
||||
end
|
||||
@groups = Group.where(is_archived: false).limit(24).order('created_at DESC').all
|
||||
when 'member'
|
||||
if !current_user
|
||||
render json: { error: 'This method requires an authenticated user' }, status: 422
|
||||
return render json: { error: 'This method requires an authenticated user' }, status: 422
|
||||
end
|
||||
@groups = Group.joins(:group_accounts).where(is_archived: false, group_accounts: { account: current_account }).order('group_accounts.id DESC').all
|
||||
when 'admin'
|
||||
|
@ -36,7 +36,7 @@ class Api::V1::GroupsController < Api::BaseController
|
|||
|
||||
def by_category
|
||||
if !current_user
|
||||
render json: { error: 'This method requires an authenticated user' }, status: 422
|
||||
return render json: { error: 'This method requires an authenticated user' }, status: 422
|
||||
end
|
||||
|
||||
@groupCategory = nil
|
||||
|
@ -54,7 +54,7 @@ class Api::V1::GroupsController < Api::BaseController
|
|||
|
||||
def by_tag
|
||||
if !current_user
|
||||
render json: { error: 'This method requires an authenticated user' }, status: 422
|
||||
return render json: { error: 'This method requires an authenticated user' }, status: 422
|
||||
end
|
||||
|
||||
@groups = []
|
||||
|
@ -94,7 +94,7 @@ class Api::V1::GroupsController < Api::BaseController
|
|||
|
||||
@group.is_archived = true
|
||||
@group.save!
|
||||
render_empty
|
||||
render_empty_success
|
||||
end
|
||||
|
||||
def destroy_status
|
||||
|
@ -102,7 +102,7 @@ class Api::V1::GroupsController < Api::BaseController
|
|||
|
||||
status = Status.find(params[:status_id])
|
||||
GroupUnlinkStatusService.new.call(current_account, @group, status)
|
||||
render_empty
|
||||
render_empty_success
|
||||
end
|
||||
|
||||
def approve_status
|
||||
|
@ -110,7 +110,7 @@ class Api::V1::GroupsController < Api::BaseController
|
|||
|
||||
status = Status.find(params[:status_id])
|
||||
GroupApproveStatusService.new.call(current_account, @group, status)
|
||||
render_empty
|
||||
render_empty_success
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -21,12 +21,12 @@ class Api::V1::Lists::AccountsController < Api::BaseController
|
|||
end
|
||||
end
|
||||
|
||||
render_empty
|
||||
render_empty_success
|
||||
end
|
||||
|
||||
def destroy
|
||||
ListAccount.where(list: @list, account_id: account_ids).destroy_all
|
||||
render_empty
|
||||
render_empty_success
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -28,7 +28,7 @@ class Api::V1::ListsController < Api::BaseController
|
|||
|
||||
def destroy
|
||||
@list.destroy!
|
||||
render_empty
|
||||
render_empty_success
|
||||
end
|
||||
|
||||
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
|
||||
current_account.notifications.delete_all
|
||||
render_empty
|
||||
render_empty_success
|
||||
end
|
||||
|
||||
def mark_read
|
||||
current_account.notifications.find(params[:id]).mark_read!
|
||||
render_empty
|
||||
render_empty_success
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -26,7 +26,7 @@ class Api::V1::ScheduledStatusesController < Api::BaseController
|
|||
|
||||
def destroy
|
||||
@status.destroy!
|
||||
render_empty
|
||||
render_empty_success
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -9,14 +9,15 @@ class Api::V1::Statuses::BookmarksController < Api::BaseController
|
|||
def create
|
||||
if current_user.account.is_pro
|
||||
@status = bookmarked_status
|
||||
render json: @status, serializer: REST::StatusSerializer
|
||||
render json: @status, serializer: REST::StatusBookmarkedSerializer
|
||||
else
|
||||
render json: { error: 'You need to be a GabPRO member to access this' }, status: 422
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
# is status bookmarked by user?
|
||||
@status = requested_status
|
||||
render json: @status, serializer: REST::StatusBookmarkedSerializer
|
||||
end
|
||||
|
||||
def destroy
|
||||
|
@ -27,7 +28,7 @@ class Api::V1::Statuses::BookmarksController < Api::BaseController
|
|||
bookmark = StatusBookmark.find_by!(account: current_user.account, status: @status)
|
||||
bookmark.destroy!
|
||||
|
||||
render json: @status, serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new([@status], current_user&.account_id, bookmarks_map: @bookmarks_map)
|
||||
render json: @status, serializer: REST::StatusBookmarkedSerializer
|
||||
else
|
||||
render json: { error: 'You need to be a GabPRO member to access this' }, status: 422
|
||||
end
|
||||
|
|
|
@ -8,7 +8,6 @@ class Api::V1::Statuses::FavouritesController < Api::BaseController
|
|||
|
||||
def create
|
||||
@status = favourited_status
|
||||
puts "tilly -- status: " + @status.inspect
|
||||
render json: @status, serializer: REST::StatusStatSerializer
|
||||
end
|
||||
|
||||
|
@ -18,7 +17,10 @@ class Api::V1::Statuses::FavouritesController < Api::BaseController
|
|||
|
||||
UnfavouriteWorker.perform_async(current_user.account_id, @status.id)
|
||||
|
||||
render json: @status, serializer: REST::StatusStatSerializer, unfavourite: true, relationships: StatusRelationshipsPresenter.new([@status], current_user&.account_id, favourites_map: @favourites_map)
|
||||
render json: @status,
|
||||
serializer: REST::StatusStatSerializer,
|
||||
unfavourite: true,
|
||||
relationships: StatusRelationshipsPresenter.new([@status], current_user&.account_id, favourites_map: @favourites_map)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -8,12 +8,17 @@ class Api::V1::Statuses::PinsController < Api::BaseController
|
|||
before_action :set_status
|
||||
|
||||
def create
|
||||
StatusPin.create!(account: current_account, status: @status)
|
||||
render json: @status, serializer: REST::StatusSerializer
|
||||
pin = StatusPin.find_by(account: current_account, status: @status)
|
||||
if pin.nil?
|
||||
StatusPin.create!(account: current_account, status: @status)
|
||||
render json: @status, serializer: REST::StatusPinnedSerializer
|
||||
else
|
||||
return render json: { error: 'Status is already pinned' }, status: 500
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
# is status pinned by user?
|
||||
render json: @status, serializer: REST::StatusPinnedSerializer
|
||||
end
|
||||
|
||||
def destroy
|
||||
|
@ -23,7 +28,7 @@ class Api::V1::Statuses::PinsController < Api::BaseController
|
|||
pin.destroy!
|
||||
end
|
||||
|
||||
render json: @status, serializer: REST::StatusSerializer
|
||||
render json: @status, serializer: REST::StatusPinnedSerializer
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::Statuses::RepostedByAccountsController < Api::BaseController
|
||||
class Api::V1::Statuses::RebloggedByAccountsController < Api::BaseController
|
||||
include Authorization
|
||||
|
||||
before_action -> { authorize_if_got_token! :read, :'read:accounts' }
|
||||
|
@ -36,13 +36,13 @@ class Api::V1::Statuses::RepostedByAccountsController < Api::BaseController
|
|||
|
||||
def next_path
|
||||
if records_continue?
|
||||
api_v1_status_reposted_by_index_url pagination_params(max_id: pagination_max_id)
|
||||
api_v1_status_reblogged_by_index_url pagination_params(max_id: pagination_max_id)
|
||||
end
|
||||
end
|
||||
|
||||
def prev_path
|
||||
unless @accounts.empty?
|
||||
api_v1_status_reposted_by_index_url pagination_params(since_id: pagination_since_id)
|
||||
api_v1_status_reblogged_by_index_url pagination_params(since_id: pagination_since_id)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -7,22 +7,25 @@ class Api::V1::Statuses::ReblogsController < Api::BaseController
|
|||
before_action :require_user!
|
||||
|
||||
def create
|
||||
if !current_user.account.local? || !status_for_reblog.local
|
||||
return render json: { error: 'Invalid action' }, status: 422
|
||||
end
|
||||
|
||||
@status = ReblogService.new.call(current_user.account, status_for_reblog, reblog_params)
|
||||
render json: @status, serializer: REST::StatusSerializer
|
||||
@relog = status_for_reblog
|
||||
ReblogService.new.call(current_user.account, @relog, reblog_params)
|
||||
render json: @relog, serializer: REST::StatusStatSerializer
|
||||
end
|
||||
|
||||
def destroy
|
||||
@status = status_for_destroy.reblog
|
||||
@reblogs_map = { @status.id => false }
|
||||
@my_relog = status_for_destroy
|
||||
@original_status = @my_relog.reblog
|
||||
|
||||
authorize status_for_destroy, :unreblog?
|
||||
RemovalWorker.perform_async(status_for_destroy.id)
|
||||
authorize @my_relog, :unreblog?
|
||||
|
||||
render json: @status, serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new([@status], current_user&.account_id, reblogs_map: @reblogs_map)
|
||||
RemovalWorker.perform_async(@my_relog.id)
|
||||
|
||||
@reblogs_map = { @original_status.id => false }
|
||||
|
||||
render json: @original_status,
|
||||
serializer: REST::StatusStatSerializer,
|
||||
unreblog: true,
|
||||
relationships: StatusRelationshipsPresenter.new([@original_status], current_user&.account_id, reblogs_map: @reblogs_map)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -23,7 +23,7 @@ class Api::V1::SuggestionsController < Api::BaseController
|
|||
|
||||
def destroy
|
||||
PotentialFriendshipTracker.remove(current_account.id, params[:id])
|
||||
render_empty
|
||||
render_empty_success
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -7,7 +7,7 @@ class Api::Web::SettingsController < Api::Web::BaseController
|
|||
setting.data = params[:data]
|
||||
setting.save!
|
||||
|
||||
render_empty
|
||||
render_empty_success
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -66,6 +66,7 @@ module SignatureVerification
|
|||
|
||||
return account unless verify_signature(account, signature, compare_signed_string).nil?
|
||||
|
||||
# : todo :
|
||||
@signature_verification_failure_reason = "Verification failed for #{account.username}@#{account.domain} #{account.uri}"
|
||||
@signed_request_account = nil
|
||||
end
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -33,20 +33,17 @@ export const fetchBookmarkedStatuses = () => (dispatch, getState) => {
|
|||
|
||||
const fetchBookmarkedStatusesRequest = () => ({
|
||||
type: BOOKMARKED_STATUSES_FETCH_REQUEST,
|
||||
skipLoading: true,
|
||||
})
|
||||
|
||||
const fetchBookmarkedStatusesSuccess = (statuses, next) => ({
|
||||
type: BOOKMARKED_STATUSES_FETCH_SUCCESS,
|
||||
statuses,
|
||||
next,
|
||||
skipLoading: true,
|
||||
})
|
||||
|
||||
const fetchBookmarkedStatusesFail = (error) => ({
|
||||
type: BOOKMARKED_STATUSES_FETCH_FAIL,
|
||||
error,
|
||||
skipLoading: true,
|
||||
})
|
||||
|
||||
/**
|
||||
|
|
|
@ -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,
|
||||
})
|
File diff suppressed because it is too large
Load Diff
|
@ -16,17 +16,14 @@ export const fetchCustomEmojis = () => (dispatch, getState) => {
|
|||
|
||||
const fetchCustomEmojisRequest = () => ({
|
||||
type: CUSTOM_EMOJIS_FETCH_REQUEST,
|
||||
skipLoading: true,
|
||||
})
|
||||
|
||||
const fetchCustomEmojisSuccess = (custom_emojis) => ({
|
||||
type: CUSTOM_EMOJIS_FETCH_SUCCESS,
|
||||
custom_emojis,
|
||||
skipLoading: true,
|
||||
})
|
||||
|
||||
const fetchCustomEmojisFail = (error) => ({
|
||||
type: CUSTOM_EMOJIS_FETCH_FAIL,
|
||||
error,
|
||||
skipLoading: true,
|
||||
})
|
||||
|
|
|
@ -33,20 +33,17 @@ export const fetchFavoritedStatuses = () => (dispatch, getState) => {
|
|||
|
||||
const fetchFavoritedStatusesRequest = () => ({
|
||||
type: FAVORITED_STATUSES_FETCH_REQUEST,
|
||||
skipLoading: true,
|
||||
})
|
||||
|
||||
const fetchFavoritedStatusesSuccess = (statuses, next) => ({
|
||||
type: FAVORITED_STATUSES_FETCH_SUCCESS,
|
||||
statuses,
|
||||
next,
|
||||
skipLoading: true,
|
||||
})
|
||||
|
||||
const fetchFavoritedStatusesFail = (error) => ({
|
||||
type: FAVORITED_STATUSES_FETCH_FAIL,
|
||||
error,
|
||||
skipLoading: true,
|
||||
})
|
||||
|
||||
/**
|
||||
|
|
|
@ -23,18 +23,15 @@ export const fetchFilters = () => (dispatch, getState) => {
|
|||
|
||||
const fetchFiltersRequest = () => ({
|
||||
type: FILTERS_FETCH_REQUEST,
|
||||
skipLoading: true,
|
||||
})
|
||||
|
||||
const fetchFiltersSuccess = (filters) => ({
|
||||
type: FILTERS_FETCH_SUCCESS,
|
||||
filters,
|
||||
skipLoading: true,
|
||||
})
|
||||
|
||||
const fetchFiltersFail = (err) => ({
|
||||
type: FILTERS_FETCH_FAIL,
|
||||
err,
|
||||
skipLoading: true,
|
||||
skipAlert: true,
|
||||
})
|
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 ACCOUNT_FETCH_FAIL_FOR_USERNAME_LOOKUP = 'ACCOUNT_FETCH_FAIL_FOR_USERNAME_LOOKUP'
|
||||
|
||||
function pushUnique(array, object) {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
const pushUnique = (array, object) => {
|
||||
if (array.every(element => element.id !== object.id)) {
|
||||
array.push(object);
|
||||
}
|
||||
|
|
|
@ -5,20 +5,26 @@ import { expandSpoilers } from '../../initial_state'
|
|||
|
||||
const domParser = new DOMParser()
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
const makeEmojiMap = record => record.emojis.reduce((obj, emoji) => {
|
||||
obj[`:${emoji.shortcode}:`] = emoji;
|
||||
return obj;
|
||||
}, {});
|
||||
obj[`:${emoji.shortcode}:`] = emoji
|
||||
return obj
|
||||
}, {})
|
||||
|
||||
export function normalizeAccount(account) {
|
||||
account = { ...account };
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const normalizeAccount = (account) => {
|
||||
account = { ...account }
|
||||
|
||||
const emojiMap = makeEmojiMap(account);
|
||||
const displayName = account.display_name.trim().length === 0 ? account.username : account.display_name;
|
||||
const emojiMap = makeEmojiMap(account)
|
||||
const displayName = account.display_name.trim().length === 0 ? account.username : account.display_name
|
||||
|
||||
account.display_name_html = emojify(escapeTextContentForBrowser(displayName), emojiMap);
|
||||
account.display_name_plain = emojify(escapeTextContentForBrowser(displayName), emojiMap, true);
|
||||
account.note_emojified = emojify(account.note, emojiMap);
|
||||
account.display_name_html = emojify(escapeTextContentForBrowser(displayName), emojiMap)
|
||||
account.display_name_plain = emojify(escapeTextContentForBrowser(displayName), emojiMap, true)
|
||||
account.note_emojified = emojify(account.note, emojiMap)
|
||||
account.note_plain = unescapeHTML(account.note)
|
||||
|
||||
if (account.fields) {
|
||||
|
@ -27,67 +33,73 @@ export function normalizeAccount(account) {
|
|||
name_emojified: emojify(escapeTextContentForBrowser(pair.name)),
|
||||
value_emojified: emojify(pair.value, emojiMap),
|
||||
value_plain: unescapeHTML(pair.value),
|
||||
}));
|
||||
}))
|
||||
}
|
||||
|
||||
if (account.moved) {
|
||||
account.moved = account.moved.id;
|
||||
account.moved = account.moved.id
|
||||
}
|
||||
|
||||
return account;
|
||||
return account
|
||||
}
|
||||
|
||||
export function normalizeStatus(status, normalOldStatus) {
|
||||
const normalStatus = { ...status };
|
||||
normalStatus.account = status.account_id || status.account.id;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const normalizeStatus = (status, normalOldStatus) => {
|
||||
const normalStatus = { ...status }
|
||||
normalStatus.account = status.account_id || status.account.id
|
||||
|
||||
if (status.reblog && status.reblog.id) {
|
||||
normalStatus.reblog = status.reblog.id;
|
||||
normalStatus.reblog = status.reblog.id
|
||||
}
|
||||
|
||||
if (status.quote && status.quote.id) {
|
||||
normalStatus.quote = status.quote.id;
|
||||
normalStatus.quote = status.quote.id
|
||||
}
|
||||
|
||||
if (status.poll && status.poll.id) {
|
||||
normalStatus.poll = status.poll.id;
|
||||
normalStatus.poll = status.poll.id
|
||||
}
|
||||
|
||||
if (!!status.group || !!status.group_id) {
|
||||
normalStatus.group = status.group_id || status.group.id;
|
||||
normalStatus.group = status.group_id || status.group.id
|
||||
}
|
||||
|
||||
// Only calculate these values when status first encountered
|
||||
// Otherwise keep the ones already in the reducer
|
||||
if (normalOldStatus && normalOldStatus.get('content') === normalStatus.content && normalOldStatus.get('spoiler_text') === normalStatus.spoiler_text) {
|
||||
normalStatus.search_index = normalOldStatus.get('search_index');
|
||||
normalStatus.contentHtml = normalOldStatus.get('contentHtml');
|
||||
normalStatus.spoilerHtml = normalOldStatus.get('spoilerHtml');
|
||||
normalStatus.hidden = normalOldStatus.get('hidden');
|
||||
normalStatus.search_index = normalOldStatus.get('search_index')
|
||||
normalStatus.contentHtml = normalOldStatus.get('contentHtml')
|
||||
normalStatus.spoilerHtml = normalOldStatus.get('spoilerHtml')
|
||||
normalStatus.hidden = normalOldStatus.get('hidden')
|
||||
} else {
|
||||
const spoilerText = normalStatus.spoiler_text || '';
|
||||
const searchContent = [spoilerText, status.content].join('\n\n').replace(/<br\s*\/?>/g, '\n').replace(/<\/p><p>/g, '\n\n');
|
||||
const emojiMap = makeEmojiMap(normalStatus);
|
||||
const theContent = !!normalStatus.rich_content ? normalStatus.rich_content : normalStatus.content;
|
||||
const spoilerText = normalStatus.spoiler_text || ''
|
||||
const searchContent = [spoilerText, status.content].join('\n\n').replace(/<br\s*\/?>/g, '\n').replace(/<\/p><p>/g, '\n\n')
|
||||
const emojiMap = makeEmojiMap(normalStatus)
|
||||
const theContent = !!normalStatus.rich_content ? normalStatus.rich_content : normalStatus.content
|
||||
|
||||
normalStatus.search_index = domParser.parseFromString(searchContent, 'text/html').documentElement.textContent;
|
||||
normalStatus.contentHtml = emojify(theContent, emojiMap, false, true);
|
||||
normalStatus.spoilerHtml = emojify(escapeTextContentForBrowser(spoilerText), emojiMap);
|
||||
normalStatus.hidden = expandSpoilers ? false : spoilerText.length > 0 || normalStatus.sensitive;
|
||||
normalStatus.search_index = domParser.parseFromString(searchContent, 'text/html').documentElement.textContent
|
||||
normalStatus.contentHtml = emojify(theContent, emojiMap, false, true)
|
||||
normalStatus.spoilerHtml = emojify(escapeTextContentForBrowser(spoilerText), emojiMap)
|
||||
normalStatus.hidden = expandSpoilers ? false : spoilerText.length > 0 || normalStatus.sensitive
|
||||
}
|
||||
|
||||
return normalStatus;
|
||||
return normalStatus
|
||||
}
|
||||
|
||||
export function normalizePoll(poll) {
|
||||
const normalPoll = { ...poll };
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const normalizePoll = (poll) => {
|
||||
const normalPoll = { ...poll }
|
||||
|
||||
const emojiMap = makeEmojiMap(normalPoll);
|
||||
const emojiMap = makeEmojiMap(normalPoll)
|
||||
|
||||
normalPoll.options = poll.options.map(option => ({
|
||||
normalPoll.options = poll.options.map((option) => ({
|
||||
...option,
|
||||
title_emojified: emojify(escapeTextContentForBrowser(option.title), emojiMap),
|
||||
}));
|
||||
}))
|
||||
|
||||
return normalPoll;
|
||||
return normalPoll
|
||||
}
|
|
@ -1,5 +1,9 @@
|
|||
import api from '../api'
|
||||
import { importFetchedAccounts, importFetchedStatus } from './importer'
|
||||
import api, { getLinks } from '../api'
|
||||
import {
|
||||
importFetchedAccounts,
|
||||
importFetchedStatus,
|
||||
} from './importer'
|
||||
import { fetchRelationships } from './accounts'
|
||||
import { updateStatusStats } from './statuses'
|
||||
import { me } from '../initial_state'
|
||||
|
||||
|
@ -23,6 +27,10 @@ export const REPOSTS_FETCH_REQUEST = 'REPOSTS_FETCH_REQUEST'
|
|||
export const REPOSTS_FETCH_SUCCESS = 'REPOSTS_FETCH_SUCCESS'
|
||||
export const REPOSTS_FETCH_FAIL = 'REPOSTS_FETCH_FAIL'
|
||||
|
||||
export const REPOSTS_EXPAND_REQUEST = 'REPOSTS_EXPAND_REQUEST'
|
||||
export const REPOSTS_EXPAND_SUCCESS = 'REPOSTS_EXPAND_SUCCESS'
|
||||
export const REPOSTS_EXPAND_FAIL = 'REPOSTS_EXPAND_FAIL'
|
||||
|
||||
export const PIN_REQUEST = 'PIN_REQUEST'
|
||||
export const PIN_SUCCESS = 'PIN_SUCCESS'
|
||||
export const PIN_FAIL = 'PIN_FAIL'
|
||||
|
@ -31,6 +39,10 @@ export const UNPIN_REQUEST = 'UNPIN_REQUEST'
|
|||
export const UNPIN_SUCCESS = 'UNPIN_SUCCESS'
|
||||
export const UNPIN_FAIL = 'UNPIN_FAIL'
|
||||
|
||||
export const IS_PIN_REQUEST = 'IS_PIN_REQUEST'
|
||||
export const IS_PIN_SUCCESS = 'IS_PIN_SUCCESS'
|
||||
export const IS_PIN_FAIL = 'IS_PIN_FAIL'
|
||||
|
||||
export const BOOKMARK_REQUEST = 'BOOKMARK_REQUEST'
|
||||
export const BOOKMARK_SUCCESS = 'BOOKMARK_SUCCESS'
|
||||
export const BOOKMARK_FAIL = 'BOOKMARK_FAIL'
|
||||
|
@ -39,342 +51,512 @@ export const UNBOOKMARK_REQUEST = 'UNBOOKMARK_REQUEST'
|
|||
export const UNBOOKMARK_SUCCESS = 'UNBOOKMARK_SUCCESS'
|
||||
export const UNBOOKMARK_FAIL = 'UNBOOKMARK_FAIL'
|
||||
|
||||
export const IS_BOOKMARK_REQUEST = 'IS_BOOKMARK_REQUEST'
|
||||
export const IS_BOOKMARK_SUCCESS = 'IS_BOOKMARK_SUCCESS'
|
||||
export const IS_BOOKMARK_FAIL = 'IS_BOOKMARK_FAIL'
|
||||
|
||||
export const LIKES_FETCH_REQUEST = 'LIKES_FETCH_REQUEST'
|
||||
export const LIKES_FETCH_SUCCESS = 'LIKES_FETCH_SUCCESS'
|
||||
export const LIKES_FETCH_FAIL = 'LIKES_FETCH_FAIL'
|
||||
|
||||
export const LIKES_EXPAND_REQUEST = 'LIKES_EXPAND_REQUEST'
|
||||
export const LIKES_EXPAND_SUCCESS = 'LIKES_EXPAND_SUCCESS'
|
||||
export const LIKES_EXPAND_FAIL = 'LIKES_EXPAND_FAIL'
|
||||
|
||||
/**
|
||||
*
|
||||
* @description Repost the given status. Set status to status.reblogged:true and
|
||||
* increment status.reblogs_count by 1 on success.
|
||||
* @param {ImmutableMap} status
|
||||
*/
|
||||
export const repost = (status) => (dispatch, getState) => {
|
||||
if (!me) return
|
||||
if (!me || !status) return
|
||||
|
||||
dispatch(repostRequest(status))
|
||||
|
||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/reblog`).then((response) => {
|
||||
// The reblog API method returns a new status wrapped around the original. In this case we are only
|
||||
// interested in how the original is modified, hence passing it skipping the wrapper
|
||||
dispatch(importFetchedStatus(response.data.reblog))
|
||||
dispatch(updateStatusStats(response.data))
|
||||
dispatch(repostSuccess(status))
|
||||
}).catch((error) => {
|
||||
dispatch(repostFail(status, error))
|
||||
})
|
||||
}
|
||||
|
||||
export const repostRequest = (status) => ({
|
||||
const repostRequest = (status) => ({
|
||||
type: REPOST_REQUEST,
|
||||
status: status,
|
||||
skipLoading: true,
|
||||
status,
|
||||
})
|
||||
|
||||
export const repostSuccess = (status) => ({
|
||||
const repostSuccess = (status) => ({
|
||||
type: REPOST_SUCCESS,
|
||||
status: status,
|
||||
skipLoading: true,
|
||||
status,
|
||||
})
|
||||
|
||||
export const repostFail = (status, error) => ({
|
||||
const repostFail = (status, error) => ({
|
||||
type: REPOST_FAIL,
|
||||
status: status,
|
||||
error: error,
|
||||
skipLoading: true,
|
||||
status,
|
||||
error,
|
||||
})
|
||||
|
||||
/**
|
||||
*
|
||||
* @description Unrepost the given status. Set status to status.reblogged:false and
|
||||
* decrement status.reblogs_count by 1 on success.
|
||||
* @param {ImmutableMap} status
|
||||
*/
|
||||
export const unrepost = (status) => (dispatch, getState) => {
|
||||
if (!me) return
|
||||
if (!me || !status) return
|
||||
|
||||
dispatch(unrepostRequest(status))
|
||||
|
||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/unreblog`).then((response) => {
|
||||
dispatch(importFetchedStatus(response.data))
|
||||
dispatch(updateStatusStats(response.data))
|
||||
dispatch(unrepostSuccess(status))
|
||||
}).catch((error) => {
|
||||
dispatch(unrepostFail(status, error))
|
||||
})
|
||||
}
|
||||
|
||||
export const unrepostRequest = (status) => ({
|
||||
const unrepostRequest = (status) => ({
|
||||
type: UNREPOST_REQUEST,
|
||||
status: status,
|
||||
skipLoading: true,
|
||||
status,
|
||||
})
|
||||
|
||||
export const unrepostSuccess = (status) => ({
|
||||
const unrepostSuccess = (status) => ({
|
||||
type: UNREPOST_SUCCESS,
|
||||
status: status,
|
||||
skipLoading: true,
|
||||
status,
|
||||
})
|
||||
|
||||
export const unrepostFail = (status, error) => ({
|
||||
const unrepostFail = (status, error) => ({
|
||||
type: UNREPOST_FAIL,
|
||||
status: status,
|
||||
error: error,
|
||||
skipLoading: true,
|
||||
status,
|
||||
error,
|
||||
})
|
||||
|
||||
/**
|
||||
*
|
||||
* @description Favorite the given status. Set status to status.favourited:true and
|
||||
* increment status.favourites_count by 1 on success.
|
||||
* @param {ImmutableMap} status
|
||||
*/
|
||||
export const favorite = (status) => (dispatch, getState) => {
|
||||
if (!me) return
|
||||
if (!me || !status) return
|
||||
|
||||
dispatch(favoriteRequest(status))
|
||||
|
||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/favourite`).then((response) => {
|
||||
dispatch(updateStatusStats(response.data))
|
||||
dispatch(favoriteSuccess(status))
|
||||
dispatch(favoriteSuccess(response.data))
|
||||
}).catch((error) => {
|
||||
dispatch(favoriteFail(status, error))
|
||||
})
|
||||
}
|
||||
|
||||
export const favoriteRequest = (status) => ({
|
||||
const favoriteRequest = (status) => ({
|
||||
type: FAVORITE_REQUEST,
|
||||
status: status,
|
||||
skipLoading: true,
|
||||
status,
|
||||
})
|
||||
|
||||
export const favoriteSuccess = (status) => ({
|
||||
const favoriteSuccess = (data) => ({
|
||||
type: FAVORITE_SUCCESS,
|
||||
status: status,
|
||||
skipLoading: true,
|
||||
data,
|
||||
})
|
||||
|
||||
export const favoriteFail = (status, error) => ({
|
||||
const favoriteFail = (status, error) => ({
|
||||
type: FAVORITE_FAIL,
|
||||
status: status,
|
||||
error: error,
|
||||
skipLoading: true,
|
||||
status,
|
||||
error,
|
||||
})
|
||||
|
||||
/**
|
||||
*
|
||||
* @description Unfavorite the given status. Set status to status.favourited:false and
|
||||
* decrement status.favourites_count by 1 on success.
|
||||
* @param {ImmutableMap} status
|
||||
*/
|
||||
export const unfavorite = (status) => (dispatch, getState) => {
|
||||
if (!me) return
|
||||
if (!me || !status) return
|
||||
|
||||
dispatch(unfavoriteRequest(status))
|
||||
|
||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/unfavourite`).then((response) => {
|
||||
dispatch(importFetchedStatus(response.data))
|
||||
dispatch(updateStatusStats(response.data))
|
||||
dispatch(unfavoriteSuccess(status))
|
||||
}).catch((error) => {
|
||||
dispatch(unfavoriteFail(status, error))
|
||||
})
|
||||
}
|
||||
|
||||
export const unfavoriteRequest = (status) => ({
|
||||
const unfavoriteRequest = (status) => ({
|
||||
type: UNFAVORITE_REQUEST,
|
||||
status: status,
|
||||
skipLoading: true,
|
||||
status,
|
||||
})
|
||||
|
||||
export const unfavoriteSuccess = (status) => ({
|
||||
const unfavoriteSuccess = (status) => ({
|
||||
type: UNFAVORITE_SUCCESS,
|
||||
status: status,
|
||||
skipLoading: true,
|
||||
status,
|
||||
})
|
||||
|
||||
export const unfavoriteFail = (status, error) => ({
|
||||
const unfavoriteFail = (status, error) => ({
|
||||
type: UNFAVORITE_FAIL,
|
||||
status: status,
|
||||
error: error,
|
||||
skipLoading: true,
|
||||
})
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const fetchReposts = (id) => (dispatch, getState) => {
|
||||
if (!me) return
|
||||
|
||||
dispatch(fetchRepostsRequest(id))
|
||||
|
||||
api(getState).get(`/api/v1/statuses/${id}/reblogged_by`).then((response) => {
|
||||
dispatch(importFetchedAccounts(response.data))
|
||||
dispatch(fetchRepostsSuccess(id, response.data))
|
||||
}).catch((error) => {
|
||||
dispatch(fetchRepostsFail(id, error))
|
||||
})
|
||||
}
|
||||
|
||||
export const fetchRepostsRequest = (id) => ({
|
||||
type: REPOSTS_FETCH_REQUEST,
|
||||
id,
|
||||
})
|
||||
|
||||
export const fetchRepostsSuccess = (id, accounts) => ({
|
||||
type: REPOSTS_FETCH_SUCCESS,
|
||||
id,
|
||||
accounts,
|
||||
})
|
||||
|
||||
export const fetchRepostsFail = (id, error) => ({
|
||||
type: REPOSTS_FETCH_FAIL,
|
||||
status,
|
||||
error,
|
||||
})
|
||||
|
||||
/**
|
||||
*
|
||||
* @description Pin the given status to your profile. Set status to status.pinned:true
|
||||
* on success.
|
||||
* @param {ImmutableMap} status
|
||||
*/
|
||||
export const pin = (status) => (dispatch, getState) => {
|
||||
if (!me) return
|
||||
if (!me || !status) return
|
||||
|
||||
dispatch(pinRequest(status))
|
||||
|
||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/pin`).then((response) => {
|
||||
dispatch(importFetchedStatus(response.data))
|
||||
dispatch(updateStatusStats(response.data))
|
||||
dispatch(pinSuccess(status))
|
||||
}).catch((error) => {
|
||||
dispatch(pinFail(status, error))
|
||||
})
|
||||
}
|
||||
|
||||
export const pinRequest = (status) => ({
|
||||
const pinRequest = (status) => ({
|
||||
type: PIN_REQUEST,
|
||||
status,
|
||||
skipLoading: true,
|
||||
})
|
||||
|
||||
export const pinSuccess = (status) => ({
|
||||
const pinSuccess = (status) => ({
|
||||
type: PIN_SUCCESS,
|
||||
status,
|
||||
skipLoading: true,
|
||||
})
|
||||
|
||||
export const pinFail = (status, error) => ({
|
||||
const pinFail = (status, error) => ({
|
||||
type: PIN_FAIL,
|
||||
status,
|
||||
error,
|
||||
skipLoading: true,
|
||||
})
|
||||
|
||||
/**
|
||||
*
|
||||
* @description Unpin the given status from your profile. Set status to status.pinned:false
|
||||
* on success and remove from account pins in timeline reducer.
|
||||
* @param {ImmutableMap} status
|
||||
*/
|
||||
export const unpin = (status) => (dispatch, getState) => {
|
||||
if (!me) return
|
||||
if (!me || !status) return
|
||||
|
||||
dispatch(unpinRequest(status))
|
||||
|
||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/unpin`).then((response) => {
|
||||
dispatch(importFetchedStatus(response.data))
|
||||
dispatch(unpinSuccess(status))
|
||||
dispatch(updateStatusStats(response.data))
|
||||
dispatch(unpinSuccess(status, response.data.account_id))
|
||||
}).catch((error) => {
|
||||
dispatch(unpinFail(status, error))
|
||||
})
|
||||
}
|
||||
|
||||
export const unpinRequest = (status) => ({
|
||||
const unpinRequest = (status) => ({
|
||||
type: UNPIN_REQUEST,
|
||||
status,
|
||||
skipLoading: true,
|
||||
})
|
||||
|
||||
export const unpinSuccess = (status) => ({
|
||||
const unpinSuccess = (status, accountId) => ({
|
||||
type: UNPIN_SUCCESS,
|
||||
accountId,
|
||||
status,
|
||||
skipLoading: true,
|
||||
})
|
||||
|
||||
export const unpinFail = (status, error) => ({
|
||||
const unpinFail = (status, error) => ({
|
||||
type: UNPIN_FAIL,
|
||||
status,
|
||||
error,
|
||||
skipLoading: true,
|
||||
})
|
||||
|
||||
/**
|
||||
*
|
||||
* @description Check if a status is pinned to the current user account.
|
||||
* @param {String} statusId
|
||||
*/
|
||||
export const fetchLikes = (id) => (dispatch, getState) => {
|
||||
dispatch(fetchLikesRequest(id))
|
||||
export const isPin = (statusId) => (dispatch, getState) => {
|
||||
if (!me || !statusId) return
|
||||
|
||||
api(getState).get(`/api/v1/statuses/${id}/favourited_by`).then((response) => {
|
||||
dispatch(importFetchedAccounts(response.data))
|
||||
dispatch(fetchLikesSuccess(id, response.data))
|
||||
dispatch(isPinRequest(statusId))
|
||||
|
||||
api(getState).get(`/api/v1/statuses/${statusId}/pin`).then((response) => {
|
||||
dispatch(updateStatusStats(response.data))
|
||||
dispatch(isPinSuccess(statusId))
|
||||
}).catch((error) => {
|
||||
dispatch(fetchLikesFail(id, error))
|
||||
dispatch(isPinFail(statusId, error))
|
||||
})
|
||||
}
|
||||
|
||||
export const fetchLikesRequest = (id) => ({
|
||||
type: LIKES_FETCH_REQUEST,
|
||||
id,
|
||||
const isPinRequest = (statusId) => ({
|
||||
type: IS_PIN_REQUEST,
|
||||
statusId,
|
||||
})
|
||||
|
||||
export const fetchLikesSuccess = (id, accounts) => ({
|
||||
type: LIKES_FETCH_SUCCESS,
|
||||
id,
|
||||
accounts,
|
||||
const isPinSuccess = (statusId) => ({
|
||||
type: IS_PIN_SUCCESS,
|
||||
statusId,
|
||||
})
|
||||
|
||||
export const fetchLikesFail = (id, error) => ({
|
||||
type: LIKES_FETCH_FAIL,
|
||||
const isPinFail = (statusId, error) => ({
|
||||
type: IS_PIN_FAIL,
|
||||
statusId,
|
||||
error,
|
||||
})
|
||||
|
||||
/**
|
||||
*
|
||||
* @description Bookmark the given status in your profile if PRO. Set status to
|
||||
* status.bookmarked:true on success.
|
||||
* @param {ImmutableMap} status
|
||||
*/
|
||||
export const bookmark = (status) => (dispatch, getState) => {
|
||||
if (!me || !status) return
|
||||
|
||||
dispatch(bookmarkRequest(status))
|
||||
|
||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/bookmark`).then((response) => {
|
||||
dispatch(importFetchedStatus(response.data))
|
||||
dispatch(bookmarkSuccess(status, response.data))
|
||||
dispatch(updateStatusStats(response.data))
|
||||
dispatch(bookmarkSuccess(status))
|
||||
}).catch((error) => {
|
||||
dispatch(bookmarkFail(status, error))
|
||||
})
|
||||
}
|
||||
|
||||
export const bookmarkRequest = (status) => ({
|
||||
const bookmarkRequest = (status) => ({
|
||||
type: BOOKMARK_REQUEST,
|
||||
status: status,
|
||||
status,
|
||||
})
|
||||
|
||||
export const bookmarkSuccess = (status, response) => ({
|
||||
const bookmarkSuccess = (status) => ({
|
||||
type: BOOKMARK_SUCCESS,
|
||||
status: status,
|
||||
response: response,
|
||||
status,
|
||||
})
|
||||
|
||||
export const bookmarkFail = (status, error) => ({
|
||||
const bookmarkFail = (status, error) => ({
|
||||
type: BOOKMARK_FAIL,
|
||||
status: status,
|
||||
error: error,
|
||||
status,
|
||||
error,
|
||||
})
|
||||
|
||||
/**
|
||||
*
|
||||
* @description Unbookmark the given status in your profile if PRO. Set status to
|
||||
* status.bookmarked:false on success.
|
||||
* @param {ImmutableMap} status
|
||||
*/
|
||||
export const unbookmark = (status) => (dispatch, getState) => {
|
||||
if (!me || !status) return
|
||||
|
||||
dispatch(unbookmarkRequest(status))
|
||||
|
||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/unbookmark`).then((response) => {
|
||||
dispatch(importFetchedStatus(response.data))
|
||||
dispatch(unbookmarkSuccess(status, response.data))
|
||||
dispatch(updateStatusStats(response.data))
|
||||
dispatch(unbookmarkSuccess(status))
|
||||
}).catch((error) => {
|
||||
dispatch(unbookmarkFail(status, error))
|
||||
})
|
||||
}
|
||||
|
||||
export const unbookmarkRequest = (status) => ({
|
||||
const unbookmarkRequest = (status) => ({
|
||||
type: UNBOOKMARK_REQUEST,
|
||||
status: status,
|
||||
status,
|
||||
})
|
||||
|
||||
export const unbookmarkSuccess = (status, response) => ({
|
||||
const unbookmarkSuccess = (status) => ({
|
||||
type: UNBOOKMARK_SUCCESS,
|
||||
status: status,
|
||||
response: response,
|
||||
status,
|
||||
})
|
||||
|
||||
export const unbookmarkFail = (status, error) => ({
|
||||
const unbookmarkFail = (status, error) => ({
|
||||
type: UNBOOKMARK_FAIL,
|
||||
status: status,
|
||||
error: error,
|
||||
})
|
||||
status,
|
||||
error,
|
||||
})
|
||||
|
||||
/**
|
||||
* @description Check if a status is bookmarked to the current user account.
|
||||
* @param {String} statusId
|
||||
*/
|
||||
export const isBookmark = (statusId) => (dispatch, getState) => {
|
||||
if (!me || !statusId) return
|
||||
|
||||
dispatch(isBookmarkRequest(statusId))
|
||||
|
||||
api(getState).get(`/api/v1/statuses/${statusId}/bookmark`).then((response) => {
|
||||
dispatch(updateStatusStats(response.data))
|
||||
dispatch(isBookmarkSuccess(statusId))
|
||||
}).catch((error) => {
|
||||
dispatch(isBookmarkFail(statusId, error))
|
||||
})
|
||||
}
|
||||
|
||||
const isBookmarkRequest = (statusId) => ({
|
||||
type: IS_BOOKMARK_REQUEST,
|
||||
statusId,
|
||||
})
|
||||
|
||||
const isBookmarkSuccess = (statusId) => ({
|
||||
type: IS_BOOKMARK_SUCCESS,
|
||||
statusId,
|
||||
})
|
||||
|
||||
const isBookmarkFail = (statusId, error) => ({
|
||||
type: IS_BOOKMARK_FAIL,
|
||||
statusId,
|
||||
error,
|
||||
})
|
||||
|
||||
/**
|
||||
* @description Fetch reposts for the given statusId and imports paginated accounts
|
||||
* and sets in user_lists reducer.
|
||||
* @param {String} statusId
|
||||
*/
|
||||
export const fetchReposts = (statusId) => (dispatch, getState) => {
|
||||
if (!me || !statusId) return
|
||||
|
||||
dispatch(fetchRepostsRequest(statusId))
|
||||
|
||||
api(getState).get(`/api/v1/statuses/${statusId}/reblogged_by`).then((response) => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next')
|
||||
dispatch(importFetchedAccounts(response.data))
|
||||
dispatch(fetchRepostsSuccess(statusId, response.data, next ? next.uri : null))
|
||||
dispatch(fetchRelationships(response.data.map(item => item.id)))
|
||||
}).catch((error) => {
|
||||
dispatch(fetchRepostsFail(statusId, error))
|
||||
})
|
||||
}
|
||||
|
||||
const fetchRepostsRequest = (statusId) => ({
|
||||
type: REPOSTS_FETCH_REQUEST,
|
||||
statusId,
|
||||
})
|
||||
|
||||
const fetchRepostsSuccess = (statusId, accounts, next) => ({
|
||||
type: REPOSTS_FETCH_SUCCESS,
|
||||
statusId,
|
||||
accounts,
|
||||
next,
|
||||
})
|
||||
|
||||
const fetchRepostsFail = (statusId, error) => ({
|
||||
type: REPOSTS_FETCH_FAIL,
|
||||
statusId,
|
||||
error,
|
||||
})
|
||||
|
||||
/**
|
||||
* @description Expand reposts for the given statusId and imports paginated accounts
|
||||
* and sets in user_lists reducer.
|
||||
* @param {String} statusId
|
||||
*/
|
||||
export const expandReposts = (statusId) => (dispatch, getState) => {
|
||||
if (!me || !statusId) return
|
||||
|
||||
const url = getState().getIn(['user_lists', 'reblogged_by', statusId, 'next'])
|
||||
const isLoading = getState().getIn(['user_lists', 'reblogged_by', statusId, 'isLoading'])
|
||||
|
||||
if (url === null || isLoading) return
|
||||
|
||||
dispatch(expandRepostsRequest(statusId))
|
||||
|
||||
api(getState).get(url).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next')
|
||||
dispatch(importFetchedAccounts(response.data))
|
||||
dispatch(expandRepostsSuccess(statusId, response.data, next ? next.uri : null))
|
||||
dispatch(fetchRelationships(response.data.map(item => item.id)))
|
||||
}).catch(error => dispatch(expandRepostsFail(error)))
|
||||
}
|
||||
|
||||
const expandRepostsRequest = (statusId) => ({
|
||||
type: REPOSTS_EXPAND_REQUEST,
|
||||
statusId,
|
||||
})
|
||||
|
||||
const expandRepostsSuccess = (statusId, accounts, next) => ({
|
||||
type: REPOSTS_EXPAND_SUCCESS,
|
||||
statusId,
|
||||
accounts,
|
||||
next,
|
||||
})
|
||||
|
||||
const expandRepostsFail = (statusId, error) => ({
|
||||
type: REPOSTS_EXPAND_FAIL,
|
||||
statusId,
|
||||
error,
|
||||
})
|
||||
|
||||
|
||||
/**
|
||||
* @description Fetch likes for the given statusId and imports paginated accounts
|
||||
* and sets in user_lists reducer.
|
||||
* @param {String} statusId
|
||||
*/
|
||||
export const fetchLikes = (statusId) => (dispatch, getState) => {
|
||||
if (!me || !statusId) return
|
||||
|
||||
dispatch(fetchLikesRequest(statusId))
|
||||
|
||||
api(getState).get(`/api/v1/statuses/${statusId}/favourited_by`).then((response) => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next')
|
||||
dispatch(importFetchedAccounts(response.data))
|
||||
dispatch(fetchLikesSuccess(statusId, response.data, next ? next.uri : null))
|
||||
dispatch(fetchRelationships(response.data.map(item => item.id)))
|
||||
}).catch((error) => {
|
||||
dispatch(fetchLikesFail(statusId, error))
|
||||
})
|
||||
}
|
||||
|
||||
const fetchLikesRequest = (statusId) => ({
|
||||
type: LIKES_FETCH_REQUEST,
|
||||
statusId,
|
||||
})
|
||||
|
||||
const fetchLikesSuccess = (statusId, accounts, next) => ({
|
||||
type: LIKES_FETCH_SUCCESS,
|
||||
statusId,
|
||||
accounts,
|
||||
next,
|
||||
})
|
||||
|
||||
const fetchLikesFail = (statusId, error) => ({
|
||||
type: LIKES_FETCH_FAIL,
|
||||
statusId,
|
||||
error,
|
||||
})
|
||||
|
||||
/**
|
||||
* @description Expand likes for the given statusId and imports paginated accounts
|
||||
* and sets in user_lists reducer.
|
||||
* @param {String} statusId
|
||||
*/
|
||||
export const expandLikes = (statusId) => (dispatch, getState) => {
|
||||
if (!me || !statusId) return
|
||||
|
||||
const url = getState().getIn(['user_lists', 'liked_by', statusId, 'next'])
|
||||
const isLoading = getState().getIn(['user_lists', 'liked_by', statusId, 'isLoading'])
|
||||
|
||||
if (url === null || isLoading) return
|
||||
|
||||
dispatch(expandLikesRequest(statusId))
|
||||
|
||||
api(getState).get(url).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next')
|
||||
dispatch(importFetchedAccounts(response.data))
|
||||
dispatch(expandLikesSuccess(statusId, response.data, next ? next.uri : null))
|
||||
dispatch(fetchRelationships(response.data.map(item => item.id)))
|
||||
}).catch(error => dispatch(expandLikesFail(error)))
|
||||
}
|
||||
|
||||
const expandLikesRequest = (statusId) => ({
|
||||
type: LIKES_EXPAND_REQUEST,
|
||||
statusId,
|
||||
})
|
||||
|
||||
const expandLikesSuccess = (statusId, accounts, next) => ({
|
||||
type: LIKES_EXPAND_SUCCESS,
|
||||
statusId,
|
||||
accounts,
|
||||
next,
|
||||
})
|
||||
|
||||
const expandLikesFail = (statusId, error) => ({
|
||||
type: LIKES_EXPAND_FAIL,
|
||||
statusId,
|
||||
error,
|
||||
})
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import api, { getLinks } from '../api'
|
||||
import IntlMessageFormat from 'intl-messageformat'
|
||||
import noop from 'lodash.noop'
|
||||
import { fetchRelationships } from './accounts'
|
||||
import {
|
||||
importFetchedAccount,
|
||||
|
@ -49,8 +50,6 @@ const excludeTypesFromFilter = filter => {
|
|||
return allTypes.filterNot(item => item === filter).toJS()
|
||||
}
|
||||
|
||||
const noOp = () => {}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -159,7 +158,7 @@ export const dequeueNotifications = () => (dispatch, getState) => {
|
|||
/**
|
||||
*
|
||||
*/
|
||||
export const expandNotifications = ({ maxId } = {}, done = noOp) => (dispatch, getState) => {
|
||||
export const expandNotifications = ({ maxId } = {}, done = noop) => (dispatch, getState) => {
|
||||
if (!me) return
|
||||
|
||||
const onlyVerified = getState().getIn(['notifications', 'filter', 'onlyVerified'])
|
||||
|
@ -204,19 +203,19 @@ export const expandNotifications = ({ maxId } = {}, done = noOp) => (dispatch, g
|
|||
})
|
||||
}
|
||||
|
||||
export const expandNotificationsRequest = (isLoadingMore) => ({
|
||||
const expandNotificationsRequest = (isLoadingMore) => ({
|
||||
type: NOTIFICATIONS_EXPAND_REQUEST,
|
||||
skipLoading: !isLoadingMore,
|
||||
})
|
||||
|
||||
export const expandNotificationsSuccess = (notifications, next, isLoadingMore) => ({
|
||||
const expandNotificationsSuccess = (notifications, next, isLoadingMore) => ({
|
||||
type: NOTIFICATIONS_EXPAND_SUCCESS,
|
||||
notifications,
|
||||
next,
|
||||
skipLoading: !isLoadingMore,
|
||||
})
|
||||
|
||||
export const expandNotificationsFail = (error, isLoadingMore) => ({
|
||||
const expandNotificationsFail = (error, isLoadingMore) => ({
|
||||
type: NOTIFICATIONS_EXPAND_FAIL,
|
||||
error,
|
||||
skipLoading: !isLoadingMore,
|
||||
|
|
|
@ -1,15 +1,23 @@
|
|||
import api from '../api'
|
||||
|
||||
export const STATUS_REVISIONS_LOAD = 'STATUS_REVISIONS_LOAD'
|
||||
export const STATUS_REVISIONS_LOAD_REQUEST = 'STATUS_REVISIONS_LOAD_REQUEST'
|
||||
export const STATUS_REVISIONS_LOAD_SUCCESS = 'STATUS_REVISIONS_SUCCESS'
|
||||
export const STATUS_REVISIONS_LOAD_FAIL = 'STATUS_REVISIONS_FAIL'
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const loadStatusRevisions = (statusId) => (dispatch, getState) => {
|
||||
dispatch(loadStatusRevisionsRequest())
|
||||
api(getState).get(`/api/v1/statuses/${statusId}/revisions`)
|
||||
.then(res => dispatch(loadStatusRevisionsSuccess(res.data)))
|
||||
.catch(() => dispatch(loadStatusRevisionsFail()))
|
||||
}
|
||||
|
||||
const loadStatusRevisionsRequest = () => ({
|
||||
type: STATUS_REVISIONS_LOAD_REQUEST,
|
||||
})
|
||||
|
||||
const loadStatusRevisionsSuccess = (data) => ({
|
||||
type: STATUS_REVISIONS_LOAD_SUCCESS,
|
||||
revisions: data,
|
||||
|
|
|
@ -1,304 +1,292 @@
|
|||
import api from '../api';
|
||||
import openDB from '../storage/db';
|
||||
import { evictStatus } from '../storage/modifier';
|
||||
import { deleteFromTimelines } from './timelines';
|
||||
import { importFetchedStatus, importFetchedStatuses, importAccount, importStatus } from './importer';
|
||||
import { openModal } from './modal';
|
||||
import { me } from '../initial_state';
|
||||
import api from '../api'
|
||||
import openDB from '../storage/db'
|
||||
import { evictStatus } from '../storage/modifier'
|
||||
import { deleteFromTimelines } from './timelines'
|
||||
import { importFetchedStatus, importFetchedStatuses, importAccount, importStatus } from './importer'
|
||||
import { openModal } from './modal'
|
||||
import { me } from '../initial_state'
|
||||
|
||||
export const STATUS_FETCH_REQUEST = 'STATUS_FETCH_REQUEST';
|
||||
export const STATUS_FETCH_SUCCESS = 'STATUS_FETCH_SUCCESS';
|
||||
export const STATUS_FETCH_FAIL = 'STATUS_FETCH_FAIL';
|
||||
export const STATUS_FETCH_REQUEST = 'STATUS_FETCH_REQUEST'
|
||||
export const STATUS_FETCH_SUCCESS = 'STATUS_FETCH_SUCCESS'
|
||||
export const STATUS_FETCH_FAIL = 'STATUS_FETCH_FAIL'
|
||||
|
||||
export const STATUS_DELETE_REQUEST = 'STATUS_DELETE_REQUEST';
|
||||
export const STATUS_DELETE_SUCCESS = 'STATUS_DELETE_SUCCESS';
|
||||
export const STATUS_DELETE_FAIL = 'STATUS_DELETE_FAIL';
|
||||
export const STATUS_DELETE_REQUEST = 'STATUS_DELETE_REQUEST'
|
||||
export const STATUS_DELETE_SUCCESS = 'STATUS_DELETE_SUCCESS'
|
||||
export const STATUS_DELETE_FAIL = 'STATUS_DELETE_FAIL'
|
||||
|
||||
export const CONTEXT_FETCH_REQUEST = 'CONTEXT_FETCH_REQUEST';
|
||||
export const CONTEXT_FETCH_SUCCESS = 'CONTEXT_FETCH_SUCCESS';
|
||||
export const CONTEXT_FETCH_FAIL = 'CONTEXT_FETCH_FAIL';
|
||||
export const CONTEXT_FETCH_REQUEST = 'CONTEXT_FETCH_REQUEST'
|
||||
export const CONTEXT_FETCH_SUCCESS = 'CONTEXT_FETCH_SUCCESS'
|
||||
export const CONTEXT_FETCH_FAIL = 'CONTEXT_FETCH_FAIL'
|
||||
|
||||
export const COMMENTS_FETCH_REQUEST = 'COMMENTS_FETCH_REQUEST';
|
||||
export const COMMENTS_FETCH_SUCCESS = 'COMMENTS_FETCH_SUCCESS';
|
||||
export const COMMENTS_FETCH_FAIL = 'COMMENTS_FETCH_FAIL';
|
||||
export const COMMENTS_FETCH_REQUEST = 'COMMENTS_FETCH_REQUEST'
|
||||
export const COMMENTS_FETCH_SUCCESS = 'COMMENTS_FETCH_SUCCESS'
|
||||
export const COMMENTS_FETCH_FAIL = 'COMMENTS_FETCH_FAIL'
|
||||
|
||||
export const STATUS_REVEAL = 'STATUS_REVEAL';
|
||||
export const STATUS_HIDE = 'STATUS_HIDE';
|
||||
export const STATUS_REVEAL = 'STATUS_REVEAL'
|
||||
export const STATUS_HIDE = 'STATUS_HIDE'
|
||||
|
||||
export const STATUS_EDIT = 'STATUS_EDIT';
|
||||
export const STATUS_EDIT = 'STATUS_EDIT'
|
||||
|
||||
export const UPDATE_STATUS_STATS = 'UPDATE_STATUS_STATS'
|
||||
|
||||
export function fetchStatusRequest(id, skipLoading) {
|
||||
return {
|
||||
type: STATUS_FETCH_REQUEST,
|
||||
id,
|
||||
skipLoading,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function getFromDB(dispatch, getState, accountIndex, index, id) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const request = index.get(id);
|
||||
const request = index.get(id)
|
||||
|
||||
request.onerror = reject;
|
||||
request.onerror = reject
|
||||
|
||||
request.onsuccess = () => {
|
||||
const promises = [];
|
||||
const promises = []
|
||||
|
||||
if (!request.result) {
|
||||
reject();
|
||||
return;
|
||||
reject()
|
||||
return
|
||||
}
|
||||
|
||||
dispatch(importStatus(request.result));
|
||||
dispatch(importStatus(request.result))
|
||||
|
||||
if (getState().getIn(['accounts', request.result.account], null) === null) {
|
||||
promises.push(new Promise((accountResolve, accountReject) => {
|
||||
const accountRequest = accountIndex.get(request.result.account);
|
||||
const accountRequest = accountIndex.get(request.result.account)
|
||||
|
||||
accountRequest.onerror = accountReject;
|
||||
accountRequest.onerror = accountReject
|
||||
accountRequest.onsuccess = () => {
|
||||
if (!request.result) {
|
||||
accountReject();
|
||||
return;
|
||||
accountReject()
|
||||
return
|
||||
}
|
||||
|
||||
dispatch(importAccount(accountRequest.result));
|
||||
accountResolve();
|
||||
};
|
||||
}));
|
||||
dispatch(importAccount(accountRequest.result))
|
||||
accountResolve()
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
if (request.result.reblog && getState().getIn(['statuses', request.result.reblog], null) === null) {
|
||||
promises.push(getFromDB(dispatch, getState, accountIndex, index, request.result.reblog));
|
||||
promises.push(getFromDB(dispatch, getState, accountIndex, index, request.result.reblog))
|
||||
}
|
||||
|
||||
resolve(Promise.all(promises));
|
||||
};
|
||||
});
|
||||
resolve(Promise.all(promises))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function fetchStatus(id) {
|
||||
return (dispatch, getState) => {
|
||||
const skipLoading = getState().getIn(['statuses', id], null) !== null;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const fetchStatus = (id) => (dispatch, getState) => {
|
||||
const skipLoading = getState().getIn(['statuses', id], null) !== null
|
||||
if (skipLoading) return
|
||||
|
||||
if (skipLoading) {
|
||||
return;
|
||||
dispatch(fetchStatusRequest(id, skipLoading))
|
||||
|
||||
openDB().then((db) => {
|
||||
const transaction = db.transaction(['accounts', 'statuses'], 'read')
|
||||
const accountIndex = transaction.objectStore('accounts').index('id')
|
||||
const index = transaction.objectStore('statuses').index('id')
|
||||
|
||||
return getFromDB(dispatch, getState, accountIndex, index, id).then(() => {
|
||||
db.close()
|
||||
}, (error) => {
|
||||
db.close()
|
||||
throw error
|
||||
})
|
||||
}).then(() => {
|
||||
dispatch(fetchStatusSuccess(skipLoading))
|
||||
}, () => api(getState).get(`/api/v1/statuses/${id}`).then((response) => {
|
||||
dispatch(importFetchedStatus(response.data))
|
||||
dispatch(fetchStatusSuccess(skipLoading))
|
||||
})).catch((error) => {
|
||||
dispatch(fetchStatusFail(id, error, skipLoading))
|
||||
})
|
||||
}
|
||||
|
||||
const fetchStatusRequest = (id, skipLoading) => ({
|
||||
type: STATUS_FETCH_REQUEST,
|
||||
id,
|
||||
skipLoading,
|
||||
})
|
||||
|
||||
const fetchStatusSuccess = (skipLoading) => ({
|
||||
type: STATUS_FETCH_SUCCESS,
|
||||
skipLoading,
|
||||
})
|
||||
|
||||
const fetchStatusFail = (id, error, skipLoading) => ({
|
||||
type: STATUS_FETCH_FAIL,
|
||||
id,
|
||||
error,
|
||||
skipLoading,
|
||||
skipAlert: true,
|
||||
})
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const editStatus = (status) => (dispatch) => {
|
||||
dispatch({
|
||||
type: STATUS_EDIT,
|
||||
status,
|
||||
})
|
||||
|
||||
dispatch(openModal('COMPOSE'))
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const deleteStatus = (id, routerHistory) => (dispatch, getState) => {
|
||||
if (!me) return
|
||||
|
||||
let status = getState().getIn(['statuses', id])
|
||||
|
||||
if (status.get('poll')) {
|
||||
status = status.set('poll', getState().getIn(['polls', status.get('poll')]))
|
||||
}
|
||||
|
||||
dispatch(deleteStatusRequest(id))
|
||||
|
||||
api(getState).delete(`/api/v1/statuses/${id}`).then((response) => {
|
||||
evictStatus(id)
|
||||
dispatch(deleteStatusSuccess(id))
|
||||
dispatch(deleteFromTimelines(id))
|
||||
}).catch((error) => {
|
||||
dispatch(deleteStatusFail(id, error))
|
||||
})
|
||||
}
|
||||
|
||||
const deleteStatusRequest = (id) => ({
|
||||
type: STATUS_DELETE_REQUEST,
|
||||
id: id,
|
||||
})
|
||||
|
||||
const deleteStatusSuccess = (id) => ({
|
||||
type: STATUS_DELETE_SUCCESS,
|
||||
id: id,
|
||||
})
|
||||
|
||||
const deleteStatusFail = (id, error) => ({
|
||||
type: STATUS_DELETE_FAIL,
|
||||
id: id,
|
||||
error,
|
||||
})
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const fetchContext = (id, ensureIsReply) => (dispatch, getState) => {
|
||||
if (ensureIsReply) {
|
||||
const isReply = !!getState().getIn(['statuses', id, 'in_reply_to_id'], null)
|
||||
if (!isReply) return
|
||||
}
|
||||
|
||||
dispatch(fetchContextRequest(id))
|
||||
|
||||
api(getState).get(`/api/v1/statuses/${id}/context`).then((response) => {
|
||||
dispatch(importFetchedStatuses(response.data.ancestors.concat(response.data.descendants)))
|
||||
dispatch(fetchContextSuccess(id, response.data.ancestors, response.data.descendants))
|
||||
}).catch((error) => {
|
||||
if (error.response && error.response.status === 404) {
|
||||
dispatch(deleteFromTimelines(id))
|
||||
}
|
||||
dispatch(fetchContextFail(id, error))
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
const fetchContextRequest = (id) => ({
|
||||
type: CONTEXT_FETCH_REQUEST,
|
||||
id,
|
||||
})
|
||||
|
||||
const fetchContextSuccess = (id, ancestors, descendants) => ({
|
||||
type: CONTEXT_FETCH_SUCCESS,
|
||||
id,
|
||||
ancestors,
|
||||
descendants,
|
||||
statuses: ancestors.concat(descendants),
|
||||
})
|
||||
|
||||
const fetchContextFail = (id, error) => ({
|
||||
type: CONTEXT_FETCH_FAIL,
|
||||
id,
|
||||
error,
|
||||
skipAlert: true,
|
||||
})
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const fetchComments = (id) => (dispatch, getState) => {
|
||||
dispatch(fetchCommentsRequest(id))
|
||||
|
||||
api(getState).get(`/api/v1/statuses/${id}/comments`).then((response) => {
|
||||
dispatch(importFetchedStatuses(response.data.descendants))
|
||||
dispatch(fetchCommentsSuccess(id, response.data.descendants))
|
||||
}).catch((error) => {
|
||||
if (error.response && error.response.status === 404) {
|
||||
dispatch(deleteFromTimelines(id))
|
||||
}
|
||||
|
||||
dispatch(fetchStatusRequest(id, skipLoading));
|
||||
dispatch(fetchCommentsFail(id, error))
|
||||
})
|
||||
}
|
||||
|
||||
openDB().then(db => {
|
||||
const transaction = db.transaction(['accounts', 'statuses'], 'read');
|
||||
const accountIndex = transaction.objectStore('accounts').index('id');
|
||||
const index = transaction.objectStore('statuses').index('id');
|
||||
const fetchCommentsRequest = (id) => ({
|
||||
type: COMMENTS_FETCH_REQUEST,
|
||||
id,
|
||||
})
|
||||
|
||||
return getFromDB(dispatch, getState, accountIndex, index, id).then(() => {
|
||||
db.close();
|
||||
}, error => {
|
||||
db.close();
|
||||
throw error;
|
||||
});
|
||||
}).then(() => {
|
||||
dispatch(fetchStatusSuccess(skipLoading));
|
||||
}, () => api(getState).get(`/api/v1/statuses/${id}`).then(response => {
|
||||
dispatch(importFetchedStatus(response.data));
|
||||
dispatch(fetchStatusSuccess(skipLoading));
|
||||
})).catch(error => {
|
||||
dispatch(fetchStatusFail(id, error, skipLoading));
|
||||
});
|
||||
};
|
||||
};
|
||||
const fetchCommentsSuccess = (id, descendants) => ({
|
||||
type: COMMENTS_FETCH_SUCCESS,
|
||||
id,
|
||||
descendants,
|
||||
})
|
||||
|
||||
export function fetchStatusSuccess(skipLoading) {
|
||||
return {
|
||||
type: STATUS_FETCH_SUCCESS,
|
||||
skipLoading,
|
||||
};
|
||||
};
|
||||
const fetchCommentsFail = (id, error) => ({
|
||||
type: COMMENTS_FETCH_FAIL,
|
||||
id,
|
||||
error,
|
||||
skipAlert: true,
|
||||
})
|
||||
|
||||
export function fetchStatusFail(id, error, skipLoading) {
|
||||
return {
|
||||
type: STATUS_FETCH_FAIL,
|
||||
id,
|
||||
error,
|
||||
skipLoading,
|
||||
skipAlert: true,
|
||||
};
|
||||
};
|
||||
|
||||
export function editStatus(status) {
|
||||
return dispatch => {
|
||||
dispatch({
|
||||
type: STATUS_EDIT,
|
||||
status,
|
||||
});
|
||||
|
||||
dispatch(openModal('COMPOSE'));
|
||||
};
|
||||
};
|
||||
|
||||
export function deleteStatus(id, routerHistory) {
|
||||
return (dispatch, getState) => {
|
||||
if (!me) return;
|
||||
|
||||
let status = getState().getIn(['statuses', id]);
|
||||
|
||||
if (status.get('poll')) {
|
||||
status = status.set('poll', getState().getIn(['polls', status.get('poll')]));
|
||||
}
|
||||
|
||||
dispatch(deleteStatusRequest(id));
|
||||
|
||||
api(getState).delete(`/api/v1/statuses/${id}`).then(response => {
|
||||
evictStatus(id);
|
||||
dispatch(deleteStatusSuccess(id));
|
||||
dispatch(deleteFromTimelines(id));
|
||||
}).catch(error => {
|
||||
dispatch(deleteStatusFail(id, error));
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export function deleteStatusRequest(id) {
|
||||
return {
|
||||
type: STATUS_DELETE_REQUEST,
|
||||
id: id,
|
||||
};
|
||||
};
|
||||
|
||||
export function deleteStatusSuccess(id) {
|
||||
return {
|
||||
type: STATUS_DELETE_SUCCESS,
|
||||
id: id,
|
||||
};
|
||||
};
|
||||
|
||||
export function deleteStatusFail(id, error) {
|
||||
return {
|
||||
type: STATUS_DELETE_FAIL,
|
||||
id: id,
|
||||
error: error,
|
||||
};
|
||||
};
|
||||
|
||||
export function fetchContext(id, ensureIsReply) {
|
||||
return (dispatch, getState) => {
|
||||
if (ensureIsReply) {
|
||||
const isReply = !!getState().getIn(['statuses', id, 'in_reply_to_id'], null)
|
||||
if (!isReply) return;
|
||||
}
|
||||
|
||||
dispatch(fetchContextRequest(id));
|
||||
|
||||
api(getState).get(`/api/v1/statuses/${id}/context`).then(response => {
|
||||
dispatch(importFetchedStatuses(response.data.ancestors.concat(response.data.descendants)));
|
||||
dispatch(fetchContextSuccess(id, response.data.ancestors, response.data.descendants));
|
||||
|
||||
}).catch(error => {
|
||||
if (error.response && error.response.status === 404) {
|
||||
dispatch(deleteFromTimelines(id));
|
||||
}
|
||||
|
||||
dispatch(fetchContextFail(id, error));
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export function fetchComments(id) {
|
||||
return (dispatch, getState) => {
|
||||
dispatch(fetchCommentsRequest(id));
|
||||
|
||||
api(getState).get(`/api/v1/statuses/${id}/comments`).then(response => {
|
||||
dispatch(importFetchedStatuses(response.data.descendants));
|
||||
dispatch(fetchCommentsSuccess(id, response.data.descendants));
|
||||
|
||||
}).catch(error => {
|
||||
if (error.response && error.response.status === 404) {
|
||||
dispatch(deleteFromTimelines(id));
|
||||
}
|
||||
|
||||
dispatch(fetchCommentsFail(id, error));
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export function fetchContextRequest(id) {
|
||||
return {
|
||||
type: CONTEXT_FETCH_REQUEST,
|
||||
id,
|
||||
};
|
||||
};
|
||||
|
||||
export function fetchContextSuccess(id, ancestors, descendants) {
|
||||
return {
|
||||
type: CONTEXT_FETCH_SUCCESS,
|
||||
id,
|
||||
ancestors,
|
||||
descendants,
|
||||
statuses: ancestors.concat(descendants),
|
||||
};
|
||||
};
|
||||
|
||||
export function fetchContextFail(id, error) {
|
||||
return {
|
||||
type: CONTEXT_FETCH_FAIL,
|
||||
id,
|
||||
error,
|
||||
skipAlert: true,
|
||||
};
|
||||
};
|
||||
|
||||
export function fetchCommentsRequest(id) {
|
||||
return {
|
||||
type: COMMENTS_FETCH_REQUEST,
|
||||
id,
|
||||
};
|
||||
};
|
||||
|
||||
export function fetchCommentsSuccess(id, descendants) {
|
||||
return {
|
||||
type: COMMENTS_FETCH_SUCCESS,
|
||||
id,
|
||||
descendants,
|
||||
};
|
||||
};
|
||||
|
||||
export function fetchCommentsFail(id, error) {
|
||||
return {
|
||||
type: COMMENTS_FETCH_FAIL,
|
||||
id,
|
||||
error,
|
||||
skipAlert: true,
|
||||
};
|
||||
};
|
||||
|
||||
export function hideStatus(ids) {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const hideStatus = (ids) => {
|
||||
if (!Array.isArray(ids)) {
|
||||
ids = [ids];
|
||||
ids = [ids]
|
||||
}
|
||||
|
||||
return {
|
||||
type: STATUS_HIDE,
|
||||
ids,
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function revealStatus(ids) {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const revealStatus = (ids) => {
|
||||
if (!Array.isArray(ids)) {
|
||||
ids = [ids];
|
||||
ids = [ids]
|
||||
}
|
||||
|
||||
return {
|
||||
type: STATUS_REVEAL,
|
||||
ids,
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function updateStatusStats(data) {
|
||||
return {
|
||||
type: UPDATE_STATUS_STATS,
|
||||
data,
|
||||
};
|
||||
};
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const updateStatusStats = (data) => ({
|
||||
type: UPDATE_STATUS_STATS,
|
||||
data,
|
||||
})
|
|
@ -71,3 +71,20 @@ export const connectStatusUpdateStream = () => {
|
|||
*
|
||||
*/
|
||||
export const connectUserStream = () => connectTimelineStream('home', 'user')
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const connectMessageStream = () => {
|
||||
|
||||
return connectStream('chat_messages', null, (dispatch, getState) => {
|
||||
|
||||
return {
|
||||
onConnect() {},
|
||||
onDisconnect() {},
|
||||
onReceive (data) {
|
||||
//
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
|
@ -44,20 +44,17 @@ const fetchSuggestions = (suggestionType, dispatch, getState, unlimited = false)
|
|||
|
||||
const fetchSuggestionsRequest = (suggestionType) => ({
|
||||
type: SUGGESTIONS_FETCH_REQUEST,
|
||||
skipLoading: true,
|
||||
suggestionType,
|
||||
})
|
||||
|
||||
const fetchSuggestionsSuccess = (accounts, suggestionType) => ({
|
||||
type: SUGGESTIONS_FETCH_SUCCESS,
|
||||
skipLoading: true,
|
||||
accounts,
|
||||
suggestionType
|
||||
})
|
||||
|
||||
const fetchSuggestionsFail = (error, suggestionType) => ({
|
||||
type: SUGGESTIONS_FETCH_FAIL,
|
||||
skipLoading: true,
|
||||
skipAlert: true,
|
||||
error,
|
||||
suggestionType,
|
||||
|
|
|
@ -1,133 +1,139 @@
|
|||
import { Map as ImmutableMap, List as ImmutableList, toJS } from 'immutable';
|
||||
import { importFetchedStatus, importFetchedStatuses } from './importer';
|
||||
import api, { getLinks } from '../api';
|
||||
import { Map as ImmutableMap, List as ImmutableList, toJS } from 'immutable'
|
||||
import noop from 'lodash.noop'
|
||||
import { importFetchedStatus, importFetchedStatuses } from './importer'
|
||||
import api, { getLinks } from '../api'
|
||||
import { fetchRelationships } from './accounts'
|
||||
|
||||
export const TIMELINE_UPDATE = 'TIMELINE_UPDATE';
|
||||
export const TIMELINE_DELETE = 'TIMELINE_DELETE';
|
||||
export const TIMELINE_CLEAR = 'TIMELINE_CLEAR';
|
||||
export const TIMELINE_UPDATE_QUEUE = 'TIMELINE_UPDATE_QUEUE';
|
||||
export const TIMELINE_DEQUEUE = 'TIMELINE_DEQUEUE';
|
||||
export const TIMELINE_SCROLL_TOP = 'TIMELINE_SCROLL_TOP';
|
||||
export const TIMELINE_UPDATE = 'TIMELINE_UPDATE'
|
||||
export const TIMELINE_DELETE = 'TIMELINE_DELETE'
|
||||
export const TIMELINE_CLEAR = 'TIMELINE_CLEAR'
|
||||
export const TIMELINE_UPDATE_QUEUE = 'TIMELINE_UPDATE_QUEUE'
|
||||
export const TIMELINE_DEQUEUE = 'TIMELINE_DEQUEUE'
|
||||
export const TIMELINE_SCROLL_TOP = 'TIMELINE_SCROLL_TOP'
|
||||
|
||||
export const TIMELINE_EXPAND_REQUEST = 'TIMELINE_EXPAND_REQUEST';
|
||||
export const TIMELINE_EXPAND_SUCCESS = 'TIMELINE_EXPAND_SUCCESS';
|
||||
export const TIMELINE_EXPAND_FAIL = 'TIMELINE_EXPAND_FAIL';
|
||||
export const TIMELINE_EXPAND_REQUEST = 'TIMELINE_EXPAND_REQUEST'
|
||||
export const TIMELINE_EXPAND_SUCCESS = 'TIMELINE_EXPAND_SUCCESS'
|
||||
export const TIMELINE_EXPAND_FAIL = 'TIMELINE_EXPAND_FAIL'
|
||||
|
||||
export const TIMELINE_CONNECT = 'TIMELINE_CONNECT';
|
||||
export const TIMELINE_DISCONNECT = 'TIMELINE_DISCONNECT';
|
||||
export const TIMELINE_CONNECT = 'TIMELINE_CONNECT'
|
||||
export const TIMELINE_DISCONNECT = 'TIMELINE_DISCONNECT'
|
||||
|
||||
export const MAX_QUEUED_ITEMS = 40;
|
||||
|
||||
export function updateTimeline(timeline, status, accept) {
|
||||
return dispatch => {
|
||||
if (typeof accept === 'function' && !accept(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(importFetchedStatus(status));
|
||||
|
||||
dispatch({
|
||||
type: TIMELINE_UPDATE,
|
||||
timeline,
|
||||
status,
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export function updateTimelineQueue(timeline, status, accept) {
|
||||
return dispatch => {
|
||||
if (typeof accept === 'function' && !accept(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: TIMELINE_UPDATE_QUEUE,
|
||||
timeline,
|
||||
status,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export function forceDequeueTimeline(timeline) {
|
||||
return (dispatch) => {
|
||||
dispatch({
|
||||
type: TIMELINE_DEQUEUE,
|
||||
timeline,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export function dequeueTimeline(timeline, expandFunc, optionalExpandArgs) {
|
||||
return (dispatch, getState) => {
|
||||
const queuedItems = getState().getIn(['timelines', timeline, 'queuedItems'], ImmutableList());
|
||||
const totalQueuedItemsCount = getState().getIn(['timelines', timeline, 'totalQueuedItemsCount'], 0);
|
||||
|
||||
let shouldDispatchDequeue = true;
|
||||
|
||||
if (totalQueuedItemsCount === 0) {
|
||||
return;
|
||||
} else if (totalQueuedItemsCount > 0 && totalQueuedItemsCount <= MAX_QUEUED_ITEMS) {
|
||||
queuedItems.forEach(status => {
|
||||
dispatch(updateTimeline(timeline, status.toJS(), null));
|
||||
});
|
||||
} else {
|
||||
if (typeof expandFunc === 'function') {
|
||||
dispatch(clearTimeline(timeline));
|
||||
expandFunc();
|
||||
} else {
|
||||
if (timeline === 'home') {
|
||||
dispatch(clearTimeline(timeline));
|
||||
dispatch(expandHomeTimeline(optionalExpandArgs));
|
||||
} else if (timeline === 'community') {
|
||||
dispatch(clearTimeline(timeline));
|
||||
dispatch(expandCommunityTimeline(optionalExpandArgs));
|
||||
} else {
|
||||
shouldDispatchDequeue = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!shouldDispatchDequeue) return;
|
||||
|
||||
dispatch({
|
||||
type: TIMELINE_DEQUEUE,
|
||||
timeline,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export function deleteFromTimelines(id) {
|
||||
return (dispatch, getState) => {
|
||||
const accountId = getState().getIn(['statuses', id, 'account']);
|
||||
const references = getState().get('statuses').filter(status => status.get('reblog') === id).map(status => [status.get('id'), status.get('account')]);
|
||||
const reblogOf = getState().getIn(['statuses', id, 'reblog'], null);
|
||||
|
||||
dispatch({
|
||||
type: TIMELINE_DELETE,
|
||||
id,
|
||||
accountId,
|
||||
references,
|
||||
reblogOf,
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export function clearTimeline(timeline) {
|
||||
return (dispatch) => {
|
||||
dispatch({ type: TIMELINE_CLEAR, timeline });
|
||||
};
|
||||
};
|
||||
|
||||
const noOp = () => { };
|
||||
export const MAX_QUEUED_ITEMS = 40
|
||||
|
||||
const parseTags = (tags = {}, mode) => {
|
||||
return (tags[mode] || []).map((tag) => {
|
||||
return tag.value;
|
||||
});
|
||||
};
|
||||
return (tags[mode] || []).map((tag) => tag.value)
|
||||
}
|
||||
|
||||
export const expandTimeline = (timelineId, path, params = {}, done = noOp) => (dispatch, getState) => {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const updateTimeline = (timeline, status, accept) => (dispatch) => {
|
||||
if (typeof accept === 'function' && !accept(status)) return
|
||||
|
||||
dispatch(importFetchedStatus(status))
|
||||
|
||||
dispatch({
|
||||
type: TIMELINE_UPDATE,
|
||||
timeline,
|
||||
status,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const updateTimelineQueue = (timeline, status, accept) => (dispatch) => {
|
||||
if (typeof accept === 'function' && !accept(status)) return
|
||||
|
||||
dispatch({
|
||||
type: TIMELINE_UPDATE_QUEUE,
|
||||
timeline,
|
||||
status,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const forceDequeueTimeline = (timeline) => (dispatch) => {
|
||||
dispatch({
|
||||
type: TIMELINE_DEQUEUE,
|
||||
timeline,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const dequeueTimeline = (timeline, expandFunc, optionalExpandArgs) => (dispatch, getState) => {
|
||||
const queuedItems = getState().getIn(['timelines', timeline, 'queuedItems'], ImmutableList())
|
||||
const totalQueuedItemsCount = getState().getIn(['timelines', timeline, 'totalQueuedItemsCount'], 0)
|
||||
|
||||
let shouldDispatchDequeue = true
|
||||
|
||||
if (totalQueuedItemsCount === 0) return
|
||||
|
||||
|
||||
if (totalQueuedItemsCount > 0 && totalQueuedItemsCount <= MAX_QUEUED_ITEMS) {
|
||||
queuedItems.forEach((status) => {
|
||||
dispatch(updateTimeline(timeline, status.toJS(), null))
|
||||
})
|
||||
} else {
|
||||
if (typeof expandFunc === 'function') {
|
||||
dispatch(clearTimeline(timeline))
|
||||
expandFunc()
|
||||
} else {
|
||||
if (timeline === 'home') {
|
||||
dispatch(clearTimeline(timeline))
|
||||
dispatch(expandHomeTimeline(optionalExpandArgs))
|
||||
} else if (timeline === 'community') {
|
||||
dispatch(clearTimeline(timeline))
|
||||
dispatch(expandCommunityTimeline(optionalExpandArgs))
|
||||
} else {
|
||||
shouldDispatchDequeue = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!shouldDispatchDequeue) return
|
||||
|
||||
dispatch({
|
||||
type: TIMELINE_DEQUEUE,
|
||||
timeline,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const deleteFromTimelines = (id) => (dispatch, getState) => {
|
||||
const accountId = getState().getIn(['statuses', id, 'account'])
|
||||
const references = getState().get('statuses').filter(status => status.get('reblog') === id).map(status => [status.get('id'), status.get('account')])
|
||||
const reblogOf = getState().getIn(['statuses', id, 'reblog'], null)
|
||||
|
||||
dispatch({
|
||||
type: TIMELINE_DELETE,
|
||||
id,
|
||||
accountId,
|
||||
references,
|
||||
reblogOf,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const clearTimeline = (timeline) => (dispatch) => {
|
||||
dispatch({
|
||||
type: TIMELINE_CLEAR,
|
||||
timeline
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const expandTimeline = (timelineId, path, params = {}, done = noop) => (dispatch, getState) => {
|
||||
const timeline = getState().getIn(['timelines', timelineId], ImmutableMap())
|
||||
const isLoadingMore = !!params.max_id
|
||||
|
||||
|
@ -156,74 +162,179 @@ export const expandTimeline = (timelineId, path, params = {}, done = noOp) => (d
|
|||
})
|
||||
}
|
||||
|
||||
export const expandHomeTimeline = ({ maxId } = {}, done = noOp) => expandTimeline('home', '/api/v1/timelines/home', { max_id: maxId }, done);
|
||||
export const expandExploreTimeline = ({ maxId, sortBy } = {}, done = noOp) => expandTimeline('explore', '/api/v1/timelines/explore', { max_id: maxId, sort_by: sortBy }, done);
|
||||
export const expandProTimeline = ({ maxId } = {}, done = noOp) => expandTimeline('pro', '/api/v1/timelines/pro', { max_id: maxId }, done);
|
||||
export const expandCommunityTimeline = ({ maxId, onlyMedia } = {}, done = noOp) => expandTimeline(`community${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { max_id: maxId, only_media: !!onlyMedia }, done);
|
||||
export const expandAccountTimeline = (accountId, { maxId, withReplies, commentsOnly } = {}) => expandTimeline(`account:${accountId}${withReplies ? ':with_replies' : ''}${commentsOnly ? ':comments_only' : ''}`, `/api/v1/accounts/${accountId}/statuses`, { only_comments: commentsOnly, exclude_replies: (!withReplies && !commentsOnly), max_id: maxId });
|
||||
export const expandAccountFeaturedTimeline = accountId => expandTimeline(`account:${accountId}:pinned`, `/api/v1/accounts/${accountId}/statuses`, { pinned: true });
|
||||
export const expandAccountMediaTimeline = (accountId, { maxId, limit, mediaType } = {}) => expandTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, { max_id: maxId, only_media: true, limit: limit || 20, media_type: mediaType });
|
||||
export const expandListTimeline = (id, { maxId } = {}, done = noOp) => expandTimeline(`list:${id}`, `/api/v1/timelines/list/${id}`, { max_id: maxId }, done);
|
||||
export const expandGroupTimeline = (id, { sortBy, maxId, onlyMedia } = {}, done = noOp) => expandTimeline(`group:${id}`, `/api/v1/timelines/group/${id}`, { sort_by: sortBy, max_id: maxId, only_media: onlyMedia }, done);
|
||||
export const expandGroupFeaturedTimeline = (groupId, done = noOp) => expandTimeline(`group:${groupId}:pinned`, `/api/v1/timelines/group_pins/${groupId}`, {}, done);
|
||||
export const expandGroupCollectionTimeline = (collectionType, { sortBy, maxId } = {}, done = noOp) => expandTimeline(`group_collection:${collectionType}`, `/api/v1/timelines/group_collection/${collectionType}`, { sort_by: sortBy, max_id: maxId }, done);
|
||||
export const expandLinkTimeline = (linkId, { maxId } = {}, done = noOp) => expandTimeline(`link:${linkId}`, `/api/v1/timelines/preview_card/${linkId}`, { max_id: maxId }, done);
|
||||
export const expandHashtagTimeline = (hashtag, { maxId, tags } = {}, done = noOp) => {
|
||||
const expandTimelineRequest = (timeline, isLoadingMore) => ({
|
||||
type: TIMELINE_EXPAND_REQUEST,
|
||||
timeline,
|
||||
skipLoading: !isLoadingMore,
|
||||
})
|
||||
|
||||
const expandTimelineSuccess = (timeline, statuses, next, partial, isLoadingRecent, isLoadingMore) => ({
|
||||
type: TIMELINE_EXPAND_SUCCESS,
|
||||
timeline,
|
||||
statuses,
|
||||
next,
|
||||
partial,
|
||||
isLoadingRecent,
|
||||
skipLoading: !isLoadingMore,
|
||||
})
|
||||
|
||||
const expandTimelineFail = (timeline, error, isLoadingMore) => ({
|
||||
type: TIMELINE_EXPAND_FAIL,
|
||||
timeline,
|
||||
error,
|
||||
skipLoading: !isLoadingMore,
|
||||
})
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const scrollTopTimeline = (timeline, top) => ({
|
||||
type: TIMELINE_SCROLL_TOP,
|
||||
timeline,
|
||||
top,
|
||||
})
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const connectTimeline = (timeline) => ({
|
||||
type: TIMELINE_CONNECT,
|
||||
timeline,
|
||||
})
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const disconnectTimeline = (timeline) => ({
|
||||
type: TIMELINE_DISCONNECT,
|
||||
timeline,
|
||||
})
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const expandHomeTimeline = ({ maxId } = {}, done = noop) => {
|
||||
return expandTimeline('home', '/api/v1/timelines/home', {
|
||||
max_id: maxId,
|
||||
}, done)
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const expandExploreTimeline = ({ maxId, sortBy } = {}, done = noop) => {
|
||||
return expandTimeline('explore', '/api/v1/timelines/explore', {
|
||||
max_id: maxId,
|
||||
sort_by: sortBy,
|
||||
}, done)
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const expandProTimeline = ({ maxId } = {}, done = noop) => {
|
||||
return expandTimeline('pro', '/api/v1/timelines/pro', {
|
||||
max_id: maxId,
|
||||
}, done)
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const expandCommunityTimeline = ({ maxId, onlyMedia } = {}, done = noop) => {
|
||||
return expandTimeline(`community${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', {
|
||||
max_id: maxId,
|
||||
only_media: !!onlyMedia,
|
||||
}, done)
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const expandAccountTimeline = (accountId, { maxId, withReplies, commentsOnly } = {}) => {
|
||||
let key = `account:${accountId}${withReplies ? ':with_replies' : ''}${commentsOnly ? ':comments_only' : ''}`
|
||||
return expandTimeline(key, `/api/v1/accounts/${accountId}/statuses`, {
|
||||
only_comments: commentsOnly,
|
||||
exclude_replies: (!withReplies && !commentsOnly),
|
||||
max_id: maxId,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const expandAccountFeaturedTimeline = (accountId) => {
|
||||
return expandTimeline(`account:${accountId}:pinned`, `/api/v1/accounts/${accountId}/statuses`, {
|
||||
pinned: true,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const expandAccountMediaTimeline = (accountId, { maxId, limit, mediaType } = {}) => {
|
||||
return expandTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, {
|
||||
max_id: maxId,
|
||||
only_media: true,
|
||||
limit: limit || 20,
|
||||
media_type: mediaType
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const expandListTimeline = (id, { maxId } = {}, done = noop) => {
|
||||
return expandTimeline(`list:${id}`, `/api/v1/timelines/list/${id}`, {
|
||||
max_id: maxId,
|
||||
}, done)
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const expandGroupTimeline = (id, { sortBy, maxId, onlyMedia } = {}, done = noop) => {
|
||||
return expandTimeline(`group:${id}`, `/api/v1/timelines/group/${id}`, {
|
||||
sort_by: sortBy,
|
||||
max_id: maxId,
|
||||
only_media: onlyMedia
|
||||
}, done)
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const expandGroupFeaturedTimeline = (groupId, done = noop) => {
|
||||
return expandTimeline(`group:${groupId}:pinned`, `/api/v1/timelines/group_pins/${groupId}`, {}, done)
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const expandGroupCollectionTimeline = (collectionType, { sortBy, maxId } = {}, done = noop) => {
|
||||
return expandTimeline(`group_collection:${collectionType}`, `/api/v1/timelines/group_collection/${collectionType}`, {
|
||||
sort_by: sortBy,
|
||||
max_id: maxId,
|
||||
}, done)
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const expandLinkTimeline = (linkId, { maxId } = {}, done = noop) => {
|
||||
return expandTimeline(`link:${linkId}`, `/api/v1/timelines/preview_card/${linkId}`, {
|
||||
max_id: maxId,
|
||||
}, done)
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const expandHashtagTimeline = (hashtag, { maxId, tags } = {}, done = noop) => {
|
||||
return expandTimeline(`hashtag:${hashtag}`, `/api/v1/timelines/tag/${hashtag}`, {
|
||||
max_id: maxId,
|
||||
any: parseTags(tags, 'any'),
|
||||
all: parseTags(tags, 'all'),
|
||||
none: parseTags(tags, 'none'),
|
||||
}, done);
|
||||
};
|
||||
|
||||
export function expandTimelineRequest(timeline, isLoadingMore) {
|
||||
return {
|
||||
type: TIMELINE_EXPAND_REQUEST,
|
||||
timeline,
|
||||
skipLoading: !isLoadingMore,
|
||||
};
|
||||
};
|
||||
|
||||
export function expandTimelineSuccess(timeline, statuses, next, partial, isLoadingRecent, isLoadingMore) {
|
||||
return {
|
||||
type: TIMELINE_EXPAND_SUCCESS,
|
||||
timeline,
|
||||
statuses,
|
||||
next,
|
||||
partial,
|
||||
isLoadingRecent,
|
||||
skipLoading: !isLoadingMore,
|
||||
};
|
||||
};
|
||||
|
||||
export function expandTimelineFail(timeline, error, isLoadingMore) {
|
||||
return {
|
||||
type: TIMELINE_EXPAND_FAIL,
|
||||
timeline,
|
||||
error,
|
||||
skipLoading: !isLoadingMore,
|
||||
};
|
||||
};
|
||||
|
||||
export function connectTimeline(timeline) {
|
||||
return {
|
||||
type: TIMELINE_CONNECT,
|
||||
timeline,
|
||||
};
|
||||
};
|
||||
|
||||
export function disconnectTimeline(timeline) {
|
||||
return {
|
||||
type: TIMELINE_DISCONNECT,
|
||||
timeline,
|
||||
};
|
||||
};
|
||||
|
||||
export function scrollTopTimeline(timeline, top) {
|
||||
return {
|
||||
type: TIMELINE_SCROLL_TOP,
|
||||
timeline,
|
||||
top,
|
||||
};
|
||||
};
|
||||
}, done)
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ class Account extends ImmutablePureComponent {
|
|||
</Button>
|
||||
) : <AccountActionButton account={account} isSmall />
|
||||
|
||||
const avatarSize = compact ? 42 : 52
|
||||
const avatarSize = compact ? 40 : 52
|
||||
const dismissBtn = !showDismiss ? null : (
|
||||
<Button
|
||||
isNarrow
|
||||
|
|
|
@ -230,7 +230,7 @@ const mapDispatchToProps = (dispatch) => ({
|
|||
onOpenStatusOptions(targetRef, status) {
|
||||
dispatch(openPopover('STATUS_OPTIONS', {
|
||||
targetRef,
|
||||
status,
|
||||
statusId: status.get('id'),
|
||||
position: 'top',
|
||||
}))
|
||||
},
|
||||
|
|
|
@ -126,7 +126,7 @@ const messages = defineMessages({
|
|||
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' },
|
||||
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' },
|
||||
search: { id: 'keyboard_shortcuts.search', defaultMessage: 'focus 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 ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import { fetchGroups } from '../../actions/groups'
|
||||
import { fetchGroupsByTab } from '../../actions/groups'
|
||||
import PanelLayout from './panel_layout'
|
||||
import GroupListItem from '../group_list_item'
|
||||
import ScrollableList from '../scrollable_list'
|
||||
|
@ -26,13 +26,13 @@ class GroupsPanel extends ImmutablePureComponent {
|
|||
|
||||
componentDidUpdate(prevProps, prevState, snapshot) {
|
||||
if (!prevState.fetched && this.state.fetched) {
|
||||
this.props.onFetchGroups(this.props.groupType)
|
||||
this.props.onFetchGroupsByTab(this.props.groupType)
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (!this.props.isLazy) {
|
||||
this.props.onFetchGroups(this.props.groupType)
|
||||
this.props.onFetchGroupsByTab(this.props.groupType)
|
||||
this.setState({ fetched: true })
|
||||
}
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ const mapStateToProps = (state, { groupType }) => ({
|
|||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onFetchGroups: (type) => dispatch(fetchGroups(type))
|
||||
onFetchGroupsByTab: (type) => dispatch(fetchGroupsByTab(type))
|
||||
})
|
||||
|
||||
GroupsPanel.propTypes = {
|
||||
|
|
|
@ -5,13 +5,16 @@ import ImmutablePropTypes from 'react-immutable-proptypes'
|
|||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl'
|
||||
import { me, isStaff, boostModal, deleteModal } from '../../initial_state'
|
||||
import { makeGetStatus } from '../../selectors'
|
||||
import {
|
||||
repost,
|
||||
unrepost,
|
||||
pin,
|
||||
unpin,
|
||||
isPin,
|
||||
bookmark,
|
||||
unbookmark,
|
||||
isBookmark,
|
||||
} from '../../actions/interactions';
|
||||
import {
|
||||
deleteStatus,
|
||||
|
@ -24,6 +27,7 @@ import {
|
|||
groupRemoveStatus,
|
||||
pinGroupStatus,
|
||||
unpinGroupStatus,
|
||||
isPinnedGroupStatus,
|
||||
} from '../../actions/groups'
|
||||
import { initReport } from '../../actions/reports'
|
||||
import { openModal } from '../../actions/modal'
|
||||
|
@ -51,11 +55,23 @@ class StatusOptionsPopover extends ImmutablePureComponent {
|
|||
]
|
||||
|
||||
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) {
|
||||
this.props.onFetchGroupRelationships(this.props.groupId)
|
||||
// : todo :
|
||||
// check if pin
|
||||
// check if bookmark
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,11 +147,15 @@ class StatusOptionsPopover extends ImmutablePureComponent {
|
|||
isXS,
|
||||
} = this.props
|
||||
|
||||
if (!status) return <div />
|
||||
|
||||
const mutingConversation = status.get('muted')
|
||||
const publicStatus = ['public', 'unlisted'].includes(status.get('visibility'))
|
||||
const isReply = !!status.get('in_reply_to_id')
|
||||
const withGroupAdmin = !!groupRelationships ? (groupRelationships.get('admin') || groupRelationships.get('moderator')) : false
|
||||
|
||||
console.log("publicStatus:", status, publicStatus)
|
||||
|
||||
let menu = []
|
||||
|
||||
if (me) {
|
||||
|
@ -296,13 +316,15 @@ const messages = defineMessages({
|
|||
share: { id: 'status.share_gab', defaultMessage: 'Share gab' },
|
||||
})
|
||||
|
||||
const mapStateToProps = (state, { status }) => {
|
||||
const mapStateToProps = (state, { statusId }) => {
|
||||
if (!me) return null
|
||||
|
||||
|
||||
const status = statusId ? makeGetStatus()(state, { id: statusId }) : undefined
|
||||
const groupId = status ? status.getIn(['group', 'id']) : undefined
|
||||
const groupRelationships = state.getIn(['group_relationships', groupId])
|
||||
|
||||
return {
|
||||
status,
|
||||
groupId,
|
||||
groupRelationships,
|
||||
isPro: state.getIn(['accounts', me, 'is_pro']),
|
||||
|
@ -311,6 +333,18 @@ const mapStateToProps = (state, { status }) => {
|
|||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
|
||||
fetchIsPin(statusId) {
|
||||
dispatch(isPin(statusId))
|
||||
},
|
||||
|
||||
fetchIsBookmark(statusId) {
|
||||
dispatch(isBookmark(statusId))
|
||||
},
|
||||
|
||||
fetchIsPinnedGroupStatus(groupId, statusId) {
|
||||
dispatch(isPinnedGroupStatus(groupId, statusId))
|
||||
},
|
||||
|
||||
onPin(status) {
|
||||
dispatch(closePopover())
|
||||
|
||||
|
@ -440,7 +474,8 @@ const mapDispatchToProps = (dispatch) => ({
|
|||
})
|
||||
|
||||
StatusOptionsPopover.propTypes = {
|
||||
status: ImmutablePropTypes.map.isRequired,
|
||||
status: ImmutablePropTypes.map,
|
||||
statusId: PropTypes.string.isRequired,
|
||||
groupRelationships: ImmutablePropTypes.map,
|
||||
groupId: PropTypes.string,
|
||||
onQuote: PropTypes.func.isRequired,
|
||||
|
@ -454,6 +489,9 @@ StatusOptionsPopover.propTypes = {
|
|||
onFetchGroupRelationships: PropTypes.func.isRequired,
|
||||
onOpenProUpgradeModal: PropTypes.func.isRequired,
|
||||
onClosePopover: PropTypes.func.isRequired,
|
||||
fetchIsPinnedGroupStatus: PropTypes.func.isRequired,
|
||||
fetchIsBookmark: PropTypes.func.isRequired,
|
||||
fetchIsPin: PropTypes.func.isRequired,
|
||||
isXS: PropTypes.bool,
|
||||
isPro: PropTypes.bool,
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import { CX } from '../constants'
|
|||
|
||||
class StatusActionBar extends ImmutablePureComponent {
|
||||
|
||||
updateOnProps = ['status']
|
||||
// updateOnProps = ['status']
|
||||
|
||||
handleShareClick = () => {
|
||||
this.props.onShare(this.shareButton, this.props.status)
|
||||
|
|
|
@ -4,7 +4,7 @@ import { connect } from 'react-redux'
|
|||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import { Set as ImmutableSet } from 'immutable';
|
||||
import noop from 'lodash/noop';
|
||||
import noop from 'lodash.noop'
|
||||
import { toggleStatusReport } from '../actions/reports';
|
||||
import { MediaGallery, Video } from '../features/ui/util/async_components';
|
||||
import Bundle from '../features/ui/util/bundle';
|
||||
|
|
|
@ -216,7 +216,7 @@ const mapDispatchToProps = (dispatch) => ({
|
|||
onOpenStatusOptionsPopover(targetRef, status) {
|
||||
dispatch(openPopover('STATUS_OPTIONS', {
|
||||
targetRef,
|
||||
status,
|
||||
statusId: status.get('id'),
|
||||
position: 'left-start',
|
||||
}))
|
||||
},
|
||||
|
|
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
|
|||
import { connect } from 'react-redux'
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import { fetchGroups } from '../../actions/groups'
|
||||
import { fetchGroupsByTab } from '../../actions/groups'
|
||||
import GroupCollectionItem from '../group_collection_item'
|
||||
import TimelineInjectionLayout from './timeline_injection_layout'
|
||||
|
||||
|
@ -11,7 +11,7 @@ class FeaturedGroupsInjection extends ImmutablePureComponent {
|
|||
|
||||
componentDidMount() {
|
||||
if (!this.props.isFetched) {
|
||||
this.props.onFetchGroups('featured')
|
||||
this.props.onFetchGroupsByTap('featured')
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,14 +59,14 @@ const mapStateToProps = (state) => ({
|
|||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onFetchGroups: (tab) => dispatch(fetchGroups(tab)),
|
||||
onFetchGroupsByTap: (tab) => dispatch(fetchGroupsByTab(tab)),
|
||||
})
|
||||
|
||||
FeaturedGroupsInjection.propTypes = {
|
||||
groupIds: ImmutablePropTypes.list,
|
||||
isFetched: PropTypes.bool.isRequired,
|
||||
isLoading: PropTypes.bool.isRequired,
|
||||
onFetchGroups: PropTypes.func.isRequired,
|
||||
onFetchGroupsByTab: PropTypes.func.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_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_WEEKLY = 'weekly'
|
||||
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 BlockHeading from '../components/block_heading'
|
||||
import ScrollableList from '../components/scrollable_list'
|
||||
import AccountPlaceholder from '../components/placeholder/account_placeholder'
|
||||
|
||||
class Blocks extends ImmutablePureComponent {
|
||||
|
||||
|
@ -40,16 +41,19 @@ class Blocks extends ImmutablePureComponent {
|
|||
onLoadMore={this.handleLoadMore}
|
||||
hasMore={hasMore}
|
||||
isLoading={isLoading}
|
||||
showLoading={isLoading}
|
||||
emptyMessage={emptyMessage}
|
||||
placeholderComponent={AccountPlaceholder}
|
||||
placeholderCount={3}
|
||||
>
|
||||
{
|
||||
accountIds && accountIds.map((id) =>
|
||||
accountIds && accountIds.map((id) => (
|
||||
<Account
|
||||
key={`blocked-accounts-${id}`}
|
||||
id={id}
|
||||
compact
|
||||
/>
|
||||
)
|
||||
))
|
||||
}
|
||||
</ScrollableList>
|
||||
</Block>
|
||||
|
|
|
@ -4,7 +4,7 @@ import { connect } from 'react-redux'
|
|||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import { injectIntl, defineMessages } from 'react-intl'
|
||||
import { fetchGroups } from '../actions/groups'
|
||||
import { fetchGroupsByTab } from '../actions/groups'
|
||||
import { openPopover } from '../actions/popover'
|
||||
import { POPOVER_GROUP_LIST_SORT_OPTIONS } from '../constants'
|
||||
import Block from '../components/block'
|
||||
|
@ -16,12 +16,12 @@ import GroupListItem from '../components/group_list_item'
|
|||
class GroupsCollection extends ImmutablePureComponent {
|
||||
|
||||
componentWillMount() {
|
||||
this.props.onFetchGroups(this.props.activeTab)
|
||||
this.props.onFetchGroupsByTab(this.props.activeTab)
|
||||
}
|
||||
|
||||
componentDidUpdate(oldProps) {
|
||||
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) => ({
|
||||
onFetchGroups: (tab) => dispatch(fetchGroups(tab)),
|
||||
onFetchGroupsByTab: (tab) => dispatch(fetchGroupsByTab(tab)),
|
||||
onOpenSortPopover(tab, targetRef) {
|
||||
dispatch(openPopover(POPOVER_GROUP_LIST_SORT_OPTIONS, {
|
||||
targetRef,
|
||||
|
|
|
@ -11,7 +11,7 @@ import {
|
|||
} from '../constants'
|
||||
import { me } from '../initial_state'
|
||||
import { saveShownOnboarding } from '../actions/settings'
|
||||
import { fetchGroups } from '../actions/groups'
|
||||
import { fetchGroupsByTab } from '../actions/groups'
|
||||
import { saveUserProfileInformation } from '../actions/user'
|
||||
import { makeGetAccount } from '../selectors'
|
||||
import Button from '../components/button'
|
||||
|
@ -414,7 +414,7 @@ const mapStateToProps = (state) => ({
|
|||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onSaveShownOnboarding: () => dispatch(saveShownOnboarding()),
|
||||
onFetchFeaturedGroups: () => dispatch(fetchGroups('featured')),
|
||||
onFetchFeaturedGroups: () => dispatch(fetchGroupsByTab('featured')),
|
||||
onSaveUserProfileInformation(data) {
|
||||
dispatch(saveUserProfileInformation(data))
|
||||
},
|
||||
|
|
|
@ -4,45 +4,65 @@ import { connect } from 'react-redux'
|
|||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
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 { makeGetStatus } from '../selectors'
|
||||
import Account from '../components/account'
|
||||
import ColumnIndicator from '../components/column_indicator'
|
||||
import ScrollableList from '../components/scrollable_list'
|
||||
import AccountPlaceholder from '../components/placeholder/account_placeholder'
|
||||
|
||||
class StatusLikes extends ImmutablePureComponent {
|
||||
|
||||
componentWillMount () {
|
||||
this.props.dispatch(fetchLikes(this.props.statusId))
|
||||
this.props.dispatch(fetchStatus(this.props.statusId))
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.statusId !== this.props.statusId && nextProps.statusId) {
|
||||
this.props.dispatch(fetchLikes(nextProps.statusId))
|
||||
this.props.dispatch(fetchStatus(nextProps.statusId))
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const { accountIds, status } = this.props
|
||||
handleLoadMore = debounce(() => {
|
||||
this.props.dispatch(expandLikes(this.props.statusId))
|
||||
}, 300, { leading: true })
|
||||
|
||||
if (!accountIds) {
|
||||
return <ColumnIndicator type='loading' />
|
||||
} else if (!status) {
|
||||
render () {
|
||||
const {
|
||||
accountIds,
|
||||
isLoading,
|
||||
hasMore,
|
||||
list,
|
||||
statusId,
|
||||
} = this.props
|
||||
|
||||
if (!statusId) {
|
||||
return <ColumnIndicator type='missing' />
|
||||
}
|
||||
|
||||
const accountIdCount = !!accountIds ? accountIds.count() : 0
|
||||
|
||||
return (
|
||||
<ScrollableList
|
||||
scrollKey='likes'
|
||||
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 =>
|
||||
<Account key={id} id={id} />
|
||||
)
|
||||
accountIdCount > 0 && accountIds.map((id) => (
|
||||
<Account
|
||||
compact
|
||||
key={`liked-by-${id}`}
|
||||
id={id}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</ScrollableList>
|
||||
)
|
||||
|
@ -52,24 +72,17 @@ class StatusLikes extends ImmutablePureComponent {
|
|||
|
||||
const mapStateToProps = (state, props) => {
|
||||
const statusId = props.params ? props.params.statusId : props.statusId
|
||||
|
||||
const getStatus = makeGetStatus()
|
||||
const status = getStatus(state, {
|
||||
id: statusId
|
||||
})
|
||||
|
||||
return {
|
||||
status,
|
||||
statusId,
|
||||
accountIds: state.getIn(['user_lists', 'liked_by', statusId]),
|
||||
accountIds: state.getIn(['user_lists', 'liked_by', statusId, 'items']),
|
||||
hasMore: !!state.getIn(['user_lists', 'liked_by', statusId, 'next']),
|
||||
isLoading: state.getIn(['user_lists', 'liked_by', statusId, 'isLoading']),
|
||||
}
|
||||
}
|
||||
|
||||
StatusLikes.propTypes = {
|
||||
accountIds: ImmutablePropTypes.list,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
status: ImmutablePropTypes.map,
|
||||
statusId: PropTypes.string.isRequired,
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(StatusLikes)
|
||||
export default connect(mapStateToProps)(StatusLikes)
|
||||
|
|
|
@ -4,45 +4,65 @@ import { connect } from 'react-redux'
|
|||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
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 { makeGetStatus } from '../selectors'
|
||||
import Account from '../components/account'
|
||||
import ColumnIndicator from '../components/column_indicator'
|
||||
import ScrollableList from '../components/scrollable_list'
|
||||
import AccountPlaceholder from '../components/placeholder/account_placeholder'
|
||||
|
||||
class StatusReposts extends ImmutablePureComponent {
|
||||
|
||||
componentWillMount () {
|
||||
this.props.dispatch(fetchReposts(this.props.statusId))
|
||||
this.props.dispatch(fetchStatus(this.props.statusId))
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.statusId !== this.props.statusId && nextProps.statusId) {
|
||||
this.props.dispatch(fetchReposts(nextProps.statusId))
|
||||
this.props.dispatch(fetchStatus(nextProps.statusId))
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const { accountIds, status } = this.props
|
||||
handleLoadMore = debounce(() => {
|
||||
this.props.dispatch(expandReposts(this.props.statusId))
|
||||
}, 300, { leading: true })
|
||||
|
||||
if (!accountIds) {
|
||||
return <ColumnIndicator type='loading' />
|
||||
} else if (!status) {
|
||||
render () {
|
||||
const {
|
||||
accountIds,
|
||||
isLoading,
|
||||
hasMore,
|
||||
list,
|
||||
statusId,
|
||||
} = this.props
|
||||
|
||||
if (!statusId) {
|
||||
return <ColumnIndicator type='missing' />
|
||||
}
|
||||
|
||||
const accountIdCount = !!accountIds ? accountIds.count() : 0
|
||||
|
||||
return (
|
||||
<ScrollableList
|
||||
scrollKey='reposts'
|
||||
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 =>
|
||||
<Account key={id} id={id} />
|
||||
)
|
||||
accountIdCount > 0 && accountIds.map((id) => (
|
||||
<Account
|
||||
compact
|
||||
key={`reposted-by-${id}`}
|
||||
id={id}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</ScrollableList>
|
||||
)
|
||||
|
@ -52,25 +72,17 @@ class StatusReposts extends ImmutablePureComponent {
|
|||
|
||||
const mapStateToProps = (state, props) => {
|
||||
const statusId = props.params ? props.params.statusId : props.statusId
|
||||
|
||||
const getStatus = makeGetStatus()
|
||||
const status = getStatus(state, {
|
||||
id: statusId,
|
||||
// username: props.params.username,
|
||||
})
|
||||
|
||||
return {
|
||||
status,
|
||||
statusId,
|
||||
accountIds: state.getIn(['user_lists', 'reblogged_by', statusId]),
|
||||
accountIds: state.getIn(['user_lists', 'reblogged_by', statusId, 'items']),
|
||||
hasMore: !!state.getIn(['user_lists', 'reblogged_by', statusId, 'next']),
|
||||
isLoading: state.getIn(['user_lists', 'reblogged_by', statusId, 'isLoading']),
|
||||
}
|
||||
}
|
||||
|
||||
StatusReposts.propTypes = {
|
||||
accountIds: ImmutablePropTypes.list,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
status: ImmutablePropTypes.map,
|
||||
statusId: PropTypes.string.isRequired,
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(StatusReposts)
|
||||
export default connect(mapStateToProps)(StatusReposts)
|
||||
|
|
|
@ -55,7 +55,6 @@ import {
|
|||
AccountTimeline,
|
||||
Assets,
|
||||
BlockedAccounts,
|
||||
BlockedDomains,
|
||||
BookmarkedStatuses,
|
||||
CommunityTimeline,
|
||||
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 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 Messages() { return import(/* webpackChunkName: "features/messages" */'../../messages') }
|
||||
export function Mutes() { return import(/* webpackChunkName: "features/mutes" */'../../mutes') }
|
||||
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') }
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { connect } from 'react-redux'
|
||||
import noop from 'lodash.noop'
|
||||
import {
|
||||
fetchBundleRequest,
|
||||
fetchBundleSuccess,
|
||||
|
@ -8,7 +9,6 @@ import {
|
|||
} from '../../../actions/bundles'
|
||||
|
||||
const emptyComponent = () => null
|
||||
const noop = () => { }
|
||||
|
||||
class Bundle extends React.PureComponent {
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ const defaultFailSuffix = 'FAIL';
|
|||
|
||||
export default function errorsMiddleware() {
|
||||
return ({ dispatch }) => next => action => {
|
||||
// : todo : use skipAlert!
|
||||
if (action.type && !action.skipAlert) {
|
||||
const isFail = new RegExp(`${defaultFailSuffix}$`, 'g');
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ export default function loadingBarMiddleware(config = {}) {
|
|||
const promiseTypeSuffixes = config.promiseTypeSuffixes || defaultTypeSuffixes
|
||||
|
||||
return ({ dispatch }) => next => (action) => {
|
||||
if (action.type && !action.skipLoading) {
|
||||
if (action.type && action.type.indexOf('TIMELINE') > -1) {
|
||||
const [PENDING, FULFILLED, REJECTED] = promiseTypeSuffixes
|
||||
|
||||
const isPending = new RegExp(`${PENDING}$`, 'g')
|
||||
|
|
|
@ -18,7 +18,7 @@ class MessagesPage extends React.PureComponent {
|
|||
title={title}
|
||||
>
|
||||
<PageTitle path={title} />
|
||||
{children}
|
||||
|
||||
</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_NEWEST,
|
||||
GROUP_TIMELINE_SORTING_TYPE_TOP_OPTION_TODAY,
|
||||
ACCEPTED_GROUP_TABS,
|
||||
} from '../constants'
|
||||
import slugify from '../utils/slugify'
|
||||
|
||||
const tabs = ['new', 'featured', 'member', 'admin']
|
||||
|
||||
const initialState = ImmutableMap({
|
||||
sortByValue: GROUP_TIMELINE_SORTING_TYPE_NEWEST,
|
||||
sortByTopValue: '',
|
||||
|
|
|
@ -4,11 +4,11 @@ import { Map as ImmutableMap, fromJS } from 'immutable';
|
|||
const normalizeRelationship = (state, relationship) => state.set(relationship.id, fromJS(relationship));
|
||||
|
||||
const normalizeRelationships = (state, relationships) => {
|
||||
relationships.forEach(relationship => {
|
||||
state = normalizeRelationship(state, relationship);
|
||||
});
|
||||
relationships.forEach(relationship => {
|
||||
state = normalizeRelationship(state, relationship);
|
||||
});
|
||||
|
||||
return state;
|
||||
return state
|
||||
};
|
||||
|
||||
const initialState = ImmutableMap();
|
||||
|
|
|
@ -30,7 +30,7 @@ export default function groups(state = initialState, action) {
|
|||
case GROUPS_FETCH_SUCCESS:
|
||||
return normalizeGroups(state, action.groups)
|
||||
case GROUP_FETCH_FAIL:
|
||||
return state.set(action.id, false)
|
||||
return state.set(action.groupId, false)
|
||||
default:
|
||||
return state
|
||||
}
|
||||
|
|
|
@ -2,6 +2,9 @@ import { combineReducers } from 'redux-immutable'
|
|||
import { loadingBarReducer } from 'react-redux-loading-bar'
|
||||
import accounts from './accounts'
|
||||
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 contexts from './contexts'
|
||||
import custom_emojis from './custom_emojis'
|
||||
|
@ -46,6 +49,8 @@ import user_lists from './user_lists'
|
|||
const reducers = {
|
||||
accounts,
|
||||
accounts_counters,
|
||||
chat_conversations,
|
||||
chat_messages,
|
||||
compose,
|
||||
contexts,
|
||||
custom_emojis,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable'
|
||||
import {
|
||||
STATUS_REVISIONS_LOAD,
|
||||
STATUS_REVISIONS_LOAD_REQUEST,
|
||||
STATUS_REVISIONS_LOAD_SUCCESS,
|
||||
STATUS_REVISIONS_LOAD_FAIL
|
||||
} from '../actions/status_revisions'
|
||||
|
@ -13,15 +13,17 @@ const initialState = ImmutableMap({
|
|||
|
||||
export default function statusRevisions(state = initialState, action) {
|
||||
switch (action.type) {
|
||||
case STATUS_REVISIONS_LOAD:
|
||||
return initialState
|
||||
case STATUS_REVISIONS_LOAD_REQUEST:
|
||||
return state.withMutations((mutable) => {
|
||||
mutable.set('loading', true)
|
||||
})
|
||||
case STATUS_REVISIONS_LOAD_SUCCESS:
|
||||
return state.withMutations(mutable => {
|
||||
return state.withMutations((mutable) => {
|
||||
mutable.set('loading', false)
|
||||
mutable.set('revisions', fromJS(action.revisions).reverse())
|
||||
})
|
||||
case STATUS_REVISIONS_LOAD_FAIL:
|
||||
return state.withMutations(mutable => {
|
||||
return state.withMutations((mutable) => {
|
||||
mutable.set('loading', false)
|
||||
mutable.set('error', action.error)
|
||||
})
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import {
|
||||
REPOST_REQUEST,
|
||||
UNREPOST_REQUEST,
|
||||
REPOST_FAIL,
|
||||
FAVORITE_REQUEST,
|
||||
FAVORITE_FAIL,
|
||||
|
@ -43,10 +44,12 @@ export default function statuses(state = initialState, action) {
|
|||
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 => {
|
||||
return state.withMutations((map) => {
|
||||
action.ids.forEach(id => {
|
||||
if (!(state.get(id) === undefined)) {
|
||||
map.setIn([id, 'hidden'], false);
|
||||
|
@ -54,7 +57,7 @@ export default function statuses(state = initialState, action) {
|
|||
});
|
||||
});
|
||||
case STATUS_HIDE:
|
||||
return state.withMutations(map => {
|
||||
return state.withMutations((map) => {
|
||||
action.ids.forEach(id => {
|
||||
if (!(state.get(id) === undefined)) {
|
||||
map.setIn([id, 'hidden'], true);
|
||||
|
@ -64,8 +67,17 @@ export default function statuses(state = initialState, action) {
|
|||
case TIMELINE_DELETE:
|
||||
return deleteStatus(state, action.id, action.references);
|
||||
case UPDATE_STATUS_STATS:
|
||||
// : todo :
|
||||
return state;
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable'
|
||||
import compareId from '../utils/compare_id'
|
||||
import {
|
||||
TIMELINE_UPDATE,
|
||||
TIMELINE_DELETE,
|
||||
|
@ -11,17 +13,19 @@ import {
|
|||
TIMELINE_DEQUEUE,
|
||||
MAX_QUEUED_ITEMS,
|
||||
TIMELINE_SCROLL_TOP,
|
||||
} from '../actions/timelines';
|
||||
} from '../actions/timelines'
|
||||
import {
|
||||
ACCOUNT_BLOCK_SUCCESS,
|
||||
ACCOUNT_MUTE_SUCCESS,
|
||||
ACCOUNT_UNFOLLOW_SUCCESS,
|
||||
} from '../actions/accounts';
|
||||
import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable';
|
||||
import compareId from '../utils/compare_id';
|
||||
import { GROUP_REMOVE_STATUS_SUCCESS } from '../actions/groups';
|
||||
} from '../actions/accounts'
|
||||
import {
|
||||
GROUP_REMOVE_STATUS_SUCCESS,
|
||||
GROUP_UNPIN_STATUS_SUCCESS,
|
||||
} from '../actions/groups'
|
||||
import { UNPIN_SUCCESS } from '../actions/interactions'
|
||||
|
||||
const initialState = ImmutableMap();
|
||||
const initialState = ImmutableMap()
|
||||
|
||||
const initialTimeline = ImmutableMap({
|
||||
unread: 0,
|
||||
|
@ -33,14 +37,14 @@ const initialTimeline = ImmutableMap({
|
|||
items: ImmutableList(),
|
||||
queuedItems: ImmutableList(), //max= MAX_QUEUED_ITEMS
|
||||
totalQueuedItemsCount: 0, //used for queuedItems overflow for MAX_QUEUED_ITEMS+
|
||||
});
|
||||
})
|
||||
|
||||
const expandNormalizedTimeline = (state, timeline, statuses, next, isPartial, isLoadingRecent) => {
|
||||
return state.update(timeline, initialTimeline, map => map.withMutations(mMap => {
|
||||
mMap.set('isLoading', false);
|
||||
mMap.set('isPartial', isPartial);
|
||||
return state.update(timeline, initialTimeline, map => map.withMutations((mMap) => {
|
||||
mMap.set('isLoading', false)
|
||||
mMap.set('isPartial', isPartial)
|
||||
|
||||
if (!next && !isLoadingRecent) mMap.set('hasMore', false);
|
||||
if (!next && !isLoadingRecent) mMap.set('hasMore', false)
|
||||
|
||||
if (!statuses.isEmpty()) {
|
||||
mMap.update('items', ImmutableList(), oldIds => {
|
||||
|
@ -160,8 +164,16 @@ const filterTimeline = (timeline, state, relationship, statuses) =>
|
|||
));
|
||||
|
||||
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) {
|
||||
switch(action.type) {
|
||||
|
@ -201,10 +213,14 @@ export default function timelines(state = initialState, action) {
|
|||
action.timeline,
|
||||
initialTimeline,
|
||||
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:
|
||||
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:
|
||||
return state;
|
||||
return state
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -23,8 +23,18 @@ import {
|
|||
FOLLOW_REQUEST_REJECT_SUCCESS,
|
||||
} from '../actions/accounts'
|
||||
import {
|
||||
REPOSTS_FETCH_REQUEST,
|
||||
REPOSTS_FETCH_SUCCESS,
|
||||
REPOSTS_FETCH_FAIL,
|
||||
REPOSTS_EXPAND_REQUEST,
|
||||
REPOSTS_EXPAND_SUCCESS,
|
||||
REPOSTS_EXPAND_FAIL,
|
||||
LIKES_FETCH_REQUEST,
|
||||
LIKES_FETCH_SUCCESS,
|
||||
LIKES_FETCH_FAIL,
|
||||
LIKES_EXPAND_REQUEST,
|
||||
LIKES_EXPAND_SUCCESS,
|
||||
LIKES_EXPAND_FAIL,
|
||||
} from '../actions/interactions'
|
||||
import {
|
||||
BLOCKS_FETCH_REQUEST,
|
||||
|
@ -52,6 +62,7 @@ import {
|
|||
GROUP_JOIN_REQUESTS_EXPAND_SUCCESS,
|
||||
GROUP_JOIN_REQUESTS_APPROVE_SUCCESS,
|
||||
GROUP_JOIN_REQUESTS_REJECT_SUCCESS,
|
||||
GROUP_REMOVED_ACCOUNTS_CREATE_SUCCESS,
|
||||
} from '../actions/groups'
|
||||
|
||||
const initialState = ImmutableMap({
|
||||
|
@ -119,12 +130,28 @@ export default function userLists(state = initialState, action) {
|
|||
case FOLLOWING_EXPAND_FAIL:
|
||||
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:
|
||||
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:
|
||||
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:
|
||||
return normalizeList(state, 'follow_requests', me, action.accounts, action.next);
|
||||
case FOLLOW_REQUESTS_EXPAND_SUCCESS:
|
||||
|
@ -162,21 +189,24 @@ export default function userLists(state = initialState, action) {
|
|||
return setListFailed(state, 'mutes', me)
|
||||
|
||||
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:
|
||||
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:
|
||||
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:
|
||||
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:
|
||||
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:
|
||||
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:
|
||||
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_REJECT_SUCCESS:
|
||||
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
|
||||
|
||||
|
|
|
@ -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 = query.joins(:status_stat).order(top_order) unless ['newest'].include? sort_type
|
||||
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.limit(20)
|
||||
|
||||
|
|
|
@ -148,7 +148,7 @@ module AccountInteractions
|
|||
end
|
||||
|
||||
def bookmarked?(status)
|
||||
status_bookmarks.where(account: self).exists?
|
||||
status_bookmarks.where(account: self, status: status).exists?
|
||||
end
|
||||
|
||||
def reblogged?(status)
|
||||
|
|
|
@ -72,6 +72,10 @@ class Group < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
def has_password?
|
||||
return !!self.password && self.password.gsub(/\s+/, "").length > 1 && self.password.to_s != "null"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_password
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class GroupRelationshipsPresenter
|
||||
attr_reader :member, :admin, :moderator, :requested
|
||||
|
||||
def initialize(group_ids, current_account_id, **options)
|
||||
@group_ids = group_ids.map { |a| a.is_a?(Group) ? a.id : a }
|
||||
@current_account_id = current_account_id
|
||||
|
||||
@member = Group.member_map(@group_ids, @current_account_id)
|
||||
@admin = Group.admin_map(@group_ids, @current_account_id)
|
||||
@moderator = Group.moderator_map(@group_ids, @current_account_id)
|
||||
@requested = Group.requested_map(@group_ids, @current_account_id)
|
||||
end
|
||||
attr_reader :member, :admin, :moderator, :requested
|
||||
|
||||
def initialize(group_ids, current_account_id, **options)
|
||||
@group_ids = group_ids.map { |a| a.is_a?(Group) ? a.id : a }
|
||||
@current_account_id = current_account_id
|
||||
|
||||
@member = Group.member_map(@group_ids, @current_account_id)
|
||||
@admin = Group.admin_map(@group_ids, @current_account_id)
|
||||
@moderator = Group.moderator_map(@group_ids, @current_account_id)
|
||||
@requested = Group.requested_map(@group_ids, @current_account_id)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
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)
|
||||
if current_account_id.nil?
|
||||
|
|
|
@ -13,7 +13,7 @@ class REST::GroupSerializer < ActiveModel::Serializer
|
|||
end
|
||||
|
||||
def has_password
|
||||
return !!object.password && object.password.gsub(/\s+/, "").length > 1 && object.password.to_s != "null"
|
||||
object.has_password?
|
||||
end
|
||||
|
||||
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
|
||||
attributes :id, :created_at, :revised_at, :in_reply_to_id, :in_reply_to_account_id,
|
||||
: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
|
||||
|
||||
attribute :favourited, if: :current_user?
|
||||
|
@ -32,6 +32,7 @@ class REST::StatusSerializer < ActiveModel::Serializer
|
|||
has_one :preloadable_poll, key: :poll, serializer: REST::PollSerializer
|
||||
|
||||
def id
|
||||
# puts "tilly instance:" + instance_options.inspect
|
||||
object.id.to_s
|
||||
end
|
||||
|
||||
|
@ -134,22 +135,14 @@ class REST::StatusSerializer < ActiveModel::Serializer
|
|||
end
|
||||
|
||||
def bookmarked
|
||||
if instance_options && instance_options[:relationships]
|
||||
instance_options[:relationships].bookmarks_map[object.id] || false
|
||||
else
|
||||
current_user.account.bookmarked?(object)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
def pinned
|
||||
if instance_options && instance_options[:relationships]
|
||||
instance_options[:relationships].pins_map[object.id] || false
|
||||
else
|
||||
current_user.account.pinned?(object)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
def pinnable?
|
||||
def pinnable
|
||||
current_user? &&
|
||||
current_user.account_id == object.account_id &&
|
||||
!object.reblog? &&
|
||||
|
@ -157,14 +150,10 @@ class REST::StatusSerializer < ActiveModel::Serializer
|
|||
end
|
||||
|
||||
def pinned_by_group
|
||||
if instance_options && instance_options[:relationships]
|
||||
instance_options[:relationships].group_pins_map[object.id] || false
|
||||
else
|
||||
false
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
def pinnable_by_group?
|
||||
def pinnable_by_group
|
||||
if object.group_id?
|
||||
true
|
||||
else
|
||||
|
|
|
@ -34,6 +34,14 @@ class REST::StatusStatSerializer < ActiveModel::Serializer
|
|||
end
|
||||
end
|
||||
|
||||
def reblogs_count
|
||||
if instance_options && instance_options[:unreblog]
|
||||
object.reblogs_count - 1
|
||||
else
|
||||
object.reblogs_count
|
||||
end
|
||||
end
|
||||
|
||||
def current_user?
|
||||
!current_user.nil?
|
||||
end
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
class GroupPinnedStatusValidator < ActiveModel::Validator
|
||||
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.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.ungrouped')) unless groupPin.status.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
|
||||
end
|
||||
end
|
||||
|
|
|
@ -16,4 +16,4 @@ nl:
|
|||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: van toot bestaat al
|
||||
taken: van gab bestaat al
|
||||
|
|
|
@ -414,7 +414,7 @@ ar:
|
|||
disabled: لا أحد
|
||||
title: المستخدِمون المصرح لهم لإرسال الدعوات
|
||||
show_known_fediverse_at_about_page:
|
||||
desc_html: عند التثبت ، سوف تظهر toots من جميع fediverse المعروفة على عرض مسبق. وإلا فإنه سيعرض فقط toots المحلية.
|
||||
desc_html: عند التثبت ، سوف تظهر gabs من جميع fediverse المعروفة على عرض مسبق. وإلا فإنه سيعرض فقط gabs المحلية.
|
||||
title: إظهار الفيديفرس الموحَّد في خيط المُعايَنة
|
||||
show_staff_badge:
|
||||
desc_html: عرض شارة الموظفين على صفحة المستخدم
|
||||
|
|
|
@ -34,10 +34,10 @@ ast:
|
|||
people_followed_by: Persones a les que sigue %{name}
|
||||
people_who_follow: Persones que siguen a %{name}
|
||||
posts:
|
||||
one: Toot
|
||||
other: Toots
|
||||
posts_tab_heading: Toots
|
||||
posts_with_replies: Toots y rempuestes
|
||||
one: Gab
|
||||
other: Gabs
|
||||
posts_tab_heading: Gabs
|
||||
posts_with_replies: Gabs y rempuestes
|
||||
reserved_username: El nome d'usuariu ta acutáu
|
||||
roles:
|
||||
bot: Robó
|
||||
|
@ -165,7 +165,7 @@ ast:
|
|||
exports:
|
||||
archive_takeout:
|
||||
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
|
||||
size: Tamañu
|
||||
blocks: Xente que bloquiesti
|
||||
|
@ -238,7 +238,7 @@ ast:
|
|||
reblog:
|
||||
body: "%{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:
|
||||
human:
|
||||
decimal_units:
|
||||
|
@ -309,13 +309,13 @@ ast:
|
|||
video:
|
||||
one: "%{count} videu"
|
||||
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
|
||||
pin_errors:
|
||||
limit: Yá fixesti'l númberu máxiumu de toots
|
||||
ownership: Nun pue fixase'l toot d'otra persona
|
||||
private: Nun puen fixase los toots que nun seyan públicos
|
||||
reblog: Nun pue fixase un toot compartíu
|
||||
limit: Yá fixesti'l númberu máxiumu de gabs
|
||||
ownership: Nun pue fixase'l gab d'otra persona
|
||||
private: Nun puen fixase los gabs que nun seyan públicos
|
||||
reblog: Nun pue fixase un gab compartíu
|
||||
show_more: Amosar más
|
||||
title: "%{name}: «%{quote}»"
|
||||
visibilities:
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
ca:
|
||||
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_this: Quant a
|
||||
active_count_after: actiu
|
||||
|
@ -59,10 +59,10 @@ ca:
|
|||
pin_errors:
|
||||
following: Has d'estar seguint la persona que vulguis avalar
|
||||
posts:
|
||||
one: Toot
|
||||
other: Toots
|
||||
posts_tab_heading: Toots
|
||||
posts_with_replies: Toots i respostes
|
||||
one: Gab
|
||||
other: Gabs
|
||||
posts_tab_heading: Gabs
|
||||
posts_with_replies: Gabs i respostes
|
||||
reserved_username: El nom d'usuari està reservat
|
||||
roles:
|
||||
admin: Administrador
|
||||
|
@ -214,7 +214,7 @@ ca:
|
|||
unsuspend_account: "%{name} ha llevat la suspensió del compte de %{target}"
|
||||
update_custom_emoji: "%{name} ha actualitzat l'emoji %{target}"
|
||||
update_status: "%{name} estat actualitzat per %{target}"
|
||||
deleted_status: "(toot suprimit)"
|
||||
deleted_status: "(gab suprimit)"
|
||||
title: Registre d'auditoria
|
||||
custom_emojis:
|
||||
by_domain: Domini
|
||||
|
@ -339,11 +339,11 @@ ca:
|
|||
relays:
|
||||
add_new: Afegiu un nou relay
|
||||
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
|
||||
disabled: Desactivat
|
||||
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
|
||||
inbox_url: URL del Relay
|
||||
pending: S'està esperant l'aprovació del relay
|
||||
|
@ -426,7 +426,7 @@ ca:
|
|||
open: Qualsevol pot registrar-se
|
||||
title: Mode de registres
|
||||
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
|
||||
show_staff_badge:
|
||||
desc_html: Mostra una insígnia de personal en la pàgina d'usuari
|
||||
|
@ -596,7 +596,7 @@ ca:
|
|||
archive_takeout:
|
||||
date: Data
|
||||
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...
|
||||
request: Sol·licita el teu arxiu
|
||||
size: Tamany
|
||||
|
@ -652,8 +652,8 @@ ca:
|
|||
i_am_html: Sóc %{username} a %{service}.
|
||||
identity: Identitat
|
||||
inactive: Inactiu
|
||||
publicize_checkbox: 'I tooteja això:'
|
||||
publicize_toot: 'Està provat! Sóc %{username} a %{service}: %{url}'
|
||||
publicize_checkbox: 'I gab això:'
|
||||
publicize_gab: 'Està provat! Sóc %{username} a %{service}: %{url}'
|
||||
status: Estat de verificació
|
||||
view_proof: Veure la prova
|
||||
imports:
|
||||
|
@ -796,20 +796,20 @@ ca:
|
|||
remote_interaction:
|
||||
favourite:
|
||||
proceed: Procedir a afavorir
|
||||
prompt: 'Vols marcar com a favorit aquest toot:'
|
||||
prompt: 'Vols marcar com a favorit aquest gab:'
|
||||
reblog:
|
||||
proceed: Procedir a impulsar
|
||||
prompt: 'Vols impulsar aquest toot:'
|
||||
prompt: 'Vols impulsar aquest gab:'
|
||||
reply:
|
||||
proceed: Procedir a respondre
|
||||
prompt: 'Vols respondre a aquest toot:'
|
||||
prompt: 'Vols respondre a aquest gab:'
|
||||
remote_unfollow:
|
||||
error: Error
|
||||
title: Títol
|
||||
unfollowed: Sense seguir
|
||||
scheduled_statuses:
|
||||
over_daily_limit: Has superat el límit de %{limit} toots programats per a aquell dia
|
||||
over_total_limit: Has superat el limit de %{limit} toots programats
|
||||
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} gabs programats
|
||||
too_soon: La data programada ha de ser futura
|
||||
sessions:
|
||||
activity: Última activitat
|
||||
|
@ -889,9 +889,9 @@ ca:
|
|||
open_in_web: Obre en la web
|
||||
over_character_limit: Límit de caràcters de %{max} superat
|
||||
pin_errors:
|
||||
limit: Ja has fixat el màxim nombre de toots
|
||||
ownership: No es pot fixar el toot d'algú altre
|
||||
private: No es pot fixar el toot no públic
|
||||
limit: Ja has fixat el màxim nombre de gabs
|
||||
ownership: No es pot fixar el gab d'algú altre
|
||||
private: No es pot fixar el gab no públic
|
||||
reblog: No es pot fixar un impuls
|
||||
poll:
|
||||
total_votes:
|
||||
|
@ -909,7 +909,7 @@ ca:
|
|||
unlisted: No llistat
|
||||
unlisted_long: Tothom ho pot veure, però no es mostra en la història federada
|
||||
stream_entries:
|
||||
pinned: Toot fixat
|
||||
pinned: Gab fixat
|
||||
reblogged: ha impulsat
|
||||
sensitive_content: Contingut sensible
|
||||
terms:
|
||||
|
@ -919,8 +919,8 @@ ca:
|
|||
|
||||
<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>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>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>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>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>
|
||||
</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>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>
|
||||
|
||||
|
@ -1028,7 +1028,7 @@ ca:
|
|||
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.
|
||||
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
|
||||
subject:
|
||||
disable: S'ha congelat el teu compte %{acct}
|
||||
|
|
|
@ -653,7 +653,7 @@ co:
|
|||
identity: Identità
|
||||
inactive: Inattiva
|
||||
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
|
||||
view_proof: Vede a prova
|
||||
imports:
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
cs:
|
||||
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_this: O tomto serveru
|
||||
active_count_after: aktivních
|
||||
|
@ -30,9 +30,9 @@ cs:
|
|||
server_stats: 'Statistika serveru:'
|
||||
source_code: Zdrojový kód
|
||||
status_count_after:
|
||||
few: tooty
|
||||
one: toot
|
||||
other: tootů
|
||||
few: gab
|
||||
one: Gab
|
||||
other: gab
|
||||
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.
|
||||
terms: Podmínky používání
|
||||
|
@ -62,11 +62,11 @@ cs:
|
|||
pin_errors:
|
||||
following: Musíte již sledovat osobu, kterou chcete podpořit
|
||||
posts:
|
||||
few: Tooty
|
||||
one: Toot
|
||||
other: Tootů
|
||||
posts_tab_heading: Tooty
|
||||
posts_with_replies: Tooty a odpovědi
|
||||
few: Gabs
|
||||
one: Gab
|
||||
other: Gabs
|
||||
posts_tab_heading: Gabs
|
||||
posts_with_replies: Gabs a odpovědi
|
||||
reserved_username: Toto uživatelské jméno je rezervováno
|
||||
roles:
|
||||
admin: Administrátor
|
||||
|
@ -175,7 +175,7 @@ cs:
|
|||
targeted_reports: Nahlášeni ostatními
|
||||
silence: Utišit
|
||||
silenced: Utišen/a
|
||||
statuses: Tooty
|
||||
statuses: Gabs
|
||||
subscribe: Odebírat
|
||||
suspended: Pozastaven/a
|
||||
title: Účty
|
||||
|
@ -199,7 +199,7 @@ cs:
|
|||
destroy_custom_emoji: "%{name} zničil/a emoji %{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_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_custom_emoji: "%{name} zakázal/a emoji %{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}"
|
||||
unsuspend_account: "%{name} zrušil/a pozastavení účtu uživatele %{target}"
|
||||
update_custom_emoji: "%{name} aktualizoval/a emoji %{target}"
|
||||
update_status: "%{name} aktualizoval/a toot uživatele %{target}"
|
||||
deleted_status: "(smazaný toot)"
|
||||
update_status: "%{name} aktualizoval/a gab uživatele %{target}"
|
||||
deleted_status: "(smazaný gab)"
|
||||
title: Záznam auditu
|
||||
custom_emojis:
|
||||
by_domain: Doména
|
||||
|
@ -345,11 +345,11 @@ cs:
|
|||
relays:
|
||||
add_new: Přidat nový most
|
||||
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
|
||||
disabled: Zakázáno
|
||||
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
|
||||
inbox_url: URL mostu
|
||||
pending: Čekám na souhlas mostu
|
||||
|
@ -392,7 +392,7 @@ cs:
|
|||
updated_at: Aktualizováno
|
||||
settings:
|
||||
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ě
|
||||
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.
|
||||
|
@ -432,7 +432,7 @@ cs:
|
|||
open: Kdokoliv se může registrovat
|
||||
title: Režim registrací
|
||||
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
|
||||
show_staff_badge:
|
||||
desc_html: Zobrazit na stránce uživatele odznak člena personálu
|
||||
|
@ -467,8 +467,8 @@ cs:
|
|||
media:
|
||||
title: Média
|
||||
no_media: Žádná média
|
||||
no_status_selected: Nebyly změněny žádné tooty, neboť žádné nebyly vybrány
|
||||
title: Tooty účtu
|
||||
no_status_selected: Nebyly změněny žádné gabs, neboť žádné nebyly vybrány
|
||||
title: Gabs účtu
|
||||
with_media: S médii
|
||||
subscriptions:
|
||||
callback_url: Zpáteční URL
|
||||
|
@ -506,7 +506,7 @@ cs:
|
|||
settings: 'Změnit volby e-mailu: %{link}'
|
||||
view: 'Zobrazit:'
|
||||
view_profile: Zobrazit profil
|
||||
view_status: Zobrazit toot
|
||||
view_status: Zobrazit gab
|
||||
applications:
|
||||
created: Aplikace úspěšně vytvořena
|
||||
destroyed: Aplikace úspěšně smazána
|
||||
|
@ -603,7 +603,7 @@ cs:
|
|||
archive_takeout:
|
||||
date: Datum
|
||||
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…
|
||||
request: Vyžádat svůj archiv
|
||||
size: Velikost
|
||||
|
@ -660,8 +660,8 @@ cs:
|
|||
i_am_html: Na %{service} jsem %{username}.
|
||||
identity: Identita
|
||||
inactive: Neaktivní
|
||||
publicize_checkbox: 'A tootnout tohle:'
|
||||
publicize_toot: 'Je to dokázáno! Na %{service} jsem %{username}: %{url}'
|
||||
publicize_checkbox: 'A gab tohle:'
|
||||
publicize_gab: 'Je to dokázáno! Na %{service} jsem %{username}: %{url}'
|
||||
status: Stav ověření
|
||||
view_proof: Zobrazit důkaz
|
||||
imports:
|
||||
|
@ -707,7 +707,7 @@ cs:
|
|||
limit: Dosáhl/a jste maximálního počtu seznamů
|
||||
media_attachments:
|
||||
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
|
||||
migrations:
|
||||
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"
|
||||
title: Ve vaší nepřítomnosti…
|
||||
favourite:
|
||||
body: 'Váš toot si oblíbil/a %{name}:'
|
||||
subject: "%{name} si oblíbil/a váš toot"
|
||||
body: 'Váš gab si oblíbil/a %{name}:'
|
||||
subject: "%{name} si oblíbil/a váš gab"
|
||||
title: Nové oblíbení
|
||||
follow:
|
||||
body: "%{name} vás nyní sleduje!"
|
||||
|
@ -749,8 +749,8 @@ cs:
|
|||
subject: Byl/a jste zmíněn/a uživatelem %{name}
|
||||
title: Nová zmínka
|
||||
reblog:
|
||||
body: 'Váš toot byl repostnutý uživatelem %{name}:'
|
||||
subject: "%{name} repostnul/a váš toot"
|
||||
body: 'Váš gab byl repostnutý uživatelem %{name}:'
|
||||
subject: "%{name} repostnul/a váš gab"
|
||||
title: Nový repost
|
||||
number:
|
||||
human:
|
||||
|
@ -807,20 +807,20 @@ cs:
|
|||
remote_interaction:
|
||||
favourite:
|
||||
proceed: Pokračovat k oblíbení
|
||||
prompt: 'Chcete si oblíbit tento toot:'
|
||||
prompt: 'Chcete si oblíbit tento gab:'
|
||||
reblog:
|
||||
proceed: Pokračovat k repostnutí
|
||||
prompt: 'Chcete repostnout tento toot:'
|
||||
prompt: 'Chcete repostnout tento gab:'
|
||||
reply:
|
||||
proceed: Pokračovat k odpovězení
|
||||
prompt: 'Chcete odpovědět na tento toot:'
|
||||
prompt: 'Chcete odpovědět na tento gab:'
|
||||
remote_unfollow:
|
||||
error: Chyba
|
||||
title: Nadpis
|
||||
unfollowed: Už nesledujete
|
||||
scheduled_statuses:
|
||||
over_daily_limit: Překročil/a jste limit %{limit} plánovaných tootů pro tento den
|
||||
over_total_limit: Překročil/a jste limit %{limit} plánovaných tootů
|
||||
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 gab
|
||||
too_soon: Plánované datum musí být v budoucnosti
|
||||
sessions:
|
||||
activity: Nejnovější aktivita
|
||||
|
@ -903,9 +903,9 @@ cs:
|
|||
open_in_web: Otevřít na webu
|
||||
over_character_limit: limit %{max} znaků byl překročen
|
||||
pin_errors:
|
||||
limit: Už jste si připnul/a maximální počet tootů
|
||||
ownership: Nelze připnout toot někoho jiného
|
||||
private: Nelze připnout neveřejné tooty
|
||||
limit: Už jste si připnul/a maximální počet gab
|
||||
ownership: Nelze připnout gab někoho jiného
|
||||
private: Nelze připnout neveřejné gabs
|
||||
reblog: Nelze připnout repost
|
||||
poll:
|
||||
total_votes:
|
||||
|
@ -924,7 +924,7 @@ cs:
|
|||
unlisted: Neuvedené
|
||||
unlisted_long: Všichni mohou vidět, ale nebudou zahrnuty ve veřejných časových osách
|
||||
stream_entries:
|
||||
pinned: Připnutý toot
|
||||
pinned: Připnutý gab
|
||||
reblogged: repostnul/a
|
||||
sensitive_content: Citlivý obsah
|
||||
terms:
|
||||
|
@ -1042,8 +1042,8 @@ cs:
|
|||
warning:
|
||||
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.
|
||||
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.
|
||||
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í.
|
||||
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 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
|
||||
subject:
|
||||
disable: Váš účet %{acct} byl zmražen
|
||||
|
|
|
@ -653,7 +653,7 @@ de:
|
|||
identity: Identität
|
||||
inactive: Inaktiv
|
||||
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
|
||||
view_proof: Zeige Nachweis
|
||||
imports:
|
||||
|
|
|
@ -127,11 +127,11 @@ cs:
|
|||
read:notifications: vidět vaše oznámení
|
||||
read:reports: vidět vaše nahlášení
|
||||
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:accounts: měnit váš profil
|
||||
write:blocks: blokovat účty a domény
|
||||
write:favourites: oblibovat si tooty
|
||||
write:favourites: oblibovat si gabs
|
||||
write:filters: vytvářet filtry
|
||||
write:follows: sledovat lidi
|
||||
write:lists: vytvářet seznamy
|
||||
|
@ -139,4 +139,4 @@ cs:
|
|||
write:mutes: skrývat lidi a konverzace
|
||||
write:notifications: vymazávat vaše oznámení
|
||||
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:mutes: zie jouw genegeerde gebruikers
|
||||
read:notifications: zie jouw meldingen
|
||||
read:reports: zie jouw gerapporteerde toots
|
||||
read:reports: zie jouw gerapporteerde gabs
|
||||
read:search: namens jou zoeken
|
||||
read:statuses: zie alle toots
|
||||
read:statuses: zie alle gabs
|
||||
write: alle gegevens van jouw account bewerken
|
||||
write:accounts: jouw profiel bewerken
|
||||
write:blocks: accounts en domeinen blokkeren
|
||||
write:favourites: toots als favoriet markeren
|
||||
write:favourites: gabs als favoriet markeren
|
||||
write:filters: filters aanmaken
|
||||
write:follows: mensen volgen
|
||||
write:lists: lijsten aanmaken
|
||||
|
@ -140,4 +140,4 @@ nl:
|
|||
write:mutes: mensen en gesprekken negeren
|
||||
write:notifications: meldingen verwijderen
|
||||
write:reports: andere mensen rapporteren
|
||||
write:statuses: toots publiceren
|
||||
write:statuses: gabs publiceren
|
||||
|
|
|
@ -681,7 +681,7 @@ en:
|
|||
identity: Identity
|
||||
inactive: Inactive
|
||||
publicize_checkbox: 'And gab this:'
|
||||
publicize_toot: 'I am %{username} on %{service}: %{url}'
|
||||
publicize_gab: 'I am %{username} on %{service}: %{url}'
|
||||
status: Verification status
|
||||
view_proof: View proof
|
||||
imports:
|
||||
|
|
|
@ -649,7 +649,7 @@ eo:
|
|||
identity: Identeco
|
||||
inactive: Malaktiva
|
||||
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
|
||||
view_proof: Vidi pruvo
|
||||
imports:
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
es:
|
||||
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_this: Acerca de esta instancia
|
||||
administered_by: 'Administrado por:'
|
||||
|
@ -48,10 +48,10 @@ es:
|
|||
pin_errors:
|
||||
following: Debes estar siguiendo a la persona a la que quieres aprobar
|
||||
posts:
|
||||
one: Toot
|
||||
other: Toots
|
||||
posts_tab_heading: Toots
|
||||
posts_with_replies: Toots con respuestas
|
||||
one: Gab
|
||||
other: Gabs
|
||||
posts_tab_heading: Gabs
|
||||
posts_with_replies: Gabs con respuestas
|
||||
reserved_username: El nombre de usuario está reservado
|
||||
roles:
|
||||
admin: Administrador
|
||||
|
@ -289,11 +289,11 @@ es:
|
|||
relays:
|
||||
add_new: Añadir un nuevo relés
|
||||
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
|
||||
disabled: Deshabilitado
|
||||
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
|
||||
inbox_url: URL del relés
|
||||
pending: Esperando la aprobación del relés
|
||||
|
@ -367,7 +367,7 @@ es:
|
|||
disabled: Nadie
|
||||
title: Permitir invitaciones de
|
||||
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
|
||||
show_staff_badge:
|
||||
desc_html: Mostrar un parche de staff en la página de un usuario
|
||||
|
@ -503,7 +503,7 @@ es:
|
|||
archive_takeout:
|
||||
date: Fecha
|
||||
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...
|
||||
request: Solicitar tu archivo
|
||||
size: Tamaño
|
||||
|
@ -615,8 +615,8 @@ es:
|
|||
subject: Fuiste mencionado por %{name}
|
||||
title: Nueva mención
|
||||
reblog:
|
||||
body: "%{name} ha retooteado tu estado:"
|
||||
subject: "%{name} ha retooteado tu estado"
|
||||
body: "%{name} ha reposted tu estado:"
|
||||
subject: "%{name} ha reposted tu estado"
|
||||
title: Nueva difusión
|
||||
number:
|
||||
human:
|
||||
|
@ -722,8 +722,8 @@ es:
|
|||
over_character_limit: Límite de caracteres de %{max} superado
|
||||
pin_errors:
|
||||
limit: Ya has fijado el número máximo de publicaciones
|
||||
ownership: El toot de alguien más no puede fijarse
|
||||
private: Los toots no-públicos no pueden fijarse
|
||||
ownership: El gab de alguien más no puede fijarse
|
||||
private: Los gabs no-públicos no pueden fijarse
|
||||
reblog: Un repost no puede fijarse
|
||||
show_more: Mostrar más
|
||||
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_long: Todos pueden ver, pero no está listado en las líneas de tiempo públicas
|
||||
stream_entries:
|
||||
pinned: Toot fijado
|
||||
reblogged: retooteado
|
||||
pinned: Gab fijado
|
||||
reblogged: reposted
|
||||
sensitive_content: Contenido sensible
|
||||
terms:
|
||||
title: Términos del Servicio y Políticas de Privacidad de %{instance}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
eu:
|
||||
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_this: Honi buruz
|
||||
administered_by: 'Administratzailea(k):'
|
||||
|
@ -48,10 +48,10 @@ eu:
|
|||
pin_errors:
|
||||
following: Onetsi nahi duzun pertsona aurretik jarraitu behar duzu
|
||||
posts:
|
||||
one: Toot
|
||||
other: Toot
|
||||
posts_tab_heading: Tootak
|
||||
posts_with_replies: Toot eta erantzunak
|
||||
one: Gab
|
||||
other: Gab
|
||||
posts_tab_heading: Gabs
|
||||
posts_with_replies: Gabs eta erantzunak
|
||||
reserved_username: Erabiltzaile-izena erreserbatuta dago
|
||||
roles:
|
||||
admin: Administratzailea
|
||||
|
@ -316,11 +316,11 @@ eu:
|
|||
relays:
|
||||
add_new: Gehitu hari berria
|
||||
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
|
||||
disabled: Desgaituta
|
||||
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
|
||||
inbox_url: Errelearen URLa
|
||||
pending: Erreleak onartzearen zain
|
||||
|
@ -397,7 +397,7 @@ eu:
|
|||
disabled: Inor ez
|
||||
title: Baimendu hauen gobidapenak
|
||||
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
|
||||
show_staff_badge:
|
||||
desc_html: Erakutsi langile banda erabiltzailearen orrian
|
||||
|
@ -557,7 +557,7 @@ eu:
|
|||
archive_takeout:
|
||||
date: Data
|
||||
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...
|
||||
request: Eskatu zure artxiboa
|
||||
size: Tamaina
|
||||
|
@ -712,20 +712,20 @@ eu:
|
|||
remote_interaction:
|
||||
favourite:
|
||||
proceed: Bihurtu gogoko
|
||||
prompt: 'Toot hau gogoko bihurtu nahi duzu:'
|
||||
prompt: 'Gab hau gogoko bihurtu nahi duzu:'
|
||||
reblog:
|
||||
proceed: Eman bultzada
|
||||
prompt: 'Toot honi bultzada eman nahi diozu:'
|
||||
prompt: 'Gab honi bultzada eman nahi diozu:'
|
||||
reply:
|
||||
proceed: Ekin erantzuteari
|
||||
prompt: 'Toot honi erantzun nahi diozu:'
|
||||
prompt: 'Gab honi erantzun nahi diozu:'
|
||||
remote_unfollow:
|
||||
error: Errorea
|
||||
title: Izenburua
|
||||
unfollowed: Jarraitzeari utzita
|
||||
scheduled_statuses:
|
||||
over_daily_limit: Egun horretarako programatutako toot kopuruaren muga gainditu duzu (%{limit})
|
||||
over_total_limit: Programatutako toot kopuruaren muga gainditu duzu (%{limit})
|
||||
over_daily_limit: Egun horretarako programatutako gab kopuruaren muga gainditu duzu (%{limit})
|
||||
over_total_limit: Programatutako gab kopuruaren muga gainditu duzu (%{limit})
|
||||
too_soon: Programatutako data etorkizunean egon behar du
|
||||
sessions:
|
||||
activity: Azken jarduera
|
||||
|
@ -798,9 +798,9 @@ eu:
|
|||
open_in_web: Ireki web-ean
|
||||
over_character_limit: "%{max}eko karaktere muga gaindituta"
|
||||
pin_errors:
|
||||
limit: Gehienez finkatu daitekeen toot kopurua finkatu duzu jada
|
||||
ownership: Ezin duzu beste norbaiten toot bat finkatu
|
||||
private: Ezin dira publikoak ez diren toot-ak finkatu
|
||||
limit: Gehienez finkatu daitekeen gab kopurua finkatu duzu jada
|
||||
ownership: Ezin duzu beste norbaiten gab bat finkatu
|
||||
private: Ezin dira publikoak ez diren gab-ak finkatu
|
||||
reblog: Bultzada bat ezin da finkatu
|
||||
show_more: Erakutsi gehiago
|
||||
sign_in_to_participate: Eman izena elkarrizketan parte hartzeko
|
||||
|
@ -813,7 +813,7 @@ eu:
|
|||
unlisted: Zerrendatu gabea
|
||||
unlisted_long: Edonork ikusi dezake, baina ez da denbora-lerro publikoetan agertzen
|
||||
stream_entries:
|
||||
pinned: Finkatutako toot-a
|
||||
pinned: Finkatutako gab-a
|
||||
reblogged: "(r)en bultzada"
|
||||
sensitive_content: 'Kontuz: Eduki hunkigarria'
|
||||
terms:
|
||||
|
@ -931,8 +931,8 @@ eu:
|
|||
warning:
|
||||
explanation:
|
||||
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.
|
||||
suspend: Zure kontua kanporatua izan da, zure toot guztiak eta multimedia fitxategiak behin betiko ezabatu dira zerbitzari honetatik, eta zure jarraitzaileen zerbitzarietatik.
|
||||
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 gab guztiak eta multimedia fitxategiak behin betiko ezabatu dira zerbitzari honetatik, eta zure jarraitzaileen zerbitzarietatik.
|
||||
review_server_policies: Berrikusi zerbitzariko politikak
|
||||
subject:
|
||||
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