Merge branch 'develop' into update-deos

This commit is contained in:
syuilo 2023-07-31 17:58:39 +09:00
commit af368e077b
14 changed files with 87 additions and 63 deletions

View File

@ -18,7 +18,9 @@
- OAuth 2.0のサポート
### Client
-
- Enhance: 自分が押したリアクションのデザインを改善
- Fix: サーバー情報画面(`/instance-info/{domain}`)でブロックができないのを修正
- Fix: 未読のお知らせの「わかった」をクリック・タップしてもその場で「わかった」が消えない問題を修正
### Server
-

View File

@ -147,7 +147,6 @@
"rss-parser": "3.13.0",
"rxjs": "7.8.1",
"sanitize-html": "2.11.0",
"semver": "7.5.4",
"sharp": "0.32.4",
"sharp-read-bmp": "github:misskey-dev/sharp-read-bmp",
"slacc": "0.0.10",

View File

@ -10,7 +10,6 @@ import * as os from 'node:os';
import cluster from 'node:cluster';
import chalk from 'chalk';
import chalkTemplate from 'chalk-template';
import semver from 'semver';
import Logger from '@/logger.js';
import { loadConfig } from '@/config.js';
import type { Config } from '@/config.js';

View File

@ -21,7 +21,7 @@
"@rollup/plugin-replace": "5.0.2",
"@rollup/pluginutils": "5.0.2",
"@syuilo/aiscript": "0.15.0",
"@tabler/icons-webfont": "2.25.0",
"@tabler/icons-webfont": "2.30.0",
"@vitejs/plugin-vue": "4.2.3",
"@vue-macros/reactivity-transform": "0.3.16",
"@vue/compiler-sfc": "3.3.4",

View File

