diff --git a/app/controllers/settings/flavours_controller.rb b/app/controllers/settings/flavours_controller.rb
new file mode 100644
index 0000000000..865d5a4792
--- /dev/null
+++ b/app/controllers/settings/flavours_controller.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+class Settings::FlavoursController < Settings::BaseController
+
+ def index
+ redirect_to action: 'show', flavour: current_flavour
+ end
+
+ def show
+ unless Themes.instance.flavours.include?(params[:flavour]) or params[:flavour] == current_flavour
+ redirect_to action: 'show', flavour: current_flavour
+ end
+
+ @listing = Themes.instance.flavours
+ @selected = params[:flavour]
+ end
+
+ def update
+ user_settings.update(user_settings_params(params[:flavour]).to_h)
+ redirect_to action: 'show', flavour: params[:flavour]
+ end
+
+ private
+
+ def user_settings
+ UserSettingsDecorator.new(current_user)
+ end
+
+ def user_settings_params(flavour)
+ params.require(:user).merge({ setting_flavour: flavour }).permit(
+ :setting_flavour,
+ :setting_skin
+ )
+ end
+end
diff --git a/app/controllers/settings/preferences_controller.rb b/app/controllers/settings/preferences_controller.rb
index 9177d37da6..7cd1abe0c9 100644
--- a/app/controllers/settings/preferences_controller.rb
+++ b/app/controllers/settings/preferences_controller.rb
@@ -39,8 +39,6 @@ class Settings::PreferencesController < Settings::BaseController
:setting_reduce_motion,
:setting_system_font_ui,
:setting_noindex,
- :setting_flavour,
- :setting_skin,
notification_emails: %i(follow follow_request reblog favourite mention digest),
interactions: %i(must_be_follower must_be_following)
)
diff --git a/app/javascript/core/settings.js b/app/javascript/core/settings.js
index ada5fba2b1..c9edcf197c 100644
--- a/app/javascript/core/settings.js
+++ b/app/javascript/core/settings.js
@@ -37,7 +37,3 @@ delegate(document, '#account_header', 'change', ({ target }) => {
header.style.backgroundImage = `url(${url})`;
});
-
-delegate(document, '#user_setting_flavour, #user_setting_skin', 'change', ({ target }) => {
- target.form.submit();
-});
diff --git a/app/javascript/flavours/glitch/images/glitch-preview.jpg b/app/javascript/flavours/glitch/images/glitch-preview.jpg
new file mode 100644
index 0000000000..fc5c420435
Binary files /dev/null and b/app/javascript/flavours/glitch/images/glitch-preview.jpg differ
diff --git a/app/javascript/flavours/glitch/names.yml b/app/javascript/flavours/glitch/names.yml
index b3d579cb27..ef82abed2f 100644
--- a/app/javascript/flavours/glitch/names.yml
+++ b/app/javascript/flavours/glitch/names.yml
@@ -1,6 +1,8 @@
en:
flavours:
- glitch: Glitch Edition
+ glitch:
+ description: The default flavour for GlitchSoc instances.
+ name: Glitch Edition
skins:
glitch:
default: Default
diff --git a/app/javascript/flavours/glitch/packs/common.js b/app/javascript/flavours/glitch/packs/common.js
index 07445d2b3f..8dd4372bc4 100644
--- a/app/javascript/flavours/glitch/packs/common.js
+++ b/app/javascript/flavours/glitch/packs/common.js
@@ -1 +1,4 @@
import 'flavours/glitch/styles/index.scss';
+
+// This ensures that webpack compiles our images.
+require.context('../images', true);
diff --git a/app/javascript/flavours/glitch/styles/admin.scss b/app/javascript/flavours/glitch/styles/admin.scss
index 87bc710af6..7c50322175 100644
--- a/app/javascript/flavours/glitch/styles/admin.scss
+++ b/app/javascript/flavours/glitch/styles/admin.scss
@@ -246,6 +246,22 @@
}
}
+.flavour-screen {
+ display: block;
+ margin: 10px auto;
+ max-width: 100%;
+}
+
+.flavour-description {
+ display: block;
+ font-size: 16px;
+ margin: 10px 0;
+
+ & > p {
+ margin: 10px 0;
+ }
+}
+
.report-accounts {
display: flex;
flex-wrap: wrap;
diff --git a/app/javascript/flavours/glitch/theme.yml b/app/javascript/flavours/glitch/theme.yml
index 9437e2c045..435fa23293 100644
--- a/app/javascript/flavours/glitch/theme.yml
+++ b/app/javascript/flavours/glitch/theme.yml
@@ -26,6 +26,12 @@ pack:
# language tags and whose default exports are a messages object.
locales: locales
+# (OPTIONAL) A file to use as the preview screenshot for the flavour,
+# or an array thereof. These filenames must be unique across all
+# images (regardless of path), so it's a good idea to namespace them
+# to your theme. It's up to you to let webpack know to compile them.
+screenshot: glitch-preview.jpg
+
# (OPTIONAL) The directory which contains the pack files.
# Defaults to the theme directory (`app/javascript/themes/[theme]`),
# which should be sufficient for like 99% of use-cases lol.
diff --git a/app/javascript/flavours/vanilla/names.yml b/app/javascript/flavours/vanilla/names.yml
index 8816fcb3ab..94326f6ee3 100644
--- a/app/javascript/flavours/vanilla/names.yml
+++ b/app/javascript/flavours/vanilla/names.yml
@@ -1,6 +1,8 @@
en:
flavours:
- vanilla: Vanilla Mastodon
+ vanilla:
+ description: The theme used by vanilla Mastodon instances. This theme might not support all of the features of GlitchSoc.
+ name: Vanilla Mastodon
skins:
vanilla:
default: Default
diff --git a/app/javascript/flavours/vanilla/theme.yml b/app/javascript/flavours/vanilla/theme.yml
index 491ea173b0..0b27c31bb1 100644
--- a/app/javascript/flavours/vanilla/theme.yml
+++ b/app/javascript/flavours/vanilla/theme.yml
@@ -24,6 +24,12 @@ pack:
# the flavour, relative to this directory.
locales: ../../mastodon/locales
+# (OPTIONAL) A file to use as the preview screenshot for the flavour,
+# or an array thereof. These filenames must be unique across all
+# images (regardless of path), so it's a good idea to namespace them
+# to your theme. It's up to you to let webpack know to compile them.
+screenshot: screenshot.jpg
+
# (OPTIONAL) The directory which contains the pack files.
# Defaults to this directory (`app/javascript/flavour/[flavour]`),
# but in the case of the vanilla Mastodon flavour the pack files are
diff --git a/app/javascript/images/screenshot.jpg b/app/javascript/images/screenshot.jpg
new file mode 100644
index 0000000000..45b270fbb0
Binary files /dev/null and b/app/javascript/images/screenshot.jpg differ
diff --git a/app/lib/themes.rb b/app/lib/themes.rb
index 49e9ebbc38..55824a5c4e 100644
--- a/app/lib/themes.rb
+++ b/app/lib/themes.rb
@@ -14,17 +14,27 @@ class Themes
result = Hash.new
Dir.glob(Rails.root.join('app', 'javascript', 'flavours', '*', 'theme.yml')) do |path|
data = YAML.load_file(path)
- name = File.basename(File.dirname(path))
+ dir = File.dirname(path)
+ name = File.basename(dir)
+ locales = []
+ screenshots = []
if data['locales']
- locales = []
- Dir.glob(File.join(File.dirname(path), data['locales'], '*.{js,json}')) do |locale|
+ Dir.glob(File.join(dir, data['locales'], '*.{js,json}')) do |locale|
localeName = File.basename(locale, File.extname(locale))
locales.push(localeName) unless localeName.match(/defaultMessages|whitelist|index/)
end
- data['locales'] = locales
+ end
+ if data['screenshot']
+ if data['screenshot'].is_a? Array
+ screenshots = data['screenshot']
+ else
+ screenshots.push(data['screenshot'])
+ end
end
if data['pack']
data['name'] = name
+ data['locales'] = locales
+ data['screenshot'] = screenshots
data['skin'] = { 'default' => [] }
result[name] = data
end
diff --git a/app/views/settings/flavours/show.html.haml b/app/views/settings/flavours/show.html.haml
new file mode 100644
index 0000000000..43c0377370
--- /dev/null
+++ b/app/views/settings/flavours/show.html.haml
@@ -0,0 +1,19 @@
+- content_for :page_title do
+ = t "flavours.#{@selected}.name", default: @selected
+
+= simple_form_for current_user, url: settings_flavour_path(@selected), html: { method: :put } do |f|
+ = render 'shared/error_messages', object: current_user
+
+ - Themes.instance.flavour(@selected)['screenshot'].each do |screen|
+ %img.flavour-screen{ src: asset_pack_path(screen) }
+
+ .flavour-description
+ = t "flavours.#{@selected}.description", default: ''
+
+ %hr/
+
+ .fields-group
+ = f.input :setting_skin, collection: Themes.instance.skins_for(@selected), label_method: lambda { |skin| I18n.t("skins.#{@selected}.#{skin}", default: skin) }, wrapper: :with_label, include_blank: false
+
+ .actions
+ = f.button :button, t('generic.use_this'), type: :submit
diff --git a/app/views/settings/preferences/show.html.haml b/app/views/settings/preferences/show.html.haml
index 45a3b2eb07..d1459d93ca 100644
--- a/app/views/settings/preferences/show.html.haml
+++ b/app/views/settings/preferences/show.html.haml
@@ -26,10 +26,6 @@
%h4= t 'preferences.web'
.fields-group
- - if Themes.instance.flavours.size > 1
- = f.input :setting_flavour, collection: Themes.instance.flavours, label_method: lambda { |flavour| I18n.t("flavours.#{flavour}", default: flavour) }, wrapper: :with_label, include_blank: false
- = f.input :setting_skin, collection: Themes.instance.skins_for(current_flavour), label_method: lambda { |skin| I18n.t("skins.#{current_flavour}.#{skin}", default: skin) }, wrapper: :with_label, include_blank: false
-
= f.input :setting_unfollow_modal, as: :boolean, wrapper: :with_label
= f.input :setting_boost_modal, as: :boolean, wrapper: :with_label
= f.input :setting_favourite_modal, as: :boolean, wrapper: :with_label
diff --git a/config/locales/en.yml b/config/locales/en.yml
index c8acc237ac..804f9b199a 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -424,6 +424,7 @@ en:
changes_saved_msg: Changes successfully saved!
powered_by: powered by %{link}
save_changes: Save changes
+ use_this: Use this
validation_errors:
one: Something isn't quite right yet! Please review the error below
other: Something isn't quite right yet! Please review %{count} errors below
@@ -587,6 +588,7 @@ en:
development: Development
edit_profile: Edit profile
export: Data export
+ flavours: Flavours
followers: Authorized followers
import: Import
keyword_mutes: Muted keywords
diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml
index 1722eea7bd..aa6940e916 100644
--- a/config/locales/simple_form.en.yml
+++ b/config/locales/simple_form.en.yml
@@ -13,7 +13,6 @@ en:
note:
one: 1 character left
other: %{count} characters left
- setting_flavour: Affects how Mastodon looks when you're logged in from any device
setting_noindex: Affects your public profile and status pages
setting_skin: Reskins the selected Mastodon flavour
imports:
@@ -47,7 +46,6 @@ en:
setting_default_sensitive: Always mark media as sensitive
setting_delete_modal: Show confirmation dialog before deleting a toot
setting_favourite_modal: Show confirmation dialog before favouriting
- setting_flavour: Flavour
setting_noindex: Opt-out of search engine indexing
setting_reduce_motion: Reduce motion in animations
setting_skin: Skin
diff --git a/config/navigation.rb b/config/navigation.rb
index 3f4c00dfa9..b08b1769de 100644
--- a/config/navigation.rb
+++ b/config/navigation.rb
@@ -17,6 +17,12 @@ SimpleNavigation::Configuration.run do |navigation|
settings.item :follower_domains, safe_join([fa_icon('users fw'), t('settings.followers')]), settings_follower_domains_url
end
+ primary.item :flavours, safe_join([fa_icon('paint-brush fw'), t('settings.flavours')]), settings_flavours_url do |flavours|
+ Themes.instance.flavours.each do |flavour|
+ flavours.item flavour.to_sym, safe_join([fa_icon('star fw'), t("flavours.#{flavour}.name", default: flavour)]), settings_flavour_url(flavour)
+ end
+ end
+
primary.item :invites, safe_join([fa_icon('user-plus fw'), t('invites.title')]), invites_path, if: proc { Setting.min_invite_role == 'user' }
primary.item :development, safe_join([fa_icon('code fw'), t('settings.development')]), settings_applications_url do |development|
diff --git a/config/routes.rb b/config/routes.rb
index a41e76c2cc..75b9c2d58f 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -102,6 +102,8 @@ Rails.application.routes.draw do
end
end
+ resources :flavours, only: [:index, :show, :update], param: :flavour
+
resource :delete, only: [:show, :destroy]
resource :migration, only: [:show, :update]
@@ -240,7 +242,7 @@ Rails.application.routes.draw do
resources :media, only: [:create, :update]
resources :blocks, only: [:index]
resources :mutes, only: [:index] do
- collection do
+ collection do
get 'details'
end
end