Merge branch 'develop' into sensitive-channel-mute
This commit is contained in:
commit
fbefba7f0f
|
|
@ -9,8 +9,10 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
|||
- 依存関係の更新
|
||||
|
||||
### Client
|
||||
- Enhance: デッキのUI説明を追加
|
||||
- Fix: バージョン表記のないPlayが正しく動作しない問題を修正
|
||||
バージョン表記のないものは v0.x 系として実行されます。v1.x 系で動作させたい場合は必ずバージョン表記を含めてください。
|
||||
- Fix: デッキUIでメニュー位置を下にしているとプロファイル削除ボタンが表示されないのを修正
|
||||
- Enhance: センシティブチャンネルの投稿が多くの場所で畳まれるようになりました
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2893,6 +2893,15 @@ _deck:
|
|||
usedAsMinWidthWhenFlexible: "「幅を自動調整」が有効の場合、これが幅の最小値となります"
|
||||
flexible: "幅を自動調整"
|
||||
enableSyncBetweenDevicesForProfiles: "プロファイル情報のデバイス間同期を有効にする"
|
||||
showHowToUse: "UIの説明を見る"
|
||||
|
||||
_howToUse:
|
||||
addColumn_title: "カラム追加"
|
||||
addColumn_description: "カラムの種類を選んで追加できます。"
|
||||
settings_title: "UI設定"
|
||||
settings_description: "デッキUIの詳細設定を行えます。"
|
||||
switchProfile_title: "プロファイル切り替え"
|
||||
switchProfile_description: "UIのレイアウトをプロファイルとして保存し、いつでも切り替えられるようにできます。"
|
||||
|
||||
_columns:
|
||||
main: "メイン"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "misskey",
|
||||
"version": "2025.12.2-beta.1",
|
||||
"version": "2025.12.2-beta.2",
|
||||
"codename": "nasubi",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import * as fs from 'node:fs';
|
|||
import { fileURLToPath } from 'node:url';
|
||||
import { dirname } from 'node:path';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import si from 'systeminformation';
|
||||
import { Mutex } from 'async-mutex';
|
||||
import fetch from 'node-fetch';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
|
|
@ -84,6 +83,7 @@ export class AiService {
|
|||
|
||||
@bindThis
|
||||
private async getCpuFlags(): Promise<string[]> {
|
||||
const si = await import('systeminformation');
|
||||
const str = await si.cpuFlags();
|
||||
return str.split(/\s+/);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,13 +4,12 @@
|
|||
*/
|
||||
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import si from 'systeminformation';
|
||||
import Xev from 'xev';
|
||||
import * as osUtils from 'os-utils';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import type { OnApplicationShutdown } from '@nestjs/common';
|
||||
import { MiMeta } from '@/models/_.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { OnApplicationShutdown } from '@nestjs/common';
|
||||
|
||||
const ev = new Xev();
|
||||
|
||||
|
|
@ -97,12 +96,14 @@ function cpuUsage(): Promise<number> {
|
|||
|
||||
// MEMORY STAT
|
||||
async function mem() {
|
||||
const si = await import('systeminformation');
|
||||
const data = await si.mem();
|
||||
return data;
|
||||
}
|
||||
|
||||
// NETWORK STAT
|
||||
async function net() {
|
||||
const si = await import('systeminformation');
|
||||
const iface = await si.networkInterfaceDefault();
|
||||
const data = await si.networkStats(iface);
|
||||
return data[0];
|
||||
|
|
@ -110,5 +111,6 @@ async function net() {
|
|||
|
||||
// FS STAT
|
||||
async function fs() {
|
||||
const si = await import('systeminformation');
|
||||
return await si.disksIO().catch(() => ({ rIO_sec: 0, wIO_sec: 0 }));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,15 +4,11 @@
|
|||
*/
|
||||
|
||||
import * as os from 'node:os';
|
||||
import sysUtils from 'systeminformation';
|
||||
import type Logger from '@/logger.js';
|
||||
|
||||
export async function showMachineInfo(parentLogger: Logger) {
|
||||
const logger = parentLogger.createSubLogger('machine');
|
||||
logger.debug(`Hostname: ${os.hostname()}`);
|
||||
logger.debug(`Platform: ${process.platform} Arch: ${process.arch}`);
|
||||
const mem = await sysUtils.mem();
|
||||
const totalmem = (mem.total / 1024 / 1024 / 1024).toFixed(1);
|
||||
const availmem = (mem.available / 1024 / 1024 / 1024).toFixed(1);
|
||||
logger.debug(`CPU: ${os.cpus().length} core MEM: ${totalmem}GB (available: ${availmem}GB)`);
|
||||
logger.debug(`CPU: ${os.cpus().length} core MEM: ${(os.totalmem() / 1024 / 1024 / 1024).toFixed(1)}GB (available: ${(os.freemem() / 1024 / 1024 / 1024).toFixed(1)}GB)`);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
*/
|
||||
|
||||
import * as os from 'node:os';
|
||||
import si from 'systeminformation';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { DataSource } from 'typeorm';
|
||||
import * as Redis from 'ioredis';
|
||||
|
|
@ -112,6 +111,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
|
||||
) {
|
||||
super(meta, paramDef, async () => {
|
||||
const si = await import('systeminformation');
|
||||
|
||||
const memStats = await si.mem();
|
||||
const fsStats = await si.fsSize();
|
||||
const netInterface = await si.networkInterfaceDefault();
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
*/
|
||||
|
||||
import * as os from 'node:os';
|
||||
import si from 'systeminformation';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||
import { MiMeta } from '@/models/_.js';
|
||||
|
|
@ -93,6 +92,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
},
|
||||
};
|
||||
|
||||
const si = await import('systeminformation');
|
||||
|
||||
const memStats = await si.mem();
|
||||
const fsStats = await si.fsSize();
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<template>
|
||||
<div
|
||||
:class="[$style.root, { [$style.modal]: modal, _popup: modal }]"
|
||||
:class="[$style.root]"
|
||||
@dragover.stop="onDragover"
|
||||
@dragenter="onDragenter"
|
||||
@dragleave="onDragleave"
|
||||
|
|
@ -114,7 +114,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { inject, watch, nextTick, onMounted, defineAsyncComponent, provide, shallowRef, ref, computed, useTemplateRef, onUnmounted } from 'vue';
|
||||
import { watch, nextTick, onMounted, defineAsyncComponent, provide, shallowRef, ref, computed, useTemplateRef, onUnmounted } from 'vue';
|
||||
import * as mfm from 'mfm-js';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import insertTextAtCursor from 'insert-text-at-cursor';
|
||||
|
|
@ -161,8 +161,6 @@ import { closeTip } from '@/tips.js';
|
|||
|
||||
const $i = ensureSignin();
|
||||
|
||||
const modal = inject(DI.inModal, false);
|
||||
|
||||
const props = withDefaults(defineProps<PostFormProps & {
|
||||
fixed?: boolean;
|
||||
autofocus?: boolean;
|
||||
|
|
@ -1447,13 +1445,6 @@ defineExpose({
|
|||
.root {
|
||||
position: relative;
|
||||
container-type: inline-size;
|
||||
|
||||
&.modal {
|
||||
width: 100%;
|
||||
max-width: 520px;
|
||||
overflow-x: clip;
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
|
||||
//#region header
|
||||
|
|
@ -1722,7 +1713,8 @@ html[data-color-scheme=light] .preview {
|
|||
min-width: 100%;
|
||||
width: 100%;
|
||||
min-height: 90px;
|
||||
height: 100%;
|
||||
max-height: 500px;
|
||||
field-sizing: content;
|
||||
}
|
||||
|
||||
.textCount {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkPostForm
|
||||
ref="form"
|
||||
:class="$style.form"
|
||||
class="_popup"
|
||||
v-bind="props"
|
||||
autofocus
|
||||
freezeAfterPosted
|
||||
|
|
@ -73,7 +74,8 @@ function onModalClosed() {
|
|||
|
||||
<style lang="scss" module>
|
||||
.form {
|
||||
max-height: 100%;
|
||||
width: 100%;
|
||||
max-width: 520px;
|
||||
margin: 0 auto auto auto;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<SearchMarker>
|
||||
<MkFolder :defaultOpen="true">
|
||||
<template #icon><SearchIcon><i class="ti ti-bolt"></i></SearchIcon></template>
|
||||
<template #label><SearchLabel>Misskey® Reactions Boost Technology™ (RBT)</SearchLabel><span class="_beta">{{ i18n.ts.beta }}</span></template>
|
||||
<template #label><SearchLabel>Misskey® Reactions Boost Technology™ (RBT)</SearchLabel></template>
|
||||
<template v-if="rbtForm.savedState.enableReactionsBuffering" #suffix>Enabled</template>
|
||||
<template v-else #suffix>Disabled</template>
|
||||
<template v-if="rbtForm.modified.value" #footer>
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<SearchMarker :keywords="['lockdown']">
|
||||
<FormSection>
|
||||
<template #label><SearchLabel>{{ i18n.ts.lockdown }}</SearchLabel><span class="_beta">{{ i18n.ts.beta }}</span></template>
|
||||
<template #label><SearchLabel>{{ i18n.ts.lockdown }}</SearchLabel></template>
|
||||
|
||||
<div class="_gaps_m">
|
||||
<SearchMarker :keywords="['login', 'signin']">
|
||||
|
|
@ -213,9 +213,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, watch } from 'vue';
|
||||
import type { MkSelectItem } from '@/components/MkSelect.vue';
|
||||
import MkSwitch from '@/components/MkSwitch.vue';
|
||||
import MkSelect from '@/components/MkSelect.vue';
|
||||
import type { MkSelectItem } from '@/components/MkSelect.vue';
|
||||
import FormSection from '@/components/form/section.vue';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<SearchMarker :keywords="['follow', 'message']">
|
||||
<MkInput v-model="profile.followedMessage" :max="200" manualSave :mfmPreview="false">
|
||||
<template #label><SearchLabel>{{ i18n.ts._profile.followedMessage }}</SearchLabel><span class="_beta">{{ i18n.ts.beta }}</span></template>
|
||||
<template #label><SearchLabel>{{ i18n.ts._profile.followedMessage }}</SearchLabel></template>
|
||||
<template #caption>
|
||||
<div><SearchText>{{ i18n.ts._profile.followedMessageDescription }}</SearchText></div>
|
||||
<div>{{ i18n.ts._profile.followedMessageDescriptionForLockedAccount }}</div>
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ export const TIPS = [
|
|||
'clips',
|
||||
'userLists',
|
||||
'postForm',
|
||||
'deck',
|
||||
'tl.home',
|
||||
'tl.local',
|
||||
'tl.social',
|
||||
|
|
|
|||
|
|
@ -14,6 +14,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<i v-if="store.r.realtimeMode.value" class="ti ti-bolt ti-fw"></i>
|
||||
<i v-else class="ti ti-bolt-off ti-fw"></i>
|
||||
</button>
|
||||
<button v-if="!iconOnly && showWidgetButton" v-tooltip.noDelay.right="i18n.ts.widgets" class="_button" :class="[$style.widget]" @click="() => emit('widgetButtonClick')">
|
||||
<i class="ti ti-apps ti-fw"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div :class="$style.middle">
|
||||
<MkA v-tooltip.noDelay.right="i18n.ts.timeline" :class="$style.item" :activeClass="$style.active" to="/" exact>
|
||||
|
|
@ -51,7 +54,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</MkA>
|
||||
</div>
|
||||
<div :class="$style.bottom">
|
||||
<button v-if="showWidgetButton" v-tooltip.noDelay.right="i18n.ts.widgets" class="_button" :class="[$style.widget]" @click="() => emit('widgetButtonClick')">
|
||||
<button v-if="iconOnly && showWidgetButton" v-tooltip.noDelay.right="i18n.ts.widgets" class="_button" :class="[$style.widget]" @click="() => emit('widgetButtonClick')">
|
||||
<i class="ti ti-apps ti-fw"></i>
|
||||
</button>
|
||||
<button v-if="iconOnly" v-tooltip.noDelay.right="i18n.ts.realtimeMode" class="_button" :class="[$style.realtimeMode, store.r.realtimeMode.value ? $style.on : null]" @click="toggleRealtimeMode">
|
||||
|
|
@ -436,6 +439,12 @@ function menuEdit() {
|
|||
}
|
||||
}
|
||||
|
||||
.widget {
|
||||
display: inline-block;
|
||||
width: var(--top-height);
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.bottom {
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
|
|
|
|||
|
|
@ -38,36 +38,39 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
@headerWheel="onWheel"
|
||||
/>
|
||||
</section>
|
||||
<div v-if="layout.length === 0" class="_panel" :class="$style.onboarding">
|
||||
<div v-if="layout.length === 0" class="_panel _gaps" :class="$style.onboarding">
|
||||
<div>{{ i18n.ts._deck.introduction }}</div>
|
||||
<div>{{ i18n.ts._deck.introduction2 }}</div>
|
||||
<MkInfo v-if="!store.r.tips.value.deck" closable @close="closeTip('deck')">
|
||||
<button class="_textButton" @click="showTour">{{ i18n.ts._deck.showHowToUse }}</button>
|
||||
</MkInfo>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="prefer.r['deck.menuPosition'].value === 'right'" :class="$style.sideMenu">
|
||||
<div :class="$style.sideMenuTop">
|
||||
<button v-tooltip.noDelay.left="`${i18n.ts._deck.profile}: ${prefer.s['deck.profile']}`" :class="$style.sideMenuButton" class="_button" @click="switchProfileMenu"><i class="ti ti-caret-down"></i></button>
|
||||
<button ref="swicthProfileButtonEl" v-tooltip.noDelay.left="`${i18n.ts._deck.profile}: ${prefer.s['deck.profile']}`" :class="$style.sideMenuButton" class="_button" @click="switchProfileMenu"><i class="ti ti-caret-down"></i></button>
|
||||
<button v-tooltip.noDelay.left="i18n.ts._deck.deleteProfile" :class="$style.sideMenuButton" class="_button" @click="deleteProfile"><i class="ti ti-trash"></i></button>
|
||||
</div>
|
||||
<div :class="$style.sideMenuMiddle">
|
||||
<button v-tooltip.noDelay.left="i18n.ts._deck.addColumn" :class="$style.sideMenuButton" class="_button" @click="addColumn"><i class="ti ti-plus"></i></button>
|
||||
<button ref="addColumnButtonEl" v-tooltip.noDelay.left="i18n.ts._deck.addColumn" :class="$style.sideMenuButton" class="_button" @click="addColumn"><i class="ti ti-plus"></i></button>
|
||||
</div>
|
||||
<div :class="$style.sideMenuBottom">
|
||||
<button v-tooltip.noDelay.left="i18n.ts.settings" :class="$style.sideMenuButton" class="_button" @click="showSettings"><i class="ti ti-settings-2"></i></button>
|
||||
<button ref="settingsButtonEl" v-tooltip.noDelay.left="i18n.ts.settings" :class="$style.sideMenuButton" class="_button" @click="showSettings"><i class="ti ti-settings-2"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="prefer.r['deck.menuPosition'].value === 'bottom'" :class="$style.bottomMenu">
|
||||
<div :class="$style.bottomMenuLeft">
|
||||
<button v-tooltip.noDelay.left="`${i18n.ts._deck.profile}: ${prefer.s['deck.profile']}`" :class="$style.bottomMenuButton" class="_button" @click="switchProfileMenu"><i class="ti ti-caret-down"></i></button>
|
||||
<button v-tooltip.noDelay.left="i18n.ts._deck.deleteProfile" :class="$style.bottomMenuButton" class="_button" @click="deleteProfile"><i class="ti ti-trash"></i></button>
|
||||
<button ref="swicthProfileButtonEl" v-tooltip.noDelay.top="`${i18n.ts._deck.profile}: ${prefer.s['deck.profile']}`" :class="$style.bottomMenuButton" class="_button" @click="switchProfileMenu"><i class="ti ti-caret-down"></i></button>
|
||||
<button v-tooltip.noDelay.top="i18n.ts._deck.deleteProfile" :class="$style.bottomMenuButton" class="_button" @click="deleteProfile"><i class="ti ti-trash"></i></button>
|
||||
</div>
|
||||
<div :class="$style.bottomMenuMiddle">
|
||||
<button v-tooltip.noDelay.left="i18n.ts._deck.addColumn" :class="$style.bottomMenuButton" class="_button" @click="addColumn"><i class="ti ti-plus"></i></button>
|
||||
<button ref="addColumnButtonEl" v-tooltip.noDelay.top="i18n.ts._deck.addColumn" :class="$style.bottomMenuButton" class="_button" @click="addColumn"><i class="ti ti-plus"></i></button>
|
||||
</div>
|
||||
<div :class="$style.bottomMenuRight">
|
||||
<button v-tooltip.noDelay.left="i18n.ts.settings" :class="$style.bottomMenuButton" class="_button" @click="showSettings"><i class="ti ti-settings-2"></i></button>
|
||||
<button ref="settingsButtonEl" v-tooltip.noDelay.top="i18n.ts.settings" :class="$style.bottomMenuButton" class="_button" @click="showSettings"><i class="ti ti-settings-2"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -96,6 +99,7 @@ import { $i } from '@/i.js';
|
|||
import { i18n } from '@/i18n.js';
|
||||
import { deviceKind } from '@/utility/device-kind.js';
|
||||
import { prefer } from '@/preferences.js';
|
||||
import { store } from '@/store.js';
|
||||
import XMainColumn from '@/ui/deck/main-column.vue';
|
||||
import XTlColumn from '@/ui/deck/tl-column.vue';
|
||||
import XAntennaColumn from '@/ui/deck/antenna-column.vue';
|
||||
|
|
@ -107,10 +111,13 @@ import XMentionsColumn from '@/ui/deck/mentions-column.vue';
|
|||
import XDirectColumn from '@/ui/deck/direct-column.vue';
|
||||
import XRoleTimelineColumn from '@/ui/deck/role-timeline-column.vue';
|
||||
import XChatColumn from '@/ui/deck/chat-column.vue';
|
||||
import MkInfo from '@/components/MkInfo.vue';
|
||||
import { mainRouter } from '@/router.js';
|
||||
import { columns, layout, columnTypes, switchProfileMenu, addColumn as addColumnToStore, deleteProfile as deleteProfile_ } from '@/deck.js';
|
||||
import { shouldSuggestRestoreBackup } from '@/preferences/utility.js';
|
||||
import { shouldSuggestReload } from '@/utility/reload-suggest.js';
|
||||
import { startTour } from '@/utility/tour.js';
|
||||
import { closeTip } from '@/tips.js';
|
||||
|
||||
const XStatusBars = defineAsyncComponent(() => import('@/ui/_common_/statusbars.vue'));
|
||||
const XAnnouncements = defineAsyncComponent(() => import('@/ui/_common_/announcements.vue'));
|
||||
|
|
@ -163,6 +170,9 @@ function showSettings() {
|
|||
}
|
||||
|
||||
const columnsEl = useTemplateRef('columnsEl');
|
||||
const addColumnButtonEl = useTemplateRef('addColumnButtonEl');
|
||||
const settingsButtonEl = useTemplateRef('settingsButtonEl');
|
||||
const swicthProfileButtonEl = useTemplateRef('swicthProfileButtonEl');
|
||||
|
||||
const addColumn = async (ev) => {
|
||||
const { canceled, result: column } = await os.select({
|
||||
|
|
@ -218,6 +228,30 @@ async function deleteProfile() {
|
|||
os.success();
|
||||
}
|
||||
|
||||
function showTour() {
|
||||
if (addColumnButtonEl.value == null ||
|
||||
settingsButtonEl.value == null ||
|
||||
swicthProfileButtonEl.value == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
startTour([{
|
||||
element: addColumnButtonEl.value,
|
||||
title: i18n.ts._deck._howToUse.addColumn_title,
|
||||
description: i18n.ts._deck._howToUse.addColumn_description,
|
||||
}, {
|
||||
element: settingsButtonEl.value,
|
||||
title: i18n.ts._deck._howToUse.settings_title,
|
||||
description: i18n.ts._deck._howToUse.settings_description,
|
||||
}, {
|
||||
element: swicthProfileButtonEl.value,
|
||||
title: i18n.ts._deck._howToUse.switchProfile_title,
|
||||
description: i18n.ts._deck._howToUse.switchProfile_description,
|
||||
}]).then(() => {
|
||||
closeTip('deck');
|
||||
});
|
||||
}
|
||||
|
||||
window.document.documentElement.style.overflowY = 'hidden';
|
||||
window.document.documentElement.style.scrollBehavior = 'auto';
|
||||
</script>
|
||||
|
|
@ -345,7 +379,7 @@ window.document.documentElement.style.scrollBehavior = 'auto';
|
|||
}
|
||||
|
||||
.bottomMenuButton {
|
||||
display: block;
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
aspect-ratio: 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<XTitlebar v-if="prefer.r.showTitlebar.value" style="flex-shrink: 0;"/>
|
||||
|
||||
<div :class="$style.nonTitlebarArea">
|
||||
<XSidebar v-if="!isMobile" :class="$style.sidebar" :showWidgetButton="!isDesktop" @widgetButtonClick="widgetsShowing = true"/>
|
||||
<XSidebar v-if="!isMobile" :class="$style.sidebar" :showWidgetButton="!showWidgetsSide" @widgetButtonClick="widgetsShowing = true"/>
|
||||
|
||||
<div :class="[$style.contents, !isMobile && prefer.r.showTitlebar.value ? $style.withSidebarAndTitlebar : null]" @contextmenu.stop="onContextmenu">
|
||||
<div>
|
||||
|
|
@ -22,7 +22,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<XMobileFooterMenu v-if="isMobile" ref="navFooter" v-model:drawerMenuShowing="drawerMenuShowing" v-model:widgetsShowing="widgetsShowing"/>
|
||||
</div>
|
||||
|
||||
<div v-if="isDesktop && !pageMetadata?.needWideArea" :class="$style.widgets">
|
||||
<div v-if="showWidgetsSide && !pageMetadata?.needWideArea" :class="$style.widgets">
|
||||
<XWidgets/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -64,7 +64,8 @@ const DESKTOP_THRESHOLD = 1100;
|
|||
const MOBILE_THRESHOLD = 500;
|
||||
|
||||
// デスクトップでウィンドウを狭くしたときモバイルUIが表示されて欲しいことはあるので deviceKind === 'desktop' の判定は行わない
|
||||
const isDesktop = ref(window.innerWidth >= DESKTOP_THRESHOLD);
|
||||
const showWidgetsSide = window.innerWidth >= DESKTOP_THRESHOLD;
|
||||
|
||||
const isMobile = ref(deviceKind === 'smartphone' || window.innerWidth <= MOBILE_THRESHOLD);
|
||||
window.addEventListener('resize', () => {
|
||||
isMobile.value = deviceKind === 'smartphone' || window.innerWidth <= MOBILE_THRESHOLD;
|
||||
|
|
@ -102,14 +103,6 @@ if (window.innerWidth > 1024) {
|
|||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (!isDesktop.value) {
|
||||
window.addEventListener('resize', () => {
|
||||
if (window.innerWidth >= DESKTOP_THRESHOLD) isDesktop.value = true;
|
||||
}, { passive: true });
|
||||
}
|
||||
});
|
||||
|
||||
const onContextmenu = (ev) => {
|
||||
if (isLink(ev.target)) return;
|
||||
if (['INPUT', 'TEXTAREA', 'IMG', 'VIDEO', 'CANVAS'].includes(ev.target.tagName) || ev.target.attributes['contenteditable']) return;
|
||||
|
|
|
|||
|
|
@ -10948,6 +10948,36 @@ export interface Locale extends ILocale {
|
|||
* プロファイル情報のデバイス間同期を有効にする
|
||||
*/
|
||||
"enableSyncBetweenDevicesForProfiles": string;
|
||||
/**
|
||||
* UIの説明を見る
|
||||
*/
|
||||
"showHowToUse": string;
|
||||
"_howToUse": {
|
||||
/**
|
||||
* カラム追加
|
||||
*/
|
||||
"addColumn_title": string;
|
||||
/**
|
||||
* カラムの種類を選んで追加できます。
|
||||
*/
|
||||
"addColumn_description": string;
|
||||
/**
|
||||
* UI設定
|
||||
*/
|
||||
"settings_title": string;
|
||||
/**
|
||||
* デッキUIの詳細設定を行えます。
|
||||
*/
|
||||
"settings_description": string;
|
||||
/**
|
||||
* プロファイル切り替え
|
||||
*/
|
||||
"switchProfile_title": string;
|
||||
/**
|
||||
* UIのレイアウトをプロファイルとして保存し、いつでも切り替えられるようにできます。
|
||||
*/
|
||||
"switchProfile_description": string;
|
||||
};
|
||||
"_columns": {
|
||||
/**
|
||||
* メイン
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"type": "module",
|
||||
"name": "misskey-js",
|
||||
"version": "2025.12.2-beta.1",
|
||||
"version": "2025.12.2-beta.2",
|
||||
"description": "Misskey SDK for JavaScript",
|
||||
"license": "MIT",
|
||||
"main": "./built/index.js",
|
||||
|
|
|
|||
Loading…
Reference in New Issue