Skip to content
This repository has been archived by the owner on Aug 21, 2024. It is now read-only.

Commit

Permalink
Merge remote-tracking branch 'misskey-dev/master' into custom-nj/develop
Browse files Browse the repository at this point in the history
  • Loading branch information
nafu-at committed Jul 21, 2023
2 parents e084284 + 4e24aff commit cc45f95
Show file tree
Hide file tree
Showing 19 changed files with 145 additions and 85 deletions.
9 changes: 7 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
-->

## 13.x.x (unreleased)
## 13.14.1

### General
- 招待機能を改善しました
Expand All @@ -27,6 +27,7 @@
- deck UIのカラムのメニューからアンテナとリストの編集画面を開けるように
- ドライブファイルのメニューで画像をクロップできるように
- 画像を動画と同様に簡単に隠せるように
- Enhance: ノートの埋め込みが複数画像と動画を表示されるように
- オリジナル画像を保持せずにアップロードする場合webpでアップロードされるように(Safari以外)
- 見たことのあるRenoteを省略して表示をオンのときに自分のnoteのrenoteを省略するように
- フォルダーやファイルに対しても開発者モード使用時、IDをコピーできるように
Expand All @@ -42,6 +43,8 @@
- ロール設定画面でロールIDを確認できるように
- コンテキストメニュー表示時のパフォーマンスを改善
- フォロー/フォロワー非公開時の表示を改善
- 本文にMFMが含まれている場合に自動でたたまれる機能が、返信先や引用RNにも適用されるように
- position は対象外になりました
- AiScriptを0.15.0に更新
- Fix: サーバーメトリクスが90度傾いている
- Fix: 非ログイン時にクレデンシャルが必要なページに行くとエラーが出る問題を修正
Expand All @@ -59,7 +62,8 @@
- nsfwjs のモデルロードを排他することで、重複ロードによってメモリ使用量が増加しないように
- 連合の配送ジョブのパフォーマンスを向上(ロック機構の見直し、Redisキャッシュの活用)
- featuredノートのsignedGet回数を減らしました
- リモートサーバーからのNSFW映像のキャッシュだけを無効化できるオプションを追加
- ActivityPubの署名用鍵長を2048bitに変更しパフォーマンスを向上(新規アカウントのみ)
- リモートサーバーのセンシティブなファイルのキャッシュだけを無効化できるオプションを追加
- MeilisearchにIndexするノートの範囲を設定できるように
- Export notes with file detail
- Add unix socket support
Expand All @@ -70,6 +74,7 @@
- Fix: 非英語環境でのPostgreSQLのエラーハンドリングを修正
- Fix: インスタンスのアイコンがbase64の場合の挙動を修正
- Fix: ローカルの `Person` を指す `acct` URI を解析するときのバグを修正しました
- Fix: 無効化されたアンテナが再度有効化されないことがある問題を修正

## 13.13.2