@ -168,10 +168,10 @@ export default defineComponent({
> *:empty {
display: none;
}
> *:not(:last-child) {
margin-bottom: var(--margin);
}
&:not(.date-separated-list-nogap) > *:not(:last-child) {
margin-bottom: var(--margin);
}
}

View File

@ -751,18 +751,25 @@ async function post(ev?: MouseEvent) {
claimAchievement('notes1');
}
const text = postData.text?.toLowerCase() ?? '';
if ((text.includes('love') || text.includes('❤')) && text.includes('misskey')) {
const text = postData.text ?? '';
const lowerCase = text.toLowerCase();
if ((lowerCase.includes('love') || lowerCase.includes('❤')) && lowerCase.includes('misskey')) {
claimAchievement('iLoveMisskey');
}
if (
text.includes('https://youtu.be/Efrlqw8ytg4'.toLowerCase()) ||
text.includes('https://www.youtube.com/watch?v=Efrlqw8ytg4'.toLowerCase()) ||
text.includes('https://m.youtube.com/watch?v=Efrlqw8ytg4'.toLowerCase()) ||
text.includes('https://youtu.be/XVCwzwxdHuA'.toLowerCase()) ||
text.includes('https://www.youtube.com/watch?v=XVCwzwxdHuA'.toLowerCase()) ||
text.includes('https://m.youtube.com/watch?v=XVCwzwxdHuA'.toLowerCase())
) {
if ([
'https://youtu.be/Efrlqw8ytg4',
'https://www.youtube.com/watch?v=Efrlqw8ytg4',
'https://m.youtube.com/watch?v=Efrlqw8ytg4',
'https://youtu.be/XVCwzwxdHuA',
'https://www.youtube.com/watch?v=XVCwzwxdHuA',
'https://m.youtube.com/watch?v=XVCwzwxdHuA',
'https://open.spotify.com/track/3Cuj0mZrlLoXx9nydNi7RB',
'https://open.spotify.com/track/7anfcaNPQWlWCwyCHmZqNy',
'https://open.spotify.com/track/5Odr16TvEN4my22K9nbH7l',
'https://open.spotify.com/album/5bOlxyl4igOrp2DwVQxBco',
].some(url => text.includes(url))) {
claimAchievement('brainDiver');
}

View File

@ -143,15 +143,13 @@ useTooltip(buttonEl, async (showing) => {
}
}
&.reacted {
background: var(--accent);
&:hover {
background: var(--accent);
}
&.reacted, &.reacted:hover {
background: var(--accentedBg);
color: var(--accent);
border: 1px solid var(--accent);
> .count {
color: var(--fgOnAccent);
color: var(--accent);
}
> .icon {

View File

@ -60,7 +60,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template v-if="showActions">
<div v-if="tweetId" :class="$style.action">
<MkButton :small="true" inline @click="tweetExpanded = true">
<i class="ti ti-brand-twitter"></i> {{ i18n.ts.expandTweet }}
<i class="ti ti-brand-x"></i> {{ i18n.ts.expandTweet }}
</MkButton>
</div>
<div v-if="!playerEnabled && player.url" :class="$style.action">

View File

@ -7,15 +7,15 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkStickyContainer>
<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template>
<MkSpacer :contentMax="800">
<MkPagination v-slot="{items}" :pagination="pagination" class="ruryvtyk _gaps_m">
<section v-for="(announcement, i) in items" :key="announcement.id" class="announcement _panel">
<MkPagination ref="paginationEl" v-slot="{items}" :pagination="pagination" class="ruryvtyk _gaps_m">
<section v-for="announcement in items" :key="announcement.id" class="announcement _panel">
<div class="header"><span v-if="$i && !announcement.isRead">🆕 </span>{{ announcement.title }}</div>
<div class="content">
<Mfm :text="announcement.text"/>
<img v-if="announcement.imageUrl" :src="announcement.imageUrl"/>
</div>
<div v-if="$i && !announcement.isRead" class="footer">
<MkButton primary @click="read(items, announcement, i)"><i class="ti ti-check"></i> {{ i18n.ts.gotIt }}</MkButton>
<MkButton primary @click="read(announcement.id)"><i class="ti ti-check"></i> {{ i18n.ts.gotIt }}</MkButton>
</div>
</section>
</MkPagination>
@ -24,7 +24,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<script lang="ts" setup>
import { } from 'vue';
import { ref } from 'vue';
import MkPagination from '@/components/MkPagination.vue';
import MkButton from '@/components/MkButton.vue';
import * as os from '@/os';
@ -37,13 +37,15 @@ const pagination = {
limit: 10,
};
// TODO:
function read(items, announcement, i) {
items[i] = {
...announcement,
isRead: true,
};
os.api('i/read-announcement', { announcementId: announcement.id });
const paginationEl = ref<InstanceType<typeof MkPagination>>();
function read(id: string) {
if (!paginationEl.value) return;
paginationEl.value.updateItem(id, announcement => {
announcement.isRead = true;
return announcement;
});
os.api('i/read-announcement', { announcementId: id });
}
const headerActions = $computed(() => []);

View File

@ -34,8 +34,8 @@ SPDX-License-Identifier: AGPL-3.0-only
<FormSection v-if="iAmModerator">
<template #label>Moderation</template>
<div class="_gaps_s">
<MkSwitch v-model="suspended" @update:modelValue="toggleSuspend">{{ i18n.ts.stopActivityDelivery }}</MkSwitch>
<MkSwitch v-model="isBlocked" @update:modelValue="toggleBlock">{{ i18n.ts.blockThisInstance }}</MkSwitch>
<MkSwitch v-model="suspended" :disabled="!instance" @update:modelValue="toggleSuspend">{{ i18n.ts.stopActivityDelivery }}</MkSwitch>
<MkSwitch v-model="isBlocked" :disabled="!meta || !instance" @update:modelValue="toggleBlock">{{ i18n.ts.blockThisInstance }}</MkSwitch>
<MkButton @click="refreshMetadata"><i class="ti ti-refresh"></i> Refresh metadata</MkButton>
</div>
</FormSection>
@ -129,7 +129,7 @@ import MkSelect from '@/components/MkSelect.vue';
import MkSwitch from '@/components/MkSwitch.vue';
import * as os from '@/os';
import number from '@/filters/number';
import { iAmModerator } from '@/account';
import { iAmModerator, iAmAdmin } from '@/account';
import { definePageMetadata } from '@/scripts/page-metadata';
import { i18n } from '@/i18n';
import MkUserCardMini from '@/components/MkUserCardMini.vue';
@ -143,11 +143,11 @@ const props = defineProps<{
let tab = $ref('overview');
let chartSrc = $ref('instance-requests');
let meta = $ref<misskey.entities.DetailedInstanceMetadata | null>(null);
let meta = $ref<misskey.entities.AdminInstanceMetadata | null>(null);
let instance = $ref<misskey.entities.Instance | null>(null);
let suspended = $ref(false);
let isBlocked = $ref(false);
let faviconUrl = $ref(null);
let faviconUrl = $ref<string | null>(null);
const usersPagination = {
endpoint: iAmModerator ? 'admin/show-users' : 'users' as const,
@ -160,7 +160,10 @@ const usersPagination = {
offsetMode: true,
};
async function fetch() {
async function fetch(): Promise<void> {
if (iAmAdmin) {
meta = await os.api('admin/meta');
}
instance = await os.api('federation/show-instance', {
host: props.host,
});
@ -169,21 +172,25 @@ async function fetch() {
faviconUrl = getProxiedImageUrlNullable(instance.faviconUrl, 'preview') ?? getProxiedImageUrlNullable(instance.iconUrl, 'preview');
}
async function toggleBlock(ev) {
if (meta == null) return;
async function toggleBlock(): Promise<void> {
if (!meta) throw new Error('No meta?');
if (!instance) throw new Error('No instance?');
const { host } = instance;
await os.api('admin/update-meta', {
blockedHosts: isBlocked ? meta.blockedHosts.concat([instance.host]) : meta.blockedHosts.filter(x => x !== instance.host),
blockedHosts: isBlocked ? meta.blockedHosts.concat([host]) : meta.blockedHosts.filter(x => x !== host),
});
}
async function toggleSuspend(v) {
async function toggleSuspend(): Promise<void> {
if (!instance) throw new Error('No instance?');
await os.api('admin/federation/update-instance', {
host: instance.host,
isSuspended: suspended,
});
}
function refreshMetadata() {
function refreshMetadata(): void {
if (!instance) throw new Error('No instance?');
os.api('admin/federation/refresh-remote-instance-metadata', {
host: instance.host,
});

View File

@ -17,6 +17,11 @@ export type Acct = {
// @public (undocumented)
type Ad = TODO_2;
// @public (undocumented)
type AdminInstanceMetadata = DetailedInstanceMetadata & {
blockedHosts: string[];
};
// @public (undocumented)
type Announcement = {
id: ID;
@ -329,8 +334,8 @@ export type Endpoints = {
res: TODO;
};
'admin/meta': {
req: TODO;
res: TODO;
req: NoParams;
res: AdminInstanceMetadata;
};
'admin/reset-password': {
req: TODO;
@ -2226,6 +2231,7 @@ declare namespace entities {
LiteInstanceMetadata,
DetailedInstanceMetadata,
InstanceMetadata,
AdminInstanceMetadata,
ServerInfo,
Stats,
Page,
@ -2317,7 +2323,7 @@ type ID = string;
// @public (undocumented)
type Instance = {
id: ID;
caughtAt: DateString;
firstRetrievedAt: DateString;
host: string;
usersCount: number;
notesCount: number;
@ -2331,6 +2337,7 @@ type Instance = {
lastCommunicatedAt: DateString;
isNotResponding: boolean;
isSuspended: boolean;
isBlocked: boolean;
softwareName: string | null;
softwareVersion: string | null;
openRegistrations: boolean | null;

View File

@ -2,7 +2,7 @@ import type {
Ad, Announcement, Antenna, App, AuthSession, Blocking, Channel, Clip, DateString, DetailedInstanceMetadata, DriveFile, DriveFolder, Following, FollowingFolloweePopulated, FollowingFollowerPopulated, FollowRequest, GalleryPost, Instance,
LiteInstanceMetadata,
MeDetailed,
Note, NoteFavorite, OriginType, Page, ServerInfo, Stats, User, UserDetailed, MeSignup, UserGroup, UserList, UserSorting, Notification, NoteReaction, Signin, MessagingMessage, Invite, InviteLimit,
Note, NoteFavorite, OriginType, Page, ServerInfo, Stats, User, UserDetailed, MeSignup, UserGroup, UserList, UserSorting, Notification, NoteReaction, Signin, MessagingMessage, Invite, InviteLimit, AdminInstanceMetadata,
} from './entities.js';
type TODO = Record<string, any> | null;
@ -20,7 +20,7 @@ export type Endpoints = {
'admin/get-table-stats': { req: TODO; res: TODO; };
'admin/invite': { req: TODO; res: TODO; };
'admin/logs': { req: TODO; res: TODO; };
'admin/meta': { req: TODO; res: TODO; };
'admin/meta': { req: NoParams; res: AdminInstanceMetadata; };
'admin/reset-password': { req: TODO; res: TODO; };
'admin/resolve-abuse-user-report': { req: TODO; res: TODO; };
'admin/resync-chart': { req: TODO; res: TODO; };

View File

@ -346,6 +346,11 @@ export type DetailedInstanceMetadata = LiteInstanceMetadata & {
export type InstanceMetadata = LiteInstanceMetadata | DetailedInstanceMetadata;
export type AdminInstanceMetadata = DetailedInstanceMetadata & {
// TODO: There are more fields.
blockedHosts: string[];
};
export type ServerInfo = {
machine: string;
cpu: {
@ -482,7 +487,7 @@ export type Blocking = {
export type Instance = {
id: ID;
caughtAt: DateString;
firstRetrievedAt: DateString;
host: string;
usersCount: number;
notesCount: number;
@ -496,6 +501,7 @@ export type Instance = {
lastCommunicatedAt: DateString;
isNotResponding: boolean;
isSuspended: boolean;
isBlocked: boolean;
softwareName: string | null;
softwareVersion: string | null;
openRegistrations: boolean | null;

View File

@ -341,9 +341,6 @@ importers:
sanitize-html:
specifier: 2.11.0
version: 2.11.0
semver:
specifier: 7.5.4
version: 7.5.4
sharp:
specifier: 0.32.4
version: 0.32.4
@ -665,8 +662,8 @@ importers:
specifier: 0.15.0
version: 0.15.0
'@tabler/icons-webfont':
specifier: 2.25.0
version: 2.25.0
specifier: 2.30.0
version: 2.30.0
'@vitejs/plugin-vue':
specifier: 4.2.3
version: 4.2.3(vite@4.4.7)(vue@3.3.4)
@ -7610,14 +7607,14 @@ packages:
dependencies:
defer-to-connect: 2.0.1
/@tabler/icons-webfont@2.25.0:
resolution: {integrity: sha512-IWYVnYlCwlGC95kvpY5Hdiyn1/amXOUwsfRthtmgEtHCQly4JSLRuaD90xD0O+pQ+wZBXIVNsO3pKdg74zEaBg==}
/@tabler/icons-webfont@2.30.0:
resolution: {integrity: sha512-tGGKxeATvyHJBHl5FzY4oAShbAiR4ovstG62lqb2HGlOJwz4Io9TSk4eoB88nqxg3sT5no2YsAKXcr1UnlpnNQ==}
dependencies:
'@tabler/icons': 2.25.0
'@tabler/icons': 2.30.0
dev: false
/@tabler/icons@2.25.0:
resolution: {integrity: sha512-Z+FtSZoG/CM1TMCgg7elUew2m0+qMdh5gutMhvxiIY77KIIsE6L/6fUBy+rPXWE9v7MV296fsnCvbpfgwpXupQ==}
/@tabler/icons@2.30.0:
resolution: {integrity: sha512-tvtmkI4ALjKThVVORh++sB9JnkFY7eGInKxNy+Df7WVQiF7T85tlvGADzlgX4Ic+CK5MIUzZ0jhOlQ/RRlgXpg==}
dev: false
/@tensorflow/tfjs-backend-cpu@4.4.0(@tensorflow/tfjs-core@4.4.0):