diff options
| author | Hazel K <acomputerdog@gmail.com> | 2024-10-06 12:26:25 -0400 |
|---|---|---|
| committer | Hazel K <acomputerdog@gmail.com> | 2024-10-06 12:26:25 -0400 |
| commit | 047563bdde95c528da5c136bf98935a06840f47e (patch) | |
| tree | 154c9d666a13cfcd3b626a65942d3dc8f84b5aec | |
| parent | fix modlog and translations for "Mark as NSFW" (diff) | |
| parent | merge: Warn when a domain is implicitly blocked because a base domain is bloc... (diff) | |
| download | sharkey-047563bdde95c528da5c136bf98935a06840f47e.tar.gz sharkey-047563bdde95c528da5c136bf98935a06840f47e.tar.bz2 sharkey-047563bdde95c528da5c136bf98935a06840f47e.zip | |
Merge branch 'develop' into hazelnoot/579-reject-reports
# Conflicts:
# packages/frontend/src/pages/instance-info.vue
19 files changed, 121 insertions, 41 deletions
diff --git a/locales/en-US.yml b/locales/en-US.yml index dfd236b9c5..5cfeceb442 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -143,8 +143,10 @@ markAsSensitive: "Mark as sensitive" unmarkAsSensitive: "Unmark as sensitive" enterFileName: "Enter filename" mute: "Mute" +muted: "Muted" unmute: "Unmute" renoteMute: "Mute Boosts" +renoteMuted: "Boosts muted" renoteUnmute: "Unmute Boosts" block: "Block" unblock: "Unblock" @@ -265,6 +267,9 @@ noCustomEmojis: "There are no emoji" noJobs: "There are no jobs" federating: "Federating" blocked: "Blocked" +blockedByBase: "This host is blocked implicitly because a base domain is blocked. To unblock this host, first unblock the base domain(s)." +silencedByBase: "This host is silenced implicitly because a base domain is silenced. To un-silence this host, first un-silence the base domain(s)." +mediaSilencedByBase: "This host's media is silenced implicitly because a base domain's media is silenced. To un-silence this host, first un-silence the base domain(s)." suspended: "Suspended" all: "All" subscribing: "Subscribing" diff --git a/locales/index.d.ts b/locales/index.d.ts index fb8d9339fc..b3699e2a9c 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -589,6 +589,10 @@ export interface Locale extends ILocale { */ "mute": string; /** + * Muted + */ + "muted": string; + /** * ミュート解除 */ "unmute": string; @@ -597,6 +601,10 @@ export interface Locale extends ILocale { */ "renoteMute": string; /** + * Boosts muted + */ + "renoteMuted": string; + /** * ブーストのミュートを解除 */ "renoteUnmute": string; @@ -1077,6 +1085,18 @@ export interface Locale extends ILocale { */ "blocked": string; /** + * This host is blocked implicitly because a base domain is blocked. To unblock this host, first unblock the base domain(s). + */ + "blockedByBase": string; + /** + * This host is silenced implicitly because a base domain is silenced. To un-silence this host, first un-silence the base domain(s). + */ + "silencedByBase": string; + /** + * This host's media is silenced implicitly because a base domain's media is silenced. To un-silence this host, first un-silence the base domain(s). + */ + "mediaSilencedByBase": string; + /** * 配信停止 */ "suspended": string; @@ -4442,10 +4462,6 @@ export interface Locale extends ILocale { */ "disableFederationOk": string; /** - * 猫の話し方を無効にする - */ - "disableCatSpeak": string; - /** * 現在このサーバーは招待制です。招待コードをお持ちの方のみ登録できます。 */ "invitationRequiredToRegister": string; @@ -5789,7 +5805,7 @@ export interface Locale extends ILocale { */ "social": string; /** - * バッッブルタイムラインでは、管理者が選択した接続サーバーからのメモを表示できます。 + * バブルタイムラインでは、管理者が選択した接続サーバーからの投稿を表示できます。 */ "bubble": string; /** @@ -9151,7 +9167,7 @@ export interface Locale extends ILocale { */ "global": string; /** - * バッッブル + * バブル */ "bubble": string; }; diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index d86b7a73d1..e115640a6a 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -143,8 +143,10 @@ markAsSensitive: "センシティブとして設定" unmarkAsSensitive: "センシティブを解除する" enterFileName: "ファイル名を入力" mute: "ミュート" +muted: "Muted" unmute: "ミュート解除" renoteMute: "ブーストをミュート" +renoteMuted: "Boosts muted" renoteUnmute: "ブーストのミュートを解除" block: "ブロック" unblock: "ブロック解除" @@ -265,6 +267,9 @@ noCustomEmojis: "絵文字はありません" noJobs: "ジョブはありません" federating: "連合中" blocked: "ブロック中" +blockedByBase: "This host is blocked implicitly because a base domain is blocked. To unblock this host, first unblock the base domain(s)." +silencedByBase: "This host is silenced implicitly because a base domain is silenced. To un-silence this host, first un-silence the base domain(s)." +mediaSilencedByBase: "This host's media is silenced implicitly because a base domain's media is silenced. To un-silence this host, first un-silence the base domain(s)." suspended: "配信停止" all: "全て" subscribing: "購読中" diff --git a/packages/backend/src/core/activitypub/ApRendererService.ts b/packages/backend/src/core/activitypub/ApRendererService.ts index 55d1054de9..499a163d6c 100644 --- a/packages/backend/src/core/activitypub/ApRendererService.ts +++ b/packages/backend/src/core/activitypub/ApRendererService.ts @@ -526,6 +526,7 @@ export class ApRendererService { publicKey: this.renderKey(user, keypair, '#main-key'), isCat: user.isCat, noindex: user.noindex, + indexable: !user.noindex, speakAsCat: user.speakAsCat, attachment: attachment.length ? attachment : undefined, }; diff --git a/packages/backend/src/core/activitypub/misc/contexts.ts b/packages/backend/src/core/activitypub/misc/contexts.ts index 815b20b910..86a665732a 100644 --- a/packages/backend/src/core/activitypub/misc/contexts.ts +++ b/packages/backend/src/core/activitypub/misc/contexts.ts @@ -545,6 +545,7 @@ const extension_context_definition = { Emoji: 'toot:Emoji', featured: 'toot:featured', discoverable: 'toot:discoverable', + indexable: 'toot:indexable', // schema schema: 'http://schema.org#', PropertyValue: 'schema:PropertyValue', diff --git a/packages/backend/src/core/activitypub/models/ApNoteService.ts b/packages/backend/src/core/activitypub/models/ApNoteService.ts index 7b7a7921fb..382cda301f 100644 --- a/packages/backend/src/core/activitypub/models/ApNoteService.ts +++ b/packages/backend/src/core/activitypub/models/ApNoteService.ts @@ -587,7 +587,7 @@ export class ApNoteService { // ここでuriの代わりに添付されてきたNote Objectが指定されていると、サーバーフェッチを経ずにノートが生成されるが // 添付されてきたNote Objectは偽装されている可能性があるため、常にuriを指定してサーバーフェッチを行う。 const createFrom = options.sentFrom?.origin === new URL(uri).origin ? value : uri; - return await this.createNote(createFrom, options.resolver, true); + return await this.createNote(createFrom, options.resolver, false); } finally { unlock(); } diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts index 5a69fbf679..dbfa31024a 100644 --- a/packages/backend/src/server/api/endpoints/admin/meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/meta.ts @@ -128,7 +128,7 @@ export const meta = { }, silencedHosts: { type: 'array', - optional: true, + optional: false, nullable: false, items: { type: 'string', diff --git a/packages/backend/src/server/web/ClientServerService.ts b/packages/backend/src/server/web/ClientServerService.ts index 0af90a844b..e20707977f 100644 --- a/packages/backend/src/server/web/ClientServerService.ts +++ b/packages/backend/src/server/web/ClientServerService.ts @@ -193,9 +193,9 @@ export class ClientServerService { icon: meta.iconUrl, appleTouchIcon: meta.app512IconUrl, themeColor: meta.themeColor, - serverErrorImageUrl: meta.serverErrorImageUrl ?? 'https://launcher.moe/error.png', - infoImageUrl: meta.infoImageUrl ?? 'https://launcher.moe/nothinghere.png', - notFoundImageUrl: meta.notFoundImageUrl ?? 'https://launcher.moe/missingpage.webp', + serverErrorImageUrl: meta.serverErrorImageUrl ?? '/status/error.png', + infoImageUrl: meta.infoImageUrl ?? '/status/nothinghere.png', + notFoundImageUrl: meta.notFoundImageUrl ?? '/status/missingpage.webp', instanceUrl: this.config.url, randomMOTD: this.config.customMOTD ? this.config.customMOTD[Math.floor(Math.random() * this.config.customMOTD.length)] : undefined, metaJson: htmlSafeJsonStringify(await this.metaEntityService.packDetailed(meta)), diff --git a/packages/frontend/assets/status/error.png b/packages/frontend/assets/status/error.png Binary files differnew file mode 100644 index 0000000000..9f21236c39 --- /dev/null +++ b/packages/frontend/assets/status/error.png diff --git a/packages/frontend/assets/status/missingpage.webp b/packages/frontend/assets/status/missingpage.webp Binary files differnew file mode 100644 index 0000000000..3ac83b3110 --- /dev/null +++ b/packages/frontend/assets/status/missingpage.webp diff --git a/packages/frontend/assets/status/nothinghere.png b/packages/frontend/assets/status/nothinghere.png Binary files differnew file mode 100644 index 0000000000..5ebe210acd --- /dev/null +++ b/packages/frontend/assets/status/nothinghere.png diff --git a/packages/frontend/src/boot/main-boot.ts b/packages/frontend/src/boot/main-boot.ts index c10930a038..5ff998fac4 100644 --- a/packages/frontend/src/boot/main-boot.ts +++ b/packages/frontend/src/boot/main-boot.ts @@ -216,19 +216,25 @@ export async function mainBoot() { claimAchievement('collectAchievements30'); } - window.setInterval(() => { - if (Math.floor(Math.random() * 20000) === 0) { - claimAchievement('justPlainLucky'); - } - }, 1000 * 10); + if (!claimedAchievements.includes('justPlainLucky')) { + window.setInterval(() => { + if (Math.floor(Math.random() * 20000) === 0) { + claimAchievement('justPlainLucky'); + } + }, 1000 * 10); + } - window.setTimeout(() => { - claimAchievement('client30min'); - }, 1000 * 60 * 30); + if (!claimedAchievements.includes('client30min')) { + window.setTimeout(() => { + claimAchievement('client30min'); + }, 1000 * 60 * 30); + } - window.setTimeout(() => { - claimAchievement('client60min'); - }, 1000 * 60 * 60); + if (!claimedAchievements.includes('client60min')) { + window.setTimeout(() => { + claimAchievement('client60min'); + }, 1000 * 60 * 60); + } // 邪魔 //const lastUsed = miLocalStorage.getItem('lastUsed'); diff --git a/packages/frontend/src/components/MkPostForm.vue b/packages/frontend/src/components/MkPostForm.vue index dc3f3aa94c..add5296f0a 100644 --- a/packages/frontend/src/components/MkPostForm.vue +++ b/packages/frontend/src/components/MkPostForm.vue @@ -630,11 +630,22 @@ async function onPaste(ev: ClipboardEvent) { if (paste.length > 1000) { ev.preventDefault(); - os.confirm({ - type: 'info', + os.actions({ + type: 'question', text: i18n.ts.attachAsFileQuestion, - }).then(({ canceled }) => { - if (canceled) { + actions: [ + { + value: 'yes', + text: i18n.ts.yes, + primary: true, + }, + { + value: 'no', + text: i18n.ts.no, + }, + ], + }).then(({ result }) => { + if (result !== 'yes') { insertTextAtCursor(textareaEl.value, paste); return; } diff --git a/packages/frontend/src/components/MkVisitorDashboard.vue b/packages/frontend/src/components/MkVisitorDashboard.vue index b154f7a5b3..ff2e27aaf8 100644 --- a/packages/frontend/src/components/MkVisitorDashboard.vue +++ b/packages/frontend/src/components/MkVisitorDashboard.vue @@ -142,6 +142,7 @@ function showMenu(ev: MouseEvent) { height: 32px; border-radius: var(--radius-sm); font-size: 18px; + z-index: 50; } .mainFg { diff --git a/packages/frontend/src/const.ts b/packages/frontend/src/const.ts index c94c0d4408..058db9b981 100644 --- a/packages/frontend/src/const.ts +++ b/packages/frontend/src/const.ts @@ -160,9 +160,9 @@ export const ROLE_POLICIES = [ export const CURRENT_STICKY_TOP = 'CURRENT_STICKY_TOP'; export const CURRENT_STICKY_BOTTOM = 'CURRENT_STICKY_BOTTOM'; -export const DEFAULT_SERVER_ERROR_IMAGE_URL = 'https://launcher.moe/error.png'; -export const DEFAULT_NOT_FOUND_IMAGE_URL = 'https://launcher.moe/missingpage.webp'; -export const DEFAULT_INFO_IMAGE_URL = 'https://launcher.moe/nothinghere.png'; +export const DEFAULT_SERVER_ERROR_IMAGE_URL = '/status/error.png'; +export const DEFAULT_NOT_FOUND_IMAGE_URL = '/status/missingpage.webp'; +export const DEFAULT_INFO_IMAGE_URL = '/status/nothinghere.png'; export const MFM_TAGS = ['tada', 'jelly', 'twitch', 'shake', 'spin', 'jump', 'bounce', 'flip', 'x2', 'x3', 'x4', 'scale', 'position', 'fg', 'bg', 'border', 'font', 'blur', 'rainbow', 'sparkle', 'rotate', 'ruby', 'unixtime', 'crop', 'fade', 'followmouse']; export const MFM_PARAMS: Record<typeof MFM_TAGS[number], string[]> = { diff --git a/packages/frontend/src/index.html b/packages/frontend/src/index.html index 733116b75f..fdeb642c70 100644 --- a/packages/frontend/src/index.html +++ b/packages/frontend/src/index.html @@ -20,7 +20,7 @@ worker-src 'self'; script-src 'self' 'unsafe-eval' https://*.hcaptcha.com https://challenges.cloudflare.com https://esm.sh; style-src 'self' 'unsafe-inline'; - img-src 'self' data: blob: www.google.com xn--931a.moe launcher.moe localhost:3000 localhost:5173 127.0.0.1:5173 127.0.0.1:3000 activitypub.software secure.gravatar.com avatars.githubusercontent.com; + img-src 'self' data: blob: www.google.com xn--931a.moe localhost:3000 localhost:5173 127.0.0.1:5173 127.0.0.1:3000 activitypub.software secure.gravatar.com avatars.githubusercontent.com; media-src 'self' localhost:3000 localhost:5173 127.0.0.1:5173 127.0.0.1:3000; connect-src 'self' localhost:3000 localhost:5173 127.0.0.1:5173 127.0.0.1:3000 https://newassets.hcaptcha.com https://api.listenbrainz.org; frame-src *;" diff --git a/packages/frontend/src/pages/instance-info.vue b/packages/frontend/src/pages/instance-info.vue index b5803ab3f1..5401ea51e0 100644 --- a/packages/frontend/src/pages/instance-info.vue +++ b/packages/frontend/src/pages/instance-info.vue @@ -45,11 +45,14 @@ SPDX-License-Identifier: AGPL-3.0-only </MkKeyValue> <MkButton v-if="suspensionState === 'none'" :disabled="!instance" danger @click="stopDelivery">{{ i18n.ts._delivery.stop }}</MkButton> <MkButton v-if="suspensionState !== 'none'" :disabled="!instance" @click="resumeDelivery">{{ i18n.ts._delivery.resume }}</MkButton> - <MkSwitch v-model="isBlocked" :disabled="!meta || !instance" @update:modelValue="toggleBlock">{{ i18n.ts.blockThisInstance }}</MkSwitch> - <MkSwitch v-model="isSilenced" :disabled="!meta || !instance" @update:modelValue="toggleSilenced">{{ i18n.ts.silenceThisInstance }}</MkSwitch> + <MkInfo v-if="isBaseBlocked" warn>{{ i18n.ts.blockedByBase }}</MkInfo> + <MkSwitch v-model="isBlocked" :disabled="!meta || !instance || isBaseBlocked" @update:modelValue="toggleBlock">{{ i18n.ts.blockThisInstance }}</MkSwitch> + <MkInfo v-if="isBaseSilenced" warn>{{ i18n.ts.silencedByBase }}</MkInfo> + <MkSwitch v-model="isSilenced" :disabled="!meta || !instance || isBaseSilenced" @update:modelValue="toggleSilenced">{{ i18n.ts.silenceThisInstance }}</MkSwitch> <MkSwitch v-model="isNSFW" :disabled="!instance" @update:modelValue="toggleNSFW">{{ i18n.ts.markInstanceAsNSFW }}</MkSwitch> <MkSwitch v-model="rejectReports" :disabled="!instance" @update:modelValue="toggleRejectReports">{{ i18n.ts.rejectReports }}</MkSwitch> - <MkSwitch v-model="isMediaSilenced" :disabled="!meta || !instance" @update:modelValue="toggleMediaSilenced">{{ i18n.ts.mediaSilenceThisInstance }}</MkSwitch> + <MkInfo v-if="isBaseMediaSilenced" warn>{{ i18n.ts.mediaSilencedByBase }}</MkInfo> + <MkSwitch v-model="isMediaSilenced" :disabled="!meta || !instance || isBaseMediaSilenced" @update:modelValue="toggleMediaSilenced">{{ i18n.ts.mediaSilenceThisInstance }}</MkSwitch> <MkButton @click="refreshMetadata"><i class="ti ti-refresh"></i> Refresh metadata</MkButton> <MkTextarea v-model="moderationNote" manualSave> <template #label>{{ i18n.ts.moderationNote }}</template> @@ -157,6 +160,7 @@ import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue'; import { getProxiedImageUrlNullable } from '@/scripts/media-proxy.js'; import { dateString } from '@/filters/date.js'; import MkTextarea from '@/components/MkTextarea.vue'; +import MkInfo from '@/components/MkInfo.vue'; const props = defineProps<{ host: string; @@ -176,6 +180,21 @@ const isMediaSilenced = ref(false); const faviconUrl = ref<string | null>(null); const moderationNote = ref(''); +const baseDomains = computed(() => { + const domains: string[] = []; + + const parts = props.host.toLowerCase().split('.'); + for (let s = 1; s < parts.length; s++) { + const domain = parts.slice(s).join('.'); + domains.push(domain); + } + + return domains; +}); +const isBaseBlocked = computed(() => meta.value && baseDomains.value.some(d => meta.value?.blockedHosts.includes(d))); +const isBaseSilenced = computed(() => meta.value && baseDomains.value.some(d => meta.value?.silencedHosts.includes(d))); +const isBaseMediaSilenced = computed(() => meta.value && baseDomains.value.some(d => meta.value?.mediaSilencedHosts.includes(d))); + const usersPagination = { endpoint: iAmModerator ? 'admin/show-users' : 'users' as const, limit: 10, diff --git a/packages/frontend/src/pages/user/home.vue b/packages/frontend/src/pages/user/home.vue index b997fe1c3f..e82ec0cb97 100644 --- a/packages/frontend/src/pages/user/home.vue +++ b/packages/frontend/src/pages/user/home.vue @@ -30,7 +30,12 @@ SPDX-License-Identifier: AGPL-3.0-only </button> </div> </div> - <span v-if="$i && $i.id != user.id && user.isFollowed" class="followed">{{ i18n.ts.followsYou }}</span> + <div v-if="$i && $i.id != user.id" class="info-badges"> + <span v-if="user.isFollowed">{{ i18n.ts.followsYou }}</span> + <span v-if="user.isMuted">{{ i18n.ts.muted }}</span> + <span v-if="user.isRenoteMuted">{{ i18n.ts.renoteMuted }}</span> + <span v-if="user.isBlocking">{{ i18n.ts.blocked }}</span> + </div> <div class="actions"> <button class="menu _button" @click="menu"><i class="ti ti-dots"></i></button> <MkFollowButton v-if="$i?.id != user.id" v-model:user="user" :inline="true" :transparent="false" :full="true" class="koudoku"/> @@ -445,15 +450,25 @@ onUnmounted(() => { background: linear-gradient(transparent, rgba(#000, 0.7)); } - > .followed { + > .info-badges { position: absolute; top: 12px; left: 12px; - padding: 4px 8px; - color: #fff; - background: rgba(0, 0, 0, 0.7); - font-size: 0.7em; - border-radius: var(--radius-sm); + + display: flex; + flex-direction: row; + + > * { + padding: 4px 8px; + color: #fff; + background: rgba(0, 0, 0, 0.7); + font-size: 0.7em; + border-radius: var(--radius-sm); + } + + > :not(:first-child) { + margin-left: 8px; + } } > .actions { diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index 0e83bdfcca..e3bf828982 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -5199,7 +5199,7 @@ export type operations = { enableEmail: boolean; enableServiceWorker: boolean; translatorAvailable: boolean; - silencedHosts?: string[]; + silencedHosts: string[]; mediaSilencedHosts: string[]; pinnedUsers: string[]; hiddenTags: string[]; |