Merge branch 'develop' into fetch
This commit is contained in:
commit
560c1c2128
|
@ -20,6 +20,9 @@ You should also include the user name that made the change.
|
|||
- You may have to `yarn run clean-all`, `sudo corepack enable` and `yarn set version berry` before running `yarn install` if you're still on yarn classic
|
||||
- 新たに動的なPagesを作ることはできなくなりました
|
||||
- 代わりに今後AiScriptを用いてより柔軟に動的なコンテンツを作成できるMisskey Play機能の実装を予定しています。
|
||||
- AiScriptが0.12.0にアップデートされました
|
||||
- 0.12.0の変更点についてはこちら https://github.com/syuilo/aiscript/blob/master/CHANGELOG.md#0120
|
||||
- 0.12.0未満のプラグインは読み込むことはできません
|
||||
- iOS15以下のデバイスはサポートされなくなりました
|
||||
- API: カスタム絵文字エンティティに`url`プロパティが含まれなくなりました
|
||||
- 絵文字画像を表示するには、`<instance host>/emoji/<emoji name>.webp`にリクエストすると画像が返ります。
|
||||
|
@ -27,6 +30,7 @@ You should also include the user name that made the change.
|
|||
- remote: `https://p1.a9z.dev/emoji/syuilo_birth_present@mk.f72u.net.webp`
|
||||
- API: `user`および`note`エンティティに`emojis`プロパティが含まれなくなりました
|
||||
- API: `user`エンティティに`avatarColor`および`bannerColor`プロパティが含まれなくなりました
|
||||
- API: `instance`エンティティに`latestStatus`、`lastCommunicatedAt`、`latestRequestSentAt`プロパティが含まれなくなりました
|
||||
|
||||
### Improvements
|
||||
- Push notification of Antenna note @tamaina
|
||||
|
@ -41,6 +45,7 @@ You should also include the user name that made the change.
|
|||
- Server: delete outdated notifications regularly to improve db performance @syuilo
|
||||
- Server: delete outdated hard-mutes regularly to improve db performance @syuilo
|
||||
- Server: delete outdated notes of antenna regularly to improve db performance @syuilo
|
||||
- Server: improve activitypub deliver performance @syuilo
|
||||
- Client: use tabler-icons instead of fontawesome to better design @syuilo
|
||||
- Client: Add new gabber kick sounds (thanks for noizenecio)
|
||||
- Client: Add link to user RSS feed in profile menu @ssmucny
|
||||
|
|
|
@ -167,7 +167,6 @@ annotation: "注釈"
|
|||
federation: "連合"
|
||||
instances: "インスタンス"
|
||||
registeredAt: "初観測"
|
||||
latestRequestSentAt: "直近のリクエスト送信"
|
||||
latestRequestReceivedAt: "直近のリクエスト受信"
|
||||
latestStatus: "直近のステータス"
|
||||
storageUsage: "ストレージ使用量"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "misskey",
|
||||
"version": "13.0.0-beta.17",
|
||||
"version": "13.0.0-beta.20",
|
||||
"codename": "indigo",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
export class removeLatestRequestSentAt1672703171386 {
|
||||
name = 'removeLatestRequestSentAt1672703171386'
|
||||
|
||||
async up(queryRunner) {
|
||||
await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "latestRequestSentAt"`);
|
||||
}
|
||||
|
||||
async down(queryRunner) {
|
||||
await queryRunner.query(`ALTER TABLE "instance" ADD "latestRequestSentAt" TIMESTAMP WITH TIME ZONE`);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
export class removeLastCommunicatedAt1672704017999 {
|
||||
name = 'removeLastCommunicatedAt1672704017999'
|
||||
|
||||
async up(queryRunner) {
|
||||
await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "lastCommunicatedAt"`);
|
||||
}
|
||||
|
||||
async down(queryRunner) {
|
||||
await queryRunner.query(`ALTER TABLE "instance" ADD "lastCommunicatedAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
export class removeLatestStatus1672704136584 {
|
||||
name = 'removeLatestStatus1672704136584'
|
||||
|
||||
async up(queryRunner) {
|
||||
await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "latestStatus"`);
|
||||
}
|
||||
|
||||
async down(queryRunner) {
|
||||
await queryRunner.query(`ALTER TABLE "instance" ADD "latestStatus" integer`);
|
||||
}
|
||||
}
|
|
@ -37,7 +37,6 @@
|
|||
"@nestjs/testing": "9.2.1",
|
||||
"@peertube/http-signature": "1.7.0",
|
||||
"@sinonjs/fake-timers": "10.0.2",
|
||||
"@syuilo/aiscript": "0.11.1",
|
||||
"accepts": "^1.3.8",
|
||||
"ajv": "8.11.2",
|
||||
"archiver": "5.3.1",
|
||||
|
|
|
@ -22,7 +22,7 @@ export class FederatedInstanceService {
|
|||
}
|
||||
|
||||
@bindThis
|
||||
public async registerOrFetchInstanceDoc(host: string): Promise<Instance> {
|
||||
public async fetch(host: string): Promise<Instance> {
|
||||
host = this.utilityService.toPuny(host);
|
||||
|
||||
const cached = this.cache.get(host);
|
||||
|
@ -35,7 +35,6 @@ export class FederatedInstanceService {
|
|||
id: this.idService.genId(),
|
||||
host,
|
||||
caughtAt: new Date(),
|
||||
lastCommunicatedAt: new Date(),
|
||||
}).then(x => this.instancesRepository.findOneByOrFail(x.identifiers[0]));
|
||||
|
||||
this.cache.set(host, i);
|
||||
|
@ -45,4 +44,17 @@ export class FederatedInstanceService {
|
|||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public async updateCachePartial(host: string, data: Partial<Instance>): Promise<void> {
|
||||
host = this.utilityService.toPuny(host);
|
||||
|
||||
const cached = this.cache.get(host);
|
||||
if (cached == null) return;
|
||||
|
||||
this.cache.set(host, {
|
||||
...cached,
|
||||
...data,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -428,7 +428,7 @@ export class NoteCreateService {
|
|||
|
||||
// Register host
|
||||
if (this.userEntityService.isRemoteUser(user)) {
|
||||
this.federatedInstanceService.registerOrFetchInstanceDoc(user.host).then(i => {
|
||||
this.federatedInstanceService.fetch(user.host).then(i => {
|
||||
this.instancesRepository.increment({ id: i.id }, 'notesCount', 1);
|
||||
this.instanceChart.updateNote(i.host, note, true);
|
||||
});
|
||||
|
|
|
@ -100,7 +100,7 @@ export class NoteDeleteService {
|
|||
this.perUserNotesChart.update(user, note, false);
|
||||
|
||||
if (this.userEntityService.isRemoteUser(user)) {
|
||||
this.federatedInstanceService.registerOrFetchInstanceDoc(user.host).then(i => {
|
||||
this.federatedInstanceService.fetch(user.host).then(i => {
|
||||
this.instancesRepository.decrement({ id: i.id }, 'notesCount', 1);
|
||||
this.instanceChart.updateNote(i.host, note, false);
|
||||
});
|
||||
|
|
|
@ -205,12 +205,12 @@ export class UserFollowingService {
|
|||
|
||||
//#region Update instance stats
|
||||
if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) {
|
||||
this.federatedInstanceService.registerOrFetchInstanceDoc(follower.host).then(i => {
|
||||
this.federatedInstanceService.fetch(follower.host).then(i => {
|
||||
this.instancesRepository.increment({ id: i.id }, 'followingCount', 1);
|
||||
this.instanceChart.updateFollowing(i.host, true);
|
||||
});
|
||||
} else if (this.userEntityService.isLocalUser(follower) && this.userEntityService.isRemoteUser(followee)) {
|
||||
this.federatedInstanceService.registerOrFetchInstanceDoc(followee.host).then(i => {
|
||||
this.federatedInstanceService.fetch(followee.host).then(i => {
|
||||
this.instancesRepository.increment({ id: i.id }, 'followersCount', 1);
|
||||
this.instanceChart.updateFollowers(i.host, true);
|
||||
});
|
||||
|
@ -323,12 +323,12 @@ export class UserFollowingService {
|
|||
|
||||
//#region Update instance stats
|
||||
if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) {
|
||||
this.federatedInstanceService.registerOrFetchInstanceDoc(follower.host).then(i => {
|
||||
this.federatedInstanceService.fetch(follower.host).then(i => {
|
||||
this.instancesRepository.decrement({ id: i.id }, 'followingCount', 1);
|
||||
this.instanceChart.updateFollowing(i.host, false);
|
||||
});
|
||||
} else if (this.userEntityService.isLocalUser(follower) && this.userEntityService.isRemoteUser(followee)) {
|
||||
this.federatedInstanceService.registerOrFetchInstanceDoc(followee.host).then(i => {
|
||||
this.federatedInstanceService.fetch(followee.host).then(i => {
|
||||
this.instancesRepository.decrement({ id: i.id }, 'followersCount', 1);
|
||||
this.instanceChart.updateFollowers(i.host, false);
|
||||
});
|
||||
|
|
|
@ -348,7 +348,7 @@ export class ApPersonService implements OnModuleInit {
|
|||
}
|
||||
|
||||
// Register host
|
||||
this.federatedInstanceService.registerOrFetchInstanceDoc(host).then(i => {
|
||||
this.federatedInstanceService.fetch(host).then(i => {
|
||||
this.instancesRepository.increment({ id: i.id }, 'usersCount', 1);
|
||||
this.instanceChart.newUser(i.host);
|
||||
this.fetchInstanceMetadataService.fetchInstanceMetadata(i);
|
||||
|
|
|
@ -86,7 +86,7 @@ export default class FederationChart extends Chart<typeof schema> {
|
|||
.where(`instance.host IN (${ subInstancesQuery.getQuery() })`)
|
||||
.andWhere(meta.blockedHosts.length === 0 ? '1=1' : 'instance.host NOT IN (:...blocked)', { blocked: meta.blockedHosts })
|
||||
.andWhere('instance.isSuspended = false')
|
||||
.andWhere('instance.lastCommunicatedAt > :gt', { gt: new Date(Date.now() - (1000 * 60 * 60 * 24 * 30)) })
|
||||
.andWhere('instance.isNotResponding = false')
|
||||
.getRawOne()
|
||||
.then(x => parseInt(x.count, 10)),
|
||||
this.instancesRepository.createQueryBuilder('instance')
|
||||
|
@ -94,7 +94,7 @@ export default class FederationChart extends Chart<typeof schema> {
|
|||
.where(`instance.host IN (${ pubInstancesQuery.getQuery() })`)
|
||||
.andWhere(meta.blockedHosts.length === 0 ? '1=1' : 'instance.host NOT IN (:...blocked)', { blocked: meta.blockedHosts })
|
||||
.andWhere('instance.isSuspended = false')
|
||||
.andWhere('instance.lastCommunicatedAt > :gt', { gt: new Date(Date.now() - (1000 * 60 * 60 * 24 * 30)) })
|
||||
.andWhere('instance.isNotResponding = false')
|
||||
.getRawOne()
|
||||
.then(x => parseInt(x.count, 10)),
|
||||
]);
|
||||
|
|
|
@ -7,8 +7,8 @@ import type { } from '@/models/entities/Blocking.js';
|
|||
import type { User } from '@/models/entities/User.js';
|
||||
import type { Instance } from '@/models/entities/Instance.js';
|
||||
import { MetaService } from '@/core/MetaService.js';
|
||||
import { UserEntityService } from './UserEntityService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { UserEntityService } from './UserEntityService.js';
|
||||
|
||||
@Injectable()
|
||||
export class InstanceEntityService {
|
||||
|
@ -33,8 +33,6 @@ export class InstanceEntityService {
|
|||
notesCount: instance.notesCount,
|
||||
followingCount: instance.followingCount,
|
||||
followersCount: instance.followersCount,
|
||||
latestRequestSentAt: instance.latestRequestSentAt ? instance.latestRequestSentAt.toISOString() : null,
|
||||
lastCommunicatedAt: instance.lastCommunicatedAt.toISOString(),
|
||||
isNotResponding: instance.isNotResponding,
|
||||
isSuspended: instance.isSuspended,
|
||||
isBlocked: meta.blockedHosts.includes(instance.host),
|
||||
|
|
|
@ -59,22 +59,6 @@ export class Instance {
|
|||
})
|
||||
public followersCount: number;
|
||||
|
||||
/**
|
||||
* 直近のリクエスト送信日時
|
||||
*/
|
||||
@Column('timestamp with time zone', {
|
||||
nullable: true,
|
||||
})
|
||||
public latestRequestSentAt: Date | null;
|
||||
|
||||
/**
|
||||
* 直近のリクエスト送信時のHTTPステータスコード
|
||||
*/
|
||||
@Column('integer', {
|
||||
nullable: true,
|
||||
})
|
||||
public latestStatus: number | null;
|
||||
|
||||
/**
|
||||
* 直近のリクエスト受信日時
|
||||
*/
|
||||
|
@ -83,12 +67,6 @@ export class Instance {
|
|||
})
|
||||
public latestRequestReceivedAt: Date | null;
|
||||
|
||||
/**
|
||||
* このインスタンスと最後にやり取りした日時
|
||||
*/
|
||||
@Column('timestamp with time zone')
|
||||
public lastCommunicatedAt: Date;
|
||||
|
||||
/**
|
||||
* このインスタンスと不通かどうか
|
||||
*/
|
||||
|
|
|
@ -32,16 +32,6 @@ export const packedFederationInstanceSchema = {
|
|||
type: 'number',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
latestRequestSentAt: {
|
||||
type: 'string',
|
||||
optional: false, nullable: true,
|
||||
format: 'date-time',
|
||||
},
|
||||
lastCommunicatedAt: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
format: 'date-time',
|
||||
},
|
||||
isNotResponding: {
|
||||
type: 'boolean',
|
||||
optional: false, nullable: false,
|
||||
|
|
|
@ -15,10 +15,10 @@ import ApRequestChart from '@/core/chart/charts/ap-request.js';
|
|||
import FederationChart from '@/core/chart/charts/federation.js';
|
||||
import { StatusError } from '@/misc/status-error.js';
|
||||
import { UtilityService } from '@/core/UtilityService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { QueueLoggerService } from '../QueueLoggerService.js';
|
||||
import type Bull from 'bull';
|
||||
import type { DeliverJobData } from '../types.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
|
||||
@Injectable()
|
||||
export class DeliverProcessorService {
|
||||
|
@ -48,7 +48,6 @@ export class DeliverProcessorService {
|
|||
) {
|
||||
this.logger = this.queueLoggerService.logger.createSubLogger('deliver');
|
||||
this.suspendedHostsCache = new Cache<Instance[]>(1000 * 60 * 60);
|
||||
this.latest = null;
|
||||
}
|
||||
|
||||
@bindThis
|
||||
|
@ -76,20 +75,18 @@ export class DeliverProcessorService {
|
|||
}
|
||||
|
||||
try {
|
||||
if (this.latest !== (this.latest = JSON.stringify(job.data.content, null, 2))) {
|
||||
this.logger.debug(`delivering ${this.latest}`);
|
||||
}
|
||||
|
||||
await this.apRequestService.signedPost(job.data.user, job.data.to, job.data.content);
|
||||
|
||||
// Update stats
|
||||
this.federatedInstanceService.registerOrFetchInstanceDoc(host).then(i => {
|
||||
this.instancesRepository.update(i.id, {
|
||||
latestRequestSentAt: new Date(),
|
||||
latestStatus: 200,
|
||||
lastCommunicatedAt: new Date(),
|
||||
isNotResponding: false,
|
||||
});
|
||||
this.federatedInstanceService.fetch(host).then(i => {
|
||||
if (i.isNotResponding) {
|
||||
this.instancesRepository.update(i.id, {
|
||||
isNotResponding: false,
|
||||
});
|
||||
this.federatedInstanceService.updateCachePartial(host, {
|
||||
isNotResponding: false,
|
||||
});
|
||||
}
|
||||
|
||||
this.fetchInstanceMetadataService.fetchInstanceMetadata(i);
|
||||
|
||||
|
@ -100,13 +97,16 @@ export class DeliverProcessorService {
|
|||
|
||||
return 'Success';
|
||||
} catch (res) {
|
||||
// Update stats
|
||||
this.federatedInstanceService.registerOrFetchInstanceDoc(host).then(i => {
|
||||
this.instancesRepository.update(i.id, {
|
||||
latestRequestSentAt: new Date(),
|
||||
latestStatus: res instanceof StatusError ? res.statusCode : null,
|
||||
isNotResponding: true,
|
||||
});
|
||||
// Update stats
|
||||
this.federatedInstanceService.fetch(host).then(i => {
|
||||
if (!i.isNotResponding) {
|
||||
this.instancesRepository.update(i.id, {
|
||||
isNotResponding: true,
|
||||
});
|
||||
this.federatedInstanceService.updateCachePartial(host, {
|
||||
isNotResponding: true,
|
||||
});
|
||||
}
|
||||
|
||||
this.instanceChart.requestSent(i.host, false);
|
||||
this.apRequestChart.deliverFail();
|
||||
|
@ -114,17 +114,17 @@ export class DeliverProcessorService {
|
|||
});
|
||||
|
||||
if (res instanceof StatusError) {
|
||||
// 4xx
|
||||
// 4xx
|
||||
if (res.isClientError) {
|
||||
// HTTPステータスコード4xxはクライアントエラーであり、それはつまり
|
||||
// 何回再送しても成功することはないということなのでエラーにはしないでおく
|
||||
// HTTPステータスコード4xxはクライアントエラーであり、それはつまり
|
||||
// 何回再送しても成功することはないということなのでエラーにはしないでおく
|
||||
return `${res.statusCode} ${res.statusMessage}`;
|
||||
}
|
||||
|
||||
// 5xx etc.
|
||||
throw `${res.statusCode} ${res.statusMessage}`;
|
||||
} else {
|
||||
// DNS error, socket error, timeout ...
|
||||
// DNS error, socket error, timeout ...
|
||||
throw res;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -176,10 +176,12 @@ export class InboxProcessorService {
|
|||
}
|
||||
|
||||
// Update stats
|
||||
this.federatedInstanceService.registerOrFetchInstanceDoc(authUser.user.host).then(i => {
|
||||
this.federatedInstanceService.fetch(authUser.user.host).then(i => {
|
||||
this.instancesRepository.update(i.id, {
|
||||
latestRequestReceivedAt: new Date(),
|
||||
lastCommunicatedAt: new Date(),
|
||||
isNotResponding: false,
|
||||
});
|
||||
this.federatedInstanceService.updateCachePartial(host, {
|
||||
isNotResponding: false,
|
||||
});
|
||||
|
||||
|
|
|
@ -64,8 +64,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||
case '-followers': query.orderBy('instance.followersCount', 'ASC'); break;
|
||||
case '+caughtAt': query.orderBy('instance.caughtAt', 'DESC'); break;
|
||||
case '-caughtAt': query.orderBy('instance.caughtAt', 'ASC'); break;
|
||||
case '+lastCommunicatedAt': query.orderBy('instance.lastCommunicatedAt', 'DESC'); break;
|
||||
case '-lastCommunicatedAt': query.orderBy('instance.lastCommunicatedAt', 'ASC'); break;
|
||||
case '+latestRequestReceivedAt': query.orderBy('instance.latestRequestReceivedAt', 'DESC'); break;
|
||||
case '-latestRequestReceivedAt': query.orderBy('instance.latestRequestReceivedAt', 'ASC'); break;
|
||||
|
||||
default: query.orderBy('instance.id', 'DESC'); break;
|
||||
}
|
||||
|
|
|
@ -139,10 +139,12 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||
throw new ApiError(meta.errors.noSuchUser);
|
||||
}
|
||||
|
||||
if (me == null && ip != null) {
|
||||
this.perUserPvChart.commitByVisitor(user, ip);
|
||||
} else if (me && me.id !== user.id) {
|
||||
this.perUserPvChart.commitByUser(user, me.id);
|
||||
if (user.host == null) {
|
||||
if (me == null && ip != null) {
|
||||
this.perUserPvChart.commitByVisitor(user, ip);
|
||||
} else if (me && me.id !== user.id) {
|
||||
this.perUserPvChart.commitByUser(user, me.id);
|
||||
}
|
||||
}
|
||||
|
||||
return await this.userEntityService.pack(user, me, {
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
"@rollup/plugin-alias": "4.0.2",
|
||||
"@rollup/plugin-json": "6.0.0",
|
||||
"@rollup/pluginutils": "5.0.2",
|
||||
"@syuilo/aiscript": "0.11.1",
|
||||
"@syuilo/aiscript": "0.12.0",
|
||||
"@tabler/icons": "^1.118.0",
|
||||
"@vitejs/plugin-vue": "4.0.0",
|
||||
"@vue/compiler-sfc": "3.2.45",
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { ref, shallowRef } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import XWindow from '@/components/MkWindow.vue';
|
||||
import MkTextarea from '@/components/form/textarea.vue';
|
||||
|
@ -40,7 +40,7 @@ const emit = defineEmits<{
|
|||
(ev: 'closed'): void;
|
||||
}>();
|
||||
|
||||
const uiWindow = ref<InstanceType<typeof XWindow>>();
|
||||
const uiWindow = shallowRef<InstanceType<typeof XWindow>>();
|
||||
const comment = ref(props.initialComment || '');
|
||||
|
||||
function send() {
|
||||
|
|
|
@ -16,9 +16,9 @@
|
|||
</li>
|
||||
</ol>
|
||||
<ol v-else-if="emojis.length > 0" ref="suggests" class="emojis">
|
||||
<li v-for="emoji in emojis" tabindex="-1" :key="emoji.emoji" @click="complete(type, emoji.emoji)" @keydown="onKeydown">
|
||||
<li v-for="emoji in emojis" :key="emoji.emoji" tabindex="-1" @click="complete(type, emoji.emoji)" @keydown="onKeydown">
|
||||
<div class="emoji">
|
||||
<MkEmoji :emoji="emoji.emoji" />
|
||||
<MkEmoji :emoji="emoji.emoji"/>
|
||||
</div>
|
||||
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||
<span v-if="q" class="name" v-html="sanitizeHtml(emoji.name.replace(q, `<b>${q}</b>`))"></span>
|
||||
|
@ -35,7 +35,8 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { markRaw, ref, onUpdated, onMounted, onBeforeUnmount, nextTick, watch } from 'vue';
|
||||
import { markRaw, ref, shallowRef, onUpdated, onMounted, onBeforeUnmount, nextTick, watch } from 'vue';
|
||||
import sanitizeHtml from 'sanitize-html';
|
||||
import contains from '@/scripts/contains';
|
||||
import { char2twemojiFilePath, char2fluentEmojiFilePath } from '@/scripts/emoji-base';
|
||||
import { acct } from '@/filters/user';
|
||||
|
@ -45,7 +46,6 @@ import { defaultStore } from '@/store';
|
|||
import { emojilist } from '@/scripts/emojilist';
|
||||
import { instance } from '@/instance';
|
||||
import { i18n } from '@/i18n';
|
||||
import sanitizeHtml from 'sanitize-html';
|
||||
|
||||
type EmojiDef = {
|
||||
emoji: string;
|
||||
|
@ -136,7 +136,7 @@ const emit = defineEmits<{
|
|||
}>();
|
||||
|
||||
const suggests = ref<Element>();
|
||||
const rootEl = ref<HTMLDivElement>();
|
||||
const rootEl = shallowRef<HTMLDivElement>();
|
||||
|
||||
const fetching = ref(true);
|
||||
const users = ref<any[]>([]);
|
||||
|
|
|
@ -47,8 +47,8 @@ const emit = defineEmits<{
|
|||
(ev: 'click', payload: MouseEvent): void;
|
||||
}>();
|
||||
|
||||
let el = $ref<HTMLElement | null>(null);
|
||||
let ripples = $ref<HTMLElement | null>(null);
|
||||
let el = $shallowRef<HTMLElement | null>(null);
|
||||
let ripples = $shallowRef<HTMLElement | null>(null);
|
||||
|
||||
onMounted(() => {
|
||||
if (props.autofocus) {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, onMounted, onBeforeUnmount, watch } from 'vue';
|
||||
import { ref, shallowRef, computed, onMounted, onBeforeUnmount, watch } from 'vue';
|
||||
import { defaultStore } from '@/store';
|
||||
import { i18n } from '@/i18n';
|
||||
|
||||
|
@ -42,7 +42,7 @@ const emit = defineEmits<{
|
|||
|
||||
const available = ref(false);
|
||||
|
||||
const captchaEl = ref<HTMLDivElement | undefined>();
|
||||
const captchaEl = shallowRef<HTMLDivElement | undefined>();
|
||||
|
||||
const variable = computed(() => {
|
||||
switch (props.provider) {
|
||||
|
@ -62,7 +62,7 @@ const src = computed(() => {
|
|||
}
|
||||
});
|
||||
|
||||
const scriptId = computed(() => `script-${props.provider}`)
|
||||
const scriptId = computed(() => `script-${props.provider}`);
|
||||
|
||||
const captcha = computed<Captcha>(() => window[variable.value] || {} as unknown as Captcha);
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<template>
|
||||
<div class="cbbedffa">
|
||||
<canvas ref="chartEl"></canvas>
|
||||
<MkChartLegend ref="legendEl" style="margin-top: 8px;"/>
|
||||
<div v-if="fetching" class="fetching">
|
||||
<MkLoading/>
|
||||
</div>
|
||||
|
@ -13,9 +14,8 @@
|
|||
id-denylist violation when setting it. This is causing about 60+ lint issues.
|
||||
As this is part of Chart.js's API it makes sense to disable the check here.
|
||||
*/
|
||||
import { onMounted, ref, watch, PropType, onUnmounted } from 'vue';
|
||||
import { onMounted, ref, shallowRef, watch, PropType, onUnmounted } from 'vue';
|
||||
import { Chart } from 'chart.js';
|
||||
import 'chartjs-adapter-date-fns';
|
||||
import { enUS } from 'date-fns/locale';
|
||||
import gradient from 'chartjs-plugin-gradient';
|
||||
import * as os from '@/os';
|
||||
|
@ -25,6 +25,8 @@ import { chartVLine } from '@/scripts/chart-vline';
|
|||
import { alpha } from '@/scripts/color';
|
||||
import date from '@/filters/date';
|
||||
import { initChart } from '@/scripts/init-chart';
|
||||
import { chartLegend } from '@/scripts/chart-legend';
|
||||
import MkChartLegend from '@/components/MkChartLegend.vue';
|
||||
|
||||
initChart();
|
||||
|
||||
|
@ -68,6 +70,8 @@ const props = defineProps({
|
|||
},
|
||||
});
|
||||
|
||||
let legendEl = $shallowRef<InstanceType<typeof MkChartLegend>>();
|
||||
|
||||
const sum = (...arr) => arr.reduce((r, a) => r.map((b, i) => a[i] + b));
|
||||
const negate = arr => arr.map(x => -x);
|
||||
|
||||
|
@ -102,7 +106,7 @@ let chartData: {
|
|||
}[];
|
||||
} = null;
|
||||
|
||||
const chartEl = ref<HTMLCanvasElement>(null);
|
||||
const chartEl = shallowRef<HTMLCanvasElement>(null);
|
||||
const fetching = ref(true);
|
||||
|
||||
const getDate = (ago: number) => {
|
||||
|
@ -221,11 +225,7 @@ const render = () => {
|
|||
},
|
||||
plugins: {
|
||||
legend: {
|
||||
display: props.detailed,
|
||||
position: 'bottom',
|
||||
labels: {
|
||||
boxWidth: 16,
|
||||
},
|
||||
display: false,
|
||||
},
|
||||
tooltip: {
|
||||
enabled: false,
|
||||
|
@ -265,7 +265,7 @@ const render = () => {
|
|||
gradient,
|
||||
},
|
||||
},
|
||||
plugins: [chartVLine(vLineColor)],
|
||||
plugins: [chartVLine(vLineColor), ...(props.detailed ? [chartLegend(legendEl)] : [])],
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
<template>
|
||||
<div :class="$style.root">
|
||||
<button v-for="item in items" class="_button item" :class="{ disabled: item.hidden }" @click="onClick(item)">
|
||||
<span class="box" :style="{ background: chart.config.type === 'line' ? item.strokeStyle?.toString() : item.fillStyle?.toString() }"></span>
|
||||
{{ item.text }}
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref, shallowRef, watch, PropType, onUnmounted } from 'vue';
|
||||
import { Chart, LegendItem } from 'chart.js';
|
||||
|
||||
const props = defineProps({
|
||||
});
|
||||
|
||||
let chart = $shallowRef<Chart>();
|
||||
let items = $shallowRef<LegendItem[]>([]);
|
||||
|
||||
function update(_chart: Chart, _items: LegendItem[]) {
|
||||
chart = _chart,
|
||||
items = _items;
|
||||
}
|
||||
|
||||
function onClick(item: LegendItem) {
|
||||
if (chart == null) return;
|
||||
const { type } = chart.config;
|
||||
if (type === 'pie' || type === 'doughnut') {
|
||||
// Pie and doughnut charts only have a single dataset and visibility is per item
|
||||
chart.toggleDataVisibility(item.index);
|
||||
} else {
|
||||
chart.setDatasetVisibility(item.datasetIndex, !chart.isDatasetVisible(item.datasetIndex));
|
||||
}
|
||||
chart.update();
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
update,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
.root {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
|
||||
&:global {
|
||||
> .item {
|
||||
font-size: 85%;
|
||||
padding: 4px 12px 4px 8px;
|
||||
border: solid 1px var(--divider);
|
||||
border-radius: 999px;
|
||||
|
||||
&:hover {
|
||||
border-color: var(--inputBorderHover);
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
text-decoration: line-through;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
> .box {
|
||||
display: inline-block;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 100%;
|
||||
vertical-align: -10%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -22,7 +22,7 @@ const emit = defineEmits<{
|
|||
(ev: 'closed'): void;
|
||||
}>();
|
||||
|
||||
let rootEl = $ref<HTMLDivElement>();
|
||||
let rootEl = $shallowRef<HTMLDivElement>();
|
||||
|
||||
let zIndex = $ref<number>(os.claimZIndex('high'));
|
||||
|
||||
|
|
|
@ -50,8 +50,8 @@ const props = defineProps<{
|
|||
}>();
|
||||
|
||||
const imgUrl = getProxiedImageUrl(props.file.url);
|
||||
let dialogEl = $ref<InstanceType<typeof XModalWindow>>();
|
||||
let imgEl = $ref<HTMLImageElement>();
|
||||
let dialogEl = $shallowRef<InstanceType<typeof XModalWindow>>();
|
||||
let imgEl = $shallowRef<HTMLImageElement>();
|
||||
let cropper: Cropper | null = null;
|
||||
let loading = $ref(true);
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onBeforeUnmount, onMounted, ref } from 'vue';
|
||||
import { onBeforeUnmount, onMounted, ref, shallowRef } from 'vue';
|
||||
import MkModal from '@/components/MkModal.vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import MkInput from '@/components/form/input.vue';
|
||||
|
@ -94,7 +94,7 @@ const emit = defineEmits<{
|
|||
(ev: 'closed'): void;
|
||||
}>();
|
||||
|
||||
const modal = ref<InstanceType<typeof MkModal>>();
|
||||
const modal = shallowRef<InstanceType<typeof MkModal>>();
|
||||
|
||||
const inputValue = ref(props.input?.default || null);
|
||||
const selectedValue = ref(props.select?.default || null);
|
||||
|
|
|
@ -88,7 +88,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { markRaw, nextTick, onActivated, onBeforeUnmount, onMounted, ref, watch } from 'vue';
|
||||
import { markRaw, nextTick, onActivated, onBeforeUnmount, onMounted, ref, shallowRef, watch } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import MkButton from './MkButton.vue';
|
||||
import XNavFolder from '@/components/MkDrive.navFolder.vue';
|
||||
|
@ -118,8 +118,8 @@ const emit = defineEmits<{
|
|||
(ev: 'open-folder', v: Misskey.entities.DriveFolder): void;
|
||||
}>();
|
||||
|
||||
const loadMoreFiles = ref<InstanceType<typeof MkButton>>();
|
||||
const fileInput = ref<HTMLInputElement>();
|
||||
const loadMoreFiles = shallowRef<InstanceType<typeof MkButton>>();
|
||||
const fileInput = shallowRef<HTMLInputElement>();
|
||||
|
||||
const folder = ref<Misskey.entities.DriveFolder | null>(null);
|
||||
const files = ref<Misskey.entities.DriveFile[]>([]);
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { ref, shallowRef } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import XDrive from '@/components/MkDrive.vue';
|
||||
import XModalWindow from '@/components/MkModalWindow.vue';
|
||||
|
@ -38,7 +38,7 @@ const emit = defineEmits<{
|
|||
(ev: 'closed'): void;
|
||||
}>();
|
||||
|
||||
const dialog = ref<InstanceType<typeof XModalWindow>>();
|
||||
const dialog = shallowRef<InstanceType<typeof XModalWindow>>();
|
||||
|
||||
const selected = ref<Misskey.entities.DriveFile[]>([]);
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, watch, onMounted } from 'vue';
|
||||
import { ref, shallowRef, computed, watch, onMounted } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import XSection from '@/components/MkEmojiPicker.section.vue';
|
||||
import { emojilist, UnicodeEmojiDef, unicodeEmojiCategories as categories } from '@/scripts/emojilist';
|
||||
|
@ -102,8 +102,8 @@ const emit = defineEmits<{
|
|||
(ev: 'chosen', v: string): void;
|
||||
}>();
|
||||
|
||||
const search = ref<HTMLInputElement>();
|
||||
const emojis = ref<HTMLDivElement>();
|
||||
const search = shallowRef<HTMLInputElement>();
|
||||
const emojis = shallowRef<HTMLDivElement>();
|
||||
|
||||
const {
|
||||
reactions: pinned,
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { shallowRef } from 'vue';
|
||||
import MkModal from '@/components/MkModal.vue';
|
||||
import MkEmojiPicker from '@/components/MkEmojiPicker.vue';
|
||||
import { defaultStore } from '@/store';
|
||||
|
@ -48,8 +48,8 @@ const emit = defineEmits<{
|
|||
(ev: 'closed'): void;
|
||||
}>();
|
||||
|
||||
const modal = ref<InstanceType<typeof MkModal>>();
|
||||
const picker = ref<InstanceType<typeof MkEmojiPicker>>();
|
||||
const modal = shallowRef<InstanceType<typeof MkModal>>();
|
||||
const picker = shallowRef<InstanceType<typeof MkEmojiPicker>>();
|
||||
|
||||
function chosen(emoji: any) {
|
||||
emit('done', emoji);
|
||||
|
|
|
@ -37,7 +37,7 @@ const emit = defineEmits<{
|
|||
(ev: 'closed'): void;
|
||||
}>();
|
||||
|
||||
const dialog = $ref<InstanceType<typeof XModalWindow>>();
|
||||
const dialog = $shallowRef<InstanceType<typeof XModalWindow>>();
|
||||
|
||||
let caption = $ref(props.default);
|
||||
|
||||
|
|
|
@ -12,11 +12,10 @@ import { markRaw, version as vueVersion, onMounted, onBeforeUnmount, nextTick, w
|
|||
import { Chart } from 'chart.js';
|
||||
import { enUS } from 'date-fns/locale';
|
||||
import tinycolor from 'tinycolor2';
|
||||
import { MatrixController, MatrixElement } from 'chartjs-chart-matrix';
|
||||
import * as os from '@/os';
|
||||
import 'chartjs-adapter-date-fns';
|
||||
import { defaultStore } from '@/store';
|
||||
import { useChartTooltip } from '@/scripts/use-chart-tooltip';
|
||||
import { MatrixController, MatrixElement } from 'chartjs-chart-matrix';
|
||||
import { chartVLine } from '@/scripts/chart-vline';
|
||||
import { alpha } from '@/scripts/color';
|
||||
import { initChart } from '@/scripts/init-chart';
|
||||
|
@ -27,8 +26,8 @@ const props = defineProps<{
|
|||
src: string;
|
||||
}>();
|
||||
|
||||
const rootEl = $ref<HTMLDivElement>(null);
|
||||
const chartEl = $ref<HTMLCanvasElement>(null);
|
||||
const rootEl = $shallowRef<HTMLDivElement>(null);
|
||||
const chartEl = $shallowRef<HTMLCanvasElement>(null);
|
||||
const now = new Date();
|
||||
let chartInstance: Chart = null;
|
||||
let fetching = $ref(true);
|
||||
|
|
|
@ -28,7 +28,7 @@ const emit = defineEmits<{
|
|||
(ev: 'closed'): void;
|
||||
}>();
|
||||
|
||||
const modal = $ref<InstanceType<typeof MkModal>>();
|
||||
const modal = $shallowRef<InstanceType<typeof MkModal>>();
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
@ -24,7 +24,7 @@ const props = withDefaults(defineProps<{
|
|||
cover: true,
|
||||
});
|
||||
|
||||
const canvas = $ref<HTMLCanvasElement>();
|
||||
const canvas = $shallowRef<HTMLCanvasElement>();
|
||||
let loaded = $ref(false);
|
||||
|
||||
function draw() {
|
||||
|
|
|
@ -94,8 +94,8 @@ const chartLimit = 500;
|
|||
let chartSpan = $ref<'hour' | 'day'>('hour');
|
||||
let chartSrc = $ref('active-users');
|
||||
let heatmapSrc = $ref('active-users');
|
||||
let subDoughnutEl = $ref<HTMLCanvasElement>();
|
||||
let pubDoughnutEl = $ref<HTMLCanvasElement>();
|
||||
let subDoughnutEl = $shallowRef<HTMLCanvasElement>();
|
||||
let pubDoughnutEl = $shallowRef<HTMLCanvasElement>();
|
||||
|
||||
const { handler: externalTooltipHandler1 } = useChartTooltip({
|
||||
position: 'middle',
|
||||
|
|
|
@ -44,7 +44,7 @@ const preferedModalType = (deviceKind === 'desktop' && props.src != null) ? 'pop
|
|||
deviceKind === 'smartphone' ? 'drawer' :
|
||||
'dialog';
|
||||
|
||||
const modal = $ref<InstanceType<typeof MkModal>>();
|
||||
const modal = $shallowRef<InstanceType<typeof MkModal>>();
|
||||
|
||||
const menu = defaultStore.state.menu;
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ const props = withDefaults(defineProps<{
|
|||
}>(), {
|
||||
});
|
||||
|
||||
const audioEl = $ref<HTMLAudioElement | null>();
|
||||
const audioEl = $shallowRef<HTMLAudioElement | null>();
|
||||
let hide = $ref(true);
|
||||
|
||||
function volumechange() {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
<script lang="ts" setup>
|
||||
import { on } from 'events';
|
||||
import { nextTick, onBeforeUnmount, onMounted, onUnmounted, ref, watch } from 'vue';
|
||||
import { nextTick, onBeforeUnmount, onMounted, onUnmounted, ref, shallowRef, watch } from 'vue';
|
||||
import MkMenu from './MkMenu.vue';
|
||||
import { MenuItem } from '@/types/menu';
|
||||
import * as os from '@/os';
|
||||
|
@ -24,7 +24,7 @@ const emit = defineEmits<{
|
|||
(ev: 'actioned'): void;
|
||||
}>();
|
||||
|
||||
const el = ref<HTMLElement>();
|
||||
const el = shallowRef<HTMLElement>();
|
||||
const align = 'left';
|
||||
|
||||
function setPosition() {
|
||||
|
|
|
@ -78,11 +78,11 @@ const emit = defineEmits<{
|
|||
(ev: 'close', actioned?: boolean): void;
|
||||
}>();
|
||||
|
||||
let itemsEl = $ref<HTMLDivElement>();
|
||||
let itemsEl = $shallowRef<HTMLDivElement>();
|
||||
|
||||
let items2: InnerMenuItem[] = $ref([]);
|
||||
|
||||
let child = $ref<InstanceType<typeof XChild>>();
|
||||
let child = $shallowRef<InstanceType<typeof XChild>>();
|
||||
|
||||
let keymap = $computed(() => ({
|
||||
'up|k|shift+tab': focusUp,
|
||||
|
@ -112,7 +112,7 @@ watch(() => props.items, () => {
|
|||
});
|
||||
|
||||
let childMenu = $ref<MenuItem[] | null>();
|
||||
let childTarget = $ref<HTMLElement | null>();
|
||||
let childTarget = $shallowRef<HTMLElement | null>();
|
||||
|
||||
function closeChild() {
|
||||
childMenu = null;
|
||||
|
@ -203,7 +203,7 @@ onBeforeUnmount(() => {
|
|||
> .item {
|
||||
display: block;
|
||||
position: relative;
|
||||
padding: 6px 16px;
|
||||
padding: 5px 16px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
white-space: nowrap;
|
||||
|
@ -226,10 +226,6 @@ onBeforeUnmount(() => {
|
|||
border-radius: 6px;
|
||||
}
|
||||
|
||||
> * {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
&:not(:disabled):hover {
|
||||
color: var(--accent);
|
||||
text-decoration: none;
|
||||
|
|
|
@ -61,7 +61,7 @@ let maxHeight = $ref<number>();
|
|||
let fixed = $ref(false);
|
||||
let transformOrigin = $ref('center');
|
||||
let showing = $ref(true);
|
||||
let content = $ref<HTMLElement>();
|
||||
let content = $shallowRef<HTMLElement>();
|
||||
const zIndex = os.claimZIndex(props.zPriority);
|
||||
const type = $computed<ModalTypes>(() => {
|
||||
if (props.preferType === 'auto') {
|
||||
|
|
|
@ -49,7 +49,7 @@ router.addListener('push', ctx => {
|
|||
|
||||
let pageMetadata = $ref<null | ComputedRef<PageMetadata>>();
|
||||
let rootEl = $ref();
|
||||
let modal = $ref<InstanceType<typeof MkModal>>();
|
||||
let modal = $shallowRef<InstanceType<typeof MkModal>>();
|
||||
let path = $ref(props.initialPath);
|
||||
let width = $ref(860);
|
||||
let height = $ref(660);
|
||||
|
|
|
@ -41,9 +41,9 @@ const emit = defineEmits<{
|
|||
(event: 'ok'): void;
|
||||
}>();
|
||||
|
||||
let modal = $ref<InstanceType<typeof MkModal>>();
|
||||
let rootEl = $ref<HTMLElement>();
|
||||
let headerEl = $ref<HTMLElement>();
|
||||
let modal = $shallowRef<InstanceType<typeof MkModal>>();
|
||||
let rootEl = $shallowRef<HTMLElement>();
|
||||
let headerEl = $shallowRef<HTMLElement>();
|
||||
let bodyWidth = $ref(0);
|
||||
let bodyHeight = $ref(0);
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
</div>
|
||||
<MkPoll v-if="appearNote.poll" ref="pollViewer" :note="appearNote" class="poll"/>
|
||||
<MkUrlPreview v-for="url in urls" :key="url" :url="url" :compact="true" :detail="false" class="url-preview"/>
|
||||
<div v-if="appearNote.renote" class="renote"><MkNoteSimple :note="appearNote.renote"/></div>
|
||||
<div v-if="appearNote.renote" class="renote"><MkNoteSimple :note="appearNote.renote" class="note"/></div>
|
||||
<button v-if="isLong && collapsed" class="fade _button" @click="collapsed = false">
|
||||
<span>{{ i18n.ts.showMore }}</span>
|
||||
</button>
|
||||
|
@ -101,7 +101,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, inject, onMounted, onUnmounted, reactive, ref, Ref } from 'vue';
|
||||
import { computed, inject, onMounted, onUnmounted, reactive, ref, shallowRef, Ref } from 'vue';
|
||||
import * as mfm from 'mfm-js';
|
||||
import * as misskey from 'misskey-js';
|
||||
import MkNoteSub from '@/components/MkNoteSub.vue';
|
||||
|
@ -156,11 +156,11 @@ const isRenote = (
|
|||
note.poll == null
|
||||
);
|
||||
|
||||
const el = ref<HTMLElement>();
|
||||
const menuButton = ref<HTMLElement>();
|
||||
const renoteButton = ref<InstanceType<typeof MkRenoteButton>>();
|
||||
const renoteTime = ref<HTMLElement>();
|
||||
const reactButton = ref<HTMLElement>();
|
||||
const el = shallowRef<HTMLElement>();
|
||||
const menuButton = shallowRef<HTMLElement>();
|
||||
const renoteButton = shallowRef<InstanceType<typeof MkRenoteButton>>();
|
||||
const renoteTime = shallowRef<HTMLElement>();
|
||||
const reactButton = shallowRef<HTMLElement>();
|
||||
let appearNote = $computed(() => isRenote ? note.renote as misskey.entities.Note : note);
|
||||
const isMyRenote = $i && ($i.id === note.userId);
|
||||
const showContent = ref(false);
|
||||
|
@ -529,7 +529,7 @@ function readPromo() {
|
|||
> .renote {
|
||||
padding: 8px 0;
|
||||
|
||||
> * {
|
||||
> .note {
|
||||
padding: 16px;
|
||||
border: dashed 1px var(--renote);
|
||||
border-radius: 8px;
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
</div>
|
||||
<MkPoll v-if="appearNote.poll" ref="pollViewer" :note="appearNote" class="poll"/>
|
||||
<MkUrlPreview v-for="url in urls" :key="url" :url="url" :compact="true" :detail="true" class="url-preview"/>
|
||||
<div v-if="appearNote.renote" class="renote"><MkNoteSimple :note="appearNote.renote"/></div>
|
||||
<div v-if="appearNote.renote" class="renote"><MkNoteSimple :note="appearNote.renote" class="note"/></div>
|
||||
</div>
|
||||
<MkA v-if="appearNote.channel && !inChannel" class="channel" :to="`/channels/${appearNote.channel.id}`"><i class="ti ti-device-tv"></i> {{ appearNote.channel.name }}</MkA>
|
||||
</div>
|
||||
|
@ -112,7 +112,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, inject, onMounted, onUnmounted, reactive, ref } from 'vue';
|
||||
import { computed, inject, onMounted, onUnmounted, reactive, ref, shallowRef } from 'vue';
|
||||
import * as mfm from 'mfm-js';
|
||||
import * as misskey from 'misskey-js';
|
||||
import MkNoteSub from '@/components/MkNoteSub.vue';
|
||||
|
@ -166,11 +166,11 @@ const isRenote = (
|
|||
note.poll == null
|
||||
);
|
||||
|
||||
const el = ref<HTMLElement>();
|
||||
const menuButton = ref<HTMLElement>();
|
||||
const renoteButton = ref<InstanceType<typeof MkRenoteButton>>();
|
||||
const renoteTime = ref<HTMLElement>();
|
||||
const reactButton = ref<HTMLElement>();
|
||||
const el = shallowRef<HTMLElement>();
|
||||
const menuButton = shallowRef<HTMLElement>();
|
||||
const renoteButton = shallowRef<InstanceType<typeof MkRenoteButton>>();
|
||||
const renoteTime = shallowRef<HTMLElement>();
|
||||
const reactButton = shallowRef<HTMLElement>();
|
||||
let appearNote = $computed(() => isRenote ? note.renote as misskey.entities.Note : note);
|
||||
const isMyRenote = $i && ($i.id === note.userId);
|
||||
const showContent = ref(false);
|
||||
|
@ -491,7 +491,7 @@ if (appearNote.replyId) {
|
|||
> .renote {
|
||||
padding: 8px 0;
|
||||
|
||||
> * {
|
||||
> .note {
|
||||
padding: 16px;
|
||||
border: dashed 1px var(--renote);
|
||||
border-radius: 8px;
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { shallowRef } from 'vue';
|
||||
import XNote from '@/components/MkNote.vue';
|
||||
import XList from '@/components/MkDateSeparatedList.vue';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
|
@ -29,7 +29,7 @@ const props = defineProps<{
|
|||
noGap?: boolean;
|
||||
}>();
|
||||
|
||||
const pagingComponent = ref<InstanceType<typeof MkPagination>>();
|
||||
const pagingComponent = shallowRef<InstanceType<typeof MkPagination>>();
|
||||
|
||||
defineExpose({
|
||||
pagingComponent,
|
||||
|
|
|
@ -73,7 +73,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, onUnmounted, watch } from 'vue';
|
||||
import { ref, shallowRef, onMounted, onUnmounted, watch } from 'vue';
|
||||
import * as misskey from 'misskey-js';
|
||||
import XReactionIcon from '@/components/MkReactionIcon.vue';
|
||||
import MkFollowButton from '@/components/MkFollowButton.vue';
|
||||
|
@ -95,7 +95,7 @@ const props = withDefaults(defineProps<{
|
|||
full: false,
|
||||
});
|
||||
|
||||
const elRef = ref<HTMLElement>(null);
|
||||
const elRef = shallowRef<HTMLElement>(null);
|
||||
const reactionRef = ref(null);
|
||||
|
||||
let readObserver: IntersectionObserver | undefined;
|
||||
|
|
|
@ -56,7 +56,7 @@ const props = withDefaults(defineProps<{
|
|||
|
||||
let includingTypes = $computed(() => props.includingTypes || []);
|
||||
|
||||
const dialog = $ref<InstanceType<typeof XModalWindow>>();
|
||||
const dialog = $shallowRef<InstanceType<typeof XModalWindow>>();
|
||||
|
||||
let typesMap = $ref<Record<typeof notificationTypes[number], boolean>>({});
|
||||
let useGlobalSetting = $ref((includingTypes === null || includingTypes.length === 0) && props.showGlobalToggle);
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { defineComponent, markRaw, onUnmounted, onMounted, computed, ref } from 'vue';
|
||||
import { defineComponent, markRaw, onUnmounted, onMounted, computed, shallowRef } from 'vue';
|
||||
import { notificationTypes } from 'misskey-js';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import XNotification from '@/components/MkNotification.vue';
|
||||
|
@ -33,7 +33,7 @@ const props = defineProps<{
|
|||
unreadOnly?: boolean;
|
||||
}>();
|
||||
|
||||
const pagingComponent = ref<InstanceType<typeof MkPagination>>();
|
||||
const pagingComponent = shallowRef<InstanceType<typeof MkPagination>>();
|
||||
|
||||
const pagination: Paging = {
|
||||
endpoint: 'i/notifications' as const,
|
||||
|
|
|
@ -47,7 +47,7 @@ defineEmits<{
|
|||
const router = new Router(routes, props.initialPath);
|
||||
|
||||
let pageMetadata = $ref<null | ComputedRef<PageMetadata>>();
|
||||
let windowEl = $ref<InstanceType<typeof XWindow>>();
|
||||
let windowEl = $shallowRef<InstanceType<typeof XWindow>>();
|
||||
const history = $ref<{ path: string; key: any; }[]>([{
|
||||
path: router.getCurrentPath(),
|
||||
key: router.getCurrentKey(),
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ComputedRef, isRef, markRaw, onActivated, onDeactivated, Ref, ref, watch } from 'vue';
|
||||
import { computed, ComputedRef, isRef, markRaw, onActivated, onDeactivated, Ref, ref, shallowRef, watch } from 'vue';
|
||||
import * as misskey from 'misskey-js';
|
||||
import * as os from '@/os';
|
||||
import { onScrollTop, isTopVisible, getScrollPosition, getScrollContainer } from '@/scripts/scroll';
|
||||
|
@ -65,7 +65,7 @@ const props = withDefaults(defineProps<{
|
|||
disableAutoLoad?: boolean;
|
||||
displayLimit?: number;
|
||||
}>(), {
|
||||
displayLimit: 30,
|
||||
displayLimit: 20,
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
@ -74,7 +74,7 @@ const emit = defineEmits<{
|
|||
|
||||
type Item = { id: string; [another: string]: unknown; };
|
||||
|
||||
const rootEl = ref<HTMLElement>();
|
||||
const rootEl = shallowRef<HTMLElement>();
|
||||
const items = ref<Item[]>([]);
|
||||
const queue = ref<Item[]>([]);
|
||||
const offset = ref(0);
|
||||
|
|
|
@ -22,7 +22,7 @@ const emit = defineEmits<{
|
|||
(ev: 'closed'): void;
|
||||
}>();
|
||||
|
||||
let modal = $ref<InstanceType<typeof MkModal>>();
|
||||
let modal = $shallowRef<InstanceType<typeof MkModal>>();
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
@ -128,10 +128,10 @@ const emit = defineEmits<{
|
|||
(ev: 'esc'): void;
|
||||
}>();
|
||||
|
||||
const textareaEl = $ref<HTMLTextAreaElement | null>(null);
|
||||
const cwInputEl = $ref<HTMLInputElement | null>(null);
|
||||
const hashtagsInputEl = $ref<HTMLInputElement | null>(null);
|
||||
const visibilityButton = $ref<HTMLElement | null>(null);
|
||||
const textareaEl = $shallowRef<HTMLTextAreaElement | null>(null);
|
||||
const cwInputEl = $shallowRef<HTMLInputElement | null>(null);
|
||||
const hashtagsInputEl = $shallowRef<HTMLInputElement | null>(null);
|
||||
const visibilityButton = $shallowRef<HTMLElement | null>(null);
|
||||
|
||||
let posting = $ref(false);
|
||||
let posted = $ref(false);
|
||||
|
|
|
@ -31,8 +31,8 @@ const emit = defineEmits<{
|
|||
(ev: 'closed'): void;
|
||||
}>();
|
||||
|
||||
let modal = $ref<InstanceType<typeof MkModal>>();
|
||||
let form = $ref<InstanceType<typeof MkPostForm>>();
|
||||
let modal = $shallowRef<InstanceType<typeof MkModal>>();
|
||||
let form = $shallowRef<InstanceType<typeof MkPostForm>>();
|
||||
|
||||
function onPosted() {
|
||||
modal.close({
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, ref, watch } from 'vue';
|
||||
import { computed, onMounted, ref, shallowRef, watch } from 'vue';
|
||||
import * as misskey from 'misskey-js';
|
||||
import XDetails from '@/components/MkReactionsViewer.details.vue';
|
||||
import XReactionIcon from '@/components/MkReactionIcon.vue';
|
||||
|
@ -28,7 +28,7 @@ const props = defineProps<{
|
|||
note: misskey.entities.Note;
|
||||
}>();
|
||||
|
||||
const buttonRef = ref<HTMLElement>();
|
||||
const buttonRef = shallowRef<HTMLElement>();
|
||||
|
||||
const canToggle = computed(() => !props.reaction.match(/@\w/) && $i);
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import { computed, ref, shallowRef } from 'vue';
|
||||
import * as misskey from 'misskey-js';
|
||||
import XDetails from '@/components/MkUsersTooltip.vue';
|
||||
import { pleaseLogin } from '@/scripts/please-login';
|
||||
|
@ -28,7 +28,7 @@ const props = defineProps<{
|
|||
count: number;
|
||||
}>();
|
||||
|
||||
const buttonRef = ref<HTMLElement>();
|
||||
const buttonRef = shallowRef<HTMLElement>();
|
||||
|
||||
const canRenote = computed(() => ['public', 'home'].includes(props.note.visibility) || props.note.userId === $i.id);
|
||||
|
||||
|
|
|
@ -12,19 +12,18 @@ import { markRaw, version as vueVersion, onMounted, onBeforeUnmount, nextTick }
|
|||
import { Chart } from 'chart.js';
|
||||
import { enUS } from 'date-fns/locale';
|
||||
import tinycolor from 'tinycolor2';
|
||||
import { MatrixController, MatrixElement } from 'chartjs-chart-matrix';
|
||||
import * as os from '@/os';
|
||||
import 'chartjs-adapter-date-fns';
|
||||
import { defaultStore } from '@/store';
|
||||
import { useChartTooltip } from '@/scripts/use-chart-tooltip';
|
||||
import { MatrixController, MatrixElement } from 'chartjs-chart-matrix';
|
||||
import { chartVLine } from '@/scripts/chart-vline';
|
||||
import { alpha } from '@/scripts/color';
|
||||
import { initChart } from '@/scripts/init-chart';
|
||||
|
||||
initChart();
|
||||
|
||||
const rootEl = $ref<HTMLDivElement>(null);
|
||||
const chartEl = $ref<HTMLCanvasElement>(null);
|
||||
const rootEl = $shallowRef<HTMLDivElement>(null);
|
||||
const chartEl = $shallowRef<HTMLCanvasElement>(null);
|
||||
const now = new Date();
|
||||
let chartInstance: Chart = null;
|
||||
let fetching = $ref(true);
|
||||
|
|
|
@ -32,7 +32,7 @@ const emit = defineEmits<{
|
|||
(ev: 'cancelled'): void;
|
||||
}>();
|
||||
|
||||
const dialog = $ref<InstanceType<typeof XModalWindow>>();
|
||||
const dialog = $shallowRef<InstanceType<typeof XModalWindow>>();
|
||||
|
||||
function onClose() {
|
||||
emit('cancelled');
|
||||
|
|
|
@ -33,7 +33,7 @@ const emit = defineEmits<{
|
|||
(ev: 'closed'): void;
|
||||
}>();
|
||||
|
||||
const dialog = $ref<InstanceType<typeof XModalWindow>>();
|
||||
const dialog = $shallowRef<InstanceType<typeof XModalWindow>>();
|
||||
|
||||
function onSignup(res) {
|
||||
emit('done', res);
|
||||
|
|
|
@ -64,10 +64,10 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, onUnmounted, ref } from 'vue';
|
||||
import { onMounted, onUnmounted, ref, shallowRef } from 'vue';
|
||||
|
||||
const particles = ref([]);
|
||||
const el = ref<HTMLElement>();
|
||||
const el = shallowRef<HTMLElement>();
|
||||
const width = ref(0);
|
||||
const height = ref(0);
|
||||
const colors = ['#FF1493', '#00FFFF', '#FFE202', '#FFE202', '#FFE202'];
|
||||
|
|
|
@ -19,9 +19,9 @@ const computedStyle = getComputedStyle(document.documentElement);
|
|||
const idForCanvas = Array.from(Array(16)).map(() => SAFE_FOR_HTML_ID[Math.floor(Math.random() * SAFE_FOR_HTML_ID.length)]).join('');
|
||||
const idForTags = Array.from(Array(16)).map(() => SAFE_FOR_HTML_ID[Math.floor(Math.random() * SAFE_FOR_HTML_ID.length)]).join('');
|
||||
let available = $ref(false);
|
||||
let rootEl = $ref<HTMLElement | null>(null);
|
||||
let canvasEl = $ref<HTMLCanvasElement | null>(null);
|
||||
let tagsEl = $ref<HTMLElement | null>(null);
|
||||
let rootEl = $shallowRef<HTMLElement | null>(null);
|
||||
let canvasEl = $shallowRef<HTMLCanvasElement | null>(null);
|
||||
let tagsEl = $shallowRef<HTMLElement | null>(null);
|
||||
let width = $ref(300);
|
||||
|
||||
watch($$(available), () => {
|
||||
|
|
|
@ -54,7 +54,7 @@ const emit = defineEmits<{
|
|||
(ev: 'done', result: { name: string | null, permissions: string[] }): void;
|
||||
}>();
|
||||
|
||||
const dialog = $ref<InstanceType<typeof XModalWindow>>();
|
||||
const dialog = $shallowRef<InstanceType<typeof XModalWindow>>();
|
||||
let name = $ref(props.initialName);
|
||||
let permissions = $ref({});
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { nextTick, onMounted, onUnmounted, ref } from 'vue';
|
||||
import { nextTick, onMounted, onUnmounted, ref, shallowRef } from 'vue';
|
||||
import * as os from '@/os';
|
||||
import { calcPopupPosition } from '@/scripts/popup-position';
|
||||
|
||||
|
@ -34,7 +34,7 @@ const emit = defineEmits<{
|
|||
(ev: 'closed'): void;
|
||||
}>();
|
||||
|
||||
const el = ref<HTMLElement>();
|
||||
const el = shallowRef<HTMLElement>();
|
||||
const zIndex = os.claimZIndex('high');
|
||||
|
||||
function setPosition() {
|
||||
|
|
|
@ -10,14 +10,14 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { shallowRef } from 'vue';
|
||||
import MkModal from '@/components/MkModal.vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import MkSparkle from '@/components/MkSparkle.vue';
|
||||
import { version } from '@/config';
|
||||
import { i18n } from '@/i18n';
|
||||
|
||||
const modal = ref<InstanceType<typeof MkModal>>();
|
||||
const modal = shallowRef<InstanceType<typeof MkModal>>();
|
||||
|
||||
const whatIsNew = () => {
|
||||
modal.value.close();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<MkPagination ref="pagingComponent" :pagination="pagination">
|
||||
<MkPagination :pagination="pagination">
|
||||
<template #empty>
|
||||
<div class="_fullinfo">
|
||||
<img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/>
|
||||
|
@ -16,7 +16,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { shallowRef } from 'vue';
|
||||
import MkUserInfo from '@/components/MkUserInfo.vue';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import { userPage } from '@/filters/user';
|
||||
|
@ -26,8 +26,6 @@ const props = defineProps<{
|
|||
pagination: Paging;
|
||||
noGap?: boolean;
|
||||
}>();
|
||||
|
||||
const pagingComponent = ref<InstanceType<typeof MkPagination>>();
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
@ -22,7 +22,7 @@ const props = defineProps<{
|
|||
},
|
||||
}>();
|
||||
|
||||
const specified = $ref<HTMLElement>();
|
||||
const specified = $shallowRef<HTMLElement>();
|
||||
|
||||
if (props.note.visibility === 'specified') {
|
||||
useTooltip($$(specified), async (showing) => {
|
||||
|
|
|
@ -1,42 +1,42 @@
|
|||
<template>
|
||||
<MkModal ref="modal" :z-priority="'high'" :src="src" @click="modal.close()" @closed="emit('closed')">
|
||||
<div class="gqyayizv _popup">
|
||||
<button key="public" class="_button" :class="{ active: v === 'public' }" data-index="1" @click="choose('public')">
|
||||
<div><i class="ti ti-world"></i></div>
|
||||
<div>
|
||||
<button key="public" class="_button item" :class="{ active: v === 'public' }" data-index="1" @click="choose('public')">
|
||||
<div class="icon"><i class="ti ti-world"></i></div>
|
||||
<div class="body">
|
||||
<span>{{ i18n.ts._visibility.public }}</span>
|
||||
<span>{{ i18n.ts._visibility.publicDescription }}</span>
|
||||
</div>
|
||||
</button>
|
||||
<button key="home" class="_button" :class="{ active: v === 'home' }" data-index="2" @click="choose('home')">
|
||||
<div><i class="ti ti-home"></i></div>
|
||||
<div>
|
||||
<button key="home" class="_button item" :class="{ active: v === 'home' }" data-index="2" @click="choose('home')">
|
||||
<div class="icon"><i class="ti ti-home"></i></div>
|
||||
<div class="body">
|
||||
<span>{{ i18n.ts._visibility.home }}</span>
|
||||
<span>{{ i18n.ts._visibility.homeDescription }}</span>
|
||||
</div>
|
||||
</button>
|
||||
<button key="followers" class="_button" :class="{ active: v === 'followers' }" data-index="3" @click="choose('followers')">
|
||||
<div><i class="ti ti-lock-open"></i></div>
|
||||
<div>
|
||||
<button key="followers" class="_button item" :class="{ active: v === 'followers' }" data-index="3" @click="choose('followers')">
|
||||
<div class="icon"><i class="ti ti-lock-open"></i></div>
|
||||
<div class="body">
|
||||
<span>{{ i18n.ts._visibility.followers }}</span>
|
||||
<span>{{ i18n.ts._visibility.followersDescription }}</span>
|
||||
</div>
|
||||
</button>
|
||||
<button key="specified" :disabled="localOnly" class="_button" :class="{ active: v === 'specified' }" data-index="4" @click="choose('specified')">
|
||||
<div><i class="ti ti-mail"></i></div>
|
||||
<div>
|
||||
<button key="specified" :disabled="localOnly" class="_button item" :class="{ active: v === 'specified' }" data-index="4" @click="choose('specified')">
|
||||
<div class="icon"><i class="ti ti-mail"></i></div>
|
||||
<div class="body">
|
||||
<span>{{ i18n.ts._visibility.specified }}</span>
|
||||
<span>{{ i18n.ts._visibility.specifiedDescription }}</span>
|
||||
</div>
|
||||
</button>
|
||||
<div class="divider"></div>
|
||||
<button key="localOnly" class="_button localOnly" :class="{ active: localOnly }" data-index="5" @click="localOnly = !localOnly">
|
||||
<div><i class="ti ti-world-off"></i></div>
|
||||
<div>
|
||||
<button key="localOnly" class="_button item localOnly" :class="{ active: localOnly }" data-index="5" @click="localOnly = !localOnly">
|
||||
<div class="icon"><i class="ti ti-world-off"></i></div>
|
||||
<div class="body">
|
||||
<span>{{ i18n.ts._visibility.localOnly }}</span>
|
||||
<span>{{ i18n.ts._visibility.localOnlyDescription }}</span>
|
||||
</div>
|
||||
<div><i :class="localOnly ? 'ti ti-toggle-right' : 'ti ti-toggle-left'"></i></div>
|
||||
<div class="toggle"><i :class="localOnly ? 'ti ti-toggle-right' : 'ti ti-toggle-left'"></i></div>
|
||||
</button>
|
||||
</div>
|
||||
</MkModal>
|
||||
|
@ -48,7 +48,7 @@ import * as misskey from 'misskey-js';
|
|||
import MkModal from '@/components/MkModal.vue';
|
||||
import { i18n } from '@/i18n';
|
||||
|
||||
const modal = $ref<InstanceType<typeof MkModal>>();
|
||||
const modal = $shallowRef<InstanceType<typeof MkModal>>();
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
currentVisibility: typeof misskey.noteVisibilities[number];
|
||||
|
@ -89,7 +89,7 @@ function choose(visibility: typeof misskey.noteVisibilities[number]): void {
|
|||
border-top: solid 0.5px var(--divider);
|
||||
}
|
||||
|
||||
> button {
|
||||
> .item {
|
||||
display: flex;
|
||||
padding: 8px 14px;
|
||||
font-size: 12px;
|
||||
|
@ -115,7 +115,7 @@ function choose(visibility: typeof misskey.noteVisibilities[number]): void {
|
|||
background: inherit;
|
||||
}
|
||||
|
||||
> *:nth-child(1) {
|
||||
> .icon {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
@ -127,7 +127,7 @@ function choose(visibility: typeof misskey.noteVisibilities[number]): void {
|
|||
margin-bottom: auto;
|
||||
}
|
||||
|
||||
> *:nth-child(2) {
|
||||
> .body {
|
||||
flex: 1 1 auto;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
|
@ -143,7 +143,7 @@ function choose(visibility: typeof misskey.noteVisibilities[number]): void {
|
|||
}
|
||||
}
|
||||
|
||||
> *:nth-child(3) {
|
||||
> .toggle {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
|
|
@ -9,10 +9,10 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { watch, ref } from 'vue';
|
||||
import { watch, shallowRef } from 'vue';
|
||||
import MkModal from '@/components/MkModal.vue';
|
||||
|
||||
const modal = ref<InstanceType<typeof MkModal>>();
|
||||
const modal = shallowRef<InstanceType<typeof MkModal>>();
|
||||
|
||||
const props = defineProps<{
|
||||
success: boolean;
|
||||
|
|
|
@ -88,7 +88,7 @@ const emit = defineEmits<{
|
|||
|
||||
provide('inWindow', true);
|
||||
|
||||
let rootEl = $ref<HTMLElement | null>();
|
||||
let rootEl = $shallowRef<HTMLElement | null>();
|
||||
let showing = $ref(true);
|
||||
let beforeClickedAt = 0;
|
||||
let maximized = $ref(false);
|
||||
|
|
|
@ -35,7 +35,7 @@ const emit = defineEmits<{
|
|||
(ev: 'update:modelValue', v: boolean): void;
|
||||
}>();
|
||||
|
||||
let button = $ref<HTMLElement>();
|
||||
let button = $shallowRef<HTMLElement>();
|
||||
const checked = toRefs(props).modelValue;
|
||||
const toggle = () => {
|
||||
if (props.disabled) return;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="dwzlatin" :class="{ opened }" ref="root">
|
||||
<div class="dwzlatin" :class="{ opened }">
|
||||
<div class="header _button" @click="toggle">
|
||||
<span class="icon"><slot name="icon"></slot></span>
|
||||
<span class="text"><slot name="label"></slot></span>
|
||||
|
@ -19,7 +19,7 @@
|
|||
>
|
||||
<KeepAlive>
|
||||
<div v-show="opened">
|
||||
<MkSpacer :margin-min="14" :margin-max="22" :container="root">
|
||||
<MkSpacer :margin-min="14" :margin-max="22">
|
||||
<slot></slot>
|
||||
</MkSpacer>
|
||||
</div>
|
||||
|
@ -40,7 +40,6 @@ const props = withDefaults(defineProps<{
|
|||
|
||||
let opened = $ref(props.defaultOpen);
|
||||
let openedAtLeastOnce = $ref(props.defaultOpen);
|
||||
let root = $ref<HTMLElement>();
|
||||
|
||||
function enter(el) {
|
||||
const elementHeight = el.getBoundingClientRect().height;
|
||||
|
@ -142,6 +141,7 @@ function toggle() {
|
|||
> .body {
|
||||
background: var(--panel);
|
||||
border-radius: 0 0 6px 6px;
|
||||
container-type: inline-size;
|
||||
}
|
||||
|
||||
&.opened {
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, onUnmounted, nextTick, ref, watch, computed, toRefs } from 'vue';
|
||||
import { onMounted, onUnmounted, nextTick, ref, shallowRef, watch, computed, toRefs } from 'vue';
|
||||
import { debounce } from 'throttle-debounce';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import { useInterval } from '@/scripts/use-interval';
|
||||
|
@ -74,9 +74,9 @@ const focused = ref(false);
|
|||
const changed = ref(false);
|
||||
const invalid = ref(false);
|
||||
const filled = computed(() => v.value !== '' && v.value != null);
|
||||
const inputEl = ref<HTMLElement>();
|
||||
const prefixEl = ref<HTMLElement>();
|
||||
const suffixEl = ref<HTMLElement>();
|
||||
const inputEl = shallowRef<HTMLElement>();
|
||||
const prefixEl = shallowRef<HTMLElement>();
|
||||
const suffixEl = shallowRef<HTMLElement>();
|
||||
const height =
|
||||
props.small ? 35 :
|
||||
props.large ? 39 :
|
||||
|
|
|
@ -34,7 +34,7 @@ const emit = defineEmits<{
|
|||
(ev: 'update:modelValue', v: boolean): void;
|
||||
}>();
|
||||
|
||||
let button = $ref<HTMLElement>();
|
||||
let button = $shallowRef<HTMLElement>();
|
||||
const checked = toRefs(props).modelValue;
|
||||
const toggle = () => {
|
||||
if (props.disabled) return;
|
||||
|
|
|
@ -77,9 +77,9 @@ const metadata = injectPageMetadata();
|
|||
const hideTitle = inject('shouldOmitHeaderTitle', false);
|
||||
const thin_ = props.thin || inject('shouldHeaderThin', false);
|
||||
|
||||
const el = $ref<HTMLElement | undefined>(undefined);
|
||||
const el = $shallowRef<HTMLElement | undefined>(undefined);
|
||||
const tabRefs: Record<string, HTMLElement | null> = {};
|
||||
const tabHighlightEl = $ref<HTMLElement | null>(null);
|
||||
const tabHighlightEl = $shallowRef<HTMLElement | null>(null);
|
||||
const bg = ref<string | undefined>(undefined);
|
||||
let narrow = $ref(false);
|
||||
const hasTabs = $computed(() => props.tabs.length > 0);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div ref="root" :class="$style.root" :style="{ padding: margin + 'px' }">
|
||||
<div ref="content" :class="$style.content">
|
||||
<div :class="[$style.root, { [$style.rootMin]: forceSpacerMin }]">
|
||||
<div :class="$style.content">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -14,85 +14,13 @@ const props = withDefaults(defineProps<{
|
|||
contentMax?: number | null;
|
||||
marginMin?: number;
|
||||
marginMax?: number;
|
||||
|
||||
// MkFolderとかで開閉アニメーションの際にheightを正しく伝えるため
|
||||
container?: HTMLElement,
|
||||
}>(), {
|
||||
contentMax: null,
|
||||
marginMin: 12,
|
||||
marginMax: 24,
|
||||
});
|
||||
|
||||
let ro: ResizeObserver;
|
||||
let root = $ref<HTMLElement>();
|
||||
let content = $ref<HTMLElement>();
|
||||
let margin = $ref(props.marginMin);
|
||||
const widthHistory = [null, null] as [number | null, number | null];
|
||||
const heightHistory = [null, null] as [number | null, number | null];
|
||||
const shouldSpacerMin = inject('shouldSpacerMin', false);
|
||||
|
||||
const adjust = (rect: { width: number; height: number; }) => {
|
||||
if (shouldSpacerMin || deviceKind === 'smartphone') {
|
||||
margin = props.marginMin;
|
||||
return;
|
||||
}
|
||||
|
||||
if (rect.width > (props.contentMax ?? 0) || (rect.width > 360 && window.innerWidth > 400)) {
|
||||
margin = props.marginMax;
|
||||
} else {
|
||||
margin = props.marginMin;
|
||||
}
|
||||
};
|
||||
|
||||
if (props.container) {
|
||||
const width = props.container.offsetWidth;
|
||||
const height = props.container.offsetHeight;
|
||||
adjust({
|
||||
width,
|
||||
height,
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
ro = new ResizeObserver((entries) => {
|
||||
/* iOSが対応していない
|
||||
adjust({
|
||||
width: entries[0].borderBoxSize[0].inlineSize,
|
||||
height: entries[0].borderBoxSize[0].blockSize,
|
||||
});
|
||||
*/
|
||||
|
||||
const width = props.container ? props.container.offsetWidth : root!.offsetWidth;
|
||||
const height = props.container ? props.container.offsetHeight : root!.offsetHeight;
|
||||
|
||||
//#region Prevent infinite resizing
|
||||
// https://github.com/misskey-dev/misskey/issues/9076
|
||||
const pastWidth = widthHistory.pop();
|
||||
widthHistory.unshift(width);
|
||||
const pastHeight = heightHistory.pop();
|
||||
heightHistory.unshift(height);
|
||||
|
||||
|
||||
if (pastWidth === width && pastHeight === height) {
|
||||
return;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
adjust({
|
||||
width,
|
||||
height,
|
||||
});
|
||||
});
|
||||
ro.observe(root!);
|
||||
|
||||
if (props.contentMax) {
|
||||
content!.style.maxWidth = `${props.contentMax}px`;
|
||||
}
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
ro.disconnect();
|
||||
});
|
||||
const forceSpacerMin = inject('forceSpacerMin', false) || deviceKind === 'smartphone';
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
|
@ -100,9 +28,25 @@ onUnmounted(() => {
|
|||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
}
|
||||
.rootMin {
|
||||
padding: v-bind('props.marginMin + "px"') !important;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin: 0 auto;
|
||||
max-width: v-bind('props.contentMax + "px"');
|
||||
container-type: inline-size;
|
||||
}
|
||||
|
||||
@container (max-width: 360px) {
|
||||
.root {
|
||||
padding: v-bind('props.marginMin + "px"');
|
||||
}
|
||||
}
|
||||
|
||||
@container (min-width: 361px) {
|
||||
.root {
|
||||
padding: v-bind('props.marginMax + "px"');
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -18,9 +18,9 @@ const CURRENT_STICKY_TOP = 'CURRENT_STICKY_TOP';
|
|||
<script lang="ts" setup>
|
||||
import { onMounted, onUnmounted, provide, inject, Ref, ref, watch } from 'vue';
|
||||
|
||||
const rootEl = $ref<HTMLElement>();
|
||||
const headerEl = $ref<HTMLElement>();
|
||||
const bodyEl = $ref<HTMLElement>();
|
||||
const rootEl = $shallowRef<HTMLElement>();
|
||||
const headerEl = $shallowRef<HTMLElement>();
|
||||
const bodyEl = $shallowRef<HTMLElement>();
|
||||
|
||||
let headerHeight = $ref<string | undefined>();
|
||||
let childStickyTop = $ref(0);
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
<script lang="ts">
|
||||
import { defineComponent, onMounted, nextTick, onUnmounted, PropType } from 'vue';
|
||||
import { parse } from '@syuilo/aiscript';
|
||||
import XBlock from './page.block.vue';
|
||||
import { Hpml } from '@/scripts/hpml/evaluator';
|
||||
import { url } from '@/config';
|
||||
|
@ -28,38 +27,11 @@ export default defineComponent({
|
|||
randomSeed: Math.random(),
|
||||
visitor: $i,
|
||||
url: url,
|
||||
enableAiScript: !defaultStore.state.disablePagesScript,
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
if (props.page.script && hpml.aiscript) {
|
||||
let ast;
|
||||
try {
|
||||
ast = parse(props.page.script);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
/*os.alert({
|
||||
type: 'error',
|
||||
text: 'Syntax error :('
|
||||
});*/
|
||||
return;
|
||||
}
|
||||
hpml.aiscript.exec(ast).then(() => {
|
||||
hpml.eval();
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
/*os.alert({
|
||||
type: 'error',
|
||||
text: err
|
||||
});*/
|
||||
});
|
||||
} else {
|
||||
hpml.eval();
|
||||
}
|
||||
});
|
||||
onUnmounted(() => {
|
||||
if (hpml.aiscript) hpml.aiscript.abort();
|
||||
hpml.eval();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -156,7 +156,7 @@ const patrons = [
|
|||
let easterEggReady = false;
|
||||
let easterEggEmojis = $ref([]);
|
||||
let easterEggEngine = $ref(null);
|
||||
const containerEl = $ref<HTMLElement>();
|
||||
const containerEl = $shallowRef<HTMLElement>();
|
||||
|
||||
function iconLoaded() {
|
||||
const emojis = defaultStore.state.reactions;
|
||||
|
|
|
@ -30,15 +30,13 @@
|
|||
<option value="-followers">{{ i18n.ts.followers }} ({{ i18n.ts.ascendingOrder }})</option>
|
||||
<option value="+caughtAt">{{ i18n.ts.registeredAt }} ({{ i18n.ts.descendingOrder }})</option>
|
||||
<option value="-caughtAt">{{ i18n.ts.registeredAt }} ({{ i18n.ts.ascendingOrder }})</option>
|
||||
<option value="+lastCommunicatedAt">{{ i18n.ts.lastCommunication }} ({{ i18n.ts.descendingOrder }})</option>
|
||||
<option value="-lastCommunicatedAt">{{ i18n.ts.lastCommunication }} ({{ i18n.ts.ascendingOrder }})</option>
|
||||
</MkSelect>
|
||||
</FormSplit>
|
||||
</div>
|
||||
|
||||
<MkPagination v-slot="{items}" ref="instances" :key="host + state" :pagination="pagination">
|
||||
<div class="dqokceoi">
|
||||
<MkA v-for="instance in items" :key="instance.id" v-tooltip.mfm="`Last communicated: ${dateString(instance.lastCommunicatedAt)}\nStatus: ${getStatus(instance)}`" class="instance" :to="`/instance-info/${instance.host}`">
|
||||
<MkA v-for="instance in items" :key="instance.id" v-tooltip.mfm="`Status: ${getStatus(instance)}`" class="instance" :to="`/instance-info/${instance.host}`">
|
||||
<MkInstanceCardMini :instance="instance"/>
|
||||
</MkA>
|
||||
</div>
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, onUnmounted, ref, inject, watch, nextTick } from 'vue';
|
||||
import { computed, onMounted, onUnmounted, ref, shallowRef, inject, watch, nextTick } from 'vue';
|
||||
import tinycolor from 'tinycolor2';
|
||||
import { popupMenu } from '@/os';
|
||||
import { url } from '@/config';
|
||||
|
@ -64,9 +64,9 @@ const emit = defineEmits<{
|
|||
|
||||
const metadata = injectPageMetadata();
|
||||
|
||||
const el = ref<HTMLElement>(null);
|
||||
const el = shallowRef<HTMLElement>(null);
|
||||
const tabRefs = {};
|
||||
const tabHighlightEl = $ref<HTMLElement | null>(null);
|
||||
const tabHighlightEl = $shallowRef<HTMLElement | null>(null);
|
||||
const bg = ref(null);
|
||||
const height = ref(0);
|
||||
const hasTabs = computed(() => {
|
||||
|
|
|
@ -58,7 +58,7 @@ import * as os from '@/os';
|
|||
import { i18n } from '@/i18n';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata';
|
||||
|
||||
let reports = $ref<InstanceType<typeof MkPagination>>();
|
||||
let reports = $shallowRef<InstanceType<typeof MkPagination>>();
|
||||
|
||||
let state = $ref('unresolved');
|
||||
let reporterOrigin = $ref('combined');
|
||||
|
|
|
@ -68,7 +68,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, defineAsyncComponent, defineComponent, ref, toRef } from 'vue';
|
||||
import { computed, defineAsyncComponent, defineComponent, ref, shallowRef } from 'vue';
|
||||
import XHeader from './_header_.vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import MkInput from '@/components/form/input.vue';
|
||||
|
@ -81,7 +81,7 @@ import * as os from '@/os';
|
|||
import { i18n } from '@/i18n';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata';
|
||||
|
||||
const emojisPaginationComponent = ref<InstanceType<typeof MkPagination>>();
|
||||
const emojisPaginationComponent = shallowRef<InstanceType<typeof MkPagination>>();
|
||||
|
||||
const tab = ref('local');
|
||||
const query = ref(null);
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
</div>
|
||||
</MkSpacer>
|
||||
</div>
|
||||
<div v-if="!(narrow && currentPage?.route.name == null)" class="main" style="container-type: inline-size;">
|
||||
<div v-if="!(narrow && currentPage?.route.name == null)" class="main">
|
||||
<RouterView/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,439 +0,0 @@
|
|||
<template>
|
||||
<div class="_debobigegoItem">
|
||||
<div class="_debobigegoLabel"><i class="fas fa-microchip"></i> {{ $ts.cpuAndMemory }}</div>
|
||||
<div class="_debobigegoPanel xhexznfu">
|
||||
<div>
|
||||
<canvas :ref="cpumem"></canvas>
|
||||
</div>
|
||||
<div v-if="serverInfo">
|
||||
<div class="_table">
|
||||
<div class="_row">
|
||||
<div class="_cell"><div class="_label">MEM total</div>{{ bytes(serverInfo.mem.total) }}</div>
|
||||
<div class="_cell"><div class="_label">MEM used</div>{{ bytes(memUsage) }} ({{ (memUsage / serverInfo.mem.total * 100).toFixed(0) }}%)</div>
|
||||
<div class="_cell"><div class="_label">MEM free</div>{{ bytes(serverInfo.mem.total - memUsage) }} ({{ ((serverInfo.mem.total - memUsage) / serverInfo.mem.total * 100).toFixed(0) }}%)</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="_debobigegoItem">
|
||||
<div class="_debobigegoLabel"><i class="fas fa-hdd"></i> {{ $ts.disk }}</div>
|
||||
<div class="_debobigegoPanel xhexznfu">
|
||||
<div>
|
||||
<canvas :ref="disk"></canvas>
|
||||
</div>
|
||||
<div v-if="serverInfo">
|
||||
<div class="_table">
|
||||
<div class="_row">
|
||||
<div class="_cell"><div class="_label">Disk total</div>{{ bytes(serverInfo.fs.total) }}</div>
|
||||
<div class="_cell"><div class="_label">Disk used</div>{{ bytes(serverInfo.fs.used) }} ({{ (serverInfo.fs.used / serverInfo.fs.total * 100).toFixed(0) }}%)</div>
|
||||
<div class="_cell"><div class="_label">Disk free</div>{{ bytes(serverInfo.fs.total - serverInfo.fs.used) }} ({{ ((serverInfo.fs.total - serverInfo.fs.used) / serverInfo.fs.total * 100).toFixed(0) }}%)</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="_debobigegoItem">
|
||||
<div class="_debobigegoLabel"><i class="fas fa-exchange-alt"></i> {{ $ts.network }}</div>
|
||||
<div class="_debobigegoPanel xhexznfu">
|
||||
<div>
|
||||
<canvas :ref="net"></canvas>
|
||||
</div>
|
||||
<div v-if="serverInfo">
|
||||
<div class="_table">
|
||||
<div class="_row">
|
||||
<div class="_cell"><div class="_label">Interface</div>{{ serverInfo.net.interface }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, markRaw } from 'vue';
|
||||
import { Chart } from 'chart.js';
|
||||
import MkwFederation from '../../widgets/federation.vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import MkSelect from '@/components/form/select.vue';
|
||||
import MkInput from '@/components/form/input.vue';
|
||||
import MkContainer from '@/components/MkContainer.vue';
|
||||
import MkFolder from '@/components/MkFolder.vue';
|
||||
import { version, url } from '@/config';
|
||||
import bytes from '@/filters/bytes';
|
||||
import number from '@/filters/number';
|
||||
import * as os from '@/os';
|
||||
import { stream } from '@/stream';
|
||||
import { alpha } from '@/scripts/color';
|
||||
import { initChart } from '@/scripts/init-chart';
|
||||
|
||||
initChart();
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
MkButton,
|
||||
MkSelect,
|
||||
MkInput,
|
||||
MkContainer,
|
||||
MkFolder,
|
||||
MkwFederation,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
version,
|
||||
url,
|
||||
stats: null,
|
||||
serverInfo: null,
|
||||
connection: null,
|
||||
queueConnection: markRaw(stream.useChannel('queueStats')),
|
||||
memUsage: 0,
|
||||
chartCpuMem: null,
|
||||
chartNet: null,
|
||||
jobs: [],
|
||||
logs: [],
|
||||
logLevel: 'all',
|
||||
logDomain: '',
|
||||
modLogs: [],
|
||||
dbInfo: null,
|
||||
overviewHeight: '1fr',
|
||||
queueHeight: '1fr',
|
||||
paused: false,
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
gridColor() {
|
||||
// TODO: var(--panel)の色が暗いか明るいかで判定する
|
||||
return this.$store.state.darkMode ? 'rgba(255, 255, 255, 0.1)' : 'rgba(0, 0, 0, 0.1)';
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.fetchJobs();
|
||||
|
||||
Chart.defaults.color = getComputedStyle(document.documentElement).getPropertyValue('--fg');
|
||||
|
||||
os.api('admin/server-info', {}).then(res => {
|
||||
this.serverInfo = res;
|
||||
|
||||
this.connection = markRaw(stream.useChannel('serverStats'));
|
||||
this.connection.on('stats', this.onStats);
|
||||
this.connection.on('statsLog', this.onStatsLog);
|
||||
this.connection.send('requestLog', {
|
||||
id: Math.random().toString().substr(2, 8),
|
||||
length: 150,
|
||||
});
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.queueConnection.send('requestLog', {
|
||||
id: Math.random().toString().substr(2, 8),
|
||||
length: 200,
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
beforeUnmount() {
|
||||
if (this.connection) {
|
||||
this.connection.off('stats', this.onStats);
|
||||
this.connection.off('statsLog', this.onStatsLog);
|
||||
this.connection.dispose();
|
||||
}
|
||||
this.queueConnection.dispose();
|
||||
},
|
||||
|
||||
methods: {
|
||||
cpumem(el) {
|
||||
if (this.chartCpuMem != null) return;
|
||||
this.chartCpuMem = markRaw(new Chart(el, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: [],
|
||||
datasets: [{
|
||||
label: 'CPU',
|
||||
pointRadius: 0,
|
||||
tension: 0,
|
||||
borderWidth: 2,
|
||||
borderColor: '#86b300',
|
||||
backgroundColor: alpha('#86b300', 0.1),
|
||||
data: [],
|
||||
}, {
|
||||
label: 'MEM (active)',
|
||||
pointRadius: 0,
|
||||
tension: 0,
|
||||
borderWidth: 2,
|
||||
borderColor: '#935dbf',
|
||||
backgroundColor: alpha('#935dbf', 0.02),
|
||||
data: [],
|
||||
}, {
|
||||
label: 'MEM (used)',
|
||||
pointRadius: 0,
|
||||
tension: 0,
|
||||
borderWidth: 2,
|
||||
borderColor: '#935dbf',
|
||||
borderDash: [5, 5],
|
||||
fill: false,
|
||||
data: [],
|
||||
}],
|
||||
},
|
||||
options: {
|
||||
aspectRatio: 3,
|
||||
layout: {
|
||||
padding: {
|
||||
left: 16,
|
||||
right: 16,
|
||||
top: 16,
|
||||
bottom: 0,
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
position: 'bottom',
|
||||
labels: {
|
||||
boxWidth: 16,
|
||||
},
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
gridLines: {
|
||||
display: false,
|
||||
color: this.gridColor,
|
||||
zeroLineColor: this.gridColor,
|
||||
},
|
||||
ticks: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
y: {
|
||||
position: 'right',
|
||||
gridLines: {
|
||||
display: true,
|
||||
color: this.gridColor,
|
||||
zeroLineColor: this.gridColor,
|
||||
},
|
||||
ticks: {
|
||||
display: false,
|
||||
max: 100,
|
||||
},
|
||||
},
|
||||
},
|
||||
tooltips: {
|
||||
intersect: false,
|
||||
mode: 'index',
|
||||
},
|
||||
},
|
||||
}));
|
||||
},
|
||||
|
||||
net(el) {
|
||||
if (this.chartNet != null) return;
|
||||
this.chartNet = markRaw(new Chart(el, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: [],
|
||||
datasets: [{
|
||||
label: 'In',
|
||||
pointRadius: 0,
|
||||
tension: 0,
|
||||
borderWidth: 2,
|
||||
borderColor: '#94a029',
|
||||
backgroundColor: alpha('#94a029', 0.1),
|
||||
data: [],
|
||||
}, {
|
||||
label: 'Out',
|
||||
pointRadius: 0,
|
||||
tension: 0,
|
||||
borderWidth: 2,
|
||||
borderColor: '#ff9156',
|
||||
backgroundColor: alpha('#ff9156', 0.1),
|
||||
data: [],
|
||||
}],
|
||||
},
|
||||
options: {
|
||||
aspectRatio: 3,
|
||||
layout: {
|
||||
padding: {
|
||||
left: 16,
|
||||
right: 16,
|
||||
top: 16,
|
||||
bottom: 0,
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
position: 'bottom',
|
||||
labels: {
|
||||
boxWidth: 16,
|
||||
},
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
gridLines: {
|
||||
display: false,
|
||||
color: this.gridColor,
|
||||
zeroLineColor: this.gridColor,
|
||||
},
|
||||
ticks: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
y: {
|
||||
position: 'right',
|
||||
gridLines: {
|
||||
display: true,
|
||||
color: this.gridColor,
|
||||
zeroLineColor: this.gridColor,
|
||||
},
|
||||
ticks: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
tooltips: {
|
||||
intersect: false,
|
||||
mode: 'index',
|
||||
},
|
||||
},
|
||||
}));
|
||||
},
|
||||
|
||||
disk(el) {
|
||||
if (this.chartDisk != null) return;
|
||||
this.chartDisk = markRaw(new Chart(el, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: [],
|
||||
datasets: [{
|
||||
label: 'Read',
|
||||
pointRadius: 0,
|
||||
tension: 0,
|
||||
borderWidth: 2,
|
||||
borderColor: '#94a029',
|
||||
backgroundColor: alpha('#94a029', 0.1),
|
||||
data: [],
|
||||
}, {
|
||||
label: 'Write',
|
||||
pointRadius: 0,
|
||||
tension: 0,
|
||||
borderWidth: 2,
|
||||
borderColor: '#ff9156',
|
||||
backgroundColor: alpha('#ff9156', 0.1),
|
||||
data: [],
|
||||
}],
|
||||
},
|
||||
options: {
|
||||
aspectRatio: 3,
|
||||
layout: {
|
||||
padding: {
|
||||
left: 16,
|
||||
right: 16,
|
||||
top: 16,
|
||||
bottom: 0,
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
position: 'bottom',
|
||||
labels: {
|
||||
boxWidth: 16,
|
||||
},
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
gridLines: {
|
||||
display: false,
|
||||
color: this.gridColor,
|
||||
zeroLineColor: this.gridColor,
|
||||
},
|
||||
ticks: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
y: {
|
||||
position: 'right',
|
||||
gridLines: {
|
||||
display: true,
|
||||
color: this.gridColor,
|
||||
zeroLineColor: this.gridColor,
|
||||
},
|
||||
ticks: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
tooltips: {
|
||||
intersect: false,
|
||||
mode: 'index',
|
||||
},
|
||||
},
|
||||
}));
|
||||
},
|
||||
|
||||
fetchJobs() {
|
||||
os.api('admin/queue/deliver-delayed', {}).then(jobs => {
|
||||
this.jobs = jobs;
|
||||
});
|
||||
},
|
||||
|
||||
onStats(stats) {
|
||||
if (this.paused) return;
|
||||
|
||||
const cpu = (stats.cpu * 100).toFixed(0);
|
||||
const memActive = (stats.mem.active / this.serverInfo.mem.total * 100).toFixed(0);
|
||||
const memUsed = (stats.mem.used / this.serverInfo.mem.total * 100).toFixed(0);
|
||||
this.memUsage = stats.mem.active;
|
||||
|
||||
this.chartCpuMem.data.labels.push('');
|
||||
this.chartCpuMem.data.datasets[0].data.push(cpu);
|
||||
this.chartCpuMem.data.datasets[1].data.push(memActive);
|
||||
this.chartCpuMem.data.datasets[2].data.push(memUsed);
|
||||
this.chartNet.data.labels.push('');
|
||||
this.chartNet.data.datasets[0].data.push(stats.net.rx);
|
||||
this.chartNet.data.datasets[1].data.push(stats.net.tx);
|
||||
this.chartDisk.data.labels.push('');
|
||||
this.chartDisk.data.datasets[0].data.push(stats.fs.r);
|
||||
this.chartDisk.data.datasets[1].data.push(stats.fs.w);
|
||||
if (this.chartCpuMem.data.datasets[0].data.length > 150) {
|
||||
this.chartCpuMem.data.labels.shift();
|
||||
this.chartCpuMem.data.datasets[0].data.shift();
|
||||
this.chartCpuMem.data.datasets[1].data.shift();
|
||||
this.chartCpuMem.data.datasets[2].data.shift();
|
||||
this.chartNet.data.labels.shift();
|
||||
this.chartNet.data.datasets[0].data.shift();
|
||||
this.chartNet.data.datasets[1].data.shift();
|
||||
this.chartDisk.data.labels.shift();
|
||||
this.chartDisk.data.datasets[0].data.shift();
|
||||
this.chartDisk.data.datasets[1].data.shift();
|
||||
}
|
||||
this.chartCpuMem.update();
|
||||
this.chartNet.update();
|
||||
this.chartDisk.update();
|
||||
},
|
||||
|
||||
onStatsLog(statsLog) {
|
||||
for (const stats of [...statsLog].reverse()) {
|
||||
this.onStats(stats);
|
||||
}
|
||||
},
|
||||
|
||||
bytes,
|
||||
|
||||
number,
|
||||
|
||||
pause() {
|
||||
this.paused = true;
|
||||
},
|
||||
|
||||
resume() {
|
||||
this.paused = false;
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.xhexznfu {
|
||||
> div:nth-child(2) {
|
||||
padding: 16px;
|
||||
border-top: solid 0.5px var(--divider);
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -12,18 +12,17 @@ import { markRaw, version as vueVersion, onMounted, onBeforeUnmount, nextTick }
|
|||
import { Chart } from 'chart.js';
|
||||
import { enUS } from 'date-fns/locale';
|
||||
import tinycolor from 'tinycolor2';
|
||||
import gradient from 'chartjs-plugin-gradient';
|
||||
import * as os from '@/os';
|
||||
import 'chartjs-adapter-date-fns';
|
||||
import { defaultStore } from '@/store';
|
||||
import { useChartTooltip } from '@/scripts/use-chart-tooltip';
|
||||
import gradient from 'chartjs-plugin-gradient';
|
||||
import { chartVLine } from '@/scripts/chart-vline';
|
||||
import { alpha } from '@/scripts/color';
|
||||
import { initChart } from '@/scripts/init-chart';
|
||||
|
||||
initChart();
|
||||
|
||||
const chartEl = $ref<HTMLCanvasElement>(null);
|
||||
const chartEl = $shallowRef<HTMLCanvasElement>(null);
|
||||
const now = new Date();
|
||||
let chartInstance: Chart = null;
|
||||
const chartLimit = 7;
|
||||
|
|
|
@ -34,8 +34,8 @@ import { initChart } from '@/scripts/init-chart';
|
|||
initChart();
|
||||
|
||||
const chartLimit = 50;
|
||||
const chartEl = $ref<HTMLCanvasElement>();
|
||||
const chartEl2 = $ref<HTMLCanvasElement>();
|
||||
const chartEl = $shallowRef<HTMLCanvasElement>();
|
||||
const chartEl2 = $shallowRef<HTMLCanvasElement>();
|
||||
let fetching = $ref(true);
|
||||
|
||||
const { handler: externalTooltipHandler } = useChartTooltip();
|
||||
|
|
|
@ -22,7 +22,7 @@ const fetching = ref(true);
|
|||
|
||||
const fetch = async () => {
|
||||
const fetchedInstances = await os.api('federation/instances', {
|
||||
sort: '+lastCommunicatedAt',
|
||||
sort: '+latestRequestReceivedAt',
|
||||
limit: 6,
|
||||
});
|
||||
instances.value = fetchedInstances;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, onUnmounted, ref } from 'vue';
|
||||
import { onMounted, onUnmounted, ref, shallowRef } from 'vue';
|
||||
import { Chart } from 'chart.js';
|
||||
import number from '@/filters/number';
|
||||
import { defaultStore } from '@/store';
|
||||
|
@ -16,7 +16,7 @@ const props = defineProps<{
|
|||
data: { name: string; value: number; color: string; onClick?: () => void }[];
|
||||
}>();
|
||||
|
||||
const chartEl = ref<HTMLCanvasElement>(null);
|
||||
const chartEl = shallowRef<HTMLCanvasElement>(null);
|
||||
|
||||
const { handler: externalTooltipHandler } = useChartTooltip({
|
||||
position: 'middle',
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { watch, onMounted, onUnmounted, ref } from 'vue';
|
||||
import { watch, onMounted, onUnmounted, ref, shallowRef } from 'vue';
|
||||
import { Chart } from 'chart.js';
|
||||
import number from '@/filters/number';
|
||||
import * as os from '@/os';
|
||||
|
@ -19,7 +19,7 @@ const props = defineProps<{
|
|||
type: string;
|
||||
}>();
|
||||
|
||||
const chartEl = ref<HTMLCanvasElement>(null);
|
||||
const chartEl = shallowRef<HTMLCanvasElement>(null);
|
||||
|
||||
const { handler: externalTooltipHandler } = useChartTooltip();
|
||||
|
||||
|
|
|
@ -43,10 +43,10 @@ const activeSincePrevTick = ref(0);
|
|||
const active = ref(0);
|
||||
const delayed = ref(0);
|
||||
const waiting = ref(0);
|
||||
let chartProcess = $ref<InstanceType<typeof XChart>>();
|
||||
let chartActive = $ref<InstanceType<typeof XChart>>();
|
||||
let chartDelayed = $ref<InstanceType<typeof XChart>>();
|
||||
let chartWaiting = $ref<InstanceType<typeof XChart>>();
|
||||
let chartProcess = $shallowRef<InstanceType<typeof XChart>>();
|
||||
let chartActive = $shallowRef<InstanceType<typeof XChart>>();
|
||||
let chartDelayed = $shallowRef<InstanceType<typeof XChart>>();
|
||||
let chartWaiting = $shallowRef<InstanceType<typeof XChart>>();
|
||||
|
||||
const props = defineProps<{
|
||||
domain: string;
|
||||
|
|
|
@ -77,12 +77,11 @@ import * as os from '@/os';
|
|||
import { stream } from '@/stream';
|
||||
import { i18n } from '@/i18n';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata';
|
||||
import 'chartjs-adapter-date-fns';
|
||||
import { defaultStore } from '@/store';
|
||||
import MkFileListForAdmin from '@/components/MkFileListForAdmin.vue';
|
||||
import MkFolder from '@/components/MkFolder.vue';
|
||||
|
||||
const rootEl = $ref<HTMLElement>();
|
||||
const rootEl = $shallowRef<HTMLElement>();
|
||||
let serverInfo: any = $ref(null);
|
||||
let topSubInstancesForPie: any = $ref(null);
|
||||
let topPubInstancesForPie: any = $ref(null);
|
||||
|
@ -153,7 +152,7 @@ onMounted(async () => {
|
|||
});
|
||||
|
||||
os.api('federation/instances', {
|
||||
sort: '+lastCommunicatedAt',
|
||||
sort: '+latestRequestReceivedAt',
|
||||
limit: 25,
|
||||
}).then(res => {
|
||||
activeInstances = res;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { watch, onMounted, onUnmounted, ref } from 'vue';
|
||||
import { watch, onMounted, onUnmounted, ref, shallowRef } from 'vue';
|
||||
import { Chart } from 'chart.js';
|
||||
import number from '@/filters/number';
|
||||
import * as os from '@/os';
|
||||
|
@ -19,7 +19,7 @@ const props = defineProps<{
|
|||
type: string;
|
||||
}>();
|
||||
|
||||
const chartEl = ref<HTMLCanvasElement>(null);
|
||||
const chartEl = shallowRef<HTMLCanvasElement>(null);
|
||||
|
||||
const { handler: externalTooltipHandler } = useChartTooltip();
|
||||
|
||||
|
|
|
@ -53,10 +53,10 @@ const active = ref(0);
|
|||
const delayed = ref(0);
|
||||
const waiting = ref(0);
|
||||
const jobs = ref([]);
|
||||
let chartProcess = $ref<InstanceType<typeof XChart>>();
|
||||
let chartActive = $ref<InstanceType<typeof XChart>>();
|
||||
let chartDelayed = $ref<InstanceType<typeof XChart>>();
|
||||
let chartWaiting = $ref<InstanceType<typeof XChart>>();
|
||||
let chartProcess = $shallowRef<InstanceType<typeof XChart>>();
|
||||
let chartActive = $shallowRef<InstanceType<typeof XChart>>();
|
||||
let chartDelayed = $shallowRef<InstanceType<typeof XChart>>();
|
||||
let chartWaiting = $shallowRef<InstanceType<typeof XChart>>();
|
||||
|
||||
const props = defineProps<{
|
||||
domain: string;
|
||||
|
|
|
@ -65,7 +65,7 @@ import { definePageMetadata } from '@/scripts/page-metadata';
|
|||
import MkUserCardMini from '@/components/MkUserCardMini.vue';
|
||||
import { dateString } from '@/filters/date';
|
||||
|
||||
let paginationComponent = $ref<InstanceType<typeof MkPagination>>();
|
||||
let paginationComponent = $shallowRef<InstanceType<typeof MkPagination>>();
|
||||
|
||||
let sort = $ref('+createdAt');
|
||||
let state = $ref('all');
|
||||
|
|
|
@ -34,8 +34,8 @@ const props = defineProps<{
|
|||
|
||||
let antenna = $ref(null);
|
||||
let queue = $ref(0);
|
||||
let rootEl = $ref<HTMLElement>();
|
||||
let tlEl = $ref<InstanceType<typeof XTimeline>>();
|
||||
let rootEl = $shallowRef<HTMLElement>();
|
||||
let tlEl = $shallowRef<InstanceType<typeof XTimeline>>();
|
||||
const keymap = $computed(() => ({
|
||||
't': focus,
|
||||
}));
|
||||
|
|
|
@ -72,7 +72,7 @@ const props = defineProps<{
|
|||
}>();
|
||||
|
||||
let origin = $ref('local');
|
||||
let tagsEl = $ref<InstanceType<typeof MkFolder>>();
|
||||
let tagsEl = $shallowRef<InstanceType<typeof MkFolder>>();
|
||||
let tagsLocal = $ref([]);
|
||||
let tagsRemote = $ref([]);
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ const props = withDefaults(defineProps<{
|
|||
});
|
||||
|
||||
let tab = $ref(props.initialTab);
|
||||
let tagsEl = $ref<InstanceType<typeof MkFolder>>();
|
||||
let tagsEl = $shallowRef<InstanceType<typeof MkFolder>>();
|
||||
let searchQuery = $ref(null);
|
||||
let searchOrigin = $ref('combined');
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue