From 14a9e1050ba57bcb4cf82b48829accc98c9bd504 Mon Sep 17 00:00:00 2001 From: Kaity A Date: Tue, 24 Oct 2023 21:16:09 +1000 Subject: [PATCH 01/17] feat: allow using wildcards in antenna --- locales/en-US.yml | 2 +- locales/es-ES.yml | 2 +- packages/backend/src/core/AntennaService.ts | 8 ++++++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/locales/en-US.yml b/locales/en-US.yml index ddcf610903..e573a15b09 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -402,7 +402,7 @@ antennaKeywordsDescription: "Separate with spaces for an AND condition or with l notifyAntenna: "Notify about new notes" withFileAntenna: "Only notes with files" enableServiceworker: "Enable Push-Notifications for your Browser" -antennaUsersDescription: "List one username per line" +antennaUsersDescription: "List one username per line. Use \"*@instance.com\" to specify all users of an instance" caseSensitive: "Case sensitive" withReplies: "Include replies" connectedTo: "Following account(s) are connected" diff --git a/locales/es-ES.yml b/locales/es-ES.yml index 82a996efbb..f1193d567a 100644 --- a/locales/es-ES.yml +++ b/locales/es-ES.yml @@ -391,7 +391,7 @@ antennaKeywordsDescription: "Separar con espacios es una declaración AND, separ notifyAntenna: "Notificar nueva nota" withFileAntenna: "Sólo notas con archivos adjuntados" enableServiceworker: "Activar ServiceWorker" -antennaUsersDescription: "Elegir nombres de usuarios separados por una linea nueva" +antennaUsersDescription: "Elegir nombres de usuarios separados por una linea nueva. Utilice \"*@instance.com\" para especificar todos los usuarios de una instancia." caseSensitive: "Distinguir mayúsculas de minúsculas" withReplies: "Incluir respuestas" connectedTo: "Estas cuentas están conectadas" diff --git a/packages/backend/src/core/AntennaService.ts b/packages/backend/src/core/AntennaService.ts index 65be275548..f5db80dedd 100644 --- a/packages/backend/src/core/AntennaService.ts +++ b/packages/backend/src/core/AntennaService.ts @@ -115,13 +115,17 @@ export class AntennaService implements OnApplicationShutdown { const { username, host } = Acct.parse(x); return this.utilityService.getFullApAccount(username, host).toLowerCase(); }); - if (!accts.includes(this.utilityService.getFullApAccount(noteUser.username, noteUser.host).toLowerCase())) return false; + const matchUser = this.utilityService.getFullApAccount(noteUser.username, noteUser.host).toLowerCase(); + const matchWildcard = this.utilityService.getFullApAccount('*', noteUser.host).toLowerCase(); + if (!accts.includes(matchUser) && !accts.includes(matchWildcard)) return false; } else if (antenna.src === 'users_blacklist') { const accts = antenna.users.map(x => { const { username, host } = Acct.parse(x); return this.utilityService.getFullApAccount(username, host).toLowerCase(); }); - if (accts.includes(this.utilityService.getFullApAccount(noteUser.username, noteUser.host).toLowerCase())) return false; + const matchUser = this.utilityService.getFullApAccount(noteUser.username, noteUser.host).toLowerCase(); + const matchWildcard = this.utilityService.getFullApAccount('*', noteUser.host).toLowerCase(); + if (accts.includes(matchUser) || accts.includes(matchWildcard)) return false; } const keywords = antenna.keywords From 25e6409cc91fc7ad733f8c8154aca3d55124c5c1 Mon Sep 17 00:00:00 2001 From: dakkar Date: Wed, 20 Mar 2024 15:38:20 +0000 Subject: [PATCH 02/17] allow overriding all string config values via env - fixes #465 will need end-user documentation! --- packages/backend/src/config.ts | 101 +++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/packages/backend/src/config.ts b/packages/backend/src/config.ts index c99bc7ae03..1e08a0f6a8 100644 --- a/packages/backend/src/config.ts +++ b/packages/backend/src/config.ts @@ -212,6 +212,8 @@ export function loadConfig(): Config { {} as Source, ) as Source; + applyEnvOverrides(config); + const url = tryCreateUrl(config.url); const version = meta.version; const host = url.host; @@ -304,3 +306,102 @@ function convertRedisOptions(options: RedisOptionsSource, host: string): RedisOp db: options.db ?? 0, }; } + +/* + this function allows overriding any string-valued config option with + a sensible-named environment variable + + e.g. `MK_CONFIG_MEILISEARCH_APIKEY` overrides `config.meilisearch.apikey` + + the option's containing object must be present in the config *file*, + so in the example above, `config.meilisearch` must be set to + something in the file, it can't be completely commented out. + + you can also override a single `dbSlave` value, + e.g. `MK_CONFIG_DBSLAVES_1_PASS` sets the password for the 2nd + database replica (the first one would be + `MK_CONFIG_DBSLAVES_0_PASS`); again, `config.dbSlaves` must be set + to an array of the right size already in the file + + values can be read from files, too: setting `MK_DB_PASS_FILE` to + `/some/file` would set the main database password to the contents of + `/some/file` (trimmed of whitespaces) + */ +function applyEnvOverrides(config: Source) { + // these inner functions recurse through the config structure, using + // the given steps, building the env variable name + + function _apply_top(steps: (string | number)[]) { + _apply_inner(config, '', steps); + } + + function _apply_inner(thisConfig: any, name: string, steps: (string | number)[]) { + // are there more steps after this one? recurse + if (steps.length > 1) { + const thisStep = steps.shift(); + if (thisStep === null || thisStep === undefined) return; + + // if a step is not a simple value, iterate through it + if (typeof thisStep === 'object') { + for (const thisOneStep of thisStep) { + _descend(thisConfig, name, thisOneStep, steps); + } + } else { + _descend(thisConfig, name, thisStep, steps); + } + + // the actual override has happened at the bottom of the + // recursion, we're done + return; + } + + // this is the last step, same thing as above + const lastStep = steps[0]; + + if (typeof lastStep === 'object') { + for (const lastOneStep of lastStep) { + _lastBit(thisConfig, name, lastOneStep); + } + } else { + _lastBit(thisConfig, name, lastStep); + } + } + + // this recurses down, bailing out if there's no config to override + function _descend(thisConfig: any, name: string, thisStep: string | number, steps: (string | number)[]) { + name = `${name}${thisStep.toString().toUpperCase()}_`; + thisConfig = thisConfig[thisStep]; + if (!thisConfig) return; + _apply_inner(thisConfig, name, steps); + } + + // this is the bottom of the recursion: look at the environment and + // set the value + function _lastBit(thisConfig: any, name: string, lastStep: string | number) { + name = `${name}${lastStep.toString().toUpperCase()}`; + + const val = process.env[`MK_CONFIG_${name}`]; + if (val != null && val != undefined) { + thisConfig[lastStep] = val; + } + + const file = process.env[`MK_CONFIG_${name}_FILE`]; + if (file) { + thisConfig[lastStep] = fs.readFileSync(file, 'utf-8').trim(); + } + } + + // these are all the settings that can be overridden + + _apply_top([['url', 'port', 'socket', 'chmodSocket', 'disableHsts']]); + _apply_top(['db', ['host', 'port', 'db', 'user', 'pass']]); + _apply_top(['dbSlaves', config.dbSlaves?.keys(), ['host', 'port', 'db', 'user', 'pass']]); + _apply_top([ + ['redis', 'redisForPubsub', 'redisForJobQueue', 'redisForTimelines'], + ['host','port','username','pass','db','prefix'], + ]); + _apply_top(['meilisearch', ['host', 'port', 'apikey', 'ssl', 'index', 'scope']]); + _apply_top([['clusterLimit', 'deliverJobConcurrency', 'inboxJobConcurrency', 'relashionshipJobConcurrency', 'deliverJobPerSec', 'inboxJobPerSec', 'relashionshipJobPerSec', 'deliverJobMaxAttempts', 'inboxJobMaxAttempts']]); + _apply_top([['outgoingAddress', 'outgoingAddressFamily', 'proxy', 'proxySmtp', 'mediaProxy', 'videoThumbnailGenerator']]); + _apply_top([['maxFileSize', 'maxNoteLength', 'pidFile']]); +} From 435cab01c8cf7f29e873eb7d9711dd0ad2ead816 Mon Sep 17 00:00:00 2001 From: dakkar Date: Thu, 21 Mar 2024 10:00:16 +0000 Subject: [PATCH 03/17] deal with (possible, future) non-alnum config keys --- packages/backend/src/config.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/backend/src/config.ts b/packages/backend/src/config.ts index 1e08a0f6a8..8f814e4520 100644 --- a/packages/backend/src/config.ts +++ b/packages/backend/src/config.ts @@ -367,9 +367,13 @@ function applyEnvOverrides(config: Source) { } } + function _step2name(step: string|number): string { + return step.toString().replaceAll(/[^a-z0-9]+/gi,'').toUpperCase(); + } + // this recurses down, bailing out if there's no config to override function _descend(thisConfig: any, name: string, thisStep: string | number, steps: (string | number)[]) { - name = `${name}${thisStep.toString().toUpperCase()}_`; + name = `${name}${_step2name(thisStep)}_`; thisConfig = thisConfig[thisStep]; if (!thisConfig) return; _apply_inner(thisConfig, name, steps); @@ -378,7 +382,7 @@ function applyEnvOverrides(config: Source) { // this is the bottom of the recursion: look at the environment and // set the value function _lastBit(thisConfig: any, name: string, lastStep: string | number) { - name = `${name}${lastStep.toString().toUpperCase()}`; + name = `${name}${_step2name(lastStep)}`; const val = process.env[`MK_CONFIG_${name}`]; if (val != null && val != undefined) { From 74362af828b78d6e8b16cde00996db2afb63a4fe Mon Sep 17 00:00:00 2001 From: dakkar Date: Sat, 23 Mar 2024 12:19:13 +0000 Subject: [PATCH 04/17] allow custom oneko image via themes - fixes #472 after this change, one can set a custom image by: * upload an appropriate image to the drive (some images can be found at https://github.com/vencordcss/onekocord/tree/main/onekoskins), possibly with the "keep original" option set * copy the URL to the image in the drive * create/edit a theme so that it contains (inside `props`): "oneko-image": '"url(https://yourinstance.example.com/files/ee17b385-a084-4e2a-b531-225dfb96cc3c)', with the proper URL That's it! --- packages/frontend/src/components/SkOneko.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/src/components/SkOneko.vue b/packages/frontend/src/components/SkOneko.vue index fbf50067a9..a82258e97e 100644 --- a/packages/frontend/src/components/SkOneko.vue +++ b/packages/frontend/src/components/SkOneko.vue @@ -235,6 +235,6 @@ onMounted(init); pointer-events: none; image-rendering: pixelated; z-index: 2147483647; - background-image: url(/client-assets/oneko.gif); + background-image: var(--oneko-image, url(/client-assets/oneko.gif)); } From 0e8cdb30b719a1cc0d9fc3e9c14eacb54444caeb Mon Sep 17 00:00:00 2001 From: dakkar Date: Sun, 24 Mar 2024 11:12:17 +0000 Subject: [PATCH 05/17] allow setting values not present in the config file replicas and arrays in general, are more complicated :/ --- packages/backend/src/config.ts | 53 +++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/packages/backend/src/config.ts b/packages/backend/src/config.ts index 8f814e4520..8d4c5464a6 100644 --- a/packages/backend/src/config.ts +++ b/packages/backend/src/config.ts @@ -311,17 +311,13 @@ function convertRedisOptions(options: RedisOptionsSource, host: string): RedisOp this function allows overriding any string-valued config option with a sensible-named environment variable - e.g. `MK_CONFIG_MEILISEARCH_APIKEY` overrides `config.meilisearch.apikey` - - the option's containing object must be present in the config *file*, - so in the example above, `config.meilisearch` must be set to - something in the file, it can't be completely commented out. + e.g. `MK_CONFIG_MEILISEARCH_APIKEY` sets `config.meilisearch.apikey` you can also override a single `dbSlave` value, e.g. `MK_CONFIG_DBSLAVES_1_PASS` sets the password for the 2nd database replica (the first one would be - `MK_CONFIG_DBSLAVES_0_PASS`); again, `config.dbSlaves` must be set - to an array of the right size already in the file + `MK_CONFIG_DBSLAVES_0_PASS`); in this case, `config.dbSlaves` must + be set to an array of the right size already in the file values can be read from files, too: setting `MK_DB_PASS_FILE` to `/some/file` would set the main database password to the contents of @@ -332,10 +328,10 @@ function applyEnvOverrides(config: Source) { // the given steps, building the env variable name function _apply_top(steps: (string | number)[]) { - _apply_inner(config, '', steps); + _walk('', [], steps); } - function _apply_inner(thisConfig: any, name: string, steps: (string | number)[]) { + function _walk(name: string, path: (string | number)[], steps: (string | number)[]) { // are there more steps after this one? recurse if (steps.length > 1) { const thisStep = steps.shift(); @@ -344,10 +340,10 @@ function applyEnvOverrides(config: Source) { // if a step is not a simple value, iterate through it if (typeof thisStep === 'object') { for (const thisOneStep of thisStep) { - _descend(thisConfig, name, thisOneStep, steps); + _descend(name, path, thisOneStep, steps); } } else { - _descend(thisConfig, name, thisStep, steps); + _descend(name, path, thisStep, steps); } // the actual override has happened at the bottom of the @@ -360,10 +356,10 @@ function applyEnvOverrides(config: Source) { if (typeof lastStep === 'object') { for (const lastOneStep of lastStep) { - _lastBit(thisConfig, name, lastOneStep); + _lastBit(name, path, lastOneStep); } } else { - _lastBit(thisConfig, name, lastStep); + _lastBit(name, path, lastStep); } } @@ -372,29 +368,40 @@ function applyEnvOverrides(config: Source) { } // this recurses down, bailing out if there's no config to override - function _descend(thisConfig: any, name: string, thisStep: string | number, steps: (string | number)[]) { + function _descend(name: string, path: (string | number)[], thisStep: string | number, steps: (string | number)[]) { name = `${name}${_step2name(thisStep)}_`; - thisConfig = thisConfig[thisStep]; - if (!thisConfig) return; - _apply_inner(thisConfig, name, steps); + path = [ ...path, thisStep ]; + _walk(name, path, steps); } // this is the bottom of the recursion: look at the environment and // set the value - function _lastBit(thisConfig: any, name: string, lastStep: string | number) { - name = `${name}${_step2name(lastStep)}`; + function _lastBit(name: string, path: (string | number)[], lastStep: string | number) { + name = `MK_CONFIG_${name}${_step2name(lastStep)}`; - const val = process.env[`MK_CONFIG_${name}`]; + const val = process.env[name]; if (val != null && val != undefined) { - thisConfig[lastStep] = val; + _assign(path, lastStep, val); } - const file = process.env[`MK_CONFIG_${name}_FILE`]; + const file = process.env[`${name}_FILE`]; if (file) { - thisConfig[lastStep] = fs.readFileSync(file, 'utf-8').trim(); + _assign(path, lastStep, fs.readFileSync(file, 'utf-8').trim()); } } + function _assign(path: (string | number)[], lastStep: string | number, value: string) { + let thisConfig = config; + for (const step of path) { + if (!thisConfig[step]) { + thisConfig[step] = {}; + } + thisConfig = thisConfig[step]; + } + + thisConfig[lastStep] = value; + } + // these are all the settings that can be overridden _apply_top([['url', 'port', 'socket', 'chmodSocket', 'disableHsts']]); From 4271402e0d0e1840791158de288a3e7617227ec4 Mon Sep 17 00:00:00 2001 From: dakkar Date: Sun, 24 Mar 2024 11:17:55 +0000 Subject: [PATCH 06/17] recognise numbers and boolean values --- packages/backend/src/config.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/backend/src/config.ts b/packages/backend/src/config.ts index 8d4c5464a6..f6ce9b3cdf 100644 --- a/packages/backend/src/config.ts +++ b/packages/backend/src/config.ts @@ -390,6 +390,8 @@ function applyEnvOverrides(config: Source) { } } + const alwaysStrings = { 'chmodSocket': 1 }; + function _assign(path: (string | number)[], lastStep: string | number, value: string) { let thisConfig = config; for (const step of path) { @@ -399,6 +401,14 @@ function applyEnvOverrides(config: Source) { thisConfig = thisConfig[step]; } + if (!alwaysStrings[lastStep]) { + if (value.match(/^[0-9]+$/)) { + value = parseInt(value); + } else if (value.match(/^(true|false)$/i)) { + value = !!value.match(/^true$/i); + } + } + thisConfig[lastStep] = value; } From 194d8a5527ed98a2f9679e1381a6d7290f10a1b7 Mon Sep 17 00:00:00 2001 From: Sugar Date: Sat, 11 May 2024 09:44:03 +0200 Subject: [PATCH 07/17] feat: send edit events to servers that interacted a server replied to, renoted or reacted to a note knows about a note, and as such it should get notified about it being edited. this matches similar logic in mastodon. --- packages/backend/src/core/NoteEditService.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/packages/backend/src/core/NoteEditService.ts b/packages/backend/src/core/NoteEditService.ts index a01dfec664..399461dd70 100644 --- a/packages/backend/src/core/NoteEditService.ts +++ b/packages/backend/src/core/NoteEditService.ts @@ -699,6 +699,24 @@ export class NoteEditService implements OnApplicationShutdown { dm.addFollowersRecipe(); } + if (['public', 'home'].includes(note.visibility)) { + // Send edit event to all users who replied to, + // renoted a post or reacted to a note. + const noteId = note.id; + const users = await this.usersRepository.createQueryBuilder() + .where( + 'id IN (SELECT "userId" FROM note WHERE "replyId" = :noteId OR "renoteId" = :noteId UNION SELECT "userId" FROM note_reaction WHERE "noteId" = :noteId)', + { noteId }, + ) + .andWhere('host IS NOT NULL') + .getMany(); + for (const u of users) { + // User was verified to be remote by checking + // whether host IS NOT NULL in SQL query. + dm.addDirectRecipe(u as MiRemoteUser); + } + } + if (['public'].includes(note.visibility)) { this.relayService.deliverToRelays(user, noteActivity); } From eac9f389420b5ae3c18dfe0bf0c5aead8f164655 Mon Sep 17 00:00:00 2001 From: Sebastian Di Luzio Date: Mon, 20 May 2024 11:10:45 +0000 Subject: [PATCH 08/17] fix(i18n): adjust grammar in about_misskey --- locales/en-US.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locales/en-US.yml b/locales/en-US.yml index fe27a131ba..0203d9562d 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -1830,7 +1830,7 @@ _registry: domain: "Domain" createKey: "Create key" _aboutMisskey: - about: "Sharkey is open-source software based on Misskey which has been in developed since 2014 by syuilo." + about: "Sharkey is open-source software based on Misskey which has been in development by syuilo since 2014." contributors: "Main contributors" allContributors: "All contributors" source: "Source code" From 4c4b43124862a4ee564cb8d6dafa44be8c95cb78 Mon Sep 17 00:00:00 2001 From: Leah Date: Thu, 23 May 2024 18:08:31 +0000 Subject: [PATCH 09/17] Ported cutiekeys followmouse mfm --- locales/en-US.yml | 3 + .../frontend/src/components/CkFollowMouse.vue | 81 +++++++++++ .../frontend/src/components/MkMfmWindow.vue | 134 ++++++++++-------- .../global/MkMisskeyFlavoredMarkdown.ts | 23 +++ packages/frontend/src/const.ts | 5 +- 5 files changed, 184 insertions(+), 62 deletions(-) create mode 100644 packages/frontend/src/components/CkFollowMouse.vue diff --git a/locales/en-US.yml b/locales/en-US.yml index fe27a131ba..07173c131e 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -2478,6 +2478,7 @@ _moderationLogTypes: unsetUserAvatar: "Unset this user's avatar" unsetUserBanner: "Unset this user's banner" _mfm: + uncommonFeature: "This is not a widespread feature, it may not display properly on most other fedi software, including other Misskey forks" intro: "MFM is a markup language used on Misskey, Sharkey, Firefish, Akkoma, and more that can be used in many places. Here you can view a list of all available MFM syntax." dummy: "Sharkey expands the world of the Fediverse" mention: "Mention" @@ -2542,6 +2543,8 @@ _mfm: rotateDescription: "Turns content by a specified angle." position: "Position" positionDescription: "Move content by a specified amount." + followMouse: "Follow Mouse" + followMouseDescription: "Content will follow the mouse. On mobile it will follow wherever the user taps." scale: "Scale" scaleDescription: "Scale content by a specified amount." foreground: "Foreground color" diff --git a/packages/frontend/src/components/CkFollowMouse.vue b/packages/frontend/src/components/CkFollowMouse.vue new file mode 100644 index 0000000000..b55a577b3f --- /dev/null +++ b/packages/frontend/src/components/CkFollowMouse.vue @@ -0,0 +1,81 @@ + + + + + diff --git a/packages/frontend/src/components/MkMfmWindow.vue b/packages/frontend/src/components/MkMfmWindow.vue index ce2a0e7391..fd23eb0097 100644 --- a/packages/frontend/src/components/MkMfmWindow.vue +++ b/packages/frontend/src/components/MkMfmWindow.vue @@ -9,17 +9,17 @@ - +
{{ i18n.ts._mfm.intro }}
-
+
{{ i18n.ts._mfm.mention }}

