色々fix
This commit is contained in:
parent
805280874b
commit
592c6e60a9
|
@ -14,6 +14,7 @@ export interface Locale {
|
||||||
"forgotPassword": string;
|
"forgotPassword": string;
|
||||||
"fetchingAsApObject": string;
|
"fetchingAsApObject": string;
|
||||||
"ok": string;
|
"ok": string;
|
||||||
|
"ruby": string;
|
||||||
"gotIt": string;
|
"gotIt": string;
|
||||||
"cancel": string;
|
"cancel": string;
|
||||||
"noThankYou": string;
|
"noThankYou": string;
|
||||||
|
|
|
@ -11,6 +11,7 @@ password: "パスワード"
|
||||||
forgotPassword: "パスワードを忘れた"
|
forgotPassword: "パスワードを忘れた"
|
||||||
fetchingAsApObject: "連合に照会中"
|
fetchingAsApObject: "連合に照会中"
|
||||||
ok: "OK"
|
ok: "OK"
|
||||||
|
ruby: "ルビ"
|
||||||
gotIt: "わかった"
|
gotIt: "わかった"
|
||||||
cancel: "キャンセル"
|
cancel: "キャンセル"
|
||||||
noThankYou: "やめておく"
|
noThankYou: "やめておく"
|
||||||
|
|
|
@ -330,6 +330,7 @@ import * as ep___users_following from './endpoints/users/following.js';
|
||||||
import * as ep___users_gallery_posts from './endpoints/users/gallery/posts.js';
|
import * as ep___users_gallery_posts from './endpoints/users/gallery/posts.js';
|
||||||
import * as ep___users_getFrequentlyRepliedUsers from './endpoints/users/get-frequently-replied-users.js';
|
import * as ep___users_getFrequentlyRepliedUsers from './endpoints/users/get-frequently-replied-users.js';
|
||||||
import * as ep___users_featuredNotes from './endpoints/users/featured-notes.js';
|
import * as ep___users_featuredNotes from './endpoints/users/featured-notes.js';
|
||||||
|
import * as ep___users_user_stats from './endpoints/users/stats.js';
|
||||||
import * as ep___users_lists_create from './endpoints/users/lists/create.js';
|
import * as ep___users_lists_create from './endpoints/users/lists/create.js';
|
||||||
import * as ep___users_lists_delete from './endpoints/users/lists/delete.js';
|
import * as ep___users_lists_delete from './endpoints/users/lists/delete.js';
|
||||||
import * as ep___users_lists_list from './endpoints/users/lists/list.js';
|
import * as ep___users_lists_list from './endpoints/users/lists/list.js';
|
||||||
|
@ -567,6 +568,7 @@ const $i_importMuting: Provider = { provide: 'ep:i/import-muting', useClass: ep_
|
||||||
const $i_importUserLists: Provider = { provide: 'ep:i/import-user-lists', useClass: ep___i_importUserLists.default };
|
const $i_importUserLists: Provider = { provide: 'ep:i/import-user-lists', useClass: ep___i_importUserLists.default };
|
||||||
const $i_importAntennas: Provider = { provide: 'ep:i/import-antennas', useClass: ep___i_importAntennas.default };
|
const $i_importAntennas: Provider = { provide: 'ep:i/import-antennas', useClass: ep___i_importAntennas.default };
|
||||||
const $i_notifications: Provider = { provide: 'ep:i/notifications', useClass: ep___i_notifications.default };
|
const $i_notifications: Provider = { provide: 'ep:i/notifications', useClass: ep___i_notifications.default };
|
||||||
|
const $i_userstats: Provider = { provide: 'ep:i/stats', useClass: ep___users_user_stats.default }
|
||||||
const $i_pageLikes: Provider = { provide: 'ep:i/page-likes', useClass: ep___i_pageLikes.default };
|
const $i_pageLikes: Provider = { provide: 'ep:i/page-likes', useClass: ep___i_pageLikes.default };
|
||||||
const $i_pages: Provider = { provide: 'ep:i/pages', useClass: ep___i_pages.default };
|
const $i_pages: Provider = { provide: 'ep:i/pages', useClass: ep___i_pages.default };
|
||||||
const $i_pin: Provider = { provide: 'ep:i/pin', useClass: ep___i_pin.default };
|
const $i_pin: Provider = { provide: 'ep:i/pin', useClass: ep___i_pin.default };
|
||||||
|
@ -816,6 +818,7 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention
|
||||||
$channels_timeline,
|
$channels_timeline,
|
||||||
$channels_unfollow,
|
$channels_unfollow,
|
||||||
$channels_update,
|
$channels_update,
|
||||||
|
$i_userstats,
|
||||||
$channels_favorite,
|
$channels_favorite,
|
||||||
$channels_unfavorite,
|
$channels_unfavorite,
|
||||||
$channels_myFavorites,
|
$channels_myFavorites,
|
||||||
|
@ -1103,6 +1106,7 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention
|
||||||
$admin_emoji_setisSensitiveBulk,
|
$admin_emoji_setisSensitiveBulk,
|
||||||
$admin_emoji_update,
|
$admin_emoji_update,
|
||||||
$admin_federation_deleteAllFiles,
|
$admin_federation_deleteAllFiles,
|
||||||
|
$i_userstats,
|
||||||
$admin_federation_refreshRemoteInstanceMetadata,
|
$admin_federation_refreshRemoteInstanceMetadata,
|
||||||
$admin_federation_removeAllFollowing,
|
$admin_federation_removeAllFollowing,
|
||||||
$admin_federation_updateInstance,
|
$admin_federation_updateInstance,
|
||||||
|
|
|
@ -237,6 +237,7 @@ import * as ep___i_webhooks_show from './endpoints/i/webhooks/show.js';
|
||||||
import * as ep___i_webhooks_list from './endpoints/i/webhooks/list.js';
|
import * as ep___i_webhooks_list from './endpoints/i/webhooks/list.js';
|
||||||
import * as ep___i_webhooks_update from './endpoints/i/webhooks/update.js';
|
import * as ep___i_webhooks_update from './endpoints/i/webhooks/update.js';
|
||||||
import * as ep___i_webhooks_delete from './endpoints/i/webhooks/delete.js';
|
import * as ep___i_webhooks_delete from './endpoints/i/webhooks/delete.js';
|
||||||
|
import * as ep___i_user_stats from './endpoints/users/stats.js';
|
||||||
import * as ep___invite_create from './endpoints/invite/create.js';
|
import * as ep___invite_create from './endpoints/invite/create.js';
|
||||||
import * as ep___invite_delete from './endpoints/invite/delete.js';
|
import * as ep___invite_delete from './endpoints/invite/delete.js';
|
||||||
import * as ep___invite_list from './endpoints/invite/list.js';
|
import * as ep___invite_list from './endpoints/invite/list.js';
|
||||||
|
@ -589,6 +590,7 @@ const eps = [
|
||||||
['i/webhooks/show', ep___i_webhooks_show],
|
['i/webhooks/show', ep___i_webhooks_show],
|
||||||
['i/webhooks/update', ep___i_webhooks_update],
|
['i/webhooks/update', ep___i_webhooks_update],
|
||||||
['i/webhooks/delete', ep___i_webhooks_delete],
|
['i/webhooks/delete', ep___i_webhooks_delete],
|
||||||
|
['i/stats', ep___i_user_stats],
|
||||||
['invite/create', ep___invite_create],
|
['invite/create', ep___invite_create],
|
||||||
['invite/delete', ep___invite_delete],
|
['invite/delete', ep___invite_delete],
|
||||||
['invite/list', ep___invite_list],
|
['invite/list', ep___invite_list],
|
||||||
|
|
|
@ -0,0 +1,228 @@
|
||||||
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
|
import { awaitAll } from '@/misc/prelude/await-all.js';
|
||||||
|
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||||
|
import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js';
|
||||||
|
import { DI } from '@/di-symbols.js';
|
||||||
|
import type { UsersRepository, NotesRepository, FollowingsRepository, DriveFilesRepository, NoteReactionsRepository, PageLikesRepository, NoteFavoritesRepository, PollVotesRepository } from '@/models/index.js';
|
||||||
|
import { ApiError } from '../../error.js';
|
||||||
|
|
||||||
|
export const meta = {
|
||||||
|
tags: ['users'],
|
||||||
|
|
||||||
|
requireCredential: false,
|
||||||
|
|
||||||
|
description: 'Show statistics about a user.',
|
||||||
|
|
||||||
|
errors: {
|
||||||
|
noSuchUser: {
|
||||||
|
message: 'No such user.',
|
||||||
|
code: 'NO_SUCH_USER',
|
||||||
|
id: '9e638e45-3b25-4ef7-8f95-07e8498f1819',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
res: {
|
||||||
|
type: 'object',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
properties: {
|
||||||
|
notesCount: {
|
||||||
|
type: 'integer',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
repliesCount: {
|
||||||
|
type: 'integer',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
renotesCount: {
|
||||||
|
type: 'integer',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
repliedCount: {
|
||||||
|
type: 'integer',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
renotedCount: {
|
||||||
|
type: 'integer',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
pollVotesCount: {
|
||||||
|
type: 'integer',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
pollVotedCount: {
|
||||||
|
type: 'integer',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
localFollowingCount: {
|
||||||
|
type: 'integer',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
remoteFollowingCount: {
|
||||||
|
type: 'integer',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
localFollowersCount: {
|
||||||
|
type: 'integer',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
remoteFollowersCount: {
|
||||||
|
type: 'integer',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
followingCount: {
|
||||||
|
type: 'integer',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
followersCount: {
|
||||||
|
type: 'integer',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
sentReactionsCount: {
|
||||||
|
type: 'integer',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
receivedReactionsCount: {
|
||||||
|
type: 'integer',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
noteFavoritesCount: {
|
||||||
|
type: 'integer',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
pageLikesCount: {
|
||||||
|
type: 'integer',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
pageLikedCount: {
|
||||||
|
type: 'integer',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
driveFilesCount: {
|
||||||
|
type: 'integer',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
|
driveUsage: {
|
||||||
|
type: 'integer',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
description: 'Drive usage in bytes',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export const paramDef = {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
userId: { type: 'string', format: 'misskey:id' },
|
||||||
|
},
|
||||||
|
required: ['userId'],
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
// eslint-disable-next-line import/no-default-export
|
||||||
|
@Injectable()
|
||||||
|
export default class extends Endpoint<typeof meta, typeof paramDef> {
|
||||||
|
constructor(
|
||||||
|
@Inject(DI.usersRepository)
|
||||||
|
private usersRepository: UsersRepository,
|
||||||
|
|
||||||
|
@Inject(DI.notesRepository)
|
||||||
|
private notesRepository: NotesRepository,
|
||||||
|
|
||||||
|
@Inject(DI.followingsRepository)
|
||||||
|
private followingsRepository: FollowingsRepository,
|
||||||
|
|
||||||
|
@Inject(DI.driveFilesRepository)
|
||||||
|
private driveFilesRepository: DriveFilesRepository,
|
||||||
|
|
||||||
|
@Inject(DI.noteReactionsRepository)
|
||||||
|
private noteReactionsRepository: NoteReactionsRepository,
|
||||||
|
|
||||||
|
@Inject(DI.pageLikesRepository)
|
||||||
|
private pageLikesRepository: PageLikesRepository,
|
||||||
|
|
||||||
|
@Inject(DI.noteFavoritesRepository)
|
||||||
|
private noteFavoritesRepository: NoteFavoritesRepository,
|
||||||
|
|
||||||
|
@Inject(DI.pollVotesRepository)
|
||||||
|
private pollVotesRepository: PollVotesRepository,
|
||||||
|
|
||||||
|
private driveFileEntityService: DriveFileEntityService,
|
||||||
|
) {
|
||||||
|
super(meta, paramDef, async (ps, me) => {
|
||||||
|
const user = await this.usersRepository.findOneBy({ id: ps.userId });
|
||||||
|
if (user == null) {
|
||||||
|
throw new ApiError(meta.errors.noSuchUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await awaitAll({
|
||||||
|
notesCount: this.notesRepository.createQueryBuilder('note')
|
||||||
|
.where('note.userId = :userId', { userId: user.id })
|
||||||
|
.getCount(),
|
||||||
|
repliesCount: this.notesRepository.createQueryBuilder('note')
|
||||||
|
.where('note.userId = :userId', { userId: user.id })
|
||||||
|
.andWhere('note.replyId IS NOT NULL')
|
||||||
|
.getCount(),
|
||||||
|
renotesCount: this.notesRepository.createQueryBuilder('note')
|
||||||
|
.where('note.userId = :userId', { userId: user.id })
|
||||||
|
.andWhere('note.renoteId IS NOT NULL')
|
||||||
|
.getCount(),
|
||||||
|
repliedCount: this.notesRepository.createQueryBuilder('note')
|
||||||
|
.where('note.replyUserId = :userId', { userId: user.id })
|
||||||
|
.getCount(),
|
||||||
|
renotedCount: this.notesRepository.createQueryBuilder('note')
|
||||||
|
.where('note.renoteUserId = :userId', { userId: user.id })
|
||||||
|
.getCount(),
|
||||||
|
pollVotesCount: this.pollVotesRepository.createQueryBuilder('vote')
|
||||||
|
.where('vote.userId = :userId', { userId: user.id })
|
||||||
|
.getCount(),
|
||||||
|
pollVotedCount: this.pollVotesRepository.createQueryBuilder('vote')
|
||||||
|
.innerJoin('vote.note', 'note')
|
||||||
|
.where('note.userId = :userId', { userId: user.id })
|
||||||
|
.getCount(),
|
||||||
|
localFollowingCount: this.followingsRepository.createQueryBuilder('following')
|
||||||
|
.where('following.followerId = :userId', { userId: user.id })
|
||||||
|
.andWhere('following.followeeHost IS NULL')
|
||||||
|
.getCount(),
|
||||||
|
remoteFollowingCount: this.followingsRepository.createQueryBuilder('following')
|
||||||
|
.where('following.followerId = :userId', { userId: user.id })
|
||||||
|
.andWhere('following.followeeHost IS NOT NULL')
|
||||||
|
.getCount(),
|
||||||
|
localFollowersCount: this.followingsRepository.createQueryBuilder('following')
|
||||||
|
.where('following.followeeId = :userId', { userId: user.id })
|
||||||
|
.andWhere('following.followerHost IS NULL')
|
||||||
|
.getCount(),
|
||||||
|
remoteFollowersCount: this.followingsRepository.createQueryBuilder('following')
|
||||||
|
.where('following.followeeId = :userId', { userId: user.id })
|
||||||
|
.andWhere('following.followerHost IS NOT NULL')
|
||||||
|
.getCount(),
|
||||||
|
sentReactionsCount: this.noteReactionsRepository.createQueryBuilder('reaction')
|
||||||
|
.where('reaction.userId = :userId', { userId: user.id })
|
||||||
|
.getCount(),
|
||||||
|
receivedReactionsCount: this.noteReactionsRepository.createQueryBuilder('reaction')
|
||||||
|
.innerJoin('reaction.note', 'note')
|
||||||
|
.where('note.userId = :userId', { userId: user.id })
|
||||||
|
.getCount(),
|
||||||
|
noteFavoritesCount: this.noteFavoritesRepository.createQueryBuilder('favorite')
|
||||||
|
.where('favorite.userId = :userId', { userId: user.id })
|
||||||
|
.getCount(),
|
||||||
|
pageLikesCount: this.pageLikesRepository.createQueryBuilder('like')
|
||||||
|
.where('like.userId = :userId', { userId: user.id })
|
||||||
|
.getCount(),
|
||||||
|
pageLikedCount: this.pageLikesRepository.createQueryBuilder('like')
|
||||||
|
.innerJoin('like.page', 'page')
|
||||||
|
.where('page.userId = :userId', { userId: user.id })
|
||||||
|
.getCount(),
|
||||||
|
driveFilesCount: this.driveFilesRepository.createQueryBuilder('file')
|
||||||
|
.where('file.userId = :userId', { userId: user.id })
|
||||||
|
.getCount(),
|
||||||
|
driveUsage: this.driveFileEntityService.calcDriveUsageOf(user),
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
...result,
|
||||||
|
followingCount: result.localFollowingCount + result.remoteFollowingCount,
|
||||||
|
followersCount: result.localFollowersCount + result.remoteFollowersCount,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -86,6 +86,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<button v-if="postFormActions.length > 0" v-tooltip="i18n.ts.plugin" class="_button" :class="$style.footerButton" @click="showActions"><i class="ti ti-plug"></i></button>
|
<button v-if="postFormActions.length > 0" v-tooltip="i18n.ts.plugin" class="_button" :class="$style.footerButton" @click="showActions"><i class="ti ti-plug"></i></button>
|
||||||
<button v-tooltip="i18n.ts.emoji" :class="['_button', $style.footerButton]" @click="insertEmoji"><i class="ti ti-mood-happy"></i></button>
|
<button v-tooltip="i18n.ts.emoji" :class="['_button', $style.footerButton]" @click="insertEmoji"><i class="ti ti-mood-happy"></i></button>
|
||||||
<button v-tooltip="i18n.ts.mfm" :class="['_button', $style.footerButton]" @click="insertMfm"><i class="ti ti-wand"></i></button>
|
<button v-tooltip="i18n.ts.mfm" :class="['_button', $style.footerButton]" @click="insertMfm"><i class="ti ti-wand"></i></button>
|
||||||
|
<button v-tooltip="i18n.ts.ruby" :class="['_button', $style.footerButton]" @click="insertRuby"><i class="ti ti-abc"></i></button>
|
||||||
</div>
|
</div>
|
||||||
<div :class="$style.footerRight">
|
<div :class="$style.footerRight">
|
||||||
<button v-tooltip="i18n.ts.previewNoteText" class="_button" :class="[$style.footerButton, { [$style.previewButtonActive]: showPreview }]" @click="showPreview = !showPreview"><i class="ti ti-eye"></i></button>
|
<button v-tooltip="i18n.ts.previewNoteText" class="_button" :class="[$style.footerButton, { [$style.previewButtonActive]: showPreview }]" @click="showPreview = !showPreview"><i class="ti ti-eye"></i></button>
|
||||||
|
@ -849,6 +850,9 @@ async function insertEmoji(ev: MouseEvent) {
|
||||||
function insertMfm(){
|
function insertMfm(){
|
||||||
insertTextAtCursor(textareaEl, '$');
|
insertTextAtCursor(textareaEl, '$');
|
||||||
}
|
}
|
||||||
|
function insertRuby() {
|
||||||
|
insertTextAtCursor(textareaEl, '$[ruby 本文 上につくやつ]');
|
||||||
|
}
|
||||||
function showActions(ev) {
|
function showActions(ev) {
|
||||||
os.popupMenu(postFormActions.map(action => ({
|
os.popupMenu(postFormActions.map(action => ({
|
||||||
text: action.title,
|
text: action.title,
|
||||||
|
|
|
@ -340,9 +340,24 @@ export default function(props: {
|
||||||
text:base[1]
|
text:base[1]
|
||||||
});
|
});
|
||||||
}else if(token.children.length === 2){
|
}else if(token.children.length === 2){
|
||||||
|
let txt,base;
|
||||||
console.log(token.children)
|
console.log(token.children)
|
||||||
const base = token.children[0].type !== 'unicodeEmoji' ? token.children[0].props.text : token.children[0].props.emoji;
|
if (token.children[1].type === 'emojiCode'){
|
||||||
const txt = token.children[1].type !== 'unicodeEmoji' ? token.children[1].props.text : token.children[1].props.emoji;
|
txt = token.children[1].props.name
|
||||||
|
}else if(token.children[1].type === 'unicodeEmoji'){
|
||||||
|
txt = token.children[1].props.emoji
|
||||||
|
}else {
|
||||||
|
txt = token.children[1].props.text
|
||||||
|
}
|
||||||
|
|
||||||
|
if (token.children[0].type === 'emojiCode'){
|
||||||
|
base = token.children[0].props.name
|
||||||
|
}else if(token.children[0].type === 'unicodeEmoji'){
|
||||||
|
base = token.children[0].props.emoji
|
||||||
|
}else {
|
||||||
|
base = token.children[0].props.text
|
||||||
|
}
|
||||||
|
|
||||||
return h(MkRuby,{
|
return h(MkRuby,{
|
||||||
base:base,
|
base:base,
|
||||||
basetype:token.children[0].type,
|
basetype:token.children[0].type,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import MkEmoji from './MkEmoji.vue';
|
import MkEmoji from './MkEmoji.vue';
|
||||||
|
import MkCustomEmoji from './MkCustomEmoji.vue';
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
base: string;
|
base: string;
|
||||||
text: string;
|
text: string;
|
||||||
|
@ -10,9 +11,11 @@ const props = defineProps<{
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ruby>
|
<ruby>
|
||||||
|
<MkEmoji v-if="basetype === 'unicodeEmoji' " class="emoji" :emoji="base" :normal="true" />
|
||||||
<MkEmoji v-if="basetype === 'unicodeEmoji' " class="emoji" :emoji="base" :normal="true"/>
|
<MkCustomEmoji v-else-if="basetype === 'emojiCode' " :name="base"/>
|
||||||
<p v-else >{{base}}</p>
|
<span style="white-space: pre-wrap;" v-else >{{base}}</span>
|
||||||
<rt>{{text}}</rt>
|
<rt>{{text}}</rt>
|
||||||
</ruby>
|
</ruby>
|
||||||
</template>
|
</template>
|
||||||
|
<style>
|
||||||
|
</style>
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
<template>
|
||||||
|
<div class="_gaps_m">
|
||||||
|
<FormSection v-if="stats" first>
|
||||||
|
<template #label>{{ i18n.ts.statistics }}</template>
|
||||||
|
<MkKeyValue oneline style="margin: 1em 0;">
|
||||||
|
<template #key>{{ i18n.ts.notesCount }}</template>
|
||||||
|
<template #value>{{ number(stats.notesCount) }}</template>
|
||||||
|
</MkKeyValue>
|
||||||
|
<MkKeyValue oneline style="margin: 1em 0;">
|
||||||
|
<template #key>{{ i18n.ts.repliesCount }}</template>
|
||||||
|
<template #value>{{ number(stats.repliesCount) }}</template>
|
||||||
|
</MkKeyValue>
|
||||||
|
<MkKeyValue oneline style="margin: 1em 0;">
|
||||||
|
<template #key>{{ i18n.ts.renotesCount }}</template>
|
||||||
|
<template #value>{{ number(stats.renotesCount) }}</template>
|
||||||
|
</MkKeyValue>
|
||||||
|
<MkKeyValue oneline style="margin: 1em 0;">
|
||||||
|
<template #key>{{ i18n.ts.repliedCount }}</template>
|
||||||
|
<template #value>{{ number(stats.repliedCount) }}</template>
|
||||||
|
</MkKeyValue>
|
||||||
|
<MkKeyValue oneline style="margin: 1em 0;">
|
||||||
|
<template #key>{{ i18n.ts.renotedCount }}</template>
|
||||||
|
<template #value>{{ number(stats.renotedCount) }}</template>
|
||||||
|
</MkKeyValue>
|
||||||
|
<MkKeyValue oneline style="margin: 1em 0;">
|
||||||
|
<template #key>{{ i18n.ts.pollVotesCount }}</template>
|
||||||
|
<template #value>{{ number(stats.pollVotesCount) }}</template>
|
||||||
|
</MkKeyValue>
|
||||||
|
<MkKeyValue oneline style="margin: 1em 0;">
|
||||||
|
<template #key>{{ i18n.ts.pollVotedCount }}</template>
|
||||||
|
<template #value>{{ number(stats.pollVotedCount) }}</template>
|
||||||
|
</MkKeyValue>
|
||||||
|
<MkKeyValue oneline style="margin: 1em 0;">
|
||||||
|
<template #key>{{ i18n.ts.sentReactionsCount }}</template>
|
||||||
|
<template #value>{{ number(stats.sentReactionsCount) }}</template>
|
||||||
|
</MkKeyValue>
|
||||||
|
<MkKeyValue oneline style="margin: 1em 0;">
|
||||||
|
<template #key>{{ i18n.ts.receivedReactionsCount }}</template>
|
||||||
|
<template #value>{{ number(stats.receivedReactionsCount) }}</template>
|
||||||
|
</MkKeyValue>
|
||||||
|
<MkKeyValue oneline style="margin: 1em 0;">
|
||||||
|
<template #key>{{ i18n.ts.noteFavoritesCount }}</template>
|
||||||
|
<template #value>{{ number(stats.noteFavoritesCount) }}</template>
|
||||||
|
</MkKeyValue>
|
||||||
|
<MkKeyValue oneline style="margin: 1em 0;">
|
||||||
|
<template #key>{{ i18n.ts.followingCount }}</template>
|
||||||
|
<template #value>{{ number(stats.followingCount) }}</template>
|
||||||
|
</MkKeyValue>
|
||||||
|
<MkKeyValue oneline style="margin: 1em 0;">
|
||||||
|
<template #key>{{ i18n.ts.followingCount }} ({{ i18n.ts.local }})</template>
|
||||||
|
<template #value>{{ number(stats.localFollowingCount) }}</template>
|
||||||
|
</MkKeyValue>
|
||||||
|
<MkKeyValue oneline style="margin: 1em 0;">
|
||||||
|
<template #key>{{ i18n.ts.followingCount }} ({{ i18n.ts.remote }})</template>
|
||||||
|
<template #value>{{ number(stats.remoteFollowingCount) }}</template>
|
||||||
|
</MkKeyValue>
|
||||||
|
<MkKeyValue oneline style="margin: 1em 0;">
|
||||||
|
<template #key>{{ i18n.ts.followersCount }}</template>
|
||||||
|
<template #value>{{ number(stats.followersCount) }}</template>
|
||||||
|
</MkKeyValue>
|
||||||
|
<MkKeyValue oneline style="margin: 1em 0;">
|
||||||
|
<template #key>{{ i18n.ts.followersCount }} ({{ i18n.ts.local }})</template>
|
||||||
|
<template #value>{{ number(stats.localFollowersCount) }}</template>
|
||||||
|
</MkKeyValue>
|
||||||
|
<MkKeyValue oneline style="margin: 1em 0;">
|
||||||
|
<template #key>{{ i18n.ts.followersCount }} ({{ i18n.ts.remote }})</template>
|
||||||
|
<template #value>{{ number(stats.remoteFollowersCount) }}</template>
|
||||||
|
</MkKeyValue>
|
||||||
|
<MkKeyValue oneline style="margin: 1em 0;">
|
||||||
|
<template #key>{{ i18n.ts.pageLikesCount }}</template>
|
||||||
|
<template #value>{{ number(stats.pageLikesCount) }}</template>
|
||||||
|
</MkKeyValue>
|
||||||
|
<MkKeyValue oneline style="margin: 1em 0;">
|
||||||
|
<template #key>{{ i18n.ts.pageLikedCount }}</template>
|
||||||
|
<template #value>{{ number(stats.pageLikedCount) }}</template>
|
||||||
|
</MkKeyValue>
|
||||||
|
<MkKeyValue oneline style="margin: 1em 0;">
|
||||||
|
<template #key>{{ i18n.ts.driveFilesCount }}</template>
|
||||||
|
<template #value>{{ number(stats.driveFilesCount) }}</template>
|
||||||
|
</MkKeyValue>
|
||||||
|
<MkKeyValue oneline style="margin: 1em 0;">
|
||||||
|
<template #key>{{ i18n.ts.driveUsage }}</template>
|
||||||
|
<template #value>{{ bytes(stats.driveUsage) }}</template>
|
||||||
|
</MkKeyValue>
|
||||||
|
</FormSection>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { onMounted, ref ,computed } from 'vue';
|
||||||
|
import FormSection from '@/components/form/section.vue';
|
||||||
|
import MkKeyValue from '@/components/MkKeyValue.vue';
|
||||||
|
import * as os from '@/os';
|
||||||
|
import number from '@/filters/number';
|
||||||
|
import bytes from '@/filters/bytes';
|
||||||
|
import { $i } from '@/account';
|
||||||
|
import { i18n } from '@/i18n';
|
||||||
|
import { definePageMetadata } from '@/scripts/page-metadata';
|
||||||
|
|
||||||
|
const stats = ref<any>({});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
os.api('i/stats', {
|
||||||
|
userId: $i!.id,
|
||||||
|
}).then(response => {
|
||||||
|
stats.value = response;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const headerActions = computed(() => []);
|
||||||
|
|
||||||
|
const headerTabs = computed(() => []);
|
||||||
|
|
||||||
|
definePageMetadata({
|
||||||
|
title: i18n.ts.accountInfo,
|
||||||
|
icon: 'ti ti-info-circle',
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -31,6 +31,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<template #key>{{ i18n.ts.registeredDate }}</template>
|
<template #key>{{ i18n.ts.registeredDate }}</template>
|
||||||
<template #value><MkTime :time="$i.createdAt" mode="detail"/></template>
|
<template #value><MkTime :time="$i.createdAt" mode="detail"/></template>
|
||||||
</MkKeyValue>
|
</MkKeyValue>
|
||||||
|
<FormLink to="/settings/account-stats"><template #icon><i class="ti ti-info-circle"></i></template>{{ i18n.ts.statistics }}</FormLink>
|
||||||
</div>
|
</div>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
|
|
|
@ -174,7 +174,11 @@ export const routes = [{
|
||||||
path: '/other',
|
path: '/other',
|
||||||
name: 'other',
|
name: 'other',
|
||||||
component: page(() => import('./pages/settings/other.vue')),
|
component: page(() => import('./pages/settings/other.vue')),
|
||||||
}, {
|
},{
|
||||||
|
path: '/account-stats',
|
||||||
|
name: 'other',
|
||||||
|
component: page(() => import('./pages/settings/account-stats.vue')),
|
||||||
|
},{
|
||||||
path: '/',
|
path: '/',
|
||||||
component: page(() => import('./pages/_empty_.vue')),
|
component: page(() => import('./pages/_empty_.vue')),
|
||||||
}],
|
}],
|
||||||
|
|
Loading…
Reference in New Issue