Merge branch 'develop' into pag-back

This commit is contained in:
tamaina 2023-07-19 03:24:01 +00:00
commit 72ae8441e1
54 changed files with 1558 additions and 2308 deletions

View file

@ -57,24 +57,24 @@
"@aws-sdk/client-s3": "3.367.0",
"@aws-sdk/lib-storage": "3.367.0",
"@aws-sdk/node-http-handler": "3.360.0",
"@bull-board/api": "5.6.0",
"@bull-board/fastify": "5.6.0",
"@bull-board/ui": "5.6.0",
"@bull-board/api": "5.6.1",
"@bull-board/fastify": "5.6.1",
"@bull-board/ui": "5.6.1",
"@discordapp/twemoji": "14.1.2",
"@fastify/accepts": "4.2.0",
"@fastify/cookie": "8.3.0",
"@fastify/cors": "8.3.0",
"@fastify/http-proxy": "9.2.1",
"@fastify/multipart": "7.7.0",
"@fastify/multipart": "7.7.1",
"@fastify/static": "6.10.2",
"@fastify/view": "8.0.0",
"@nestjs/common": "10.0.5",
"@nestjs/core": "10.0.5",
"@nestjs/testing": "10.0.5",
"@nestjs/common": "10.1.0",
"@nestjs/core": "10.1.0",
"@nestjs/testing": "10.1.0",
"@peertube/http-signature": "1.7.0",
"@sinonjs/fake-timers": "10.3.0",
"@swc/cli": "0.1.62",
"@swc/core": "1.3.69",
"@swc/core": "1.3.70",
"accepts": "1.3.8",
"ajv": "8.12.0",
"archiver": "5.3.1",
@ -82,7 +82,7 @@
"autwh": "0.1.0",
"bcryptjs": "2.4.3",
"blurhash": "2.0.5",
"bullmq": "4.3.0",
"bullmq": "4.4.0",
"cacheable-lookup": "7.0.0",
"cbor": "9.0.0",
"chalk": "5.3.0",
@ -94,7 +94,7 @@
"date-fns": "2.30.0",
"deep-email-validator": "0.1.21",
"escape-regexp": "0.0.1",
"fastify": "4.19.2",
"fastify": "4.20.0",
"feed": "4.2.2",
"file-type": "18.5.0",
"fluent-ffmpeg": "2.1.2",

View file

@ -4,10 +4,9 @@ import { IsNull, In, MoreThan, Not } from 'typeorm';
import { bindThis } from '@/decorators.js';
import { DI } from '@/di-symbols.js';
import type { Config } from '@/config.js';
import type { LocalUser, RemoteUser } from '@/models/entities/User.js';
import type { LocalUser, RemoteUser, User } from '@/models/entities/User.js';
import type { BlockingsRepository, FollowingsRepository, InstancesRepository, Muting, MutingsRepository, UserListJoiningsRepository, UsersRepository } from '@/models/index.js';
import type { RelationshipJobData, ThinUser } from '@/queue/types.js';
import type { User } from '@/models/entities/User.js';
import { IdService } from '@/core/IdService.js';
import { GlobalEventService } from '@/core/GlobalEventService.js';

View file

@ -2,6 +2,7 @@ import { URL } from 'node:url';
import { Inject, Injectable } from '@nestjs/common';
import { JSDOM } from 'jsdom';
import tinycolor from 'tinycolor2';
import * as Redis from 'ioredis';
import type { Instance } from '@/models/entities/Instance.js';
import type Logger from '@/logger.js';
import { DI } from '@/di-symbols.js';
@ -10,7 +11,6 @@ import { HttpRequestService } from '@/core/HttpRequestService.js';
import { bindThis } from '@/decorators.js';
import { FederatedInstanceService } from '@/core/FederatedInstanceService.js';
import type { DOMWindow } from 'jsdom';
import * as Redis from 'ioredis';
type NodeInfo = {
openRegistrations?: unknown;

View file

@ -574,7 +574,7 @@ export class NoteCreateService implements OnApplicationShutdown {
where: {
userId: data.reply.userId,
threadId: data.reply.threadId ?? data.reply.id,
}
},
});
if (!isThreadMuted) {

View file

@ -1,5 +1,6 @@
import { Inject, Injectable, OnModuleInit, forwardRef } from '@nestjs/common';
import { ModuleRef } from '@nestjs/core';
import { IsNull } from 'typeorm';
import type { LocalUser, PartialLocalUser, PartialRemoteUser, RemoteUser, User } from '@/models/entities/User.js';
import { IdentifiableError } from '@/misc/identifiable-error.js';
import { QueueService } from '@/core/QueueService.js';
@ -21,9 +22,8 @@ import { UserBlockingService } from '@/core/UserBlockingService.js';
import { MetaService } from '@/core/MetaService.js';
import { CacheService } from '@/core/CacheService.js';
import type { Config } from '@/config.js';
import Logger from '../logger.js';
import { IsNull } from 'typeorm';
import { AccountMoveService } from '@/core/AccountMoveService.js';
import Logger from '../logger.js';
const logger = new Logger('following/create');
@ -322,7 +322,7 @@ export class UserFollowingService implements OnModuleInit {
where: {
followerId: follower.id,
followeeId: followee.id,
}
},
});
if (following === null || !following.follower || !following.followee) {
@ -412,8 +412,8 @@ export class UserFollowingService implements OnModuleInit {
followerId: user.id,
followee: {
movedToUri: IsNull(),
}
}
},
},
});
const nonMovedFollowers = await this.followingsRepository.count({
relations: {
@ -423,8 +423,8 @@ export class UserFollowingService implements OnModuleInit {
followeeId: user.id,
follower: {
movedToUri: IsNull(),
}
}
},
},
});
await this.usersRepository.update(
{ id: user.id },
@ -646,7 +646,7 @@ export class UserFollowingService implements OnModuleInit {
where: {
followeeId: followee.id,
followerId: follower.id,
}
},
});
if (!following || !following.followee || !following.follower) return;

View file

@ -52,7 +52,7 @@ export class VideoProcessingService {
query({
thumbnail: '1',
url,
})
}),
);
}
}

View file