{{ i18n.ts._mfm.mentionDescription }}

- +
@@ -29,7 +29,7 @@

{{ i18n.ts._mfm.hashtagDescription }}

- +
@@ -39,7 +39,7 @@

{{ i18n.ts._mfm.linkDescription }}

- +
@@ -49,7 +49,7 @@

{{ i18n.ts._mfm.emojiDescription }}

- +
@@ -59,7 +59,7 @@

{{ i18n.ts._mfm.boldDescription }}

- +
@@ -69,7 +69,7 @@

{{ i18n.ts._mfm.smallDescription }}

- +
@@ -79,7 +79,7 @@

{{ i18n.ts._mfm.quoteDescription }}

- +
@@ -89,7 +89,7 @@

{{ i18n.ts._mfm.centerDescription }}

- +
@@ -99,7 +99,7 @@

{{ i18n.ts._mfm.inlineCodeDescription }}

- +
@@ -109,7 +109,7 @@

{{ i18n.ts._mfm.blockCodeDescription }}

- +
@@ -119,7 +119,7 @@

{{ i18n.ts._mfm.inlineMathDescription }}

- +
@@ -129,7 +129,7 @@

{{ i18n.ts._mfm.blockMathDescription }}

- +
@@ -139,7 +139,7 @@

{{ i18n.ts._mfm.searchDescription }}

