Merge branch 'gs-master' into prevent-local-only-federation
Conflicts: db/schema.rb
This commit is contained in:
		
						commit
						82b2e224a2
					
				
							
								
								
									
										0
									
								
								CODEOWNERS → .github/CODEOWNERS
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										0
									
								
								CODEOWNERS → .github/CODEOWNERS
									
									
									
									
										vendored
									
									
								
							
							
								
								
									
										3
									
								
								Gemfile
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								Gemfile
									
									
									
									
									
								
							@ -14,12 +14,13 @@ gem 'pg', '~> 0.20'
 | 
				
			|||||||
gem 'pghero', '~> 1.7'
 | 
					gem 'pghero', '~> 1.7'
 | 
				
			||||||
gem 'dotenv-rails', '~> 2.2'
 | 
					gem 'dotenv-rails', '~> 2.2'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gem 'fog-aws', '~> 1.4', require: false
 | 
					gem 'aws-sdk', '~> 2.10', require: false
 | 
				
			||||||
gem 'fog-core', '~> 1.45'
 | 
					gem 'fog-core', '~> 1.45'
 | 
				
			||||||
gem 'fog-local', '~> 0.4', require: false
 | 
					gem 'fog-local', '~> 0.4', require: false
 | 
				
			||||||
gem 'fog-openstack', '~> 0.1', require: false
 | 
					gem 'fog-openstack', '~> 0.1', require: false
 | 
				
			||||||
gem 'paperclip', '~> 5.1'
 | 
					gem 'paperclip', '~> 5.1'
 | 
				
			||||||
gem 'paperclip-av-transcoder', '~> 0.6'
 | 
					gem 'paperclip-av-transcoder', '~> 0.6'
 | 
				
			||||||
 | 
					gem 'posix-spawn'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gem 'active_model_serializers', '~> 0.10'
 | 
					gem 'active_model_serializers', '~> 0.10'
 | 
				
			||||||
gem 'addressable', '~> 2.5'
 | 
					gem 'addressable', '~> 2.5'
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										21
									
								
								Gemfile.lock
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								Gemfile.lock
									
									
									
									
									
								
							@ -57,6 +57,14 @@ GEM
 | 
				
			|||||||
      encryptor (~> 3.0.0)
 | 
					      encryptor (~> 3.0.0)
 | 
				
			||||||
    av (0.9.0)
 | 
					    av (0.9.0)
 | 
				
			||||||
      cocaine (~> 0.5.3)
 | 
					      cocaine (~> 0.5.3)
 | 
				
			||||||
 | 
					    aws-sdk (2.10.100)
 | 
				
			||||||
 | 
					      aws-sdk-resources (= 2.10.100)
 | 
				
			||||||
 | 
					    aws-sdk-core (2.10.100)
 | 
				
			||||||
 | 
					      aws-sigv4 (~> 1.0)
 | 
				
			||||||
 | 
					      jmespath (~> 1.0)
 | 
				
			||||||
 | 
					    aws-sdk-resources (2.10.100)
 | 
				
			||||||
 | 
					      aws-sdk-core (= 2.10.100)
 | 
				
			||||||
 | 
					    aws-sigv4 (1.0.2)
 | 
				
			||||||
    bcrypt (3.1.11)
 | 
					    bcrypt (3.1.11)
 | 
				
			||||||
    better_errors (2.4.0)
 | 
					    better_errors (2.4.0)
 | 
				
			||||||
      coderay (>= 1.0.0)
 | 
					      coderay (>= 1.0.0)
 | 
				
			||||||
@ -152,11 +160,6 @@ GEM
 | 
				
			|||||||
      i18n (~> 0.5)
 | 
					      i18n (~> 0.5)
 | 
				
			||||||
    fast_blank (1.0.0)
 | 
					    fast_blank (1.0.0)
 | 
				
			||||||
    ffi (1.9.18)
 | 
					    ffi (1.9.18)
 | 
				
			||||||
    fog-aws (1.4.1)
 | 
					 | 
				
			||||||
      fog-core (~> 1.38)
 | 
					 | 
				
			||||||
      fog-json (~> 1.0)
 | 
					 | 
				
			||||||
      fog-xml (~> 0.1)
 | 
					 | 
				
			||||||
      ipaddress (~> 0.8)
 | 
					 | 
				
			||||||
    fog-core (1.45.0)
 | 
					    fog-core (1.45.0)
 | 
				
			||||||
      builder
 | 
					      builder
 | 
				
			||||||
      excon (~> 0.58)
 | 
					      excon (~> 0.58)
 | 
				
			||||||
@ -170,9 +173,6 @@ GEM
 | 
				
			|||||||
      fog-core (>= 1.40)
 | 
					      fog-core (>= 1.40)
 | 
				
			||||||
      fog-json (>= 1.0)
 | 
					      fog-json (>= 1.0)
 | 
				
			||||||
      ipaddress (>= 0.8)
 | 
					      ipaddress (>= 0.8)
 | 
				
			||||||
    fog-xml (0.1.3)
 | 
					 | 
				
			||||||
      fog-core
 | 
					 | 
				
			||||||
      nokogiri (>= 1.5.11, < 2.0.0)
 | 
					 | 
				
			||||||
    formatador (0.2.5)
 | 
					    formatador (0.2.5)
 | 
				
			||||||
    fuubar (2.2.0)
 | 
					    fuubar (2.2.0)
 | 
				
			||||||
      rspec-core (~> 3.0)
 | 
					      rspec-core (~> 3.0)
 | 
				
			||||||
@ -228,6 +228,7 @@ GEM
 | 
				
			|||||||
    idn-ruby (0.1.0)
 | 
					    idn-ruby (0.1.0)
 | 
				
			||||||
    ipaddress (0.8.3)
 | 
					    ipaddress (0.8.3)
 | 
				
			||||||
    iso-639 (0.2.8)
 | 
					    iso-639 (0.2.8)
 | 
				
			||||||
 | 
					    jmespath (1.3.1)
 | 
				
			||||||
    json (2.1.0)
 | 
					    json (2.1.0)
 | 
				
			||||||
    json-ld (2.1.7)
 | 
					    json-ld (2.1.7)
 | 
				
			||||||
      multi_json (~> 1.12)
 | 
					      multi_json (~> 1.12)
 | 
				
			||||||
@ -324,6 +325,7 @@ GEM
 | 
				
			|||||||
    pghero (1.7.0)
 | 
					    pghero (1.7.0)
 | 
				
			||||||
      activerecord
 | 
					      activerecord
 | 
				
			||||||
    pkg-config (1.2.8)
 | 
					    pkg-config (1.2.8)
 | 
				
			||||||
 | 
					    posix-spawn (0.3.13)
 | 
				
			||||||
    powerpack (0.1.1)
 | 
					    powerpack (0.1.1)
 | 
				
			||||||
    pry (0.11.3)
 | 
					    pry (0.11.3)
 | 
				
			||||||
      coderay (~> 1.1.0)
 | 
					      coderay (~> 1.1.0)
 | 
				
			||||||
@ -544,6 +546,7 @@ DEPENDENCIES
 | 
				
			|||||||
  active_record_query_trace (~> 1.5)
 | 
					  active_record_query_trace (~> 1.5)
 | 
				
			||||||
  addressable (~> 2.5)
 | 
					  addressable (~> 2.5)
 | 
				
			||||||
  annotate (~> 2.7)
 | 
					  annotate (~> 2.7)
 | 
				
			||||||
 | 
					  aws-sdk (~> 2.10)
 | 
				
			||||||
  better_errors (~> 2.4)
 | 
					  better_errors (~> 2.4)
 | 
				
			||||||
  binding_of_caller (~> 0.7)
 | 
					  binding_of_caller (~> 0.7)
 | 
				
			||||||
  bootsnap
 | 
					  bootsnap
 | 
				
			||||||
@ -566,7 +569,6 @@ DEPENDENCIES
 | 
				
			|||||||
  fabrication (~> 2.18)
 | 
					  fabrication (~> 2.18)
 | 
				
			||||||
  faker (~> 1.7)
 | 
					  faker (~> 1.7)
 | 
				
			||||||
  fast_blank (~> 1.0)
 | 
					  fast_blank (~> 1.0)
 | 
				
			||||||
  fog-aws (~> 1.4)
 | 
					 | 
				
			||||||
  fog-core (~> 1.45)
 | 
					  fog-core (~> 1.45)
 | 
				
			||||||
  fog-local (~> 0.4)
 | 
					  fog-local (~> 0.4)
 | 
				
			||||||
  fog-openstack (~> 0.1)
 | 
					  fog-openstack (~> 0.1)
 | 
				
			||||||
@ -601,6 +603,7 @@ DEPENDENCIES
 | 
				
			|||||||
  pg (~> 0.20)
 | 
					  pg (~> 0.20)
 | 
				
			||||||
  pghero (~> 1.7)
 | 
					  pghero (~> 1.7)
 | 
				
			||||||
  pkg-config (~> 1.2)
 | 
					  pkg-config (~> 1.2)
 | 
				
			||||||
 | 
					  posix-spawn
 | 
				
			||||||
  pry-rails (~> 0.3)
 | 
					  pry-rails (~> 0.3)
 | 
				
			||||||
  puma (~> 3.10)
 | 
					  puma (~> 3.10)
 | 
				
			||||||
  pundit (~> 1.1)
 | 
					  pundit (~> 1.1)
 | 
				
			||||||
 | 
				
			|||||||
@ -89,7 +89,8 @@ module Admin
 | 
				
			|||||||
        :username,
 | 
					        :username,
 | 
				
			||||||
        :display_name,
 | 
					        :display_name,
 | 
				
			||||||
        :email,
 | 
					        :email,
 | 
				
			||||||
        :ip
 | 
					        :ip,
 | 
				
			||||||
 | 
					        :staff
 | 
				
			||||||
      )
 | 
					      )
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
				
			|||||||
@ -92,7 +92,9 @@ module Admin
 | 
				
			|||||||
    def filter_params
 | 
					    def filter_params
 | 
				
			||||||
      params.permit(
 | 
					      params.permit(
 | 
				
			||||||
        :local,
 | 
					        :local,
 | 
				
			||||||
        :remote
 | 
					        :remote,
 | 
				
			||||||
 | 
					        :by_domain,
 | 
				
			||||||
 | 
					        :shortcode
 | 
				
			||||||
      )
 | 
					      )
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
				
			|||||||
@ -72,19 +72,4 @@ class Api::BaseController < ApplicationController
 | 
				
			|||||||
  def render_empty
 | 
					  def render_empty
 | 
				
			||||||
    render json: {}, status: 200
 | 
					    render json: {}, status: 200
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					 | 
				
			||||||
  def set_maps(statuses) # rubocop:disable Style/AccessorMethodName
 | 
					 | 
				
			||||||
    if current_account.nil?
 | 
					 | 
				
			||||||
      @reblogs_map    = {}
 | 
					 | 
				
			||||||
      @favourites_map = {}
 | 
					 | 
				
			||||||
      @mutes_map      = {}
 | 
					 | 
				
			||||||
      return
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    status_ids       = statuses.compact.flat_map { |s| [s.id, s.reblog_of_id] }.uniq
 | 
					 | 
				
			||||||
    conversation_ids = statuses.compact.map(&:conversation_id).compact.uniq
 | 
					 | 
				
			||||||
    @reblogs_map     = Status.reblogs_map(status_ids, current_account)
 | 
					 | 
				
			||||||
    @favourites_map  = Status.favourites_map(status_ids, current_account)
 | 
					 | 
				
			||||||
    @mutes_map       = Status.mutes_map(conversation_ids, current_account)
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										20
									
								
								app/controllers/api/v1/accounts/lists_controller.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								app/controllers/api/v1/accounts/lists_controller.rb
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					# frozen_string_literal: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Api::V1::Accounts::ListsController < Api::BaseController
 | 
				
			||||||
 | 
					  before_action -> { doorkeeper_authorize! :read }
 | 
				
			||||||
 | 
					  before_action :require_user!
 | 
				
			||||||
 | 
					  before_action :set_account
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  respond_to :json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def index
 | 
				
			||||||
 | 
					    @lists = @account.lists.where(account: current_account)
 | 
				
			||||||
 | 
					    render json: @lists, each_serializer: REST::ListSerializer
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def set_account
 | 
				
			||||||
 | 
					    @account = Account.find(params[:account_id])
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
@ -1,18 +1,14 @@
 | 
				
			|||||||
