Finalized theme loading and stuff
This commit is contained in:
		
							parent
							
								
									321fa41930
								
							
						
					
					
						commit
						bdbbd06dad
					
				| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
# frozen_string_literal: true
 | 
					# frozen_string_literal: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class AboutController < ApplicationController
 | 
					class AboutController < ApplicationController
 | 
				
			||||||
 | 
					  before_action :set_pack
 | 
				
			||||||
  before_action :set_body_classes
 | 
					  before_action :set_body_classes
 | 
				
			||||||
  before_action :set_instance_presenter, only: [:show, :more, :terms]
 | 
					  before_action :set_instance_presenter, only: [:show, :more, :terms]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,6 +22,10 @@ class AboutController < ApplicationController
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  helper_method :new_user
 | 
					  helper_method :new_user
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def set_pack
 | 
				
			||||||
 | 
					    use_pack action_name == 'show' ? 'about' : 'common'
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def set_instance_presenter
 | 
					  def set_instance_presenter
 | 
				
			||||||
    @instance_presenter = InstancePresenter.new
 | 
					    @instance_presenter = InstancePresenter.new
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,6 +7,7 @@ class AccountsController < ApplicationController
 | 
				
			||||||
  def show
 | 
					  def show
 | 
				
			||||||
    respond_to do |format|
 | 
					    respond_to do |format|
 | 
				
			||||||
      format.html do
 | 
					      format.html do
 | 
				
			||||||
 | 
					        use_pack 'public'
 | 
				
			||||||
        @pinned_statuses = []
 | 
					        @pinned_statuses = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if current_account && @account.blocking?(current_account)
 | 
					        if current_account && @account.blocking?(current_account)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,8 +4,13 @@ module Admin
 | 
				
			||||||
  class BaseController < ApplicationController
 | 
					  class BaseController < ApplicationController
 | 
				
			||||||
    include Authorization
 | 
					    include Authorization
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    before_action :require_staff!
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    layout 'admin'
 | 
					    layout 'admin'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    before_action :require_staff!
 | 
				
			||||||
 | 
					    before_action :set_pack
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def set_pack
 | 
				
			||||||
 | 
					      use_pack 'admin'
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,8 +12,6 @@ class ApplicationController < ActionController::Base
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  helper_method :current_account
 | 
					  helper_method :current_account
 | 
				
			||||||
  helper_method :current_session
 | 
					  helper_method :current_session
 | 
				
			||||||
  helper_method :current_theme
 | 
					 | 
				
			||||||
  helper_method :theme_data
 | 
					 | 
				
			||||||
  helper_method :single_user_mode?
 | 
					  helper_method :single_user_mode?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  rescue_from ActionController::RoutingError, with: :not_found
 | 
					  rescue_from ActionController::RoutingError, with: :not_found
 | 
				
			||||||
