mirror of
https://github.com/misskey-dev/misskey.git
synced 2026-06-25 17:10:43 +00:00
wip
This commit is contained in:
parent
ecedd71192
commit
d38f04c97f
10 changed files with 239 additions and 5 deletions
|
|
@ -10,7 +10,7 @@ export class WorldRoom1778744540138 {
|
|||
* @param {QueryRunner} queryRunner
|
||||
*/
|
||||
async up(queryRunner) {
|
||||
await queryRunner.query(`CREATE TABLE "world_room" ("id" character varying(32) NOT NULL, "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL, "name" character varying(256) NOT NULL, "description" character varying(1024) NOT NULL, "userId" character varying(32) NOT NULL, "likedCount" integer NOT NULL DEFAULT '0', "visibility" character varying(128) NOT NULL DEFAULT 'public', "def" jsonb NOT NULL DEFAULT '{}', CONSTRAINT "PK_40cfacaf35b0b54bb2281c89767" PRIMARY KEY ("id")); COMMENT ON COLUMN "world_room"."userId" IS 'The ID of author.'`);
|
||||
await queryRunner.query(`CREATE TABLE "world_room" ("id" character varying(32) NOT NULL, "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL, "name" character varying(256) NOT NULL, "description" character varying(1024) NOT NULL, "userId" character varying(32) NOT NULL, "likedCount" integer NOT NULL DEFAULT '0', "visibility" character varying(128) NOT NULL DEFAULT 'public', "def" jsonb NOT NULL DEFAULT '{}', CONSTRAINT "PK_40cfacaf35b0b54bb2281c89767" PRIMARY KEY ("id"))`);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_88289375952050da4a7752a366" ON "world_room" ("updatedAt") `);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_f803a5efb4125c5fd8a414285e" ON "world_room" ("userId") `);
|
||||
await queryRunner.query(`ALTER TABLE "world_room" ADD CONSTRAINT "FK_f803a5efb4125c5fd8a414285ed" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
|
|
|
|||
97
packages/backend/src/core/entities/WorldRoomEntityService.ts
Normal file
97
packages/backend/src/core/entities/WorldRoomEntityService.ts
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { DriveFilesRepository, MiWorldRoom, WorldRoomsRepository } from '@/models/_.js';
|
||||
import { awaitAll } from '@/misc/prelude/await-all.js';
|
||||
import type { Packed } from '@/misc/json-schema.js';
|
||||
import type { } from '@/models/Blocking.js';
|
||||
import type { MiUser } from '@/models/User.js';
|
||||
import type { MiDriveFile } from '@/models/DriveFile.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { IdService } from '@/core/IdService.js';
|
||||
import { WorldRoomService } from '@/core/WorldRoomService.js';
|
||||
import { UserEntityService } from './UserEntityService.js';
|
||||
import { DriveFileEntityService } from './DriveFileEntityService.js';
|
||||
import { In } from 'typeorm';
|
||||
|
||||
@Injectable()
|
||||
export class WorldRoomEntityService {
|
||||
constructor(
|
||||
@Inject(DI.worldRoomsRepository)
|
||||
private worldRoomsRepository: WorldRoomsRepository,
|
||||
|
||||
@Inject(DI.driveFilesRepository)
|
||||
private driveFilesRepository: DriveFilesRepository,
|
||||
|
||||
private worldRoomService: WorldRoomService,
|
||||
private userEntityService: UserEntityService,
|
||||
private driveFileEntityService: DriveFileEntityService,
|
||||
private idService: IdService,
|
||||
) {
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public async packLite(
|
||||
src: MiWorldRoom['id'] | MiWorldRoom,
|
||||
me?: { id: MiUser['id'] } | null | undefined,
|
||||
hint?: {
|
||||
packedUser?: Packed<'UserLite'>
|
||||
},
|
||||
): Promise<Packed<'WorldRoomLite'>> {
|
||||
const meId = me ? me.id : null;
|
||||
const room = typeof src === 'object' ? src : await this.worldRoomsRepository.findOneByOrFail({ id: src });
|
||||
|
||||
return await awaitAll({
|
||||
id: room.id,
|
||||
createdAt: this.idService.parse(room.id).date.toISOString(),
|
||||
updatedAt: room.updatedAt.toISOString(),
|
||||
userId: room.userId,
|
||||
user: hint?.packedUser ?? this.userEntityService.pack(room.user ?? room.userId, me),
|
||||
name: room.name,
|
||||
description: room.description,
|
||||
});
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public async packDetailed(
|
||||
src: MiWorldRoom['id'] | MiWorldRoom,
|
||||
me?: { id: MiUser['id'] } | null | undefined,
|
||||
hint?: {
|
||||
packedUser?: Packed<'UserLite'>
|
||||
},
|
||||
): Promise<Packed<'WorldRoomDetailed'>> {
|
||||
const meId = me ? me.id : null;
|
||||
const room = typeof src === 'object' ? src : await this.worldRoomsRepository.findOneByOrFail({ id: src });
|
||||
|
||||
const attachedFileIds = this.worldRoomService.collectReferencedDriveFileIds(room.def);
|
||||
const attachedFiles = attachedFileIds.size === 0 ? [] : await this.driveFilesRepository.findBy({ id: In([...attachedFileIds]), userId: room.userId });
|
||||
|
||||
return await awaitAll({
|
||||
id: room.id,
|
||||
createdAt: this.idService.parse(room.id).date.toISOString(),
|
||||
updatedAt: room.updatedAt.toISOString(),
|
||||
userId: room.userId,
|
||||
user: hint?.packedUser ?? this.userEntityService.pack(room.user ?? room.userId, me),
|
||||
name: room.name,
|
||||
description: room.description,
|
||||
def: room.def,
|
||||
attachedFiles: this.driveFileEntityService.packMany(attachedFiles),
|
||||
});
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public async packLiteMany(
|
||||
rooms: MiWorldRoom[],
|
||||
me?: { id: MiUser['id'] } | null | undefined,
|
||||
) {
|
||||
const _users = rooms.map(({ user, userId }) => user ?? userId);
|
||||
const _userMap = await this.userEntityService.packMany(_users, me)
|
||||
.then(users => new Map(users.map(u => [u.id, u])));
|
||||
return Promise.all(rooms.map(room => this.packLite(room, me, { packedUser: _userMap.get(room.userId) })));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -75,6 +75,7 @@ import { packedChatRoomInvitationSchema } from '@/models/json-schema/chat-room-i
|
|||
import { packedChatRoomMembershipSchema } from '@/models/json-schema/chat-room-membership.js';
|
||||
import { packedAchievementNameSchema, packedAchievementSchema } from '@/models/json-schema/achievement.js';
|
||||
import { packedNoteDraftSchema } from '@/models/json-schema/note-draft.js';
|
||||
import { packedWorldRoomDetailedSchema, packedWorldRoomLiteSchema } from '@/models/json-schema/world-room.js';
|
||||
|
||||
export const refs = {
|
||||
UserLite: packedUserLiteSchema,
|
||||
|
|
@ -147,6 +148,8 @@ export const refs = {
|
|||
ChatRoom: packedChatRoomSchema,
|
||||
ChatRoomInvitation: packedChatRoomInvitationSchema,
|
||||
ChatRoomMembership: packedChatRoomMembershipSchema,
|
||||
WorldRoomLite: packedWorldRoomLiteSchema,
|
||||
WorldRoomDetailed: packedWorldRoomDetailedSchema,
|
||||
};
|
||||
|
||||
export type Packed<x extends keyof typeof refs> = SchemaType<typeof refs[x]>;
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ export class MiWorldRoom {
|
|||
@Index()
|
||||
@Column({
|
||||
...id(),
|
||||
comment: 'The ID of author.',
|
||||
})
|
||||
public userId: MiUser['id'];
|
||||
|
||||
|
|
|
|||
95
packages/backend/src/models/json-schema/world-room.ts
Normal file
95
packages/backend/src/models/json-schema/world-room.ts
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
export const packedWorldRoomLiteSchema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
format: 'id',
|
||||
},
|
||||
createdAt: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
format: 'date-time',
|
||||
},
|
||||
updatedAt: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
format: 'date-time',
|
||||
},
|
||||
userId: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
format: 'id',
|
||||
},
|
||||
user: {
|
||||
type: 'object',
|
||||
ref: 'UserLite',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const packedWorldRoomDetailedSchema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
format: 'id',
|
||||
},
|
||||
createdAt: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
format: 'date-time',
|
||||
},
|
||||
updatedAt: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
format: 'date-time',
|
||||
},
|
||||
userId: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
format: 'id',
|
||||
},
|
||||
user: {
|
||||
type: 'object',
|
||||
ref: 'UserLite',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
def: {
|
||||
type: 'object',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
attachedFiles: {
|
||||
type: 'array',
|
||||
optional: false, nullable: false,
|
||||
items: {
|
||||
type: 'object',
|
||||
optional: false, nullable: false,
|
||||
ref: 'DriveFile',
|
||||
},
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
|
|
@ -43,7 +43,7 @@ import * as os from '@/os.js';
|
|||
import MkInput from '@/components/MkInput.vue';
|
||||
import MkSwitch from '@/components/MkSwitch.vue';
|
||||
import MkRange from '@/components/MkRange.vue';
|
||||
import { WorldController } from '@/world/controller.js';
|
||||
import { WorldEngineController } from '@/world/controller.js';
|
||||
|
||||
const canvas = useTemplateRef('canvas');
|
||||
|
||||
|
|
@ -60,7 +60,7 @@ function resize() {
|
|||
|
||||
const isZenMode = ref(false);
|
||||
|
||||
const controller = new WorldController();
|
||||
const controller = new WorldEngineController();
|
||||
|
||||
onMounted(async () => {
|
||||
controller.init(canvas.value!);
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ export class WorldEngineController extends EngineControllerBase {
|
|||
}
|
||||
|
||||
public async init(canvas: HTMLCanvasElement) {
|
||||
/*
|
||||
await this._init_(canvas, {
|
||||
createWorker: (offscreen) => new Promise((resolve) => {
|
||||
import('./worker?worker').then(({ default: WorldEngineWorker }) => {
|
||||
|
|
@ -39,5 +40,6 @@ export class WorldEngineController extends EngineControllerBase {
|
|||
});
|
||||
}),
|
||||
});
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2252,7 +2252,9 @@ declare namespace entities {
|
|||
ChatMessageLiteForRoom,
|
||||
ChatRoom,
|
||||
ChatRoomInvitation,
|
||||
ChatRoomMembership
|
||||
ChatRoomMembership,
|
||||
WorldRoomLite,
|
||||
WorldRoomDetailed
|
||||
}
|
||||
}
|
||||
export { entities }
|
||||
|
|
@ -3901,6 +3903,12 @@ type V2AdminEmojiListResponse = operations['v2___admin___emoji___list']['respons
|
|||
// @public (undocumented)
|
||||
type VerifyEmailRequest = operations['verify-email']['requestBody']['content']['application/json'];
|
||||
|
||||
// @public (undocumented)
|
||||
type WorldRoomDetailed = components['schemas']['WorldRoomDetailed'];
|
||||
|
||||
// @public (undocumented)
|
||||
type WorldRoomLite = components['schemas']['WorldRoomLite'];
|
||||
|
||||
// Warnings were encountered during analysis:
|
||||
//
|
||||
// src/entities.ts:60:2 - (ae-forgotten-export) The symbol "ModerationLogPayloads" needs to be exported by the entry point index.d.ts
|
||||
|
|
|
|||
|
|
@ -69,3 +69,5 @@ export type ChatMessageLiteForRoom = components['schemas']['ChatMessageLiteForRo
|
|||
export type ChatRoom = components['schemas']['ChatRoom'];
|
||||
export type ChatRoomInvitation = components['schemas']['ChatRoomInvitation'];
|
||||
export type ChatRoomMembership = components['schemas']['ChatRoomMembership'];
|
||||
export type WorldRoomLite = components['schemas']['WorldRoomLite'];
|
||||
export type WorldRoomDetailed = components['schemas']['WorldRoomDetailed'];
|
||||
|
|
|
|||
|
|
@ -5688,6 +5688,34 @@ export type components = {
|
|||
roomId: string;
|
||||
room?: components['schemas']['ChatRoom'];
|
||||
};
|
||||
WorldRoomLite: {
|
||||
/** Format: id */
|
||||
id: string;
|
||||
/** Format: date-time */
|
||||
createdAt: string;
|
||||
/** Format: date-time */
|
||||
updatedAt: string;
|
||||
/** Format: id */
|
||||
userId: string;
|
||||
user: components['schemas']['UserLite'];
|
||||
name: string;
|
||||
description: string;
|
||||
};
|
||||
WorldRoomDetailed: {
|
||||
/** Format: id */
|
||||
id: string;
|
||||
/** Format: date-time */
|
||||
createdAt: string;
|
||||
/** Format: date-time */
|
||||
updatedAt: string;
|
||||
/** Format: id */
|
||||
userId: string;
|
||||
user: components['schemas']['UserLite'];
|
||||
name: string;
|
||||
description: string;
|
||||
def: Record<string, never>;
|
||||
attachedFiles: components['schemas']['DriveFile'][];
|
||||
};
|
||||
};
|
||||
responses: never;
|
||||
parameters: never;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue