Skip to content

Commit

Permalink
Merge pull request #456 from CodingFactory-Repos/develop-G6
Browse files Browse the repository at this point in the history
Implement the text-input and the blueprints with the text
  • Loading branch information
Loule95450 committed Jun 16, 2023
2 parents 82c264b + a4912fe commit 95ac059
Show file tree
Hide file tree
Showing 31 changed files with 1,003 additions and 332 deletions.
2 changes: 2 additions & 0 deletions back-end/src/base/canvasRoom/canvasRoom.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { CanvasGateway } from '@/common/gateways/canvas.global.gateway';
import { JwtService } from '@nestjs/jwt';
import { CanvasRoomInvitationRepository } from './canvasRoomInvitation.repository';
import { MailjetModule } from '@/external-modules/mailjet/mailjet.module';
import { CursorGateway } from '@/common/gateways/cursor.global.gateway';

@Module({
imports: [DatabaseModule, MailjetModule, forwardRef(() => AuthModule)],
Expand All @@ -23,6 +24,7 @@ import { MailjetModule } from '@/external-modules/mailjet/mailjet.module';
CanvasRoomInvitationRepository,
UsersRepository,
CanvasGateway,
CursorGateway,
],
controllers: [CanvasRoomController],
exports: [CanvasRoomService, CanvasRoomRepository],
Expand Down
64 changes: 64 additions & 0 deletions back-end/src/common/gateways/cursor.global.gateway.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { JwtService } from '@nestjs/jwt';
import { Server } from 'socket.io';
import { Inject, UseFilters, forwardRef } from '@nestjs/common';
import {
WebSocketGateway,
WebSocketServer,
OnGatewayInit,
OnGatewayConnection,
OnGatewayDisconnect,
SubscribeMessage,
} from '@nestjs/websockets';

import { WSServiceErrorCatcher } from '@/common/decorators/ws.catch.decorator';
import { AuthSocket, WSAuthMiddleware } from '@/common/middlewares/socket.auth.middleware';
import {
ElementPosition,
} from '@/base/canvasRoom/interfaces/ws.canvasRoom.interface';
import { UsersRepository } from '@/base/users/users.repository';
import { ObjectId } from 'mongodb';

@UseFilters(WSServiceErrorCatcher)
@WebSocketGateway({
transports: ['websocket'],
cors: {
origin: '*', // to be defined later
},
namespace: 'cursor',
})
export class CursorGateway implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect {
constructor(
@Inject(forwardRef(() => UsersRepository))
private usersRepository: UsersRepository,
private readonly jwtService: JwtService,
) {}
@WebSocketServer() server: Server;

afterInit(server: Server) {
server.use(WSAuthMiddleware(this.jwtService));
}

async handleConnection(client: AuthSocket) {
const query = { _id: client.user.id as ObjectId };
const projection = { projection: { profile: { email: 1 } } };
const user = await this.usersRepository.findOne(query, projection);

client.join(client.roomId);
client.join(client.user.id.toString());
client.to(client.roomId).emit('peer-connected', client.id, user.profile.firstName);
}

async handleDisconnect(client: AuthSocket) {
client.to(client.roomId).emit('peer-disconnected', client.id);
}

@SubscribeMessage('update-mouse-moved')
handleMouseMoved(client: AuthSocket, position: ElementPosition) {
client.to(client.roomId).emit('peer-mouse-moved', client.id, position);
}

@SubscribeMessage('connect-to-peer')
handleConnectToPeer(client: AuthSocket, args: { peerId: string, firstName: string }) {
client.to(args.peerId).emit('peer-connected', client.id, args.firstName, true);
}
}
30 changes: 28 additions & 2 deletions front-end/src/components/agility/AgilityCanvas.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<CanvasLoader :loading="loading">
<AgilityCanvasUI :room-id="roomId">
<canvas ref="canvas"></canvas>
<canvas ref="cursorCanvas" class="absolute pointer-events-none"></canvas>
</AgilityCanvasUI>
</CanvasLoader>
</template>
Expand All @@ -20,10 +21,12 @@ import { useProjectStore } from '@/store/modules/project.store';
import { useAgilityStore } from '@/store/modules/agility.store';
import AgilityCanvasUI from '@/components/agility/AgilityCanvasUI.vue';
import CanvasLoader from '@/components/agility/UI/CanvasLoader.vue';
import { LineContainer } from '../../lib/pixi-tools-v2/class/lineContainer';
import { LineContainer } from '@/lib/pixi-tools-v2/class/lineContainer';
import { CanvasContainer } from '@/lib/pixi-tools-v2/types/pixi-aliases';
import { useThemeStore } from '@/store/modules/theme.store';
import { config } from '@/config/config';
import { CursorScene } from '@/lib/pixi-tools-v2/cursorScene';
import { useAuthStore } from '../../store/modules/auth.store';
const route = useRoute();
const projectStore = useProjectStore();
Expand All @@ -33,19 +36,36 @@ const themeStore = useThemeStore();
const isDark = computed(() => themeStore.theme);
const scene = computed(() => projectStore.scene);
const projectLoading = computed(() => agilityStore.projectLoading);
const viewportBounds = computed(() => projectStore.getViewportBounds);
const project = computed(() => agilityStore.currentProject);
const canvas = ref<HTMLCanvasElement>();
const cursorCanvas = ref<HTMLCanvasElement>();
const roomId = ref(route.path.match(/[^/]+(?=\?)|[^/]+$/)[0]);
const loading = computed(() => projectLoading.value || projectStore.internalLoading);
let timeout: NodeJS.Timeout = null;
let rawScene: Scene = null;
let rawCursorScene: CursorScene = null;
watch(isDark, val => {
if(scene.value) {
scene.value.changeTheme(val);
}
})
});
watch(viewportBounds, val => {
rawCursorScene.viewport.x = val.x;
rawCursorScene.viewport.y = val.y;
if(val.scaleX !== undefined && val.scaleY !== undefined) {
rawCursorScene.viewport.scale.set(val.scaleX, val.scaleY);
}
if(val.mouseX !== undefined && val.mouseY !== undefined) {
rawCursorScene.viewport.updateMousePosition({ x: val.mouseX, y: val.mouseY });
}
}, { deep: true });
onMounted(() => {
document.addEventListener('fullscreenchange', onFullscreenChange);
Expand All @@ -60,12 +80,17 @@ onMounted(() => {
},
};
const authStore = useAuthStore();
const firstName = authStore.user?.profile?.firstName ?? 'unknown';
// 84 represent the offset height due to tabs
const cursorScene = new CursorScene(cursorCanvas.value as HTMLCanvasElement, 84, firstName, socketOptions);
const scene = new Scene(canvas.value as HTMLCanvasElement, 84, isDark.value, socketOptions);
projectStore.scene = scene;
projectStore.canvas = canvas.value;
projectStore.enableSelectionBox();
rawScene = scene;
rawCursorScene = cursorScene;
})
const autoFillProject = async () => {
Expand Down Expand Up @@ -144,6 +169,7 @@ const onFullscreenChange = () => {
onBeforeRouteLeave(() => {
const vp = projectStore.scene.viewport;
vp.socketPlugin.disconnect();
rawCursorScene.viewport.socketCursorManager._close();
if (document.exitFullscreen && projectStore.onFullscreen) {
projectStore.onFullscreen = false;
Expand Down
4 changes: 1 addition & 3 deletions front-end/src/components/agility/UI/ColorPickerOption.vue
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,7 @@ const changeColor = (col: ColorPickerUpdate) => {
if(projectStore.scene.viewport.socketPlugin) {
const parent = graphic.parent;
// TODO: Thomas, remove this when readuy for the live editing
if(parent instanceof TextContainer) continue;
if(parent instanceof GenericContainer || parent instanceof LineContainer) {
if(parent instanceof GenericContainer || parent instanceof LineContainer || parent instanceof TextContainer) {
projectStore.scene.viewport.socketPlugin.emit(
'ws-element-colorized',
parent.uuid,
Expand Down
4 changes: 2 additions & 2 deletions front-end/src/components/agility/UI/ToolsEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@
/>
</IconButton>
<ColorPickerOption position="bottom-[-330px] left-[30px]" />
<div v-if="isTextAreaEdited">
<!-- <div v-if="isTextAreaEdited">
<IconButton class="h-fit" type="button">
<SvgFrame
width="22"
Expand Down Expand Up @@ -165,7 +165,7 @@
}"
/>
</IconButton>
</div>
</div> -->
</div>

<ShareProject v-if="isShareModalOpen" @close="closeShareModal" />
Expand Down
14 changes: 4 additions & 10 deletions front-end/src/components/agility/modals/Blueprint.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<ModalOverlay v-if="showBlueprintModal" @close="beforeModalClose" size="xl">
<ModalOverlay @close="modalClose" size="xl">
<template #header>
<span class="text-lg font-bold pb-2 text-black dark:text-white">Available blueprints</span>
</template>
Expand Down Expand Up @@ -34,21 +34,17 @@ const emit = defineEmits(['close']);
const agilityStore = useAgilityStore();
const projectStore = useProjectStore();
const metaTemplates = computed(() => agilityStore.metaTemplates);
const showBlueprintModal = ref(false);
const isPersonaModalOpen = ref(false);
const openBlueprintModal = () => showBlueprintModal.value = true;
const closeBlueprintModal = () => showBlueprintModal.value = false;
const openPersonaModal = () => isPersonaModalOpen.value = true;
const closePersonaModal = () => isPersonaModalOpen.value = false;
const finishPersonaBuilder = () => {
closePersonaModal();
beforeModalClose();
modalClose();
}
const beforeModalClose = () => {
closeBlueprintModal();
const modalClose = () => {
emit("close");
}
Expand All @@ -60,8 +56,7 @@ const setBlueprintType = (type: LitteralBlueprintTypes) => {
projectStore.deferredBlueprint = type;
projectStore.setBlueprintEvent('pointer');
closeBlueprintModal();
emit("close");
modalClose();
}
onMounted(() => {
Expand All @@ -70,7 +65,6 @@ onMounted(() => {
}
})
openBlueprintModal();
defineExpose({
openPersonaModal
})
Expand Down
19 changes: 15 additions & 4 deletions front-end/src/lib/pixi-tools-v2/class/lineContainer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ export class LineContainer extends PluginContainer {
}

public updateTreeBounds(serializedBounds: SerializedContainerBounds) {
const graphic = this.getGraphicChildren()[0];
const graphic = this.getGraphicChildren()[0] as LineBezier;
const { absMinX, absMinY, absMaxX, absMaxY } = serializedBounds.anchors;
const bounds = (serializedBounds.childs[0] as SerializedGraphic).bounds;

Expand All @@ -221,9 +221,20 @@ export class LineContainer extends PluginContainer {
this.absMaxX = absMaxX;
this.absMaxY = absMaxY;

graphic.position.set(bounds.x, bounds.y);
graphic.width = bounds.width;
graphic.height = bounds.height;
try {
//@ts-ignore
const { start, end, startControl, endControl, lineWidth } = serializedBounds.childs[0].lineControl;
graphic.start = start;
graphic.end = end;
graphic.startControl = startControl;
graphic.endControl = endControl;
graphic.lineWidth = lineWidth;
graphic.draw();
graphic.width = bounds.width;
graphic.height = bounds.height;
} catch(err) {
console.error("Could not update the tree bounds of the graphic");
}
}

public updateLineTree(serializedControl: SerializedControl) {
Expand Down
2 changes: 0 additions & 2 deletions front-end/src/lib/pixi-tools-v2/class/normalyzer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ export class Normalizer {
attributes.bounds = {
x: position.x - width / 2,
y: position.y - height / 2,
width,
height,
};
} else {
const width = 200; // Need to find a solution rather than hardcoded
Expand Down
44 changes: 44 additions & 0 deletions front-end/src/lib/pixi-tools-v2/class/socketCursorManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Manager, ManagerOptions, Socket } from 'socket.io-client';
import { ElementPosition } from '../types/pixi-container';
import { ViewportCursor } from '../viewportCursor';

export class SocketCursorManager extends Manager {
public readonly canvasSocket: Socket;
public readonly peersId: Array<string>;
protected readonly viewport: ViewportCursor;

constructor(uri: string, roomId: string, options: Partial<ManagerOptions>, viewport: ViewportCursor, firstName: string) {
super(uri, options);

this.viewport = viewport;
this.canvasSocket = this.socket('/cursor');
this.canvasSocket.auth = { roomId };

this.canvasSocket.on('peer-connected', (peerId: string, peerFirstName: string, forced: boolean = false) => {
this.viewport.addCursorElement(peerId, peerFirstName, { x: 0, y: 0 });

if(!forced) {
this.canvasSocket.emit('connect-to-peer', { peerId, firstName });
}
});

this.canvasSocket.on('peer-disconnected', (peerId: string) => {
const element = this.viewport.cursorElements[peerId];
if(element !== undefined) {
this.viewport.removeChild(element);
element.destroy();
}
});

this.canvasSocket.on('peer-mouse-moved', (peerId: string, position: ElementPosition) => {
const element = this.viewport.cursorElements[peerId];
if(element !== undefined) {
this.viewport.updateCursorElement(element, position);
}
});
}

public updateMouseMoved(position: ElementPosition) {
this.canvasSocket.emit('update-mouse-moved', position);
}
}
20 changes: 11 additions & 9 deletions front-end/src/lib/pixi-tools-v2/class/socketManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
} from '../types/pixi-serialize';
import { Normalizer } from './normalyzer';
import { temporaryNotification } from '../utils/temporary.notification';
import { ElementPosition } from '../types/pixi-container';
import { GenericContainer } from './genericContainer';
import { FramedContainer } from './framedContainer';
import { CanvasContainer } from '../types/pixi-aliases';
Expand Down Expand Up @@ -130,10 +129,6 @@ export class SocketManager extends Manager {
}
});

this.canvasSocket.on('peer-mouse-moved', (peerId: string, position: ElementPosition) => {
console.info(`Peer ${peerId} mouse mooved at position: ${position.x},${position.y}`);
});

this.canvasSocket.on(
'element-colorimetry-updated',
(uuid: string, serializedColorimetry: SerializedColorimetry) => {
Expand All @@ -153,6 +148,8 @@ export class SocketManager extends Manager {
}
} else if (element instanceof GenericContainer) {
element.updateTreeBounds(serializedBounds);
} else if (element instanceof LineContainer) {
element.updateTreeBounds(serializedBounds);
} else if (element instanceof TextContainer) {
element.updateTreeBounds(serializedBounds);
}
Expand Down Expand Up @@ -191,6 +188,15 @@ export class SocketManager extends Manager {
//@ts-ignore
radius: child.radius,
});
} else if(element instanceof TextContainer) {
const childData = serializedColorimetry.childs[0] as SerializedGraphicColorimetry;
const child = element.getGraphicChildren()[0] as TextArea;
child.color = childData.properties.color;
child.alpha = childData.properties.alpha;
child.draw({
x: child.x,
y: child.y
})
}
} catch (err) {
if (err instanceof Error) {
Expand Down Expand Up @@ -261,10 +267,6 @@ export class SocketManager extends Manager {
this.canvasSocket.emit('delete-element', { uuid, uuidFrame });
}

public updateMouseMoved(position: ElementPosition) {
this.canvasSocket.emit('update-mouse-moved', position);
}

public updateFrameOnChildAdded(uuid: string, uuidChild: string, serialized: SerializedContainer) {
this.canvasSocket.emit('add-frame-children', { uuid, uuidChild, serialized });
}
Expand Down
Loading

0 comments on commit 95ac059

Please sign in to comment.