- +
@@ -149,7 +149,7 @@

{{ i18n.ts._mfm.flipDescription }}

- +
@@ -159,7 +159,7 @@

{{ i18n.ts._mfm.fontDescription }}

- +
@@ -169,7 +169,7 @@

{{ i18n.ts._mfm.x2Description }}

- +
@@ -179,7 +179,7 @@

{{ i18n.ts._mfm.x3Description }}

- +
@@ -189,7 +189,7 @@

{{ i18n.ts._mfm.x4Description }}

- +
@@ -199,7 +199,7 @@

{{ i18n.ts._mfm.blurDescription }}

- +
@@ -209,7 +209,7 @@

{{ i18n.ts._mfm.jellyDescription }}

- +
@@ -219,7 +219,7 @@

{{ i18n.ts._mfm.tadaDescription }}

- +
@@ -229,7 +229,7 @@

{{ i18n.ts._mfm.jumpDescription }}

- +
@@ -239,7 +239,7 @@

{{ i18n.ts._mfm.bounceDescription }}

- +
@@ -249,7 +249,7 @@

{{ i18n.ts._mfm.spinDescription }}

- +
@@ -259,7 +259,7 @@

{{ i18n.ts._mfm.shakeDescription }}

- +
@@ -269,7 +269,7 @@

