Compare commits
8 Commits
fda1cc985f
...
4998f349bf
| Author | SHA1 | Date |
|---|---|---|
|
|
4998f349bf | |
|
|
85078601c2 | |
|
|
b434beb5e2 | |
|
|
295665a177 | |
|
|
a25620e4bc | |
|
|
fd7d7318a7 | |
|
|
054ba3fea5 | |
|
|
8749716700 |
|
|
@ -22,6 +22,7 @@
|
|||
- お知らせのアイコンを設定可能に
|
||||
- チャンネルをセンシティブ指定できるようになりました
|
||||
- センシティブチャンネルのNoteのReNoteはデフォルトでHome TLに流れるようになりました
|
||||
- センシティブチャンネルのノートはユーザープロフィールに表示されません
|
||||
- 二要素認証のバックアップコードが生成されるようになりました ref. https://github.com/MisskeyIO/misskey/pull/121
|
||||
- 二要素認証でパスキーをサポートするようになりました
|
||||
|
||||
|
|
@ -30,7 +31,6 @@
|
|||
- メニューのスイッチの動作を改善
|
||||
- 絵文字ピッカーの検索の表示件数を100件に増加
|
||||
- 投稿フォームのプレビューの表示状態を記憶するように
|
||||
- ノート詳細ページ読み込み時のパフォーマンスを改善
|
||||
- AiScriptからMisskeyサーバーAPIを呼び出す際の制限を撤廃
|
||||
- Playで直接投稿フォームを埋め込めるように(`Ui:C:postForm`)
|
||||
- Enhance: ユーザーメニューでスイッチでユーザーリストに追加・削除できるように
|
||||
|
|
@ -42,6 +42,9 @@
|
|||
- Enhance: Renoteを管理者権限で削除可能に
|
||||
- `$[rainbow ]`記法が、動きのあるMFMが無効になっていても使用できるようになりました
|
||||
- Playの操作を行うAPI TokenをAPIコンソールから発行できるように
|
||||
- リアクションの表示サイズをより大きくできるように
|
||||
- ノート詳細ページ読み込み時のパフォーマンスを改善
|
||||
- タイムラインでリスト/アンテナ選択時のパフォーマンスを改善
|
||||
- Fix: サーバー情報画面(`/instance-info/{domain}`)でブロックができないのを修正
|
||||
- Fix: 未読のお知らせの「わかった」をクリック・タップしてもその場で「わかった」が消えない問題を修正
|
||||
- Fix: iOSで画面を回転させるとテキストサイズが変わる問題を修正
|
||||
|
|
@ -51,13 +54,14 @@
|
|||
- Fix: 他のサーバーのユーザーへ「メッセージを送信」した時の初期テキストのメンションが間違っている問題を修正
|
||||
|
||||
### Server
|
||||
- Fix: ノート検索 `notes/search` にてhostを指定した際に検索結果に反映されるように
|
||||
- cacheRemoteFilesの初期値はfalseになりました
|
||||
- ファイルアップロード時等にファイル名の拡張子を修正する関数(correctFilename)の挙動を改善
|
||||
- Webhookのペイロードにサーバーのurlが含まれるようになりました
|
||||
- Webhook設定でsecretを空に出来るように
|
||||
- 使われていないアンテナの自動停止を設定可能に
|
||||
- nodeinfo 2.1対応
|
||||
- 自分へのメンション一覧を取得する際のパフォーマンスを向上
|
||||
- Fix: ノート検索 `notes/search` にてhostを指定した際に検索結果に反映されるように
|
||||
- Fix: 一部のfeatured noteを照会できない問題を修正
|
||||
- Fix: muteがapiからのuser list timeline取得で機能しない問題を修正
|
||||
- Fix: ジョブキュー管理画面の認証を回避できる問題を修正
|
||||
|
|
|
|||
|
|
@ -1026,7 +1026,7 @@ export interface Locale {
|
|||
"enableChartsForRemoteUser": string;
|
||||
"enableChartsForFederatedInstances": string;
|
||||
"showClipButtonInNoteFooter": string;
|
||||
"largeNoteReactions": string;
|
||||
"reactionsDisplaySize": string;
|
||||
"noteIdOrUrl": string;
|
||||
"video": string;
|
||||
"videos": string;
|
||||
|
|
|
|||
|
|
@ -1023,7 +1023,7 @@ retryAllQueuesConfirmText: "一時的にサーバーの負荷が増大するこ
|
|||
enableChartsForRemoteUser: "リモートユーザーのチャートを生成"
|
||||
enableChartsForFederatedInstances: "リモートサーバーのチャートを生成"
|
||||
showClipButtonInNoteFooter: "ノートのアクションにクリップを追加"
|
||||
largeNoteReactions: "ノートのリアクションを大きく表示"
|
||||
reactionsDisplaySize: "リアクションの表示サイズ"
|
||||
noteIdOrUrl: "ノートIDまたはURL"
|
||||
video: "動画"
|
||||
videos: "動画"
|
||||
|
|
|
|||
|
|
@ -35,10 +35,10 @@ export class NodeinfoServerService {
|
|||
|
||||
@bindThis
|
||||
public getLinks() {
|
||||
return [/* (awaiting release) {
|
||||
rel: 'http://nodeinfo.diaspora.software/ns/schema/2.1',
|
||||
href: config.url + nodeinfo2_1path
|
||||
}, */{
|
||||
return [{
|
||||
rel: 'http://nodeinfo.diaspora.software/ns/schema/2.1',
|
||||
href: this.config.url + nodeinfo2_1path
|
||||
}, {
|
||||
rel: 'http://nodeinfo.diaspora.software/ns/schema/2.0',
|
||||
href: this.config.url + nodeinfo2_0path,
|
||||
}];
|
||||
|
|
@ -46,7 +46,7 @@ export class NodeinfoServerService {
|
|||
|
||||
@bindThis
|
||||
public createServer(fastify: FastifyInstance, options: FastifyPluginOptions, done: (err?: Error) => void) {
|
||||
const nodeinfo2 = async () => {
|
||||
const nodeinfo2 = async (version: number) => {
|
||||
const now = Date.now();
|
||||
|
||||
const notesChart = await this.notesChart.getChart('hour', 1, null);
|
||||
|
|
@ -73,11 +73,11 @@ export class NodeinfoServerService {
|
|||
|
||||
const basePolicies = { ...DEFAULT_POLICIES, ...meta.policies };
|
||||
|
||||
return {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const document: any = {
|
||||
software: {
|
||||
name: 'misskey',
|
||||
version: this.config.version,
|
||||
repository: meta.repositoryUrl,
|
||||
},
|
||||
protocols: ['activitypub'],
|
||||
services: {
|
||||
|
|
@ -114,23 +114,36 @@ export class NodeinfoServerService {
|
|||
themeColor: meta.themeColor ?? '#86b300',
|
||||
},
|
||||
};
|
||||
if (version >= 21) {
|
||||
document.software.repository = meta.repositoryUrl;
|
||||
document.software.homepage = meta.repositoryUrl;
|
||||
}
|
||||
return document;
|
||||
};
|
||||
|
||||
const cache = new MemorySingleCache<Awaited<ReturnType<typeof nodeinfo2>>>(1000 * 60 * 10);
|
||||
|
||||
fastify.get(nodeinfo2_1path, async (request, reply) => {
|
||||
const base = await cache.fetch(() => nodeinfo2());
|
||||
const base = await cache.fetch(() => nodeinfo2(21));
|
||||
|
||||
reply.header('Cache-Control', 'public, max-age=600');
|
||||
reply
|
||||
.type(
|
||||
'application/json; profile="http://nodeinfo.diaspora.software/ns/schema/2.1#"',
|
||||
)
|
||||
.header('Cache-Control', 'public, max-age=600');
|
||||
return { version: '2.1', ...base };
|
||||
});
|
||||
|
||||
fastify.get(nodeinfo2_0path, async (request, reply) => {
|
||||
const base = await cache.fetch(() => nodeinfo2());
|
||||
const base = await cache.fetch(() => nodeinfo2(20));
|
||||
|
||||
delete (base as any).software.repository;
|
||||
|
||||
reply.header('Cache-Control', 'public, max-age=600');
|
||||
reply
|
||||
.type(
|
||||
'application/json; profile="http://nodeinfo.diaspora.software/ns/schema/2.0#"',
|
||||
)
|
||||
.header('Cache-Control', 'public, max-age=600');
|
||||
return { version: '2.0', ...base };
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -80,9 +80,12 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
.innerJoinAndSelect('note.user', 'user')
|
||||
.leftJoinAndSelect('note.reply', 'reply')
|
||||
.leftJoinAndSelect('note.renote', 'renote')
|
||||
.leftJoinAndSelect('note.channel', 'channel')
|
||||
.leftJoinAndSelect('reply.user', 'replyUser')
|
||||
.leftJoinAndSelect('renote.user', 'renoteUser');
|
||||
|
||||
query.andWhere('channel.isSensitive = false');
|
||||
|
||||
this.queryService.generateVisibilityQuery(query, me);
|
||||
if (me) {
|
||||
this.queryService.generateMutedUserQuery(query, me, user);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
ref="buttonEl"
|
||||
v-ripple="canToggle"
|
||||
class="_button"
|
||||
:class="[$style.root, { [$style.reacted]: note.myReaction == reaction, [$style.canToggle]: canToggle, [$style.large]: defaultStore.state.largeNoteReactions }]"
|
||||
:class="[$style.root, { [$style.reacted]: note.myReaction == reaction, [$style.canToggle]: canToggle, [$style.small]: defaultStore.state.reactionsDisplaySize === 'small', [$style.large]: defaultStore.state.reactionsDisplaySize === 'large' }]"
|
||||
@click="toggleReaction()"
|
||||
>
|
||||
<MkReactionIcon :class="$style.icon" :reaction="reaction" :emojiUrl="note.reactionEmojis[reaction.substring(1, reaction.length - 1)]"/>
|
||||
|
|
@ -115,10 +115,11 @@ useTooltip(buttonEl, async (showing) => {
|
|||
<style lang="scss" module>
|
||||
.root {
|
||||
display: inline-block;
|
||||
height: 32px;
|
||||
height: 42px;
|
||||
margin: 2px;
|
||||
padding: 0 6px;
|
||||
border-radius: 4px;
|
||||
font-size: 1.5em;
|
||||
border-radius: 6px;
|
||||
|
||||
&.canToggle {
|
||||
background: var(--buttonBg);
|
||||
|
|
@ -132,14 +133,25 @@ useTooltip(buttonEl, async (showing) => {
|
|||
cursor: default;
|
||||
}
|
||||
|
||||
&.large {
|
||||
height: 42px;
|
||||
font-size: 1.5em;
|
||||
border-radius: 6px;
|
||||
&.small {
|
||||
height: 32px;
|
||||
font-size: 1em;
|
||||
border-radius: 4px;
|
||||
|
||||
> .count {
|
||||
font-size: 0.7em;
|
||||
line-height: 42px;
|
||||
font-size: 0.9em;
|
||||
line-height: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
&.large {
|
||||
height: 52px;
|
||||
font-size: 2em;
|
||||
border-radius: 8px;
|
||||
|
||||
> .count {
|
||||
font-size: 0.6em;
|
||||
line-height: 52px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -159,8 +171,8 @@ useTooltip(buttonEl, async (showing) => {
|
|||
}
|
||||
|
||||
.count {
|
||||
font-size: 0.9em;
|
||||
line-height: 32px;
|
||||
font-size: 0.7em;
|
||||
line-height: 42px;
|
||||
margin: 0 0 0 4px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ type Keys =
|
|||
'message_drafts' |
|
||||
'scratchpad' |
|
||||
'debug' |
|
||||
'userListsCache' |
|
||||
'antennasCache' |
|
||||
`miux:${string}` |
|
||||
`ui:folder:${string}` |
|
||||
`themes:${string}` |
|
||||
|
|
@ -41,4 +43,12 @@ export const miLocalStorage = {
|
|||
getItem: (key: Keys): string | null => window.localStorage.getItem(key),
|
||||
setItem: (key: Keys, value: string): void => window.localStorage.setItem(key, value),
|
||||
removeItem: (key: Keys): void => window.localStorage.removeItem(key),
|
||||
getItemAsJson: (key: Keys): any | undefined => {
|
||||
const item = miLocalStorage.getItem(key);
|
||||
if (item === null) {
|
||||
return undefined;
|
||||
}
|
||||
return JSON.parse(item);
|
||||
},
|
||||
setItemAsJson: (key: Keys, value: any): void => window.localStorage.setItem(key, JSON.stringify(value)),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -40,13 +40,18 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<div class="_gaps_s">
|
||||
<MkSwitch v-model="showNoteActionsOnlyHover">{{ i18n.ts.showNoteActionsOnlyHover }}</MkSwitch>
|
||||
<MkSwitch v-model="showClipButtonInNoteFooter">{{ i18n.ts.showClipButtonInNoteFooter }}</MkSwitch>
|
||||
<MkSwitch v-model="largeNoteReactions">{{ i18n.ts.largeNoteReactions }}</MkSwitch>
|
||||
<MkSwitch v-model="collapseRenotes">{{ i18n.ts.collapseRenotes }}</MkSwitch>
|
||||
<MkSwitch v-model="advancedMfm">{{ i18n.ts.enableAdvancedMfm }}</MkSwitch>
|
||||
<MkSwitch v-if="advancedMfm" v-model="animatedMfm">{{ i18n.ts.enableAnimatedMfm }}</MkSwitch>
|
||||
<MkSwitch v-model="showGapBetweenNotesInTimeline">{{ i18n.ts.showGapBetweenNotesInTimeline }}</MkSwitch>
|
||||
<MkSwitch v-model="loadRawImages">{{ i18n.ts.loadRawImages }}</MkSwitch>
|
||||
<MkSwitch v-model="useReactionPickerForContextMenu">{{ i18n.ts.useReactionPickerForContextMenu }}</MkSwitch>
|
||||
<MkRadios v-model="reactionsDisplaySize">
|
||||
<template #label>{{ i18n.ts.reactionsDisplaySize }}</template>
|
||||
<option value="small">{{ i18n.ts.small }}</option>
|
||||
<option value="medium">{{ i18n.ts.medium }}</option>
|
||||
<option value="large">{{ i18n.ts.large }}</option>
|
||||
</MkRadios>
|
||||
</div>
|
||||
|
||||
<MkSelect v-model="instanceTicker">
|
||||
|
|
@ -204,7 +209,7 @@ const overridedDeviceKind = computed(defaultStore.makeGetterSetter('overridedDev
|
|||
const serverDisconnectedBehavior = computed(defaultStore.makeGetterSetter('serverDisconnectedBehavior'));
|
||||
const showNoteActionsOnlyHover = computed(defaultStore.makeGetterSetter('showNoteActionsOnlyHover'));
|
||||
const showClipButtonInNoteFooter = computed(defaultStore.makeGetterSetter('showClipButtonInNoteFooter'));
|
||||
const largeNoteReactions = computed(defaultStore.makeGetterSetter('largeNoteReactions'));
|
||||
const reactionsDisplaySize = computed(defaultStore.makeGetterSetter('reactionsDisplaySize'));
|
||||
const collapseRenotes = computed(defaultStore.makeGetterSetter('collapseRenotes'));
|
||||
const reduceAnimation = computed(defaultStore.makeGetterSetter('animation', v => !v, v => !v));
|
||||
const useBlurEffectForModal = computed(defaultStore.makeGetterSetter('useBlurEffectForModal'));
|
||||
|
|
@ -264,6 +269,7 @@ watch([
|
|||
instanceTicker,
|
||||
overridedDeviceKind,
|
||||
mediaListWithOneImageAppearance,
|
||||
reactionsDisplaySize,
|
||||
], async () => {
|
||||
await reloadAsk();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ import { i18n } from '@/i18n';
|
|||
import { instance } from '@/instance';
|
||||
import { $i } from '@/account';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata';
|
||||
import { miLocalStorage } from '@/local-storage';
|
||||
|
||||
provide('shouldOmitHeaderTitle', true);
|
||||
|
||||
|
|
@ -67,17 +68,24 @@ function top(): void {
|
|||
}
|
||||
|
||||
async function chooseList(ev: MouseEvent): Promise<void> {
|
||||
const lists = await os.api('users/lists/list');
|
||||
const cachedLists = miLocalStorage.getItemAsJson('userListsCache');
|
||||
const lists = cachedLists ?? await os.api('users/lists/list');
|
||||
const items = lists.map(list => ({
|
||||
type: 'link' as const,
|
||||
text: list.name,
|
||||
to: `/timeline/list/${list.id}`,
|
||||
}));
|
||||
os.popupMenu(items, ev.currentTarget ?? ev.target);
|
||||
if (cachedLists == null) {
|
||||
miLocalStorage.setItemAsJson('userListsCache', lists);
|
||||
} else {
|
||||
miLocalStorage.setItemAsJson('userListsCache', await os.api('users/lists/list'));
|
||||
}
|
||||
}
|
||||
|
||||
async function chooseAntenna(ev: MouseEvent): Promise<void> {
|
||||
const antennas = await os.api('antennas/list');
|
||||
const cachedAntennas = miLocalStorage.getItemAsJson('antennasCache');
|
||||
const antennas = cachedAntennas ?? await os.api('antennas/list');
|
||||
const items = antennas.map(antenna => ({
|
||||
type: 'link' as const,
|
||||
text: antenna.name,
|
||||
|
|
@ -85,6 +93,11 @@ async function chooseAntenna(ev: MouseEvent): Promise<void> {
|
|||
to: `/timeline/antenna/${antenna.id}`,
|
||||
}));
|
||||
os.popupMenu(items, ev.currentTarget ?? ev.target);
|
||||
if (cachedAntennas == null) {
|
||||
miLocalStorage.setItemAsJson('antennasCache', antennas);
|
||||
} else {
|
||||
miLocalStorage.setItemAsJson('antennasCache', await os.api('antennas/list'));
|
||||
}
|
||||
}
|
||||
|
||||
async function chooseChannel(ev: MouseEvent): Promise<void> {
|
||||
|
|
|
|||
|
|
@ -316,9 +316,9 @@ export const defaultStore = markRaw(new Storage('base', {
|
|||
where: 'device',
|
||||
default: false,
|
||||
},
|
||||
largeNoteReactions: {
|
||||
reactionsDisplaySize: {
|
||||
where: 'device',
|
||||
default: false,
|
||||
default: 'medium' as 'small' | 'medium' | 'large',
|
||||
},
|
||||
forceShowAds: {
|
||||
where: 'device',
|
||||
|
|
|
|||
Loading…
Reference in New Issue