Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0d46089f9a | |||
| 78348007ed | |||
| 92f1e599db | |||
| 26b5979c76 | |||
| b1048525d2 | |||
| 4c31eb409c | |||
| f739cb6270 | |||
| 7420c10a58 | |||
| e40c84f31d | |||
| 994fc062cf | |||
| e7681f6c79 | |||
| 19053339d9 | |||
| b4e16c83e2 | |||
| 56cc89b521 | |||
| 1eab314b17 | |||
| ec21336d45 | |||
| e86e9b46b3 | |||
| 9b729b3d25 | |||
| 3c973e21f2 | |||
| 830e2f0a5b | |||
| 1620477a1c | |||
| 92b9a5218d | |||
| 9ed0d5ccec | |||
| a6d1727205 | |||
| 3c3982464f | |||
| bef73ff530 | |||
| 4d31c0b1de | |||
| a5f28c21e4 | |||
| c93ead7474 | |||
| 36880493cb | |||
| e8518de054 | |||
| b99e13e667 | |||
| 2518cf36d0 |
@@ -14,14 +14,17 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
|
||||
### Client
|
||||
- Enhance: デッキのUI説明を追加
|
||||
- Enhance: 設定がブラウザによって消去されないようにするオプションを追加
|
||||
- Fix: バージョン表記のないPlayが正しく動作しない問題を修正
|
||||
バージョン表記のないものは v0.x 系として実行されます。v1.x 系で動作させたい場合は必ずバージョン表記を含めてください。
|
||||
- Fix: デッキUIでメニュー位置を下にしているとプロファイル削除ボタンが表示されないのを修正
|
||||
- Fix: 一部のUnicode絵文字のリアクションがボタンにならない問題を修正
|
||||
|
||||
### Server
|
||||
- Enhance: Misskey内部でのIPアドレスペースでのレートリミットを無効化できるように
|
||||
- リバースプロキシやCDNなど別のレイヤで別途レートリミットを設定する場合や、ローカルでのテスト用途等として利用することを想定しています。
|
||||
- デフォルトは `enableIpRateLimit: true`(Misskey内部でのIPアドレスペースでのレートリミットは有効)です。
|
||||
- Fix: コントロールパネルのジョブキューページで使用される一部APIの応答速度を改善
|
||||
|
||||
## 2025.12.1
|
||||
|
||||
|
||||
@@ -1557,6 +1557,9 @@ _settings:
|
||||
showPageTabBarBottom: "ページのタブバーを下部に表示"
|
||||
emojiPaletteBanner: "絵文字ピッカーに固定表示するプリセットをパレットとして登録したり、ピッカーの表示方法をカスタマイズしたりできます。"
|
||||
enableAnimatedImages: "アニメーション画像を有効にする"
|
||||
settingsPersistence_title: "設定の永続化"
|
||||
settingsPersistence_description1: "設定の永続化を有効にすると、設定情報が失われるのを防止できます。"
|
||||
settingsPersistence_description2: "環境によっては有効化できない場合があります。"
|
||||
|
||||
_chat:
|
||||
showSenderName: "送信者の名前を表示"
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "misskey",
|
||||
"version": "2025.12.2-beta.3",
|
||||
"version": "2025.12.2",
|
||||
"codename": "nasubi",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -52,18 +52,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||
super(meta, paramDef, async (ps, me) => {
|
||||
const jobs = await this.deliverQueue.getJobs(['delayed']);
|
||||
|
||||
const res = [] as [string, number][];
|
||||
const counts = new Map<string, number>();
|
||||
|
||||
for (const job of jobs) {
|
||||
const host = new URL(job.data.to).host;
|
||||
if (res.find(x => x[0] === host)) {
|
||||
res.find(x => x[0] === host)![1]++;
|
||||
} else {
|
||||
res.push([host, 1]);
|
||||
}
|
||||
counts.set(host, (counts.get(host) ?? 0) + 1);
|
||||
}
|
||||
|
||||
res.sort((a, b) => b[1] - a[1]);
|
||||
const res = [...counts.entries()].sort((a, b) => b[1] - a[1]);
|
||||
|
||||
return res;
|
||||
});
|
||||
|
||||
@@ -52,18 +52,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||
super(meta, paramDef, async (ps, me) => {
|
||||
const jobs = await this.inboxQueue.getJobs(['delayed']);
|
||||
|
||||
const res = [] as [string, number][];
|
||||
const counts = new Map<string, number>();
|
||||
|
||||
for (const job of jobs) {
|
||||
const host = new URL(job.data.signature.keyId).host;
|
||||
if (res.find(x => x[0] === host)) {
|
||||
res.find(x => x[0] === host)![1]++;
|
||||
} else {
|
||||
res.push([host, 1]);
|
||||
}
|
||||
counts.set(host, (counts.get(host) ?? 0) + 1);
|
||||
}
|
||||
|
||||
res.sort((a, b) => b[1] - a[1]);
|
||||
const res = [...counts.entries()].sort((a, b) => b[1] - a[1]);
|
||||
|
||||
return res;
|
||||
});
|
||||
|
||||
@@ -41,7 +41,7 @@ export const emojiCharByCategory = _charGroupByCategory;
|
||||
|
||||
export function getUnicodeEmojiOrNull(char: string): UnicodeEmojiDef | null {
|
||||
// Colorize it because emojilist.json assumes that
|
||||
return unicodeEmojisMap.get(colorizeEmoji(char))
|
||||
return unicodeEmojisMap.get(forceColorizeEmoji(char))
|
||||
// カラースタイル絵文字がjsonに無い場合はテキストスタイル絵文字にフォールバックする
|
||||
?? unicodeEmojisMap.get(char)
|
||||
// それでも見つからない場合はnullを返す
|
||||
@@ -54,12 +54,12 @@ export function getUnicodeEmoji(char: string): UnicodeEmojiDef | string {
|
||||
}
|
||||
|
||||
export function isSupportedEmoji(char: string): boolean {
|
||||
return unicodeEmojisMap.has(colorizeEmoji(char)) || unicodeEmojisMap.has(char);
|
||||
return unicodeEmojisMap.has(forceColorizeEmoji(char)) || unicodeEmojisMap.has(char);
|
||||
}
|
||||
|
||||
export function getEmojiName(char: string): string {
|
||||
// Colorize it because emojilist.json assumes that
|
||||
const idx = _indexByChar.get(colorizeEmoji(char)) ?? _indexByChar.get(char);
|
||||
const idx = _indexByChar.get(forceColorizeEmoji(char)) ?? _indexByChar.get(char);
|
||||
if (idx === undefined) {
|
||||
// 絵文字情報がjsonに無い場合は名前の取得が出来ないのでそのまま返すしか無い
|
||||
return char;
|
||||
@@ -72,7 +72,24 @@ export function getEmojiName(char: string): string {
|
||||
* テキストスタイル絵文字(U+260Eなどの1文字で表現される絵文字)をカラースタイル絵文字に変換します(VS16:U+FE0Fを付与)。
|
||||
*/
|
||||
export function colorizeEmoji(char: string) {
|
||||
return char.length === 1 ? `${char}\uFE0F` : char;
|
||||
// <文字列>.length はコードポイント数ではなくUTF-16コードユニット数を返すため、サロゲートペアを含む絵文字で誤動作する。
|
||||
// そのため、配列に変換してコードポイント数を数える方法を取る。
|
||||
return Array.from(char).length === 1 ? `${char}\uFE0F` : char;
|
||||
}
|
||||
|
||||
/**
|
||||
* 文字種にかかわらず、カラースタイル絵文字への変換を試みます(本ファイルにある検索プログラム用・フォールバックが必須)。
|
||||
*/
|
||||
function forceColorizeEmoji(char: string) {
|
||||
// <文字列>.length はコードポイント数ではなくUTF-16コードユニット数を返すため、サロゲートペアを含む絵文字で誤動作する。
|
||||
// そのため、配列に変換してコードポイント数を数える方法を取る。
|
||||
const chars = Array.from(char);
|
||||
if (chars.includes('\uFE0F')) {
|
||||
return char;
|
||||
} else {
|
||||
chars.splice(1, 0, '\uFE0F');
|
||||
return chars.join('');
|
||||
}
|
||||
}
|
||||
|
||||
export interface CustomEmojiFolderTree {
|
||||
|
||||
@@ -11,6 +11,11 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
<div v-if="!narrow || currentPage?.route.name == null" class="nav">
|
||||
<div class="_gaps_s">
|
||||
<MkInfo v-if="emailNotConfigured" warn class="info">{{ i18n.ts.emailNotConfiguredWarning }} <MkA to="/settings/email" class="_link">{{ i18n.ts.configure }}</MkA></MkInfo>
|
||||
<MkInfo v-if="!storagePersisted && store.r.showStoragePersistenceSuggestion.value" class="info">
|
||||
<div>{{ i18n.ts._settings.settingsPersistence_description1 }}</div>
|
||||
<div>{{ i18n.ts._settings.settingsPersistence_description2 }}</div>
|
||||
<div><button class="_textButton" @click="enableStoragePersistence">{{ i18n.ts.enable }}</button> | <button class="_textButton" @click="skipStoragePersistence">{{ i18n.ts.skip }}</button></div>
|
||||
</MkInfo>
|
||||
<MkInfo v-if="!store.r.enablePreferencesAutoCloudBackup.value && store.r.showPreferencesAutoCloudBackupSuggestion.value" class="info">
|
||||
<div>{{ i18n.ts._preferencesBackup.autoPreferencesBackupIsNotEnabledForThisDevice }}</div>
|
||||
<div><button class="_textButton" @click="enableAutoBackup">{{ i18n.ts.enable }}</button> | <button class="_textButton" @click="skipAutoBackup">{{ i18n.ts.skip }}</button></div>
|
||||
@@ -46,6 +51,7 @@ import { enableAutoBackup, getPreferencesProfileMenu } from '@/preferences/utili
|
||||
import { store } from '@/store.js';
|
||||
import { signout } from '@/signout.js';
|
||||
import { genSearchIndexes } from '@/utility/inapp-search.js';
|
||||
import { enableStoragePersistence, storagePersisted, skipStoragePersistence } from '@/utility/storage.js';
|
||||
|
||||
const searchIndex = await import('search-index:settings').then(({ searchIndexes }) => genSearchIndexes(searchIndexes));
|
||||
|
||||
|
||||
@@ -142,6 +142,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
<hr>
|
||||
</template>
|
||||
|
||||
<MkButton v-if="!storagePersisted" @click="enableStoragePersistence">{{ i18n.ts._settings.settingsPersistence_title }}</MkButton>
|
||||
|
||||
<MkButton @click="forceCloudBackup">{{ i18n.ts._preferencesBackup.forceBackup }}</MkButton>
|
||||
|
||||
<FormSlot>
|
||||
@@ -163,7 +165,7 @@ import MkKeyValue from '@/components/MkKeyValue.vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import FormSlot from '@/components/form/slot.vue';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import { enableStoragePersistence, storagePersisted, skipStoragePersistence } from '@/utility/storage.js';
|
||||
import { ensureSignin } from '@/i.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePage } from '@/page.js';
|
||||
|
||||
@@ -118,6 +118,10 @@ export const store = markRaw(new Pizzax('base', {
|
||||
where: 'device',
|
||||
default: true,
|
||||
},
|
||||
showStoragePersistenceSuggestion: {
|
||||
where: 'device',
|
||||
default: true,
|
||||
},
|
||||
|
||||
//#region TODO: そのうち消す (preferに移行済み)
|
||||
defaultWithReplies: {
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { computed, ref, shallowRef, watch, defineAsyncComponent } from 'vue';
|
||||
import * as os from '@/os.js';
|
||||
import { store } from '@/store.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
|
||||
export const storagePersisted = ref(await navigator.storage.persisted());
|
||||
|
||||
export async function enableStoragePersistence() {
|
||||
try {
|
||||
const persisted = await navigator.storage.persist();
|
||||
if (persisted) {
|
||||
storagePersisted.value = true;
|
||||
} else {
|
||||
os.alert({
|
||||
type: 'error',
|
||||
text: i18n.ts.somethingHappened,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
os.alert({
|
||||
type: 'error',
|
||||
text: i18n.ts.somethingHappened,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function skipStoragePersistence() {
|
||||
store.set('showStoragePersistenceSuggestion', false);
|
||||
}
|
||||
@@ -6193,6 +6193,18 @@ export interface Locale extends ILocale {
|
||||
* アニメーション画像を有効にする
|
||||
*/
|
||||
"enableAnimatedImages": string;
|
||||
/**
|
||||
* 設定の永続化
|
||||
*/
|
||||
"settingsPersistence_title": string;
|
||||
/**
|
||||
* 設定の永続化を有効にすると、設定情報が失われるのを防止できます。
|
||||
*/
|
||||
"settingsPersistence_description1": string;
|
||||
/**
|
||||
* 環境によっては有効化できない場合があります。
|
||||
*/
|
||||
"settingsPersistence_description2": string;
|
||||
"_chat": {
|
||||
/**
|
||||
* 送信者の名前を表示
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"type": "module",
|
||||
"name": "misskey-js",
|
||||
"version": "2025.12.2-beta.3",
|
||||
"version": "2025.12.2",
|
||||
"description": "Misskey SDK for JavaScript",
|
||||
"license": "MIT",
|
||||
"main": "./built/index.js",
|
||||
|
||||
Reference in New Issue
Block a user