:setting_display_media,
:setting_expand_spoilers,
:setting_reduce_motion,
+ :setting_disable_swiping,
:setting_system_font_ui,
+ :setting_system_emoji_font,
:setting_noindex,
- :setting_theme,
:setting_hide_network,
+ :setting_hide_followers_count,
:setting_aggregate_reblogs,
:setting_show_application,
:setting_advanced_layout,
+// This file will be loaded on admin pages, regardless of theme.
+
+ import './public-path';
import { delegate } from '@rails/ujs';
import ready from '../mastodon/ready';
-import escapeTextContentForBrowser from 'escape-html';
+ import './public-path';
import loadPolyfills from '../mastodon/load_polyfills';
import ready from '../mastodon/ready';
import { start } from '../mastodon/common';
user.settings['display_media'] = display_media_preference if change?('setting_display_media')
user.settings['expand_spoilers'] = expand_spoilers_preference if change?('setting_expand_spoilers')
user.settings['reduce_motion'] = reduce_motion_preference if change?('setting_reduce_motion')
+ user.settings['disable_swiping'] = disable_swiping_preference if change?('setting_disable_swiping')
user.settings['system_font_ui'] = system_font_ui_preference if change?('setting_system_font_ui')
+ user.settings['system_emoji_font'] = system_emoji_font_preference if change?('setting_system_emoji_font')
user.settings['noindex'] = noindex_preference if change?('setting_noindex')
- user.settings['theme'] = theme_preference if change?('setting_theme')
+ user.settings['hide_followers_count']= hide_followers_count_preference if change?('setting_hide_followers_count')
+ user.settings['flavour'] = flavour_preference if change?('setting_flavour')
+ user.settings['skin'] = skin_preference if change?('setting_skin')
user.settings['hide_network'] = hide_network_preference if change?('setting_hide_network')
user.settings['aggregate_reblogs'] = aggregate_reblogs_preference if change?('setting_aggregate_reblogs')
user.settings['show_application'] = show_application_preference if change?('setting_show_application')
# id :bigint(8) not null, primary key
# created_at :datetime not null
# updated_at :datetime not null
+# hide_notifications :boolean default(TRUE), not null
# account_id :bigint(8) not null
# target_account_id :bigint(8) not null
+ # hide_notifications :boolean default(TRUE), not null
+ # expires_at :datetime
#
class Mute < ApplicationRecord
has_many :session_activations, dependent: :destroy
- delegate :auto_play_gif, :default_sensitive, :unfollow_modal, :boost_modal, :delete_modal,
- :reduce_motion, :system_font_ui, :noindex, :theme, :display_media, :hide_network,
+ delegate :auto_play_gif, :default_sensitive, :unfollow_modal, :boost_modal, :favourite_modal, :delete_modal,
+ :reduce_motion, :system_font_ui, :noindex, :flavour, :skin, :display_media, :hide_network, :hide_followers_count,
:expand_spoilers, :default_language, :aggregate_reblogs, :show_application,
:advanced_layout, :use_blurhash, :use_pending_items, :trends, :crop_images,
- :default_content_type, :system_emoji_font,
- :disable_swiping,
++ :disable_swiping, :default_content_type, :system_emoji_font,
to: :settings, prefix: :setting, allow_nil: false
attr_reader :invite_code, :sign_in_token_attempt
.fields-group
= f.input :setting_auto_play_gif, as: :boolean, wrapper: :with_label, recommended: true
= f.input :setting_reduce_motion, as: :boolean, wrapper: :with_label
+ = f.input :setting_disable_swiping, as: :boolean, wrapper: :with_label
= f.input :setting_system_font_ui, as: :boolean, wrapper: :with_label
+ = f.input :setting_system_emoji_font, as: :boolean, wrapper: :with_label
%h4= t 'appearance.toot_layout'
expand_spoilers: false
preview_sensitive_media: false
reduce_motion: false
- show_application: true
+ disable_swiping: false
+ show_application: false
system_font_ui: false
+ system_emoji_font: false
noindex: false
- theme: 'default'
+ hide_followers_count: false
+ enable_keybase: true
+ flavour: 'glitch'
+ skin: 'default'
aggregate_reblogs: true
advanced_layout: false
use_blurhash: true
const configPath = resolve('config', 'webpacker.yml');
const settings = safeLoad(readFileSync(configPath), 'utf8')[env.RAILS_ENV || env.NODE_ENV];
+const flavourFiles = glob.sync('app/javascript/flavours/*/theme.yml');
+const skinFiles = glob.sync('app/javascript/skins/*/*');
+const flavours = {};
-const themePath = resolve('config', 'themes.yml');
-const themes = safeLoad(readFileSync(themePath), 'utf8');
+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 < flavourFiles.length; i++) {
+ const flavourFile = flavourFiles[i];
+ const data = safeLoad(readFileSync(flavourFile), 'utf8');
+ data.name = basename(dirname(flavourFile));
+ data.skin = {};
+ if (!data.pack_directory) {
+ data.pack_directory = dirname(flavourFile);
+ }
+ if (data.locales) {
+ data.locales = join(dirname(flavourFile), data.locales);
+ }
+ if (data.pack && typeof data.pack === 'object') {
+ flavours[data.name] = data;
+ }
+}
+
+for (let i = 0; i < skinFiles.length; i++) {
+ const skinFile = skinFiles[i];
+ let skin = basename(skinFile);
+ const name = basename(dirname(skinFile));
+ if (!flavours[name]) {
+ continue;
+ }
+ const data = flavours[name].skin;
+ if (lstatSync(skinFile).isDirectory()) {
+ data[skin] = {};
+ const skinPacks = glob.sync(join(skinFile, '*.{css,scss}'));
+ for (let j = 0; j < skinPacks.length; j++) {
+ const pack = skinPacks[j];
+ data[skin][basename(pack, extname(pack))] = pack;
+ }
+ } else if ((skin = skin.match(/^(.*)\.s?css$/i))) {
+ data[skin[1]] = { common: skinFile };
+ }
+}
- function removeOuterSlashes(string) {
- return string.replace(/^\/*/, '').replace(/\/*$/, '');
- }
-
- function formatPublicPath(host = '', path = '') {
- let formattedHost = removeOuterSlashes(host);
- if (formattedHost && !/^http/i.test(formattedHost)) {
- formattedHost = `//${formattedHost}`;
- }
- const formattedPath = removeOuterSlashes(path);
- return `${formattedHost}/${formattedPath}/`;
- }
-
const output = {
path: resolve('public', settings.public_output_path),
- publicPath: formatPublicPath(env.CDN_HOST, settings.public_output_path),
+ publicPath: `/${settings.public_output_path}/`,
};
module.exports = {
settings,
- themes,
+ core,
+ flavours,
env: {
- CDN_HOST: env.CDN_HOST,
NODE_ENV: env.NODE_ENV,
+ PUBLIC_OUTPUT_PATH: settings.public_output_path,
},
output,
};
"@babel/runtime": "^7.11.2",
"@clusterws/cws": "^3.0.0",
"@gamestdio/websocket": "^0.3.2",
- "@github/webauthn-json": "^0.5.4",
+ "@github/webauthn-json": "^0.5.6",
"@rails/ujs": "^6.0.3",
"array-includes": "^3.1.1",
+ "atrament": "0.2.4",
"arrow-key-navigation": "^1.2.0",
"autoprefixer": "^9.8.6",
"axios": "^0.20.0",
"escape-html": "^1.0.3",
"exif-js": "^2.3.0",
"express": "^4.17.1",
- "file-loader": "^6.1.0",
+ "favico.js": "^0.3.10",
+ "file-loader": "^6.1.1",
"font-awesome": "^4.7.0",
"glob": "^7.1.6",
"history": "^4.10.1",