| 
						 | 
					@ -54,6 +52,69 @@ class ApplicationController < ActionController::Base
 | 
				
			||||||
    new_user_session_path
 | 
					    new_user_session_path
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def pack(data, pack_name)
 | 
				
			||||||
 | 
					    return nil unless pack?(data, pack_name)
 | 
				
			||||||
 | 
					    pack_data = {
 | 
				
			||||||
 | 
					      common: pack_name == 'common' ? nil : resolve_pack(data['name'] ? Themes.instance.get(current_theme) : Themes.instance.core, 'common'),
 | 
				
			||||||
 | 
					      name: data['name'],
 | 
				
			||||||
 | 
					      pack: pack_name,
 | 
				
			||||||
 | 
					      preload: nil,
 | 
				
			||||||
 | 
					      stylesheet: false
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if data['pack'][pack_name].is_a?(Hash)
 | 
				
			||||||
 | 
					      pack_data[:common] = nil if data['pack'][pack_name]['use_common'] == false
 | 
				
			||||||
 | 
					      pack_data[:pack] = nil unless data['pack'][pack_name]['filename']
 | 
				
			||||||
 | 
					      if data['pack'][pack_name]['preload']
 | 
				
			||||||
 | 
					        pack_data[:preload] = [data['pack'][pack_name]['preload']] if data['pack'][pack_name]['preload'].is_a?(String)
 | 
				
			||||||
 | 
					        pack_data[:preload] = data['pack'][pack_name]['preload'] if data['pack'][pack_name]['preload'].is_a?(Array)
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					      pack_data[:stylesheet] = true if data['pack'][pack_name]['stylesheet']
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    pack_data
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def pack?(data, pack_name)
 | 
				
			||||||
 | 
					    if data['pack'].is_a?(Hash) && data['pack'].key?(pack_name)
 | 
				
			||||||
 | 
					      return true if data['pack'][pack_name].is_a?(String) || data['pack'][pack_name].is_a?(Hash)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    false
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def nil_pack(data, pack_name)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      common: pack_name == 'common' ? nil : resolve_pack(data['name'] ? Themes.instance.get(current_theme) : Themes.instance.core, 'common'),
 | 
				
			||||||
 | 
					      name: data['name'],
 | 
				
			||||||
 | 
					      pack: nil,
 | 
				
			||||||
 | 
					      preload: nil,
 | 
				
			||||||
 | 
					      stylesheet: false
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def resolve_pack(data, pack_name)
 | 
				
			||||||
 | 
					    result = pack(data, pack_name)
 | 
				
			||||||
 | 
					    unless result
 | 
				
			||||||
 | 
					      if data['name'] && data.key?('fallback')
 | 
				
			||||||
 | 
					        if data['fallback'].nil?
 | 
				
			||||||
 | 
					          return nil_pack(data, pack_name)
 | 
				
			||||||
 | 
					        elsif data['fallback'].is_a?(String) && Themes.instance.get(data['fallback'])
 | 
				
			||||||
 | 
					          return resolve_pack(Themes.instance.get(data['fallback']), pack_name)
 | 
				
			||||||
 | 
					        elsif data['fallback'].is_a?(Array)
 | 
				
			||||||
 | 
					          data['fallback'].each do |fallback|
 | 
				
			||||||
 | 
					            return resolve_pack(Themes.instance.get(fallback), pack_name) if Themes.instance.get(fallback)
 | 
				
			||||||
 | 
					          end
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					        return nil_pack(data, pack_name)
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					      return data.key?('name') && data['name'] != default_theme ? resolve_pack(Themes.instance.get(default_theme), pack_name) : nil_pack(data, pack_name)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    result
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def use_pack(pack_name)
 | 
				
			||||||
 | 
					    @core = resolve_pack(Themes.instance.core, pack_name)
 | 
				
			||||||
 | 
					    @theme = resolve_pack(Themes.instance.get(current_theme), pack_name)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  protected
 | 
					  protected
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def forbidden
 | 
					  def forbidden
 | 
				
			||||||
| 
						 | 
					@ -84,13 +145,13 @@ class ApplicationController < ActionController::Base
 | 
				
			||||||
    @current_session ||= SessionActivation.find_by(session_id: cookies.signed['_session_id'])
 | 
					    @current_session ||= SessionActivation.find_by(session_id: cookies.signed['_session_id'])
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def current_theme
 | 
					  def default_theme
 | 
				
			||||||
    return Setting.default_settings['theme'] unless Themes.instance.names.include? current_user&.setting_theme
 | 
					    Setting.default_settings['theme']
 | 
				
			||||||
    current_user.setting_theme
 | 
					 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def theme_data
 | 
					  def current_theme
 | 
				
			||||||
    Themes.instance.get(current_theme)
 | 
					    return default_theme unless Themes.instance.names.include? current_user&.setting_theme
 | 
				
			||||||
 | 
					    current_user.setting_theme
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def cache_collection(raw, klass)
 | 
					  def cache_collection(raw, klass)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,10 +2,17 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Auth::ConfirmationsController < Devise::ConfirmationsController
 | 
					class Auth::ConfirmationsController < Devise::ConfirmationsController
 | 
				
			||||||
  layout 'auth'
 | 
					  layout 'auth'
 | 
				
			||||||
 | 
					  before_action :set_pack
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def show
 | 
					  def show
 | 
				
			||||||
    super do |user|
 | 
					    super do |user|
 | 
				
			||||||
      BootstrapTimelineWorker.perform_async(user.account_id) if user.errors.empty?
 | 
					      BootstrapTimelineWorker.perform_async(user.account_id) if user.errors.empty?
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  private
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def set_pack
 | 
				
			||||||
 | 
					    use_pack 'auth'
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Auth::PasswordsController < Devise::PasswordsController
 | 
					class Auth::PasswordsController < Devise::PasswordsController
 | 
				
			||||||
  before_action :check_validity_of_reset_password_token, only: :edit
 | 
					  before_action :check_validity_of_reset_password_token, only: :edit
 | 
				
			||||||
 | 
					  before_action :set_pack
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  layout 'auth'
 | 
					  layout 'auth'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,4 +18,8 @@ class Auth::PasswordsController < Devise::PasswordsController
 | 
				
			||||||
  def reset_password_token_is_valid?
 | 
					  def reset_password_token_is_valid?
 | 
				
			||||||
    resource_class.with_reset_password_token(params[:reset_password_token]).present?
 | 
					    resource_class.with_reset_password_token(params[:reset_password_token]).present?
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def set_pack
 | 
				
			||||||
 | 
					    use_pack 'auth'
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  before_action :check_enabled_registrations, only: [:new, :create]
 | 
					  before_action :check_enabled_registrations, only: [:new, :create]
 | 
				
			||||||
  before_action :configure_sign_up_params, only: [:create]
 | 
					  before_action :configure_sign_up_params, only: [:create]
 | 
				
			||||||
 | 
					  before_action :set_path
 | 
				
			||||||
  before_action :set_sessions, only: [:edit, :update]
 | 
					  before_action :set_sessions, only: [:edit, :update]
 | 
				
			||||||
  before_action :set_instance_presenter, only: [:new, :create, :update]
 | 
					  before_action :set_instance_presenter, only: [:new, :create, :update]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,6 +41,10 @@ class Auth::RegistrationsController < Devise::RegistrationsController
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private
 | 
					  private
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def set_pack
 | 
				
			||||||
 | 
					    use_pack %w(edit update).include?(action_name) ? 'admin' : 'auth'
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def set_instance_presenter
 | 
					  def set_instance_presenter
 | 
				
			||||||
    @instance_presenter = InstancePresenter.new
 | 
					    @instance_presenter = InstancePresenter.new
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,6 +9,7 @@ class Auth::SessionsController < Devise::SessionsController
 | 
				
			||||||
  skip_before_action :check_suspension, only: [:destroy]
 | 
					  skip_before_action :check_suspension, only: [:destroy]
 | 
				
			||||||
  prepend_before_action :authenticate_with_two_factor, if: :two_factor_enabled?, only: [:create]
 | 
					  prepend_before_action :authenticate_with_two_factor, if: :two_factor_enabled?, only: [:create]
 | 
				
			||||||
  before_action :set_instance_presenter, only: [:new]
 | 
					  before_action :set_instance_presenter, only: [:new]
 | 
				
			||||||
 | 
					  before_action :set_pack
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def create
 | 
					  def create
 | 
				
			||||||
    super do |resource|
 | 
					    super do |resource|
 | 
				
			||||||
| 
						 | 
					@ -85,6 +86,10 @@ class Auth::SessionsController < Devise::SessionsController
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private
 | 
					  private
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def set_pack
 | 
				
			||||||
 | 
					    use_pack 'auth'
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def set_instance_presenter
 | 
					  def set_instance_presenter
 | 
				
			||||||
    @instance_presenter = InstancePresenter.new
 | 
					    @instance_presenter = InstancePresenter.new
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,6 +4,7 @@ class AuthorizeFollowsController < ApplicationController
 | 
				
			||||||
  layout 'modal'
 | 
					  layout 'modal'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  before_action :authenticate_user!
 | 
					  before_action :authenticate_user!
 | 
				
			||||||
 | 
					  before_action :set_pack
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def show
 | 
					  def show
 | 
				
			||||||
    @account = located_account || render(:error)
 | 
					    @account = located_account || render(:error)
 | 
				
			||||||
| 
						 | 
					@ -23,6 +24,10 @@ class AuthorizeFollowsController < ApplicationController
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private
 | 
					  private
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def set_pack
 | 
				
			||||||
 | 
					    use_pack 'modal'
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def follow_attempt
 | 
					  def follow_attempt
 | 
				
			||||||
    FollowService.new.call(current_account, acct_without_prefix)
 | 
					    FollowService.new.call(current_account, acct_without_prefix)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,7 +7,9 @@ class FollowerAccountsController < ApplicationController
 | 
				
			||||||
    @follows = Follow.where(target_account: @account).recent.page(params[:page]).per(FOLLOW_PER_PAGE).preload(:account)
 | 
					    @follows = Follow.where(target_account: @account).recent.page(params[:page]).per(FOLLOW_PER_PAGE).preload(:account)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    respond_to do |format|
 | 
					    respond_to do |format|
 | 
				
			||||||
      format.html
 | 
					      format.html do
 | 
				
			||||||
 | 
					        use_pack 'public'
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      format.json do
 | 
					      format.json do
 | 
				
			||||||
        render json: collection_presenter,
 | 
					        render json: collection_presenter,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,7 +7,9 @@ class FollowingAccountsController < ApplicationController
 | 
				
			||||||
    @follows = Follow.where(account: @account).recent.page(params[:page]).per(FOLLOW_PER_PAGE).preload(:target_account)
 | 
					    @follows = Follow.where(account: @account).recent.page(params[:page]).per(FOLLOW_PER_PAGE).preload(:target_account)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    respond_to do |format|
 | 
					    respond_to do |format|
 | 
				
			||||||
      format.html
 | 
					      format.html do
 | 
				
			||||||
 | 
					        use_pack 'public'
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      format.json do
 | 
					      format.json do
 | 
				
			||||||
        render json: collection_presenter,
 | 
					        render json: collection_presenter,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class HomeController < ApplicationController
 | 
					class HomeController < ApplicationController
 | 
				
			||||||
  before_action :authenticate_user!
 | 
					  before_action :authenticate_user!
 | 
				
			||||||
 | 
					  before_action :set_pack
 | 
				
			||||||
  before_action :set_initial_state_json
 | 
					  before_action :set_initial_state_json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def index
 | 
					  def index
 | 
				
			||||||
| 
						 | 
					@ -37,6 +38,10 @@ class HomeController < ApplicationController
 | 
				
			||||||
    redirect_to(default_redirect_path)
 | 
					    redirect_to(default_redirect_path)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def set_pack
 | 
				
			||||||
 | 
					    use_pack 'home'
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def set_initial_state_json
 | 
					  def set_initial_state_json
 | 
				
			||||||
    serializable_resource = ActiveModelSerializers::SerializableResource.new(InitialStatePresenter.new(initial_state_params), serializer: InitialStateSerializer)
 | 
					    serializable_resource = ActiveModelSerializers::SerializableResource.new(InitialStatePresenter.new(initial_state_params), serializer: InitialStateSerializer)
 | 
				
			||||||
    @initial_state_json   = serializable_resource.to_json
 | 
					    @initial_state_json   = serializable_resource.to_json
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,6 +4,7 @@ class RemoteFollowController < ApplicationController
 | 
				
			||||||
  layout 'modal'
 | 
					  layout 'modal'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  before_action :set_account
 | 
					  before_action :set_account
 | 
				
			||||||
 | 
					  before_action :set_pack
 | 
				
			||||||
  before_action :gone, if: :suspended_account?
 | 
					  before_action :gone, if: :suspended_account?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def new
 | 
					  def new
 | 
				
			||||||
| 
						 | 
					@ -31,6 +32,10 @@ class RemoteFollowController < ApplicationController
 | 
				
			||||||
    { acct: session[:remote_follow] }
 | 
					    { acct: session[:remote_follow] }
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def set_pack
 | 
				
			||||||
 | 
					    use_pack 'modal'
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def set_account
 | 
					  def set_account
 | 
				
			||||||
    @account = Account.find_local!(params[:account_username])
 | 
					    @account = Account.find_local!(params[:account_username])
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,7 @@
 | 
				
			||||||
# frozen_string_literal: true
 | 
					# frozen_string_literal: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Settings::ApplicationsController < ApplicationController
 | 
					class Settings::ApplicationsController < Settings::BaseController
 | 
				
			||||||
  layout 'admin'
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  before_action :authenticate_user!
 | 
					 | 
				
			||||||
  before_action :set_application, only: [:show, :update, :destroy, :regenerate]
 | 
					  before_action :set_application, only: [:show, :update, :destroy, :regenerate]
 | 
				
			||||||
  before_action :prepare_scopes, only: [:create, :update]
 | 
					  before_action :prepare_scopes, only: [:create, :update]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,12 @@
 | 
				
			||||||
 | 
					# frozen_string_literal: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Settings::BaseController < ApplicationController
 | 
				
			||||||
 | 
					  layout 'admin'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  before_action :authenticate_user!
 | 
				
			||||||
 | 
					  before_action :set_pack
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def set_pack
 | 
				
			||||||
 | 
					    use_pack 'settings'
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
| 
						 | 
					@ -1,10 +1,8 @@
 | 
				
			||||||
# frozen_string_literal: true
 | 
					# frozen_string_literal: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Settings::DeletesController < ApplicationController
 | 
					class Settings::DeletesController < Settings::BaseController
 | 
				
			||||||
  layout 'admin'
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  before_action :check_enabled_deletion
 | 
					  before_action :check_enabled_deletion
 | 
				
			||||||
  before_action :authenticate_user!
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def show
 | 
					  def show
 | 
				
			||||||
    @confirmation = Form::DeleteConfirmation.new
 | 
					    @confirmation = Form::DeleteConfirmation.new
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,10 +1,6 @@
 | 
				
			||||||
# frozen_string_literal: true
 | 
					# frozen_string_literal: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Settings::ExportsController < ApplicationController
 | 
					class Settings::ExportsController < Settings::BaseController
 | 
				
			||||||
  layout 'admin'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  before_action :authenticate_user!
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def show
 | 
					  def show
 | 
				
			||||||
    @export = Export.new(current_account)
 | 
					    @export = Export.new(current_account)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,11 +2,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require 'sidekiq-bulk'
 | 
					require 'sidekiq-bulk'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Settings::FollowerDomainsController < ApplicationController
 | 
					class Settings::FollowerDomainsController < Settings::BaseController
 | 
				
			||||||
  layout 'admin'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  before_action :authenticate_user!
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def show
 | 
					  def show
 | 
				
			||||||
    @account = current_account
 | 
					    @account = current_account
 | 
				
			||||||
    @domains = current_account.followers.reorder('MIN(follows.id) DESC').group('accounts.domain').select('accounts.domain, count(accounts.id) as accounts_from_domain').page(params[:page]).per(10)
 | 
					    @domains = current_account.followers.reorder('MIN(follows.id) DESC').group('accounts.domain').select('accounts.domain, count(accounts.id) as accounts_from_domain').page(params[:page]).per(10)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,6 @@
 | 
				
			||||||
# frozen_string_literal: true
 | 
					# frozen_string_literal: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Settings::ImportsController < ApplicationController
 | 
					class Settings::ImportsController < Settings::BaseController
 | 
				
			||||||
  layout 'admin'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  before_action :authenticate_user!
 | 
					 | 
				
			||||||
  before_action :set_account
 | 
					  before_action :set_account
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def show
 | 
					  def show
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,6 @@
 | 
				
			||||||
# frozen_string_literal: true
 | 
					# frozen_string_literal: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Settings::KeywordMutesController < ApplicationController
 | 
					class Settings::KeywordMutesController < Settings::BaseController
 | 
				
			||||||
  layout 'admin'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  before_action :authenticate_user!
 | 
					 | 
				
			||||||
  before_action :load_keyword_mute, only: [:edit, :update, :destroy]
 | 
					  before_action :load_keyword_mute, only: [:edit, :update, :destroy]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def index
 | 
					  def index
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,10 +1,6 @@
 | 
				
			||||||
# frozen_string_literal: true
 | 
					# frozen_string_literal: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Settings::NotificationsController < ApplicationController
 | 
					class Settings::NotificationsController < Settings::BaseController
 | 
				
			||||||
  layout 'admin'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  before_action :authenticate_user!
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def show; end
 | 
					  def show; end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def update
 | 
					  def update
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,10 +1,6 @@
 | 
				
			||||||
# frozen_string_literal: true
 | 
					# frozen_string_literal: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Settings::PreferencesController < ApplicationController
 | 
					class Settings::PreferencesController < Settings::BaseController
 | 
				
			||||||
  layout 'admin'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  before_action :authenticate_user!
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def show; end
 | 
					  def show; end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def update
 | 
					  def update
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,11 +1,8 @@
 | 
				
			||||||
# frozen_string_literal: true
 | 
					# frozen_string_literal: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Settings::ProfilesController < ApplicationController
 | 
					class Settings::ProfilesController < Settings::BaseController
 | 
				
			||||||
  include ObfuscateFilename
 | 
					  include ObfuscateFilename
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  layout 'admin'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  before_action :authenticate_user!
 | 
					 | 
				
			||||||
  before_action :set_account
 | 
					  before_action :set_account
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  obfuscate_filename [:account, :avatar]
 | 
					  obfuscate_filename [:account, :avatar]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,6 @@
 | 
				
			||||||
# frozen_string_literal: true
 | 
					# frozen_string_literal: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#  Intentionally does not inherit from BaseController
 | 
				
			||||||
class Settings::SessionsController < ApplicationController
 | 
					class Settings::SessionsController < ApplicationController
 | 
				
			||||||
  before_action :set_session, only: :destroy
 | 
					  before_action :set_session, only: :destroy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,10 +1,7 @@
 | 
				
			||||||
# frozen_string_literal: true
 | 
					# frozen_string_literal: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module Settings
 | 
					module Settings
 | 
				
			||||||
  class TwoFactorAuthenticationsController < ApplicationController
 | 
					  class TwoFactorAuthenticationsController < BaseController
 | 
				
			||||||
    layout 'admin'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    before_action :authenticate_user!
 | 
					 | 
				
			||||||
    before_action :verify_otp_required, only: [:create]
 | 
					    before_action :verify_otp_required, only: [:create]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def show
 | 
					    def show
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,6 +4,7 @@ class SharesController < ApplicationController
 | 
				
			||||||
  layout 'modal'
 | 
					  layout 'modal'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  before_action :authenticate_user!
 | 
					  before_action :authenticate_user!
 | 
				
			||||||
 | 
					  before_action :set_pack
 | 
				
			||||||
  before_action :set_body_classes
 | 
					  before_action :set_body_classes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def show
 | 
					  def show
 | 
				
			||||||
| 
						 | 
					@ -24,6 +25,10 @@ class SharesController < ApplicationController
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def set_pack
 | 
				
			||||||
 | 
					    use_pack 'share'
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def set_body_classes
 | 
					  def set_body_classes
 | 
				
			||||||
    @body_classes = 'compose-standalone'
 | 
					    @body_classes = 'compose-standalone'
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,6 +14,7 @@ class StatusesController < ApplicationController
 | 
				
			||||||
  def show
 | 
					  def show
 | 
				
			||||||
    respond_to do |format|
 | 
					    respond_to do |format|
 | 
				
			||||||
      format.html do
 | 
					      format.html do
 | 
				
			||||||
 | 
					        use_pack 'public'
 | 
				
			||||||
        @ancestors   = @status.reply? ? cache_collection(@status.ancestors(current_account), Status) : []
 | 
					        @ancestors   = @status.reply? ? cache_collection(@status.ancestors(current_account), Status) : []
 | 
				
			||||||
        @descendants = cache_collection(@status.descendants(current_account), Status)
 | 
					        @descendants = cache_collection(@status.descendants(current_account), Status)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,6 +38,7 @@ class StatusesController < ApplicationController
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def embed
 | 
					  def embed
 | 
				
			||||||
 | 
					    use_pack 'embed'
 | 
				
			||||||
    response.headers['X-Frame-Options'] = 'ALLOWALL'
 | 
					    response.headers['X-Frame-Options'] = 'ALLOWALL'
 | 
				
			||||||
    render 'stream_entries/embed', layout: 'embedded'
 | 
					    render 'stream_entries/embed', layout: 'embedded'
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,6 +14,7 @@ class StreamEntriesController < ApplicationController
 | 
				
			||||||
  def show
 | 
					  def show
 | 
				
			||||||
    respond_to do |format|
 | 
					    respond_to do |format|
 | 
				
			||||||
      format.html do
 | 
					      format.html do
 | 
				
			||||||
 | 
					        use_pack 'public'
 | 
				
			||||||
        @ancestors   = @stream_entry.activity.reply? ? cache_collection(@stream_entry.activity.ancestors(current_account), Status) : []
 | 
					        @ancestors   = @stream_entry.activity.reply? ? cache_collection(@stream_entry.activity.ancestors(current_account), Status) : []
 | 
				
			||||||
        @descendants = cache_collection(@stream_entry.activity.descendants(current_account), Status)
 | 
					        @descendants = cache_collection(@stream_entry.activity.descendants(current_account), Status)
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,6 +9,7 @@ class TagsController < ApplicationController
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    respond_to do |format|
 | 
					    respond_to do |format|
 | 
				
			||||||
      format.html do
 | 
					      format.html do
 | 
				
			||||||
 | 
					        use_pack 'about'
 | 
				
			||||||
        serializable_resource = ActiveModelSerializers::SerializableResource.new(InitialStatePresenter.new(initial_state_params), serializer: InitialStateSerializer)
 | 
					        serializable_resource = ActiveModelSerializers::SerializableResource.new(InitialStatePresenter.new(initial_state_params), serializer: InitialStateSerializer)
 | 
				
			||||||
        @initial_state_json   = serializable_resource.to_json
 | 
					        @initial_state_json   = serializable_resource.to_json
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1 +0,0 @@
 | 
				
			||||||
//  This file will be loaded on about pages, regardless of theme.
 | 
					 | 
				
			||||||
| 
						 | 
					@ -13,7 +13,7 @@ window.addEventListener('message', e => {
 | 
				
			||||||
      id: data.id,
 | 
					      id: data.id,
 | 
				
			||||||
      height: document.getElementsByTagName('html')[0].scrollHeight,
 | 
					      height: document.getElementsByTagName('html')[0].scrollHeight,
 | 
				
			||||||
    }, '*');
 | 
					    }, '*');
 | 
				
			||||||
  });
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (['interactive', 'complete'].includes(document.readyState)) {
 | 
					  if (['interactive', 'complete'].includes(document.readyState)) {
 | 
				
			||||||
    setEmbedHeight();
 | 
					    setEmbedHeight();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1 +0,0 @@
 | 
				
			||||||
//  This file will be loaded on home pages, regardless of theme.
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1 +1,25 @@
 | 
				
			||||||
//  This file will be loaded on public pages, regardless of theme.
 | 
					//  This file will be loaded on public pages, regardless of theme.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const { delegate } = require('rails-ujs');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					delegate(document, '.webapp-btn', 'click', ({ target, button }) => {
 | 
				
			||||||
 | 
					  if (button !== 0) {
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  window.location.href = target.href;
 | 
				
			||||||
 | 
					  return false;
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					delegate(document, '.status__content__spoiler-link', 'click', ({ target }) => {
 | 
				
			||||||
 | 
					  const contentEl = target.parentNode.parentNode.querySelector('.e-content');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (contentEl.style.display === 'block') {
 | 
				
			||||||
 | 
					    contentEl.style.display = 'none';
 | 
				
			||||||
 | 
					    target.parentNode.style.marginBottom = 0;
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    contentEl.style.display = 'block';
 | 
				
			||||||
 | 
					    target.parentNode.style.marginBottom = null;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return false;
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,65 +1,37 @@
 | 
				
			||||||
//  This file will be loaded on settings pages, regardless of theme.
 | 
					//  This file will be loaded on settings pages, regardless of theme.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function main() {
 | 
					const { length } = require('stringz');
 | 
				
			||||||
  const { length } = require('stringz');
 | 
					const { delegate } = require('rails-ujs');
 | 
				
			||||||
  const { delegate } = require('rails-ujs');
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  delegate(document, '.webapp-btn', 'click', ({ target, button }) => {
 | 
					delegate(document, '.account_display_name', 'input', ({ target }) => {
 | 
				
			||||||
    if (button !== 0) {
 | 
					  const nameCounter = document.querySelector('.name-counter');
 | 
				
			||||||
      return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    window.location.href = target.href;
 | 
					 | 
				
			||||||
    return false;
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  delegate(document, '.status__content__spoiler-link', 'click', ({ target }) => {
 | 
					  if (nameCounter) {
 | 
				
			||||||
    const contentEl = target.parentNode.parentNode.querySelector('.e-content');
 | 
					    nameCounter.textContent = 30 - length(target.value);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
    if (contentEl.style.display === 'block') {
 | 
					});
 | 
				
			||||||
      contentEl.style.display = 'none';
 | 
					
 | 
				
			||||||
      target.parentNode.style.marginBottom = 0;
 | 
					delegate(document, '.account_note', 'input', ({ target }) => {
 | 
				
			||||||
    } else {
 | 
					  const noteCounter = document.querySelector('.note-counter');
 | 
				
			||||||
      contentEl.style.display = 'block';
 | 
					
 | 
				
			||||||
      target.parentNode.style.marginBottom = null;
 | 
					  if (noteCounter) {
 | 
				
			||||||
    }
 | 
					    const noteWithoutMetadata = processBio(target.value).text;
 | 
				
			||||||
 | 
					    noteCounter.textContent = 500 - length(noteWithoutMetadata);
 | 
				
			||||||
    return false;
 | 
					  }
 | 
				
			||||||
  });
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  delegate(document, '.account_display_name', 'input', ({ target }) => {
 | 
					delegate(document, '#account_avatar', 'change', ({ target }) => {
 | 
				
			||||||
    const nameCounter = document.querySelector('.name-counter');
 | 
					  const avatar = document.querySelector('.card.compact .avatar img');
 | 
				
			||||||
 | 
					  const [file] = target.files || [];
 | 
				
			||||||
    if (nameCounter) {
 | 
					  const url = file ? URL.createObjectURL(file) : avatar.dataset.originalSrc;
 | 
				
			||||||
      nameCounter.textContent = 30 - length(target.value);
 | 
					
 | 
				
			||||||
    }
 | 
					  avatar.src = url;
 | 
				
			||||||
  });
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  delegate(document, '.account_note', 'input', ({ target }) => {
 | 
					delegate(document, '#account_header', 'change', ({ target }) => {
 | 
				
			||||||
    const noteCounter = document.querySelector('.note-counter');
 | 
					  const header = document.querySelector('.card.compact');
 | 
				
			||||||
 | 
					  const [file] = target.files || [];
 | 
				
			||||||
    if (noteCounter) {
 | 
					  const url = file ? URL.createObjectURL(file) : header.dataset.originalSrc;
 | 
				
			||||||
      const noteWithoutMetadata = processBio(target.value).text;
 | 
					
 | 
				
			||||||
      noteCounter.textContent = 500 - length(noteWithoutMetadata);
 | 
					  header.style.backgroundImage = `url(${url})`;
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  delegate(document, '#account_avatar', 'change', ({ target }) => {
 | 
					 | 
				
			||||||
    const avatar = document.querySelector('.card.compact .avatar img');
 | 
					 | 
				
			||||||
    const [file] = target.files || [];
 | 
					 | 
				
			||||||
    const url = file ? URL.createObjectURL(file) : avatar.dataset.originalSrc;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    avatar.src = url;
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  delegate(document, '#account_header', 'change', ({ target }) => {
 | 
					 | 
				
			||||||
    const header = document.querySelector('.card.compact');
 | 
					 | 
				
			||||||
    const [file] = target.files || [];
 | 
					 | 
				
			||||||
    const url = file ? URL.createObjectURL(file) : header.dataset.originalSrc;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    header.style.backgroundImage = `url(${url})`;
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
loadPolyfills().then(main).catch(error => {
 | 
					 | 
				
			||||||
  console.error(error);
 | 
					 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1 +0,0 @@
 | 
				
			||||||
//  This file will be loaded on share pages, regardless of theme.
 | 
					 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,14 @@
 | 
				
			||||||
 | 
					#  These packs will be loaded on every appropriate page, regardless of
 | 
				
			||||||
 | 
					#  theme.
 | 
				
			||||||
 | 
					pack:
 | 
				
			||||||
 | 
					  about:
 | 
				
			||||||
 | 
					  admin: admin.js
 | 
				
			||||||
 | 
					  auth:
 | 
				
			||||||
 | 
					  common: common.js
 | 
				
			||||||
 | 
					  embed: embed.js
 | 
				
			||||||
 | 
					  error:
 | 
				
			||||||
 | 
					  home:
 | 
				
			||||||
 | 
					  modal:
 | 
				
			||||||
 | 
					  public: public.js
 | 
				
			||||||
 | 
					  settings: settings.js
 | 
				
			||||||
 | 
					  share:
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,9 @@
 | 
				
			||||||
 | 
					let theLocale;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function setLocale(locale) {
 | 
				
			||||||
 | 
					  theLocale = locale;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function getLocale() {
 | 
				
			||||||
 | 
					  return theLocale;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1 @@
 | 
				
			||||||
let theLocale;
 | 
					export * from 'locales';
 | 
				
			||||||
 | 
					 | 
				
			||||||
export function setLocale(locale) {
 | 
					 | 
				
			||||||
  theLocale = locale;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export function getLocale() {
 | 
					 | 
				
			||||||
  return theLocale;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,22 @@
 | 
				
			||||||
 | 
					import loadPolyfills from '../mastodon/load_polyfills';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function loaded() {
 | 
				
			||||||
 | 
					  const TimelineContainer = require('../mastodon/containers/timeline_container').default;
 | 
				
			||||||
 | 
					  const React             = require('react');
 | 
				
			||||||
 | 
					  const ReactDOM          = require('react-dom');
 | 
				
			||||||
 | 
					  const mountNode         = document.getElementById('mastodon-timeline');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (mountNode !== null) {
 | 
				
			||||||
 | 
					    const props = JSON.parse(mountNode.getAttribute('data-props'));
 | 
				
			||||||
 | 
					    ReactDOM.render(<TimelineContainer {...props} />, mountNode);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function main() {
 | 
				
			||||||
 | 
					  const ready = require('../mastodon/ready').default;
 | 
				
			||||||
 | 
					  ready(loaded);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					loadPolyfills().then(main).catch(error => {
 | 
				
			||||||
 | 
					  console.error(error);
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
| 
						 | 
					@ -1,15 +1,5 @@
 | 
				
			||||||
//  THIS IS THE `vanilla` THEME PACK FILE!!
 | 
					 | 
				
			||||||
//  IT'S HERE FOR UPSTREAM COMPATIBILITY!!
 | 
					 | 
				
			||||||
//  THE `glitch` PACK FILE IS IN `themes/glitch/index.js`!!
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import loadPolyfills from '../mastodon/load_polyfills';
 | 
					import loadPolyfills from '../mastodon/load_polyfills';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// import default stylesheet with variables
 | 
					 | 
				
			||||||
import 'font-awesome/css/font-awesome.css';
 | 
					 | 
				
			||||||
import '../styles/application.scss';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
require.context('../images/', true);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
loadPolyfills().then(() => {
 | 
					loadPolyfills().then(() => {
 | 
				
			||||||
  require('../mastodon/main').default();
 | 
					  require('../mastodon/main').default();
 | 
				
			||||||
}).catch(e => {
 | 
					}).catch(e => {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,3 @@
 | 
				
			||||||
 | 
					import 'font-awesome/css/font-awesome.css';
 | 
				
			||||||
 | 
					import 'styles/application.scss'
 | 
				
			||||||
 | 
					require.context('../images/', true);
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,75 @@
 | 
				
			||||||
 | 
					import loadPolyfills from '../mastodon/load_polyfills';
 | 
				
			||||||
 | 
					import ready from '../mastodon/ready';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function main() {
 | 
				
			||||||
 | 
					  const IntlRelativeFormat = require('intl-relativeformat').default;
 | 
				
			||||||
 | 
					  const emojify = require('../mastodon/features/emoji/emoji').default;
 | 
				
			||||||
 | 
					  const { getLocale } = require('../mastodon/locales');
 | 
				
			||||||
 | 
					  const { localeData } = getLocale();
 | 
				
			||||||
 | 
					  const VideoContainer = require('../mastodon/containers/video_container').default;
 | 
				
			||||||
 | 
					  const MediaGalleryContainer = require('../mastodon/containers/media_gallery_container').default;
 | 
				
			||||||
 | 
					  const CardContainer = require('../mastodon/containers/card_container').default;
 | 
				
			||||||
 | 
					  const React = require('react');
 | 
				
			||||||
 | 
					  const ReactDOM = require('react-dom');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  localeData.forEach(IntlRelativeFormat.__addLocaleData);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ready(() => {
 | 
				
			||||||
 | 
					    const locale = document.documentElement.lang;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const dateTimeFormat = new Intl.DateTimeFormat(locale, {
 | 
				
			||||||
 | 
					      year: 'numeric',
 | 
				
			||||||
 | 
					      month: 'long',
 | 
				
			||||||
 | 
					      day: 'numeric',
 | 
				
			||||||
 | 
					      hour: 'numeric',
 | 
				
			||||||
 | 
					      minute: 'numeric',
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const relativeFormat = new IntlRelativeFormat(locale);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [].forEach.call(document.querySelectorAll('.emojify'), (content) => {
 | 
				
			||||||
 | 
					      content.innerHTML = emojify(content.innerHTML);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [].forEach.call(document.querySelectorAll('time.formatted'), (content) => {
 | 
				
			||||||
 | 
					      const datetime = new Date(content.getAttribute('datetime'));
 | 
				
			||||||
 | 
					      const formattedDate = dateTimeFormat.format(datetime);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      content.title = formattedDate;
 | 
				
			||||||
 | 
					      content.textContent = formattedDate;
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [].forEach.call(document.querySelectorAll('time.time-ago'), (content) => {
 | 
				
			||||||
 | 
					      const datetime = new Date(content.getAttribute('datetime'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      content.title = dateTimeFormat.format(datetime);
 | 
				
			||||||
 | 
					      content.textContent = relativeFormat.format(datetime);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [].forEach.call(document.querySelectorAll('.logo-button'), (content) => {
 | 
				
			||||||
 | 
					      content.addEventListener('click', (e) => {
 | 
				
			||||||
 | 
					        e.preventDefault();
 | 
				
			||||||
 | 
					        window.open(e.target.href, 'mastodon-intent', 'width=400,height=400,resizable=no,menubar=no,status=no,scrollbars=yes');
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [].forEach.call(document.querySelectorAll('[data-component="Video"]'), (content) => {
 | 
				
			||||||
 | 
					      const props = JSON.parse(content.getAttribute('data-props'));
 | 
				
			||||||
 | 
					      ReactDOM.render(<VideoContainer locale={locale} {...props} />, content);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [].forEach.call(document.querySelectorAll('[data-component="MediaGallery"]'), (content) => {
 | 
				
			||||||
 | 
					      const props = JSON.parse(content.getAttribute('data-props'));
 | 
				
			||||||
 | 
					      ReactDOM.render(<MediaGalleryContainer locale={locale} {...props} />, content);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [].forEach.call(document.querySelectorAll('[data-component="Card"]'), (content) => {
 | 
				
			||||||
 | 
					      const props = JSON.parse(content.getAttribute('data-props'));
 | 
				
			||||||
 | 
					      ReactDOM.render(<CardContainer locale={locale} {...props} />, content);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					loadPolyfills().then(main).catch(error => {
 | 
				
			||||||
 | 
					  console.error(error);
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,22 @@
 | 
				
			||||||
 | 
					import loadPolyfills from '../mastodon/load_polyfills';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function loaded() {
 | 
				
			||||||
 | 
					  const ComposeContainer = require('../mastodon/containers/compose_container').default;
 | 
				
			||||||
 | 
					  const React = require('react');
 | 
				
			||||||
 | 
					  const ReactDOM = require('react-dom');
 | 
				
			||||||
 | 
					  const mountNode = document.getElementById('mastodon-compose');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (mountNode !== null) {
 | 
				
			||||||
 | 
					    const props = JSON.parse(mountNode.getAttribute('data-props'));
 | 
				
			||||||
 | 
					    ReactDOM.render(<ComposeContainer {...props} />, mountNode);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function main() {
 | 
				
			||||||
 | 
					  const ready = require('../mastodon/ready').default;
 | 
				
			||||||
 | 
					  ready(loaded);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					loadPolyfills().then(main).catch(error => {
 | 
				
			||||||
 | 
					  console.error(error);
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
| 
						 | 
					@ -1,5 +0,0 @@
 | 
				
			||||||
// This makes our fonts available everywhere.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@import 'fonts/roboto';
 | 
					 | 
				
			||||||
@import 'fonts/roboto-mono';
 | 
					 | 
				
			||||||
@import 'fonts/montserrat';
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,8 @@
 | 
				
			||||||
 | 
					//  win95 theme from cybrespace.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//  Modified to inherit glitch styles (themes/glitch/styles/index.scss)
 | 
				
			||||||
 | 
					//  instead of vanilla ones (./application.scss)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$win95-bg: #bfbfbf;
 | 
					$win95-bg: #bfbfbf;
 | 
				
			||||||
$win95-dark-grey: #404040;
 | 
					$win95-dark-grey: #404040;
 | 
				
			||||||
$win95-mid-grey: #808080;
 | 
					$win95-mid-grey: #808080;
 | 
				
			||||||
| 
						 | 
					@ -71,7 +76,7 @@ $ui-highlight-color: $win95-window-header;
 | 
				
			||||||
  src: url('../fonts/premillenium/MSSansSerif.ttf') format('truetype');
 | 
					  src: url('../fonts/premillenium/MSSansSerif.ttf') format('truetype');
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@import 'application';
 | 
					@import '../themes/glitch/styles/index';  //  Imports glitch themes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* borrowed from cybrespace style: wider columns and full column width images */
 | 
					/* borrowed from cybrespace style: wider columns and full column width images */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,7 +9,7 @@ import UI from 'themes/glitch/features/ui';
 | 
				
			||||||
import { hydrateStore } from 'themes/glitch/actions/store';
 | 
					import { hydrateStore } from 'themes/glitch/actions/store';
 | 
				
			||||||
import { connectUserStream } from 'themes/glitch/actions/streaming';
 | 
					import { connectUserStream } from 'themes/glitch/actions/streaming';
 | 
				
			||||||
import { IntlProvider, addLocaleData } from 'react-intl';
 | 
					import { IntlProvider, addLocaleData } from 'react-intl';
 | 
				
			||||||
import { getLocale } from 'mastodon/locales';
 | 
					import { getLocale } from 'locales';
 | 
				
			||||||
import initialState from 'themes/glitch/util/initial_state';
 | 
					import initialState from 'themes/glitch/util/initial_state';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { localeData, messages } = getLocale();
 | 
					const { localeData, messages } = getLocale();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,3 @@
 | 
				
			||||||
import 'font-awesome/css/font-awesome.css';
 | 
					import 'font-awesome/css/font-awesome.css';
 | 
				
			||||||
require.context('../../images/', true);
 | 
					require.context('images/', true);
 | 
				
			||||||
import './styles/index.scss';
 | 
					import 'themes/glitch/styles/index.scss';
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
import loadPolyfills from './util/load_polyfills';
 | 
					import loadPolyfills from 'themes/glitch/util/load_polyfills';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
loadPolyfills().then(() => {
 | 
					loadPolyfills().then(() => {
 | 
				
			||||||
  require('./util/main').default();
 | 
					  require('themes/glitch/util/main').default();
 | 
				
			||||||
}).catch(e => {
 | 
					}).catch(e => {
 | 
				
			||||||
  console.error(e);
 | 
					  console.error(e);
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,32 +2,14 @@ import loadPolyfills from 'themes/glitch/util/load_polyfills';
 | 
				
			||||||
import { processBio } from 'themes/glitch/util/bio_metadata';
 | 
					import { processBio } from 'themes/glitch/util/bio_metadata';
 | 
				
			||||||
import ready from 'themes/glitch/util/ready';
 | 
					import ready from 'themes/glitch/util/ready';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
window.addEventListener('message', e => {
 | 
					 | 
				
			||||||
  const data = e.data || {};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (!window.parent || data.type !== 'setHeight') {
 | 
					 | 
				
			||||||
    return;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  ready(() => {
 | 
					 | 
				
			||||||
    window.parent.postMessage({
 | 
					 | 
				
			||||||
      type: 'setHeight',
 | 
					 | 
				
			||||||
      id: data.id,
 | 
					 | 
				
			||||||
      height: document.getElementsByTagName('html')[0].scrollHeight,
 | 
					 | 
				
			||||||
    }, '*');
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function main() {
 | 
					function main() {
 | 
				
			||||||
  const { length } = require('stringz');
 | 
					 | 
				
			||||||
  const IntlRelativeFormat = require('intl-relativeformat').default;
 | 
					  const IntlRelativeFormat = require('intl-relativeformat').default;
 | 
				
			||||||
  const { delegate } = require('rails-ujs');
 | 
					  const emojify = require('themes/glitch/util/emoji').default;
 | 
				
			||||||
  const emojify = require('../themes/glitch/util/emoji').default;
 | 
					  const { getLocale } = require('locales');
 | 
				
			||||||
  const { getLocale } = require('mastodon/locales');
 | 
					 | 
				
			||||||
  const { localeData } = getLocale();
 | 
					  const { localeData } = getLocale();
 | 
				
			||||||
  const VideoContainer = require('../themes/glitch/containers/video_container').default;
 | 
					  const VideoContainer = require('themes/glitch/containers/video_container').default;
 | 
				
			||||||
  const MediaGalleryContainer = require('../themes/glitch/containers/media_gallery_container').default;
 | 
					  const MediaGalleryContainer = require('themes/glitch/containers/media_gallery_container').default;
 | 
				
			||||||
  const CardContainer = require('../themes/glitch/containers/card_container').default;
 | 
					  const CardContainer = require('themes/glitch/containers/card_container').default;
 | 
				
			||||||
  const React = require('react');
 | 
					  const React = require('react');
 | 
				
			||||||
  const ReactDOM = require('react-dom');
 | 
					  const ReactDOM = require('react-dom');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -87,61 +69,6 @@ function main() {
 | 
				
			||||||
      ReactDOM.render(<CardContainer locale={locale} {...props} />, content);
 | 
					      ReactDOM.render(<CardContainer locale={locale} {...props} />, content);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					 | 
				
			||||||
  delegate(document, '.webapp-btn', 'click', ({ target, button }) => {
 | 
					 | 
				
			||||||
    if (button !== 0) {
 | 
					 | 
				
			||||||
      return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    window.location.href = target.href;
 | 
					 | 
				
			||||||
    return false;
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  delegate(document, '.status__content__spoiler-link', 'click', ({ target }) => {
 | 
					 | 
				
			||||||
    const contentEl = target.parentNode.parentNode.querySelector('.e-content');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (contentEl.style.display === 'block') {
 | 
					 | 
				
			||||||
      contentEl.style.display = 'none';
 | 
					 | 
				
			||||||
      target.parentNode.style.marginBottom = 0;
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      contentEl.style.display = 'block';
 | 
					 | 
				
			||||||
      target.parentNode.style.marginBottom = null;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return false;
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  delegate(document, '.account_display_name', 'input', ({ target }) => {
 | 
					 | 
				
			||||||
    const nameCounter = document.querySelector('.name-counter');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (nameCounter) {
 | 
					 | 
				
			||||||
      nameCounter.textContent = 30 - length(target.value);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  delegate(document, '.account_note', 'input', ({ target }) => {
 | 
					 | 
				
			||||||
    const noteCounter = document.querySelector('.note-counter');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (noteCounter) {
 | 
					 | 
				
			||||||
      const noteWithoutMetadata = processBio(target.value).text;
 | 
					 | 
				
			||||||
      noteCounter.textContent = 500 - length(noteWithoutMetadata);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  delegate(document, '#account_avatar', 'change', ({ target }) => {
 | 
					 | 
				
			||||||
    const avatar = document.querySelector('.card.compact .avatar img');
 | 
					 | 
				
			||||||
    const [file] = target.files || [];
 | 
					 | 
				
			||||||
    const url = file ? URL.createObjectURL(file) : avatar.dataset.originalSrc;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    avatar.src = url;
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  delegate(document, '#account_header', 'change', ({ target }) => {
 | 
					 | 
				
			||||||
    const header = document.querySelector('.card.compact');
 | 
					 | 
				
			||||||
    const [file] = target.files || [];
 | 
					 | 
				
			||||||
    const url = file ? URL.createObjectURL(file) : header.dataset.originalSrc;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    header.style.backgroundImage = `url(${url})`;
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
loadPolyfills().then(main).catch(error => {
 | 
					loadPolyfills().then(main).catch(error => {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,25 +1,34 @@
 | 
				
			||||||
#  (REQUIRED) The location of the pack files.
 | 
					#  (REQUIRED) The location of the pack files.
 | 
				
			||||||
pack:
 | 
					pack:
 | 
				
			||||||
  about: packs/about.js
 | 
					  about: packs/about.js
 | 
				
			||||||
  admin: null
 | 
					  admin:
 | 
				
			||||||
  common: packs/common.js
 | 
					  auth:
 | 
				
			||||||
  embed: null
 | 
					  common:
 | 
				
			||||||
  home: packs/home.js
 | 
					    filename: packs/common.js
 | 
				
			||||||
 | 
					    stylesheet: true
 | 
				
			||||||
 | 
					  embed: packs/public.js
 | 
				
			||||||
 | 
					  error:
 | 
				
			||||||
 | 
					  home:
 | 
				
			||||||
 | 
					    filename: packs/home.js
 | 
				
			||||||
 | 
					    preload:
 | 
				
			||||||
 | 
					    - themes/glitch/async/getting_started
 | 
				
			||||||
 | 
					    - themes/glitch/async/compose
 | 
				
			||||||
 | 
					    - themes/glitch/async/home_timeline
 | 
				
			||||||
 | 
					    - themes/glitch/async/notifications
 | 
				
			||||||
 | 
					    stylesheet: true
 | 
				
			||||||
 | 
					  modal:
 | 
				
			||||||
  public: packs/public.js
 | 
					  public: packs/public.js
 | 
				
			||||||
  settings: null
 | 
					  settings:
 | 
				
			||||||
  share: packs/share.js
 | 
					  share: packs/share.js
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#  (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.
 | 
				
			||||||
#    pack_directory: app/javascript/packs
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#  (OPTIONAL) Additional javascript resources to preload, for use with
 | 
					#      pack_directory: app/javascript/packs
 | 
				
			||||||
#  lazy-loaded components. It is **STRONGLY RECOMMENDED** that you
 | 
					
 | 
				
			||||||
#  derive these pathnames from `themes/[your-theme]` to ensure that
 | 
					#  (OPTIONAL) By default the theme will fallback to the default theme
 | 
				
			||||||
#  they stay unique.
 | 
					#  if a particular pack is not provided. You can specify different
 | 
				
			||||||
preload:
 | 
					#  fallbacks here, or disable fallback behaviours altogether by
 | 
				
			||||||
- themes/glitch/async/getting_started
 | 
					#  specifying a `null` value.
 | 
				
			||||||
- themes/glitch/async/compose
 | 
					fallback:
 | 
				
			||||||
- themes/glitch/async/home_timeline
 | 
					 | 
				
			||||||
- themes/glitch/async/notifications
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,12 +1,23 @@
 | 
				
			||||||
#  (REQUIRED) The location of the pack files inside `pack_directory`.
 | 
					#  (REQUIRED) The location of the pack files inside `pack_directory`.
 | 
				
			||||||
pack:
 | 
					pack:
 | 
				
			||||||
  about: about.js
 | 
					  about: about.js
 | 
				
			||||||
  admin: null
 | 
					  admin:
 | 
				
			||||||
  common: common.js
 | 
					  auth:
 | 
				
			||||||
  embed: null
 | 
					  common:
 | 
				
			||||||
  home: application.js
 | 
					    filename: common.js
 | 
				
			||||||
 | 
					    stylesheet: true
 | 
				
			||||||
 | 
					  embed: public.js
 | 
				
			||||||
 | 
					  error:
 | 
				
			||||||
 | 
					  home:
 | 
				
			||||||
 | 
					    filename: application.js
 | 
				
			||||||
 | 
					    preload:
 | 
				
			||||||
 | 
					    - features/getting_started
 | 
				
			||||||
 | 
					    - features/compose
 | 
				
			||||||
 | 
					    - features/home_timeline
 | 
				
			||||||
 | 
					    - features/notifications
 | 
				
			||||||
 | 
					  modal:
 | 
				
			||||||
  public: public.js
 | 
					  public: public.js
 | 
				
			||||||
  settings: null
 | 
					  settings:
 | 
				
			||||||
  share: share.js
 | 
					  share: share.js
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#  (OPTIONAL) The directory which contains the pack files.
 | 
					#  (OPTIONAL) The directory which contains the pack files.
 | 
				
			||||||
| 
						 | 
					@ -15,12 +26,8 @@ pack:
 | 
				
			||||||
#  somewhere else.
 | 
					#  somewhere else.
 | 
				
			||||||
pack_directory: app/javascript/packs
 | 
					pack_directory: app/javascript/packs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#  (OPTIONAL) Additional javascript resources to preload, for use with
 | 
					#  (OPTIONAL) By default the theme will fallback to the default theme
 | 
				
			||||||
#  lazy-loaded components. It is **STRONGLY RECOMMENDED** that you
 | 
					#  if a particular pack is not provided. You can specify different
 | 
				
			||||||
#  derive these pathnames from `themes/[your-theme]` to ensure that
 | 
					#  fallbacks here, or disable fallback behaviours altogether by
 | 
				
			||||||
#  they stay unique. (Of course, vanilla doesn't do this ^^;;)
 | 
					#  specifying a `null` value.
 | 
				
			||||||
preload:
 | 
					fallback:
 | 
				
			||||||
- features/getting_started
 | 
					 | 
				
			||||||
- features/compose
 | 
					 | 
				
			||||||
- features/home_timeline
 | 
					 | 
				
			||||||
- features/notifications
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,10 @@
 | 
				
			||||||
 | 
					//  These lines are the same as in glitch:
 | 
				
			||||||
 | 
					import 'font-awesome/css/font-awesome.css';
 | 
				
			||||||
 | 
					require.context('../../images/', true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//  …But we want to use our own styles instead.
 | 
				
			||||||
 | 
					import 'styles/win95.scss';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//  Be sure to make this style file import from
 | 
				
			||||||
 | 
					//  `themes/glitch/styles/index.scss` (the glitch styling), and not
 | 
				
			||||||
 | 
					//  `application.scss` (which are the vanilla styles).
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,23 @@
 | 
				
			||||||
 | 
					#  win95 theme.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#  Ported over from `cybrespace:mastodon/theme_win95`.
 | 
				
			||||||
 | 
					#  <https://github.com/cybrespace/mastodon/tree/theme_win95>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#  You can use this theme file as inspiration for porting over
 | 
				
			||||||
 | 
					#  a preëxisting Mastodon theme.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#  We only modify the `common` pack, which contains our styling.
 | 
				
			||||||
 | 
					pack:
 | 
				
			||||||
 | 
					  common:
 | 
				
			||||||
 | 
					    filename: index.js
 | 
				
			||||||
 | 
					    stylesheet: true
 | 
				
			||||||
 | 
					  #  All unspecified packs will inherit from glitch.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#  By default, the glitch preloads will also be used here. You can
 | 
				
			||||||
 | 
					#  disable them by setting `preload` to `null`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#      preload:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#  The `fallback` parameter tells us to use glitch files for everything
 | 
				
			||||||
 | 
					#  we haven't specified.
 | 
				
			||||||
 | 
					fallback: glitch
 | 
				
			||||||
| 
						 | 
					@ -7,15 +7,27 @@ class Themes
 | 
				
			||||||
  include Singleton
 | 
					  include Singleton
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def initialize
 | 
					  def initialize
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    core = YAML.load_file(Rails.root.join('app', 'javascript', 'core', 'theme.yml'))
 | 
				
			||||||
 | 
					    core['pack'] = Hash.new unless core['pack']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    result = Hash.new
 | 
					    result = Hash.new
 | 
				
			||||||
    Dir.glob(Rails.root.join('app', 'javascript', 'themes', '*', 'theme.yml')) do |path|
 | 
					    Dir.glob(Rails.root.join('app', 'javascript', 'themes', '*', 'theme.yml')) do |path|
 | 
				
			||||||
      data = YAML.load_file(path)
 | 
					      data = YAML.load_file(path)
 | 
				
			||||||
      name = File.basename(File.dirname(path))
 | 
					      name = File.basename(File.dirname(path))
 | 
				
			||||||
      if data['pack']
 | 
					      if data['pack']
 | 
				
			||||||
 | 
					        data['name'] = name
 | 
				
			||||||
        result[name] = data
 | 
					        result[name] = data
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @core = core
 | 
				
			||||||
    @conf = result
 | 
					    @conf = result
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def core
 | 
				
			||||||
 | 
					    @core
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def get(name)
 | 
					  def get(name)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,6 @@
 | 
				
			||||||
  = site_hostname
 | 
					  = site_hostname
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- content_for :header_tags do
 | 
					- content_for :header_tags do
 | 
				
			||||||
  = javascript_pack_tag 'public', integrity: true, crossorigin: 'anonymous'
 | 
					 | 
				
			||||||
  = render partial: 'shared/og'
 | 
					  = render partial: 'shared/og'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.landing-page
 | 
					.landing-page
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- content_for :header_tags do
 | 
					- content_for :header_tags do
 | 
				
			||||||
  %script#initial-state{ type: 'application/json' }!= json_escape(@initial_state_json)
 | 
					  %script#initial-state{ type: 'application/json' }!= json_escape(@initial_state_json)
 | 
				
			||||||
  = javascript_pack_tag 'about', integrity: true, crossorigin: 'anonymous'
 | 
					 | 
				
			||||||
  = render partial: 'shared/og'
 | 
					  = render partial: 'shared/og'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.landing-page
 | 
					.landing-page
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,3 @@
 | 
				
			||||||
- content_for :header_tags do
 | 
					 | 
				
			||||||
  = javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
- content_for :page_title do
 | 
					- content_for :page_title do
 | 
				
			||||||
  = t('admin.reports.report', id: @report.id)
 | 
					  = t('admin.reports.report', id: @report.id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,3 @@
 | 
				
			||||||
- content_for :header_tags do
 | 
					 | 
				
			||||||
  = javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
- content_for :page_title do
 | 
					- content_for :page_title do
 | 
				
			||||||
  = t('admin.statuses.title')
 | 
					  = t('admin.statuses.title')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,13 +1,7 @@
 | 
				
			||||||
- content_for :header_tags do
 | 
					- content_for :header_tags do
 | 
				
			||||||
  - if theme_data['preload']
 | 
					 | 
				
			||||||
    - theme_data['preload'].each do |link|
 | 
					 | 
				
			||||||
      %link{ href: asset_pack_path("#{link}.js"), crossorigin: 'anonymous', rel: 'preload', as: 'script' }/
 | 
					 | 
				
			||||||
  %meta{name: 'applicationServerKey', content: Rails.configuration.x.vapid_public_key}
 | 
					  %meta{name: 'applicationServerKey', content: Rails.configuration.x.vapid_public_key}
 | 
				
			||||||
  %script#initial-state{ type: 'application/json' }!= json_escape(@initial_state_json)
 | 
					  %script#initial-state{ type: 'application/json' }!= json_escape(@initial_state_json)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  = javascript_pack_tag "themes/#{current_theme}", integrity: true, crossorigin: 'anonymous'
 | 
					 | 
				
			||||||
  = stylesheet_pack_tag "themes/#{current_theme}", integrity: true, media: 'all'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.app-holder#mastodon{ data: { props: Oj.dump(default_props) } }
 | 
					.app-holder#mastodon{ data: { props: Oj.dump(default_props) } }
 | 
				
			||||||
  %noscript
 | 
					  %noscript
 | 
				
			||||||
    = image_tag asset_pack_path('logo.svg'), alt: 'Mastodon'
 | 
					    = image_tag asset_pack_path('logo.svg'), alt: 'Mastodon'
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,10 @@
 | 
				
			||||||
 | 
					- if theme
 | 
				
			||||||
 | 
					  - if theme[:pack] != 'common' && theme[:common]
 | 
				
			||||||
 | 
					    = render partial: 'layouts/theme', object: theme[:common]
 | 
				
			||||||
 | 
					  - if theme[:pack]
 | 
				
			||||||
 | 
					    = javascript_pack_tag theme[:name] ? "themes/#{theme[:name]}/#{theme[:pack]}" : "core/#{theme[:pack]}", integrity: true, crossorigin: 'anonymous'
 | 
				
			||||||
 | 
					    - if theme[:stylesheet]
 | 
				
			||||||
 | 
					      = stylesheet_pack_tag theme[:name] ? "themes/#{theme[:name]}/#{theme[:pack]}" : "core/#{theme[:pack]}", integrity: true, media: 'all'
 | 
				
			||||||
 | 
					    - if theme[:preload]
 | 
				
			||||||
 | 
					      - theme[:preload].each do |link|
 | 
				
			||||||
 | 
					        %link{ href: asset_pack_path("#{link}.js"), crossorigin: 'anonymous', rel: 'preload', as: 'script' }/
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,3 @@
 | 
				
			||||||
- content_for :header_tags do
 | 
					 | 
				
			||||||
  = javascript_pack_tag 'public', integrity: true, crossorigin: 'anonymous'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
- content_for :content do
 | 
					- content_for :content do
 | 
				
			||||||
  .admin-wrapper
 | 
					  .admin-wrapper
 | 
				
			||||||
    .sidebar-wrapper
 | 
					    .sidebar-wrapper
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,16 +18,16 @@
 | 
				
			||||||
        = ' - '
 | 
					        = ' - '
 | 
				
			||||||
      = title
 | 
					      = title
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    = stylesheet_pack_tag 'common', media: 'all'
 | 
					    = javascript_pack_tag "locales", integrity: true, crossorigin: 'anonymous'
 | 
				
			||||||
    = javascript_pack_tag 'common', integrity: true, crossorigin: 'anonymous'
 | 
					 | 
				
			||||||
    = javascript_pack_tag "locale_#{I18n.locale}", integrity: true, crossorigin: 'anonymous'
 | 
					    = javascript_pack_tag "locale_#{I18n.locale}", integrity: true, crossorigin: 'anonymous'
 | 
				
			||||||
    = csrf_meta_tags
 | 
					    = csrf_meta_tags
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    - if controller_name != 'home'
 | 
					 | 
				
			||||||
      = stylesheet_pack_tag 'application', integrity: true, media: 'all'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    = yield :header_tags
 | 
					    = yield :header_tags
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    -#  These must come after :header_tags to ensure our initial state has been defined.
 | 
				
			||||||
 | 
					    = render partial: 'layouts/theme', object: @core
 | 
				
			||||||
 | 
					    = render partial: 'layouts/theme', object: @theme
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  - body_classes ||= @body_classes || ''
 | 
					  - body_classes ||= @body_classes || ''
 | 
				
			||||||
  - body_classes += ' system-font' if current_account&.user&.setting_system_font_ui
 | 
					  - body_classes += ' system-font' if current_account&.user&.setting_system_font_ui
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,3 @@
 | 
				
			||||||
- content_for :header_tags do
 | 
					 | 
				
			||||||
  = javascript_pack_tag 'public', integrity: true, crossorigin: 'anonymous'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
- content_for :content do
 | 
					- content_for :content do
 | 
				
			||||||
  .container
 | 
					  .container
 | 
				
			||||||
    .logo-container
 | 
					    .logo-container
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,10 +4,9 @@
 | 
				
			||||||
    %meta{ charset: 'utf-8' }/
 | 
					    %meta{ charset: 'utf-8' }/
 | 
				
			||||||
    %meta{ name: 'robots', content: 'noindex' }/
 | 
					    %meta{ name: 'robots', content: 'noindex' }/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    = stylesheet_pack_tag 'common', media: 'all'
 | 
					 | 
				
			||||||
    = javascript_pack_tag 'common', integrity: true, crossorigin: 'anonymous'
 | 
					    = javascript_pack_tag 'common', integrity: true, crossorigin: 'anonymous'
 | 
				
			||||||
    = stylesheet_pack_tag 'application', integrity: true, media: 'all'
 | 
					    = javascript_pack_tag 'embed', integrity: true, crossorigin: 'anonymous'
 | 
				
			||||||
    = javascript_pack_tag "locale_#{I18n.locale}", integrity: true, crossorigin: 'anonymous'
 | 
					    = javascript_pack_tag "locale_#{I18n.locale}", integrity: true, crossorigin: 'anonymous'
 | 
				
			||||||
    = javascript_pack_tag 'public', integrity: true, crossorigin: 'anonymous'
 | 
					    = render partial: 'layouts/theme', object: @core
 | 
				
			||||||
  %body.embed
 | 
					    = render partial: 'layouts/theme', object: @theme
 | 
				
			||||||
    = yield
 | 
					    = yield
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,8 +5,8 @@
 | 
				
			||||||
    %meta{ charset: 'utf-8' }/
 | 
					    %meta{ charset: 'utf-8' }/
 | 
				
			||||||
    %title= safe_join([yield(:page_title), Setting.default_settings['site_title']], ' - ')
 | 
					    %title= safe_join([yield(:page_title), Setting.default_settings['site_title']], ' - ')
 | 
				
			||||||
    %meta{ content: 'width=device-width,initial-scale=1', name: 'viewport' }/
 | 
					    %meta{ content: 'width=device-width,initial-scale=1', name: 'viewport' }/
 | 
				
			||||||
    = stylesheet_pack_tag 'common', media: 'all'
 | 
					    = render partial: 'layouts/theme', object: @core
 | 
				
			||||||
    = stylesheet_pack_tag 'application', integrity: true, media: 'all'
 | 
					    = render partial: 'layouts/theme', object: @theme
 | 
				
			||||||
  %body.error
 | 
					  %body.error
 | 
				
			||||||
    .dialog
 | 
					    .dialog
 | 
				
			||||||
      %img{ alt: Setting.default_settings['site_title'], src: '/oops.gif' }/
 | 
					      %img{ alt: Setting.default_settings['site_title'], src: '/oops.gif' }/
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,3 @@
 | 
				
			||||||
- content_for :header_tags do
 | 
					 | 
				
			||||||
  = javascript_pack_tag 'public', integrity: true, crossorigin: 'anonymous'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
- content_for :content do
 | 
					- content_for :content do
 | 
				
			||||||
  - if user_signed_in?
 | 
					  - if user_signed_in?
 | 
				
			||||||
    .account-header
 | 
					    .account-header
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,3 @@
 | 
				
			||||||
- content_for :header_tags do
 | 
					 | 
				
			||||||
  = javascript_pack_tag 'public', integrity: true, crossorigin: 'anonymous'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
- content_for :content do
 | 
					- content_for :content do
 | 
				
			||||||
  .container= yield
 | 
					  .container= yield
 | 
				
			||||||
  .footer
 | 
					  .footer
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,4 @@
 | 
				
			||||||
- content_for :header_tags do
 | 
					- content_for :header_tags do
 | 
				
			||||||
  %script#initial-state{ type: 'application/json' }!= json_escape(@initial_state_json)
 | 
					  %script#initial-state{ type: 'application/json' }!= json_escape(@initial_state_json)
 | 
				
			||||||
  = javascript_pack_tag 'share', integrity: true, crossorigin: 'anonymous'
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#mastodon-compose{ data: { props: Oj.dump(default_props) } }
 | 
					#mastodon-compose{ data: { props: Oj.dump(default_props) } }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- content_for :header_tags do
 | 
					- content_for :header_tags do
 | 
				
			||||||
  %script#initial-state{ type: 'application/json' }!= json_escape(@initial_state_json)
 | 
					  %script#initial-state{ type: 'application/json' }!= json_escape(@initial_state_json)
 | 
				
			||||||
  = javascript_pack_tag 'about', integrity: true, crossorigin: 'anonymous'
 | 
					 | 
				
			||||||
  = render 'og'
 | 
					  = render 'og'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.landing-page.tag-page
 | 
					.landing-page.tag-page
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,14 +12,24 @@ const settings = safeLoad(readFileSync(configPath), 'utf8')[env.NODE_ENV];
 | 
				
			||||||
const themeFiles = glob.sync('app/javascript/themes/*/theme.yml');
 | 
					const themeFiles = glob.sync('app/javascript/themes/*/theme.yml');
 | 
				
			||||||
const themes = {};
 | 
					const themes = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const core = function () {
 | 
				
			||||||
 | 
					  const coreFile = resolve('app', 'javascript', 'core', 'theme.yml');
 | 
				
			||||||
 | 
					  const data = safeLoad(readFileSync(coreFile), 'utf8');
 | 
				
			||||||
 | 
					  if (!data.pack_directory) {
 | 
				
			||||||
 | 
					    data.pack_directory = dirname(coreFile);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return data.pack ? data : {};
 | 
				
			||||||
 | 
					}();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
for (let i = 0; i < themeFiles.length; i++) {
 | 
					for (let i = 0; i < themeFiles.length; i++) {
 | 
				
			||||||
  const themeFile = themeFiles[i];
 | 
					  const themeFile = themeFiles[i];
 | 
				
			||||||
  const data = safeLoad(readFileSync(themeFile), 'utf8');
 | 
					  const data = safeLoad(readFileSync(themeFile), 'utf8');
 | 
				
			||||||
 | 
					  data.name = basename(dirname(themeFile));
 | 
				
			||||||
  if (!data.pack_directory) {
 | 
					  if (!data.pack_directory) {
 | 
				
			||||||
    data.pack_directory = dirname(themeFile);
 | 
					    data.pack_directory = dirname(themeFile);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (data.pack) {
 | 
					  if (data.pack) {
 | 
				
			||||||
    themes[basename(dirname(themeFile))] = data;
 | 
					    themes[data.name] = data;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,6 +53,7 @@ const output = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = {
 | 
					module.exports = {
 | 
				
			||||||
  settings,
 | 
					  settings,
 | 
				
			||||||
 | 
					  core,
 | 
				
			||||||
  themes,
 | 
					  themes,
 | 
				
			||||||
  env,
 | 
					  env,
 | 
				
			||||||
  loadersDir,
 | 
					  loadersDir,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,7 +57,7 @@ Object.keys(glitchMessages).forEach(function (key) {
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
import messages from '../../app/javascript/mastodon/locales/${locale}.json';
 | 
					import messages from '../../app/javascript/mastodon/locales/${locale}.json';
 | 
				
			||||||
import localeData from ${JSON.stringify(localeDataPath)};
 | 
					import localeData from ${JSON.stringify(localeDataPath)};
 | 
				
			||||||
import { setLocale } from '../../app/javascript/mastodon/locales';
 | 
					import { setLocale } from 'locales';
 | 
				
			||||||
${glitchInject}
 | 
					${glitchInject}
 | 
				
			||||||
setLocale({messages: mergedMessages, localeData: localeData});
 | 
					setLocale({messages: mergedMessages, localeData: localeData});
 | 
				
			||||||
`;
 | 
					`;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,33 +6,37 @@ const { sync } = require('glob');
 | 
				
			||||||
const ExtractTextPlugin = require('extract-text-webpack-plugin');
 | 
					const ExtractTextPlugin = require('extract-text-webpack-plugin');
 | 
				
			||||||
const ManifestPlugin = require('webpack-manifest-plugin');
 | 
					const ManifestPlugin = require('webpack-manifest-plugin');
 | 
				
			||||||
const extname = require('path-complete-extname');
 | 
					const extname = require('path-complete-extname');
 | 
				
			||||||
const { env, settings, themes, output, loadersDir } = require('./configuration.js');
 | 
					const { env, settings, core, themes, output, loadersDir } = require('./configuration.js');
 | 
				
			||||||
const localePackPaths = require('./generateLocalePacks');
 | 
					const localePackPaths = require('./generateLocalePacks');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const extensionGlob = `**/*{${settings.extensions.join(',')}}*`;
 | 
					function reducePacks (data, into = {}) {
 | 
				
			||||||
const entryPath = join(settings.source_path, settings.source_entry_path);
 | 
					  if (!data.pack) {
 | 
				
			||||||
const packPaths = sync(join(entryPath, extensionGlob));
 | 
					    return into;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  Object.keys(data.pack).reduce((map, entry) => {
 | 
				
			||||||
 | 
					    const pack = data.pack[entry];
 | 
				
			||||||
 | 
					    if (!pack) {
 | 
				
			||||||
 | 
					      return map;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const packFile = typeof pack === 'string' ? pack : pack.filename;
 | 
				
			||||||
 | 
					    if (packFile) {
 | 
				
			||||||
 | 
					      map[data.name ? `themes/${data.name}/${entry}` : `core/${entry}`] = resolve(data.pack_directory, packFile);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return map;
 | 
				
			||||||
 | 
					  }, into);
 | 
				
			||||||
 | 
					  return into;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = {
 | 
					module.exports = {
 | 
				
			||||||
  entry: Object.assign(
 | 
					  entry: Object.assign(
 | 
				
			||||||
    packPaths.reduce((map, entry) => {
 | 
					    { locales: resolve('app', 'javascript', 'locales') },
 | 
				
			||||||
      const localMap = map;
 | 
					 | 
				
			||||||
      const namespace = relative(join(entryPath), dirname(entry));
 | 
					 | 
				
			||||||
      localMap[join(namespace, basename(entry, extname(entry)))] = resolve(entry);
 | 
					 | 
				
			||||||
      return localMap;
 | 
					 | 
				
			||||||
    }, {}),
 | 
					 | 
				
			||||||
    localePackPaths.reduce((map, entry) => {
 | 
					    localePackPaths.reduce((map, entry) => {
 | 
				
			||||||
      const localMap = map;
 | 
					      const localMap = map;
 | 
				
			||||||
      localMap[basename(entry, extname(entry, extname(entry)))] = resolve(entry);
 | 
					      localMap[basename(entry, extname(entry, extname(entry)))] = resolve(entry);
 | 
				
			||||||
      return localMap;
 | 
					      return localMap;
 | 
				
			||||||
    }, {}),
 | 
					    }, {}),
 | 
				
			||||||
    Object.keys(themes).reduce(
 | 
					    reducePacks(core),
 | 
				
			||||||
      (themePaths, name) => {
 | 
					    Object.keys(themes).reduce((map, entry) => reducePacks(themes[entry], map), {})
 | 
				
			||||||
        const themeData = themes[name];
 | 
					 | 
				
			||||||
        themePaths[`themes/${name}`] = resolve(themeData.pack_directory, themeData.pack);
 | 
					 | 
				
			||||||
        return themePaths;
 | 
					 | 
				
			||||||
      }, {}
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
  ),
 | 
					  ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  output: {
 | 
					  output: {
 | 
				
			||||||
| 
						 | 
					@ -64,7 +68,7 @@ module.exports = {
 | 
				
			||||||
      writeToFileEmit: true,
 | 
					      writeToFileEmit: true,
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
    new webpack.optimize.CommonsChunkPlugin({
 | 
					    new webpack.optimize.CommonsChunkPlugin({
 | 
				
			||||||
      name: 'common',
 | 
					      name: 'locales',
 | 
				
			||||||
      minChunks: Infinity, // It doesn't make sense to use common chunks with multiple frontend support.
 | 
					      minChunks: Infinity, // It doesn't make sense to use common chunks with multiple frontend support.
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
default: &default
 | 
					default: &default
 | 
				
			||||||
  source_path: app/javascript
 | 
					  source_path: app/javascript
 | 
				
			||||||
  source_entry_path: packs
 | 
					 | 
				
			||||||
  public_output_path: packs
 | 
					  public_output_path: packs
 | 
				
			||||||
  cache_path: tmp/cache/webpacker
 | 
					  cache_path: tmp/cache/webpacker
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,17 +12,6 @@ default: &default
 | 
				
			||||||
  # Reload manifest.json on all requests so we reload latest compiled packs
 | 
					  # Reload manifest.json on all requests so we reload latest compiled packs
 | 
				
			||||||
  cache_manifest: false
 | 
					  cache_manifest: false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  extensions:
 | 
					 | 
				
			||||||
    - .js
 | 
					 | 
				
			||||||
    - .sass
 | 
					 | 
				
			||||||
    - .scss
 | 
					 | 
				
			||||||
    - .css
 | 
					 | 
				
			||||||
    - .png
 | 
					 | 
				
			||||||
    - .svg
 | 
					 | 
				
			||||||
    - .gif
 | 
					 | 
				
			||||||
    - .jpeg
 | 
					 | 
				
			||||||
    - .jpg
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
development:
 | 
					development:
 | 
				
			||||||
  <<: *default
 | 
					  <<: *default
 | 
				
			||||||
  compile: true
 | 
					  compile: true
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue