mirror of
https://github.com/kokonect-link/cherrypick
synced 2024-12-18 16:48:30 +09:00
Merge remote-branch 'misskey/master'
This commit is contained in:
commit
7ad4587f60
@ -12,7 +12,7 @@
|
||||
|
||||
-->
|
||||
|
||||
## 13.x.x (unreleased)
|
||||
## 13.14.1
|
||||
|
||||
### General
|
||||
- 招待機能を改善しました
|
||||
@ -27,6 +27,7 @@
|
||||
- deck UIのカラムのメニューからアンテナとリストの編集画面を開けるように
|
||||
- ドライブファイルのメニューで画像をクロップできるように
|
||||
- 画像を動画と同様に簡単に隠せるように
|
||||
- Enhance: ノートの埋め込みが複数画像と動画を表示されるように
|
||||
- オリジナル画像を保持せずにアップロードする場合webpでアップロードされるように(Safari以外)
|
||||
- 見たことのあるRenoteを省略して表示をオンのときに自分のnoteのrenoteを省略するように
|
||||
- フォルダーやファイルに対しても開発者モード使用時、IDをコピーできるように
|
||||
@ -42,6 +43,8 @@
|
||||
- ロール設定画面でロールIDを確認できるように
|
||||
- コンテキストメニュー表示時のパフォーマンスを改善
|
||||
- フォロー/フォロワー非公開時の表示を改善
|
||||
- 本文にMFMが含まれている場合に自動でたたまれる機能が、返信先や引用RNにも適用されるように
|
||||
- position は対象外になりました
|
||||
- AiScriptを0.15.0に更新
|
||||
- Fix: サーバーメトリクスが90度傾いている
|
||||
- Fix: 非ログイン時にクレデンシャルが必要なページに行くとエラーが出る問題を修正
|
||||
|
@ -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"
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
_lang_: "繁體中文"
|
||||
headlineMisskey: "貼文連繫網絡"
|
||||
introMisskey: "歡迎! CherryPick是一個開源且去中心化的社群網絡。\n通過「貼文」分享周邊新鮮事,並告訴其他人您的想法!📡\n透過「情感」功能,對大家的貼文表達情感!👍\n一起來探索這個新的世界吧!🚀"
|
||||
introMisskey: "歡迎!CherryPick 是一個開源且去中心化的社群網路服務。\n發佈「貼文」向身邊的人分享您的想法!📡\n利用「反應」表達您對貼文的感覺!👍\n讓我們一起探索新的世界吧!🚀"
|
||||
poweredByMisskeyDescription: "{name}是使用開放原始碼平台<b>CherryPick</b>的服務之一(稱為 CherryPick 伺服器)。\n"
|
||||
monthAndDay: "{month}月 {day}日"
|
||||
search: "搜尋"
|
||||
|
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "cherrypick",
|
||||
"version": "13.14.0-beta.7-cp-4.2.0-beta.1",
|
||||
"version": "13.14.1-cp-4.2.0-beta.1",
|
||||
"codename": "nasubi",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/kokonect-link/cherrypick.git"
|
||||
},
|
||||
"packageManager": "pnpm@8.6.0",
|
||||
"packageManager": "pnpm@8.6.9",
|
||||
"workspaces": [
|
||||
"packages/frontend",
|
||||
"packages/backend",
|
||||
|
@ -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,
|
||||
|
@ -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}`
|
||||
@ -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)
|
||||
|
@ -191,6 +191,7 @@ import { claimAchievement } from '@/scripts/achievements';
|
||||
import { getNoteSummary } from '@/scripts/get-note-summary';
|
||||
import MkRippleEffect from '@/components/MkRippleEffect.vue';
|
||||
import { showMovedDialog } from '@/scripts/show-moved-dialog';
|
||||
import { shouldCollapsed, shouldMfmCollapsed } from '@/scripts/collapsed';
|
||||
import { eventBus } from '@/scripts/cherrypick/eventBus';
|
||||
import { mainRouter } from '@/router';
|
||||
import { notePage } from '@/filters/note';
|
||||
@ -238,19 +239,8 @@ 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.split('\n').length > 9) ||
|
||||
(appearNote.text.length > 500) ||
|
||||
(appearNote.files.length >= 5) ||
|
||||
(urls && urls.length >= 4)
|
||||
));
|
||||
const isMFM = (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'))
|
||||
));
|
||||
const isLong = shouldCollapsed(appearNote);
|
||||
const isMFM = shouldMfmCollapsed(appearNote);
|
||||
const collapsed = ref(appearNote.cw == null && (isLong || (isMFM && defaultStore.state.collapseDefault)));
|
||||
const isDeleted = ref(false);
|
||||
const muted = ref(checkWordMute(appearNote, $i, defaultStore.state.mutedWords));
|
||||
|
@ -32,10 +32,10 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button v-if="isLong && collapsed" :class="$style.fade" class="_button" @click="collapsed = false">
|
||||
<button v-if="(isLong || (isMFM && defaultStore.state.collapseDefault)) && collapsed" :class="$style.fade" class="_button" @click="collapsed = false">
|
||||
<span :class="$style.fadeLabel">{{ i18n.ts.showMore }}</span>
|
||||
</button>
|
||||
<button v-else-if="isLong && !collapsed" :class="$style.showLess" class="_button" @click="collapsed = true">
|
||||
<button v-else-if="(isLong || (isMFM && defaultStore.state.collapseDefault)) && !collapsed" :class="$style.showLess" class="_button" @click="collapsed = true">
|
||||
<span :class="$style.showLessLabel">{{ i18n.ts.showLess }}</span>
|
||||
</button>
|
||||
<div v-if="showSubNoteFooterButton">
|
||||
@ -101,6 +101,7 @@ import MkRippleEffect from '@/components/MkRippleEffect.vue';
|
||||
import MkReactionsViewer from "@/components/MkReactionsViewer.vue";
|
||||
import { i18n } from '@/i18n';
|
||||
import { $i } from '@/account';
|
||||
import { shouldCollapsed, shouldMfmCollapsed } from '@/scripts/collapsed';
|
||||
import { defaultStore } from '@/store';
|
||||
import { miLocalStorage } from '@/local-storage';
|
||||
import { instance } from '@/instance';
|
||||
@ -135,13 +136,10 @@ const props = defineProps<{
|
||||
|
||||
let note = $ref(deepClone(props.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 isMFM = shouldMfmCollapsed(props.note);
|
||||
|
||||
const collapsed = $ref(isLong);
|
||||
const collapsed = $ref(isLong || (isMFM && defaultStore.state.collapseDefault));
|
||||
|
||||
useNoteCapture({
|
||||
rootEl: el,
|
||||
|
@ -28,6 +28,7 @@ const common = {
|
||||
template: '<MkAd v-bind="props" />',
|
||||
};
|
||||
},
|
||||
/* FIXME: disabled because it still didn’t pass after applying #11267
|
||||
async play({ canvasElement, args }) {
|
||||
if (lock) {
|
||||
console.warn('This test is unexpectedly running twice in parallel, fix it!');
|
||||
@ -77,6 +78,7 @@ const common = {
|
||||
lock = undefined;
|
||||
}
|
||||
},
|
||||
*/
|
||||
args: {
|
||||
prefer: [],
|
||||
specify: {
|
||||
|
22
packages/frontend/src/scripts/collapsed.ts
Normal file
22
packages/frontend/src/scripts/collapsed.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import * as mfm from 'cherrypick-mfm-js';
|
||||
import * as misskey from 'cherrypick-js';
|
||||
import {extractUrlFromMfm} from './extract-url-from-mfm';
|
||||
|
||||
export function shouldCollapsed(note: misskey.entities.Note): boolean {
|
||||
const urls = note.text ? extractUrlFromMfm(mfm.parse(note.text)) : null;
|
||||
return note.cw == null && note.text != null && (
|
||||
(note.text.split('\n').length > 9) ||
|
||||
(note.text.length > 500) ||
|
||||
(note.files.length >= 5) ||
|
||||
(!!urls && urls.length >= 4)
|
||||
);
|
||||
}
|
||||
|
||||
export function shouldMfmCollapsed(note: misskey.entities.Note): boolean {
|
||||
return note.cw == null && note.text != null && (
|
||||
(note.text.includes('$[x2')) ||
|
||||
(note.text.includes('$[x3')) ||
|
||||
(note.text.includes('$[x4')) ||
|
||||
(note.text.includes('$[scale'))
|
||||
);
|
||||
}
|
@ -1,3 +1,20 @@
|
||||
const requestIdleCallback: typeof globalThis.requestIdleCallback = globalThis.requestIdleCallback ?? ((callback) => {
|
||||
const start = performance.now();
|
||||
const timeoutId = setTimeout(() => {
|
||||
callback({
|
||||
didTimeout: false, // polyfill でタイムアウト発火することはない
|
||||
timeRemaining() {
|
||||
const diff = performance.now() - start;
|
||||
return Math.max(0, 50 - diff); // <https://www.w3.org/TR/requestidlecallback/#idle-periods>
|
||||
},
|
||||
});
|
||||
});
|
||||
return timeoutId;
|
||||
});
|
||||
const cancelIdleCallback: typeof globalThis.cancelIdleCallback = globalThis.cancelIdleCallback ?? ((timeoutId) => {
|
||||
clearTimeout(timeoutId);
|
||||
});
|
||||
|
||||
class IdlingRenderScheduler {
|
||||
#renderers: Set<FrameRequestCallback>;
|
||||
#rafId: number;
|
||||
|
Loading…
Reference in New Issue
Block a user