mirror of
https://activitypub.software/TransFem-org/Sharkey
synced 2024-11-21 21:45:11 +00:00
Merge branch 'develop' into hazelnoot/579-reject-reports
# Conflicts: # packages/frontend/src/pages/instance-info.vue
This commit is contained in:
commit
047563bdde
19 changed files with 121 additions and 41 deletions
|
@ -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"
|
||||
|
|
28
locales/index.d.ts
vendored
28
locales/index.d.ts
vendored
|
@ -588,6 +588,10 @@ export interface Locale extends ILocale {
|
|||
* ミュート
|
||||
*/
|
||||
"mute": string;
|
||||
/**
|
||||
* Muted
|
||||
*/
|
||||
"muted": string;
|
||||
/**
|
||||
* ミュート解除
|
||||
*/
|
||||
|
@ -596,6 +600,10 @@ export interface Locale extends ILocale {
|
|||
* ブーストをミュート
|
||||
*/
|
||||
"renoteMute": string;
|
||||
/**
|
||||
* Boosts muted
|
||||
*/
|
||||
"renoteMuted": string;
|
||||
/**
|
||||
* ブーストのミュートを解除
|
||||
*/
|
||||
|
@ -1076,6 +1084,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;
|
||||
/**
|
||||
* 配信停止
|
||||
*/
|
||||
|
@ -4441,10 +4461,6 @@ export interface Locale extends ILocale {
|
|||
* 連合なしにする
|
||||
*/
|
||||
"disableFederationOk": string;
|
||||
/**
|
||||
* 猫の話し方を無効にする
|
||||
*/
|
||||
"disableCatSpeak": 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;
|
||||
};
|
||||
|
|
|
@ -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: "購読中"
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -128,7 +128,7 @@ export const meta = {
|
|||
},
|
||||
silencedHosts: {
|
||||
type: 'array',
|
||||
optional: true,
|
||||
optional: false,
|
||||
nullable: false,
|
||||
items: {
|
||||
type: 'string',
|
||||
|
|
|
@ -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)),
|
||||
|
|
BIN
packages/frontend/assets/status/error.png
Normal file
BIN
packages/frontend/assets/status/error.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
BIN
packages/frontend/assets/status/missingpage.webp
Normal file
BIN
packages/frontend/assets/status/missingpage.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.4 KiB |
BIN
packages/frontend/assets/status/nothinghere.png
Normal file
BIN
packages/frontend/assets/status/nothinghere.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 36 KiB |
|
@ -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');
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -142,6 +142,7 @@ function showMenu(ev: MouseEvent) {
|
|||
height: 32px;
|
||||
border-radius: var(--radius-sm);
|
||||
font-size: 18px;
|
||||
z-index: 50;
|
||||
}
|
||||
|
||||
.mainFg {
|
||||
|
|
|
@ -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[]> = {
|
||||
|
|
|
@ -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 *;"
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -5199,7 +5199,7 @@ export type operations = {
|
|||
enableEmail: boolean;
|
||||
enableServiceWorker: boolean;
|
||||
translatorAvailable: boolean;
|
||||
silencedHosts?: string[];
|
||||
silencedHosts: string[];
|
||||
mediaSilencedHosts: string[];
|
||||
pinnedUsers: string[];
|
||||
hiddenTags: string[];
|
||||
|
|
Loading…
Reference in a new issue