mirror of
https://github.com/glitch-soc/mastodon.git
synced 2025-12-14 00:08:46 +00:00
Merge commit 'c4f47adb49663f24ee80d9174ab24431a8c165c0' into glitch-soc/merge-upstream
Too many conflicts to list, because of webpack → vite migration.
This commit is contained in:
@@ -9,6 +9,7 @@ services:
|
||||
environment:
|
||||
RAILS_ENV: development
|
||||
NODE_ENV: development
|
||||
VITE_RUBY_HOST: 0.0.0.0
|
||||
BIND: 0.0.0.0
|
||||
BOOTSNAP_CACHE_DIR: /tmp
|
||||
REDIS_HOST: redis
|
||||
@@ -22,11 +23,12 @@ services:
|
||||
ES_PORT: '9200'
|
||||
LIBRE_TRANSLATE_ENDPOINT: http://libretranslate:5000
|
||||
LOCAL_DOMAIN: ${LOCAL_DOMAIN:-localhost:3000}
|
||||
VITE_DEV_SERVER_PUBLIC: ${VITE_DEV_SERVER_PUBLIC:-localhost:3036}
|
||||
# Overrides default command so things don't shut down after the process ends.
|
||||
command: sleep infinity
|
||||
ports:
|
||||
- '3000:3000'
|
||||
- '3035:3035'
|
||||
- '3036:3036'
|
||||
- '4000:4000'
|
||||
networks:
|
||||
- external_network
|
||||
|
||||
17
.github/renovate.json5
vendored
17
.github/renovate.json5
vendored
@@ -25,23 +25,6 @@
|
||||
'tesseract.js', // Requires code changes
|
||||
'react-hotkeys', // Requires code changes
|
||||
|
||||
// Requires Webpacker upgrade or replacement
|
||||
'@svgr/webpack',
|
||||
'@types/webpack',
|
||||
'babel-loader',
|
||||
'compression-webpack-plugin',
|
||||
'css-loader',
|
||||
'imports-loader',
|
||||
'mini-css-extract-plugin',
|
||||
'postcss-loader',
|
||||
'sass-loader',
|
||||
'terser-webpack-plugin',
|
||||
'webpack',
|
||||
'webpack-assets-manifest',
|
||||
'webpack-bundle-analyzer',
|
||||
'webpack-dev-server',
|
||||
'webpack-cli',
|
||||
|
||||
// react-router: Requires manual upgrade
|
||||
'history',
|
||||
'react-router-dom',
|
||||
|
||||
4
.github/workflows/test-ruby.yml
vendored
4
.github/workflows/test-ruby.yml
vendored
@@ -49,7 +49,7 @@ jobs:
|
||||
public/assets
|
||||
public/packs
|
||||
public/packs-test
|
||||
tmp/cache/webpacker
|
||||
tmp/cache/vite
|
||||
key: ${{ matrix.mode }}-assets-${{ github.head_ref || github.ref_name }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ matrix.mode }}-assets-${{ github.head_ref || github.ref_name }}-${{ github.sha }}
|
||||
@@ -63,7 +63,7 @@ jobs:
|
||||
|
||||
- name: Archive asset artifacts
|
||||
run: |
|
||||
tar --exclude={"*.br","*.gz"} -zcf artifacts.tar.gz public/assets public/packs*
|
||||
tar --exclude={"*.br","*.gz"} -zcf artifacts.tar.gz public/assets public/packs* tmp/cache/vite/last-build*.json
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: matrix.mode == 'test'
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -21,10 +21,11 @@
|
||||
/public/system
|
||||
/public/assets
|
||||
/public/packs
|
||||
/public/packs-dev
|
||||
/public/packs-test
|
||||
.env
|
||||
.env.production
|
||||
/node_modules/
|
||||
node_modules/
|
||||
/build/
|
||||
|
||||
# Ignore Vagrant files
|
||||
|
||||
@@ -18,10 +18,6 @@
|
||||
!/log/.keep
|
||||
/tmp
|
||||
/coverage
|
||||
/public/system
|
||||
/public/assets
|
||||
/public/packs
|
||||
/public/packs-test
|
||||
.env
|
||||
.env.production
|
||||
.env.development
|
||||
@@ -60,6 +56,7 @@ docker-compose.override.yml
|
||||
/public/packs
|
||||
/public/packs-test
|
||||
/public/system
|
||||
/public/vite*
|
||||
|
||||
# Ignore emoji map file
|
||||
/app/javascript/mastodon/features/emoji/emoji_map.json
|
||||
|
||||
3
Gemfile
3
Gemfile
@@ -95,7 +95,6 @@ gem 'tty-prompt', '~> 0.23', require: false
|
||||
gem 'twitter-text', '~> 3.1.0'
|
||||
gem 'tzinfo-data', '~> 1.2023'
|
||||
gem 'webauthn', '~> 3.0'
|
||||
gem 'webpacker', '~> 5.4'
|
||||
gem 'webpush', github: 'mastodon/webpush', ref: '9631ac63045cfabddacc69fc06e919b4c13eb913'
|
||||
|
||||
gem 'json-ld'
|
||||
@@ -230,3 +229,5 @@ gem 'rubyzip', '~> 2.3'
|
||||
gem 'hcaptcha', '~> 7.1'
|
||||
|
||||
gem 'mail', '~> 2.8'
|
||||
|
||||
gem 'vite_rails', '~> 3.0.19'
|
||||
|
||||
18
Gemfile.lock
18
Gemfile.lock
@@ -203,6 +203,7 @@ GEM
|
||||
railties (>= 5)
|
||||
dotenv (3.1.8)
|
||||
drb (2.2.1)
|
||||
dry-cli (1.2.0)
|
||||
elasticsearch (7.17.11)
|
||||
elasticsearch-api (= 7.17.11)
|
||||
elasticsearch-transport (= 7.17.11)
|
||||
@@ -806,7 +807,6 @@ GEM
|
||||
rexml (~> 3.2, >= 3.2.5)
|
||||
rubyzip (>= 1.2.2, < 3.0)
|
||||
websocket (~> 1.0)
|
||||
semantic_range (3.1.0)
|
||||
shoulda-matchers (6.5.0)
|
||||
activesupport (>= 5.2.0)
|
||||
sidekiq (6.5.12)
|
||||
@@ -892,6 +892,15 @@ GEM
|
||||
validate_url (1.0.15)
|
||||
activemodel (>= 3.0.0)
|
||||
public_suffix
|
||||
vite_rails (3.0.19)
|
||||
railties (>= 5.1, < 9)
|
||||
vite_ruby (~> 3.0, >= 3.2.2)
|
||||
vite_ruby (3.9.2)
|
||||
dry-cli (>= 0.7, < 2)
|
||||
logger (~> 1.6)
|
||||
mutex_m
|
||||
rack-proxy (~> 0.6, >= 0.6.1)
|
||||
zeitwerk (~> 2.2)
|
||||
warden (1.2.9)
|
||||
rack (>= 2.0.9)
|
||||
webauthn (3.4.0)
|
||||
@@ -910,11 +919,6 @@ GEM
|
||||
addressable (>= 2.8.0)
|
||||
crack (>= 0.3.2)
|
||||
hashdiff (>= 0.4.0, < 2.0.0)
|
||||
webpacker (5.4.4)
|
||||
activesupport (>= 5.2)
|
||||
rack-proxy (>= 0.6.1)
|
||||
railties (>= 5.2)
|
||||
semantic_range (>= 2.3.0)
|
||||
webrick (1.9.1)
|
||||
websocket (1.2.11)
|
||||
websocket-driver (0.7.7)
|
||||
@@ -1078,9 +1082,9 @@ DEPENDENCIES
|
||||
tty-prompt (~> 0.23)
|
||||
twitter-text (~> 3.1.0)
|
||||
tzinfo-data (~> 1.2023)
|
||||
vite_rails (~> 3.0.19)
|
||||
webauthn (~> 3.0)
|
||||
webmock (~> 3.18)
|
||||
webpacker (~> 5.4)
|
||||
webpush!
|
||||
xorcist (~> 1.1)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
web: env PORT=3000 RAILS_ENV=development bundle exec puma -C config/puma.rb
|
||||
sidekiq: env PORT=3000 RAILS_ENV=development bundle exec sidekiq
|
||||
stream: env PORT=4000 yarn workspace @mastodon/streaming start
|
||||
webpack: bin/webpack-dev-server
|
||||
vite: yarn dev
|
||||
|
||||
@@ -12,7 +12,7 @@ module ThemingConcern
|
||||
def current_skin
|
||||
@current_skin ||= begin
|
||||
skins = Themes.instance.skins_for(current_flavour)
|
||||
[current_user&.setting_skin, Setting.skin, 'system', 'default'].find { |skin| skins.include?(skin) }
|
||||
[current_user&.setting_skin, Setting.skin, 'system', 'application'].find { |skin| skins.include?(skin) }
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -248,22 +248,8 @@ module ApplicationHelper
|
||||
end
|
||||
|
||||
# glitch-soc addition to handle the multiple flavors
|
||||
def preload_locale_pack
|
||||
supported_locales = Themes.instance.flavour(current_flavour)['locales']
|
||||
preload_pack_asset "locales/#{current_flavour}/#{I18n.locale}-json.js" if supported_locales.include?(I18n.locale.to_s)
|
||||
end
|
||||
|
||||
def flavoured_javascript_pack_tag(pack_name, **)
|
||||
javascript_pack_tag("flavours/#{current_flavour}/#{pack_name}", **)
|
||||
end
|
||||
|
||||
def flavoured_stylesheet_pack_tag(pack_name, **)
|
||||
stylesheet_pack_tag("flavours/#{current_flavour}/#{pack_name}", **)
|
||||
end
|
||||
|
||||
def preload_signed_in_js_packs
|
||||
preload_files = Themes.instance.flavour(current_flavour)&.fetch('signed_in_preload', nil) || []
|
||||
safe_join(preload_files.map { |entry| preload_pack_asset entry })
|
||||
def flavoured_vite_typescript_tag(pack_name, **)
|
||||
vite_typescript_tag("#{Themes.instance.flavour(current_flavour)['pack_directory'].delete_prefix('app/javascript/')}/#{pack_name}", **)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -4,7 +4,7 @@ module RoutingHelper
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
include ActionView::Helpers::AssetTagHelper
|
||||
include Webpacker::Helper
|
||||
include ViteRails::TagHelpers
|
||||
|
||||
included do
|
||||
include Rails.application.routes.url_helpers
|
||||
@@ -25,7 +25,7 @@ module RoutingHelper
|
||||
end
|
||||
|
||||
def frontend_asset_path(source, **)
|
||||
asset_pack_path("media/#{source}", **)
|
||||
vite_asset_path(source, **)
|
||||
end
|
||||
|
||||
def frontend_asset_url(source, **)
|
||||
|
||||
@@ -6,11 +6,13 @@ module ThemeHelper
|
||||
|
||||
if theme == 'system'
|
||||
''.html_safe.tap do |tags|
|
||||
tags << stylesheet_pack_tag("skins/#{flavour}/mastodon-light", media: 'not all and (prefers-color-scheme: dark)', crossorigin: 'anonymous')
|
||||
tags << stylesheet_pack_tag("skins/#{flavour}/default", media: '(prefers-color-scheme: dark)', crossorigin: 'anonymous')
|
||||
tags << vite_stylesheet_tag("skins/#{flavour}/mastodon-light.scss", media: 'not all and (prefers-color-scheme: dark)', crossorigin: 'anonymous')
|
||||
tags << vite_stylesheet_tag("skins/#{flavour}/application.scss", media: '(prefers-color-scheme: dark)', crossorigin: 'anonymous')
|
||||
end
|
||||
elsif theme == 'default'
|
||||
vite_stylesheet_tag "skins/#{flavour}/application.scss", media: 'all', crossorigin: 'anonymous'
|
||||
else
|
||||
stylesheet_pack_tag "skins/#{flavour}/#{theme}", media: 'all', crossorigin: 'anonymous'
|
||||
vite_stylesheet_tag "skins/#{flavour}/#{theme}.scss", media: 'all', crossorigin: 'anonymous'
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import './public-path';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
|
||||
import Rails from '@rails/ujs';
|
||||
@@ -273,7 +272,7 @@ async function mountReactComponent(element: Element) {
|
||||
);
|
||||
|
||||
const { default: Component } = (await import(
|
||||
`@/mastodon/components/admin/${componentName}`
|
||||
`@/mastodon/components/admin/${componentName}.jsx`
|
||||
)) as { default: React.ComponentType };
|
||||
|
||||
const root = createRoot(element);
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
import './public-path';
|
||||
import { loadLocale } from 'mastodon/locales';
|
||||
import main from 'mastodon/main';
|
||||
|
||||
import { start } from '../mastodon/common';
|
||||
import { loadLocale } from '../mastodon/locales';
|
||||
import { loadPolyfills } from '../mastodon/polyfills';
|
||||
|
||||
start();
|
||||
import { loadPolyfills } from 'mastodon/polyfills';
|
||||
|
||||
loadPolyfills()
|
||||
.then(loadLocale)
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
/* This file is a hack to have something more reliable than the upstream `common` tag
|
||||
that is implicitly generated as the common chunk through webpack's `splitChunks` config */
|
||||
|
||||
import './public-path';
|
||||
3
app/javascript/entrypoints/common.ts
Normal file
3
app/javascript/entrypoints/common.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { start } from 'mastodon/common';
|
||||
|
||||
start();
|
||||
@@ -1,15 +1,11 @@
|
||||
import './public-path';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
|
||||
import { afterInitialRender } from 'mastodon/hooks/useRenderSignal';
|
||||
|
||||
import { start } from '../mastodon/common';
|
||||
import { Status } from '../mastodon/features/standalone/status';
|
||||
import { loadPolyfills } from '../mastodon/polyfills';
|
||||
import ready from '../mastodon/ready';
|
||||
|
||||
start();
|
||||
|
||||
function loaded() {
|
||||
const mountNode = document.getElementById('mastodon-status');
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import './public-path';
|
||||
import ready from '../mastodon/ready';
|
||||
|
||||
ready(() => {
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
/* Placeholder file to have `inert.scss` compiled by Webpack
|
||||
This is used by the `wicg-inert` polyfill */
|
||||
|
||||
import '../styles/inert.scss';
|
||||
@@ -1,3 +0,0 @@
|
||||
import '../styles/mailer.scss';
|
||||
|
||||
require.context('../icons');
|
||||
@@ -1,23 +0,0 @@
|
||||
// Dynamically set webpack's loading path depending on a meta header, in order
|
||||
// to share the same assets regardless of instance configuration.
|
||||
// See https://webpack.js.org/guides/public-path/#on-the-fly
|
||||
|
||||
function removeOuterSlashes(string: 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 cdnHost = document.querySelector<HTMLMetaElement>('meta[name=cdn-host]');
|
||||
|
||||
__webpack_public_path__ = formatPublicPath(
|
||||
cdnHost ? cdnHost.content : '',
|
||||
process.env.PUBLIC_OUTPUT_PATH,
|
||||
);
|
||||
@@ -1,7 +1,5 @@
|
||||
import { createRoot } from 'react-dom/client';
|
||||
|
||||
import './public-path';
|
||||
|
||||
import { IntlMessageFormat } from 'intl-messageformat';
|
||||
import type { MessageDescriptor, PrimitiveType } from 'react-intl';
|
||||
import { defineMessages } from 'react-intl';
|
||||
@@ -10,7 +8,6 @@ import Rails from '@rails/ujs';
|
||||
import axios from 'axios';
|
||||
import { throttle } from 'lodash';
|
||||
|
||||
import { start } from '../mastodon/common';
|
||||
import { timeAgoString } from '../mastodon/components/relative_timestamp';
|
||||
import emojify from '../mastodon/features/emoji/emoji';
|
||||
import loadKeyboardExtensions from '../mastodon/load_keyboard_extensions';
|
||||
@@ -20,8 +17,6 @@ import ready from '../mastodon/ready';
|
||||
|
||||
import 'cocoon-js-vanilla';
|
||||
|
||||
start();
|
||||
|
||||
const messages = defineMessages({
|
||||
usernameTaken: {
|
||||
id: 'username.taken',
|
||||
@@ -153,9 +148,7 @@ function loaded() {
|
||||
const reactComponents = document.querySelectorAll('[data-component]');
|
||||
|
||||
if (reactComponents.length > 0) {
|
||||
import(
|
||||
/* webpackChunkName: "containers/media_container" */ '../mastodon/containers/media_container'
|
||||
)
|
||||
import('../mastodon/containers/media_container')
|
||||
.then(({ default: MediaContainer }) => {
|
||||
reactComponents.forEach((component) => {
|
||||
Array.from(component.children).forEach((child) => {
|
||||
|
||||
@@ -8,8 +8,6 @@ and performs no other task.
|
||||
|
||||
*/
|
||||
|
||||
import './public-path';
|
||||
|
||||
import axios from 'axios';
|
||||
|
||||
interface JRDLink {
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
import './public-path';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
|
||||
import { start } from '../mastodon/common';
|
||||
import ComposeContainer from '../mastodon/containers/compose_container';
|
||||
import { loadPolyfills } from '../mastodon/polyfills';
|
||||
import ready from '../mastodon/ready';
|
||||
|
||||
start();
|
||||
|
||||
function loaded() {
|
||||
const mountNode = document.getElementById('mastodon-compose');
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import './public-path';
|
||||
import axios from 'axios';
|
||||
|
||||
import ready from '../mastodon/ready';
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import Rails from '@rails/ujs';
|
||||
|
||||
export function start() {
|
||||
require.context('@/images/', true, /\.(jpg|png|svg)$/);
|
||||
|
||||
try {
|
||||
Rails.start();
|
||||
} catch {
|
||||
@@ -18,8 +18,8 @@ import StarIcon from '@/material-icons/400-24px/star-fill.svg?react';
|
||||
import StarBorderIcon from '@/material-icons/400-24px/star.svg?react';
|
||||
import VisibilityIcon from '@/material-icons/400-24px/visibility.svg?react';
|
||||
import RepeatActiveIcon from '@/svg-icons/repeat_active.svg?react';
|
||||
import RepeatDisabledIcon from '@/svg-icons/repeat_disabled.svg';
|
||||
import RepeatPrivateIcon from '@/svg-icons/repeat_private.svg';
|
||||
import RepeatDisabledIcon from '@/svg-icons/repeat_disabled.svg?react';
|
||||
import RepeatPrivateIcon from '@/svg-icons/repeat_private.svg?react';
|
||||
import RepeatPrivateActiveIcon from '@/svg-icons/repeat_private_active.svg?react';
|
||||
import { identityContextPropShape, withIdentity } from 'flavours/glitch/identity_context';
|
||||
import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'flavours/glitch/permissions';
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import '@/entrypoints/public-path';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
|
||||
import Rails from '@rails/ujs';
|
||||
@@ -273,7 +272,7 @@ async function mountReactComponent(element: Element) {
|
||||
);
|
||||
|
||||
const { default: Component } = (await import(
|
||||
`@/flavours/glitch/components/admin/${componentName}`
|
||||
`@/flavours/glitch/components/admin/${componentName}.jsx`
|
||||
)) as { default: React.ComponentType };
|
||||
|
||||
const root = createRoot(element);
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
import '@/entrypoints/public-path';
|
||||
|
||||
import { start } from 'flavours/glitch/common';
|
||||
import { loadLocale } from 'flavours/glitch/locales';
|
||||
import main from 'flavours/glitch/main';
|
||||
import { loadPolyfills } from 'flavours/glitch/polyfills';
|
||||
|
||||
start();
|
||||
|
||||
loadPolyfills()
|
||||
.then(loadLocale)
|
||||
.then(main)
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
/* This file is a hack to have something more reliable than the upstream `common` tag
|
||||
that is implicitly generated as the common chunk through webpack's `splitChunks` config */
|
||||
|
||||
import '@/entrypoints/public-path';
|
||||
|
||||
// This is a hack to ensures that webpack compiles our images.
|
||||
require.context('../images', true);
|
||||
3
app/javascript/flavours/glitch/entrypoints/common.ts
Normal file
3
app/javascript/flavours/glitch/entrypoints/common.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { start } from 'flavours/glitch/common';
|
||||
|
||||
start();
|
||||
@@ -1,15 +1,10 @@
|
||||
import { createRoot } from 'react-dom/client';
|
||||
|
||||
import '@/entrypoints/public-path';
|
||||
|
||||
import { start } from 'flavours/glitch/common';
|
||||
import { Status } from 'flavours/glitch/features/standalone/status';
|
||||
import { afterInitialRender } from 'flavours/glitch/hooks/useRenderSignal';
|
||||
import { loadPolyfills } from 'flavours/glitch/polyfills';
|
||||
import ready from 'flavours/glitch/ready';
|
||||
|
||||
start();
|
||||
|
||||
function loaded() {
|
||||
const mountNode = document.getElementById('mastodon-status');
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import '@/entrypoints/public-path';
|
||||
import ready from 'flavours/glitch/ready';
|
||||
|
||||
ready(() => {
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
/* Placeholder file to have `inert.scss` compiled by Webpack
|
||||
This is used by the `wicg-inert` polyfill */
|
||||
|
||||
import '@/styles/inert.scss';
|
||||
@@ -1,3 +0,0 @@
|
||||
import '@/styles/mailer.scss';
|
||||
|
||||
require.context('@/icons');
|
||||
@@ -1,7 +1,5 @@
|
||||
import { createRoot } from 'react-dom/client';
|
||||
|
||||
import '@/entrypoints/public-path';
|
||||
|
||||
import { IntlMessageFormat } from 'intl-messageformat';
|
||||
import type { MessageDescriptor, PrimitiveType } from 'react-intl';
|
||||
import { defineMessages } from 'react-intl';
|
||||
@@ -10,7 +8,6 @@ import Rails from '@rails/ujs';
|
||||
import axios from 'axios';
|
||||
import { throttle } from 'lodash';
|
||||
|
||||
import { start } from 'flavours/glitch/common';
|
||||
import { timeAgoString } from 'flavours/glitch/components/relative_timestamp';
|
||||
import emojify from 'flavours/glitch/features/emoji/emoji';
|
||||
import loadKeyboardExtensions from 'flavours/glitch/load_keyboard_extensions';
|
||||
@@ -20,8 +17,6 @@ import ready from 'flavours/glitch/ready';
|
||||
|
||||
import 'cocoon-js-vanilla';
|
||||
|
||||
start();
|
||||
|
||||
const messages = defineMessages({
|
||||
usernameTaken: {
|
||||
id: 'username.taken',
|
||||
@@ -153,9 +148,7 @@ function loaded() {
|
||||
const reactComponents = document.querySelectorAll('[data-component]');
|
||||
|
||||
if (reactComponents.length > 0) {
|
||||
import(
|
||||
/* webpackChunkName: "containers/media_container" */ 'flavours/glitch/containers/media_container'
|
||||
)
|
||||
import('flavours/glitch/containers/media_container')
|
||||
.then(({ default: MediaContainer }) => {
|
||||
reactComponents.forEach((component) => {
|
||||
Array.from(component.children).forEach((child) => {
|
||||
|
||||
@@ -8,8 +8,6 @@ and performs no other task.
|
||||
|
||||
*/
|
||||
|
||||
import '@/entrypoints/public-path';
|
||||
|
||||
import axios from 'axios';
|
||||
|
||||
interface JRDLink {
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
import '@/entrypoints/public-path';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
|
||||
import { start } from 'flavours/glitch/common';
|
||||
import ComposeContainer from 'flavours/glitch/containers/compose_container';
|
||||
import { loadPolyfills } from 'flavours/glitch/polyfills';
|
||||
import ready from 'flavours/glitch/ready';
|
||||
|
||||
start();
|
||||
|
||||
function loaded() {
|
||||
const mountNode = document.getElementById('mastodon-compose');
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import '@/entrypoints/public-path';
|
||||
import axios from 'axios';
|
||||
|
||||
import ready from 'flavours/glitch/ready';
|
||||
|
||||
@@ -15,10 +15,6 @@ import type { List as ImmutableList, Map as ImmutableMap } from 'immutable';
|
||||
import { useSpring, animated } from '@react-spring/web';
|
||||
import Textarea from 'react-textarea-autosize';
|
||||
import { length } from 'stringz';
|
||||
// eslint-disable-next-line import/extensions
|
||||
import tesseractWorkerPath from 'tesseract.js/dist/worker.min.js';
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
import tesseractCorePath from 'tesseract.js-core/tesseract-core.wasm.js';
|
||||
|
||||
import { showAlertForError } from 'flavours/glitch/actions/alerts';
|
||||
import { uploadThumbnail } from 'flavours/glitch/actions/compose';
|
||||
@@ -350,9 +346,15 @@ export const AltTextModal = forwardRef<ModalRef, Props & Partial<RestoreProps>>(
|
||||
|
||||
fetchTesseract()
|
||||
.then(async ({ createWorker }) => {
|
||||
const [tesseractWorkerPath, tesseractCorePath] = await Promise.all([
|
||||
// eslint-disable-next-line import/extensions
|
||||
import('tesseract.js/dist/worker.min.js?url'),
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
import('tesseract.js-core/tesseract-core.wasm.js?url'),
|
||||
]);
|
||||
const worker = await createWorker('eng', 1, {
|
||||
workerPath: tesseractWorkerPath as string,
|
||||
corePath: tesseractCorePath as string,
|
||||
workerPath: tesseractWorkerPath.default,
|
||||
corePath: tesseractCorePath.default,
|
||||
langPath: `${assetHost}/ocr/lang-data`,
|
||||
cacheMethod: 'write',
|
||||
});
|
||||
@@ -501,5 +503,4 @@ export const AltTextModal = forwardRef<ModalRef, Props & Partial<RestoreProps>>(
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
AltTextModal.displayName = 'AltTextModal';
|
||||
|
||||
@@ -9,28 +9,27 @@
|
||||
// to ensure that the prevaled file is regenerated by Babel
|
||||
// version: 4
|
||||
|
||||
const { NimbleEmojiIndex } = require('emoji-mart');
|
||||
const { uncompress: emojiMartUncompress } = require('emoji-mart/dist/utils/data');
|
||||
import { NimbleEmojiIndex } from 'emoji-mart';
|
||||
import { uncompress as emojiMartUncompress } from 'emoji-mart/dist/utils/data';
|
||||
|
||||
|
||||
let data = require('./emoji_data.json');
|
||||
const emojiMap = require('./emoji_map.json');
|
||||
const { unicodeToFilename } = require('./unicode_to_filename');
|
||||
const { unicodeToUnifiedName } = require('./unicode_to_unified_name');
|
||||
import data from './emoji_data.json';
|
||||
import emojiMap from './emoji_map.json';
|
||||
import { unicodeToFilename } from './unicode_to_filename';
|
||||
import { unicodeToUnifiedName } from './unicode_to_unified_name';
|
||||
|
||||
emojiMartUncompress(data);
|
||||
|
||||
const emojiMartData = data;
|
||||
const emojiIndex = new NimbleEmojiIndex(emojiMartData);
|
||||
|
||||
const excluded = ['®', '©', '™'];
|
||||
const skinTones = ['🏻', '🏼', '🏽', '🏾', '🏿'];
|
||||
const shortcodeMap = {};
|
||||
const excluded = ['®', '©', '™'];
|
||||
const skinTones = ['🏻', '🏼', '🏽', '🏾', '🏿'];
|
||||
const shortcodeMap = {};
|
||||
|
||||
const shortCodesToEmojiData = {};
|
||||
const emojisWithoutShortCodes = [];
|
||||
|
||||
Object.keys(emojiIndex.emojis).forEach(key => {
|
||||
Object.keys(emojiIndex.emojis).forEach((key) => {
|
||||
let emoji = emojiIndex.emojis[key];
|
||||
|
||||
// Emojis with skin tone modifiers are stored like this
|
||||
@@ -41,22 +40,22 @@ Object.keys(emojiIndex.emojis).forEach(key => {
|
||||
shortcodeMap[emoji.native] = emoji.id;
|
||||
});
|
||||
|
||||
const stripModifiers = unicode => {
|
||||
skinTones.forEach(tone => {
|
||||
const stripModifiers = (unicode) => {
|
||||
skinTones.forEach((tone) => {
|
||||
unicode = unicode.replace(tone, '');
|
||||
});
|
||||
|
||||
return unicode;
|
||||
};
|
||||
|
||||
Object.keys(emojiMap).forEach(key => {
|
||||
Object.keys(emojiMap).forEach((key) => {
|
||||
if (excluded.includes(key)) {
|
||||
delete emojiMap[key];
|
||||
return;
|
||||
}
|
||||
|
||||
const normalizedKey = stripModifiers(key);
|
||||
let shortcode = shortcodeMap[normalizedKey];
|
||||
let shortcode = shortcodeMap[normalizedKey];
|
||||
|
||||
if (!shortcode) {
|
||||
shortcode = shortcodeMap[normalizedKey + '\uFE0F'];
|
||||
@@ -82,7 +81,7 @@ Object.keys(emojiMap).forEach(key => {
|
||||
}
|
||||
});
|
||||
|
||||
Object.keys(emojiIndex.emojis).forEach(key => {
|
||||
Object.keys(emojiIndex.emojis).forEach((key) => {
|
||||
let emoji = emojiIndex.emojis[key];
|
||||
|
||||
// Emojis with skin tone modifiers are stored like this
|
||||
@@ -94,9 +93,11 @@ Object.keys(emojiIndex.emojis).forEach(key => {
|
||||
let { short_names, search, unified } = emojiMartData.emojis[key];
|
||||
|
||||
if (short_names[0] !== key) {
|
||||
throw new Error('The compressor expects the first short_code to be the ' +
|
||||
'key. It may need to be rewritten if the emoji change such that this ' +
|
||||
'is no longer the case.');
|
||||
throw new Error(
|
||||
'The compressor expects the first short_code to be the ' +
|
||||
'key. It may need to be rewritten if the emoji change such that this ' +
|
||||
'is no longer the case.',
|
||||
);
|
||||
}
|
||||
|
||||
short_names = short_names.slice(1); // first short name can be inferred from the key
|
||||
@@ -117,20 +118,22 @@ Object.keys(emojiIndex.emojis).forEach(key => {
|
||||
|
||||
// JSON.parse/stringify is to emulate what @preval is doing and avoid any
|
||||
// inconsistent behavior in dev mode
|
||||
module.exports = JSON.parse(JSON.stringify([
|
||||
shortCodesToEmojiData,
|
||||
/*
|
||||
* The property `skins` is not found in the current context.
|
||||
* This could potentially lead to issues when interacting with modules or data structures
|
||||
* that expect the presence of `skins` property.
|
||||
* Currently, no definitions or references to `skins` property can be found in:
|
||||
* - {@link node_modules/emoji-mart/dist/utils/data.js}
|
||||
* - {@link node_modules/emoji-mart/data/all.json}
|
||||
* - {@link app/javascript/mastodon/features/emoji/emoji_compressed.d.ts#Skins}
|
||||
* Future refactorings or updates should consider adding definitions or handling for `skins` property.
|
||||
*/
|
||||
emojiMartData.skins,
|
||||
emojiMartData.categories,
|
||||
emojiMartData.aliases,
|
||||
emojisWithoutShortCodes
|
||||
]));
|
||||
export default JSON.parse(
|
||||
JSON.stringify([
|
||||
shortCodesToEmojiData,
|
||||
/*
|
||||
* The property `skins` is not found in the current context.
|
||||
* This could potentially lead to issues when interacting with modules or data structures
|
||||
* that expect the presence of `skins` property.
|
||||
* Currently, no definitions or references to `skins` property can be found in:
|
||||
* - {@link node_modules/emoji-mart/dist/utils/data.js}
|
||||
* - {@link node_modules/emoji-mart/data/all.json}
|
||||
* - {@link app/javascript/flavours/glitch/features/emoji/emoji_compressed.d.ts#Skins}
|
||||
* Future refactorings or updates should consider adding definitions or handling for `skins` property.
|
||||
*/
|
||||
emojiMartData.skins,
|
||||
emojiMartData.categories,
|
||||
emojiMartData.aliases,
|
||||
emojisWithoutShortCodes,
|
||||
]),
|
||||
);
|
||||
@@ -3,9 +3,13 @@
|
||||
// emojiIndex.search functionality.
|
||||
import type { BaseEmoji } from 'emoji-mart';
|
||||
import type { Emoji } from 'emoji-mart/dist-es/utils/data';
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import emojiCompressed from 'virtual:mastodon-emoji-compressed';
|
||||
import type {
|
||||
Search,
|
||||
ShortCodesToEmojiData,
|
||||
} from 'virtual:mastodon-emoji-compressed';
|
||||
|
||||
import type { Search, ShortCodesToEmojiData } from './emoji_compressed';
|
||||
import emojiCompressed from './emoji_compressed';
|
||||
import { unicodeToUnifiedName } from './unicode_to_unified_name';
|
||||
|
||||
type Emojis = Record<
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
// (i.e. the svg filename) and a shortCode intended to be shown
|
||||
// as a "title" attribute in an HTML element (aka tooltip).
|
||||
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import emojiCompressed from 'virtual:mastodon-emoji-compressed';
|
||||
import type {
|
||||
FilenameData,
|
||||
ShortCodesToEmojiDataKey,
|
||||
} from './emoji_compressed';
|
||||
import emojiCompressed from './emoji_compressed';
|
||||
} from 'virtual:mastodon-emoji-compressed';
|
||||
|
||||
import { unicodeToFilename } from './unicode_to_filename';
|
||||
|
||||
type UnicodeMapping = Record<
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// taken from:
|
||||
// https://github.com/twitter/twemoji/blob/47732c7/twemoji-generator.js#L848-L866
|
||||
exports.unicodeToFilename = (str) => {
|
||||
export const unicodeToFilename = (str) => {
|
||||
let result = '';
|
||||
let charCode = 0;
|
||||
let p = 0;
|
||||
|
||||
@@ -6,7 +6,7 @@ function padLeft(str, num) {
|
||||
return str;
|
||||
}
|
||||
|
||||
exports.unicodeToUnifiedName = (str) => {
|
||||
export const unicodeToUnifiedName = (str) => {
|
||||
let output = '';
|
||||
|
||||
for (let i = 0; i < str.length; i += 2) {
|
||||
|
||||
@@ -1,243 +1,243 @@
|
||||
export function EmojiPicker () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/emoji_picker" */'../../emoji/emoji_picker');
|
||||
return import('../../emoji/emoji_picker');
|
||||
}
|
||||
|
||||
export function Compose () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/compose" */'../../compose');
|
||||
return import('../../compose');
|
||||
}
|
||||
|
||||
export function Notifications () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/notifications" */'../../notifications_v2');
|
||||
return import('../../notifications_v2');
|
||||
}
|
||||
|
||||
export function HomeTimeline () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/home_timeline" */'../../home_timeline');
|
||||
return import('../../home_timeline');
|
||||
}
|
||||
|
||||
export function PublicTimeline () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/public_timeline" */'../../public_timeline');
|
||||
return import('../../public_timeline');
|
||||
}
|
||||
|
||||
export function CommunityTimeline () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/community_timeline" */'../../community_timeline');
|
||||
return import('../../community_timeline');
|
||||
}
|
||||
|
||||
export function Firehose () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/firehose" */'../../firehose');
|
||||
return import('../../firehose');
|
||||
}
|
||||
|
||||
export function HashtagTimeline () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/hashtag_timeline" */'../../hashtag_timeline');
|
||||
return import('../../hashtag_timeline');
|
||||
}
|
||||
|
||||
export function ListTimeline () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/list_timeline" */'../../list_timeline');
|
||||
return import('../../list_timeline');
|
||||
}
|
||||
|
||||
export function Lists () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/lists" */'../../lists');
|
||||
return import('../../lists');
|
||||
}
|
||||
|
||||
export function DirectTimeline() {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/direct_timeline" */'../../direct_timeline');
|
||||
return import('../../direct_timeline');
|
||||
}
|
||||
|
||||
export function Status () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/status" */'../../status');
|
||||
return import('../../status');
|
||||
}
|
||||
|
||||
export function GettingStarted () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/getting_started" */'../../getting_started');
|
||||
return import('../../getting_started');
|
||||
}
|
||||
|
||||
export function GettingStartedMisc () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/getting_started_misc" */'../../getting_started_misc');
|
||||
return import('../../getting_started_misc');
|
||||
}
|
||||
|
||||
export function KeyboardShortcuts () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/keyboard_shortcuts" */'../../keyboard_shortcuts');
|
||||
return import('../../keyboard_shortcuts');
|
||||
}
|
||||
|
||||
export function PinnedStatuses () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/pinned_statuses" */'../../pinned_statuses');
|
||||
return import('../../pinned_statuses');
|
||||
}
|
||||
|
||||
export function AccountTimeline () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/account_timeline" */'../../account_timeline');
|
||||
return import('../../account_timeline');
|
||||
}
|
||||
|
||||
export function AccountGallery () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/account_gallery" */'../../account_gallery');
|
||||
return import('../../account_gallery');
|
||||
}
|
||||
|
||||
export function AccountFeatured() {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/account_featured" */'../../account_featured');
|
||||
return import('../../account_featured');
|
||||
}
|
||||
|
||||
export function Followers () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/followers" */'../../followers');
|
||||
return import('../../followers');
|
||||
}
|
||||
|
||||
export function Following () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/following" */'../../following');
|
||||
return import('../../following');
|
||||
}
|
||||
|
||||
export function Reblogs () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/reblogs" */'../../reblogs');
|
||||
return import('../../reblogs');
|
||||
}
|
||||
|
||||
export function Favourites () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/favourites" */'../../favourites');
|
||||
return import('../../favourites');
|
||||
}
|
||||
|
||||
export function FollowRequests () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/follow_requests" */'../../follow_requests');
|
||||
return import('../../follow_requests');
|
||||
}
|
||||
|
||||
export function FavouritedStatuses () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/favourited_statuses" */'../../favourited_statuses');
|
||||
return import('../../favourited_statuses');
|
||||
}
|
||||
|
||||
export function FollowedTags () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/followed_tags" */'../../followed_tags');
|
||||
return import('../../followed_tags');
|
||||
}
|
||||
|
||||
export function BookmarkedStatuses () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/bookmarked_statuses" */'../../bookmarked_statuses');
|
||||
return import('../../bookmarked_statuses');
|
||||
}
|
||||
|
||||
export function Blocks () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/blocks" */'../../blocks');
|
||||
return import('../../blocks');
|
||||
}
|
||||
|
||||
export function DomainBlocks () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/domain_blocks" */'../../domain_blocks');
|
||||
return import('../../domain_blocks');
|
||||
}
|
||||
|
||||
export function Mutes () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/mutes" */'../../mutes');
|
||||
return import('../../mutes');
|
||||
}
|
||||
|
||||
export function MuteModal () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/mute_modal" */'../components/mute_modal');
|
||||
return import('../components/mute_modal');
|
||||
}
|
||||
|
||||
export function BlockModal () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/block_modal" */'../components/block_modal');
|
||||
return import('../components/block_modal');
|
||||
}
|
||||
|
||||
export function DomainBlockModal () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/modals/domain_block_modal" */'../components/domain_block_modal');
|
||||
return import('../components/domain_block_modal');
|
||||
}
|
||||
|
||||
export function ReportModal () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/report_modal" */'../components/report_modal');
|
||||
return import('../components/report_modal');
|
||||
}
|
||||
|
||||
export function SettingsModal () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/settings_modal" */'../../local_settings');
|
||||
return import('../../local_settings');
|
||||
}
|
||||
|
||||
export function IgnoreNotificationsModal () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/ignore_notifications_modal" */'../components/ignore_notifications_modal');
|
||||
return import('../components/ignore_notifications_modal');
|
||||
}
|
||||
|
||||
export function MediaGallery () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/media_gallery" */'../../../components/media_gallery');
|
||||
return import('../../../components/media_gallery');
|
||||
}
|
||||
|
||||
export function Video () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/video" */'../../video');
|
||||
return import('../../video');
|
||||
}
|
||||
|
||||
export function EmbedModal () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/embed_modal" */'../components/embed_modal');
|
||||
return import('../components/embed_modal');
|
||||
}
|
||||
|
||||
export function ListAdder () {
|
||||
return import(/* webpackChunkName: "features/glitch/async/list_adder" */'../../list_adder');
|
||||
return import('../../list_adder');
|
||||
}
|
||||
|
||||
export function Tesseract () {
|
||||
return import(/*webpackChunkName: "tesseract" */'tesseract.js');
|
||||
return import('tesseract.js');
|
||||
}
|
||||
|
||||
export function Audio () {
|
||||
return import(/* webpackChunkName: "features/glitch/async/audio" */'../../audio');
|
||||
return import('../../audio');
|
||||
}
|
||||
|
||||
export function Directory () {
|
||||
return import(/* webpackChunkName: "features/glitch/async/directory" */'../../directory');
|
||||
return import('../../directory');
|
||||
}
|
||||
|
||||
export function OnboardingProfile () {
|
||||
return import(/* webpackChunkName: "features/glitch/async/onboarding" */'../../onboarding/profile');
|
||||
return import('../../onboarding/profile');
|
||||
}
|
||||
|
||||
export function OnboardingFollows () {
|
||||
return import(/* webpackChunkName: "features/glitch/async/onboarding" */'../../onboarding/follows');
|
||||
return import('../../onboarding/follows');
|
||||
}
|
||||
|
||||
export function CompareHistoryModal () {
|
||||
return import(/*webpackChunkName: "flavours/glitch/async/compare_history_modal" */'../components/compare_history_modal');
|
||||
return import('../components/compare_history_modal');
|
||||
}
|
||||
|
||||
export function Explore () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/explore" */'../../explore');
|
||||
return import('../../explore');
|
||||
}
|
||||
|
||||
export function Search () {
|
||||
return import(/* webpackChunkName: "features/glitch/async/explore" */'../../search');
|
||||
return import('../../search');
|
||||
}
|
||||
|
||||
export function FilterModal () {
|
||||
return import(/*webpackChunkName: "flavours/glitch/async/filter_modal" */'../components/filter_modal');
|
||||
return import('../components/filter_modal');
|
||||
}
|
||||
|
||||
export function InteractionModal () {
|
||||
return import(/*webpackChunkName: "flavours/glitch/async/modals/interaction_modal" */'../../interaction_modal');
|
||||
return import('../../interaction_modal');
|
||||
}
|
||||
|
||||
export function SubscribedLanguagesModal () {
|
||||
return import(/*webpackChunkName: "flavours/glitch/async/modals/subscribed_languages_modal" */'../../subscribed_languages_modal');
|
||||
return import('../../subscribed_languages_modal');
|
||||
}
|
||||
|
||||
export function ClosedRegistrationsModal () {
|
||||
return import(/*webpackChunkName: "flavours/glitch/async/modals/closed_registrations_modal" */'../../closed_registrations_modal');
|
||||
return import('../../closed_registrations_modal');
|
||||
}
|
||||
|
||||
export function About () {
|
||||
return import(/*webpackChunkName: "features/glitch/async/about" */'../../about');
|
||||
return import('../../about');
|
||||
}
|
||||
|
||||
export function PrivacyPolicy () {
|
||||
return import(/*webpackChunkName: "features/glitch/async/privacy_policy" */'../../privacy_policy');
|
||||
return import('../../privacy_policy');
|
||||
}
|
||||
|
||||
export function TermsOfService () {
|
||||
return import(/*webpackChunkName: "features/glitch/async/terms_of_service" */'../../terms_of_service');
|
||||
return import('../../terms_of_service');
|
||||
}
|
||||
|
||||
export function NotificationRequests () {
|
||||
return import(/*webpackChunkName: "features/glitch/notifications/requests" */'../../notifications/requests');
|
||||
return import('../../notifications/requests');
|
||||
}
|
||||
|
||||
export function NotificationRequest () {
|
||||
return import(/*webpackChunkName: "features/glitch/notifications/request" */'../../notifications/request');
|
||||
return import('../../notifications/request');
|
||||
}
|
||||
|
||||
export function LinkTimeline () {
|
||||
return import(/*webpackChunkName: "features/glitch/link_timeline" */'../../link_timeline');
|
||||
return import('../../link_timeline');
|
||||
}
|
||||
|
||||
export function AnnualReportModal () {
|
||||
return import(/*webpackChunkName: "flavours/glitch/async/modals/annual_report_modal" */'../components/annual_report_modal');
|
||||
return import('../components/annual_report_modal');
|
||||
}
|
||||
|
||||
export function ListEdit () {
|
||||
return import(/*webpackChunkName: "flavours/glitch/async/lists" */'../../lists/new');
|
||||
return import('../../lists/new');
|
||||
}
|
||||
|
||||
export function ListMembers () {
|
||||
return import(/* webpackChunkName: "flavours/glitch/async/lists" */'../../lists/members');
|
||||
return import('../../lists/members');
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// can at least log in using KaiOS devices).
|
||||
|
||||
function importArrowKeyNavigation() {
|
||||
return import(/* webpackChunkName: "arrow-key-navigation" */ 'arrow-key-navigation');
|
||||
return import('arrow-key-navigation');
|
||||
}
|
||||
|
||||
export default function loadKeyboardExtensions() {
|
||||
|
||||
@@ -5,6 +5,13 @@ import { isLocaleLoaded, setLocale } from './global_locale';
|
||||
|
||||
const localeLoadingSemaphore = new Semaphore(1);
|
||||
|
||||
const upstreamLocaleFiles = import.meta.glob<{ default: LocaleData['messages'] }>([
|
||||
'@/mastodon/locales/*.json',
|
||||
]);
|
||||
const localeFiles = import.meta.glob<{ default: LocaleData['messages'] }>([
|
||||
'./*.json',
|
||||
]);
|
||||
|
||||
export async function loadLocale() {
|
||||
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- we want to match empty strings
|
||||
const locale = document.querySelector<HTMLElement>('html')?.lang || 'en';
|
||||
@@ -17,21 +24,23 @@ export async function loadLocale() {
|
||||
// if the locale is already set, then do nothing
|
||||
if (isLocaleLoaded()) return;
|
||||
|
||||
const upstreamLocaleData = await import(
|
||||
/* webpackMode: "lazy" */
|
||||
/* webpackChunkName: "locales/vanilla/[request]" */
|
||||
/* webpackInclude: /\.json$/ */
|
||||
/* webpackPreload: true */
|
||||
`mastodon/locales/${locale}.json`
|
||||
) as LocaleData['messages'];
|
||||
// If there is no locale file, then fallback to english
|
||||
const upstreamLocaleFile = Object.hasOwn(upstreamLocaleFiles, `@/mastodon/locales/${locale}.json`)
|
||||
? upstreamLocaleFiles[`/mastodon/locales/${locale}.json`]
|
||||
: upstreamLocaleFiles['/mastodon/locales/en.json'];
|
||||
|
||||
const localeData = await import(
|
||||
/* webpackMode: "lazy" */
|
||||
/* webpackChunkName: "locales/glitch/[request]" */
|
||||
/* webpackInclude: /\.json$/ */
|
||||
/* webpackPreload: true */
|
||||
`flavours/glitch/locales/${locale}.json`
|
||||
) as LocaleData['messages'];
|
||||
if (!upstreamLocaleFile) throw new Error('Could not load the upstream locale JSON file');
|
||||
|
||||
const { default: upstreamLocaleData } = await upstreamLocaleFile();
|
||||
|
||||
// If there is no locale file, then fallback to english
|
||||
const localeFile = Object.hasOwn(localeFiles, `./${locale}.json`)
|
||||
? localeFiles[`./${locale}.json`]
|
||||
: localeFiles['./en.json'];
|
||||
|
||||
if (!localeFile) throw new Error('Could not load the locale JSON file');
|
||||
|
||||
const { default: localeData } = await localeFile();
|
||||
|
||||
setLocale({ messages: { ...upstreamLocaleData, ...localeData }, locale });
|
||||
});
|
||||
|
||||
@@ -7,17 +7,19 @@ import * as perf from 'flavours/glitch/performance';
|
||||
import ready from 'flavours/glitch/ready';
|
||||
import { store } from 'flavours/glitch/store';
|
||||
|
||||
import { isProduction } from './utils/environment';
|
||||
import { isProduction, isDevelopment } from './utils/environment';
|
||||
|
||||
/**
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
function main() {
|
||||
perf.start('main()');
|
||||
|
||||
return ready(async () => {
|
||||
const mountNode = document.getElementById('mastodon');
|
||||
const props = JSON.parse(mountNode.getAttribute('data-props'));
|
||||
if (!mountNode) {
|
||||
throw new Error('Mount node not found');
|
||||
}
|
||||
const props = JSON.parse(
|
||||
mountNode.getAttribute('data-props') ?? '{}',
|
||||
) as Record<string, unknown>;
|
||||
|
||||
const root = createRoot(mountNode);
|
||||
root.render(<Mastodon {...props} />);
|
||||
@@ -25,8 +27,10 @@ function main() {
|
||||
|
||||
if (isProduction() && me && 'serviceWorker' in navigator) {
|
||||
const { Workbox } = await import('workbox-window');
|
||||
const wb = new Workbox('/sw.js');
|
||||
/** @type {ServiceWorkerRegistration} */
|
||||
const wb = new Workbox(
|
||||
isDevelopment() ? '/packs-dev/dev-sw.js?dev-sw' : '/sw.js',
|
||||
{ type: 'module', scope: '/' },
|
||||
);
|
||||
let registration;
|
||||
|
||||
try {
|
||||
@@ -35,8 +39,14 @@ function main() {
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
if (registration && 'Notification' in window && Notification.permission === 'granted') {
|
||||
const registerPushNotifications = await import('flavours/glitch/actions/push_notifications');
|
||||
if (
|
||||
registration &&
|
||||
'Notification' in window &&
|
||||
Notification.permission === 'granted'
|
||||
) {
|
||||
const registerPushNotifications = await import(
|
||||
'flavours/glitch/actions/push_notifications'
|
||||
);
|
||||
|
||||
store.dispatch(registerPushNotifications.register());
|
||||
}
|
||||
@@ -46,4 +56,5 @@ function main() {
|
||||
});
|
||||
}
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default main;
|
||||
@@ -1,24 +1,11 @@
|
||||
//
|
||||
// Tools for performance debugging, only enabled in development mode.
|
||||
// Open up Chrome Dev Tools, then Timeline, then User Timing to see output.
|
||||
// Also see config/webpack/loaders/mark.js for the webpack loader marks.
|
||||
|
||||
import * as marky from 'marky';
|
||||
|
||||
import { isDevelopment } from './utils/environment';
|
||||
|
||||
if (isDevelopment()) {
|
||||
if (typeof performance !== 'undefined' && performance.setResourceTimingBufferSize) {
|
||||
// Increase Firefox's performance entry limit; otherwise it's capped to 150.
|
||||
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=1331135
|
||||
performance.setResourceTimingBufferSize(Infinity);
|
||||
}
|
||||
|
||||
// allows us to easily do e.g. ReactPerf.printWasted() while debugging
|
||||
//window.ReactPerf = require('react-addons-perf');
|
||||
//window.ReactPerf.start();
|
||||
}
|
||||
|
||||
export function start(name) {
|
||||
if (isDevelopment()) {
|
||||
marky.mark(name);
|
||||
|
||||
@@ -2,10 +2,13 @@
|
||||
// If there are no polyfills, then this is just Promise.resolve() which means
|
||||
// it will execute in the same tick of the event loop (i.e. near-instant).
|
||||
|
||||
// eslint-disable-next-line import/extensions -- This file is virtual so it thinks it has an extension
|
||||
import 'vite/modulepreload-polyfill';
|
||||
|
||||
import { loadIntlPolyfills } from './intl';
|
||||
|
||||
function importExtraPolyfills() {
|
||||
return import(/* webpackChunkName: "extra_polyfills" */ './extra_polyfills');
|
||||
return import('./extra_polyfills');
|
||||
}
|
||||
|
||||
export function loadPolyfills() {
|
||||
|
||||
@@ -54,11 +54,9 @@ async function loadIntlPluralRulesPolyfills(locale: string) {
|
||||
return;
|
||||
}
|
||||
// Load the polyfill 1st BEFORE loading data
|
||||
await import('@formatjs/intl-pluralrules/polyfill-force');
|
||||
await import(
|
||||
/* webpackChunkName: "i18n-pluralrules-polyfill" */ '@formatjs/intl-pluralrules/polyfill-force'
|
||||
);
|
||||
await import(
|
||||
/* webpackChunkName: "i18n-pluralrules-polyfill-[request]" */ `@formatjs/intl-pluralrules/locale-data/${unsupportedLocale}`
|
||||
`../../../../../node_modules/@formatjs/intl-pluralrules/locale-data/${unsupportedLocale}.js`
|
||||
);
|
||||
}
|
||||
|
||||
@@ -70,11 +68,9 @@ async function loadIntlPluralRulesPolyfills(locale: string) {
|
||||
// }
|
||||
// // Load the polyfill 1st BEFORE loading data
|
||||
// await import(
|
||||
// /* webpackChunkName: "i18n-relativetimeformat-polyfill" */
|
||||
// '@formatjs/intl-relativetimeformat/polyfill-force'
|
||||
// );
|
||||
// await import(
|
||||
// /* webpackChunkName: "i18n-relativetimeformat-polyfill-[request]" */
|
||||
// `@formatjs/intl-relativetimeformat/locale-data/${unsupportedLocale}`
|
||||
// );
|
||||
// }
|
||||
|
||||
@@ -1451,8 +1451,8 @@ a.sparkline {
|
||||
inset-inline-start: 10px;
|
||||
border-radius: 4px;
|
||||
background:
|
||||
url('~images/warning-stripes.svg') repeat-y left,
|
||||
url('~images/warning-stripes.svg') repeat-y right,
|
||||
url('@/images/warning-stripes.svg') repeat-y left,
|
||||
url('@/images/warning-stripes.svg') repeat-y right,
|
||||
var(--background-color);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
@use 'mixins';
|
||||
@use 'variables';
|
||||
@use 'css_variables';
|
||||
@use 'styles/fonts/roboto';
|
||||
@use 'styles/fonts/roboto-mono';
|
||||
@use '@/styles/fonts/roboto';
|
||||
@use '@/styles/fonts/roboto-mono';
|
||||
|
||||
@use 'reset';
|
||||
@use 'basics';
|
||||
|
||||
@@ -641,7 +641,7 @@ body > [data-popper-placement] {
|
||||
align-items: stretch;
|
||||
|
||||
&__border {
|
||||
background: url('~images/warning-stripes.svg') repeat-y;
|
||||
background: url('@/images/warning-stripes.svg') repeat-y;
|
||||
width: 5px;
|
||||
flex: 0 0 auto;
|
||||
|
||||
|
||||
@@ -394,7 +394,7 @@ code {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
border-radius: var(--avatar-border-radius);
|
||||
background: url('images/void.png');
|
||||
background: url('@/images/void.png');
|
||||
|
||||
&[src$='missing.png'] {
|
||||
visibility: hidden;
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
content: '';
|
||||
width: 24px;
|
||||
height: 20px;
|
||||
mask-image: url('~images/quote.svg');
|
||||
mask-image: url('@/images/quote.svg');
|
||||
background-color: var(--rich-text-decorations-color);
|
||||
position: absolute;
|
||||
inset-inline-start: 0;
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
export function isDevelopment() {
|
||||
return process.env.NODE_ENV === 'development';
|
||||
if (typeof process !== 'undefined')
|
||||
return process.env.NODE_ENV === 'development';
|
||||
else return import.meta.env.DEV;
|
||||
}
|
||||
|
||||
export function isProduction() {
|
||||
return process.env.NODE_ENV === 'production';
|
||||
if (typeof process !== 'undefined')
|
||||
return process.env.NODE_ENV === 'production';
|
||||
else return import.meta.env.PROD;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import Rails from '@rails/ujs';
|
||||
|
||||
export function start() {
|
||||
require.context('../images/', true, /\.(jpg|png|svg)$/);
|
||||
|
||||
try {
|
||||
Rails.start();
|
||||
} catch {
|
||||
@@ -9,7 +9,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import BookmarkIcon from '@/material-icons/400-24px/bookmark-fill.svg';
|
||||
import BookmarkIcon from '@/material-icons/400-24px/bookmark-fill.svg?react';
|
||||
import BookmarkBorderIcon from '@/material-icons/400-24px/bookmark.svg?react';
|
||||
import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react';
|
||||
import RepeatIcon from '@/material-icons/400-24px/repeat.svg?react';
|
||||
|
||||
@@ -15,10 +15,6 @@ import type { List as ImmutableList, Map as ImmutableMap } from 'immutable';
|
||||
import { useSpring, animated } from '@react-spring/web';
|
||||
import Textarea from 'react-textarea-autosize';
|
||||
import { length } from 'stringz';
|
||||
// eslint-disable-next-line import/extensions
|
||||
import tesseractWorkerPath from 'tesseract.js/dist/worker.min.js';
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
import tesseractCorePath from 'tesseract.js-core/tesseract-core.wasm.js';
|
||||
|
||||
import { showAlertForError } from 'mastodon/actions/alerts';
|
||||
import { uploadThumbnail } from 'mastodon/actions/compose';
|
||||
@@ -350,9 +346,15 @@ export const AltTextModal = forwardRef<ModalRef, Props & Partial<RestoreProps>>(
|
||||
|
||||
fetchTesseract()
|
||||
.then(async ({ createWorker }) => {
|
||||
const [tesseractWorkerPath, tesseractCorePath] = await Promise.all([
|
||||
// eslint-disable-next-line import/extensions
|
||||
import('tesseract.js/dist/worker.min.js?url'),
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
import('tesseract.js-core/tesseract-core.wasm.js?url'),
|
||||
]);
|
||||
const worker = await createWorker('eng', 1, {
|
||||
workerPath: tesseractWorkerPath as string,
|
||||
corePath: tesseractCorePath as string,
|
||||
workerPath: tesseractWorkerPath.default,
|
||||
corePath: tesseractCorePath.default,
|
||||
langPath: `${assetHost}/ocr/lang-data`,
|
||||
cacheMethod: 'write',
|
||||
});
|
||||
@@ -501,5 +503,4 @@ export const AltTextModal = forwardRef<ModalRef, Props & Partial<RestoreProps>>(
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
AltTextModal.displayName = 'AltTextModal';
|
||||
|
||||
@@ -9,28 +9,27 @@
|
||||
// to ensure that the prevaled file is regenerated by Babel
|
||||
// version: 4
|
||||
|
||||
const { NimbleEmojiIndex } = require('emoji-mart');
|
||||
const { uncompress: emojiMartUncompress } = require('emoji-mart/dist/utils/data');
|
||||
import { NimbleEmojiIndex } from 'emoji-mart';
|
||||
import { uncompress as emojiMartUncompress } from 'emoji-mart/dist/utils/data';
|
||||
|
||||
|
||||
let data = require('./emoji_data.json');
|
||||
const emojiMap = require('./emoji_map.json');
|
||||
const { unicodeToFilename } = require('./unicode_to_filename');
|
||||
const { unicodeToUnifiedName } = require('./unicode_to_unified_name');
|
||||
import data from './emoji_data.json';
|
||||
import emojiMap from './emoji_map.json';
|
||||
import { unicodeToFilename } from './unicode_to_filename';
|
||||
import { unicodeToUnifiedName } from './unicode_to_unified_name';
|
||||
|
||||
emojiMartUncompress(data);
|
||||
|
||||
const emojiMartData = data;
|
||||
const emojiIndex = new NimbleEmojiIndex(emojiMartData);
|
||||
|
||||
const excluded = ['®', '©', '™'];
|
||||
const skinTones = ['🏻', '🏼', '🏽', '🏾', '🏿'];
|
||||
const shortcodeMap = {};
|
||||
const excluded = ['®', '©', '™'];
|
||||
const skinTones = ['🏻', '🏼', '🏽', '🏾', '🏿'];
|
||||
const shortcodeMap = {};
|
||||
|
||||
const shortCodesToEmojiData = {};
|
||||
const emojisWithoutShortCodes = [];
|
||||
|
||||
Object.keys(emojiIndex.emojis).forEach(key => {
|
||||
Object.keys(emojiIndex.emojis).forEach((key) => {
|
||||
let emoji = emojiIndex.emojis[key];
|
||||
|
||||
// Emojis with skin tone modifiers are stored like this
|
||||
@@ -41,22 +40,22 @@ Object.keys(emojiIndex.emojis).forEach(key => {
|
||||
shortcodeMap[emoji.native] = emoji.id;
|
||||
});
|
||||
|
||||
const stripModifiers = unicode => {
|
||||
skinTones.forEach(tone => {
|
||||
const stripModifiers = (unicode) => {
|
||||
skinTones.forEach((tone) => {
|
||||
unicode = unicode.replace(tone, '');
|
||||
});
|
||||
|
||||
return unicode;
|
||||
};
|
||||
|
||||
Object.keys(emojiMap).forEach(key => {
|
||||
Object.keys(emojiMap).forEach((key) => {
|
||||
if (excluded.includes(key)) {
|
||||
delete emojiMap[key];
|
||||
return;
|
||||
}
|
||||
|
||||
const normalizedKey = stripModifiers(key);
|
||||
let shortcode = shortcodeMap[normalizedKey];
|
||||
let shortcode = shortcodeMap[normalizedKey];
|
||||
|
||||
if (!shortcode) {
|
||||
shortcode = shortcodeMap[normalizedKey + '\uFE0F'];
|
||||
@@ -82,7 +81,7 @@ Object.keys(emojiMap).forEach(key => {
|
||||
}
|
||||
});
|
||||
|
||||
Object.keys(emojiIndex.emojis).forEach(key => {
|
||||
Object.keys(emojiIndex.emojis).forEach((key) => {
|
||||
let emoji = emojiIndex.emojis[key];
|
||||
|
||||
// Emojis with skin tone modifiers are stored like this
|
||||
@@ -94,9 +93,11 @@ Object.keys(emojiIndex.emojis).forEach(key => {
|
||||
let { short_names, search, unified } = emojiMartData.emojis[key];
|
||||
|
||||
if (short_names[0] !== key) {
|
||||
throw new Error('The compressor expects the first short_code to be the ' +
|
||||
'key. It may need to be rewritten if the emoji change such that this ' +
|
||||
'is no longer the case.');
|
||||
throw new Error(
|
||||
'The compressor expects the first short_code to be the ' +
|
||||
'key. It may need to be rewritten if the emoji change such that this ' +
|
||||
'is no longer the case.',
|
||||
);
|
||||
}
|
||||
|
||||
short_names = short_names.slice(1); // first short name can be inferred from the key
|
||||
@@ -117,20 +118,22 @@ Object.keys(emojiIndex.emojis).forEach(key => {
|
||||
|
||||
// JSON.parse/stringify is to emulate what @preval is doing and avoid any
|
||||
// inconsistent behavior in dev mode
|
||||
module.exports = JSON.parse(JSON.stringify([
|
||||
shortCodesToEmojiData,
|
||||
/*
|
||||
* The property `skins` is not found in the current context.
|
||||
* This could potentially lead to issues when interacting with modules or data structures
|
||||
* that expect the presence of `skins` property.
|
||||
* Currently, no definitions or references to `skins` property can be found in:
|
||||
* - {@link node_modules/emoji-mart/dist/utils/data.js}
|
||||
* - {@link node_modules/emoji-mart/data/all.json}
|
||||
* - {@link app/javascript/flavours/glitch/features/emoji/emoji_compressed.d.ts#Skins}
|
||||
* Future refactorings or updates should consider adding definitions or handling for `skins` property.
|
||||
*/
|
||||
emojiMartData.skins,
|
||||
emojiMartData.categories,
|
||||
emojiMartData.aliases,
|
||||
emojisWithoutShortCodes
|
||||
]));
|
||||
export default JSON.parse(
|
||||
JSON.stringify([
|
||||
shortCodesToEmojiData,
|
||||
/*
|
||||
* The property `skins` is not found in the current context.
|
||||
* This could potentially lead to issues when interacting with modules or data structures
|
||||
* that expect the presence of `skins` property.
|
||||
* Currently, no definitions or references to `skins` property can be found in:
|
||||
* - {@link node_modules/emoji-mart/dist/utils/data.js}
|
||||
* - {@link node_modules/emoji-mart/data/all.json}
|
||||
* - {@link app/javascript/mastodon/features/emoji/emoji_compressed.d.ts#Skins}
|
||||
* Future refactorings or updates should consider adding definitions or handling for `skins` property.
|
||||
*/
|
||||
emojiMartData.skins,
|
||||
emojiMartData.categories,
|
||||
emojiMartData.aliases,
|
||||
emojisWithoutShortCodes,
|
||||
]),
|
||||
);
|
||||
@@ -3,9 +3,13 @@
|
||||
// emojiIndex.search functionality.
|
||||
import type { BaseEmoji } from 'emoji-mart';
|
||||
import type { Emoji } from 'emoji-mart/dist-es/utils/data';
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import emojiCompressed from 'virtual:mastodon-emoji-compressed';
|
||||
import type {
|
||||
Search,
|
||||
ShortCodesToEmojiData,
|
||||
} from 'virtual:mastodon-emoji-compressed';
|
||||
|
||||
import type { Search, ShortCodesToEmojiData } from './emoji_compressed';
|
||||
import emojiCompressed from './emoji_compressed';
|
||||
import { unicodeToUnifiedName } from './unicode_to_unified_name';
|
||||
|
||||
type Emojis = Record<
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
// (i.e. the svg filename) and a shortCode intended to be shown
|
||||
// as a "title" attribute in an HTML element (aka tooltip).
|
||||
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import emojiCompressed from 'virtual:mastodon-emoji-compressed';
|
||||
import type {
|
||||
FilenameData,
|
||||
ShortCodesToEmojiDataKey,
|
||||
} from './emoji_compressed';
|
||||
import emojiCompressed from './emoji_compressed';
|
||||
} from 'virtual:mastodon-emoji-compressed';
|
||||
|
||||
import { unicodeToFilename } from './unicode_to_filename';
|
||||
|
||||
type UnicodeMapping = Record<
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// taken from:
|
||||
// https://github.com/twitter/twemoji/blob/47732c7/twemoji-generator.js#L848-L866
|
||||
exports.unicodeToFilename = (str) => {
|
||||
export const unicodeToFilename = (str) => {
|
||||
let result = '';
|
||||
let charCode = 0;
|
||||
let p = 0;
|
||||
|
||||
@@ -6,7 +6,7 @@ function padLeft(str, num) {
|
||||
return str;
|
||||
}
|
||||
|
||||
exports.unicodeToUnifiedName = (str) => {
|
||||
export const unicodeToUnifiedName = (str) => {
|
||||
let output = '';
|
||||
|
||||
for (let i = 0; i < str.length; i += 2) {
|
||||
|
||||
@@ -1,235 +1,235 @@
|
||||
export function EmojiPicker () {
|
||||
return import(/* webpackChunkName: "emoji_picker" */'../../emoji/emoji_picker');
|
||||
return import('../../emoji/emoji_picker');
|
||||
}
|
||||
|
||||
export function Compose () {
|
||||
return import(/* webpackChunkName: "features/compose" */'../../compose');
|
||||
return import('../../compose');
|
||||
}
|
||||
|
||||
export function Notifications () {
|
||||
return import(/* webpackChunkName: "features/notifications" */'../../notifications_v2');
|
||||
return import('../../notifications_v2');
|
||||
}
|
||||
|
||||
export function HomeTimeline () {
|
||||
return import(/* webpackChunkName: "features/home_timeline" */'../../home_timeline');
|
||||
return import('../../home_timeline');
|
||||
}
|
||||
|
||||
export function PublicTimeline () {
|
||||
return import(/* webpackChunkName: "features/public_timeline" */'../../public_timeline');
|
||||
return import('../../public_timeline');
|
||||
}
|
||||
|
||||
export function CommunityTimeline () {
|
||||
return import(/* webpackChunkName: "features/community_timeline" */'../../community_timeline');
|
||||
return import('../../community_timeline');
|
||||
}
|
||||
|
||||
export function Firehose () {
|
||||
return import(/* webpackChunkName: "features/firehose" */'../../firehose');
|
||||
return import('../../firehose');
|
||||
}
|
||||
|
||||
export function HashtagTimeline () {
|
||||
return import(/* webpackChunkName: "features/hashtag_timeline" */'../../hashtag_timeline');
|
||||
return import('../../hashtag_timeline');
|
||||
}
|
||||
|
||||
export function DirectTimeline() {
|
||||
return import(/* webpackChunkName: "features/direct_timeline" */'../../direct_timeline');
|
||||
return import('../../direct_timeline');
|
||||
}
|
||||
|
||||
export function ListTimeline () {
|
||||
return import(/* webpackChunkName: "features/list_timeline" */'../../list_timeline');
|
||||
return import('../../list_timeline');
|
||||
}
|
||||
|
||||
export function Lists () {
|
||||
return import(/* webpackChunkName: "features/lists" */'../../lists');
|
||||
return import('../../lists');
|
||||
}
|
||||
|
||||
export function Status () {
|
||||
return import(/* webpackChunkName: "features/status" */'../../status');
|
||||
return import('../../status');
|
||||
}
|
||||
|
||||
export function GettingStarted () {
|
||||
return import(/* webpackChunkName: "features/getting_started" */'../../getting_started');
|
||||
return import('../../getting_started');
|
||||
}
|
||||
|
||||
export function KeyboardShortcuts () {
|
||||
return import(/* webpackChunkName: "features/keyboard_shortcuts" */'../../keyboard_shortcuts');
|
||||
return import('../../keyboard_shortcuts');
|
||||
}
|
||||
|
||||
export function PinnedStatuses () {
|
||||
return import(/* webpackChunkName: "features/pinned_statuses" */'../../pinned_statuses');
|
||||
return import('../../pinned_statuses');
|
||||
}
|
||||
|
||||
export function AccountTimeline () {
|
||||
return import(/* webpackChunkName: "features/account_timeline" */'../../account_timeline');
|
||||
return import('../../account_timeline');
|
||||
}
|
||||
|
||||
export function AccountGallery () {
|
||||
return import(/* webpackChunkName: "features/account_gallery" */'../../account_gallery');
|
||||
return import('../../account_gallery');
|
||||
}
|
||||
|
||||
export function AccountFeatured() {
|
||||
return import(/* webpackChunkName: "features/account_featured" */'../../account_featured');
|
||||
return import('../../account_featured');
|
||||
}
|
||||
|
||||
export function Followers () {
|
||||
return import(/* webpackChunkName: "features/followers" */'../../followers');
|
||||
return import('../../followers');
|
||||
}
|
||||
|
||||
export function Following () {
|
||||
return import(/* webpackChunkName: "features/following" */'../../following');
|
||||
return import('../../following');
|
||||
}
|
||||
|
||||
export function Reblogs () {
|
||||
return import(/* webpackChunkName: "features/reblogs" */'../../reblogs');
|
||||
return import('../../reblogs');
|
||||
}
|
||||
|
||||
export function Favourites () {
|
||||
return import(/* webpackChunkName: "features/favourites" */'../../favourites');
|
||||
return import('../../favourites');
|
||||
}
|
||||
|
||||
export function FollowRequests () {
|
||||
return import(/* webpackChunkName: "features/follow_requests" */'../../follow_requests');
|
||||
return import('../../follow_requests');
|
||||
}
|
||||
|
||||
export function FavouritedStatuses () {
|
||||
return import(/* webpackChunkName: "features/favourited_statuses" */'../../favourited_statuses');
|
||||
return import('../../favourited_statuses');
|
||||
}
|
||||
|
||||
export function FollowedTags () {
|
||||
return import(/* webpackChunkName: "features/followed_tags" */'../../followed_tags');
|
||||
return import('../../followed_tags');
|
||||
}
|
||||
|
||||
export function BookmarkedStatuses () {
|
||||
return import(/* webpackChunkName: "features/bookmarked_statuses" */'../../bookmarked_statuses');
|
||||
return import('../../bookmarked_statuses');
|
||||
}
|
||||
|
||||
export function Blocks () {
|
||||
return import(/* webpackChunkName: "features/blocks" */'../../blocks');
|
||||
return import('../../blocks');
|
||||
}
|
||||
|
||||
export function DomainBlocks () {
|
||||
return import(/* webpackChunkName: "features/domain_blocks" */'../../domain_blocks');
|
||||
return import('../../domain_blocks');
|
||||
}
|
||||
|
||||
export function Mutes () {
|
||||
return import(/* webpackChunkName: "features/mutes" */'../../mutes');
|
||||
return import('../../mutes');
|
||||
}
|
||||
|
||||
export function MuteModal () {
|
||||
return import(/* webpackChunkName: "modals/mute_modal" */'../components/mute_modal');
|
||||
return import('../components/mute_modal');
|
||||
}
|
||||
|
||||
export function BlockModal () {
|
||||
return import(/* webpackChunkName: "modals/block_modal" */'../components/block_modal');
|
||||
return import('../components/block_modal');
|
||||
}
|
||||
|
||||
export function DomainBlockModal () {
|
||||
return import(/* webpackChunkName: "modals/domain_block_modal" */'../components/domain_block_modal');
|
||||
return import('../components/domain_block_modal');
|
||||
}
|
||||
|
||||
export function ReportModal () {
|
||||
return import(/* webpackChunkName: "modals/report_modal" */'../components/report_modal');
|
||||
return import('../components/report_modal');
|
||||
}
|
||||
|
||||
export function IgnoreNotificationsModal () {
|
||||
return import(/* webpackChunkName: "modals/domain_block_modal" */'../components/ignore_notifications_modal');
|
||||
return import('../components/ignore_notifications_modal');
|
||||
}
|
||||
|
||||
export function MediaGallery () {
|
||||
return import(/* webpackChunkName: "status/media_gallery" */'../../../components/media_gallery');
|
||||
return import('../../../components/media_gallery');
|
||||
}
|
||||
|
||||
export function Video () {
|
||||
return import(/* webpackChunkName: "features/video" */'../../video');
|
||||
return import('../../video');
|
||||
}
|
||||
|
||||
export function EmbedModal () {
|
||||
return import(/* webpackChunkName: "modals/embed_modal" */'../components/embed_modal');
|
||||
return import('../components/embed_modal');
|
||||
}
|
||||
|
||||
export function ListAdder () {
|
||||
return import(/*webpackChunkName: "features/list_adder" */'../../list_adder');
|
||||
return import('../../list_adder');
|
||||
}
|
||||
|
||||
export function Tesseract () {
|
||||
return import(/*webpackChunkName: "tesseract" */'tesseract.js');
|
||||
return import('tesseract.js');
|
||||
}
|
||||
|
||||
export function Audio () {
|
||||
return import(/* webpackChunkName: "features/audio" */'../../audio');
|
||||
return import('../../audio');
|
||||
}
|
||||
|
||||
export function Directory () {
|
||||
return import(/* webpackChunkName: "features/directory" */'../../directory');
|
||||
return import('../../directory');
|
||||
}
|
||||
|
||||
export function OnboardingProfile () {
|
||||
return import(/* webpackChunkName: "features/onboarding" */'../../onboarding/profile');
|
||||
return import('../../onboarding/profile');
|
||||
}
|
||||
|
||||
export function OnboardingFollows () {
|
||||
return import(/* webpackChunkName: "features/onboarding" */'../../onboarding/follows');
|
||||
return import('../../onboarding/follows');
|
||||
}
|
||||
|
||||
export function CompareHistoryModal () {
|
||||
return import(/*webpackChunkName: "modals/compare_history_modal" */'../components/compare_history_modal');
|
||||
return import('../components/compare_history_modal');
|
||||
}
|
||||
|
||||
export function Explore () {
|
||||
return import(/* webpackChunkName: "features/explore" */'../../explore');
|
||||
return import('../../explore');
|
||||
}
|
||||
|
||||
export function Search () {
|
||||
return import(/* webpackChunkName: "features/explore" */'../../search');
|
||||
return import('../../search');
|
||||
}
|
||||
|
||||
export function FilterModal () {
|
||||
return import(/*webpackChunkName: "modals/filter_modal" */'../components/filter_modal');
|
||||
return import('../components/filter_modal');
|
||||
}
|
||||
|
||||
export function InteractionModal () {
|
||||
return import(/*webpackChunkName: "modals/interaction_modal" */'../../interaction_modal');
|
||||
return import('../../interaction_modal');
|
||||
}
|
||||
|
||||
export function SubscribedLanguagesModal () {
|
||||
return import(/*webpackChunkName: "modals/subscribed_languages_modal" */'../../subscribed_languages_modal');
|
||||
return import('../../subscribed_languages_modal');
|
||||
}
|
||||
|
||||
export function ClosedRegistrationsModal () {
|
||||
return import(/*webpackChunkName: "modals/closed_registrations_modal" */'../../closed_registrations_modal');
|
||||
return import('../../closed_registrations_modal');
|
||||
}
|
||||
|
||||
export function About () {
|
||||
return import(/*webpackChunkName: "features/about" */'../../about');
|
||||
return import('../../about');
|
||||
}
|
||||
|
||||
export function PrivacyPolicy () {
|
||||
return import(/*webpackChunkName: "features/privacy_policy" */'../../privacy_policy');
|
||||
return import('../../privacy_policy');
|
||||
}
|
||||
|
||||
export function TermsOfService () {
|
||||
return import(/*webpackChunkName: "features/terms_of_service" */'../../terms_of_service');
|
||||
return import('../../terms_of_service');
|
||||
}
|
||||
|
||||
export function NotificationRequests () {
|
||||
return import(/*webpackChunkName: "features/notifications/requests" */'../../notifications/requests');
|
||||
return import('../../notifications/requests');
|
||||
}
|
||||
|
||||
export function NotificationRequest () {
|
||||
return import(/*webpackChunkName: "features/notifications/request" */'../../notifications/request');
|
||||
return import('../../notifications/request');
|
||||
}
|
||||
|
||||
export function LinkTimeline () {
|
||||
return import(/*webpackChunkName: "features/link_timeline" */'../../link_timeline');
|
||||
return import('../../link_timeline');
|
||||
}
|
||||
|
||||
export function AnnualReportModal () {
|
||||
return import(/*webpackChunkName: "modals/annual_report_modal" */'../components/annual_report_modal');
|
||||
return import('../components/annual_report_modal');
|
||||
}
|
||||
|
||||
export function ListEdit () {
|
||||
return import(/*webpackChunkName: "features/lists" */'../../lists/new');
|
||||
return import('../../lists/new');
|
||||
}
|
||||
|
||||
export function ListMembers () {
|
||||
return import(/* webpackChunkName: "features/lists" */'../../lists/members');
|
||||
return import('../../lists/members');
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// can at least log in using KaiOS devices).
|
||||
|
||||
function importArrowKeyNavigation() {
|
||||
return import(/* webpackChunkName: "arrow-key-navigation" */ 'arrow-key-navigation');
|
||||
return import('arrow-key-navigation');
|
||||
}
|
||||
|
||||
export default function loadKeyboardExtensions() {
|
||||
|
||||
@@ -5,6 +5,10 @@ import { isLocaleLoaded, setLocale } from './global_locale';
|
||||
|
||||
const localeLoadingSemaphore = new Semaphore(1);
|
||||
|
||||
const localeFiles = import.meta.glob<{ default: LocaleData['messages'] }>([
|
||||
'./*.json',
|
||||
]);
|
||||
|
||||
export async function loadLocale() {
|
||||
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- we want to match empty strings
|
||||
const locale = document.querySelector<HTMLElement>('html')?.lang || 'en';
|
||||
@@ -17,13 +21,14 @@ export async function loadLocale() {
|
||||
// if the locale is already set, then do nothing
|
||||
if (isLocaleLoaded()) return;
|
||||
|
||||
const localeData = (await import(
|
||||
/* webpackMode: "lazy" */
|
||||
/* webpackChunkName: "locales/vanilla/[request]" */
|
||||
/* webpackInclude: /\.json$/ */
|
||||
/* webpackPreload: true */
|
||||
`mastodon/locales/${locale}.json`
|
||||
)) as LocaleData['messages'];
|
||||
// If there is no locale file, then fallback to english
|
||||
const localeFile = Object.hasOwn(localeFiles, `./${locale}.json`)
|
||||
? localeFiles[`./${locale}.json`]
|
||||
: localeFiles['./en.json'];
|
||||
|
||||
if (!localeFile) throw new Error('Could not load the locale JSON file');
|
||||
|
||||
const { default: localeData } = await localeFile();
|
||||
|
||||
setLocale({ messages: localeData, locale });
|
||||
});
|
||||
|
||||
@@ -7,17 +7,19 @@ import * as perf from 'mastodon/performance';
|
||||
import ready from 'mastodon/ready';
|
||||
import { store } from 'mastodon/store';
|
||||
|
||||
import { isProduction } from './utils/environment';
|
||||
import { isProduction, isDevelopment } from './utils/environment';
|
||||
|
||||
/**
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
function main() {
|
||||
perf.start('main()');
|
||||
|
||||
return ready(async () => {
|
||||
const mountNode = document.getElementById('mastodon');
|
||||
const props = JSON.parse(mountNode.getAttribute('data-props'));
|
||||
if (!mountNode) {
|
||||
throw new Error('Mount node not found');
|
||||
}
|
||||
const props = JSON.parse(
|
||||
mountNode.getAttribute('data-props') ?? '{}',
|
||||
) as Record<string, unknown>;
|
||||
|
||||
const root = createRoot(mountNode);
|
||||
root.render(<Mastodon {...props} />);
|
||||
@@ -25,8 +27,10 @@ function main() {
|
||||
|
||||
if (isProduction() && me && 'serviceWorker' in navigator) {
|
||||
const { Workbox } = await import('workbox-window');
|
||||
const wb = new Workbox('/sw.js');
|
||||
/** @type {ServiceWorkerRegistration} */
|
||||
const wb = new Workbox(
|
||||
isDevelopment() ? '/packs-dev/dev-sw.js?dev-sw' : '/sw.js',
|
||||
{ type: 'module', scope: '/' },
|
||||
);
|
||||
let registration;
|
||||
|
||||
try {
|
||||
@@ -35,8 +39,14 @@ function main() {
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
if (registration && 'Notification' in window && Notification.permission === 'granted') {
|
||||
const registerPushNotifications = await import('mastodon/actions/push_notifications');
|
||||
if (
|
||||
registration &&
|
||||
'Notification' in window &&
|
||||
Notification.permission === 'granted'
|
||||
) {
|
||||
const registerPushNotifications = await import(
|
||||
'mastodon/actions/push_notifications'
|
||||
);
|
||||
|
||||
store.dispatch(registerPushNotifications.register());
|
||||
}
|
||||
@@ -46,4 +56,5 @@ function main() {
|
||||
});
|
||||
}
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default main;
|
||||
@@ -1,24 +1,11 @@
|
||||
//
|
||||
// Tools for performance debugging, only enabled in development mode.
|
||||
// Open up Chrome Dev Tools, then Timeline, then User Timing to see output.
|
||||
// Also see config/webpack/loaders/mark.js for the webpack loader marks.
|
||||
|
||||
import * as marky from 'marky';
|
||||
|
||||
import { isDevelopment } from './utils/environment';
|
||||
|
||||
if (isDevelopment()) {
|
||||
if (typeof performance !== 'undefined' && performance.setResourceTimingBufferSize) {
|
||||
// Increase Firefox's performance entry limit; otherwise it's capped to 150.
|
||||
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=1331135
|
||||
performance.setResourceTimingBufferSize(Infinity);
|
||||
}
|
||||
|
||||
// allows us to easily do e.g. ReactPerf.printWasted() while debugging
|
||||
//window.ReactPerf = require('react-addons-perf');
|
||||
//window.ReactPerf.start();
|
||||
}
|
||||
|
||||
export function start(name) {
|
||||
if (isDevelopment()) {
|
||||
marky.mark(name);
|
||||
|
||||
@@ -2,10 +2,13 @@
|
||||
// If there are no polyfills, then this is just Promise.resolve() which means
|
||||
// it will execute in the same tick of the event loop (i.e. near-instant).
|
||||
|
||||
// eslint-disable-next-line import/extensions -- This file is virtual so it thinks it has an extension
|
||||
import 'vite/modulepreload-polyfill';
|
||||
|
||||
import { loadIntlPolyfills } from './intl';
|
||||
|
||||
function importExtraPolyfills() {
|
||||
return import(/* webpackChunkName: "extra_polyfills" */ './extra_polyfills');
|
||||
return import('./extra_polyfills');
|
||||
}
|
||||
|
||||
export function loadPolyfills() {
|
||||
|
||||
@@ -54,11 +54,9 @@ async function loadIntlPluralRulesPolyfills(locale: string) {
|
||||
return;
|
||||
}
|
||||
// Load the polyfill 1st BEFORE loading data
|
||||
await import('@formatjs/intl-pluralrules/polyfill-force');
|
||||
await import(
|
||||
/* webpackChunkName: "i18n-pluralrules-polyfill" */ '@formatjs/intl-pluralrules/polyfill-force'
|
||||
);
|
||||
await import(
|
||||
/* webpackChunkName: "i18n-pluralrules-polyfill-[request]" */ `@formatjs/intl-pluralrules/locale-data/${unsupportedLocale}`
|
||||
`../../../../node_modules/@formatjs/intl-pluralrules/locale-data/${unsupportedLocale}.js`
|
||||
);
|
||||
}
|
||||
|
||||
@@ -70,11 +68,9 @@ async function loadIntlPluralRulesPolyfills(locale: string) {
|
||||
// }
|
||||
// // Load the polyfill 1st BEFORE loading data
|
||||
// await import(
|
||||
// /* webpackChunkName: "i18n-relativetimeformat-polyfill" */
|
||||
// '@formatjs/intl-relativetimeformat/polyfill-force'
|
||||
// );
|
||||
// await import(
|
||||
// /* webpackChunkName: "i18n-relativetimeformat-polyfill-[request]" */
|
||||
// `@formatjs/intl-relativetimeformat/locale-data/${unsupportedLocale}`
|
||||
// );
|
||||
// }
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { ExpirationPlugin } from 'workbox-expiration';
|
||||
import { precacheAndRoute } from 'workbox-precaching';
|
||||
import { registerRoute } from 'workbox-routing';
|
||||
import { CacheFirst } from 'workbox-strategies';
|
||||
|
||||
@@ -15,10 +14,9 @@ function fetchRoot() {
|
||||
return fetch('/', { credentials: 'include', redirect: 'manual' });
|
||||
}
|
||||
|
||||
precacheAndRoute(self.__WB_MANIFEST);
|
||||
|
||||
registerRoute(
|
||||
/locale_.*\.js$/,
|
||||
/intl\/.*\.js$/,
|
||||
new CacheFirst({
|
||||
cacheName: `${CACHE_NAME_PREFIX}locales`,
|
||||
plugins: [
|
||||
@@ -1,41 +0,0 @@
|
||||
/* @preval */
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const { defineMessages } = require('react-intl');
|
||||
|
||||
const messages = defineMessages({
|
||||
mentioned_you: { id: 'notification.mentioned_you', defaultMessage: '{name} mentioned you' },
|
||||
});
|
||||
|
||||
const filtered = {};
|
||||
const filenames = fs.readdirSync(path.resolve(__dirname, '../locales'));
|
||||
|
||||
filenames.forEach(filename => {
|
||||
if (!filename.match(/\.json$/)) return;
|
||||
|
||||
const content = fs.readFileSync(path.resolve(__dirname, `../locales/${filename}`), 'utf-8');
|
||||
const full = JSON.parse(content);
|
||||
const locale = filename.split('.')[0];
|
||||
|
||||
filtered[locale] = {
|
||||
'notification.favourite': full['notification.favourite'] || '',
|
||||
'notification.follow': full['notification.follow'] || '',
|
||||
'notification.follow_request': full['notification.follow_request'] || '',
|
||||
'notification.mention': full[messages.mentioned_you.id] || '',
|
||||
'notification.reblog': full['notification.reblog'] || '',
|
||||
'notification.poll': full['notification.poll'] || '',
|
||||
'notification.status': full['notification.status'] || '',
|
||||
'notification.update': full['notification.update'] || '',
|
||||
'notification.admin.sign_up': full['notification.admin.sign_up'] || '',
|
||||
|
||||
'status.show_more': full['status.show_more'] || '',
|
||||
'status.reblog': full['status.reblog'] || '',
|
||||
'status.favourite': full['status.favourite'] || '',
|
||||
|
||||
'notifications.group': full['notifications.group'] || '',
|
||||
};
|
||||
});
|
||||
|
||||
module.exports = JSON.parse(JSON.stringify(filtered));
|
||||
@@ -1,8 +1,10 @@
|
||||
import { IntlMessageFormat } from 'intl-messageformat';
|
||||
|
||||
import { unescape } from 'lodash';
|
||||
|
||||
import locales from './web_push_locales';
|
||||
// see config/vite/plugins/sw-locales
|
||||
// it needs to be updated when new locale keys are used in this file
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import locales from "virtual:mastodon-sw-locales";
|
||||
|
||||
const MAX_NOTIFICATIONS = 5;
|
||||
const GROUP_TAG = 'tag';
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
export function isDevelopment() {
|
||||
return process.env.NODE_ENV === 'development';
|
||||
if (typeof process !== 'undefined')
|
||||
return process.env.NODE_ENV === 'development';
|
||||
else return import.meta.env.DEV;
|
||||
}
|
||||
|
||||
export function isProduction() {
|
||||
return process.env.NODE_ENV === 'production';
|
||||
if (typeof process !== 'undefined')
|
||||
return process.env.NODE_ENV === 'production';
|
||||
else return import.meta.env.PROD;
|
||||
}
|
||||
|
||||
1
app/javascript/skins/glitch/application.scss
Normal file
1
app/javascript/skins/glitch/application.scss
Normal file
@@ -0,0 +1 @@
|
||||
@use '@/flavours/glitch/styles/application';
|
||||
1
app/javascript/skins/glitch/contrast.scss
Normal file
1
app/javascript/skins/glitch/contrast.scss
Normal file
@@ -0,0 +1 @@
|
||||
@use '@/flavours/glitch/styles/contrast';
|
||||
@@ -1 +0,0 @@
|
||||
@use 'flavours/glitch/styles/contrast';
|
||||
@@ -1 +0,0 @@
|
||||
@use 'flavours/glitch/styles/application';
|
||||
1
app/javascript/skins/glitch/mastodon-light.scss
Normal file
1
app/javascript/skins/glitch/mastodon-light.scss
Normal file
@@ -0,0 +1 @@
|
||||
@use '@/flavours/glitch/styles/mastodon-light';
|
||||
@@ -1 +0,0 @@
|
||||
@use 'flavours/glitch/styles/mastodon-light';
|
||||
1
app/javascript/skins/vanilla/application.scss
Normal file
1
app/javascript/skins/vanilla/application.scss
Normal file
@@ -0,0 +1 @@
|
||||
@use '@/styles/application';
|
||||
1
app/javascript/skins/vanilla/contrast.scss
Normal file
1
app/javascript/skins/vanilla/contrast.scss
Normal file
@@ -0,0 +1 @@
|
||||
@use '@/styles/contrast';
|
||||
@@ -1 +0,0 @@
|
||||
@use 'styles/contrast';
|
||||
@@ -1 +0,0 @@
|
||||
@use 'styles/application';
|
||||
1
app/javascript/skins/vanilla/mastodon-light.scss
Normal file
1
app/javascript/skins/vanilla/mastodon-light.scss
Normal file
@@ -0,0 +1 @@
|
||||
@use '@/styles/mastodon-light';
|
||||
@@ -1 +0,0 @@
|
||||
@use 'styles/mastodon-light';
|
||||
1
app/javascript/skins/vanilla/win95.scss
Normal file
1
app/javascript/skins/vanilla/win95.scss
Normal file
@@ -0,0 +1 @@
|
||||
@use '@/styles/win95';
|
||||
@@ -1 +0,0 @@
|
||||
@use 'styles/win95';
|
||||
@@ -1,4 +1,4 @@
|
||||
@use 'fonts/inter';
|
||||
@use '../fonts/inter';
|
||||
|
||||
body {
|
||||
accent-color: #6364ff;
|
||||
@@ -259,7 +259,7 @@ table + p {
|
||||
.email-header-td {
|
||||
padding: 16px 32px;
|
||||
background-color: #1b001f;
|
||||
background-image: url('../images/mailer-new/common/header-bg-start.png');
|
||||
background-image: url('../../images/mailer-new/common/header-bg-start.png');
|
||||
background-position: left top;
|
||||
background-repeat: repeat;
|
||||
}
|
||||
@@ -426,7 +426,7 @@ table + p {
|
||||
|
||||
// Body content
|
||||
.email-body-td {
|
||||
background-image: url('../images/mailer-new/common/header-bg-end.png');
|
||||
background-image: url('../../images/mailer-new/common/header-bg-end.png');
|
||||
background-position: left top;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
@@ -922,7 +922,7 @@ table + p {
|
||||
// Extra content on light purple background
|
||||
.email-extra-wave {
|
||||
height: 42px;
|
||||
background-image: url('../images/mailer-new/welcome/purple-extra-soft-wave.png');
|
||||
background-image: url('../../images/mailer-new/welcome/purple-extra-soft-wave.png');
|
||||
background-position: bottom center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
@@ -930,7 +930,7 @@ table + p {
|
||||
.email-extra-td {
|
||||
padding: 32px 32px 24px;
|
||||
background-color: #f0f0ff;
|
||||
background-image: url('../images/mailer-new/welcome/purple-extra-soft-spacer.png'); // Using an image to maintain the color even in forced dark modes
|
||||
background-image: url('../../images/mailer-new/welcome/purple-extra-soft-spacer.png'); // Using an image to maintain the color even in forced dark modes
|
||||
|
||||
.email-column-td {
|
||||
padding-top: 8px;
|
||||
@@ -1,6 +1,6 @@
|
||||
@font-face {
|
||||
font-family: Inter;
|
||||
src: url('../fonts/inter/inter-variable-font-slnt-wght.woff2')
|
||||
src: url('../../fonts/inter/inter-variable-font-slnt-wght.woff2')
|
||||
format('woff2-variations');
|
||||
font-weight: 100 900;
|
||||
font-style: normal;
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
font-family: mastodon-font-monospace;
|
||||
src:
|
||||
local('Roboto Mono'),
|
||||
url('~fonts/roboto-mono/robotomono-regular-webfont.woff2') format('woff2'),
|
||||
url('~fonts/roboto-mono/robotomono-regular-webfont.woff') format('woff'),
|
||||
url('~fonts/roboto-mono/robotomono-regular-webfont.ttf') format('truetype'),
|
||||
url('~fonts/roboto-mono/robotomono-regular-webfont.svg#roboto_monoregular')
|
||||
url('@/fonts/roboto-mono/robotomono-regular-webfont.woff2') format('woff2'),
|
||||
url('@/fonts/roboto-mono/robotomono-regular-webfont.woff') format('woff'),
|
||||
url('@/fonts/roboto-mono/robotomono-regular-webfont.ttf') format('truetype'),
|
||||
url('@/fonts/roboto-mono/robotomono-regular-webfont.svg#roboto_monoregular')
|
||||
format('svg');
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
font-family: mastodon-font-sans-serif;
|
||||
src:
|
||||
local('Roboto Italic'),
|
||||
url('~fonts/roboto/roboto-italic-webfont.woff2') format('woff2'),
|
||||
url('~fonts/roboto/roboto-italic-webfont.woff') format('woff'),
|
||||
url('~fonts/roboto/roboto-italic-webfont.ttf') format('truetype'),
|
||||
url('~fonts/roboto/roboto-italic-webfont.svg#roboto-italic-webfont')
|
||||
url('@/fonts/roboto/roboto-italic-webfont.woff2') format('woff2'),
|
||||
url('@/fonts/roboto/roboto-italic-webfont.woff') format('woff'),
|
||||
url('@/fonts/roboto/roboto-italic-webfont.ttf') format('truetype'),
|
||||
url('@/fonts/roboto/roboto-italic-webfont.svg#roboto-italic-webfont')
|
||||
format('svg');
|
||||
font-weight: normal;
|
||||
font-display: swap;
|
||||
@@ -16,10 +16,10 @@
|
||||
font-family: mastodon-font-sans-serif;
|
||||
src:
|
||||
local('Roboto Bold'),
|
||||
url('~fonts/roboto/roboto-bold-webfont.woff2') format('woff2'),
|
||||
url('~fonts/roboto/roboto-bold-webfont.woff') format('woff'),
|
||||
url('~fonts/roboto/roboto-bold-webfont.ttf') format('truetype'),
|
||||
url('~fonts/roboto/roboto-bold-webfont.svg#roboto-bold-webfont')
|
||||
url('@/fonts/roboto/roboto-bold-webfont.woff2') format('woff2'),
|
||||
url('@/fonts/roboto/roboto-bold-webfont.woff') format('woff'),
|
||||
url('@/fonts/roboto/roboto-bold-webfont.ttf') format('truetype'),
|
||||
url('@/fonts/roboto/roboto-bold-webfont.svg#roboto-bold-webfont')
|
||||
format('svg');
|
||||
font-weight: bold;
|
||||
font-display: swap;
|
||||
@@ -30,10 +30,10 @@
|
||||
font-family: mastodon-font-sans-serif;
|
||||
src:
|
||||
local('Roboto Medium'),
|
||||
url('~fonts/roboto/roboto-medium-webfont.woff2') format('woff2'),
|
||||
url('~fonts/roboto/roboto-medium-webfont.woff') format('woff'),
|
||||
url('~fonts/roboto/roboto-medium-webfont.ttf') format('truetype'),
|
||||
url('~fonts/roboto/roboto-medium-webfont.svg#roboto-medium-webfont')
|
||||
url('@/fonts/roboto/roboto-medium-webfont.woff2') format('woff2'),
|
||||
url('@/fonts/roboto/roboto-medium-webfont.woff') format('woff'),
|
||||
url('@/fonts/roboto/roboto-medium-webfont.ttf') format('truetype'),
|
||||
url('@/fonts/roboto/roboto-medium-webfont.svg#roboto-medium-webfont')
|
||||
format('svg');
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
@@ -44,10 +44,10 @@
|
||||
font-family: mastodon-font-sans-serif;
|
||||
src:
|
||||
local('Roboto'),
|
||||
url('~fonts/roboto/roboto-regular-webfont.woff2') format('woff2'),
|
||||
url('~fonts/roboto/roboto-regular-webfont.woff') format('woff'),
|
||||
url('~fonts/roboto/roboto-regular-webfont.ttf') format('truetype'),
|
||||
url('~fonts/roboto/roboto-regular-webfont.svg#roboto-regular-webfont')
|
||||
url('@/fonts/roboto/roboto-regular-webfont.woff2') format('woff2'),
|
||||
url('@/fonts/roboto/roboto-regular-webfont.woff') format('woff'),
|
||||
url('@/fonts/roboto/roboto-regular-webfont.ttf') format('truetype'),
|
||||
url('@/fonts/roboto/roboto-regular-webfont.svg#roboto-regular-webfont')
|
||||
format('svg');
|
||||
font-weight: normal;
|
||||
font-display: swap;
|
||||
|
||||
@@ -1446,8 +1446,8 @@ a.sparkline {
|
||||
inset-inline-start: 10px;
|
||||
border-radius: 4px;
|
||||
background:
|
||||
url('~images/warning-stripes.svg') repeat-y left,
|
||||
url('~images/warning-stripes.svg') repeat-y right,
|
||||
url('@/images/warning-stripes.svg') repeat-y left,
|
||||
url('@/images/warning-stripes.svg') repeat-y right,
|
||||
var(--background-color);
|
||||
}
|
||||
|
||||
|
||||
@@ -641,7 +641,7 @@ body > [data-popper-placement] {
|
||||
align-items: stretch;
|
||||
|
||||
&__border {
|
||||
background: url('~images/warning-stripes.svg') repeat-y;
|
||||
background: url('@/images/warning-stripes.svg') repeat-y;
|
||||
width: 5px;
|
||||
flex: 0 0 auto;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user