From 0a882471f32d087849c76c7fa8ba975d17248faf Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Feb 2022 15:13:44 +0900 Subject: fix: better language settings Fix #8359 Fix #7968 --- packages/client/src/scripts/langmap.ts | 666 +++++++++++++++++++++++++++++++++ 1 file changed, 666 insertions(+) create mode 100644 packages/client/src/scripts/langmap.ts (limited to 'packages/client/src/scripts') diff --git a/packages/client/src/scripts/langmap.ts b/packages/client/src/scripts/langmap.ts new file mode 100644 index 0000000000..25f5b366c8 --- /dev/null +++ b/packages/client/src/scripts/langmap.ts @@ -0,0 +1,666 @@ +// TODO: sharedに置いてバックエンドのと統合したい +export const langmap = { + 'ach': { + nativeName: 'Lwo', + }, + 'ady': { + nativeName: 'Адыгэбзэ', + }, + 'af': { + nativeName: 'Afrikaans', + }, + 'af-NA': { + nativeName: 'Afrikaans (Namibia)', + }, + 'af-ZA': { + nativeName: 'Afrikaans (South Africa)', + }, + 'ak': { + nativeName: 'Tɕɥi', + }, + 'ar': { + nativeName: 'العربية', + }, + 'ar-AR': { + nativeName: 'العربية', + }, + 'ar-MA': { + nativeName: 'العربية', + }, + 'ar-SA': { + nativeName: 'العربية (السعودية)', + }, + 'ay-BO': { + nativeName: 'Aymar aru', + }, + 'az': { + nativeName: 'Azərbaycan dili', + }, + 'az-AZ': { + nativeName: 'Azərbaycan dili', + }, + 'be-BY': { + nativeName: 'Беларуская', + }, + 'bg': { + nativeName: 'Български', + }, + 'bg-BG': { + nativeName: 'Български', + }, + 'bn': { + nativeName: 'বাংলা', + }, + 'bn-IN': { + nativeName: 'বাংলা (ভারত)', + }, + 'bn-BD': { + nativeName: 'বাংলা(বাংলাদেশ)', + }, + 'br': { + nativeName: 'Brezhoneg', + }, + 'bs-BA': { + nativeName: 'Bosanski', + }, + 'ca': { + nativeName: 'Català', + }, + 'ca-ES': { + nativeName: 'Català', + }, + 'cak': { + nativeName: 'Maya Kaqchikel', + }, + 'ck-US': { + nativeName: 'ᏣᎳᎩ (tsalagi)', + }, + 'cs': { + nativeName: 'Čeština', + }, + 'cs-CZ': { + nativeName: 'Čeština', + }, + 'cy': { + nativeName: 'Cymraeg', + }, + 'cy-GB': { + nativeName: 'Cymraeg', + }, + 'da': { + nativeName: 'Dansk', + }, + 'da-DK': { + nativeName: 'Dansk', + }, + 'de': { + nativeName: 'Deutsch', + }, + 'de-AT': { + nativeName: 'Deutsch (Österreich)', + }, + 'de-DE': { + nativeName: 'Deutsch (Deutschland)', + }, + 'de-CH': { + nativeName: 'Deutsch (Schweiz)', + }, + 'dsb': { + nativeName: 'Dolnoserbšćina', + }, + 'el': { + nativeName: 'Ελληνικά', + }, + 'el-GR': { + nativeName: 'Ελληνικά', + }, + 'en': { + nativeName: 'English', + }, + 'en-GB': { + nativeName: 'English (UK)', + }, + 'en-AU': { + nativeName: 'English (Australia)', + }, + 'en-CA': { + nativeName: 'English (Canada)', + }, + 'en-IE': { + nativeName: 'English (Ireland)', + }, + 'en-IN': { + nativeName: 'English (India)', + }, + 'en-PI': { + nativeName: 'English (Pirate)', + }, + 'en-SG': { + nativeName: 'English (Singapore)', + }, + 'en-UD': { + nativeName: 'English (Upside Down)', + }, + 'en-US': { + nativeName: 'English (US)', + }, + 'en-ZA': { + nativeName: 'English (South Africa)', + }, + 'en@pirate': { + nativeName: 'English (Pirate)', + }, + 'eo': { + nativeName: 'Esperanto', + }, + 'eo-EO': { + nativeName: 'Esperanto', + }, + 'es': { + nativeName: 'Español', + }, + 'es-AR': { + nativeName: 'Español (Argentine)', + }, + 'es-419': { + nativeName: 'Español (Latinoamérica)', + }, + 'es-CL': { + nativeName: 'Español (Chile)', + }, + 'es-CO': { + nativeName: 'Español (Colombia)', + }, + 'es-EC': { + nativeName: 'Español (Ecuador)', + }, + 'es-ES': { + nativeName: 'Español (España)', + }, + 'es-LA': { + nativeName: 'Español (Latinoamérica)', + }, + 'es-NI': { + nativeName: 'Español (Nicaragua)', + }, + 'es-MX': { + nativeName: 'Español (México)', + }, + 'es-US': { + nativeName: 'Español (Estados Unidos)', + }, + 'es-VE': { + nativeName: 'Español (Venezuela)', + }, + 'et': { + nativeName: 'eesti keel', + }, + 'et-EE': { + nativeName: 'Eesti (Estonia)', + }, + 'eu': { + nativeName: 'Euskara', + }, + 'eu-ES': { + nativeName: 'Euskara', + }, + 'fa': { + nativeName: 'فارسی', + }, + 'fa-IR': { + nativeName: 'فارسی', + }, + 'fb-LT': { + nativeName: 'Leet Speak', + }, + 'ff': { + nativeName: 'Fulah', + }, + 'fi': { + nativeName: 'Suomi', + }, + 'fi-FI': { + nativeName: 'Suomi', + }, + 'fo': { + nativeName: 'Føroyskt', + }, + 'fo-FO': { + nativeName: 'Føroyskt (Færeyjar)', + }, + 'fr': { + nativeName: 'Français', + }, + 'fr-CA': { + nativeName: 'Français (Canada)', + }, + 'fr-FR': { + nativeName: 'Français (France)', + }, + 'fr-BE': { + nativeName: 'Français (Belgique)', + }, + 'fr-CH': { + nativeName: 'Français (Suisse)', + }, + 'fy-NL': { + nativeName: 'Frysk', + }, + 'ga': { + nativeName: 'Gaeilge', + }, + 'ga-IE': { + nativeName: 'Gaeilge', + }, + 'gd': { + nativeName: 'Gàidhlig', + }, + 'gl': { + nativeName: 'Galego', + }, + 'gl-ES': { + nativeName: 'Galego', + }, + 'gn-PY': { + nativeName: 'Avañe\'ẽ', + }, + 'gu-IN': { + nativeName: 'ગુજરાતી', + }, + 'gv': { + nativeName: 'Gaelg', + }, + 'gx-GR': { + nativeName: 'Ἑλληνική ἀρχαία', + }, + 'he': { + nativeName: 'עברית‏', + }, + 'he-IL': { + nativeName: 'עברית‏', + }, + 'hi': { + nativeName: 'हिन्दी', + }, + 'hi-IN': { + nativeName: 'हिन्दी', + }, + 'hr': { + nativeName: 'Hrvatski', + }, + 'hr-HR': { + nativeName: 'Hrvatski', + }, + 'hsb': { + nativeName: 'Hornjoserbšćina', + }, + 'ht': { + nativeName: 'Kreyòl', + }, + 'hu': { + nativeName: 'Magyar', + }, + 'hu-HU': { + nativeName: 'Magyar', + }, + 'hy': { + nativeName: 'Հայերեն', + }, + 'hy-AM': { + nativeName: 'Հայերեն (Հայաստան)', + }, + 'id': { + nativeName: 'Bahasa Indonesia', + }, + 'id-ID': { + nativeName: 'Bahasa Indonesia', + }, + 'is': { + nativeName: 'Íslenska', + }, + 'is-IS': { + nativeName: 'Íslenska (Iceland)', + }, + 'it': { + nativeName: 'Italiano', + }, + 'it-IT': { + nativeName: 'Italiano', + }, + 'ja': { + nativeName: '日本語', + }, + 'ja-JP': { + nativeName: '日本語 (日本)', + }, + 'jv-ID': { + nativeName: 'Basa Jawa', + }, + 'ka-GE': { + nativeName: 'ქართული', + }, + 'kk-KZ': { + nativeName: 'Қазақша', + }, + 'km': { + nativeName: 'ភាសាខ្មែរ', + }, + 'kl': { + nativeName: 'kalaallisut', + }, + 'km-KH': { + nativeName: 'ភាសាខ្មែរ', + }, + 'kab': { + nativeName: 'Taqbaylit', + }, + 'kn': { + nativeName: 'ಕನ್ನಡ', + }, + 'kn-IN': { + nativeName: 'ಕನ್ನಡ (India)', + }, + 'ko': { + nativeName: '한국어', + }, + 'ko-KR': { + nativeName: '한국어 (한국)', + }, + 'ku-TR': { + nativeName: 'Kurdî', + }, + 'kw': { + nativeName: 'Kernewek', + }, + 'la': { + nativeName: 'Latin', + }, + 'la-VA': { + nativeName: 'Latin', + }, + 'lb': { + nativeName: 'Lëtzebuergesch', + }, + 'li-NL': { + nativeName: 'Lèmbörgs', + }, + 'lt': { + nativeName: 'Lietuvių', + }, + 'lt-LT': { + nativeName: 'Lietuvių', + }, + 'lv': { + nativeName: 'Latviešu', + }, + 'lv-LV': { + nativeName: 'Latviešu', + }, + 'mai': { + nativeName: 'मैथिली, মৈথিলী', + }, + 'mg-MG': { + nativeName: 'Malagasy', + }, + 'mk': { + nativeName: 'Македонски', + }, + 'mk-MK': { + nativeName: 'Македонски (Македонски)', + }, + 'ml': { + nativeName: 'മലയാളം', + }, + 'ml-IN': { + nativeName: 'മലയാളം', + }, + 'mn-MN': { + nativeName: 'Монгол', + }, + 'mr': { + nativeName: 'मराठी', + }, + 'mr-IN': { + nativeName: 'मराठी', + }, + 'ms': { + nativeName: 'Bahasa Melayu', + }, + 'ms-MY': { + nativeName: 'Bahasa Melayu', + }, + 'mt': { + nativeName: 'Malti', + }, + 'mt-MT': { + nativeName: 'Malti', + }, + 'my': { + nativeName: 'ဗမာစကာ', + }, + 'no': { + nativeName: 'Norsk', + }, + 'nb': { + nativeName: 'Norsk (bokmål)', + }, + 'nb-NO': { + nativeName: 'Norsk (bokmål)', + }, + 'ne': { + nativeName: 'नेपाली', + }, + 'ne-NP': { + nativeName: 'नेपाली', + }, + 'nl': { + nativeName: 'Nederlands', + }, + 'nl-BE': { + nativeName: 'Nederlands (België)', + }, + 'nl-NL': { + nativeName: 'Nederlands (Nederland)', + }, + 'nn-NO': { + nativeName: 'Norsk (nynorsk)', + }, + 'oc': { + nativeName: 'Occitan', + }, + 'or-IN': { + nativeName: 'ଓଡ଼ିଆ', + }, + 'pa': { + nativeName: 'ਪੰਜਾਬੀ', + }, + 'pa-IN': { + nativeName: 'ਪੰਜਾਬੀ (ਭਾਰਤ ਨੂੰ)', + }, + 'pl': { + nativeName: 'Polski', + }, + 'pl-PL': { + nativeName: 'Polski', + }, + 'ps-AF': { + nativeName: 'پښتو', + }, + 'pt': { + nativeName: 'Português', + }, + 'pt-BR': { + nativeName: 'Português (Brasil)', + }, + 'pt-PT': { + nativeName: 'Português (Portugal)', + }, + 'qu-PE': { + nativeName: 'Qhichwa', + }, + 'rm-CH': { + nativeName: 'Rumantsch', + }, + 'ro': { + nativeName: 'Română', + }, + 'ro-RO': { + nativeName: 'Română', + }, + 'ru': { + nativeName: 'Русский', + }, + 'ru-RU': { + nativeName: 'Русский', + }, + 'sa-IN': { + nativeName: 'संस्कृतम्', + }, + 'se-NO': { + nativeName: 'Davvisámegiella', + }, + 'sh': { + nativeName: 'српскохрватски', + }, + 'si-LK': { + nativeName: 'සිංහල', + }, + 'sk': { + nativeName: 'Slovenčina', + }, + 'sk-SK': { + nativeName: 'Slovenčina (Slovakia)', + }, + 'sl': { + nativeName: 'Slovenščina', + }, + 'sl-SI': { + nativeName: 'Slovenščina', + }, + 'so-SO': { + nativeName: 'Soomaaliga', + }, + 'sq': { + nativeName: 'Shqip', + }, + 'sq-AL': { + nativeName: 'Shqip', + }, + 'sr': { + nativeName: 'Српски', + }, + 'sr-RS': { + nativeName: 'Српски (Serbia)', + }, + 'su': { + nativeName: 'Basa Sunda', + }, + 'sv': { + nativeName: 'Svenska', + }, + 'sv-SE': { + nativeName: 'Svenska', + }, + 'sw': { + nativeName: 'Kiswahili', + }, + 'sw-KE': { + nativeName: 'Kiswahili', + }, + 'ta': { + nativeName: 'தமிழ்', + }, + 'ta-IN': { + nativeName: 'தமிழ்', + }, + 'te': { + nativeName: 'తెలుగు', + }, + 'te-IN': { + nativeName: 'తెలుగు', + }, + 'tg': { + nativeName: 'забо́ни тоҷикӣ́', + }, + 'tg-TJ': { + nativeName: 'тоҷикӣ', + }, + 'th': { + nativeName: 'ภาษาไทย', + }, + 'th-TH': { + nativeName: 'ภาษาไทย (ประเทศไทย)', + }, + 'fil': { + nativeName: 'Filipino', + }, + 'tlh': { + nativeName: 'tlhIngan-Hol', + }, + 'tr': { + nativeName: 'Türkçe', + }, + 'tr-TR': { + nativeName: 'Türkçe', + }, + 'tt-RU': { + nativeName: 'татарча', + }, + 'uk': { + nativeName: 'Українська', + }, + 'uk-UA': { + nativeName: 'Українська', + }, + 'ur': { + nativeName: 'اردو', + }, + 'ur-PK': { + nativeName: 'اردو', + }, + 'uz': { + nativeName: 'O\'zbek', + }, + 'uz-UZ': { + nativeName: 'O\'zbek', + }, + 'vi': { + nativeName: 'Tiếng Việt', + }, + 'vi-VN': { + nativeName: 'Tiếng Việt', + }, + 'xh-ZA': { + nativeName: 'isiXhosa', + }, + 'yi': { + nativeName: 'ייִדיש', + }, + 'yi-DE': { + nativeName: 'ייִדיש (German)', + }, + 'zh': { + nativeName: '中文', + }, + 'zh-Hans': { + nativeName: '中文简体', + }, + 'zh-Hant': { + nativeName: '中文繁體', + }, + 'zh-CN': { + nativeName: '中文(中国大陆)', + }, + 'zh-HK': { + nativeName: '中文(香港)', + }, + 'zh-SG': { + nativeName: '中文(新加坡)', + }, + 'zh-TW': { + nativeName: '中文(台灣)', + }, + 'zu-ZA': { + nativeName: 'isiZulu', + }, +}; -- cgit v1.2.3-freya From bc9157a03b47cd3123184327c1773e2b71d24941 Mon Sep 17 00:00:00 2001 From: syuilo Date: Tue, 1 Mar 2022 21:38:56 +0900 Subject: :art: --- packages/client/src/scripts/theme.ts | 1 + packages/client/src/themes/d-ice.json5 | 13 +++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 packages/client/src/themes/d-ice.json5 (limited to 'packages/client/src/scripts') diff --git a/packages/client/src/scripts/theme.ts b/packages/client/src/scripts/theme.ts index 2001b135ca..4bc70b27ab 100644 --- a/packages/client/src/scripts/theme.ts +++ b/packages/client/src/scripts/theme.ts @@ -29,6 +29,7 @@ export const builtinThemes = [ require('@/themes/d-future.json5'), require('@/themes/d-botanical.json5'), require('@/themes/d-cherry.json5'), + require('@/themes/d-ice.json5'), require('@/themes/d-pumpkin.json5'), require('@/themes/d-black.json5'), ] as Theme[]; diff --git a/packages/client/src/themes/d-ice.json5 b/packages/client/src/themes/d-ice.json5 new file mode 100644 index 0000000000..179b060dcf --- /dev/null +++ b/packages/client/src/themes/d-ice.json5 @@ -0,0 +1,13 @@ +{ + id: '66e7e5a9-cd43-42cd-837d-12f47841fa34', + + name: 'Mi Ice Dark', + author: 'syuilo', + + base: 'dark', + + props: { + accent: '#47BFE8', + bg: '#212526', + }, +} -- cgit v1.2.3-freya From 0893f36f467e576db914faddb9e7d82b700abe17 Mon Sep 17 00:00:00 2001 From: syuilo Date: Tue, 1 Mar 2022 23:58:28 +0900 Subject: :art: --- packages/client/src/scripts/theme.ts | 1 + packages/client/src/themes/l-coffee.json5 | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 packages/client/src/themes/l-coffee.json5 (limited to 'packages/client/src/scripts') diff --git a/packages/client/src/scripts/theme.ts b/packages/client/src/scripts/theme.ts index 4bc70b27ab..45743d0ffa 100644 --- a/packages/client/src/scripts/theme.ts +++ b/packages/client/src/scripts/theme.ts @@ -17,6 +17,7 @@ export const themeProps = Object.keys(lightTheme.props).filter(key => !key.start export const builtinThemes = [ require('@/themes/l-light.json5'), + require('@/themes/l-coffee.json5'), require('@/themes/l-apricot.json5'), require('@/themes/l-rainy.json5'), require('@/themes/l-vivid.json5'), diff --git a/packages/client/src/themes/l-coffee.json5 b/packages/client/src/themes/l-coffee.json5 new file mode 100644 index 0000000000..fbcd4fa9ef --- /dev/null +++ b/packages/client/src/themes/l-coffee.json5 @@ -0,0 +1,21 @@ +{ + id: '6ed80faa-74f0-42c2-98e4-a64d9e138eab', + + name: 'Mi Coffee Light', + author: 'syuilo', + + base: 'light', + + props: { + accent: '#9f8989', + bg: '#f5f3f3', + fg: '#7f6666', + panel: '#fff', + divider: 'rgba(87, 68, 68, 0.1)', + renote: 'rgb(160, 172, 125)', + link: 'rgb(137, 151, 159)', + mention: '@accent', + mentionMe: 'rgb(170, 149, 98)', + hashtag: '@accent', + }, +} -- cgit v1.2.3-freya From e68278f93e82ba396ea2b1fbe0c7e0231c640421 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 4 Mar 2022 20:23:53 +0900 Subject: feat: 時限ミュート MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #7677 --- CHANGELOG.md | 1 + locales/ja-JP.yml | 6 +++ .../migration/1646387162108-mute-expires-at.js | 13 +++++++ packages/backend/src/models/entities/muting.ts | 7 ++++ packages/backend/src/models/repositories/muting.ts | 1 + packages/backend/src/models/schema/muting.ts | 5 +++ packages/backend/src/queue/index.ts | 5 +++ .../backend/src/queue/processors/db/export-mute.ts | 3 +- .../processors/system/check-expired-mutings.ts | 30 +++++++++++++++ .../backend/src/queue/processors/system/index.ts | 2 + .../src/server/api/endpoints/mute/create.ts | 6 +++ packages/client/src/scripts/get-user-menu.ts | 43 +++++++++++++++++++--- 12 files changed, 116 insertions(+), 6 deletions(-) create mode 100644 packages/backend/migration/1646387162108-mute-expires-at.js create mode 100644 packages/backend/src/queue/processors/system/check-expired-mutings.ts (limited to 'packages/client/src/scripts') diff --git a/CHANGELOG.md b/CHANGELOG.md index 88adeca87b..0c1d49f2e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ You should also include the user name that made the change. ### Improvements - インスタンスデフォルトテーマを設定できるように @syuilo +- ミュートに期限を設定できるように @syuilo - プロフィールの追加情報を最大16まで保存できるように @syuilo - 連合チャートにPub&Subを追加 @syuilo - デフォルトで10秒以上時間がかかるデータベースへのクエリは中断されるように @syuilo diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 90dc14815e..8f48c2940c 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -834,6 +834,12 @@ searchByGoogle: "ググる" instanceDefaultLightTheme: "インスタンスデフォルトのライトテーマ" instanceDefaultDarkTheme: "インスタンスデフォルトのダークテーマ" instanceDefaultThemeDescription: "オブジェクト形式のテーマコードを記入します。" +mutePeriod: "ミュートする期限" +indefinitely: "無期限" +tenMinutes: "10分" +oneHour: "1時間" +oneDay: "1日" +oneWeek: "1週間" _emailUnavailable: used: "既に使用されています" diff --git a/packages/backend/migration/1646387162108-mute-expires-at.js b/packages/backend/migration/1646387162108-mute-expires-at.js new file mode 100644 index 0000000000..c8be8f3c54 --- /dev/null +++ b/packages/backend/migration/1646387162108-mute-expires-at.js @@ -0,0 +1,13 @@ +export class muteExpiresAt1646387162108 { + name = 'muteExpiresAt1646387162108' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "muting" ADD "expiresAt" TIMESTAMP WITH TIME ZONE`); + await queryRunner.query(`CREATE INDEX "IDX_c1fd1c3dfb0627aa36c253fd14" ON "muting" ("expiresAt") `); + } + + async down(queryRunner) { + await queryRunner.query(`DROP INDEX "public"."IDX_c1fd1c3dfb0627aa36c253fd14"`); + await queryRunner.query(`ALTER TABLE "muting" DROP COLUMN "expiresAt"`); + } +} diff --git a/packages/backend/src/models/entities/muting.ts b/packages/backend/src/models/entities/muting.ts index 8cdd2af9d1..b3a7e7a671 100644 --- a/packages/backend/src/models/entities/muting.ts +++ b/packages/backend/src/models/entities/muting.ts @@ -14,6 +14,13 @@ export class Muting { }) public createdAt: Date; + @Index() + @Column('timestamp with time zone', { + nullable: true, + default: null, + }) + public expiresAt: Date | null; + @Index() @Column({ ...id(), diff --git a/packages/backend/src/models/repositories/muting.ts b/packages/backend/src/models/repositories/muting.ts index 6ffecc302a..643e0b68ee 100644 --- a/packages/backend/src/models/repositories/muting.ts +++ b/packages/backend/src/models/repositories/muting.ts @@ -16,6 +16,7 @@ export class MutingRepository extends Repository { return await awaitAll({ id: muting.id, createdAt: muting.createdAt.toISOString(), + expiresAt: muting.expiresAt ? muting.expiresAt.toISOString() : null, muteeId: muting.muteeId, mutee: Users.pack(muting.muteeId, me, { detail: true, diff --git a/packages/backend/src/models/schema/muting.ts b/packages/backend/src/models/schema/muting.ts index d75a4fbfed..3ab99e17e7 100644 --- a/packages/backend/src/models/schema/muting.ts +++ b/packages/backend/src/models/schema/muting.ts @@ -12,6 +12,11 @@ export const packedMutingSchema = { optional: false, nullable: false, format: 'date-time', }, + expiresAt: { + type: 'string', + optional: false, nullable: true, + format: 'date-time', + }, muteeId: { type: 'string', optional: false, nullable: false, diff --git a/packages/backend/src/queue/index.ts b/packages/backend/src/queue/index.ts index 94055e9c5a..1b1c21c4f0 100644 --- a/packages/backend/src/queue/index.ts +++ b/packages/backend/src/queue/index.ts @@ -273,6 +273,11 @@ export default function() { repeat: { cron: '0 0 * * *' }, }); + systemQueue.add('checkExpiredMutings', { + }, { + repeat: { cron: '*/5 * * * *' }, + }); + processSystemQueue(systemQueue); } diff --git a/packages/backend/src/queue/processors/db/export-mute.ts b/packages/backend/src/queue/processors/db/export-mute.ts index 8602e00bff..9fb144abb2 100644 --- a/packages/backend/src/queue/processors/db/export-mute.ts +++ b/packages/backend/src/queue/processors/db/export-mute.ts @@ -7,7 +7,7 @@ import { addFile } from '@/services/drive/add-file.js'; import { format as dateFormat } from 'date-fns'; import { getFullApAccount } from '@/misc/convert-host.js'; import { Users, Mutings } from '@/models/index.js'; -import { MoreThan } from 'typeorm'; +import { IsNull, MoreThan } from 'typeorm'; import { DbUserJobData } from '@/queue/types.js'; const logger = queueLogger.createSubLogger('export-mute'); @@ -40,6 +40,7 @@ export async function exportMute(job: Bull.Job, done: any): Promi const mutes = await Mutings.find({ where: { muterId: user.id, + expiresAt: IsNull(), ...(cursor ? { id: MoreThan(cursor) } : {}), }, take: 100, diff --git a/packages/backend/src/queue/processors/system/check-expired-mutings.ts b/packages/backend/src/queue/processors/system/check-expired-mutings.ts new file mode 100644 index 0000000000..621269e7e1 --- /dev/null +++ b/packages/backend/src/queue/processors/system/check-expired-mutings.ts @@ -0,0 +1,30 @@ +import Bull from 'bull'; +import { In } from 'typeorm'; +import { Mutings } from '@/models/index.js'; +import { queueLogger } from '../../logger.js'; +import { publishUserEvent } from '@/services/stream.js'; + +const logger = queueLogger.createSubLogger('check-expired-mutings'); + +export async function checkExpiredMutings(job: Bull.Job>, done: any): Promise { + logger.info(`Checking expired mutings...`); + + const expired = await Mutings.createQueryBuilder('muting') + .where('muting.expiresAt IS NOT NULL') + .andWhere('muting.expiresAt < :now', { now: new Date() }) + .innerJoinAndSelect('muting.mutee', 'mutee') + .getMany(); + + if (expired.length > 0) { + await Mutings.delete({ + id: In(expired.map(m => m.id)), + }); + + for (const m of expired) { + publishUserEvent(m.muterId, 'unmute', m.mutee!); + } + } + + logger.succ(`All expired mutings checked.`); + done(); +} diff --git a/packages/backend/src/queue/processors/system/index.ts b/packages/backend/src/queue/processors/system/index.ts index dca3249e82..f90f6efafd 100644 --- a/packages/backend/src/queue/processors/system/index.ts +++ b/packages/backend/src/queue/processors/system/index.ts @@ -2,11 +2,13 @@ import Bull from 'bull'; import { tickCharts } from './tick-charts.js'; import { resyncCharts } from './resync-charts.js'; import { cleanCharts } from './clean-charts.js'; +import { checkExpiredMutings } from './check-expired-mutings.js'; const jobs = { tickCharts, resyncCharts, cleanCharts, + checkExpiredMutings, } as Record> | Bull.ProcessPromiseFunction>>; export default function(dbQueue: Bull.Queue>) { diff --git a/packages/backend/src/server/api/endpoints/mute/create.ts b/packages/backend/src/server/api/endpoints/mute/create.ts index 0178aab143..dacee40d01 100644 --- a/packages/backend/src/server/api/endpoints/mute/create.ts +++ b/packages/backend/src/server/api/endpoints/mute/create.ts @@ -38,6 +38,7 @@ export const paramDef = { type: 'object', properties: { userId: { type: 'string', format: 'misskey:id' }, + expiresAt: { type: 'integer', nullable: true }, }, required: ['userId'], } as const; @@ -67,10 +68,15 @@ export default define(meta, paramDef, async (ps, user) => { throw new ApiError(meta.errors.alreadyMuting); } + if (ps.expiresAt && ps.expiresAt <= Date.now()) { + return; + } + // Create mute await Mutings.insert({ id: genId(), createdAt: new Date(), + expiresAt: ps.expiresAt ? new Date(ps.expiresAt) : null, muterId: muter.id, muteeId: mutee.id, } as Muting); diff --git a/packages/client/src/scripts/get-user-menu.ts b/packages/client/src/scripts/get-user-menu.ts index 6d1f25a942..192d14b83e 100644 --- a/packages/client/src/scripts/get-user-menu.ts +++ b/packages/client/src/scripts/get-user-menu.ts @@ -56,11 +56,44 @@ export function getUserMenu(user) { } async function toggleMute() { - os.apiWithDialog(user.isMuted ? 'mute/delete' : 'mute/create', { - userId: user.id - }).then(() => { - user.isMuted = !user.isMuted; - }); + if (user.isMuted) { + os.apiWithDialog('mute/delete', { + userId: user.id, + }).then(() => { + user.isMuted = false; + }); + } else { + const { canceled, result: period } = await os.select({ + title: i18n.ts.mutePeriod, + items: [{ + value: 'indefinitely', text: i18n.ts.indefinitely, + }, { + value: 'tenMinutes', text: i18n.ts.tenMinutes, + }, { + value: 'oneHour', text: i18n.ts.oneHour, + }, { + value: 'oneDay', text: i18n.ts.oneDay, + }, { + value: 'oneWeek', text: i18n.ts.oneWeek, + }], + default: 'indefinitely', + }); + if (canceled) return; + + const expiresAt = period === 'indefinitely' ? null + : period === 'tenMinutes' ? Date.now() + (1000 * 60 * 10) + : period === 'oneHour' ? Date.now() + (1000 * 60 * 60) + : period === 'oneDay' ? Date.now() + (1000 * 60 * 60 * 24) + : period === 'oneWeek' ? Date.now() + (1000 * 60 * 60 * 24 * 7) + : null; + + os.apiWithDialog('mute/create', { + userId: user.id, + expiresAt, + }).then(() => { + user.isMuted = true; + }); + } } async function toggleBlock() { -- cgit v1.2.3-freya From a07037affc38d9f753682dacc4d941838648c74d Mon Sep 17 00:00:00 2001 From: MeiMei <30769358+mei23@users.noreply.github.com> Date: Wed, 9 Mar 2022 22:18:14 +0900 Subject: テーマ選択から重複要素を排除するように (#8385) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/client/src/pages/settings/theme.vue | 4 ++-- packages/client/src/scripts/array.ts | 11 +++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) (limited to 'packages/client/src/scripts') diff --git a/packages/client/src/pages/settings/theme.vue b/packages/client/src/pages/settings/theme.vue index 92a6fee7a4..d134a092b6 100644 --- a/packages/client/src/pages/settings/theme.vue +++ b/packages/client/src/pages/settings/theme.vue @@ -101,7 +101,7 @@ import { ColdDeviceStorage } from '@/store'; import { i18n } from '@/i18n'; import { defaultStore } from '@/store'; import { instance } from '@/instance'; -import { concat } from '@/scripts/array'; +import { concat, uniqueBy } from '@/scripts/array'; import { fetchThemes, getThemes } from '@/theme-store'; import * as symbols from '@/symbols'; @@ -128,7 +128,7 @@ export default defineComponent({ const instanceThemes = []; if (instance.defaultLightTheme != null) instanceThemes.push(JSON5.parse(instance.defaultLightTheme)); if (instance.defaultDarkTheme != null) instanceThemes.push(JSON5.parse(instance.defaultDarkTheme)); - const themes = computed(() => instanceThemes.concat(builtinThemes.concat(installedThemes.value))); + const themes = computed(() => uniqueBy(instanceThemes.concat(builtinThemes.concat(installedThemes.value)), theme => theme.id)); const darkThemes = computed(() => themes.value.filter(t => t.base === 'dark' || t.kind === 'dark')); const lightThemes = computed(() => themes.value.filter(t => t.base === 'light' || t.kind === 'light')); const darkTheme = ColdDeviceStorage.ref('darkTheme'); diff --git a/packages/client/src/scripts/array.ts b/packages/client/src/scripts/array.ts index d63f0475d0..29d027de14 100644 --- a/packages/client/src/scripts/array.ts +++ b/packages/client/src/scripts/array.ts @@ -52,6 +52,17 @@ export function unique(xs: T[]): T[] { return [...new Set(xs)]; } +export function uniqueBy(values: TValue[], keySelector: (value: TValue) => TKey): TValue[] { + const map = new Map(); + + for (const value of values) { + const key = keySelector(value); + if (!map.has(key)) map.set(key, value); + } + + return [...map.values()]; +} + export function sum(xs: number[]): number { return xs.reduce((a, b) => a + b, 0); } -- cgit v1.2.3-freya