# frozen_string_literal: true
 | 
					# frozen_string_literal: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Api::V1::ListsController < Api::BaseController
 | 
					class Api::V1::ListsController < Api::BaseController
 | 
				
			||||||
  LISTS_LIMIT = 50
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  before_action -> { doorkeeper_authorize! :read },    only: [:index, :show]
 | 
					  before_action -> { doorkeeper_authorize! :read },    only: [:index, :show]
 | 
				
			||||||
  before_action -> { doorkeeper_authorize! :write }, except: [:index, :show]
 | 
					  before_action -> { doorkeeper_authorize! :write }, except: [:index, :show]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  before_action :require_user!
 | 
					  before_action :require_user!
 | 
				
			||||||
  before_action :set_list, except: [:index, :create]
 | 
					  before_action :set_list, except: [:index, :create]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  after_action :insert_pagination_headers, only: :index
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def index
 | 
					  def index
 | 
				
			||||||
    @lists = List.where(account: current_account).paginate_by_max_id(limit_param(LISTS_LIMIT), params[:max_id], params[:since_id])
 | 
					    @lists = List.where(account: current_account).all
 | 
				
			||||||
    render json: @lists, each_serializer: REST::ListSerializer
 | 
					    render json: @lists, each_serializer: REST::ListSerializer
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -44,36 +40,4 @@ class Api::V1::ListsController < Api::BaseController
 | 
				
			|||||||
  def list_params
 | 
					  def list_params
 | 
				
			||||||
    params.permit(:title)
 | 
					    params.permit(:title)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					 | 
				
			||||||
  def insert_pagination_headers
 | 
					 | 
				
			||||||
    set_pagination_headers(next_path, prev_path)
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def next_path
 | 
					 | 
				
			||||||
    if records_continue?
 | 
					 | 
				
			||||||
      api_v1_lists_url pagination_params(max_id: pagination_max_id)
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def prev_path
 | 
					 | 
				
			||||||
    unless @lists.empty?
 | 
					 | 
				
			||||||
      api_v1_lists_url pagination_params(since_id: pagination_since_id)
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def pagination_max_id
 | 
					 | 
				
			||||||
    @lists.last.id
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def pagination_since_id
 | 
					 | 
				
			||||||
    @lists.first.id
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def records_continue?
 | 
					 | 
				
			||||||
    @lists.size == limit_param(LISTS_LIMIT)
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def pagination_params(core_params)
 | 
					 | 
				
			||||||
    params.permit(:limit).merge(core_params)
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
@ -28,6 +28,8 @@ class Api::Web::PushSubscriptionsController < Api::BaseController
 | 
				
			|||||||
      },
 | 
					      },
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    data.deep_merge!(params[:data]) if params[:data]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    web_subscription = ::Web::PushSubscription.create!(
 | 
					    web_subscription = ::Web::PushSubscription.create!(
 | 
				
			||||||
      endpoint: params[:subscription][:endpoint],
 | 
					      endpoint: params[:subscription][:endpoint],
 | 
				
			||||||
      key_p256dh: params[:subscription][:keys][:p256dh],
 | 
					      key_p256dh: params[:subscription][:keys][:p256dh],
 | 
				
			||||||
 | 
				
			|||||||
@ -62,6 +62,7 @@ class ApplicationController < ActionController::Base
 | 
				
			|||||||
      pack: pack_name,
 | 
					      pack: pack_name,
 | 
				
			||||||
      preload: nil,
 | 
					      preload: nil,
 | 
				
			||||||
      skin: nil,
 | 
					      skin: nil,
 | 
				
			||||||
 | 
					      supported_locales: data['locales'],
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if data['pack'][pack_name].is_a?(Hash)
 | 
					    if data['pack'][pack_name].is_a?(Hash)
 | 
				
			||||||
      pack_data[:common] = nil if data['pack'][pack_name]['use_common'] == false
 | 
					      pack_data[:common] = nil if data['pack'][pack_name]['use_common'] == false
 | 
				
			||||||
@ -93,6 +94,7 @@ class ApplicationController < ActionController::Base
 | 
				
			|||||||
      pack: nil,
 | 
					      pack: nil,
 | 
				
			||||||
      preload: nil,
 | 
					      preload: nil,
 | 
				
			||||||
      skin: nil,
 | 
					      skin: nil,
 | 
				
			||||||
 | 
					      supported_locales: data['locales'],
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -44,7 +44,8 @@ module RateLimitHeaders
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def api_throttle_data
 | 
					  def api_throttle_data
 | 
				
			||||||
    request.env['rack.attack.throttle_data']['api']
 | 
					    most_limited_type, = request.env['rack.attack.throttle_data'].min_by { |_, v| v[:limit] }
 | 
				
			||||||
 | 
					    request.env['rack.attack.throttle_data'][most_limited_type]
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def request_time
 | 
					  def request_time
 | 
				
			||||||
 | 
				
			|||||||
@ -5,6 +5,7 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  before_action :store_current_location
 | 
					  before_action :store_current_location
 | 
				
			||||||
  before_action :authenticate_resource_owner!
 | 
					  before_action :authenticate_resource_owner!
 | 
				
			||||||
 | 
					  before_action :set_pack
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  include Localized
 | 
					  include Localized
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -13,4 +14,8 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
 | 
				
			|||||||
  def store_current_location
 | 
					  def store_current_location
 | 
				
			||||||
    store_location_for(:user, request.url)
 | 
					    store_location_for(:user, request.url)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def set_pack
 | 
				
			||||||
 | 
					    use_pack 'auth'
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
@ -5,6 +5,7 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  before_action :store_current_location
 | 
					  before_action :store_current_location
 | 
				
			||||||
  before_action :authenticate_resource_owner!
 | 
					  before_action :authenticate_resource_owner!
 | 
				
			||||||
 | 
					  before_action :set_pack
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  include Localized
 | 
					  include Localized
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -13,4 +14,8 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio
 | 
				
			|||||||
  def store_current_location
 | 
					  def store_current_location
 | 
				
			||||||
    store_location_for(:user, request.url)
 | 
					    store_location_for(:user, request.url)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def set_pack
 | 
				
			||||||
 | 
					    use_pack 'settings'
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										35
									
								
								app/controllers/settings/flavours_controller.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								app/controllers/settings/flavours_controller.rb
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					# frozen_string_literal: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Settings::FlavoursController < Settings::BaseController
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def index
 | 
				
			||||||
 | 
					    redirect_to action: 'show', flavour: current_flavour
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def show
 | 
				
			||||||
 | 
					    unless Themes.instance.flavours.include?(params[:flavour]) or params[:flavour] == current_flavour
 | 
				
			||||||
 | 
					      redirect_to action: 'show', flavour: current_flavour
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @listing = Themes.instance.flavours
 | 
				
			||||||
 | 
					    @selected = params[:flavour]
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def update
 | 
				
			||||||
 | 
					    user_settings.update(user_settings_params(params[:flavour]).to_h)
 | 
				
			||||||
 | 
					    redirect_to action: 'show', flavour: params[:flavour]
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def user_settings
 | 
				
			||||||
 | 
					    UserSettingsDecorator.new(current_user)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def user_settings_params(flavour)
 | 
				
			||||||
 | 
					    params.require(:user).merge({ setting_flavour: flavour }).permit(
 | 
				
			||||||
 | 
					      :setting_flavour,
 | 
				
			||||||
 | 
					      :setting_skin
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
@ -28,6 +28,7 @@ class Settings::MigrationsController < ApplicationController
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def migration_account_changed?
 | 
					  def migration_account_changed?
 | 
				
			||||||
    current_account.moved_to_account_id != @migration.account&.id
 | 
					    current_account.moved_to_account_id != @migration.account&.id &&
 | 
				
			||||||
 | 
					      current_account.id != @migration.account&.id
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
@ -33,13 +33,12 @@ class Settings::PreferencesController < Settings::BaseController
 | 
				
			|||||||
      :setting_default_sensitive,
 | 
					      :setting_default_sensitive,
 | 
				
			||||||
      :setting_unfollow_modal,
 | 
					      :setting_unfollow_modal,
 | 
				
			||||||
      :setting_boost_modal,
 | 
					      :setting_boost_modal,
 | 
				
			||||||
 | 
					      :setting_favourite_modal,
 | 
				
			||||||
      :setting_delete_modal,
 | 
					      :setting_delete_modal,
 | 
				
			||||||
      :setting_auto_play_gif,
 | 
					      :setting_auto_play_gif,
 | 
				
			||||||
      :setting_reduce_motion,
 | 
					      :setting_reduce_motion,
 | 
				
			||||||
      :setting_system_font_ui,
 | 
					      :setting_system_font_ui,
 | 
				
			||||||
      :setting_noindex,
 | 
					      :setting_noindex,
 | 
				
			||||||
      :setting_flavour,
 | 
					 | 
				
			||||||
      :setting_skin,
 | 
					 | 
				
			||||||
      notification_emails: %i(follow follow_request reblog favourite mention digest),
 | 
					      notification_emails: %i(follow follow_request reblog favourite mention digest),
 | 
				
			||||||
      interactions: %i(must_be_follower must_be_following)
 | 
					      interactions: %i(must_be_follower must_be_following)
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
				
			|||||||
@ -1,11 +1,12 @@
 | 
				
			|||||||
# frozen_string_literal: true
 | 
					# frozen_string_literal: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module Admin::FilterHelper
 | 
					module Admin::FilterHelper
 | 
				
			||||||
  ACCOUNT_FILTERS = %i(local remote by_domain silenced suspended recent username display_name email ip).freeze
 | 
					  ACCOUNT_FILTERS      = %i(local remote by_domain silenced suspended recent username display_name email ip staff).freeze
 | 
				
			||||||
  REPORT_FILTERS = %i(resolved account_id target_account_id).freeze
 | 
					  REPORT_FILTERS       = %i(resolved account_id target_account_id).freeze
 | 
				
			||||||
  INVITE_FILTER = %i(available expired).freeze
 | 
					  INVITE_FILTER        = %i(available expired).freeze
 | 
				
			||||||
 | 
					  CUSTOM_EMOJI_FILTERS = %i(local remote by_domain shortcode).freeze
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  FILTERS = ACCOUNT_FILTERS + REPORT_FILTERS + INVITE_FILTER
 | 
					  FILTERS = ACCOUNT_FILTERS + REPORT_FILTERS + INVITE_FILTER + CUSTOM_EMOJI_FILTERS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def filter_link_to(text, link_to_params, link_class_params = link_to_params)
 | 
					  def filter_link_to(text, link_to_params, link_class_params = link_to_params)
 | 
				
			||||||
    new_url = filtered_url_for(link_to_params)
 | 
					    new_url = filtered_url_for(link_to_params)
 | 
				
			||||||
 | 
				
			|||||||
@ -10,6 +10,7 @@ module SettingsHelper
 | 
				
			|||||||
    eo: 'Esperanto',
 | 
					    eo: 'Esperanto',
 | 
				
			||||||
    es: 'Español',
 | 
					    es: 'Español',
 | 
				
			||||||
    fa: 'فارسی',
 | 
					    fa: 'فارسی',
 | 
				
			||||||
 | 
					    gl: 'Galego',
 | 
				
			||||||
    fi: 'Suomi',
 | 
					    fi: 'Suomi',
 | 
				
			||||||
    fr: 'Français',
 | 
					    fr: 'Français',
 | 
				
			||||||
    he: 'עברית',
 | 
					    he: 'עברית',
 | 
				
			||||||
 | 
				
			|||||||
@ -37,7 +37,3 @@ delegate(document, '#account_header', 'change', ({ target }) => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  header.style.backgroundImage = `url(${url})`;
 | 
					  header.style.backgroundImage = `url(${url})`;
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					 | 
				
			||||||
delegate(document, '#user_setting_flavour, #user_setting_skin', 'change', ({ target }) => {
 | 
					 | 
				
			||||||
  target.form.submit();
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -58,6 +58,7 @@ export default class Status extends ImmutablePureComponent {
 | 
				
			|||||||
    'settings',
 | 
					    'settings',
 | 
				
			||||||
    'prepend',
 | 
					    'prepend',
 | 
				
			||||||
    'boostModal',
 | 
					    'boostModal',
 | 
				
			||||||
 | 
					    'favouriteModal',
 | 
				
			||||||
    'muted',
 | 
					    'muted',
 | 
				
			||||||
    'collapse',
 | 
					    'collapse',
 | 
				
			||||||
    'notification',
 | 
					    'notification',
 | 
				
			||||||
@ -204,8 +205,8 @@ export default class Status extends ImmutablePureComponent {
 | 
				
			|||||||
    this.props.onReply(this.props.status, this.context.router.history);
 | 
					    this.props.onReply(this.props.status, this.context.router.history);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  handleHotkeyFavourite = () => {
 | 
					  handleHotkeyFavourite = (e) => {
 | 
				
			||||||
    this.props.onFavourite(this.props.status);
 | 
					    this.props.onFavourite(this.props.status, e);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  handleHotkeyBoost = e => {
 | 
					  handleHotkeyBoost = e => {
 | 
				
			||||||
 | 
				
			|||||||
@ -71,8 +71,8 @@ export default class StatusActionBar extends ImmutablePureComponent {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  handleFavouriteClick = () => {
 | 
					  handleFavouriteClick = (e) => {
 | 
				
			||||||
    this.props.onFavourite(this.props.status);
 | 
					    this.props.onFavourite(this.props.status, e);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  handleReblogClick = (e) => {
 | 
					  handleReblogClick = (e) => {
 | 
				
			||||||
 | 
				
			|||||||
@ -20,7 +20,7 @@ import { initMuteModal } from 'flavours/glitch/actions/mutes';
 | 
				
			|||||||
import { initReport } from 'flavours/glitch/actions/reports';
 | 
					import { initReport } from 'flavours/glitch/actions/reports';
 | 
				
			||||||
import { openModal } from 'flavours/glitch/actions/modal';
 | 
					import { openModal } from 'flavours/glitch/actions/modal';
 | 
				
			||||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 | 
					import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 | 
				
			||||||
import { boostModal, deleteModal } from 'flavours/glitch/util/initial_state';
 | 
					import { boostModal, favouriteModal, deleteModal } from 'flavours/glitch/util/initial_state';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const messages = defineMessages({
 | 
					const messages = defineMessages({
 | 
				
			||||||
  deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
 | 
					  deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
 | 
				
			||||||
@ -78,11 +78,19 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  onFavourite (status) {
 | 
					  onModalFavourite (status) {
 | 
				
			||||||
 | 
					    dispatch(favourite(status));
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  onFavourite (status, e) {
 | 
				
			||||||
    if (status.get('favourited')) {
 | 
					    if (status.get('favourited')) {
 | 
				
			||||||
      dispatch(unfavourite(status));
 | 
					      dispatch(unfavourite(status));
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      dispatch(favourite(status));
 | 
					      if (e.shiftKey || !favouriteModal) {
 | 
				
			||||||
 | 
					        this.onModalFavourite(status);
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        dispatch(openModal('FAVOURITE', { status, onFavourite: this.onModalFavourite }));
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -48,8 +48,8 @@ export default class ActionBar extends React.PureComponent {
 | 
				
			|||||||
    this.props.onReblog(this.props.status, e);
 | 
					    this.props.onReblog(this.props.status, e);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  handleFavouriteClick = () => {
 | 
					  handleFavouriteClick = (e) => {
 | 
				
			||||||
    this.props.onFavourite(this.props.status);
 | 
					    this.props.onFavourite(this.props.status, e);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  handleDeleteClick = () => {
 | 
					  handleDeleteClick = () => {
 | 
				
			||||||
 | 
				
			|||||||
@ -30,7 +30,7 @@ import { openModal } from 'flavours/glitch/actions/modal';
 | 
				
			|||||||
import { defineMessages, injectIntl } from 'react-intl';
 | 
					import { defineMessages, injectIntl } from 'react-intl';
 | 
				
			||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
 | 
					import ImmutablePureComponent from 'react-immutable-pure-component';
 | 
				
			||||||
import { HotKeys } from 'react-hotkeys';
 | 
					import { HotKeys } from 'react-hotkeys';
 | 
				
			||||||
import { boostModal, deleteModal } from 'flavours/glitch/util/initial_state';
 | 
					import { boostModal, favouriteModal, deleteModal } from 'flavours/glitch/util/initial_state';
 | 
				
			||||||
import { attachFullscreenListener, detachFullscreenListener, isFullscreen } from 'flavours/glitch/util/fullscreen';
 | 
					import { attachFullscreenListener, detachFullscreenListener, isFullscreen } from 'flavours/glitch/util/fullscreen';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const messages = defineMessages({
 | 
					const messages = defineMessages({
 | 
				
			||||||
@ -95,11 +95,19 @@ export default class Status extends ImmutablePureComponent {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  handleFavouriteClick = (status) => {
 | 
					  handleModalFavourite = (status) => {
 | 
				
			||||||
 | 
					    this.props.dispatch(favourite(status));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  handleFavouriteClick = (status, e) => {
 | 
				
			||||||
    if (status.get('favourited')) {
 | 
					    if (status.get('favourited')) {
 | 
				
			||||||
      this.props.dispatch(unfavourite(status));
 | 
					      this.props.dispatch(unfavourite(status));
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      this.props.dispatch(favourite(status));
 | 
					      if (e.shiftKey || !favouriteModal) {
 | 
				
			||||||
 | 
					        this.handleModalFavourite(status);
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        this.props.dispatch(openModal('FAVOURITE', { status, onFavourite: this.handleModalFavourite }));
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,84 @@
 | 
				
			|||||||
 | 
					import React from 'react';
 | 
				
			||||||
 | 
					import ImmutablePropTypes from 'react-immutable-proptypes';
 | 
				
			||||||
 | 
					import PropTypes from 'prop-types';
 | 
				
			||||||
 | 
					import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 | 
				
			||||||
 | 
					import Button from 'flavours/glitch/components/button';
 | 
				
			||||||
 | 
					import StatusContent from 'flavours/glitch/components/status_content';
 | 
				
			||||||
 | 
					import Avatar from 'flavours/glitch/components/avatar';
 | 
				
			||||||
 | 
					import RelativeTimestamp from 'flavours/glitch/components/relative_timestamp';
 | 
				
			||||||
 | 
					import DisplayName from 'flavours/glitch/components/display_name';
 | 
				
			||||||
 | 
					import ImmutablePureComponent from 'react-immutable-pure-component';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messages = defineMessages({
 | 
				
			||||||
 | 
					  favourite: { id: 'status.favourite', defaultMessage: 'Favourite' },
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@injectIntl
 | 
				
			||||||
 | 
					export default class FavouriteModal extends ImmutablePureComponent {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static contextTypes = {
 | 
				
			||||||
 | 
					    router: PropTypes.object,
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static propTypes = {
 | 
				
			||||||
 | 
					    status: ImmutablePropTypes.map.isRequired,
 | 
				
			||||||
 | 
					    onFavourite: PropTypes.func.isRequired,
 | 
				
			||||||
 | 
					    onClose: PropTypes.func.isRequired,
 | 
				
			||||||
 | 
					    intl: PropTypes.object.isRequired,
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  componentDidMount() {
 | 
				
			||||||
 | 
					    this.button.focus();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  handleFavourite = () => {
 | 
				
			||||||
 | 
					    this.props.onFavourite(this.props.status);
 | 
				
			||||||
 | 
					    this.props.onClose();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  handleAccountClick = (e) => {
 | 
				
			||||||
 | 
					    if (e.button === 0) {
 | 
				
			||||||
 | 
					      e.preventDefault();
 | 
				
			||||||
 | 
					      this.props.onClose();
 | 
				
			||||||
 | 
					      this.context.router.history.push(`/accounts/${this.props.status.getIn(['account', 'id'])}`);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  setRef = (c) => {
 | 
				
			||||||
 | 
					    this.button = c;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  render () {
 | 
				
			||||||
 | 
					    const { status, intl } = this.props;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					      <div className='modal-root__modal favourite-modal'>
 | 
				
			||||||
 | 
					        <div className='favourite-modal__container'>
 | 
				
			||||||
 | 
					          <div className='status light'>
 | 
				
			||||||
 | 
					            <div className='favourite-modal__status-header'>
 | 
				
			||||||
 | 
					              <div className='favourite-modal__status-time'>
 | 
				
			||||||
 | 
					                <a href={status.get('url')} className='status__relative-time' target='_blank' rel='noopener'><RelativeTimestamp timestamp={status.get('created_at')} /></a>
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					              <a onClick={this.handleAccountClick} href={status.getIn(['account', 'url'])} className='status__display-name'>
 | 
				
			||||||
 | 
					                <div className='status__avatar'>
 | 
				
			||||||
 | 
					                  <Avatar account={status.get('account')} size={48} />
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                <DisplayName account={status.get('account')} />
 | 
				
			||||||
 | 
					              </a>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <StatusContent status={status} />
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <div className='favourite-modal__action-bar'>
 | 
				
			||||||
 | 
					          <div><FormattedMessage id='favourite_modal.combo' defaultMessage='You can press {combo} to skip this next time' values={{ combo: <span>Shift + <i className='fa fa-star' /></span> }} /></div>
 | 
				
			||||||
 | 
					          <Button text={intl.formatMessage(messages.favourite)} onClick={this.handleFavourite} ref={this.setRef} />
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -7,6 +7,7 @@ import ActionsModal from './actions_modal';
 | 
				
			|||||||
import MediaModal from './media_modal';
 | 
					import MediaModal from './media_modal';
 | 
				
			||||||
import VideoModal from './video_modal';
 | 
					import VideoModal from './video_modal';
 | 
				
			||||||
import BoostModal from './boost_modal';
 | 
					import BoostModal from './boost_modal';
 | 
				
			||||||
 | 
					import FavouriteModal from './favourite_modal';
 | 
				
			||||||
import DoodleModal from './doodle_modal';
 | 
					import DoodleModal from './doodle_modal';
 | 
				
			||||||
import ConfirmationModal from './confirmation_modal';
 | 
					import ConfirmationModal from './confirmation_modal';
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
@ -23,6 +24,7 @@ const MODAL_COMPONENTS = {
 | 
				
			|||||||
  'ONBOARDING': OnboardingModal,
 | 
					  'ONBOARDING': OnboardingModal,
 | 
				
			||||||
  'VIDEO': () => Promise.resolve({ default: VideoModal }),
 | 
					  'VIDEO': () => Promise.resolve({ default: VideoModal }),
 | 
				
			||||||
  'BOOST': () => Promise.resolve({ default: BoostModal }),
 | 
					  'BOOST': () => Promise.resolve({ default: BoostModal }),
 | 
				
			||||||
 | 
					  'FAVOURITE': () => Promise.resolve({ default: FavouriteModal }),
 | 
				
			||||||
  'DOODLE': () => Promise.resolve({ default: DoodleModal }),
 | 
					  'DOODLE': () => Promise.resolve({ default: DoodleModal }),
 | 
				
			||||||
  'CONFIRM': () => Promise.resolve({ default: ConfirmationModal }),
 | 
					  'CONFIRM': () => Promise.resolve({ default: ConfirmationModal }),
 | 
				
			||||||
  'MUTE': MuteModal,
 | 
					  'MUTE': MuteModal,
 | 
				
			||||||
@ -92,7 +94,7 @@ export default class ModalRoot extends React.PureComponent {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  renderLoading = modalId => () => {
 | 
					  renderLoading = modalId => () => {
 | 
				
			||||||
    return ['MEDIA', 'VIDEO', 'BOOST', 'DOODLE', 'CONFIRM', 'ACTIONS'].indexOf(modalId) === -1 ? <ModalLoading /> : null;
 | 
					    return ['MEDIA', 'VIDEO', 'BOOST', 'FAVOURITE', 'DOODLE', 'CONFIRM', 'ACTIONS'].indexOf(modalId) === -1 ? <ModalLoading /> : null;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  renderError = (props) => {
 | 
					  renderError = (props) => {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										
											BIN
										
									
								
								app/javascript/flavours/glitch/images/glitch-preview.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/javascript/flavours/glitch/images/glitch-preview.jpg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 193 KiB  | 
							
								
								
									
										7
									
								
								app/javascript/flavours/glitch/locales/ar.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/javascript/flavours/glitch/locales/ar.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					import inherited from 'mastodon/locales/ar.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messages = {
 | 
				
			||||||
 | 
					  //  No translations available.
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Object.assign({}, inherited, messages);
 | 
				
			||||||
							
								
								
									
										7
									
								
								app/javascript/flavours/glitch/locales/bg.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/javascript/flavours/glitch/locales/bg.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					import inherited from 'mastodon/locales/bg.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messages = {
 | 
				
			||||||
 | 
					  //  No translations available.
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Object.assign({}, inherited, messages);
 | 
				
			||||||
							
								
								
									
										7
									
								
								app/javascript/flavours/glitch/locales/ca.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/javascript/flavours/glitch/locales/ca.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					import inherited from 'mastodon/locales/ca.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messages = {
 | 
				
			||||||
 | 
					  //  No translations available.
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Object.assign({}, inherited, messages);
 | 
				
			||||||
							
								
								
									
										7
									
								
								app/javascript/flavours/glitch/locales/de.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/javascript/flavours/glitch/locales/de.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					import inherited from 'mastodon/locales/de.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messages = {
 | 
				
			||||||
 | 
					  //  No translations available.
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Object.assign({}, inherited, messages);
 | 
				
			||||||
							
								
								
									
										52
									
								
								app/javascript/flavours/glitch/locales/en.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								app/javascript/flavours/glitch/locales/en.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,52 @@
 | 
				
			|||||||
 | 
					import inherited from 'mastodon/locales/en.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messages = {
 | 
				
			||||||
 | 
					  'getting_started.open_source_notice': 'Glitchsoc is free open source software forked from {Mastodon}. You can contribute or report issues on GitHub at {github}.',
 | 
				
			||||||
 | 
					  'layout.auto': 'Auto',
 | 
				
			||||||
 | 
					  'layout.current_is': 'Your current layout is:',
 | 
				
			||||||
 | 
					  'layout.desktop': 'Desktop',
 | 
				
			||||||
 | 
					  'layout.mobile': 'Mobile',
 | 
				
			||||||
 | 
					  'navigation_bar.app_settings': 'App settings',
 | 
				
			||||||
 | 
					  'getting_started.onboarding': 'Show me around',
 | 
				
			||||||
 | 
					  'onboarding.page_one.federation': '{domain} is an \'instance\' of Mastodon. Mastodon is a network of independent servers joining up to make one larger social network. We call these servers instances.',
 | 
				
			||||||
 | 
					  'onboarding.page_one.welcome': 'Welcome to {domain}!',
 | 
				
			||||||
 | 
					  'onboarding.page_six.github': '{domain} runs on Glitchsoc. Glitchsoc is a friendly {fork} of {Mastodon}, and is compatible with any Mastodon instance or app. Glitchsoc is entirely free and open-source. You can report bugs, request features, or contribute to the code on {github}.',
 | 
				
			||||||
 | 
					  'settings.auto_collapse': 'Automatic collapsing',
 | 
				
			||||||
 | 
					  'settings.auto_collapse_all': 'Everything',
 | 
				
			||||||
 | 
					  'settings.auto_collapse_lengthy': 'Lengthy toots',
 | 
				
			||||||
 | 
					  'settings.auto_collapse_media': 'Toots with media',
 | 
				
			||||||
 | 
					  'settings.auto_collapse_notifications': 'Notifications',
 | 
				
			||||||
 | 
					  'settings.auto_collapse_reblogs': 'Boosts',
 | 
				
			||||||
 | 
					  'settings.auto_collapse_replies': 'Replies',
 | 
				
			||||||
 | 
					  'settings.close': 'Close',
 | 
				
			||||||
 | 
					  'settings.collapsed_statuses': 'Collapsed toots',
 | 
				
			||||||
 | 
					  'settings.enable_collapsed': 'Enable collapsed toots',
 | 
				
			||||||
 | 
					  'settings.general': 'General',
 | 
				
			||||||
 | 
					  'settings.image_backgrounds': 'Image backgrounds',
 | 
				
			||||||
 | 
					  'settings.image_backgrounds_media': 'Preview collapsed toot media',
 | 
				
			||||||
 | 
					  'settings.image_backgrounds_users': 'Give collapsed toots an image background',
 | 
				
			||||||
 | 
					  'settings.media': 'Media',
 | 
				
			||||||
 | 
					  'settings.media_letterbox': 'Letterbox media',
 | 
				
			||||||
 | 
					  'settings.media_fullwidth': 'Full-width media previews',
 | 
				
			||||||
 | 
					  'settings.preferences': 'User preferences',
 | 
				
			||||||
 | 
					  'settings.wide_view': 'Wide view (Desktop mode only)',
 | 
				
			||||||
 | 
					  'settings.navbar_under': 'Navbar at the bottom (Mobile only)',
 | 
				
			||||||
 | 
					  'status.collapse': 'Collapse',
 | 
				
			||||||
 | 
					  'status.uncollapse': 'Uncollapse',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  'favourite_modal.combo': 'You can press {combo} to skip this next time',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  'home.column_settings.show_direct': 'Show DMs',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  'notification.markForDeletion': 'Mark for deletion',
 | 
				
			||||||
 | 
					  'notifications.clear': 'Clear all my notifications',
 | 
				
			||||||
 | 
					  'notifications.marked_clear_confirmation': 'Are you sure you want to permanently clear all selected notifications?',
 | 
				
			||||||
 | 
					  'notifications.marked_clear': 'Clear selected notifications',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  'notification_purge.btn_all': 'Select\nall',
 | 
				
			||||||
 | 
					  'notification_purge.btn_none': 'Select\nnone',
 | 
				
			||||||
 | 
					  'notification_purge.btn_invert': 'Invert\nselection',
 | 
				
			||||||
 | 
					  'notification_purge.btn_apply': 'Clear\nselected',
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Object.assign({}, inherited, messages);
 | 
				
			||||||
							
								
								
									
										7
									
								
								app/javascript/flavours/glitch/locales/eo.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/javascript/flavours/glitch/locales/eo.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					import inherited from 'mastodon/locales/eo.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messages = {
 | 
				
			||||||
 | 
					  //  No translations available.
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Object.assign({}, inherited, messages);
 | 
				
			||||||
							
								
								
									
										7
									
								
								app/javascript/flavours/glitch/locales/es.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/javascript/flavours/glitch/locales/es.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					import inherited from 'mastodon/locales/es.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messages = {
 | 
				
			||||||
 | 
					  //  No translations available.
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Object.assign({}, inherited, messages);
 | 
				
			||||||
							
								
								
									
										7
									
								
								app/javascript/flavours/glitch/locales/fa.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/javascript/flavours/glitch/locales/fa.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					import inherited from 'mastodon/locales/fa.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messages = {
 | 
				
			||||||
 | 
					  //  No translations available.
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Object.assign({}, inherited, messages);
 | 
				
			||||||
							
								
								
									
										7
									
								
								app/javascript/flavours/glitch/locales/fi.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/javascript/flavours/glitch/locales/fi.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					import inherited from 'mastodon/locales/fi.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messages = {
 | 
				
			||||||
 | 
					  //  No translations available.
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Object.assign({}, inherited, messages);
 | 
				
			||||||
							
								
								
									
										7
									
								
								app/javascript/flavours/glitch/locales/fr.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/javascript/flavours/glitch/locales/fr.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					import inherited from 'mastodon/locales/fr.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messages = {
 | 
				
			||||||
 | 
					  //  No translations available.
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Object.assign({}, inherited, messages);
 | 
				
			||||||
							
								
								
									
										7
									
								
								app/javascript/flavours/glitch/locales/he.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/javascript/flavours/glitch/locales/he.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					import inherited from 'mastodon/locales/he.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messages = {
 | 
				
			||||||
 | 
					  //  No translations available.
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Object.assign({}, inherited, messages);
 | 
				
			||||||
							
								
								
									
										7
									
								
								app/javascript/flavours/glitch/locales/hr.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/javascript/flavours/glitch/locales/hr.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					import inherited from 'mastodon/locales/hr.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messages = {
 | 
				
			||||||
 | 
					  //  No translations available.
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Object.assign({}, inherited, messages);
 | 
				
			||||||
							
								
								
									
										7
									
								
								app/javascript/flavours/glitch/locales/hu.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/javascript/flavours/glitch/locales/hu.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					import inherited from 'mastodon/locales/hu.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messages = {
 | 
				
			||||||
 | 
					  //  No translations available.
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Object.assign({}, inherited, messages);
 | 
				
			||||||
							
								
								
									
										7
									
								
								app/javascript/flavours/glitch/locales/id.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/javascript/flavours/glitch/locales/id.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					import inherited from 'mastodon/locales/id.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messages = {
 | 
				
			||||||
 | 
					  //  No translations available.
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Object.assign({}, inherited, messages);
 | 
				
			||||||
							
								
								
									
										7
									
								
								app/javascript/flavours/glitch/locales/io.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/javascript/flavours/glitch/locales/io.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					import inherited from 'mastodon/locales/io.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messages = {
 | 
				
			||||||
 | 
					  //  No translations available.
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Object.assign({}, inherited, messages);
 | 
				
			||||||
							
								
								
									
										7
									
								
								app/javascript/flavours/glitch/locales/it.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/javascript/flavours/glitch/locales/it.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					import inherited from 'mastodon/locales/it.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messages = {
 | 
				
			||||||
 | 
					  //  No translations available.
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Object.assign({}, inherited, messages);
 | 
				
			||||||
							
								
								
									
										55
									
								
								app/javascript/flavours/glitch/locales/ja.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								app/javascript/flavours/glitch/locales/ja.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,55 @@
 | 
				
			|||||||
 | 
					import inherited from 'mastodon/locales/ja.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messages = {
 | 
				
			||||||
 | 
					  'getting_started.open_source_notice': 'Glitchsocは{Mastodon}によるフリーなオープンソースソフトウェアです。誰でもGitHub({github})から開発に參加したり、問題を報告したりできます。',
 | 
				
			||||||
 | 
					  'layout.auto': '自動',
 | 
				
			||||||
 | 
					  'layout.current_is': 'あなたの現在のレイアウト:',
 | 
				
			||||||
 | 
					  'layout.desktop': 'Desktop',
 | 
				
			||||||
 | 
					  'layout.mobile': 'Mobile',
 | 
				
			||||||
 | 
					  'navigation_bar.app_settings': 'アプリ設定',
 | 
				
			||||||
 | 
					  'getting_started.onboarding': '解説を表示',
 | 
				
			||||||
 | 
					  'onboarding.page_one.federation': '{domain}はMastodonのインスタンスです。Mastodonとは、独立したサーバが連携して作るソーシャルネットワークです。これらのサーバーをインスタンスと呼びます。',
 | 
				
			||||||
 | 
					  'onboarding.page_one.welcome': '{domain}へようこそ!',
 | 
				
			||||||
 | 
					  'onboarding.page_six.github': '{domain}はGlitchsocを使用しています。Glitchsocは{Mastodon}のフレンドリーな{fork}で、どんなMastodonアプリやインスタンスとも互換性があります。Glitchsocは完全に無料で、オープンソースです。{github}でバグ報告や機能要望あるいは貢獻をすることが可能です。',
 | 
				
			||||||
 | 
					  'settings.auto_collapse': '自動折りたたみ',
 | 
				
			||||||
 | 
					  'settings.auto_collapse_all': 'すべて',
 | 
				
			||||||
 | 
					  'settings.auto_collapse_lengthy': '長いトゥート',
 | 
				
			||||||
 | 
					  'settings.auto_collapse_media': 'メディア付きトゥート',
 | 
				
			||||||
 | 
					  'settings.auto_collapse_notifications': '通知',
 | 
				
			||||||
 | 
					  'settings.auto_collapse_reblogs': 'ブースト',
 | 
				
			||||||
 | 
					  'settings.auto_collapse_replies': '返信',
 | 
				
			||||||
 | 
					  'settings.close': '閉じる',
 | 
				
			||||||
 | 
					  'settings.collapsed_statuses': 'トゥート',
 | 
				
			||||||
 | 
					  'settings.enable_collapsed': 'トゥート折りたたみを有効にする',
 | 
				
			||||||
 | 
					  'settings.general': '一般',
 | 
				
			||||||
 | 
					  'settings.image_backgrounds': '画像背景',
 | 
				
			||||||
 | 
					  'settings.image_backgrounds_media': '折りたまれたメディア付きトゥートをプレビュー',
 | 
				
			||||||
 | 
					  'settings.image_backgrounds_users': '折りたまれたトゥートの背景を変更する',
 | 
				
			||||||
 | 
					  'settings.media': 'メディア',
 | 
				
			||||||
 | 
					  'settings.media_letterbox': 'メディアをレターボックス式で表示',
 | 
				
			||||||
 | 
					  'settings.media_fullwidth': '全幅メディアプレビュー',
 | 
				
			||||||
 | 
					  'settings.preferences': 'ユーザー設定',
 | 
				
			||||||
 | 
					  'settings.wide_view': 'ワイドビュー(Desktopレイアウトのみ)',
 | 
				
			||||||
 | 
					  'settings.navbar_under': 'ナビを画面下部に移動させる(Mobileレイアウトのみ)',
 | 
				
			||||||
 | 
					  'settings.compose_box_opts': 'コンポーズボックス設定',
 | 
				
			||||||
 | 
					  'settings.side_arm': 'セカンダリートゥートボタン',
 | 
				
			||||||
 | 
					  'settings.layout': 'レイアウト',
 | 
				
			||||||
 | 
					  'status.collapse': '折りたたむ',
 | 
				
			||||||
 | 
					  'status.uncollapse': '折りたたみを解除',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  'favourite_modal.combo': '次からは {combo} を押せば、これをスキップできます。',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  'home.column_settings.show_direct': 'DMを表示',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  'notification.markForDeletion': '選択',
 | 
				
			||||||
 | 
					  'notifications.clear': '通知を全てクリアする',
 | 
				
			||||||
 | 
					  'notifications.marked_clear_confirmation': '削除した全ての通知を完全に削除してもよろしいですか?',
 | 
				
			||||||
 | 
					  'notifications.marked_clear': '選択した通知を削除する',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  'notification_purge.btn_all': 'すべて\n選択',
 | 
				
			||||||
 | 
					  'notification_purge.btn_none': '選択\n解除',
 | 
				
			||||||
 | 
					  'notification_purge.btn_invert': '選択を\n反転',
 | 
				
			||||||
 | 
					  'notification_purge.btn_apply': '選択したものを\n削除',
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Object.assign({}, inherited, messages);
 | 
				
			||||||
							
								
								
									
										7
									
								
								app/javascript/flavours/glitch/locales/ko.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/javascript/flavours/glitch/locales/ko.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					import inherited from 'mastodon/locales/ko.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messages = {
 | 
				
			||||||
 | 
					  //  No translations available.
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Object.assign({}, inherited, messages);
 | 
				
			||||||
							
								
								
									
										7
									
								
								app/javascript/flavours/glitch/locales/nl.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/javascript/flavours/glitch/locales/nl.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					import inherited from 'mastodon/locales/nl.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messages = {
 | 
				
			||||||
 | 
					  //  No translations available.
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Object.assign({}, inherited, messages);
 | 
				
			||||||
							
								
								
									
										7
									
								
								app/javascript/flavours/glitch/locales/no.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/javascript/flavours/glitch/locales/no.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					import inherited from 'mastodon/locales/no.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messages = {
 | 
				
			||||||
 | 
					  //  No translations available.
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Object.assign({}, inherited, messages);
 | 
				
			||||||
							
								
								
									
										7
									
								
								app/javascript/flavours/glitch/locales/oc.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/javascript/flavours/glitch/locales/oc.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					import inherited from 'mastodon/locales/oc.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messages = {
 | 
				
			||||||
 | 
					  //  No translations available.
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Object.assign({}, inherited, messages);
 | 
				
			||||||
							
								
								
									
										48
									
								
								app/javascript/flavours/glitch/locales/pl.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								app/javascript/flavours/glitch/locales/pl.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,48 @@
 | 
				
			|||||||
 | 
					import inherited from 'mastodon/locales/pl.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messages = {
 | 
				
			||||||
 | 
					  'getting_started.open_source_notice': 'Glitchsoc jest wolnym i otwartoźródłowym forkiem oprogramowania {Mastodon}. Możesz współtworzyć projekt lub zgłaszać błędy na GitHubie pod adresem {github}.',
 | 
				
			||||||
 | 
					  'layout.auto': 'Automatyczny',
 | 
				
			||||||
 | 
					  'layout.current_is': 'Twój obecny układ to:',
 | 
				
			||||||
 | 
					  'layout.desktop': 'Desktopowy',
 | 
				
			||||||
 | 
					  'layout.mobile': 'Mobilny',
 | 
				
			||||||
 | 
					  'navigation_bar.app_settings': 'Ustawienia aplikacji',
 | 
				
			||||||
 | 
					  'getting_started.onboarding': 'Rozejrzyj się',
 | 
				
			||||||
 | 
					  'onboarding.page_one.federation': '{domain} jest \'instancją\' Mastodona. Mastodon to sieć działających niezależnie serwerów tworzących jedną sieć społecznościową. Te serwery nazywane są instancjami.',
 | 
				
			||||||
 | 
					  'onboarding.page_one.welcome': 'Witamy na {domain}!',
 | 
				
			||||||
 | 
					  'onboarding.page_six.github': '{domain} jest oparty na Glitchsoc. Glitchsoc jest {forkiem} {Mastodon}a kompatybilnym z każdym klientem i aplikacją Mastodona. Glitchsoc jest całkowicie wolnym i otwartoźródłowym oprogramowaniem. Możesz zgłaszać błędy i sugestie funkcji oraz współtworzyć projekt na {github}.',
 | 
				
			||||||
 | 
					  'settings.auto_collapse': 'Automatyczne zwijanie',
 | 
				
			||||||
 | 
					  'settings.auto_collapse_all': 'Wszystko',
 | 
				
			||||||
 | 
					  'settings.auto_collapse_lengthy': 'Długie wpisy',
 | 
				
			||||||
 | 
					  'settings.auto_collapse_media': 'Wpisy z zawartością multimedialną',
 | 
				
			||||||
 | 
					  'settings.auto_collapse_notifications': 'Powiadomienia',
 | 
				
			||||||
 | 
					  'settings.auto_collapse_reblogs': 'Podbicia',
 | 
				
			||||||
 | 
					  'settings.auto_collapse_replies': 'Odpowiedzi',
 | 
				
			||||||
 | 
					  'settings.close': 'Zamknij',
 | 
				
			||||||
 | 
					  'settings.collapsed_statuses': 'Zwijanie wpisów',
 | 
				
			||||||
 | 
					  'settings.enable_collapsed': 'Włącz zwijanie wpisów',
 | 
				
			||||||
 | 
					  'settings.general': 'Ogólne',
 | 
				
			||||||
 | 
					  'settings.image_backgrounds': 'Obrazy w tle',
 | 
				
			||||||
 | 
					  'settings.image_backgrounds_media': 'Wyświetlaj zawartość multimedialną zwiniętych wpisów',
 | 
				
			||||||
 | 
					  'settings.image_backgrounds_users': 'Nadaj tło zwiniętym wpisom',
 | 
				
			||||||
 | 
					  'settings.media': 'Zawartość multimedialna',
 | 
				
			||||||
 | 
					  'settings.media_letterbox': 'Letterbox media',
 | 
				
			||||||
 | 
					  'settings.media_fullwidth': 'Podgląd zawartości multimedialnej o pełnej szerokości',
 | 
				
			||||||
 | 
					  'settings.preferences': 'Preferencje użyytkownika',
 | 
				
			||||||
 | 
					  'settings.wide_view': 'Szeroki widok (tylko w trybie desktopowym)',
 | 
				
			||||||
 | 
					  'settings.navbar_under': 'Pasek nawigacji na dole (tylko w trybie mobilnym)',
 | 
				
			||||||
 | 
					  'status.collapse': 'Zwiń',
 | 
				
			||||||
 | 
					  'status.uncollapse': 'Rozwiń',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  'notification.markForDeletion': 'Oznacz do usunięcia',
 | 
				
			||||||
 | 
					  'notifications.clear': 'Wyczyść wszystkie powiadomienia',
 | 
				
			||||||
 | 
					  'notifications.marked_clear_confirmation': 'Czy na pewno chcesz bezpowrtonie usunąć wszystkie powiadomienia?',
 | 
				
			||||||
 | 
					  'notifications.marked_clear': 'Usuń zaznaczone powiadomienia',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  'notification_purge.btn_all': 'Zaznacz\nwszystkie',
 | 
				
			||||||
 | 
					  'notification_purge.btn_none': 'Odznacz\nwszystkie',
 | 
				
			||||||
 | 
					  'notification_purge.btn_invert': 'Odwróć\nzaznaczenie',
 | 
				
			||||||
 | 
					  'notification_purge.btn_apply': 'Usuń\nzaznaczone',
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Object.assign({}, inherited, messages);
 | 
				
			||||||
							
								
								
									
										7
									
								
								app/javascript/flavours/glitch/locales/pt-BR.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/javascript/flavours/glitch/locales/pt-BR.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					import inherited from 'mastodon/locales/pt-BR.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messages = {
 | 
				
			||||||
 | 
					  //  No translations available.
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Object.assign({}, inherited, messages);
 | 
				
			||||||
							
								
								
									
										7
									
								
								app/javascript/flavours/glitch/locales/pt.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/javascript/flavours/glitch/locales/pt.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					import inherited from 'mastodon/locales/pt.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messages = {
 | 
				
			||||||
 | 
					  //  No translations available.
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Object.assign({}, inherited, messages);
 | 
				
			||||||
							
								
								
									
										7
									
								
								app/javascript/flavours/glitch/locales/ru.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/javascript/flavours/glitch/locales/ru.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					import inherited from 'mastodon/locales/ru.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messages = {
 | 
				
			||||||
 | 
					  //  No translations available.
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Object.assign({}, inherited, messages);
 | 
				
			||||||
							
								
								
									
										7
									
								
								app/javascript/flavours/glitch/locales/sv.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/javascript/flavours/glitch/locales/sv.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					import inherited from 'mastodon/locales/sv.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messages = {
 | 
				
			||||||
 | 
					  //  No translations available.
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Object.assign({}, inherited, messages);
 | 
				
			||||||
							
								
								
									
										7
									
								
								app/javascript/flavours/glitch/locales/th.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/javascript/flavours/glitch/locales/th.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					import inherited from 'mastodon/locales/th.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messages = {
 | 
				
			||||||
 | 
					  //  No translations available.
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Object.assign({}, inherited, messages);
 | 
				
			||||||
							
								
								
									
										7
									
								
								app/javascript/flavours/glitch/locales/tr.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/javascript/flavours/glitch/locales/tr.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					import inherited from 'mastodon/locales/tr.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messages = {
 | 
				
			||||||
 | 
					  //  No translations available.
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Object.assign({}, inherited, messages);
 | 
				
			||||||
							
								
								
									
										7
									
								
								app/javascript/flavours/glitch/locales/uk.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/javascript/flavours/glitch/locales/uk.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					import inherited from 'mastodon/locales/uk.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messages = {
 | 
				
			||||||
 | 
					  //  No translations available.
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Object.assign({}, inherited, messages);
 | 
				
			||||||
							
								
								
									
										7
									
								
								app/javascript/flavours/glitch/locales/zh-CN.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/javascript/flavours/glitch/locales/zh-CN.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					import inherited from 'mastodon/locales/zh-CN.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messages = {
 | 
				
			||||||
 | 
					  //  No translations available.
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Object.assign({}, inherited, messages);
 | 
				
			||||||
							
								
								
									
										7
									
								
								app/javascript/flavours/glitch/locales/zh-HK.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/javascript/flavours/glitch/locales/zh-HK.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					import inherited from 'mastodon/locales/zh-HK.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messages = {
 | 
				
			||||||
 | 
					  //  No translations available.
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Object.assign({}, inherited, messages);
 | 
				
			||||||
							
								
								
									
										7
									
								
								app/javascript/flavours/glitch/locales/zh-TW.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/javascript/flavours/glitch/locales/zh-TW.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					import inherited from 'mastodon/locales/zh-TW.json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messages = {
 | 
				
			||||||
 | 
					  //  No translations available.
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Object.assign({}, inherited, messages);
 | 
				
			||||||
							
								
								
									
										8
									
								
								app/javascript/flavours/glitch/names.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								app/javascript/flavours/glitch/names.yml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					en:
 | 
				
			||||||
 | 
					  flavours:
 | 
				
			||||||
 | 
					    glitch:
 | 
				
			||||||
 | 
					      description: The default flavour for GlitchSoc instances.
 | 
				
			||||||
 | 
					      name: Glitch Edition
 | 
				
			||||||
 | 
					  skins:
 | 
				
			||||||
 | 
					    glitch:
 | 
				
			||||||
 | 
					      default: Default
 | 
				
			||||||
@ -1 +1,4 @@
 | 
				
			|||||||
import 'flavours/glitch/styles/index.scss';
 | 
					import 'flavours/glitch/styles/index.scss';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//  This ensures that webpack compiles our images.
 | 
				
			||||||
 | 
					require.context('../images', true);
 | 
				
			||||||
 | 
				
			|||||||
@ -246,6 +246,22 @@
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.flavour-screen {
 | 
				
			||||||
 | 
					  display: block;
 | 
				
			||||||
 | 
					  margin: 10px auto;
 | 
				
			||||||
 | 
					  max-width: 100%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.flavour-description {
 | 
				
			||||||
 | 
					  display: block;
 | 
				
			||||||
 | 
					  font-size: 16px;
 | 
				
			||||||
 | 
					  margin: 10px 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  & > p {
 | 
				
			||||||
 | 
					    margin: 10px 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.report-accounts {
 | 
					.report-accounts {
 | 
				
			||||||
  display: flex;
 | 
					  display: flex;
 | 
				
			||||||
  flex-wrap: wrap;
 | 
					  flex-wrap: wrap;
 | 
				
			||||||
 | 
				
			|||||||
@ -2286,7 +2286,6 @@
 | 
				
			|||||||
.getting-started {
 | 
					.getting-started {
 | 
				
			||||||
  box-sizing: border-box;
 | 
					  box-sizing: border-box;
 | 
				
			||||||
  padding-bottom: 235px;
 | 
					  padding-bottom: 235px;
 | 
				
			||||||
  background: url('~images/mastodon-getting-started.png') no-repeat 0 100%;
 | 
					 | 
				
			||||||
  flex: 1 0 auto;
 | 
					  flex: 1 0 auto;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  p {
 | 
					  p {
 | 
				
			||||||
@ -3913,6 +3912,7 @@ button.icon-button.active i.fa-retweet {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.boost-modal,
 | 
					.boost-modal,
 | 
				
			||||||
 | 
					.favourite-modal,
 | 
				
			||||||
.confirmation-modal,
 | 
					.confirmation-modal,
 | 
				
			||||||
.report-modal,
 | 
					.report-modal,
 | 
				
			||||||
.actions-modal,
 | 
					.actions-modal,
 | 
				
			||||||
@ -3944,7 +3944,8 @@ button.icon-button.active i.fa-retweet {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.boost-modal__container {
 | 
					.boost-modal__container,
 | 
				
			||||||
 | 
					.favourite-modal__container{
 | 
				
			||||||
  overflow-x: scroll;
 | 
					  overflow-x: scroll;
 | 
				
			||||||
  padding: 10px;
 | 
					  padding: 10px;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -3955,6 +3956,7 @@ button.icon-button.active i.fa-retweet {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.boost-modal__action-bar,
 | 
					.boost-modal__action-bar,
 | 
				
			||||||
 | 
					.favourite-modal__action-bar,
 | 
				
			||||||
.confirmation-modal__action-bar,
 | 
					.confirmation-modal__action-bar,
 | 
				
			||||||
.mute-modal__action-bar,
 | 
					.mute-modal__action-bar,
 | 
				
			||||||
.report-modal__action-bar {
 | 
					.report-modal__action-bar {
 | 
				
			||||||
@ -3976,11 +3978,13 @@ button.icon-button.active i.fa-retweet {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.boost-modal__status-header {
 | 
					.boost-modal__status-header,
 | 
				
			||||||
 | 
					.favourite-modal__status-header {
 | 
				
			||||||
  font-size: 15px;
 | 
					  font-size: 15px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.boost-modal__status-time {
 | 
					.boost-modal__status-time,
 | 
				
			||||||
 | 
					.favourite-modal__status-time {
 | 
				
			||||||
  float: right;
 | 
					  float: right;
 | 
				
			||||||
  font-size: 14px;
 | 
					  font-size: 14px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -20,6 +20,18 @@ pack:
 | 
				
			|||||||
  settings:
 | 
					  settings:
 | 
				
			||||||
  share: packs/share.js
 | 
					  share: packs/share.js
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#  (OPTIONAL) The directory which contains localization files for
 | 
				
			||||||
 | 
					#  the flavour, relative to this directory. The contents of this
 | 
				
			||||||
 | 
					#  directory must be `.js` or `.json` files whose names correspond to
 | 
				
			||||||
 | 
					#  language tags and whose default exports are a messages object.
 | 
				
			||||||
 | 
					locales: locales
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#  (OPTIONAL) A file to use as the preview screenshot for the flavour,
 | 
				
			||||||
 | 
					#  or an array thereof. These filenames must be unique across all
 | 
				
			||||||
 | 
					#  images (regardless of path), so it's a good idea to namespace them
 | 
				
			||||||
 | 
					#  to your theme. It's up to you to let webpack know to compile them.
 | 
				
			||||||
 | 
					screenshot: glitch-preview.jpg
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#  (OPTIONAL) The directory which contains the pack files.
 | 
					#  (OPTIONAL) The directory which contains the pack files.
 | 
				
			||||||
#  Defaults to the theme directory (`app/javascript/themes/[theme]`),
 | 
					#  Defaults to the theme directory (`app/javascript/themes/[theme]`),
 | 
				
			||||||
#  which should be sufficient for like 99% of use-cases lol.
 | 
					#  which should be sufficient for like 99% of use-cases lol.
 | 
				
			||||||
 | 
				
			|||||||
@ -15,6 +15,7 @@ export const reduceMotion = getMeta('reduce_motion');
 | 
				
			|||||||
export const autoPlayGif = getMeta('auto_play_gif');
 | 
					export const autoPlayGif = getMeta('auto_play_gif');
 | 
				
			||||||
export const unfollowModal = getMeta('unfollow_modal');
 | 
					export const unfollowModal = getMeta('unfollow_modal');
 | 
				
			||||||
export const boostModal = getMeta('boost_modal');
 | 
					export const boostModal = getMeta('boost_modal');
 | 
				
			||||||
 | 
					export const favouriteModal = getMeta('favourite_modal');
 | 
				
			||||||
export const deleteModal = getMeta('delete_modal');
 | 
					export const deleteModal = getMeta('delete_modal');
 | 
				
			||||||
export const me = getMeta('me');
 | 
					export const me = getMeta('me');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										8
									
								
								app/javascript/flavours/vanilla/names.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								app/javascript/flavours/vanilla/names.yml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					en:
 | 
				
			||||||
 | 
					  flavours:
 | 
				
			||||||
 | 
					    vanilla:
 | 
				
			||||||
 | 
					      description: The theme used by vanilla Mastodon instances. This theme might not support all of the features of GlitchSoc.
 | 
				
			||||||
 | 
					      name: Vanilla Mastodon
 | 
				
			||||||
 | 
					  skins:
 | 
				
			||||||
 | 
					    vanilla:
 | 
				
			||||||
 | 
					      default: Default
 | 
				
			||||||
@ -20,13 +20,23 @@ pack:
 | 
				
			|||||||
  settings:
 | 
					  settings:
 | 
				
			||||||
  share: share.js
 | 
					  share: share.js
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#  (OPTIONAL) The directory which contains localization files for
 | 
				
			||||||
 | 
					#  the flavour, relative to this directory.
 | 
				
			||||||
 | 
					locales: ../../mastodon/locales
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#  (OPTIONAL) A file to use as the preview screenshot for the flavour,
 | 
				
			||||||
 | 
					#  or an array thereof. These filenames must be unique across all
 | 
				
			||||||
 | 
					#  images (regardless of path), so it's a good idea to namespace them
 | 
				
			||||||
 | 
					#  to your theme. It's up to you to let webpack know to compile them.
 | 
				
			||||||
 | 
					screenshot: screenshot.jpg
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#  (OPTIONAL) The directory which contains the pack files.
 | 
					#  (OPTIONAL) The directory which contains the pack files.
 | 
				
			||||||
#  Defaults to the theme directory (`app/javascript/themes/[theme]`),
 | 
					#  Defaults to this directory (`app/javascript/flavour/[flavour]`),
 | 
				
			||||||
#  but in the case of the vanilla Mastodon theme the pack files are
 | 
					#  but in the case of the vanilla Mastodon flavour the pack files are
 | 
				
			||||||
#  somewhere else.
 | 
					#  somewhere else.
 | 
				
			||||||
pack_directory: app/javascript/packs
 | 
					pack_directory: app/javascript/packs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#  (OPTIONAL) By default the theme will fallback to the default theme
 | 
					#  (OPTIONAL) By default the theme will fallback to the default flavour
 | 
				
			||||||
#  if a particular pack is not provided. You can specify different
 | 
					#  if a particular pack is not provided. You can specify different
 | 
				
			||||||
#  fallbacks here, or disable fallback behaviours altogether by
 | 
					#  fallbacks here, or disable fallback behaviours altogether by
 | 
				
			||||||
#  specifying a `null` value.
 | 
					#  specifying a `null` value.
 | 
				
			||||||
 | 
				
			|||||||
@ -1,46 +0,0 @@
 | 
				
			|||||||
{
 | 
					 | 
				
			||||||
  "getting_started.open_source_notice": "Glitchsoc is free open source software forked from {Mastodon}. You can contribute or report issues on GitHub at {github}.",
 | 
					 | 
				
			||||||
  "layout.auto": "Auto",
 | 
					 | 
				
			||||||
  "layout.current_is": "Your current layout is:",
 | 
					 | 
				
			||||||
  "layout.desktop": "Desktop",
 | 
					 | 
				
			||||||
  "layout.mobile": "Mobile",
 | 
					 | 
				
			||||||
  "navigation_bar.app_settings": "App settings",
 | 
					 | 
				
			||||||
  "getting_started.onboarding": "Show me around",
 | 
					 | 
				
			||||||
  "onboarding.page_one.federation": "{domain} is an 'instance' of Mastodon. Mastodon is a network of independent servers joining up to make one larger social network. We call these servers instances.",
 | 
					 | 
				
			||||||
  "onboarding.page_one.welcome": "Welcome to {domain}!",
 | 
					 | 
				
			||||||
  "onboarding.page_six.github": "{domain} runs on Glitchsoc. Glitchsoc is a friendly {fork} of {Mastodon}, and is compatible with any Mastodon instance or app. Glitchsoc is entirely free and open-source. You can report bugs, request features, or contribute to the code on {github}.",
 | 
					 | 
				
			||||||
  "settings.auto_collapse": "Automatic collapsing",
 | 
					 | 
				
			||||||
  "settings.auto_collapse_all": "Everything",
 | 
					 | 
				
			||||||
  "settings.auto_collapse_lengthy": "Lengthy toots",
 | 
					 | 
				
			||||||
  "settings.auto_collapse_media": "Toots with media",
 | 
					 | 
				
			||||||
  "settings.auto_collapse_notifications": "Notifications",
 | 
					 | 
				
			||||||
  "settings.auto_collapse_reblogs": "Boosts",
 | 
					 | 
				
			||||||
  "settings.auto_collapse_replies": "Replies",
 | 
					 | 
				
			||||||
  "settings.close": "Close",
 | 
					 | 
				
			||||||
  "settings.collapsed_statuses": "Collapsed toots",
 | 
					 | 
				
			||||||
  "settings.enable_collapsed": "Enable collapsed toots",
 | 
					 | 
				
			||||||
  "settings.general": "General",
 | 
					 | 
				
			||||||
  "settings.image_backgrounds": "Image backgrounds",
 | 
					 | 
				
			||||||
  "settings.image_backgrounds_media": "Preview collapsed toot media",
 | 
					 | 
				
			||||||
  "settings.image_backgrounds_users": "Give collapsed toots an image background",
 | 
					 | 
				
			||||||
  "settings.media": "Media",
 | 
					 | 
				
			||||||
  "settings.media_letterbox": "Letterbox media",
 | 
					 | 
				
			||||||
  "settings.media_fullwidth": "Full-width media previews",
 | 
					 | 
				
			||||||
  "settings.preferences": "User preferences",
 | 
					 | 
				
			||||||
  "settings.wide_view": "Wide view (Desktop mode only)",
 | 
					 | 
				
			||||||
  "settings.navbar_under": "Navbar at the bottom (Mobile only)",
 | 
					 | 
				
			||||||
  "status.collapse": "Collapse",
 | 
					 | 
				
			||||||
  "status.uncollapse": "Uncollapse",
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  "home.column_settings.show_direct": "Show DMs",
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  "notification.markForDeletion": "Mark for deletion",
 | 
					 | 
				
			||||||
  "notifications.clear": "Clear all my notifications",
 | 
					 | 
				
			||||||
  "notifications.marked_clear_confirmation": "Are you sure you want to permanently clear all selected notifications?",
 | 
					 | 
				
			||||||
  "notifications.marked_clear": "Clear selected notifications",
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  "notification_purge.btn_all": "Select\nall",
 | 
					 | 
				
			||||||
  "notification_purge.btn_none": "Select\nnone",
 | 
					 | 
				
			||||||
  "notification_purge.btn_invert": "Invert\nselection",
 | 
					 | 
				
			||||||
  "notification_purge.btn_apply": "Clear\nselected"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,44 +0,0 @@
 | 
				
			|||||||
{
 | 
					 | 
				
			||||||
  "getting_started.open_source_notice": "Glitchsocは{Mastodon}によるフリーなオープンソースソフトウェアです。誰でもGitHub({github})から開発に參加したり、問題を報告したりできます。",
 | 
					 | 
				
			||||||
  "layout.auto": "自動",
 | 
					 | 
				
			||||||
  "layout.current_is": "あなたの現在のレイアウト:",
 | 
					 | 
				
			||||||
  "layout.desktop": "デスクトップ",
 | 
					 | 
				
			||||||
  "layout.mobile": "モバイル",
 | 
					 | 
				
			||||||
  "navigation_bar.app_settings": "アプリ設定",
 | 
					 | 
				
			||||||
  "getting_started.onboarding": "解説",
 | 
					 | 
				
			||||||
  "onboarding.page_one.federation": "{domain}はMastodonのインスタンスです。Mastodonとは、独立したサーバが連携して作るソーシャルネットワークです。これらのサーバーをインスタンスと呼びます。",
 | 
					 | 
				
			||||||
  "onboarding.page_one.welcome": "{domain}へようこそ!",
 | 
					 | 
				
			||||||
  "onboarding.page_six.github": "{domain}はGlitchsocを使用しています。Glitchsocは{Mastodon}のフレンドリーな{fork}で、どんなMastodonアプリやインスタンスとも互換性があります。Glitchsocは完全に無料で、オープンソースです。{github}でバグ報告や機能要望あるいは貢獻をすることが可能です。",
 | 
					 | 
				
			||||||
  "settings.auto_collapse": "自動折りたたみ",
 | 
					 | 
				
			||||||
  "settings.auto_collapse_all": "すべて",
 | 
					 | 
				
			||||||
  "settings.auto_collapse_lengthy": "長いトゥート",
 | 
					 | 
				
			||||||
  "settings.auto_collapse_media": "メディア付きトゥート",
 | 
					 | 
				
			||||||
  "settings.auto_collapse_notifications": "通知",
 | 
					 | 
				
			||||||
  "settings.auto_collapse_reblogs": "ブースト",
 | 
					 | 
				
			||||||
  "settings.auto_collapse_replies": "返信",
 | 
					 | 
				
			||||||
  "settings.close": "閉じる",
 | 
					 | 
				
			||||||
  "settings.collapsed_statuses": "トゥート",
 | 
					 | 
				
			||||||
  "settings.enable_collapsed": "トゥート折りたたみを有効にする",
 | 
					 | 
				
			||||||
  "settings.general": "一般",
 | 
					 | 
				
			||||||
  "settings.image_backgrounds": "画像背景",
 | 
					 | 
				
			||||||
  "settings.image_backgrounds_media": "折りたまれたメディア付きテゥートをプレビュー",
 | 
					 | 
				
			||||||
  "settings.image_backgrounds_users": "折りたまれたトゥートの背景を変更する",
 | 
					 | 
				
			||||||
  "settings.media": "メディア",
 | 
					 | 
				
			||||||
  "settings.media_letterbox": "メディアをレターボックス式で表示",
 | 
					 | 
				
			||||||
  "settings.media_fullwidth": "全幅メディアプリビュー",
 | 
					 | 
				
			||||||
  "settings.preferences": "ユーザー設定",
 | 
					 | 
				
			||||||
  "settings.wide_view": "ワイドビュー(デスクトップレイアウトのみ)",
 | 
					 | 
				
			||||||
  "settings.navbar_under": "ナビを画面下部に移動させる(モバイルレイアウトのみ)",
 | 
					 | 
				
			||||||
  "status.collapse": "折りたたむ",
 | 
					 | 
				
			||||||
  "status.uncollapse": "折りたたみを解除",
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  "notification.markForDeletion": "選択",
 | 
					 | 
				
			||||||
  "notifications.clear": "通知を全てクリアする",
 | 
					 | 
				
			||||||
  "notifications.marked_clear_confirmation": "削除した全ての通知を完全に削除してもよろしいですか?",
 | 
					 | 
				
			||||||
  "notifications.marked_clear": "選択した通知を削除する",
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  "notification_purge.btn_all": "すべて\n選択",
 | 
					 | 
				
			||||||
  "notification_purge.btn_none": "選択\n解除",
 | 
					 | 
				
			||||||
  "notification_purge.btn_invert": "選択を\n反転",
 | 
					 | 
				
			||||||
  "notification_purge.btn_apply": "選択したものを\n削除"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,44 +0,0 @@
 | 
				
			|||||||
{
 | 
					 | 
				
			||||||
  "getting_started.open_source_notice": "Glitchsoc jest wolnym i otwartoźródłowym forkiem oprogramowania {Mastodon}. Możesz współtworzyć projekt lub zgłaszać błędy na GitHubie pod adresem {github}.",
 | 
					 | 
				
			||||||
  "layout.auto": "Automatyczny",
 | 
					 | 
				
			||||||
  "layout.current_is": "Twój obecny układ to:",
 | 
					 | 
				
			||||||
  "layout.desktop": "Desktopowy",
 | 
					 | 
				
			||||||
  "layout.mobile": "Mobilny",
 | 
					 | 
				
			||||||
  "navigation_bar.app_settings": "Ustawienia aplikacji",
 | 
					 | 
				
			||||||
  "getting_started.onboarding": "Rozejrzyj się",
 | 
					 | 
				
			||||||
  "onboarding.page_one.federation": "{domain} jest 'instancją' Mastodona. Mastodon to sieć działających niezależnie serwerów tworzących jedną sieć społecznościową. Te serwery nazywane są instancjami.",
 | 
					 | 
				
			||||||
  "onboarding.page_one.welcome": "Witamy na {domain}!",
 | 
					 | 
				
			||||||
  "onboarding.page_six.github": "{domain} jest oparty na Glitchsoc. Glitchsoc jest {forkiem} {Mastodon}a kompatybilnym z każdym klientem i aplikacją Mastodona. Glitchsoc jest całkowicie wolnym i otwartoźródłowym oprogramowaniem. Możesz zgłaszać błędy i sugestie funkcji oraz współtworzyć projekt na {github}.",
 | 
					 | 
				
			||||||
  "settings.auto_collapse": "Automatyczne zwijanie",
 | 
					 | 
				
			||||||
  "settings.auto_collapse_all": "Wszystko",
 | 
					 | 
				
			||||||
  "settings.auto_collapse_lengthy": "Długie wpisy",
 | 
					 | 
				
			||||||
  "settings.auto_collapse_media": "Wpisy z zawartością multimedialną",
 | 
					 | 
				
			||||||
  "settings.auto_collapse_notifications": "Powiadomienia",
 | 
					 | 
				
			||||||
  "settings.auto_collapse_reblogs": "Podbicia",
 | 
					 | 
				
			||||||
  "settings.auto_collapse_replies": "Odpowiedzi",
 | 
					 | 
				
			||||||
  "settings.close": "Zamknij",
 | 
					 | 
				
			||||||
  "settings.collapsed_statuses": "Zwijanie wpisów",
 | 
					 | 
				
			||||||
  "settings.enable_collapsed": "Włącz zwijanie wpisów",
 | 
					 | 
				
			||||||
  "settings.general": "Ogólne",
 | 
					 | 
				
			||||||
  "settings.image_backgrounds": "Obrazy w tle",
 | 
					 | 
				
			||||||
  "settings.image_backgrounds_media": "Wyświetlaj zawartość multimedialną zwiniętych wpisów",
 | 
					 | 
				
			||||||
  "settings.image_backgrounds_users": "Nadaj tło zwiniętym wpisom",
 | 
					 | 
				
			||||||
  "settings.media": "Zawartość multimedialna",
 | 
					 | 
				
			||||||
  "settings.media_letterbox": "Letterbox media",
 | 
					 | 
				
			||||||
  "settings.media_fullwidth": "Podgląd zawartości multimedialnej o pełnej szerokości",
 | 
					 | 
				
			||||||
  "settings.preferences": "Preferencje użyytkownika",
 | 
					 | 
				
			||||||
  "settings.wide_view": "Szeroki widok (tylko w trybie desktopowym)",
 | 
					 | 
				
			||||||
  "settings.navbar_under": "Pasek nawigacji na dole (tylko w trybie mobilnym)",
 | 
					 | 
				
			||||||
  "status.collapse": "Zwiń",
 | 
					 | 
				
			||||||
  "status.uncollapse": "Rozwiń",
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  "notification.markForDeletion": "Oznacz do usunięcia",
 | 
					 | 
				
			||||||
  "notifications.clear": "Wyczyść wszystkie powiadomienia",
 | 
					 | 
				
			||||||
  "notifications.marked_clear_confirmation": "Czy na pewno chcesz bezpowrtonie usunąć wszystkie powiadomienia?",
 | 
					 | 
				
			||||||
  "notifications.marked_clear": "Usuń zaznaczone powiadomienia",
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  "notification_purge.btn_all": "Zaznacz\nwszystkie",
 | 
					 | 
				
			||||||
  "notification_purge.btn_none": "Odznacz\nwszystkie",
 | 
					 | 
				
			||||||
  "notification_purge.btn_invert": "Odwróć\nzaznaczenie",
 | 
					 | 
				
			||||||
  "notification_purge.btn_apply": "Usuń\nzaznaczone"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								app/javascript/images/screenshot.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/javascript/images/screenshot.jpg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 234 KiB  | 
@ -10,6 +10,10 @@ export const FAVOURITED_STATUSES_EXPAND_FAIL    = 'FAVOURITED_STATUSES_EXPAND_FA
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export function fetchFavouritedStatuses() {
 | 
					export function fetchFavouritedStatuses() {
 | 
				
			||||||
  return (dispatch, getState) => {
 | 
					  return (dispatch, getState) => {
 | 
				
			||||||
 | 
					    if (getState().getIn(['status_lists', 'favourites', 'isLoading'])) {
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    dispatch(fetchFavouritedStatusesRequest());
 | 
					    dispatch(fetchFavouritedStatusesRequest());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    api(getState).get('/api/v1/favourites').then(response => {
 | 
					    api(getState).get('/api/v1/favourites').then(response => {
 | 
				
			||||||
@ -46,7 +50,7 @@ export function expandFavouritedStatuses() {
 | 
				
			|||||||
  return (dispatch, getState) => {
 | 
					  return (dispatch, getState) => {
 | 
				
			||||||
    const url = getState().getIn(['status_lists', 'favourites', 'next'], null);
 | 
					    const url = getState().getIn(['status_lists', 'favourites', 'next'], null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (url === null) {
 | 
					    if (url === null || getState().getIn(['status_lists', 'favourites', 'isLoading'])) {
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,5 @@
 | 
				
			|||||||
import axios from 'axios';
 | 
					import axios from 'axios';
 | 
				
			||||||
 | 
					import { pushNotificationsSetting } from '../settings';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const SET_BROWSER_SUPPORT = 'PUSH_NOTIFICATIONS_SET_BROWSER_SUPPORT';
 | 
					export const SET_BROWSER_SUPPORT = 'PUSH_NOTIFICATIONS_SET_BROWSER_SUPPORT';
 | 
				
			||||||
export const SET_SUBSCRIPTION = 'PUSH_NOTIFICATIONS_SET_SUBSCRIPTION';
 | 
					export const SET_SUBSCRIPTION = 'PUSH_NOTIFICATIONS_SET_SUBSCRIPTION';
 | 
				
			||||||
@ -42,11 +43,15 @@ export function saveSettings() {
 | 
				
			|||||||
    const state = getState().get('push_notifications');
 | 
					    const state = getState().get('push_notifications');
 | 
				
			||||||
    const subscription = state.get('subscription');
 | 
					    const subscription = state.get('subscription');
 | 
				
			||||||
    const alerts = state.get('alerts');
 | 
					    const alerts = state.get('alerts');
 | 
				
			||||||
 | 
					    const data = { alerts };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    axios.put(`/api/web/push_subscriptions/${subscription.get('id')}`, {
 | 
					    axios.put(`/api/web/push_subscriptions/${subscription.get('id')}`, {
 | 
				
			||||||
      data: {
 | 
					      data,
 | 
				
			||||||
        alerts,
 | 
					    }).then(() => {
 | 
				
			||||||
      },
 | 
					      const me = getState().getIn(['meta', 'me']);
 | 
				
			||||||
 | 
					      if (me) {
 | 
				
			||||||
 | 
					        pushNotificationsSetting.set(me, data);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,7 @@
 | 
				
			|||||||
import React from 'react';
 | 
					import React from 'react';
 | 
				
			||||||
import PropTypes from 'prop-types';
 | 
					import PropTypes from 'prop-types';
 | 
				
			||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
 | 
					import ImmutablePropTypes from 'react-immutable-proptypes';
 | 
				
			||||||
 | 
					import { autoPlayGif } from '../initial_state';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class Avatar extends React.PureComponent {
 | 
					export default class Avatar extends React.PureComponent {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -8,12 +9,12 @@ export default class Avatar extends React.PureComponent {
 | 
				
			|||||||
    account: ImmutablePropTypes.map.isRequired,
 | 
					    account: ImmutablePropTypes.map.isRequired,
 | 
				
			||||||
    size: PropTypes.number.isRequired,
 | 
					    size: PropTypes.number.isRequired,
 | 
				
			||||||
    style: PropTypes.object,
 | 
					    style: PropTypes.object,
 | 
				
			||||||
    animate: PropTypes.bool,
 | 
					 | 
				
			||||||
    inline: PropTypes.bool,
 | 
					    inline: PropTypes.bool,
 | 
				
			||||||
 | 
					    animate: PropTypes.bool,
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static defaultProps = {
 | 
					  static defaultProps = {
 | 
				
			||||||
    animate: false,
 | 
					    animate: autoPlayGif,
 | 
				
			||||||
    size: 20,
 | 
					    size: 20,
 | 
				
			||||||
    inline: false,
 | 
					    inline: false,
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
				
			|||||||
@ -1,22 +1,29 @@
 | 
				
			|||||||
import React from 'react';
 | 
					import React from 'react';
 | 
				
			||||||
 | 
					import PropTypes from 'prop-types';
 | 
				
			||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
 | 
					import ImmutablePropTypes from 'react-immutable-proptypes';
 | 
				
			||||||
 | 
					import { autoPlayGif } from '../initial_state';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class AvatarOverlay extends React.PureComponent {
 | 
					export default class AvatarOverlay extends React.PureComponent {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static propTypes = {
 | 
					  static propTypes = {
 | 
				
			||||||
    account: ImmutablePropTypes.map.isRequired,
 | 
					    account: ImmutablePropTypes.map.isRequired,
 | 
				
			||||||
    friend: ImmutablePropTypes.map.isRequired,
 | 
					    friend: ImmutablePropTypes.map.isRequired,
 | 
				
			||||||
 | 
					    animate: PropTypes.bool,
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static defaultProps = {
 | 
				
			||||||
 | 
					    animate: autoPlayGif,
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  render() {
 | 
					  render() {
 | 
				
			||||||
    const { account, friend } = this.props;
 | 
					    const { account, friend, animate } = this.props;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const baseStyle = {
 | 
					    const baseStyle = {
 | 
				
			||||||
      backgroundImage: `url(${account.get('avatar_static')})`,
 | 
					      backgroundImage: `url(${account.get(animate ? 'avatar' : 'avatar_static')})`,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const overlayStyle = {
 | 
					    const overlayStyle = {
 | 
				
			||||||
      backgroundImage: `url(${friend.get('avatar_static')})`,
 | 
					      backgroundImage: `url(${friend.get(animate ? 'avatar' : 'avatar_static')})`,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
 | 
				
			|||||||
@ -156,6 +156,8 @@ export default class ComposeForm extends ImmutablePureComponent {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
      <div className='compose-form'>
 | 
					      <div className='compose-form'>
 | 
				
			||||||
 | 
					        <WarningContainer />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <Collapsable isVisible={this.props.spoiler} fullHeight={50}>
 | 
					        <Collapsable isVisible={this.props.spoiler} fullHeight={50}>
 | 
				
			||||||
          <div className='spoiler-input'>
 | 
					          <div className='spoiler-input'>
 | 
				
			||||||
            <label>
 | 
					            <label>
 | 
				
			||||||
@ -165,8 +167,6 @@ export default class ComposeForm extends ImmutablePureComponent {
 | 
				
			|||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </Collapsable>
 | 
					        </Collapsable>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <WarningContainer />
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        <ReplyIndicatorContainer />
 | 
					        <ReplyIndicatorContainer />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <div className='compose-form__autosuggest-wrapper'>
 | 
					        <div className='compose-form__autosuggest-wrapper'>
 | 
				
			||||||
@ -199,11 +199,11 @@ export default class ComposeForm extends ImmutablePureComponent {
 | 
				
			|||||||
            <SensitiveButtonContainer />
 | 
					            <SensitiveButtonContainer />
 | 
				
			||||||
            <SpoilerButtonContainer />
 | 
					            <SpoilerButtonContainer />
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
 | 
					          <div className='character-counter__wrapper'><CharacterCounter max={500} text={text} /></div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          <div className='compose-form__publish'>
 | 
					        <div className='compose-form__publish'>
 | 
				
			||||||
            <div className='character-counter__wrapper'><CharacterCounter max={500} text={text} /></div>
 | 
					          <div className='compose-form__publish-button-wrapper'><Button text={publishText} onClick={this.handleSubmit} disabled={disabled || this.props.is_uploading || length(text) > 500 || (text.length !== 0 && text.trim().length === 0)} block /></div>
 | 
				
			||||||
            <div className='compose-form__publish-button-wrapper'><Button text={publishText} onClick={this.handleSubmit} disabled={disabled || this.props.is_uploading || length(text) > 500 || (text.length !== 0 && text.trim().length === 0)} block /></div>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
				
			|||||||
@ -6,6 +6,7 @@ import IconButton from '../../../components/icon_button';
 | 
				
			|||||||
import DisplayName from '../../../components/display_name';
 | 
					import DisplayName from '../../../components/display_name';
 | 
				
			||||||
import { defineMessages, injectIntl } from 'react-intl';
 | 
					import { defineMessages, injectIntl } from 'react-intl';
 | 
				
			||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
 | 
					import ImmutablePureComponent from 'react-immutable-pure-component';
 | 
				
			||||||
 | 
					import { isRtl } from '../../../rtl';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const messages = defineMessages({
 | 
					const messages = defineMessages({
 | 
				
			||||||
  cancel: { id: 'reply_indicator.cancel', defaultMessage: 'Cancel' },
 | 
					  cancel: { id: 'reply_indicator.cancel', defaultMessage: 'Cancel' },
 | 
				
			||||||
@ -42,7 +43,10 @@ export default class ReplyIndicator extends ImmutablePureComponent {
 | 
				
			|||||||
      return null;
 | 
					      return null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const content  = { __html: status.get('contentHtml') };
 | 
					    const content = { __html: status.get('contentHtml') };
 | 
				
			||||||
 | 
					    const style   = {
 | 
				
			||||||
 | 
					      direction: isRtl(status.get('search_index')) ? 'rtl' : 'ltr',
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
      <div className='reply-indicator'>
 | 
					      <div className='reply-indicator'>
 | 
				
			||||||
@ -55,7 +59,7 @@ export default class ReplyIndicator extends ImmutablePureComponent {
 | 
				
			|||||||
          </a>
 | 
					          </a>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <div className='reply-indicator__content' dangerouslySetInnerHTML={content} />
 | 
					        <div className='reply-indicator__content' style={style} dangerouslySetInnerHTML={content} />
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
@ -62,7 +62,7 @@ export default class Upload extends ImmutablePureComponent {
 | 
				
			|||||||
  render () {
 | 
					  render () {
 | 
				
			||||||
    const { intl, media } = this.props;
 | 
					    const { intl, media } = this.props;
 | 
				
			||||||
    const active          = this.state.hovered || this.state.focused;
 | 
					    const active          = this.state.hovered || this.state.focused;
 | 
				
			||||||
    const description     = this.state.dirtyDescription || media.get('description') || '';
 | 
					    const description     = this.state.dirtyDescription || (this.state.dirtyDescription !== '' && media.get('description')) || '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
      <div className='compose-form__upload' onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>
 | 
					      <div className='compose-form__upload' onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>
 | 
				
			||||||
 | 
				
			|||||||
@ -9,6 +9,7 @@ import { addColumn, removeColumn, moveColumn } from '../../actions/columns';
 | 
				
			|||||||
import StatusList from '../../components/status_list';
 | 
					import StatusList from '../../components/status_list';
 | 
				
			||||||
import { defineMessages, injectIntl } from 'react-intl';
 | 
					import { defineMessages, injectIntl } from 'react-intl';
 | 
				
			||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
 | 
					import ImmutablePureComponent from 'react-immutable-pure-component';
 | 
				
			||||||
 | 
					import { debounce } from 'lodash';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const messages = defineMessages({
 | 
					const messages = defineMessages({
 | 
				
			||||||
  heading: { id: 'column.favourites', defaultMessage: 'Favourites' },
 | 
					  heading: { id: 'column.favourites', defaultMessage: 'Favourites' },
 | 
				
			||||||
@ -16,6 +17,7 @@ const messages = defineMessages({
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const mapStateToProps = state => ({
 | 
					const mapStateToProps = state => ({
 | 
				
			||||||
  statusIds: state.getIn(['status_lists', 'favourites', 'items']),
 | 
					  statusIds: state.getIn(['status_lists', 'favourites', 'items']),
 | 
				
			||||||
 | 
					  isLoading: state.getIn(['status_lists', 'favourites', 'isLoading'], true),
 | 
				
			||||||
  hasMore: !!state.getIn(['status_lists', 'favourites', 'next']),
 | 
					  hasMore: !!state.getIn(['status_lists', 'favourites', 'next']),
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -30,6 +32,7 @@ export default class Favourites extends ImmutablePureComponent {
 | 
				
			|||||||
    columnId: PropTypes.string,
 | 
					    columnId: PropTypes.string,
 | 
				
			||||||
    multiColumn: PropTypes.bool,
 | 
					    multiColumn: PropTypes.bool,
 | 
				
			||||||
    hasMore: PropTypes.bool,
 | 
					    hasMore: PropTypes.bool,
 | 
				
			||||||
 | 
					    isLoading: PropTypes.bool,
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  componentWillMount () {
 | 
					  componentWillMount () {
 | 
				
			||||||
@ -59,12 +62,12 @@ export default class Favourites extends ImmutablePureComponent {
 | 
				
			|||||||
    this.column = c;
 | 
					    this.column = c;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  handleScrollToBottom = () => {
 | 
					  handleScrollToBottom = debounce(() => {
 | 
				
			||||||
    this.props.dispatch(expandFavouritedStatuses());
 | 
					    this.props.dispatch(expandFavouritedStatuses());
 | 
				
			||||||
  }
 | 
					  }, 300, { leading: true })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  render () {
 | 
					  render () {
 | 
				
			||||||
    const { intl, statusIds, columnId, multiColumn, hasMore } = this.props;
 | 
					    const { intl, statusIds, columnId, multiColumn, hasMore, isLoading } = this.props;
 | 
				
			||||||
    const pinned = !!columnId;
 | 
					    const pinned = !!columnId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
@ -85,6 +88,7 @@ export default class Favourites extends ImmutablePureComponent {
 | 
				
			|||||||
          statusIds={statusIds}
 | 
					          statusIds={statusIds}
 | 
				
			||||||
          scrollKey={`favourited_statuses-${columnId}`}
 | 
					          scrollKey={`favourited_statuses-${columnId}`}
 | 
				
			||||||
          hasMore={hasMore}
 | 
					          hasMore={hasMore}
 | 
				
			||||||
 | 
					          isLoading={isLoading}
 | 
				
			||||||
          onScrollToBottom={this.handleScrollToBottom}
 | 
					          onScrollToBottom={this.handleScrollToBottom}
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
      </Column>
 | 
					      </Column>
 | 
				
			||||||
 | 
				
			|||||||
@ -161,7 +161,7 @@ export default class ListTimeline extends React.PureComponent {
 | 
				
			|||||||
          scrollKey={`list_timeline-${columnId}`}
 | 
					          scrollKey={`list_timeline-${columnId}`}
 | 
				
			||||||
          timelineId={`list:${id}`}
 | 
					          timelineId={`list:${id}`}
 | 
				
			||||||
          loadMore={this.handleLoadMore}
 | 
					          loadMore={this.handleLoadMore}
 | 
				
			||||||
          emptyMessage={<FormattedMessage id='empty_column.list' defaultMessage='There is nothing in this list yet.' />}
 | 
					          emptyMessage={<FormattedMessage id='empty_column.list' defaultMessage='There is nothing in this list yet. When members of this list post new statuses, they will appear here.' />}
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
      </Column>
 | 
					      </Column>
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
				
			|||||||
@ -8,6 +8,7 @@ import {
 | 
				
			|||||||
} from '../../../actions/timelines';
 | 
					} from '../../../actions/timelines';
 | 
				
			||||||
import Column from '../../../components/column';
 | 
					import Column from '../../../components/column';
 | 
				
			||||||
import ColumnHeader from '../../../components/column_header';
 | 
					import ColumnHeader from '../../../components/column_header';
 | 
				
			||||||
 | 
					import { connectHashtagStream } from '../../../actions/streaming';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@connect()
 | 
					@connect()
 | 
				
			||||||
export default class HashtagTimeline extends React.PureComponent {
 | 
					export default class HashtagTimeline extends React.PureComponent {
 | 
				
			||||||
@ -29,16 +30,13 @@ export default class HashtagTimeline extends React.PureComponent {
 | 
				
			|||||||
    const { dispatch, hashtag } = this.props;
 | 
					    const { dispatch, hashtag } = this.props;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    dispatch(refreshHashtagTimeline(hashtag));
 | 
					    dispatch(refreshHashtagTimeline(hashtag));
 | 
				
			||||||
 | 
					    this.disconnect = dispatch(connectHashtagStream(hashtag));
 | 
				
			||||||
    this.polling = setInterval(() => {
 | 
					 | 
				
			||||||
      dispatch(refreshHashtagTimeline(hashtag));
 | 
					 | 
				
			||||||
    }, 10000);
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  componentWillUnmount () {
 | 
					  componentWillUnmount () {
 | 
				
			||||||
    if (typeof this.polling !== 'undefined') {
 | 
					    if (this.disconnect) {
 | 
				
			||||||
      clearInterval(this.polling);
 | 
					      this.disconnect();
 | 
				
			||||||
      this.polling = null;
 | 
					      this.disconnect = null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -9,6 +9,7 @@ import {
 | 
				
			|||||||
import Column from '../../../components/column';
 | 
					import Column from '../../../components/column';
 | 
				
			||||||
import ColumnHeader from '../../../components/column_header';
 | 
					import ColumnHeader from '../../../components/column_header';
 | 
				
			||||||
import { defineMessages, injectIntl } from 'react-intl';
 | 
					import { defineMessages, injectIntl } from 'react-intl';
 | 
				
			||||||
 | 
					import { connectPublicStream } from '../../../actions/streaming';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const messages = defineMessages({
 | 
					const messages = defineMessages({
 | 
				
			||||||
  title: { id: 'standalone.public_title', defaultMessage: 'A look inside...' },
 | 
					  title: { id: 'standalone.public_title', defaultMessage: 'A look inside...' },
 | 
				
			||||||
@ -35,16 +36,13 @@ export default class PublicTimeline extends React.PureComponent {
 | 
				
			|||||||
    const { dispatch } = this.props;
 | 
					    const { dispatch } = this.props;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    dispatch(refreshPublicTimeline());
 | 
					    dispatch(refreshPublicTimeline());
 | 
				
			||||||
 | 
					    this.disconnect = dispatch(connectPublicStream());
 | 
				
			||||||
    this.polling = setInterval(() => {
 | 
					 | 
				
			||||||
      dispatch(refreshPublicTimeline());
 | 
					 | 
				
			||||||
    }, 3000);
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  componentWillUnmount () {
 | 
					  componentWillUnmount () {
 | 
				
			||||||
    if (typeof this.polling !== 'undefined') {
 | 
					    if (this.disconnect) {
 | 
				
			||||||
      clearInterval(this.polling);
 | 
					      this.disconnect();
 | 
				
			||||||
      this.polling = null;
 | 
					      this.disconnect = null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -43,7 +43,7 @@ export default class Card extends React.PureComponent {
 | 
				
			|||||||
      Immutable.fromJS([
 | 
					      Immutable.fromJS([
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          type: 'image',
 | 
					          type: 'image',
 | 
				
			||||||
          url: card.get('url'),
 | 
					          url: card.get('embed_url'),
 | 
				
			||||||
          description: card.get('title'),
 | 
					          description: card.get('title'),
 | 
				
			||||||
          meta: {
 | 
					          meta: {
 | 
				
			||||||
            original: {
 | 
					            original: {
 | 
				
			||||||
@ -59,6 +59,8 @@ export default class Card extends React.PureComponent {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  renderLink () {
 | 
					  renderLink () {
 | 
				
			||||||
    const { card, maxDescription } = this.props;
 | 
					    const { card, maxDescription } = this.props;
 | 
				
			||||||
 | 
					    const { width }  = this.state;
 | 
				
			||||||
 | 
					    const horizontal = card.get('width') > card.get('height') && (card.get('width') + 100 >= width);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let image    = '';
 | 
					    let image    = '';
 | 
				
			||||||
    let provider = card.get('provider_name');
 | 
					    let provider = card.get('provider_name');
 | 
				
			||||||
@ -75,17 +77,15 @@ export default class Card extends React.PureComponent {
 | 
				
			|||||||
      provider = decodeIDNA(getHostname(card.get('url')));
 | 
					      provider = decodeIDNA(getHostname(card.get('url')));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const className = classnames('status-card', {
 | 
					    const className = classnames('status-card', { horizontal });
 | 
				
			||||||
      'horizontal': card.get('width') > card.get('height'),
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
      <a href={card.get('url')} className={className} target='_blank' rel='noopener'>
 | 
					      <a href={card.get('url')} className={className} target='_blank' rel='noopener' ref={this.setRef}>
 | 
				
			||||||
        {image}
 | 
					        {image}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <div className='status-card__content'>
 | 
					        <div className='status-card__content'>
 | 
				
			||||||
          <strong className='status-card__title' title={card.get('title')}>{card.get('title')}</strong>
 | 
					          <strong className='status-card__title' title={card.get('title')}>{card.get('title')}</strong>
 | 
				
			||||||
          <p className='status-card__description'>{(card.get('description') || '').substring(0, maxDescription)}</p>
 | 
					          {!horizontal && <p className='status-card__description'>{(card.get('description') || '').substring(0, maxDescription)}</p>}
 | 
				
			||||||
          <span className='status-card__host'>{provider}</span>
 | 
					          <span className='status-card__host'>{provider}</span>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      </a>
 | 
					      </a>
 | 
				
			||||||
 | 
				
			|||||||
@ -53,7 +53,10 @@ export default class ColumnsArea extends ImmutablePureComponent {
 | 
				
			|||||||
    if (!this.props.singleColumn) {
 | 
					    if (!this.props.singleColumn) {
 | 
				
			||||||
      this.node.addEventListener('wheel', this.handleWheel,  detectPassiveEvents.hasSupport ? { passive: true } : false);
 | 
					      this.node.addEventListener('wheel', this.handleWheel,  detectPassiveEvents.hasSupport ? { passive: true } : false);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    this.lastIndex = getIndex(this.context.router.history.location.pathname);
 | 
					
 | 
				
			||||||
 | 
					    this.lastIndex   = getIndex(this.context.router.history.location.pathname);
 | 
				
			||||||
 | 
					    this.isRtlLayout = document.getElementsByTagName('body')[0].classList.contains('rtl');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.setState({ shouldAnimate: true });
 | 
					    this.setState({ shouldAnimate: true });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -79,7 +82,8 @@ export default class ColumnsArea extends ImmutablePureComponent {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  handleChildrenContentChange() {
 | 
					  handleChildrenContentChange() {
 | 
				
			||||||
    if (!this.props.singleColumn) {
 | 
					    if (!this.props.singleColumn) {
 | 
				
			||||||
      this._interruptScrollAnimation = scrollRight(this.node, this.node.scrollWidth - window.innerWidth);
 | 
					      const modifier = this.isRtlLayout ? -1 : 1;
 | 
				
			||||||
 | 
					      this._interruptScrollAnimation = scrollRight(this.node, (this.node.scrollWidth - window.innerWidth) * modifier);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -23,6 +23,7 @@ export default class VideoModal extends ImmutablePureComponent {
 | 
				
			|||||||
            src={media.get('url')}
 | 
					            src={media.get('url')}
 | 
				
			||||||
            startTime={time}
 | 
					            startTime={time}
 | 
				
			||||||
            onCloseVideo={onClose}
 | 
					            onCloseVideo={onClose}
 | 
				
			||||||
 | 
					            detailed
 | 
				
			||||||
            description={media.get('description')}
 | 
					            description={media.get('description')}
 | 
				
			||||||
          />
 | 
					          />
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
				
			|||||||
@ -17,6 +17,18 @@ const messages = defineMessages({
 | 
				
			|||||||
  exit_fullscreen: { id: 'video.exit_fullscreen', defaultMessage: 'Exit full screen' },
 | 
					  exit_fullscreen: { id: 'video.exit_fullscreen', defaultMessage: 'Exit full screen' },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const formatTime = secondsNum => {
 | 
				
			||||||
 | 
					  let hours   = Math.floor(secondsNum / 3600);
 | 
				
			||||||
 | 
					  let minutes = Math.floor((secondsNum - (hours * 3600)) / 60);
 | 
				
			||||||
 | 
					  let seconds = secondsNum - (hours * 3600) - (minutes * 60);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (hours   < 10) hours   = '0' + hours;
 | 
				
			||||||
 | 
					  if (minutes < 10) minutes = '0' + minutes;
 | 
				
			||||||
 | 
					  if (seconds < 10) seconds = '0' + seconds;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (hours === '00' ? '' : `${hours}:`) + `${minutes}:${seconds}`;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const findElementPosition = el => {
 | 
					const findElementPosition = el => {
 | 
				
			||||||
  let box;
 | 
					  let box;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -83,11 +95,13 @@ export default class Video extends React.PureComponent {
 | 
				
			|||||||
    startTime: PropTypes.number,
 | 
					    startTime: PropTypes.number,
 | 
				
			||||||
    onOpenVideo: PropTypes.func,
 | 
					    onOpenVideo: PropTypes.func,
 | 
				
			||||||
    onCloseVideo: PropTypes.func,
 | 
					    onCloseVideo: PropTypes.func,
 | 
				
			||||||
 | 
					    detailed: PropTypes.bool,
 | 
				
			||||||
    intl: PropTypes.object.isRequired,
 | 
					    intl: PropTypes.object.isRequired,
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  state = {
 | 
					  state = {
 | 
				
			||||||
    progress: 0,
 | 
					    currentTime: 0,
 | 
				
			||||||
 | 
					    duration: 0,
 | 
				
			||||||
    paused: true,
 | 
					    paused: true,
 | 
				
			||||||
    dragging: false,
 | 
					    dragging: false,
 | 
				
			||||||
    fullscreen: false,
 | 
					    fullscreen: false,
 | 
				
			||||||
@ -117,7 +131,10 @@ export default class Video extends React.PureComponent {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  handleTimeUpdate = () => {
 | 
					  handleTimeUpdate = () => {
 | 
				
			||||||
    this.setState({ progress: 100 * (this.video.currentTime / this.video.duration) });
 | 
					    this.setState({
 | 
				
			||||||
 | 
					      currentTime: Math.floor(this.video.currentTime),
 | 
				
			||||||
 | 
					      duration: Math.floor(this.video.duration),
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  handleMouseDown = e => {
 | 
					  handleMouseDown = e => {
 | 
				
			||||||
@ -143,8 +160,10 @@ export default class Video extends React.PureComponent {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  handleMouseMove = throttle(e => {
 | 
					  handleMouseMove = throttle(e => {
 | 
				
			||||||
    const { x } = getPointerPosition(this.seek, e);
 | 
					    const { x } = getPointerPosition(this.seek, e);
 | 
				
			||||||
    this.video.currentTime = this.video.duration * x;
 | 
					    const currentTime = Math.floor(this.video.duration * x);
 | 
				
			||||||
    this.setState({ progress: x * 100 });
 | 
					
 | 
				
			||||||
 | 
					    this.video.currentTime = currentTime;
 | 
				
			||||||
 | 
					    this.setState({ currentTime });
 | 
				
			||||||
  }, 60);
 | 
					  }, 60);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  togglePlay = () => {
 | 
					  togglePlay = () => {
 | 
				
			||||||
@ -226,11 +245,12 @@ export default class Video extends React.PureComponent {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  render () {
 | 
					  render () {
 | 
				
			||||||
    const { preview, src, width, height, startTime, onOpenVideo, onCloseVideo, intl, alt } = this.props;
 | 
					    const { preview, src, width, height, startTime, onOpenVideo, onCloseVideo, intl, alt, detailed } = this.props;
 | 
				
			||||||
    const { progress, buffer, dragging, paused, fullscreen, hovered, muted, revealed } = this.state;
 | 
					    const { currentTime, duration, buffer, dragging, paused, fullscreen, hovered, muted, revealed } = this.state;
 | 
				
			||||||
 | 
					    const progress = (currentTime / duration) * 100;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
      <div className={classNames('video-player', { inactive: !revealed, inline: width && height && !fullscreen, fullscreen })} style={{ width, height }} ref={this.setPlayerRef} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>
 | 
					      <div className={classNames('video-player', { inactive: !revealed, detailed, inline: width && height && !fullscreen, fullscreen })} style={{ width, height }} ref={this.setPlayerRef} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>
 | 
				
			||||||
        <video
 | 
					        <video
 | 
				
			||||||
          ref={this.setVideoRef}
 | 
					          ref={this.setVideoRef}
 | 
				
			||||||
          src={src}
 | 
					          src={src}
 | 
				
			||||||
@ -267,16 +287,27 @@ export default class Video extends React.PureComponent {
 | 
				
			|||||||
            />
 | 
					            />
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          <div className='video-player__buttons left'>
 | 
					          <div className='video-player__buttons-bar'>
 | 
				
			||||||
            <button aria-label={intl.formatMessage(paused ? messages.play : messages.pause)} onClick={this.togglePlay}><i className={classNames('fa fa-fw', { 'fa-play': paused, 'fa-pause': !paused })} /></button>
 | 
					            <div className='video-player__buttons left'>
 | 
				
			||||||
            <button aria-label={intl.formatMessage(muted ? messages.unmute : messages.mute)} onClick={this.toggleMute}><i className={classNames('fa fa-fw', { 'fa-volume-off': muted, 'fa-volume-up': !muted })} /></button>
 | 
					              <button aria-label={intl.formatMessage(paused ? messages.play : messages.pause)} onClick={this.togglePlay}><i className={classNames('fa fa-fw', { 'fa-play': paused, 'fa-pause': !paused })} /></button>
 | 
				
			||||||
            {!onCloseVideo && <button aria-label={intl.formatMessage(messages.hide)} onClick={this.toggleReveal}><i className='fa fa-fw fa-eye' /></button>}
 | 
					              <button aria-label={intl.formatMessage(muted ? messages.unmute : messages.mute)} onClick={this.toggleMute}><i className={classNames('fa fa-fw', { 'fa-volume-off': muted, 'fa-volume-up': !muted })} /></button>
 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
          <div className='video-player__buttons right'>
 | 
					              {!onCloseVideo && <button aria-label={intl.formatMessage(messages.hide)} onClick={this.toggleReveal}><i className='fa fa-fw fa-eye' /></button>}
 | 
				
			||||||
            {(!fullscreen && onOpenVideo) && <button aria-label={intl.formatMessage(messages.expand)} onClick={this.handleOpenVideo}><i className='fa fa-fw fa-expand' /></button>}
 | 
					
 | 
				
			||||||
            {onCloseVideo && <button aria-label={intl.formatMessage(messages.close)} onClick={this.handleCloseVideo}><i className='fa fa-fw fa-times' /></button>}
 | 
					              {(detailed || fullscreen) &&
 | 
				
			||||||
            <button aria-label={intl.formatMessage(fullscreen ? messages.exit_fullscreen : messages.fullscreen)} onClick={this.toggleFullscreen}><i className={classNames('fa fa-fw', { 'fa-arrows-alt': !fullscreen, 'fa-compress': fullscreen })} /></button>
 | 
					                <span>
 | 
				
			||||||
 | 
					                  <span className='video-player__time-current'>{formatTime(currentTime)}</span>
 | 
				
			||||||
 | 
					                  <span className='video-player__time-sep'>/</span>
 | 
				
			||||||
 | 
					                  <span className='video-player__time-total'>{formatTime(duration)}</span>
 | 
				
			||||||
 | 
					                </span>
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <div className='video-player__buttons right'>
 | 
				
			||||||
 | 
					              {(!fullscreen && onOpenVideo) && <button aria-label={intl.formatMessage(messages.expand)} onClick={this.handleOpenVideo}><i className='fa fa-fw fa-expand' /></button>}
 | 
				
			||||||
 | 
					              {onCloseVideo && <button aria-label={intl.formatMessage(messages.close)} onClick={this.handleCloseVideo}><i className='fa fa-fw fa-compress' /></button>}
 | 
				
			||||||
 | 
					              <button aria-label={intl.formatMessage(fullscreen ? messages.exit_fullscreen : messages.fullscreen)} onClick={this.toggleFullscreen}><i className={classNames('fa fa-fw', { 'fa-arrows-alt': !fullscreen, 'fa-compress': fullscreen })} /></button>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
 | 
				
			|||||||
@ -36,9 +36,9 @@
 | 
				
			|||||||
  "column.favourites": "المفضلة",
 | 
					  "column.favourites": "المفضلة",
 | 
				
			||||||
  "column.follow_requests": "طلبات المتابعة",
 | 
					  "column.follow_requests": "طلبات المتابعة",
 | 
				
			||||||
  "column.home": "الرئيسية",
 | 
					  "column.home": "الرئيسية",
 | 
				
			||||||
  "column.lists": "Lists",
 | 
					  "column.lists": "القوائم",
 | 
				
			||||||
  "column.mutes": "الحسابات المكتومة",
 | 
					  "column.mutes": "الحسابات المكتومة",
 | 
				
			||||||
  "column.notifications": "الإشعارات",
 | 
					  "column.notifications": "الإخطارات",
 | 
				
			||||||
  "column.pins": "التبويقات المثبتة",
 | 
					  "column.pins": "التبويقات المثبتة",
 | 
				
			||||||
  "column.public": "الخيط العام الموحد",
 | 
					  "column.public": "الخيط العام الموحد",
 | 
				
			||||||
  "column_back_button.label": "العودة",
 | 
					  "column_back_button.label": "العودة",
 | 
				
			||||||
@ -64,7 +64,7 @@
 | 
				
			|||||||
  "confirmations.delete.confirm": "حذف",
 | 
					  "confirmations.delete.confirm": "حذف",
 | 
				
			||||||
  "confirmations.delete.message": "هل أنت متأكد أنك تريد حذف هذا المنشور ؟",
 | 
					  "confirmations.delete.message": "هل أنت متأكد أنك تريد حذف هذا المنشور ؟",
 | 
				
			||||||
  "confirmations.delete_list.confirm": "Delete",
 | 
					  "confirmations.delete_list.confirm": "Delete",
 | 
				
			||||||
  "confirmations.delete_list.message": "Are you sure you want to permanently delete this list?",
 | 
					  "confirmations.delete_list.message": "هل تود حقا حذف هذه القائمة ؟",
 | 
				
			||||||
  "confirmations.domain_block.confirm": "إخفاء إسم النطاق كاملا",
 | 
					  "confirmations.domain_block.confirm": "إخفاء إسم النطاق كاملا",
 | 
				
			||||||
  "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.",
 | 
					  "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.",
 | 
				
			||||||
  "confirmations.mute.confirm": "أكتم",
 | 
					  "confirmations.mute.confirm": "أكتم",
 | 
				
			||||||
@ -109,32 +109,32 @@
 | 
				
			|||||||
  "home.settings": "إعدادات العمود",
 | 
					  "home.settings": "إعدادات العمود",
 | 
				
			||||||
  "keyboard_shortcuts.back": "للعودة",
 | 
					  "keyboard_shortcuts.back": "للعودة",
 | 
				
			||||||
  "keyboard_shortcuts.boost": "للترقية",
 | 
					  "keyboard_shortcuts.boost": "للترقية",
 | 
				
			||||||
  "keyboard_shortcuts.column": "to focus a status in one of the columns",
 | 
					  "keyboard_shortcuts.column": "للتركيز على منشور على أحد الأعمدة",
 | 
				
			||||||
  "keyboard_shortcuts.compose": "to focus the compose textarea",
 | 
					  "keyboard_shortcuts.compose": "للتركيز على نافذة تحرير النصوص",
 | 
				
			||||||
  "keyboard_shortcuts.description": "Description",
 | 
					  "keyboard_shortcuts.description": "Description",
 | 
				
			||||||
  "keyboard_shortcuts.down": "للإنتقال إلى أسفل القائمة",
 | 
					  "keyboard_shortcuts.down": "للإنتقال إلى أسفل القائمة",
 | 
				
			||||||
  "keyboard_shortcuts.enter": "to open status",
 | 
					  "keyboard_shortcuts.enter": "to open status",
 | 
				
			||||||
  "keyboard_shortcuts.favourite": "to favourite",
 | 
					  "keyboard_shortcuts.favourite": "للإضافة إلى المفضلة",
 | 
				
			||||||
  "keyboard_shortcuts.heading": "Keyboard Shortcuts",
 | 
					  "keyboard_shortcuts.heading": "Keyboard Shortcuts",
 | 
				
			||||||
  "keyboard_shortcuts.hotkey": "Hotkey",
 | 
					  "keyboard_shortcuts.hotkey": "مفتاح الإختصار",
 | 
				
			||||||
  "keyboard_shortcuts.legend": "to display this legend",
 | 
					  "keyboard_shortcuts.legend": "لعرض هذا المفتاح",
 | 
				
			||||||
  "keyboard_shortcuts.mention": "لذِكر الناشر",
 | 
					  "keyboard_shortcuts.mention": "لذِكر الناشر",
 | 
				
			||||||
  "keyboard_shortcuts.reply": "للردّ",
 | 
					  "keyboard_shortcuts.reply": "للردّ",
 | 
				
			||||||
  "keyboard_shortcuts.search": "to focus search",
 | 
					  "keyboard_shortcuts.search": "للتركيز على البحث",
 | 
				
			||||||
  "keyboard_shortcuts.toot": "لتحرير تبويق جديد",
 | 
					  "keyboard_shortcuts.toot": "لتحرير تبويق جديد",
 | 
				
			||||||
  "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
 | 
					  "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
 | 
				
			||||||
  "keyboard_shortcuts.up": "للإنتقال إلى أعلى القائمة",
 | 
					  "keyboard_shortcuts.up": "للإنتقال إلى أعلى القائمة",
 | 
				
			||||||
  "lightbox.close": "إغلاق",
 | 
					  "lightbox.close": "إغلاق",
 | 
				
			||||||
  "lightbox.next": "التالي",
 | 
					  "lightbox.next": "التالي",
 | 
				
			||||||
  "lightbox.previous": "العودة",
 | 
					  "lightbox.previous": "العودة",
 | 
				
			||||||
  "lists.account.add": "Add to list",
 | 
					  "lists.account.add": "أضف إلى القائمة",
 | 
				
			||||||
  "lists.account.remove": "Remove from list",
 | 
					  "lists.account.remove": "إحذف من القائمة",
 | 
				
			||||||
  "lists.delete": "Delete list",
 | 
					  "lists.delete": "Delete list",
 | 
				
			||||||
  "lists.edit": "Edit list",
 | 
					  "lists.edit": "تعديل القائمة",
 | 
				
			||||||
  "lists.new.create": "Add list",
 | 
					  "lists.new.create": "إنشاء قائمة",
 | 
				
			||||||
  "lists.new.title_placeholder": "New list title",
 | 
					  "lists.new.title_placeholder": "عنوان القائمة الجديدة",
 | 
				
			||||||
  "lists.search": "Search among follows",
 | 
					  "lists.search": "إبحث في قائمة الحسابات التي تُتابِعها",
 | 
				
			||||||
  "lists.subheading": "Your lists",
 | 
					  "lists.subheading": "قوائمك",
 | 
				
			||||||
  "loading_indicator.label": "تحميل ...",
 | 
					  "loading_indicator.label": "تحميل ...",
 | 
				
			||||||
  "media_gallery.toggle_visible": "عرض / إخفاء",
 | 
					  "media_gallery.toggle_visible": "عرض / إخفاء",
 | 
				
			||||||
  "missing_indicator.label": "تعذر العثور عليه",
 | 
					  "missing_indicator.label": "تعذر العثور عليه",
 | 
				
			||||||
@ -146,7 +146,7 @@
 | 
				
			|||||||
  "navigation_bar.follow_requests": "طلبات المتابعة",
 | 
					  "navigation_bar.follow_requests": "طلبات المتابعة",
 | 
				
			||||||
  "navigation_bar.info": "معلومات إضافية",
 | 
					  "navigation_bar.info": "معلومات إضافية",
 | 
				
			||||||
  "navigation_bar.keyboard_shortcuts": "إختصارات لوحة المفاتيح",
 | 
					  "navigation_bar.keyboard_shortcuts": "إختصارات لوحة المفاتيح",
 | 
				
			||||||
  "navigation_bar.lists": "Lists",
 | 
					  "navigation_bar.lists": "القوائم",
 | 
				
			||||||
  "navigation_bar.logout": "خروج",
 | 
					  "navigation_bar.logout": "خروج",
 | 
				
			||||||
  "navigation_bar.mutes": "الحسابات المكتومة",
 | 
					  "navigation_bar.mutes": "الحسابات المكتومة",
 | 
				
			||||||
  "navigation_bar.pins": "التبويقات المثبتة",
 | 
					  "navigation_bar.pins": "التبويقات المثبتة",
 | 
				
			||||||
@ -209,7 +209,7 @@
 | 
				
			|||||||
  "search_popout.search_format": "نمط البحث المتقدم",
 | 
					  "search_popout.search_format": "نمط البحث المتقدم",
 | 
				
			||||||
  "search_popout.tips.hashtag": "وسم",
 | 
					  "search_popout.tips.hashtag": "وسم",
 | 
				
			||||||
  "search_popout.tips.status": "حالة",
 | 
					  "search_popout.tips.status": "حالة",
 | 
				
			||||||
  "search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags",
 | 
					  "search_popout.tips.text": "جملة قصيرة تُمكّنُك من عرض أسماء و حسابات و كلمات رمزية",
 | 
				
			||||||
  "search_popout.tips.user": "مستخدِم",
 | 
					  "search_popout.tips.user": "مستخدِم",
 | 
				
			||||||
  "search_results.total": "{count, number} {count, plural, one {result} و {results}}",
 | 
					  "search_results.total": "{count, number} {count, plural, one {result} و {results}}",
 | 
				
			||||||
  "standalone.public_title": "نظرة على ...",
 | 
					  "standalone.public_title": "نظرة على ...",
 | 
				
			||||||
 | 
				
			|||||||
@ -133,7 +133,7 @@
 | 
				
			|||||||
  "lists.edit": "Edit list",
 | 
					  "lists.edit": "Edit list",
 | 
				
			||||||
  "lists.new.create": "Add list",
 | 
					  "lists.new.create": "Add list",
 | 
				
			||||||
  "lists.new.title_placeholder": "New list title",
 | 
					  "lists.new.title_placeholder": "New list title",
 | 
				
			||||||
  "lists.search": "Search among follows",
 | 
					  "lists.search": "Search among people you follow",
 | 
				
			||||||
  "lists.subheading": "Your lists",
 | 
					  "lists.subheading": "Your lists",
 | 
				
			||||||
  "loading_indicator.label": "Зареждане...",
 | 
					  "loading_indicator.label": "Зареждане...",
 | 
				
			||||||
  "media_gallery.toggle_visible": "Toggle visibility",
 | 
					  "media_gallery.toggle_visible": "Toggle visibility",
 | 
				
			||||||
 | 
				
			|||||||
@ -36,7 +36,7 @@
 | 
				
			|||||||
  "column.favourites": "Favorits",
 | 
					  "column.favourites": "Favorits",
 | 
				
			||||||
  "column.follow_requests": "Peticions per seguir-te",
 | 
					  "column.follow_requests": "Peticions per seguir-te",
 | 
				
			||||||
  "column.home": "Inici",
 | 
					  "column.home": "Inici",
 | 
				
			||||||
  "column.lists": "Lists",
 | 
					  "column.lists": "Llistes",
 | 
				
			||||||
  "column.mutes": "Usuaris silenciats",
 | 
					  "column.mutes": "Usuaris silenciats",
 | 
				
			||||||
  "column.notifications": "Notificacions",
 | 
					  "column.notifications": "Notificacions",
 | 
				
			||||||
  "column.pins": "Toot fixat",
 | 
					  "column.pins": "Toot fixat",
 | 
				
			||||||
@ -64,7 +64,7 @@
 | 
				
			|||||||
  "confirmations.delete.confirm": "Esborrar",
 | 
					  "confirmations.delete.confirm": "Esborrar",
 | 
				
			||||||
  "confirmations.delete.message": "Estàs segur que vols esborrar aquest estat?",
 | 
					  "confirmations.delete.message": "Estàs segur que vols esborrar aquest estat?",
 | 
				
			||||||
  "confirmations.delete_list.confirm": "Delete",
 | 
					  "confirmations.delete_list.confirm": "Delete",
 | 
				
			||||||
  "confirmations.delete_list.message": "Are you sure you want to permanently delete this list?",
 | 
					  "confirmations.delete_list.message": "Estàs segur que vols esborrar permanenment aquesta llista?",
 | 
				
			||||||
  "confirmations.domain_block.confirm": "Amagar tot el domini",
 | 
					  "confirmations.domain_block.confirm": "Amagar tot el domini",
 | 
				
			||||||
  "confirmations.domain_block.message": "Estàs realment, realment segur que vols bloquejar totalment {domain}? En la majoria dels casos bloquejar o silenciar és suficient i preferible.",
 | 
					  "confirmations.domain_block.message": "Estàs realment, realment segur que vols bloquejar totalment {domain}? En la majoria dels casos bloquejar o silenciar és suficient i preferible.",
 | 
				
			||||||
  "confirmations.mute.confirm": "Silenciar",
 | 
					  "confirmations.mute.confirm": "Silenciar",
 | 
				
			||||||
@ -127,14 +127,14 @@
 | 
				
			|||||||
  "lightbox.close": "Tancar",
 | 
					  "lightbox.close": "Tancar",
 | 
				
			||||||
  "lightbox.next": "Següent",
 | 
					  "lightbox.next": "Següent",
 | 
				
			||||||
  "lightbox.previous": "Anterior",
 | 
					  "lightbox.previous": "Anterior",
 | 
				
			||||||
  "lists.account.add": "Add to list",
 | 
					  "lists.account.add": "Afegir a la llista",
 | 
				
			||||||
  "lists.account.remove": "Remove from list",
 | 
					  "lists.account.remove": "Treure de la llista",
 | 
				
			||||||
  "lists.delete": "Delete list",
 | 
					  "lists.delete": "Delete list",
 | 
				
			||||||
  "lists.edit": "Edit list",
 | 
					  "lists.edit": "Editar llista",
 | 
				
			||||||
  "lists.new.create": "Add list",
 | 
					  "lists.new.create": "Afegir llista",
 | 
				
			||||||
  "lists.new.title_placeholder": "New list title",
 | 
					  "lists.new.title_placeholder": "Nou títol de llista",
 | 
				
			||||||
  "lists.search": "Search among follows",
 | 
					  "lists.search": "Cercar entre les persones que segueixes",
 | 
				
			||||||
  "lists.subheading": "Your lists",
 | 
					  "lists.subheading": "Les teves llistes",
 | 
				
			||||||
  "loading_indicator.label": "Carregant...",
 | 
					  "loading_indicator.label": "Carregant...",
 | 
				
			||||||
  "media_gallery.toggle_visible": "Alternar visibilitat",
 | 
					  "media_gallery.toggle_visible": "Alternar visibilitat",
 | 
				
			||||||
  "missing_indicator.label": "No trobat",
 | 
					  "missing_indicator.label": "No trobat",
 | 
				
			||||||
@ -146,7 +146,7 @@
 | 
				
			|||||||
  "navigation_bar.follow_requests": "Sol·licituds de seguiment",
 | 
					  "navigation_bar.follow_requests": "Sol·licituds de seguiment",
 | 
				
			||||||
  "navigation_bar.info": "Informació addicional",
 | 
					  "navigation_bar.info": "Informació addicional",
 | 
				
			||||||
  "navigation_bar.keyboard_shortcuts": "Dreceres de teclat",
 | 
					  "navigation_bar.keyboard_shortcuts": "Dreceres de teclat",
 | 
				
			||||||
  "navigation_bar.lists": "Lists",
 | 
					  "navigation_bar.lists": "Llistes",
 | 
				
			||||||
  "navigation_bar.logout": "Tancar sessió",
 | 
					  "navigation_bar.logout": "Tancar sessió",
 | 
				
			||||||
  "navigation_bar.mutes": "Usuaris silenciats",
 | 
					  "navigation_bar.mutes": "Usuaris silenciats",
 | 
				
			||||||
  "navigation_bar.pins": "Toots fixats",
 | 
					  "navigation_bar.pins": "Toots fixats",
 | 
				
			||||||
 | 
				
			|||||||
@ -133,7 +133,7 @@
 | 
				
			|||||||
  "lists.edit": "Edit list",
 | 
					  "lists.edit": "Edit list",
 | 
				
			||||||
  "lists.new.create": "Add list",
 | 
					  "lists.new.create": "Add list",
 | 
				
			||||||
  "lists.new.title_placeholder": "New list title",
 | 
					  "lists.new.title_placeholder": "New list title",
 | 
				
			||||||
  "lists.search": "Search among follows",
 | 
					  "lists.search": "Search among people you follow",
 | 
				
			||||||
  "lists.subheading": "Your lists",
 | 
					  "lists.subheading": "Your lists",
 | 
				
			||||||
  "loading_indicator.label": "Wird geladen …",
 | 
					  "loading_indicator.label": "Wird geladen …",
 | 
				
			||||||
  "media_gallery.toggle_visible": "Sichtbarkeit umschalten",
 | 
					  "media_gallery.toggle_visible": "Sichtbarkeit umschalten",
 | 
				
			||||||
 | 
				
			|||||||
@ -1293,6 +1293,19 @@
 | 
				
			|||||||
    ],
 | 
					    ],
 | 
				
			||||||
    "path": "app/javascript/mastodon/features/ui/components/boost_modal.json"
 | 
					    "path": "app/javascript/mastodon/features/ui/components/boost_modal.json"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    "descriptors": [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        "defaultMessage": "Favourite",
 | 
				
			||||||
 | 
					        "id": "status.favourite"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        "defaultMessage": "You can press {combo} to skip this next time",
 | 
				
			||||||
 | 
					        "id": "favourite_modal.combo"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    "path": "app/javascript/mastodon/features/ui/components/favourite_modal.json"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    "descriptors": [
 | 
					    "descriptors": [
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
@ -1601,4 +1614,4 @@
 | 
				
			|||||||
    ],
 | 
					    ],
 | 
				
			||||||
    "path": "app/javascript/mastodon/features/video/index.json"
 | 
					    "path": "app/javascript/mastodon/features/video/index.json"
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
				
			|||||||
@ -33,6 +33,7 @@
 | 
				
			|||||||
  "bundle_modal_error.retry": "Try again",
 | 
					  "bundle_modal_error.retry": "Try again",
 | 
				
			||||||
  "column.blocks": "Blocked users",
 | 
					  "column.blocks": "Blocked users",
 | 
				
			||||||
  "column.community": "Local timeline",
 | 
					  "column.community": "Local timeline",
 | 
				
			||||||
 | 
					  "column.direct": "Direct messages",
 | 
				
			||||||
  "column.favourites": "Favourites",
 | 
					  "column.favourites": "Favourites",
 | 
				
			||||||
  "column.follow_requests": "Follow requests",
 | 
					  "column.follow_requests": "Follow requests",
 | 
				
			||||||
  "column.home": "Home",
 | 
					  "column.home": "Home",
 | 
				
			||||||
@ -88,10 +89,11 @@
 | 
				
			|||||||
  "emoji_button.symbols": "Symbols",
 | 
					  "emoji_button.symbols": "Symbols",
 | 
				
			||||||
  "emoji_button.travel": "Travel & Places",
 | 
					  "emoji_button.travel": "Travel & Places",
 | 
				
			||||||
  "empty_column.community": "The local timeline is empty. Write something publicly to get the ball rolling!",
 | 
					  "empty_column.community": "The local timeline is empty. Write something publicly to get the ball rolling!",
 | 
				
			||||||
 | 
					  "empty_column.direct": "You don't have any direct messages yet. When you send or receive one, it will show up here.",
 | 
				
			||||||
  "empty_column.hashtag": "There is nothing in this hashtag yet.",
 | 
					  "empty_column.hashtag": "There is nothing in this hashtag yet.",
 | 
				
			||||||
  "empty_column.home": "Your home timeline is empty! Visit {public} or use search to get started and meet other users.",
 | 
					  "empty_column.home": "Your home timeline is empty! Visit {public} or use search to get started and meet other users.",
 | 
				
			||||||
  "empty_column.home.public_timeline": "the public timeline",
 | 
					  "empty_column.home.public_timeline": "the public timeline",
 | 
				
			||||||
  "empty_column.list": "There is nothing in this list yet.",
 | 
					  "empty_column.list": "There is nothing in this list yet. When members of this list post new statuses, they will appear here.",
 | 
				
			||||||
  "empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.",
 | 
					  "empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.",
 | 
				
			||||||
  "empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other instances to fill it up",
 | 
					  "empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other instances to fill it up",
 | 
				
			||||||
  "follow_request.authorize": "Authorize",
 | 
					  "follow_request.authorize": "Authorize",
 | 
				
			||||||
@ -133,7 +135,7 @@
 | 
				
			|||||||
  "lists.edit": "Edit list",
 | 
					  "lists.edit": "Edit list",
 | 
				
			||||||
  "lists.new.create": "Add list",
 | 
					  "lists.new.create": "Add list",
 | 
				
			||||||
  "lists.new.title_placeholder": "New list title",
 | 
					  "lists.new.title_placeholder": "New list title",
 | 
				
			||||||
  "lists.search": "Search among follows",
 | 
					  "lists.search": "Search among people you follow",
 | 
				
			||||||
  "lists.subheading": "Your lists",
 | 
					  "lists.subheading": "Your lists",
 | 
				
			||||||
  "loading_indicator.label": "Loading...",
 | 
					  "loading_indicator.label": "Loading...",
 | 
				
			||||||
  "media_gallery.toggle_visible": "Toggle visibility",
 | 
					  "media_gallery.toggle_visible": "Toggle visibility",
 | 
				
			||||||
@ -141,6 +143,7 @@
 | 
				
			|||||||
  "mute_modal.hide_notifications": "Hide notifications from this user?",
 | 
					  "mute_modal.hide_notifications": "Hide notifications from this user?",
 | 
				
			||||||
  "navigation_bar.blocks": "Blocked users",
 | 
					  "navigation_bar.blocks": "Blocked users",
 | 
				
			||||||
  "navigation_bar.community_timeline": "Local timeline",
 | 
					  "navigation_bar.community_timeline": "Local timeline",
 | 
				
			||||||
 | 
					  "navigation_bar.direct": "Direct messages",
 | 
				
			||||||
  "navigation_bar.edit_profile": "Edit profile",
 | 
					  "navigation_bar.edit_profile": "Edit profile",
 | 
				
			||||||
  "navigation_bar.favourites": "Favourites",
 | 
					  "navigation_bar.favourites": "Favourites",
 | 
				
			||||||
  "navigation_bar.follow_requests": "Follow requests",
 | 
					  "navigation_bar.follow_requests": "Follow requests",
 | 
				
			||||||
 | 
				
			|||||||
@ -133,7 +133,7 @@
 | 
				
			|||||||
  "lists.edit": "Edit list",
 | 
					  "lists.edit": "Edit list",
 | 
				
			||||||
  "lists.new.create": "Add list",
 | 
					  "lists.new.create": "Add list",
 | 
				
			||||||
  "lists.new.title_placeholder": "New list title",
 | 
					  "lists.new.title_placeholder": "New list title",
 | 
				
			||||||
  "lists.search": "Search among follows",
 | 
					  "lists.search": "Search among people you follow",
 | 
				
			||||||
  "lists.subheading": "Your lists",
 | 
					  "lists.subheading": "Your lists",
 | 
				
			||||||
  "loading_indicator.label": "Ŝarganta…",
 | 
					  "loading_indicator.label": "Ŝarganta…",
 | 
				
			||||||
  "media_gallery.toggle_visible": "Baskuli videblecon",
 | 
					  "media_gallery.toggle_visible": "Baskuli videblecon",
 | 
				
			||||||
 | 
				
			|||||||
@ -133,7 +133,7 @@
 | 
				
			|||||||
  "lists.edit": "Edit list",
 | 
					  "lists.edit": "Edit list",
 | 
				
			||||||
  "lists.new.create": "Add list",
 | 
					  "lists.new.create": "Add list",
 | 
				
			||||||
  "lists.new.title_placeholder": "New list title",
 | 
					  "lists.new.title_placeholder": "New list title",
 | 
				
			||||||
  "lists.search": "Search among follows",
 | 
					  "lists.search": "Search among people you follow",
 | 
				
			||||||
  "lists.subheading": "Your lists",
 | 
					  "lists.subheading": "Your lists",
 | 
				
			||||||
  "loading_indicator.label": "Cargando…",
 | 
					  "loading_indicator.label": "Cargando…",
 | 
				
			||||||
  "media_gallery.toggle_visible": "Cambiar visibilidad",
 | 
					  "media_gallery.toggle_visible": "Cambiar visibilidad",
 | 
				
			||||||
 | 
				
			|||||||
@ -133,7 +133,7 @@
 | 
				
			|||||||
  "lists.edit": "Edit list",
 | 
					  "lists.edit": "Edit list",
 | 
				
			||||||
  "lists.new.create": "Add list",
 | 
					  "lists.new.create": "Add list",
 | 
				
			||||||
  "lists.new.title_placeholder": "New list title",
 | 
					  "lists.new.title_placeholder": "New list title",
 | 
				
			||||||
  "lists.search": "Search among follows",
 | 
					  "lists.search": "Search among people you follow",
 | 
				
			||||||
  "lists.subheading": "Your lists",
 | 
					  "lists.subheading": "Your lists",
 | 
				
			||||||
  "loading_indicator.label": "بارگیری...",
 | 
					  "loading_indicator.label": "بارگیری...",
 | 
				
			||||||
  "media_gallery.toggle_visible": "تغییر پیدایی",
 | 
					  "media_gallery.toggle_visible": "تغییر پیدایی",
 | 
				
			||||||
 | 
				
			|||||||
@ -133,7 +133,7 @@
 | 
				
			|||||||
  "lists.edit": "Edit list",
 | 
					  "lists.edit": "Edit list",
 | 
				
			||||||
  "lists.new.create": "Add list",
 | 
					  "lists.new.create": "Add list",
 | 
				
			||||||
  "lists.new.title_placeholder": "New list title",
 | 
					  "lists.new.title_placeholder": "New list title",
 | 
				
			||||||
  "lists.search": "Search among follows",
 | 
					  "lists.search": "Search among people you follow",
 | 
				
			||||||
  "lists.subheading": "Your lists",
 | 
					  "lists.subheading": "Your lists",
 | 
				
			||||||
  "loading_indicator.label": "Ladataan...",
 | 
					  "loading_indicator.label": "Ladataan...",
 | 
				
			||||||
  "media_gallery.toggle_visible": "Toggle visibility",
 | 
					  "media_gallery.toggle_visible": "Toggle visibility",
 | 
				
			||||||
 | 
				
			|||||||
@ -63,8 +63,8 @@
 | 
				
			|||||||
  "confirmations.block.message": "Confirmez-vous le blocage de {name} ?",
 | 
					  "confirmations.block.message": "Confirmez-vous le blocage de {name} ?",
 | 
				
			||||||
  "confirmations.delete.confirm": "Supprimer",
 | 
					  "confirmations.delete.confirm": "Supprimer",
 | 
				
			||||||
  "confirmations.delete.message": "Confirmez-vous la suppression de ce pouet ?",
 | 
					  "confirmations.delete.message": "Confirmez-vous la suppression de ce pouet ?",
 | 
				
			||||||
  "confirmations.delete_list.confirm": "Delete",
 | 
					  "confirmations.delete_list.confirm": "Supprimer",
 | 
				
			||||||
  "confirmations.delete_list.message": "Are you sure you want to permanently delete this list?",
 | 
					  "confirmations.delete_list.message": "Êtes-vous sûr de vouloir supprimer définitivement cette liste ?",
 | 
				
			||||||
  "confirmations.domain_block.confirm": "Masquer le domaine entier",
 | 
					  "confirmations.domain_block.confirm": "Masquer le domaine entier",
 | 
				
			||||||
  "confirmations.domain_block.message": "Êtes-vous vraiment, vraiment sûr⋅e de vouloir bloquer {domain} en entier ? Dans la plupart des cas, quelques blocages ou masquages ciblés sont suffisants et préférables.",
 | 
					  "confirmations.domain_block.message": "Êtes-vous vraiment, vraiment sûr⋅e de vouloir bloquer {domain} en entier ? Dans la plupart des cas, quelques blocages ou masquages ciblés sont suffisants et préférables.",
 | 
				
			||||||
  "confirmations.mute.confirm": "Masquer",
 | 
					  "confirmations.mute.confirm": "Masquer",
 | 
				
			||||||
@ -91,7 +91,7 @@
 | 
				
			|||||||
  "empty_column.hashtag": "Il n’y a encore aucun contenu associé à ce hashtag",
 | 
					  "empty_column.hashtag": "Il n’y a encore aucun contenu associé à ce hashtag",
 | 
				
			||||||
  "empty_column.home": "Vous ne suivez encore personne. Visitez {public} ou bien utilisez la recherche pour vous connecter à d’autres utilisateur⋅ice⋅s.",
 | 
					  "empty_column.home": "Vous ne suivez encore personne. Visitez {public} ou bien utilisez la recherche pour vous connecter à d’autres utilisateur⋅ice⋅s.",
 | 
				
			||||||
  "empty_column.home.public_timeline": "le fil public",
 | 
					  "empty_column.home.public_timeline": "le fil public",
 | 
				
			||||||
  "empty_column.list": "Il n'y a rien dans cette liste pour l'instant.",
 | 
					  "empty_column.list": "Il n'y a rien dans cette liste pour l'instant. Dès que des personnes de cette liste publierons de nouveaux statuts, ils apparaîtront ici.",
 | 
				
			||||||
  "empty_column.notifications": "Vous n’avez pas encore de notification. Interagissez avec d’autres utilisateur⋅ice⋅s pour débuter la conversation.",
 | 
					  "empty_column.notifications": "Vous n’avez pas encore de notification. Interagissez avec d’autres utilisateur⋅ice⋅s pour débuter la conversation.",
 | 
				
			||||||
  "empty_column.public": "Il n’y a rien ici ! Écrivez quelque chose publiquement, ou bien suivez manuellement des utilisateur⋅ice⋅s d’autres instances pour remplir le fil public.",
 | 
					  "empty_column.public": "Il n’y a rien ici ! Écrivez quelque chose publiquement, ou bien suivez manuellement des utilisateur⋅ice⋅s d’autres instances pour remplir le fil public.",
 | 
				
			||||||
  "follow_request.authorize": "Accepter",
 | 
					  "follow_request.authorize": "Accepter",
 | 
				
			||||||
@ -113,28 +113,28 @@
 | 
				
			|||||||
  "keyboard_shortcuts.compose": "pour centrer la zone de redaction",
 | 
					  "keyboard_shortcuts.compose": "pour centrer la zone de redaction",
 | 
				
			||||||
  "keyboard_shortcuts.description": "Description",
 | 
					  "keyboard_shortcuts.description": "Description",
 | 
				
			||||||
  "keyboard_shortcuts.down": "descendre dans la liste",
 | 
					  "keyboard_shortcuts.down": "descendre dans la liste",
 | 
				
			||||||
  "keyboard_shortcuts.enter": "to open status",
 | 
					  "keyboard_shortcuts.enter": "pour ouvrir le statut",
 | 
				
			||||||
  "keyboard_shortcuts.favourite": "to favourite",
 | 
					  "keyboard_shortcuts.favourite": "vers les favoris",
 | 
				
			||||||
  "keyboard_shortcuts.heading": "Keyboard Shortcuts",
 | 
					  "keyboard_shortcuts.heading": "Raccourcis clavier",
 | 
				
			||||||
  "keyboard_shortcuts.hotkey": "Hotkey",
 | 
					  "keyboard_shortcuts.hotkey": "Raccourci",
 | 
				
			||||||
  "keyboard_shortcuts.legend": "to display this legend",
 | 
					  "keyboard_shortcuts.legend": "pour afficher cette légende",
 | 
				
			||||||
  "keyboard_shortcuts.mention": "to mention author",
 | 
					  "keyboard_shortcuts.mention": "pour mentionner l'auteur",
 | 
				
			||||||
  "keyboard_shortcuts.reply": "to reply",
 | 
					  "keyboard_shortcuts.reply": "pour répondre",
 | 
				
			||||||
  "keyboard_shortcuts.search": "to focus search",
 | 
					  "keyboard_shortcuts.search": "to focus search",
 | 
				
			||||||
  "keyboard_shortcuts.toot": "to start a brand new toot",
 | 
					  "keyboard_shortcuts.toot": "pour démarrer un tout nouveau pouet",
 | 
				
			||||||
  "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
 | 
					  "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
 | 
				
			||||||
  "keyboard_shortcuts.up": "to move up in the list",
 | 
					  "keyboard_shortcuts.up": "to move up in the list",
 | 
				
			||||||
  "lightbox.close": "Fermer",
 | 
					  "lightbox.close": "Fermer",
 | 
				
			||||||
  "lightbox.next": "Suivant",
 | 
					  "lightbox.next": "Suivant",
 | 
				
			||||||
  "lightbox.previous": "Précédent",
 | 
					  "lightbox.previous": "Précédent",
 | 
				
			||||||
  "lists.account.add": "Add to list",
 | 
					  "lists.account.add": "Ajouter à la liste",
 | 
				
			||||||
  "lists.account.remove": "Remove from list",
 | 
					  "lists.account.remove": "Supprimer de la liste",
 | 
				
			||||||
  "lists.delete": "Delete list",
 | 
					  "lists.delete": "Effacer la liste",
 | 
				
			||||||
  "lists.edit": "Edit list",
 | 
					  "lists.edit": "Éditer la liste",
 | 
				
			||||||
  "lists.new.create": "Add list",
 | 
					  "lists.new.create": "Ajouter une liste",
 | 
				
			||||||
  "lists.new.title_placeholder": "New list title",
 | 
					  "lists.new.title_placeholder": "Titre de la nouvelle liste",
 | 
				
			||||||
  "lists.search": "Search among follows",
 | 
					  "lists.search": "Rechercher parmi les gens que vous suivez",
 | 
				
			||||||
  "lists.subheading": "Your lists",
 | 
					  "lists.subheading": "Vos listes",
 | 
				
			||||||
  "loading_indicator.label": "Chargement…",
 | 
					  "loading_indicator.label": "Chargement…",
 | 
				
			||||||
  "media_gallery.toggle_visible": "Modifier la visibilité",
 | 
					  "media_gallery.toggle_visible": "Modifier la visibilité",
 | 
				
			||||||
  "missing_indicator.label": "Non trouvé",
 | 
					  "missing_indicator.label": "Non trouvé",
 | 
				
			||||||
@ -145,8 +145,8 @@
 | 
				
			|||||||
  "navigation_bar.favourites": "Favoris",
 | 
					  "navigation_bar.favourites": "Favoris",
 | 
				
			||||||
  "navigation_bar.follow_requests": "Demandes de suivi",
 | 
					  "navigation_bar.follow_requests": "Demandes de suivi",
 | 
				
			||||||
  "navigation_bar.info": "Plus d’informations",
 | 
					  "navigation_bar.info": "Plus d’informations",
 | 
				
			||||||
  "navigation_bar.keyboard_shortcuts": "Keyboard shortcuts",
 | 
					  "navigation_bar.keyboard_shortcuts": "Raccourcis clavier",
 | 
				
			||||||
  "navigation_bar.lists": "Lists",
 | 
					  "navigation_bar.lists": "Listes",
 | 
				
			||||||
  "navigation_bar.logout": "Déconnexion",
 | 
					  "navigation_bar.logout": "Déconnexion",
 | 
				
			||||||
  "navigation_bar.mutes": "Comptes masqués",
 | 
					  "navigation_bar.mutes": "Comptes masqués",
 | 
				
			||||||
  "navigation_bar.pins": "Pouets épinglés",
 | 
					  "navigation_bar.pins": "Pouets épinglés",
 | 
				
			||||||
@ -241,7 +241,7 @@
 | 
				
			|||||||
  "tabs_bar.home": "Accueil",
 | 
					  "tabs_bar.home": "Accueil",
 | 
				
			||||||
  "tabs_bar.local_timeline": "Fil public local",
 | 
					  "tabs_bar.local_timeline": "Fil public local",
 | 
				
			||||||
  "tabs_bar.notifications": "Notifications",
 | 
					  "tabs_bar.notifications": "Notifications",
 | 
				
			||||||
  "ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
 | 
					  "ui.beforeunload": "Votre brouillon sera perdu si vous quittez Mastodon.",
 | 
				
			||||||
  "upload_area.title": "Glissez et déposez pour envoyer",
 | 
					  "upload_area.title": "Glissez et déposez pour envoyer",
 | 
				
			||||||
  "upload_button.label": "Joindre un média",
 | 
					  "upload_button.label": "Joindre un média",
 | 
				
			||||||
  "upload_form.description": "Décrire pour les malvoyants",
 | 
					  "upload_form.description": "Décrire pour les malvoyants",
 | 
				
			||||||
 | 
				
			|||||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user