{{ i18n.ts._mfm.twitchDescription }}

- +
@@ -279,7 +279,7 @@

{{ i18n.ts._mfm.rainbowDescription }}

- +
@@ -289,7 +289,7 @@

{{ i18n.ts._mfm.sparkleDescription }}

- + MFM
@@ -299,7 +299,7 @@

{{ i18n.ts._mfm.rotateDescription }}

- + MFM
@@ -309,17 +309,29 @@

{{ i18n.ts._mfm.positionDescription }}

- + MFM
+
+
{{ i18n.ts._mfm.followMouse }}
+ {{ i18n.ts._mfm.uncommonFeature }} +
+
+

{{ i18n.ts._mfm.followMouseDescription }}

+
+ + MFM +
+
+
{{ i18n.ts._mfm.scale }}

{{ i18n.ts._mfm.scaleDescription }}

- + MFM
@@ -329,7 +341,7 @@

{{ i18n.ts._mfm.foregroundDescription }}

- + MFM
@@ -339,7 +351,7 @@

{{ i18n.ts._mfm.backgroundDescription }}

- + MFM
@@ -349,7 +361,7 @@

{{ i18n.ts._mfm.plainDescription }}

- + MFM
@@ -362,18 +374,19 @@ diff --git a/packages/frontend/src/components/global/MkMisskeyFlavoredMarkdown.ts b/packages/frontend/src/components/global/MkMisskeyFlavoredMarkdown.ts index f8b5fcfedc..2f699ccd84 100644 --- a/packages/frontend/src/components/global/MkMisskeyFlavoredMarkdown.ts +++ b/packages/frontend/src/components/global/MkMisskeyFlavoredMarkdown.ts @@ -6,6 +6,7 @@ import { VNode, h, defineAsyncComponent, SetupContext } from 'vue'; import * as mfm from '@transfem-org/sfm-js'; import * as Misskey from 'misskey-js'; +import CkFollowMouse from '../CkFollowMouse.vue'; import MkUrl from '@/components/global/MkUrl.vue'; import MkTime from '@/components/global/MkTime.vue'; import MkLink from '@/components/MkLink.vue'; @@ -232,6 +233,28 @@ export default function (props: MfmProps, { emit }: { emit: SetupContext = { tada: ['speed=', 'delay='], jelly: ['speed=', 'delay='], @@ -179,11 +179,12 @@ export const MFM_PARAMS: Record = { position: ['x=', 'y='], fg: ['color='], bg: ['color='], - border: ['width=', 'style=', 'color=', 'radius=', 'noclip'], + border: ['width=', 'style=', 'color=', 'radius=', 'noclip'], font: ['serif', 'monospace', 'cursive', 'fantasy', 'emoji', 'math'], blur: [], rainbow: ['speed=', 'delay='], rotate: ['deg='], ruby: [], unixtime: [], + followmouse: ['x', 'y', 'rotateByVelocity', 'speed='], }; From f9a7cd0daa869b23b100f6d32e71f0faaa7873fc Mon Sep 17 00:00:00 2001 From: Leah Date: Thu, 23 May 2024 21:40:25 +0000 Subject: [PATCH 10/17] Ported firefish crop and fade mfm --- locales/en-US.yml | 4 +++ .../frontend/src/components/MkMfmWindow.vue | 26 ++++++++++++++- .../global/MkMisskeyFlavoredMarkdown.ts | 32 +++++++++++++++++++ packages/frontend/src/const.ts | 4 ++- packages/frontend/src/style.scss | 9 ++++++ 5 files changed, 73 insertions(+), 2 deletions(-) diff --git a/locales/en-US.yml b/locales/en-US.yml index 07173c131e..c442d41c1e 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -2543,12 +2543,16 @@ _mfm: rotateDescription: "Turns content by a specified angle." position: "Position" positionDescription: "Move content by a specified amount." + crop: "Crop" + cropDescription: "Crop content." followMouse: "Follow Mouse" followMouseDescription: "Content will follow the mouse. On mobile it will follow wherever the user taps." scale: "Scale" scaleDescription: "Scale content by a specified amount." foreground: "Foreground color" foregroundDescription: "Change the foreground color of text." + fade: 'Fade' + fadeDescription: 'Fade text in and out.' background: "Background color" backgroundDescription: "Change the background color of text." plain: "Plain" diff --git a/packages/frontend/src/components/MkMfmWindow.vue b/packages/frontend/src/components/MkMfmWindow.vue index fd23eb0097..a742ad184c 100644 --- a/packages/frontend/src/components/MkMfmWindow.vue +++ b/packages/frontend/src/components/MkMfmWindow.vue @@ -304,6 +304,16 @@
+
+
{{ i18n.ts._mfm.crop }}
+
+

{{ i18n.ts._mfm.cropDescription }}

+
+ + MFM +
+
+
{{ i18n.ts._mfm.position }}
@@ -316,7 +326,7 @@
{{ i18n.ts._mfm.followMouse }}
- {{ i18n.ts._mfm.uncommonFeature }} + {{ i18n.ts._mfm.uncommonFeature }}

{{ i18n.ts._mfm.followMouseDescription }}

@@ -336,6 +346,16 @@
+
+
{{ i18n.ts._mfm.fade }}
+
+

{{ i18n.ts._mfm.fadeDescription }}

+
+ + MFM +
+
+
{{ i18n.ts._mfm.foreground }}
@@ -445,6 +465,9 @@ const preview_rotate = ref( '$[rotate 🍮]\n$[rotate.deg=45 🍮]\n$[rotate.x,deg=45 Hello, world!]', ); const preview_position = ref('$[position.y=-1 🍮]\n$[position.x=-1 🍮]'); +const preview_crop = ref( + "$[crop.top=50 🍮] $[crop.right=50 🍮] $[crop.bottom=50 🍮] $[crop.left=50 🍮]", +); const preview_followmouse = ref('$[followmouse.x 🍮]\n$[followmouse.x,y,rotateByVelocity,speed=0.4 🍮]'); const preview_scale = ref( '$[scale.x=1.3 🍮]\n$[scale.x=1.5,y=3 🍮]\n$[scale.y=0.3 🍮]', @@ -454,6 +477,7 @@ const preview_bg = ref('$[bg.color=31748f Background color]'); const preview_plain = ref( '**bold** @mention #hashtag `code` $[x2 🍮]', ); +const preview_fade = ref(`$[fade 🍮] $[fade.out 🍮] $[fade.speed=3s 🍮] $[fade.delay=3s 🍮]`);