Expand Down
3 changes: 3 additions & 0 deletions locales/sv-SE.yml
Original file line number Diff line number Diff line change
Expand Up @@ -389,10 +389,13 @@ help: "Hjälp"
close: "Stäng"
invites: "Inbjudan"
members: "Medlemmar"
transfer: "Överför"
text: "Text"
enable: "Aktivera"
next: "Nästa"
invitations: "Inbjudan"
invitationCode: "Inbjudningskod"
available: "Tillgängligt"
weakPassword: "Svagt Lösenord"
normalPassword: "Medel Lösenord"
strongPassword: "Starkt Lösenord"
Expand Down
2 changes: 1 addition & 1 deletion locales/zh-TW.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
_lang_: "繁體中文"
headlineMisskey: "貼文連繫網絡"
introMisskey: "歡迎! Misskey是一個開源且去中心化的社群網絡。\n通過「貼文」分享周邊新鮮事,並告訴其他人您的想法!📡\n透過「情感」功能,對大家的貼文表達情感!👍\n一起來探索這個新的世界吧!🚀"
introMisskey: "歡迎!Misskey 是一個開源且去中心化的社群網路服務。\n發佈「貼文」向身邊的人分享您的想法!📡\n利用「反應」表達您對貼文的感覺!👍\n讓我們一起探索新的世界吧!🚀"
poweredByMisskeyDescription: "{name}是使用開放原始碼平台<b>Misskey</b>的服務之一(稱為 Misskey 伺服器)。\n"
monthAndDay: "{month}月 {day}日"
search: "搜尋"
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"name": "misskey",
"version": "13.14.0-beta.7-nj",
"version": "13.14.1-nj",
"codename": "nasubi",
"repository": {
"type": "git",
"url": "https://github.com/TeamNijimiss/misskey.git"
},
"packageManager": "[email protected].0",
"packageManager": "[email protected].9",
"workspaces": [
"packages/frontend",
"packages/backend",
Expand Down
1 change: 1 addition & 0 deletions packages/backend/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ function tryCreateUrl(url: string) {
function convertRedisOptions(options: RedisOptionsSource, host: string): RedisOptions & RedisOptionsSource {
return {
...options,
password: options.pass,
prefix: options.prefix ?? host,
family: options.family == null ? 0 : options.family,
keyPrefix: `${options.prefix ?? host}:`,
Expand Down
2 changes: 1 addition & 1 deletion packages/backend/src/core/CreateSystemUserService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export class CreateSystemUserService {
// Generate secret
const secret = generateNativeUserToken();

const keyPair = await genRsaKeyPair(4096);
const keyPair = await genRsaKeyPair();

let account!: User;

Expand Down
2 changes: 1 addition & 1 deletion packages/backend/src/core/QueueService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export class QueueService {
removeOnFail: true,
};

await this.deliverQueue.addBulk(Array.from(inboxes.entries()).map(d => ({
await this.deliverQueue.addBulk(Array.from(inboxes.entries(), d => ({
name: d[0],
data: {
user,
Expand Down
2 changes: 1 addition & 1 deletion packages/backend/src/core/SignupService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export class SignupService {

const keyPair = await new Promise<string[]>((res, rej) =>
generateKeyPair('rsa', {
modulusLength: 4096,
modulusLength: 2048,
publicKeyEncoding: {
type: 'spki',
format: 'pem',
Expand Down
10 changes: 5 additions & 5 deletions packages/backend/src/server/api/endpoints/antennas/notes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
throw new ApiError(meta.errors.noSuchAntenna);
}

this.antennasRepository.update(antenna.id, {
isActive: true,
lastUsedAt: new Date(),
});

const limit = ps.limit + (ps.untilId ? 1 : 0) + (ps.sinceId ? 1 : 0); // untilIdに指定したものも含まれるため+1
const noteIdsRes = await this.redisClient.xrevrange(
`antennaTimeline:${antenna.id}`,
Expand Down Expand Up @@ -112,11 +117,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
this.noteReadService.read(me.id, notes);
}

this.antennasRepository.update(antenna.id, {
isActive: true,
lastUsedAt: new Date(),
});

return await this.noteEntityService.packMany(notes, me);
});
}
Expand Down
2 changes: 2 additions & 0 deletions packages/backend/src/server/api/endpoints/antennas/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
withReplies: ps.withReplies,
withFile: ps.withFile,
notify: ps.notify,
isActive: true,
lastUsedAt: new Date(),
});

this.globalEventService.publishInternalEvent('antennaUpdated', await this.antennasRepository.findOneByOrFail({ id: antenna.id }));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
const procedures = this.twoFactorAuthenticationService.getProcedures();

if (!(procedures as any)[attestation.fmt]) {
throw new Error('unsupported fmt');
throw new Error(`unsupported fmt: ${attestation.fmt}. Supported ones: ${Object.keys(procedures)}`);
}

const verificationData = (procedures as any)[attestation.fmt].verify({
Expand Down
22 changes: 12 additions & 10 deletions packages/backend/src/server/web/views/note.pug
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ block vars
- const title = user.name ? `${user.name} (@${user.username})` : `@${user.username}`;
- const url = `${config.url}/notes/${note.id}`;
- const isRenote = note.renote && note.text == null && note.fileIds.length == 0 && note.poll == null;
- const image = (note.files || []).find(file => file.type.startsWith('image/') && !file.isSensitive)
- const video = (note.files || []).find(file => file.type.startsWith('video/') && !file.isSensitive)
- const images = (note.files || []).filter(file => file.type.startsWith('image/') && !file.isSensitive)
- const videos = (note.files || []).filter(file => file.type.startsWith('video/') && !file.isSensitive)

block title
= `${title} | ${instanceName}`
Expand All @@ -19,15 +19,17 @@ block og
meta(property='og:title' content= title)
meta(property='og:description' content= summary)
meta(property='og:url' content= url)
if video
meta(property='og:video:url' content= video.url)
meta(property='og:video:secure_url' content= video.url)
meta(property='og:video:type' content= video.type)
// FIXME: add width and height
// FIXME: add embed player for Twitter
if image
if videos.length
each video in videos
meta(property='og:video:url' content= video.url)
meta(property='og:video:secure_url' content= video.url)
meta(property='og:video:type' content= video.type)
// FIXME: add width and height
// FIXME: add embed player for Twitter
if images.length
meta(property='twitter:card' content='summary_large_image')
meta(property='og:image' content= image.url)
each image in images
meta(property='og:image' content= image.url)
else
meta(property='twitter:card' content='summary')
meta(property='og:image' content= avatarUrl)
Expand Down
13 changes: 2 additions & 11 deletions packages/frontend/src/components/MkNote.vue
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ import { getNoteSummary } from '@/scripts/get-note-summary';
import { MenuItem } from '@/types/menu';
import MkRippleEffect from '@/components/MkRippleEffect.vue';
import { showMovedDialog } from '@/scripts/show-moved-dialog';
import { shouldCollapsed } from '@/scripts/collapsed';
const props = defineProps<{
note: misskey.entities.Note;
Expand Down Expand Up @@ -204,17 +205,7 @@ let appearNote = $computed(() => isRenote ? note.renote as misskey.entities.Note
const isMyRenote = $i && ($i.id === note.userId);
const showContent = ref(false);
const urls = appearNote.text ? extractUrlFromMfm(mfm.parse(appearNote.text)) : null;
const isLong = (appearNote.cw == null && appearNote.text != null && (
(appearNote.text.includes('$[x2')) ||
(appearNote.text.includes('$[x3')) ||
(appearNote.text.includes('$[x4')) ||
(appearNote.text.includes('$[scale')) ||
(appearNote.text.includes('$[position')) ||
(appearNote.text.split('\n').length > 15) ||
(appearNote.text.length > 650) ||
(appearNote.files.length >= 5) ||
(urls && urls.length >= 4)
));
const isLong = shouldCollapsed(appearNote);
const collapsed = ref(appearNote.cw == null && isLong);
const isDeleted = ref(false);
const muted = ref(checkWordMute(appearNote, $i, defaultStore.state.mutedWords));
Expand Down
7 changes: 2 additions & 5 deletions packages/frontend/src/components/MkSubNoteContent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,13 @@ import MkMediaList from '@/components/MkMediaList.vue';
import MkPoll from '@/components/MkPoll.vue';
import { i18n } from '@/i18n';
import { $i } from '@/account';
import { shouldCollapsed } from '@/scripts/collapsed';
const props = defineProps<{
note: misskey.entities.Note;
}>();
const isLong =
props.note.cw == null && props.note.text != null && (
(props.note.text.split('\n').length > 9) ||
(props.note.text.length > 500)
);
const isLong = shouldCollapsed(props.note);
const collapsed = $ref(isLong);
</script>
Expand Down
30 changes: 17 additions & 13 deletions packages/frontend/src/components/MkUrlPreview.vue
Original file line number Diff line number Diff line change
Expand Up @@ -52,19 +52,21 @@
</footer>
</article>
</component>
<div v-if="tweetId" :class="$style.action">
<MkButton :small="true" inline @click="tweetExpanded = true">
<i class="ti ti-brand-twitter"></i> {{ i18n.ts.expandTweet }}
</MkButton>
</div>
<div v-if="!playerEnabled && player.url" :class="$style.action">
<MkButton :small="true" inline @click="playerEnabled = true">
<i class="ti ti-player-play"></i> {{ i18n.ts.enablePlayer }}
</MkButton>
<MkButton v-if="!isMobile" :small="true" inline @click="openPlayer()">
<i class="ti ti-picture-in-picture"></i> {{ i18n.ts.openInWindow }}
</MkButton>
</div>
<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 }}
</MkButton>
</div>
<div v-if="!playerEnabled && player.url" :class="$style.action">
<MkButton :small="true" inline @click="playerEnabled = true">
<i class="ti ti-player-play"></i> {{ i18n.ts.enablePlayer }}
</MkButton>
<MkButton v-if="!isMobile" :small="true" inline @click="openPlayer()">
<i class="ti ti-picture-in-picture"></i> {{ i18n.ts.openInWindow }}
</MkButton>
</div>
</template>
</div>
</template>

Expand All @@ -85,9 +87,11 @@ const props = withDefaults(defineProps<{
url: string;
detail?: boolean;
compact?: boolean;
showActions?: boolean;
}>(), {
detail: false,
compact: false,
showActions: true,
});
const MOBILE_THRESHOLD = 500;
Expand Down
2 changes: 1 addition & 1 deletion packages/frontend/src/components/MkUrlPreviewPopup.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<div :class="$style.root" :style="{ zIndex, top: top + 'px', left: left + 'px' }">
<Transition :name="defaultStore.state.animation ? '_transition_zoom' : ''" @afterLeave="emit('closed')">
<MkUrlPreview v-if="showing" class="_popup _shadow" :url="url"/>
<MkUrlPreview v-if="showing" class="_popup _shadow" :url="url" :showActions="false"/>
</Transition>
</div>
</template>
Expand Down
81 changes: 50 additions & 31 deletions packages/frontend/src/components/global/MkAd.stories.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import { userEvent, waitFor, within } from '@storybook/testing-library';
import { StoryObj } from '@storybook/vue3';
import MkAd from './MkAd.vue';
import { i18n } from '@/i18n';

let lock: Promise<undefined> | undefined;

const common = {
render(args) {
return {
Expand All @@ -25,41 +28,57 @@ const common = {
template: '<MkAd v-bind="props" />',
};
},
/* FIXME: disabled because it still didn’t pass after applying #11267
async play({ canvasElement, args }) {
const canvas = within(canvasElement);
const a = canvas.getByRole<HTMLAnchorElement>('link');
await expect(a.href).toMatch(/^https?:\/\/.*#test$/);
const img = within(a).getByRole('img');
await expect(img).toBeInTheDocument();
let buttons = canvas.getAllByRole<HTMLButtonElement>('button');
await expect(buttons).toHaveLength(1);
const i = buttons[0];
await expect(i).toBeInTheDocument();
await userEvent.click(i);
await waitFor(() => expect(canvasElement).toHaveTextContent(i18n.ts._ad.back));
await expect(a).not.toBeInTheDocument();
await expect(i).not.toBeInTheDocument();
buttons = canvas.getAllByRole<HTMLButtonElement>('button');
await expect(buttons).toHaveLength(args.__hasReduce ? 2 : 1);
const reduce = args.__hasReduce ? buttons[0] : null;
const back = buttons[args.__hasReduce ? 1 : 0];
if (reduce) {
await expect(reduce).toBeInTheDocument();
await expect(reduce).toHaveTextContent(i18n.ts._ad.reduceFrequencyOfThisAd);
if (lock) {
console.warn('This test is unexpectedly running twice in parallel, fix it!');
console.warn('See also: https://github.com/misskey-dev/misskey/issues/11267');
await lock;
}
await expect(back).toBeInTheDocument();
await expect(back).toHaveTextContent(i18n.ts._ad.back);
await userEvent.click(back);
await waitFor(() => expect(canvas.queryByRole('img')).toBeTruthy());
if (reduce) {
await expect(reduce).not.toBeInTheDocument();
let resolve: (value?: any) => void;
lock = new Promise(r => resolve = r);
try {
const canvas = within(canvasElement);
const a = canvas.getByRole<HTMLAnchorElement>('link');
await expect(a.href).toMatch(/^https?:\/\/.*#test$/);
const img = within(a).getByRole('img');
await expect(img).toBeInTheDocument();
let buttons = canvas.getAllByRole<HTMLButtonElement>('button');
await expect(buttons).toHaveLength(1);
const i = buttons[0];
await expect(i).toBeInTheDocument();
await userEvent.click(i);
await waitFor(() => expect(canvasElement).toHaveTextContent(i18n.ts._ad.back));
await expect(a).not.toBeInTheDocument();
await expect(i).not.toBeInTheDocument();
buttons = canvas.getAllByRole<HTMLButtonElement>('button');
await expect(buttons).toHaveLength(args.__hasReduce ? 2 : 1);
const reduce = args.__hasReduce ? buttons[0] : null;
const back = buttons[args.__hasReduce ? 1 : 0];
if (reduce) {
await expect(reduce).toBeInTheDocument();
await expect(reduce).toHaveTextContent(i18n.ts._ad.reduceFrequencyOfThisAd);
}
await expect(back).toBeInTheDocument();
await expect(back).toHaveTextContent(i18n.ts._ad.back);
await userEvent.click(back);
await waitFor(() => expect(canvas.queryByRole('img')).toBeTruthy());
if (reduce) {
await expect(reduce).not.toBeInTheDocument();
}
await expect(back).not.toBeInTheDocument();
const aAgain = canvas.getByRole<HTMLAnchorElement>('link');
await expect(aAgain).toBeInTheDocument();
const imgAgain = within(aAgain).getByRole('img');
await expect(imgAgain).toBeInTheDocument();
} finally {
resolve!();
lock = undefined;
}
await expect(back).not.toBeInTheDocument();
const aAgain = canvas.getByRole<HTMLAnchorElement>('link');
await expect(aAgain).toBeInTheDocument();
const imgAgain = within(aAgain).getByRole('img');
await expect(imgAgain).toBeInTheDocument();
},
*/
args: {
prefer: [],
specify: {
Expand Down
Loading

0 comments on commit cc45f95

Please sign in to comment.