mirror of
https://github.com/mastodon/mastodon.git
synced 2026-01-12 16:26:38 +00:00
re-adds SW Locales and PWA plugins from #24981
This commit is contained in:
parent
eae0549178
commit
dc3667f50f
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -75,4 +75,5 @@ docker-compose.override.yml
|
|||
# Ignore local-only rspec configuration
|
||||
.rspec-local
|
||||
|
||||
/.dist
|
||||
# Vite Ruby output
|
||||
/public/vite*
|
||||
|
|
|
|||
|
|
@ -60,6 +60,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
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
/* Placeholder file to have `inert.scss` compiled by Vite
|
||||
This is used by the `wicg-inert` polyfill */
|
||||
|
||||
import '../styles/inert.scss';
|
||||
|
|
@ -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?url';
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
import tesseractCorePath from 'tesseract.js-core/tesseract-core.wasm.js?url';
|
||||
|
||||
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,
|
||||
corePath: tesseractCorePath,
|
||||
workerPath: tesseractWorkerPath.default,
|
||||
corePath: tesseractCorePath.default,
|
||||
langPath: `${assetHost}/ocr/lang-data`,
|
||||
cacheMethod: 'write',
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
82
config/vite/plugin-sw-locales.ts
Normal file
82
config/vite/plugin-sw-locales.ts
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
/* This plugin provides the `virtual:mastodon-sw-locales` import
|
||||
which exports translations for every locales, but only with the
|
||||
keys defined below.
|
||||
This is used by the notifications code in the service-worker, to
|
||||
provide localised texts without having to load all the translations
|
||||
*/
|
||||
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
|
||||
import type { Plugin, ResolvedConfig } from 'vite';
|
||||
|
||||
const KEEP_KEYS = [
|
||||
'notification.favourite',
|
||||
'notification.follow',
|
||||
'notification.follow_request',
|
||||
'notification.mention',
|
||||
'notification.reblog',
|
||||
'notification.poll',
|
||||
'notification.status',
|
||||
'notification.update',
|
||||
'notification.admin.sign_up',
|
||||
'status.show_more',
|
||||
'status.reblog',
|
||||
'status.favourite',
|
||||
'notifications.group',
|
||||
];
|
||||
|
||||
export function MastodonServiceWorkerLocales(): Plugin {
|
||||
const virtualModuleId = 'virtual:mastodon-sw-locales';
|
||||
const resolvedVirtualModuleId = '\0' + virtualModuleId;
|
||||
|
||||
let config: ResolvedConfig;
|
||||
|
||||
return {
|
||||
name: 'mastodon-sw-locales',
|
||||
configResolved(resolvedConfig) {
|
||||
config = resolvedConfig;
|
||||
},
|
||||
resolveId(id) {
|
||||
if (id === virtualModuleId) {
|
||||
return resolvedVirtualModuleId;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
},
|
||||
load(id) {
|
||||
if (id === resolvedVirtualModuleId) {
|
||||
const filteredLocales: Record<string, Record<string, string>> = {};
|
||||
const localesPath = path.resolve(config.root, 'mastodon/locales');
|
||||
|
||||
const filenames = fs.readdirSync(localesPath);
|
||||
|
||||
filenames
|
||||
.filter((filename) => /[a-zA-Z-]+\.json$/.exec(filename))
|
||||
.forEach((filename) => {
|
||||
const content = fs.readFileSync(
|
||||
path.resolve(localesPath, filename),
|
||||
'utf-8',
|
||||
);
|
||||
const full = JSON.parse(content) as Record<string, string>;
|
||||
const locale = filename.split('.')[0];
|
||||
|
||||
if (!locale)
|
||||
throw new Error('Could not parse locale from filename');
|
||||
|
||||
const filteredLocale: Record<string, string> = {};
|
||||
|
||||
Object.entries(full).forEach(([key, value]) => {
|
||||
if (KEEP_KEYS.includes(key)) filteredLocale[key] = value;
|
||||
});
|
||||
|
||||
filteredLocales[locale] = filteredLocale;
|
||||
});
|
||||
|
||||
return `const locales = ${JSON.stringify(filteredLocales)}; \n export default locales;`;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
@ -11,8 +11,8 @@
|
|||
],
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"build:development": "cross-env RAILS_ENV=development NODE_ENV=development ./bin/vite build",
|
||||
"build:production": "cross-env RAILS_ENV=production NODE_ENV=production ./bin/vite build",
|
||||
"build:development": "cross-env RAILS_ENV=development NODE_ENV=development vite build",
|
||||
"build:production": "cross-env RAILS_ENV=production NODE_ENV=production vite build",
|
||||
"fix:js": "eslint . --cache --fix",
|
||||
"fix:css": "stylelint --fix \"**/*.{css,scss}\"",
|
||||
"fix": "yarn fix:js && yarn fix:css",
|
||||
|
|
@ -42,6 +42,7 @@
|
|||
"@formatjs/intl-pluralrules": "^5.4.4",
|
||||
"@gamestdio/websocket": "^0.3.2",
|
||||
"@github/webauthn-json": "^2.1.1",
|
||||
"@optimize-lodash/rollup-plugin": "^5.0.2",
|
||||
"@rails/ujs": "7.1.501",
|
||||
"@react-spring/web": "^9.7.5",
|
||||
"@reduxjs/toolkit": "^2.0.1",
|
||||
|
|
@ -103,6 +104,7 @@
|
|||
"use-debounce": "^10.0.0",
|
||||
"vite": "^6.3.0",
|
||||
"vite-bundle-analyzer": "^0.18.1",
|
||||
"vite-plugin-pwa": "^1.0.0",
|
||||
"wicg-inert": "^3.1.2",
|
||||
"workbox-expiration": "^7.0.0",
|
||||
"workbox-precaching": "^7.0.0",
|
||||
|
|
|
|||
|
|
@ -1,13 +1,16 @@
|
|||
/// <reference types="vitest/config" />
|
||||
|
||||
import path from 'node:path';
|
||||
import fs from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
|
||||
import { optimizeLodashImports } from '@optimize-lodash/rollup-plugin';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import { loadEnv } from 'vite';
|
||||
import { loadEnv, PluginOption } from 'vite';
|
||||
import svgr from 'vite-plugin-svgr';
|
||||
import { analyzer } from 'vite-bundle-analyzer';
|
||||
import RailsPlugin from 'vite-plugin-rails';
|
||||
import { VitePWA } from 'vite-plugin-pwa';
|
||||
|
||||
import {
|
||||
configDefaults,
|
||||
defineConfig,
|
||||
|
|
@ -16,7 +19,7 @@ import {
|
|||
} from 'vitest/config';
|
||||
import postcssPresetEnv from 'postcss-preset-env';
|
||||
|
||||
import { manifestSRI } from './config/vite/plugin-manifest-sri';
|
||||
import { MastodonServiceWorkerLocales } from './config/vite/plugin-sw-locales';
|
||||
|
||||
const jsRoot = path.resolve(__dirname, 'app/javascript');
|
||||
const entrypointRoot = path.resolve(jsRoot, 'entrypoints');
|
||||
|
|
@ -52,6 +55,11 @@ const config: UserConfigFnPromise = async ({ mode }) => {
|
|||
},
|
||||
},
|
||||
server: {
|
||||
headers: {
|
||||
// This is needed in dev environment because we load the worker from `/dev-sw/dev-sw.js`,
|
||||
// but it needs to be scoped to the whole domain
|
||||
'Service-Worker-Allowed': '/',
|
||||
},
|
||||
hmr: {
|
||||
clientPort: parseInt(env.VITE_HMR_PORT ?? '3000'),
|
||||
},
|
||||
|
|
@ -101,7 +109,43 @@ const config: UserConfigFnPromise = async ({ mode }) => {
|
|||
},
|
||||
},
|
||||
},
|
||||
plugins: [RailsPlugin(), react(), svgr(), manifestSRI(), analyzer()],
|
||||
plugins: [
|
||||
RailsPlugin(),
|
||||
react(),
|
||||
MastodonServiceWorkerLocales(),
|
||||
VitePWA({
|
||||
srcDir: 'mastodon/service_worker',
|
||||
filename: 'sw.js',
|
||||
manifest: false,
|
||||
injectRegister: null,
|
||||
injectManifest: {
|
||||
buildPlugins: {
|
||||
vite: [
|
||||
// Provide a virtual import with only the locales used in the ServiceWorker
|
||||
MastodonServiceWorkerLocales(),
|
||||
],
|
||||
},
|
||||
globIgnores: [
|
||||
// Do not preload those files
|
||||
'intl/*.js',
|
||||
'extra_polyfills-*.js',
|
||||
'polyfill-force-*.js',
|
||||
'assets/mailer-*.{js,css}',
|
||||
'**/*tesseract*',
|
||||
],
|
||||
maximumFileSizeToCacheInBytes: 2 * 1_024 * 1_024, // 2 MiB
|
||||
},
|
||||
devOptions: {
|
||||
enabled: true,
|
||||
type: 'module',
|
||||
},
|
||||
}),
|
||||
svgr(),
|
||||
// manifestSRI(),
|
||||
// Old library types need to be converted
|
||||
optimizeLodashImports() as PluginOption,
|
||||
!!process.env.ANALYZE_BUNDLE_SIZE && analyzer({ analyzerMode: 'static' }),
|
||||
],
|
||||
test: {
|
||||
environment: 'jsdom',
|
||||
include: [
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user