@ -3,8 +3,8 @@ import { DI } from '@/di-symbols.js';
import type { AbuseUserReportsRepository } from '@/models/index.js';
import { awaitAll } from '@/misc/prelude/await-all.js';
import type { AbuseUserReport } from '@/models/entities/AbuseUserReport.js';
import { UserEntityService } from './UserEntityService.js';
import { bindThis } from '@/decorators.js';
import { UserEntityService } from './UserEntityService.js';
@Injectable()
export class AbuseUserReportEntityService {

View file

@ -4,8 +4,8 @@ import type { AuthSessionsRepository } from '@/models/index.js';
import { awaitAll } from '@/misc/prelude/await-all.js';
import type { AuthSession } from '@/models/entities/AuthSession.js';
import type { User } from '@/models/entities/User.js';
import { AppEntityService } from './AppEntityService.js';
import { bindThis } from '@/decorators.js';
import { AppEntityService } from './AppEntityService.js';
@Injectable()
export class AuthSessionEntityService {

View file

@ -50,7 +50,7 @@ export class ChannelEntityService {
const hasUnreadNote = meId ? await this.noteUnreadsRepository.exist({
where: {
noteChannelId: channel.id,
userId: meId
userId: meId,
},
}) : undefined;

View file

@ -4,8 +4,8 @@ import type { FollowRequestsRepository } from '@/models/index.js';
import type { } from '@/models/entities/Blocking.js';
import type { User } from '@/models/entities/User.js';
import type { FollowRequest } from '@/models/entities/FollowRequest.js';
import { UserEntityService } from './UserEntityService.js';
import { bindThis } from '@/decorators.js';
import { UserEntityService } from './UserEntityService.js';
@Injectable()
export class FollowRequestEntityService {

View file

@ -3,8 +3,8 @@ import { DI } from '@/di-symbols.js';
import type { GalleryLikesRepository } from '@/models/index.js';
import type { } from '@/models/entities/Blocking.js';
import type { GalleryLike } from '@/models/entities/GalleryLike.js';
import { GalleryPostEntityService } from './GalleryPostEntityService.js';
import { bindThis } from '@/decorators.js';
import { GalleryPostEntityService } from './GalleryPostEntityService.js';
@Injectable()
export class GalleryLikeEntityService {

View file

@ -4,8 +4,8 @@ import type { ModerationLogsRepository } from '@/models/index.js';
import { awaitAll } from '@/misc/prelude/await-all.js';
import type { } from '@/models/entities/Blocking.js';
import type { ModerationLog } from '@/models/entities/ModerationLog.js';
import { UserEntityService } from './UserEntityService.js';
import { bindThis } from '@/decorators.js';
import { UserEntityService } from './UserEntityService.js';
@Injectable()
export class ModerationLogEntityService {

View file

@ -4,8 +4,8 @@ import type { NoteFavoritesRepository } from '@/models/index.js';
import type { } from '@/models/entities/Blocking.js';
import type { User } from '@/models/entities/User.js';
import type { NoteFavorite } from '@/models/entities/NoteFavorite.js';
import { NoteEntityService } from './NoteEntityService.js';
import { bindThis } from '@/decorators.js';
import { NoteEntityService } from './NoteEntityService.js';
@Injectable()
export class NoteFavoriteEntityService {

View file

@ -4,8 +4,8 @@ import type { PageLikesRepository } from '@/models/index.js';
import type { } from '@/models/entities/Blocking.js';
import type { User } from '@/models/entities/User.js';
import type { PageLike } from '@/models/entities/PageLike.js';
import { PageEntityService } from './PageEntityService.js';
import { bindThis } from '@/decorators.js';
import { PageEntityService } from './PageEntityService.js';
@Injectable()
export class PageLikeEntityService {

View file

@ -3,8 +3,8 @@ import { DI } from '@/di-symbols.js';
import type { SigninsRepository } from '@/models/index.js';
import type { } from '@/models/entities/Blocking.js';
import type { Signin } from '@/models/entities/Signin.js';
import { UserEntityService } from './UserEntityService.js';
import { bindThis } from '@/decorators.js';
import { UserEntityService } from './UserEntityService.js';
@Injectable()
export class SigninEntityService {

View file

@ -1,11 +1,11 @@
import { Writable, WritableOptions } from "node:stream";
import { Writable, WritableOptions } from 'node:stream';
export class DevNull extends Writable implements NodeJS.WritableStream {
constructor(opts?: WritableOptions) {
super(opts);
}
constructor(opts?: WritableOptions) {
super(opts);
}
_write (chunk: any, encoding: BufferEncoding, cb: (err?: Error | null) => void) {
setImmediate(cb);
}
_write (chunk: any, encoding: BufferEncoding, cb: (err?: Error | null) => void) {
setImmediate(cb);
}
}

View file

@ -5,10 +5,10 @@ const CHARS = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
export const ulidRegExp = /^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$/;
export function parseUlid(id: string): { date: Date; } {
const timestamp = id.slice(0, 10);
let time = 0;
for (let i = 0; i < 10; i++) {
time = time * 32 + CHARS.indexOf(timestamp[i]);
}
return { date: new Date(time) };
const timestamp = id.slice(0, 10);
let time = 0;
for (let i = 0; i < 10; i++) {
time = time * 32 + CHARS.indexOf(timestamp[i]);
}
return { date: new Date(time) };
}

View file

@ -10,7 +10,7 @@ export async function awaitAll<T>(obj: Promiseable<T>): Promise<T> {
const resolvedValues = await Promise.all(values.map(value =>
(!value || !value.constructor || value.constructor.name !== 'Object')
? value
: awaitAll(value)
: awaitAll(value),
));
for (let i = 0; i < keys.length; i++) {

View file

@ -49,7 +49,6 @@ import { User } from '@/models/entities/User.js';
import { UserIp } from '@/models/entities/UserIp.js';
import { UserKeypair } from '@/models/entities/UserKeypair.js';
import { UserList } from '@/models/entities/UserList.js';
import { UserListFavorite } from './entities/UserListFavorite.js';
import { UserListJoining } from '@/models/entities/UserListJoining.js';
import { UserNotePining } from '@/models/entities/UserNotePining.js';
import { UserPending } from '@/models/entities/UserPending.js';
@ -64,6 +63,7 @@ import { Role } from '@/models/entities/Role.js';
import { RoleAssignment } from '@/models/entities/RoleAssignment.js';
import { Flash } from '@/models/entities/Flash.js';
import { FlashLike } from '@/models/entities/FlashLike.js';
import { UserListFavorite } from './entities/UserListFavorite.js';
import type { Repository } from 'typeorm';
export {

View file

@ -9,10 +9,10 @@ import type { DriveFile } from '@/models/entities/DriveFile.js';
import type { Note } from '@/models/entities/Note.js';
import { EmailService } from '@/core/EmailService.js';
import { bindThis } from '@/decorators.js';
import { SearchService } from '@/core/SearchService.js';
import { QueueLoggerService } from '../QueueLoggerService.js';
import type * as Bull from 'bullmq';
import type { DbUserDeleteJobData } from '../types.js';
import { SearchService } from "@/core/SearchService.js";
@Injectable()
export class DeleteAccountProcessorService {

View file

@ -1,16 +1,16 @@
import { Inject, Injectable } from '@nestjs/common';
import type * as Bull from 'bullmq';
import { UserFollowingService } from '@/core/UserFollowingService.js';
import { UserBlockingService } from '@/core/UserBlockingService.js';
import { bindThis } from '@/decorators.js';
import type Logger from '@/logger.js';
import { QueueLoggerService } from '../QueueLoggerService.js';
import { RelationshipJobData } from '../types.js';
import type { UsersRepository } from '@/models/index.js';
import { DI } from '@/di-symbols.js';
import { LocalUser, RemoteUser } from '@/models/entities/User.js';
import { RelationshipJobData } from '../types.js';
import { QueueLoggerService } from '../QueueLoggerService.js';
import type * as Bull from 'bullmq';
@Injectable()
export class RelationshipProcessorService {

View file

@ -3,6 +3,8 @@ import { fileURLToPath } from 'node:url';
import { dirname } from 'node:path';
import { Inject, Injectable } from '@nestjs/common';
import rename from 'rename';
import sharp from 'sharp';
import { sharpBmp } from 'sharp-read-bmp';
import type { Config } from '@/config.js';
import type { DriveFile, DriveFilesRepository } from '@/models/index.js';
import { DI } from '@/di-symbols.js';
@ -18,11 +20,9 @@ import { contentDisposition } from '@/misc/content-disposition.js';
import { FileInfoService } from '@/core/FileInfoService.js';
import { LoggerService } from '@/core/LoggerService.js';
import { bindThis } from '@/decorators.js';
import type { FastifyInstance, FastifyRequest, FastifyReply, FastifyPluginOptions } from 'fastify';
import { isMimeImage } from '@/misc/is-mime-image.js';
import sharp from 'sharp';
import { sharpBmp } from 'sharp-read-bmp';
import { correctFilename } from '@/misc/correct-filename.js';
import type { FastifyInstance, FastifyRequest, FastifyReply, FastifyPluginOptions } from 'fastify';
const _filename = fileURLToPath(import.meta.url);
const _dirname = dirname(_filename);
@ -180,8 +180,8 @@ export class FileServerService {
reply.header('Content-Disposition',
contentDisposition(
'inline',
correctFilename(file.filename, image.ext)
)
correctFilename(file.filename, image.ext),
),
);
return image.data;
}
@ -278,11 +278,11 @@ export class FileServerService {
};
} else {
const data = (await sharpBmp(file.path, file.mime, { animated: !('static' in request.query) }))
.resize({
height: 'emoji' in request.query ? 128 : 320,
withoutEnlargement: true,
})
.webp(webpDefault);
.resize({
height: 'emoji' in request.query ? 128 : 320,
withoutEnlargement: true,
})
.webp(webpDefault);
image = {
data,
@ -355,8 +355,8 @@ export class FileServerService {
reply.header('Content-Disposition',
contentDisposition(
'inline',
correctFilename(file.filename, image.ext)
)
correctFilename(file.filename, image.ext),
),
);
return image.data;
} catch (e) {

View file

@ -1,18 +1,18 @@
import { Inject, Injectable } from '@nestjs/common';
import { IsNull } from 'typeorm';
import vary from 'vary';
import fastifyAccepts from '@fastify/accepts';
import { DI } from '@/di-symbols.js';
import type { UsersRepository } from '@/models/index.js';
import type { Config } from '@/config.js';
import { escapeAttribute, escapeValue } from '@/misc/prelude/xml.js';
import type { User } from '@/models/entities/User.js';
import * as Acct from '@/misc/acct.js';
import { NodeinfoServerService } from './NodeinfoServerService.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';
import type { FindOptionsWhere } from 'typeorm';
import { bindThis } from '@/decorators.js';
import { NodeinfoServerService } from './NodeinfoServerService.js';
import type { FindOptionsWhere } from 'typeorm';
import type { FastifyInstance, FastifyPluginOptions } from 'fastify';
import fastifyAccepts from '@fastify/accepts';
@Injectable()
export class WellKnownServerService {

View file

@ -13,9 +13,9 @@ import { EmailService } from '@/core/EmailService.js';
import { LocalUser } from '@/models/entities/User.js';
import { FastifyReplyError } from '@/misc/fastify-reply-error.js';
import { bindThis } from '@/decorators.js';
import { L_CHARS, secureRndstr } from '@/misc/secure-rndstr.js';
import { SigninService } from './SigninService.js';
import type { FastifyRequest, FastifyReply } from 'fastify';
import { L_CHARS, secureRndstr } from '@/misc/secure-rndstr.js';
@Injectable()
export class SignupApiService {

View file

@ -91,7 +91,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
if (queryarry) {
emojis = emojis.filter(emoji =>
queryarry.includes(`:${emoji.name}:`)
queryarry.includes(`:${emoji.name}:`),
);
} else {
emojis = emojis.filter(emoji =>

View file

@ -5,8 +5,8 @@ import type { UsersRepository, BlockingsRepository } from '@/models/index.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { UserBlockingService } from '@/core/UserBlockingService.js';
import { DI } from '@/di-symbols.js';
import { ApiError } from '../../error.js';
import { GetterService } from '@/server/api/GetterService.js';
import { ApiError } from '../../error.js';
export const meta = {
tags: ['account'],
@ -88,7 +88,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
where: {
blockerId: blocker.id,
blockeeId: blockee.id,
}
},
});
if (!exist) {

View file

@ -2,8 +2,8 @@ import { Inject, Injectable } from '@nestjs/common';
import { Endpoint } from '@/server/api/endpoint-base.js';
import type { ClipNotesRepository, ClipsRepository } from '@/models/index.js';
import { DI } from '@/di-symbols.js';
import { ApiError } from '../../error.js';
import { GetterService } from '@/server/api/GetterService.js';
import { ApiError } from '../../error.js';
export const meta = {
tags: ['account', 'notes', 'clips'],

View file

@ -5,8 +5,8 @@ import type { UsersRepository, FollowingsRepository } from '@/models/index.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { UserFollowingService } from '@/core/UserFollowingService.js';
import { DI } from '@/di-symbols.js';
import { ApiError } from '../../error.js';
import { GetterService } from '@/server/api/GetterService.js';
import { ApiError } from '../../error.js';
export const meta = {
tags: ['following', 'users'],

View file

@ -5,8 +5,8 @@ import type { UsersRepository, FollowingsRepository } from '@/models/index.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { UserFollowingService } from '@/core/UserFollowingService.js';
import { DI } from '@/di-symbols.js';
import { ApiError } from '../../error.js';
import { GetterService } from '@/server/api/GetterService.js';
import { ApiError } from '../../error.js';
export const meta = {
tags: ['following', 'users'],

View file

@ -23,7 +23,7 @@ export const meta = {
id: 'e5b3b9f0-2b8f-4b9f-9c1f-8c5c1b2e1b1a',
kind: 'permission',
},
}
},
} as const;
export const paramDef = {

View file

@ -267,7 +267,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
super(meta, paramDef, async (ps, me) => {
const instance = await this.metaService.fetch(true);
const ads = await this.adsRepository.createQueryBuilder("ads")
const ads = await this.adsRepository.createQueryBuilder('ads')
.where('ads.expiresAt > :now', { now: new Date() })
.andWhere('ads.startsAt <= :now', { now: new Date() })
.andWhere(new Brackets(qb => {

View file

@ -4,8 +4,8 @@ import type { NotesRepository } from '@/models/index.js';
import { Endpoint } from '@/server/api/endpoint-base.js';
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
import { DI } from '@/di-symbols.js';
import { ApiError } from '../../error.js';
import { GetterService } from '@/server/api/GetterService.js';
import { ApiError } from '../../error.js';
export const meta = {
tags: ['notes'],

View file

@ -3,8 +3,8 @@ import type { NotesRepository } from '@/models/index.js';
import { Endpoint } from '@/server/api/endpoint-base.js';
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
import { DI } from '@/di-symbols.js';
import { ApiError } from '../../error.js';
import { GetterService } from '@/server/api/GetterService.js';
import { ApiError } from '../../error.js';
export const meta = {
tags: ['notes'],

View file

@ -3,8 +3,8 @@ import type { PromoReadsRepository } from '@/models/index.js';
import { IdService } from '@/core/IdService.js';
import { Endpoint } from '@/server/api/endpoint-base.js';
import { DI } from '@/di-symbols.js';
import { ApiError } from '../../error.js';
import { GetterService } from '@/server/api/GetterService.js';
import { ApiError } from '../../error.js';
export const meta = {
tags: ['notes'],

View file

@ -35,7 +35,7 @@ export const meta = {
code: 'NO_SUCH_REGISTRATION',
id: ' b09d8066-8064-5613-efb6-0e963b21d012',
},
}
},
} as const;
export const paramDef = {

View file

@ -5,8 +5,8 @@ import type { NotesRepository, UsersRepository } from '@/models/index.js';
import { Endpoint } from '@/server/api/endpoint-base.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { DI } from '@/di-symbols.js';
import { ApiError } from '../../error.js';
import { GetterService } from '@/server/api/GetterService.js';
import { ApiError } from '../../error.js';
export const meta = {
tags: ['users'],

View file

@ -3,9 +3,9 @@ import { isUserRelated } from '@/misc/is-user-related.js';
import type { Packed } from '@/misc/json-schema.js';
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
import { bindThis } from '@/decorators.js';
import { RoleService } from '@/core/RoleService.js';
import Channel from '../channel.js';
import { StreamMessages } from '../types.js';
import { RoleService } from '@/core/RoleService.js';
class RoleTimelineChannel extends Channel {
public readonly chName = 'roleTimeline';

View file

@ -19,10 +19,10 @@
"@rollup/plugin-json": "6.0.0",
"@rollup/plugin-replace": "5.0.2",
"@rollup/pluginutils": "5.0.2",
"@syuilo/aiscript": "0.13.3",
"@syuilo/aiscript": "0.14.0",
"@tabler/icons-webfont": "2.25.0",
"@vitejs/plugin-vue": "4.2.3",
"@vue-macros/reactivity-transform": "0.3.14",
"@vue-macros/reactivity-transform": "0.3.15",
"@vue/compiler-sfc": "3.3.4",
"astring": "1.8.6",
"autosize": "6.0.1",
@ -54,7 +54,7 @@
"prismjs": "1.29.0",
"punycode": "2.3.0",
"querystring": "0.2.1",
"rollup": "3.26.2",
"rollup": "3.26.3",
"s-age": "1.1.2",
"sanitize-html": "2.11.0",
"sass": "1.63.6",
@ -77,24 +77,24 @@
"vuedraggable": "next"
},
"devDependencies": {
"@storybook/addon-actions": "7.0.27",
"@storybook/addon-essentials": "7.0.27",
"@storybook/addon-interactions": "7.0.27",
"@storybook/addon-links": "7.0.27",
"@storybook/addon-storysource": "7.0.27",
"@storybook/addons": "7.0.27",
"@storybook/blocks": "7.0.27",
"@storybook/core-events": "7.0.27",
"@storybook/addon-actions": "7.1.0",
"@storybook/addon-essentials": "7.1.0",
"@storybook/addon-interactions": "7.1.0",
"@storybook/addon-links": "7.1.0",
"@storybook/addon-storysource": "7.1.0",
"@storybook/addons": "7.1.0",
"@storybook/blocks": "7.1.0",
"@storybook/core-events": "7.1.0",
"@storybook/jest": "0.1.0",
"@storybook/manager-api": "7.0.27",
"@storybook/preview-api": "7.0.27",
"@storybook/react": "7.0.27",
"@storybook/react-vite": "7.0.27",
"@storybook/manager-api": "7.1.0",
"@storybook/preview-api": "7.1.0",
"@storybook/react": "7.1.0",
"@storybook/react-vite": "7.1.0",
"@storybook/testing-library": "0.2.0",
"@storybook/theming": "7.0.27",
"@storybook/types": "7.0.27",
"@storybook/vue3": "7.0.27",
"@storybook/vue3-vite": "7.0.27",
"@storybook/theming": "7.1.0",
"@storybook/types": "7.1.0",
"@storybook/vue3": "7.1.0",
"@storybook/vue3-vite": "7.1.0",
"@testing-library/jest-dom": "5.16.5",
"@testing-library/vue": "7.0.0",
"@types/escape-regexp": "0.0.1",
@ -132,7 +132,7 @@
"react": "18.2.0",
"react-dom": "18.2.0",
"start-server-and-test": "2.0.0",
"storybook": "7.0.27",
"storybook": "7.1.0",
"storybook-addon-misskey-theme": "github:misskey-dev/storybook-addon-misskey-theme",
"summaly": "github:misskey-dev/summaly",
"vite-plugin-turbosnap": "1.0.2",

View file

@ -259,6 +259,17 @@ useTooltip(renoteButton, async (showing) => {
}, {}, 'closed');
});
type Visibility = 'public' | 'home' | 'followers' | 'specified';
// defaultStore.state.visibilitystringstring
function smallerVisibility(a: Visibility | string, b: Visibility | string): Visibility {
if (a === 'specified' || b === 'specified') return 'specified';
if (a === 'followers' || b === 'followers') return 'followers';
if (a === 'home' || b === 'home') return 'home';
// if (a === 'public' || b === 'public')
return 'public';
}
function renote(viaKeyboard = false) {
pleaseLogin();
showMovedDialog();
@ -309,7 +320,12 @@ function renote(viaKeyboard = false) {
os.popup(MkRippleEffect, { x, y }, {}, 'end');
}
const configuredVisibility = defaultStore.state.rememberNoteVisibility ? defaultStore.state.visibility : defaultStore.state.defaultNoteVisibility;
const localOnly = defaultStore.state.rememberNoteVisibility ? defaultStore.state.localOnly : defaultStore.state.defaultNoteLocalOnly;
os.api('notes/create', {
localOnly,
visibility: smallerVisibility(appearNote.visibility, configuredVisibility),
renoteId: appearNote.id,
}).then(() => {
os.toast(i18n.ts.renoted);

View file

@ -15,13 +15,13 @@
</div>
<div :class="$style.status">
<div :class="$style.statusItem">
<p :class="$style.statusItemLabel">{{ i18n.ts.notes }}</p><span :class="$style.statusItemValue">{{ user.notesCount }}</span>
<p :class="$style.statusItemLabel">{{ i18n.ts.notes }}</p><span :class="$style.statusItemValue">{{ number(user.notesCount) }}</span>
</div>
<div :class="$style.statusItem">
<p :class="$style.statusItemLabel">{{ i18n.ts.following }}</p><span :class="$style.statusItemValue">{{ user.followingCount }}</span>
<div v-if="isFfVisibleForMe(user)" :class="$style.statusItem">
<p :class="$style.statusItemLabel">{{ i18n.ts.following }}</p><span :class="$style.statusItemValue">{{ number(user.followingCount) }}</span>
</div>
<div :class="$style.statusItem">
<p :class="$style.statusItemLabel">{{ i18n.ts.followers }}</p><span :class="$style.statusItemValue">{{ user.followersCount }}</span>
<div v-if="isFfVisibleForMe(user)" :class="$style.statusItem">
<p :class="$style.statusItemLabel">{{ i18n.ts.followers }}</p><span :class="$style.statusItemValue">{{ number(user.followersCount) }}</span>
</div>
</div>
<MkFollowButton v-if="$i && user.id != $i.id" :class="$style.follow" :user="user" mini/>
@ -31,9 +31,11 @@
<script lang="ts" setup>
import * as misskey from 'misskey-js';
import MkFollowButton from '@/components/MkFollowButton.vue';
import number from '@/filters/number';
import { userPage } from '@/filters/user';
import { i18n } from '@/i18n';
import { $i } from '@/account';
import { isFfVisibleForMe } from '@/scripts/isFfVisibleForMe';
defineProps<{
user: misskey.entities.UserDetailed;

View file

@ -30,11 +30,11 @@
<div :class="$style.statusItemLabel">{{ i18n.ts.notes }}</div>
<div>{{ number(user.notesCount) }}</div>
</div>
<div :class="$style.statusItem">
<div v-if="isFfVisibleForMe(user)" :class="$style.statusItem">
<div :class="$style.statusItemLabel">{{ i18n.ts.following }}</div>
<div>{{ number(user.followingCount) }}</div>
</div>
<div :class="$style.statusItem">
<div v-if="isFfVisibleForMe(user)" :class="$style.statusItem">
<div :class="$style.statusItemLabel">{{ i18n.ts.followers }}</div>
<div>{{ number(user.followersCount) }}</div>
</div>
@ -61,6 +61,7 @@ import number from '@/filters/number';
import { i18n } from '@/i18n';
import { defaultStore } from '@/store';
import { $i } from '@/account';
import { isFfVisibleForMe } from '@/scripts/isFfVisibleForMe';
const props = defineProps<{
showing: boolean;

View file

@ -33,7 +33,7 @@ import MkTextarea from '@/components/MkTextarea.vue';
import MkInput from '@/components/MkInput.vue';
import { useRouter } from '@/router';
const PRESET_DEFAULT = `/// @ 0.13.3
const PRESET_DEFAULT = `/// @ 0.14.0
var name = ""
@ -51,7 +51,7 @@ Ui:render([
])
`;
const PRESET_OMIKUJI = `/// @ 0.13.3
const PRESET_OMIKUJI = `/// @ 0.14.0
//
//
@ -94,7 +94,7 @@ Ui:render([
])
`;
const PRESET_SHUFFLE = `/// @ 0.13.3
const PRESET_SHUFFLE = `/// @ 0.14.0
//
let string = "ペペロンチーノ"
@ -173,7 +173,7 @@ var cursor = 0
do()
`;
const PRESET_QUIZ = `/// @ 0.13.3
const PRESET_QUIZ = `/// @ 0.14.0
let title = '地理クイズ'
let qas = [{
@ -286,7 +286,7 @@ qaEls.push(Ui:C:container({
Ui:render(qaEls)
`;
const PRESET_TIMELINE = `/// @ 0.13.3
const PRESET_TIMELINE = `/// @ 0.14.0
// API
@fetch() {

View file

@ -100,15 +100,15 @@
</dl>
</div>
<div class="status">
<MkA v-click-anime :to="userPage(user)">
<MkA :to="userPage(user)">
<b>{{ number(user.notesCount) }}</b>
<span>{{ i18n.ts.notes }}</span>
</MkA>
<MkA v-click-anime :to="userPage(user, 'following')">
<MkA v-if="isFfVisibleForMe(user)" :to="userPage(user, 'following')">
<b>{{ number(user.followingCount) }}</b>
<span>{{ i18n.ts.following }}</span>
</MkA>
<MkA v-click-anime :to="userPage(user, 'followers')">
<MkA v-if="isFfVisibleForMe(user)" :to="userPage(user, 'followers')">
<b>{{ number(user.followersCount) }}</b>
<span>{{ i18n.ts.followers }}</span>
</MkA>
@ -160,6 +160,7 @@ import { dateString } from '@/filters/date';
import { confetti } from '@/scripts/confetti';
import MkNotes from '@/components/MkNotes.vue';
import { api } from '@/os';
import { isFfVisibleForMe } from '@/scripts/isFfVisibleForMe';
const XPhotos = defineAsyncComponent(() => import('./index.photos.vue'));
const XActivity = defineAsyncComponent(() => import('./index.activity.vue'));

View file

@ -0,0 +1,11 @@
import * as misskey from 'misskey-js';
import { $i } from '@/account';
export function isFfVisibleForMe(user: misskey.entities.UserDetailed): boolean {
if ($i && $i.id === user.id) return true;
if (user.ffVisibility === 'private') return false;
if (user.ffVisibility === 'followers' && !user.isFollowing) return false;
return true;
}