From bc0c1b05627c3697f32ea607fd05784c2873abbb Mon Sep 17 00:00:00 2001 From: dank074 Date: Mon, 15 Nov 2021 21:12:05 -0600 Subject: [PATCH 1/3] create widget handler --- .../events/RoomWidgetWordQuizUpdateEvent.ts | 110 ++++++++++++++++++ .../widgets/handlers/WordQuizWidgetHandler.ts | 75 ++++++++++++ src/views/room/RoomView.tsx | 2 + src/views/room/widgets/RoomWidgetsView.tsx | 2 + .../widgets/word-quiz/WordQuizWidgetView.tsx | 6 + 5 files changed, 195 insertions(+) create mode 100644 src/api/nitro/room/widgets/events/RoomWidgetWordQuizUpdateEvent.ts create mode 100644 src/api/nitro/room/widgets/handlers/WordQuizWidgetHandler.ts create mode 100644 src/views/room/widgets/word-quiz/WordQuizWidgetView.tsx diff --git a/src/api/nitro/room/widgets/events/RoomWidgetWordQuizUpdateEvent.ts b/src/api/nitro/room/widgets/events/RoomWidgetWordQuizUpdateEvent.ts new file mode 100644 index 00000000..3652881c --- /dev/null +++ b/src/api/nitro/room/widgets/events/RoomWidgetWordQuizUpdateEvent.ts @@ -0,0 +1,110 @@ +import { IQuestion } from '@nitrots/nitro-renderer'; +import { RoomWidgetUpdateEvent } from './RoomWidgetUpdateEvent'; + +export class RoomWidgetWordQuizUpdateEvent extends RoomWidgetUpdateEvent +{ + public static readonly NEW_QUESTION = 'RWPUW_NEW_QUESTION'; + public static readonly QUESTION_FINISHED = 'RWPUW_QUESION_FINSIHED'; + public static readonly QUESTION_ANSWERED = 'RWPUW_QUESTION_ANSWERED'; + + private _id: number = -1; + private _pollType: string = null; + private _pollId: number = -1; + private _questionId: number = -1; + private _duration: number = -1; + private _question: IQuestion = null; + private _userId: number = -1; + private _value: string; + private _answerCounts: Map; + + constructor(type: string, id: number) + { + super(type); + this._id = id; + } + + public get id(): number + { + return this._id; + } + + public get pollType(): string + { + return this._pollType; + } + + public set pollType(k: string) + { + this._pollType = k; + } + + public get pollId(): number + { + return this._pollId; + } + + public set pollId(k: number) + { + this._pollId = k; + } + + public get questionId(): number + { + return this._questionId; + } + + public set questionId(k: number) + { + this._questionId = k; + } + + public get duration(): number + { + return this._duration; + } + + public set duration(k: number) + { + this._duration = k; + } + + public get question(): IQuestion + { + return this._question; + } + + public set question(k: IQuestion) + { + this._question = k; + } + + public get userId(): number + { + return this._userId; + } + + public set userId(k: number) + { + this._userId = k; + } + + public get value(): string + { + return this._value; + } + + public set value(k: string) + { + this._value = k; + } + + public get answerCounts(): Map + { + return this._answerCounts; + } + + public set answerCounts(k: Map) + { + this._answerCounts = k; + } +} diff --git a/src/api/nitro/room/widgets/handlers/WordQuizWidgetHandler.ts b/src/api/nitro/room/widgets/handlers/WordQuizWidgetHandler.ts new file mode 100644 index 00000000..c65632ee --- /dev/null +++ b/src/api/nitro/room/widgets/handlers/WordQuizWidgetHandler.ts @@ -0,0 +1,75 @@ +import { AvatarAction, NitroEvent, RoomSessionWordQuizEvent, RoomWidgetEnum } from '@nitrots/nitro-renderer'; +import { RoomWidgetHandler } from '.'; +import { GetRoomEngine } from '../../GetRoomEngine'; +import { RoomWidgetUpdateEvent } from '../events'; +import { RoomWidgetWordQuizUpdateEvent } from '../events/RoomWidgetWordQuizUpdateEvent'; +import { RoomWidgetMessage } from '../messages'; + +export class WordQuizWidgetHandler extends RoomWidgetHandler +{ + public processEvent(event: NitroEvent): void + { + const roomQuizEvent = (event as RoomSessionWordQuizEvent); + let widgetEvent: RoomWidgetWordQuizUpdateEvent; + + switch(event.type) + { + case RoomSessionWordQuizEvent.ANSWERED: + const roomId = this.container.roomSession.roomId; + const userData = this.container.roomSession.userDataManager.getUserData(roomQuizEvent.userId); + if(!userData) return; + widgetEvent = new RoomWidgetWordQuizUpdateEvent(RoomWidgetWordQuizUpdateEvent.QUESTION_ANSWERED, roomQuizEvent.id); + widgetEvent.value = roomQuizEvent.value; + widgetEvent.userId = roomQuizEvent.userId; + widgetEvent.answerCounts = roomQuizEvent.answerCounts; + + if(widgetEvent.value === '0') + { + GetRoomEngine().updateRoomObjectUserGesture(roomId, userData.roomIndex, AvatarAction.getGestureId(AvatarAction.GESTURE_SAD)); + } + else + { + GetRoomEngine().updateRoomObjectUserGesture(roomId, userData.roomIndex, AvatarAction.getGestureId(AvatarAction.GESTURE_SMILE)); + } + break; + case RoomSessionWordQuizEvent.FINISHED: + widgetEvent = new RoomWidgetWordQuizUpdateEvent(RoomWidgetWordQuizUpdateEvent.QUESTION_FINISHED, roomQuizEvent.id); + widgetEvent.pollId = roomQuizEvent.pollId; + widgetEvent.questionId = roomQuizEvent.questionId; + widgetEvent.answerCounts = roomQuizEvent.answerCounts; + break; + case RoomSessionWordQuizEvent.QUESTION: + widgetEvent = new RoomWidgetWordQuizUpdateEvent(RoomWidgetWordQuizUpdateEvent.NEW_QUESTION, roomQuizEvent.id); + widgetEvent.question = roomQuizEvent.question; + widgetEvent.duration = roomQuizEvent.duration; + widgetEvent.pollType = roomQuizEvent.pollType; + widgetEvent.questionId = roomQuizEvent.questionId; + widgetEvent.pollId = roomQuizEvent.pollId; + break; + } + + if(!widgetEvent) return; + + this.container.eventDispatcher.dispatchEvent(widgetEvent); + } + + public processWidgetMessage(message: RoomWidgetMessage): RoomWidgetUpdateEvent + { + return null; + } + + public get type(): string + { + return RoomWidgetEnum.WORD_QUIZZ; + } + + public get eventTypes(): string[] + { + return [RoomSessionWordQuizEvent.ANSWERED, RoomSessionWordQuizEvent.FINISHED, RoomSessionWordQuizEvent.QUESTION]; + } + + public get messageTypes(): string[] + { + return []; + } +} diff --git a/src/views/room/RoomView.tsx b/src/views/room/RoomView.tsx index b885b48c..1118a685 100644 --- a/src/views/room/RoomView.tsx +++ b/src/views/room/RoomView.tsx @@ -2,6 +2,7 @@ import { EventDispatcher, NitroRectangle, RoomGeometry, RoomVariableEnum, Vector import { FC, useEffect, useRef, useState } from 'react'; import { DispatchMouseEvent, DispatchTouchEvent, DoorbellWidgetHandler, FurniChooserWidgetHandler, FurnitureContextMenuWidgetHandler, FurnitureCreditWidgetHandler, FurnitureCustomStackHeightWidgetHandler, FurnitureDimmerWidgetHandler, FurnitureExternalImageWidgetHandler, FurnitureMannequinWidgetHandler, FurniturePresentWidgetHandler, GetNitroInstance, GetRoomEngine, InitializeRoomInstanceRenderingCanvas, IRoomWidgetHandlerManager, RoomWidgetAvatarInfoHandler, RoomWidgetChatHandler, RoomWidgetChatInputHandler, RoomWidgetHandlerManager, RoomWidgetInfostandHandler, RoomWidgetRoomToolsHandler, RoomWidgetUpdateRoomViewEvent, UserChooserWidgetHandler } from '../../api'; import { FurnitureYoutubeDisplayWidgetHandler } from '../../api/nitro/room/widgets/handlers/FurnitureYoutubeDisplayWidgetHandler'; +import { WordQuizWidgetHandler } from '../../api/nitro/room/widgets/handlers/WordQuizWidgetHandler'; import { RoomContextProvider } from './context/RoomContext'; import { RoomColorView } from './RoomColorView'; import { RoomViewProps } from './RoomView.types'; @@ -37,6 +38,7 @@ export const RoomView: FC = props => widgetHandlerManager.registerHandler(new RoomWidgetChatHandler()); widgetHandlerManager.registerHandler(new UserChooserWidgetHandler()); widgetHandlerManager.registerHandler(new DoorbellWidgetHandler()); + widgetHandlerManager.registerHandler(new WordQuizWidgetHandler()); widgetHandlerManager.registerHandler(new FurniChooserWidgetHandler()); widgetHandlerManager.registerHandler(new FurnitureContextMenuWidgetHandler()); diff --git a/src/views/room/widgets/RoomWidgetsView.tsx b/src/views/room/widgets/RoomWidgetsView.tsx index 3fd67cdc..0a94e885 100644 --- a/src/views/room/widgets/RoomWidgetsView.tsx +++ b/src/views/room/widgets/RoomWidgetsView.tsx @@ -16,6 +16,7 @@ import { InfoStandWidgetView } from './infostand/InfoStandWidgetView'; import { RoomThumbnailWidgetView } from './room-thumbnail/RoomThumbnailWidgetView'; import { RoomToolsWidgetView } from './room-tools/RoomToolsWidgetView'; import { RoomWidgetViewProps } from './RoomWidgets.types'; +import { WordQuizWidgetView } from './word-quiz/WordQuizWidgetView'; export const RoomWidgetsView: FC = props => { const { roomSession = null, eventDispatcher = null, widgetHandler = null } = useRoomContext(); @@ -349,6 +350,7 @@ export const RoomWidgetsView: FC = props => + ); } diff --git a/src/views/room/widgets/word-quiz/WordQuizWidgetView.tsx b/src/views/room/widgets/word-quiz/WordQuizWidgetView.tsx new file mode 100644 index 00000000..13f54726 --- /dev/null +++ b/src/views/room/widgets/word-quiz/WordQuizWidgetView.tsx @@ -0,0 +1,6 @@ +import { FC } from 'react'; + +export const WordQuizWidgetView: FC<{}> = props => +{ + return null; +} From b7c978c7860d27043757dcb0bb260a573fa5f04c Mon Sep 17 00:00:00 2001 From: dank074 Date: Tue, 16 Nov 2021 01:03:59 -0600 Subject: [PATCH 2/3] add another handler --- .../events/RoomWidgetPollUpdateEvent.ts | 110 ++++++++++++++++++ .../widgets/handlers/PollWidgetHandler.ts | 76 ++++++++++++ .../widgets/messages/RoomWidgetPollMessage.ts | 44 +++++++ src/views/room/RoomView.tsx | 2 + src/views/room/widgets/RoomWidgets.scss | 1 + .../widgets/word-quiz/WordQuizWidgetView.scss | 12 ++ .../widgets/word-quiz/WordQuizWidgetView.tsx | 44 ++++++- .../widgets/word-quiz/common/VoteValue.ts | 2 + .../word-quiz/views/question/QuestionView.tsx | 14 +++ .../views/question/QuestionView.types.ts | 7 ++ 10 files changed, 310 insertions(+), 2 deletions(-) create mode 100644 src/api/nitro/room/widgets/events/RoomWidgetPollUpdateEvent.ts create mode 100644 src/api/nitro/room/widgets/handlers/PollWidgetHandler.ts create mode 100644 src/api/nitro/room/widgets/messages/RoomWidgetPollMessage.ts create mode 100644 src/views/room/widgets/word-quiz/WordQuizWidgetView.scss create mode 100644 src/views/room/widgets/word-quiz/common/VoteValue.ts create mode 100644 src/views/room/widgets/word-quiz/views/question/QuestionView.tsx create mode 100644 src/views/room/widgets/word-quiz/views/question/QuestionView.types.ts diff --git a/src/api/nitro/room/widgets/events/RoomWidgetPollUpdateEvent.ts b/src/api/nitro/room/widgets/events/RoomWidgetPollUpdateEvent.ts new file mode 100644 index 00000000..58e8d644 --- /dev/null +++ b/src/api/nitro/room/widgets/events/RoomWidgetPollUpdateEvent.ts @@ -0,0 +1,110 @@ +import { PollQuestion } from '@nitrots/nitro-renderer'; +import { RoomWidgetUpdateEvent } from './RoomWidgetUpdateEvent'; + +export class RoomWidgetPollUpdateEvent extends RoomWidgetUpdateEvent +{ + public static readonly OFFER = 'RWPUW_OFFER'; + public static readonly ERROR = 'RWPUW_ERROR'; + public static readonly CONTENT = 'RWPUW_CONTENT'; + + private _id = -1; + private _summary: string; + private _headline: string; + private _numQuestions = 0; + private _startMessage = ''; + private _endMessage = ''; + private _questionArray: PollQuestion[] = null; + private _pollType = ''; + private _npsPoll = false; + + constructor(type: string, id: number) + { + super(type); + this._id = id; + } + + public get id(): number + { + return this._id; + } + + public get summary(): string + { + return this._summary; + } + + public set summary(k: string) + { + this._summary = k; + } + + public get headline(): string + { + return this._headline; + } + + public set headline(k: string) + { + this._headline = k; + } + + public get numQuestions(): number + { + return this._numQuestions; + } + + public set numQuestions(k: number) + { + this._numQuestions = k; + } + + public get startMessage(): string + { + return this._startMessage; + } + + public set startMessage(k: string) + { + this._startMessage = k; + } + + public get endMessage(): string + { + return this._endMessage; + } + + public set endMessage(k: string) + { + this._endMessage = k; + } + + public get questionArray(): PollQuestion[] + { + return this._questionArray; + } + + public set questionArray(k: PollQuestion[]) + { + this._questionArray = k; + } + + public get pollType(): string + { + return this._pollType; + } + + public set pollType(k: string) + { + this._pollType = k; + } + + public get npsPoll(): boolean + { + return this._npsPoll; + } + + public set npsPoll(k: boolean) + { + this._npsPoll = k; + } +} diff --git a/src/api/nitro/room/widgets/handlers/PollWidgetHandler.ts b/src/api/nitro/room/widgets/handlers/PollWidgetHandler.ts new file mode 100644 index 00000000..df4d67b7 --- /dev/null +++ b/src/api/nitro/room/widgets/handlers/PollWidgetHandler.ts @@ -0,0 +1,76 @@ +import { NitroEvent, RoomSessionPollEvent, RoomWidgetEnum } from '@nitrots/nitro-renderer'; +import { RoomWidgetPollUpdateEvent } from '../events/RoomWidgetPollUpdateEvent'; +import { RoomWidgetUpdateEvent } from '../events/RoomWidgetUpdateEvent'; +import { RoomWidgetMessage } from '../messages/RoomWidgetMessage'; +import { RoomWidgetPollMessage } from '../messages/RoomWidgetPollMessage'; +import { RoomWidgetHandler } from './RoomWidgetHandler'; + +export class PollWidgetHandler extends RoomWidgetHandler +{ + public processEvent(event: NitroEvent): void + { + const pollEvent = (event as RoomSessionPollEvent); + + let widgetEvent: RoomWidgetPollUpdateEvent; + + switch(event.type) + { + case RoomSessionPollEvent.OFFER: + widgetEvent = new RoomWidgetPollUpdateEvent(RoomWidgetPollUpdateEvent.OFFER, pollEvent.id); + widgetEvent.summary = pollEvent.summary; + widgetEvent.headline = pollEvent.headline; + break; + case RoomSessionPollEvent.ERROR: + widgetEvent = new RoomWidgetPollUpdateEvent(RoomWidgetPollUpdateEvent.ERROR, pollEvent.id); + widgetEvent.summary = pollEvent.summary; + widgetEvent.headline = pollEvent.headline; + break; + case RoomSessionPollEvent.CONTENT: + widgetEvent = new RoomWidgetPollUpdateEvent(RoomWidgetPollUpdateEvent.CONTENT, pollEvent.id); + widgetEvent.startMessage = pollEvent.startMessage; + widgetEvent.endMessage = pollEvent.endMessage; + widgetEvent.numQuestions = pollEvent.numQuestions; + widgetEvent.questionArray = pollEvent.questionArray; + widgetEvent.npsPoll = pollEvent.npsPoll; + break; + } + + if(!widgetEvent) return; + + this.container.eventDispatcher.dispatchEvent(widgetEvent); + } + + public processWidgetMessage(message: RoomWidgetMessage): RoomWidgetUpdateEvent + { + const pollMessage = (message as RoomWidgetPollMessage); + + switch(message.type) + { + case RoomWidgetPollMessage.START: + this.container.roomSession.sendPollStartMessage(pollMessage.id); + break; + case RoomWidgetPollMessage.REJECT: + this.container.roomSession.sendPollRejectMessage(pollMessage.id); + break; + case RoomWidgetPollMessage.ANSWER: + this.container.roomSession.sendPollAnswerMessage(pollMessage.id, pollMessage.questionId, pollMessage.answers); + break; + } + return null; + } + + public get type(): string + { + return RoomWidgetEnum.ROOM_POLL; + } + + public get eventTypes(): string[] + { + return [RoomSessionPollEvent.OFFER, RoomSessionPollEvent.ERROR, RoomSessionPollEvent.CONTENT]; + } + + public get messageTypes(): string[] + { + return [RoomWidgetPollMessage.ANSWER, RoomWidgetPollMessage.REJECT, RoomWidgetPollMessage.START]; + } +} diff --git a/src/api/nitro/room/widgets/messages/RoomWidgetPollMessage.ts b/src/api/nitro/room/widgets/messages/RoomWidgetPollMessage.ts new file mode 100644 index 00000000..a74d97bf --- /dev/null +++ b/src/api/nitro/room/widgets/messages/RoomWidgetPollMessage.ts @@ -0,0 +1,44 @@ +import { RoomWidgetMessage } from './RoomWidgetMessage'; + +export class RoomWidgetPollMessage extends RoomWidgetMessage +{ + public static readonly START = 'RWPM_START'; + public static readonly REJECT = 'RWPM_REJECT'; + public static readonly ANSWER = 'RWPM_ANSWER'; + + private _id = -1; + private _questionId = 0; + private _answers: string[] = null; + + constructor(type: string, id: number) + { + super(type); + + this._id = id; + } + + public get id(): number + { + return this._id; + } + + public get questionId(): number + { + return this._questionId; + } + + public set questionId(k: number) + { + this._questionId = k; + } + + public get answers(): string[] + { + return this._answers; + } + + public set answers(k: string[]) + { + this._answers = k; + } +} diff --git a/src/views/room/RoomView.tsx b/src/views/room/RoomView.tsx index 1118a685..eecff624 100644 --- a/src/views/room/RoomView.tsx +++ b/src/views/room/RoomView.tsx @@ -2,6 +2,7 @@ import { EventDispatcher, NitroRectangle, RoomGeometry, RoomVariableEnum, Vector import { FC, useEffect, useRef, useState } from 'react'; import { DispatchMouseEvent, DispatchTouchEvent, DoorbellWidgetHandler, FurniChooserWidgetHandler, FurnitureContextMenuWidgetHandler, FurnitureCreditWidgetHandler, FurnitureCustomStackHeightWidgetHandler, FurnitureDimmerWidgetHandler, FurnitureExternalImageWidgetHandler, FurnitureMannequinWidgetHandler, FurniturePresentWidgetHandler, GetNitroInstance, GetRoomEngine, InitializeRoomInstanceRenderingCanvas, IRoomWidgetHandlerManager, RoomWidgetAvatarInfoHandler, RoomWidgetChatHandler, RoomWidgetChatInputHandler, RoomWidgetHandlerManager, RoomWidgetInfostandHandler, RoomWidgetRoomToolsHandler, RoomWidgetUpdateRoomViewEvent, UserChooserWidgetHandler } from '../../api'; import { FurnitureYoutubeDisplayWidgetHandler } from '../../api/nitro/room/widgets/handlers/FurnitureYoutubeDisplayWidgetHandler'; +import { PollWidgetHandler } from '../../api/nitro/room/widgets/handlers/PollWidgetHandler'; import { WordQuizWidgetHandler } from '../../api/nitro/room/widgets/handlers/WordQuizWidgetHandler'; import { RoomContextProvider } from './context/RoomContext'; import { RoomColorView } from './RoomColorView'; @@ -39,6 +40,7 @@ export const RoomView: FC = props => widgetHandlerManager.registerHandler(new UserChooserWidgetHandler()); widgetHandlerManager.registerHandler(new DoorbellWidgetHandler()); widgetHandlerManager.registerHandler(new WordQuizWidgetHandler()); + widgetHandlerManager.registerHandler(new PollWidgetHandler()); widgetHandlerManager.registerHandler(new FurniChooserWidgetHandler()); widgetHandlerManager.registerHandler(new FurnitureContextMenuWidgetHandler()); diff --git a/src/views/room/widgets/RoomWidgets.scss b/src/views/room/widgets/RoomWidgets.scss index 4cac258a..6c2a2f2b 100644 --- a/src/views/room/widgets/RoomWidgets.scss +++ b/src/views/room/widgets/RoomWidgets.scss @@ -8,3 +8,4 @@ @import './object-location/ObjectLocationView'; @import './room-tools/RoomToolsWidgetView'; @import './choosers/ChooserWidgetView'; +@import './word-quiz/WordQuizWidgetView'; diff --git a/src/views/room/widgets/word-quiz/WordQuizWidgetView.scss b/src/views/room/widgets/word-quiz/WordQuizWidgetView.scss new file mode 100644 index 00000000..d4291278 --- /dev/null +++ b/src/views/room/widgets/word-quiz/WordQuizWidgetView.scss @@ -0,0 +1,12 @@ +.word-quiz-question-container { + position: absolute; + top: 10px; + left: 0px; + .wordquiz-question { + font-size: large; + background: rgba($dark, 0.90); + //box-shadow: inset 0px 5px lighten(rgba($dark,.6),2.5), inset 0 -4px darken(rgba($dark,.6),4); + border-radius: $border-radius; + transition: all 0.2s ease; + } +} diff --git a/src/views/room/widgets/word-quiz/WordQuizWidgetView.tsx b/src/views/room/widgets/word-quiz/WordQuizWidgetView.tsx index 13f54726..a529f409 100644 --- a/src/views/room/widgets/word-quiz/WordQuizWidgetView.tsx +++ b/src/views/room/widgets/word-quiz/WordQuizWidgetView.tsx @@ -1,6 +1,46 @@ -import { FC } from 'react'; +import { IQuestion } from '@nitrots/nitro-renderer'; +import { FC, useCallback, useState } from 'react'; +import { RoomWidgetWordQuizUpdateEvent } from '../../../../api/nitro/room/widgets/events/RoomWidgetWordQuizUpdateEvent'; +import { BatchUpdates, CreateEventDispatcherHook } from '../../../../hooks'; +import { useRoomContext } from '../../context/RoomContext'; +import { QuestionView } from './views/question/QuestionView'; export const WordQuizWidgetView: FC<{}> = props => { - return null; + const { eventDispatcher = null, widgetHandler = null } = useRoomContext(); + const [pollId, setPollId ] = useState(-1); + const [question, setQuestion] = useState(null); + const [ answerSent, setAnswerSent ] = useState(false); + + const onRoomWidgetWordQuizUpdateEvent = useCallback((event: RoomWidgetWordQuizUpdateEvent) => + { + switch(event.type) + { + case RoomWidgetWordQuizUpdateEvent.NEW_QUESTION: + BatchUpdates(() => + { + setPollId(event.id); + setQuestion(event.question); + setAnswerSent(false); + }); + //this._showSignCounters = new Dictionary(); + //this.showNewQuestion(this._question, k.duration); + break; + } + }, []); + + const vote = useCallback((vote: string) => + { + + }, []); + + CreateEventDispatcherHook(RoomWidgetWordQuizUpdateEvent.NEW_QUESTION, eventDispatcher, onRoomWidgetWordQuizUpdateEvent); + CreateEventDispatcherHook(RoomWidgetWordQuizUpdateEvent.QUESTION_ANSWERED, eventDispatcher, onRoomWidgetWordQuizUpdateEvent); + CreateEventDispatcherHook(RoomWidgetWordQuizUpdateEvent.QUESTION_FINISHED, eventDispatcher, onRoomWidgetWordQuizUpdateEvent); + + return ( + <> + {question && } + + ); } diff --git a/src/views/room/widgets/word-quiz/common/VoteValue.ts b/src/views/room/widgets/word-quiz/common/VoteValue.ts new file mode 100644 index 00000000..ef84aaff --- /dev/null +++ b/src/views/room/widgets/word-quiz/common/VoteValue.ts @@ -0,0 +1,2 @@ +export const VALUE_KEY_DISLIKE = '0'; +export const VALUE_KEY_LIKE = '1'; diff --git a/src/views/room/widgets/word-quiz/views/question/QuestionView.tsx b/src/views/room/widgets/word-quiz/views/question/QuestionView.tsx new file mode 100644 index 00000000..13bbf225 --- /dev/null +++ b/src/views/room/widgets/word-quiz/views/question/QuestionView.tsx @@ -0,0 +1,14 @@ +import { FC } from 'react'; +import { QuestionViewProps } from './QuestionView.types'; + +export const QuestionView:FC = props => +{ + const { question = null, canVote = null } = props; + + return ( +
+
{question}
+
+ + ) +} diff --git a/src/views/room/widgets/word-quiz/views/question/QuestionView.types.ts b/src/views/room/widgets/word-quiz/views/question/QuestionView.types.ts new file mode 100644 index 00000000..09fda7b4 --- /dev/null +++ b/src/views/room/widgets/word-quiz/views/question/QuestionView.types.ts @@ -0,0 +1,7 @@ + +export interface QuestionViewProps +{ + question: string; + canVote: boolean; + vote(value: string): void; +} From 1e8476032460c56db9f1010b86fda6ce4b6f4e5b Mon Sep 17 00:00:00 2001 From: dank074 Date: Wed, 17 Nov 2021 00:09:47 -0600 Subject: [PATCH 3/3] finished logic --- .../widgets/handlers/PollWidgetHandler.ts | 1 - .../widgets/handlers/WordQuizWidgetHandler.ts | 1 - .../wordquiz-widget/thumbs-down-small.png | Bin 0 -> 145 bytes .../wordquiz-widget/thumbs-down.png | Bin 0 -> 182 bytes .../wordquiz-widget/thumbs-up-small.png | Bin 0 -> 135 bytes .../wordquiz-widget/thumbs-up.png | Bin 0 -> 174 bytes src/views/room/widgets/RoomWidgetsView.tsx | 8 +- .../widgets/word-quiz/WordQuizWidgetView.scss | 43 ++++- .../widgets/word-quiz/WordQuizWidgetView.tsx | 153 ++++++++++++++++-- .../widgets/word-quiz/common/VoteValue.ts | 6 + .../word-quiz/views/question/QuestionView.tsx | 18 ++- .../views/question/QuestionView.types.ts | 2 + .../widgets/word-quiz/views/vote/VoteView.tsx | 16 ++ .../word-quiz/views/vote/VoteView.types.ts | 5 + 14 files changed, 222 insertions(+), 31 deletions(-) create mode 100644 src/assets/images/room-widgets/wordquiz-widget/thumbs-down-small.png create mode 100644 src/assets/images/room-widgets/wordquiz-widget/thumbs-down.png create mode 100644 src/assets/images/room-widgets/wordquiz-widget/thumbs-up-small.png create mode 100644 src/assets/images/room-widgets/wordquiz-widget/thumbs-up.png create mode 100644 src/views/room/widgets/word-quiz/views/vote/VoteView.tsx create mode 100644 src/views/room/widgets/word-quiz/views/vote/VoteView.types.ts diff --git a/src/api/nitro/room/widgets/handlers/PollWidgetHandler.ts b/src/api/nitro/room/widgets/handlers/PollWidgetHandler.ts index df4d67b7..0d1b0457 100644 --- a/src/api/nitro/room/widgets/handlers/PollWidgetHandler.ts +++ b/src/api/nitro/room/widgets/handlers/PollWidgetHandler.ts @@ -43,7 +43,6 @@ export class PollWidgetHandler extends RoomWidgetHandler public processWidgetMessage(message: RoomWidgetMessage): RoomWidgetUpdateEvent { const pollMessage = (message as RoomWidgetPollMessage); - switch(message.type) { case RoomWidgetPollMessage.START: diff --git a/src/api/nitro/room/widgets/handlers/WordQuizWidgetHandler.ts b/src/api/nitro/room/widgets/handlers/WordQuizWidgetHandler.ts index c65632ee..df24b06e 100644 --- a/src/api/nitro/room/widgets/handlers/WordQuizWidgetHandler.ts +++ b/src/api/nitro/room/widgets/handlers/WordQuizWidgetHandler.ts @@ -11,7 +11,6 @@ export class WordQuizWidgetHandler extends RoomWidgetHandler { const roomQuizEvent = (event as RoomSessionWordQuizEvent); let widgetEvent: RoomWidgetWordQuizUpdateEvent; - switch(event.type) { case RoomSessionWordQuizEvent.ANSWERED: diff --git a/src/assets/images/room-widgets/wordquiz-widget/thumbs-down-small.png b/src/assets/images/room-widgets/wordquiz-widget/thumbs-down-small.png new file mode 100644 index 0000000000000000000000000000000000000000..78e51cfe5666ccc5fe46dcd7976f615d19eab56b GIT binary patch literal 145 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4f5uPrNAr-gYPIcsBP~c$s?*H$9 zZdkj6i$Tur7G^ow5`Hd;Ee-EoTf{t%3P-w%zGj`@S-x*>Vfq>2*}a+NP7@R&Lzig! sFNyP+%$9WF=#@-=yCb|#^S2#h&~MqhAozyaL!ccDp00i_>zopr00L$)8~^|S literal 0 HcmV?d00001 diff --git a/src/assets/images/room-widgets/wordquiz-widget/thumbs-down.png b/src/assets/images/room-widgets/wordquiz-widget/thumbs-down.png new file mode 100644 index 0000000000000000000000000000000000000000..fd320c51d72f0debe17f9537d132ec4de35bf815 GIT binary patch literal 182 zcmeAS@N?(olHy`uVBq!ia0vp^@<6P_!3HFkdog(dsaj7L$B>F!Z?9bBYf#{5O}y9n zz20n9x0&0EGbb0S{y*j`US~PiMJ+NW|82kxr`Fv+B;%QntL{+KYvB5RZqC;?8;co3 zcluQ5JW=caG8r!IE7jJKC2Yu=J)QJ hqVly?g7yYi8Nao2ZhvIZ@C@h>22WQ%mvv4FO#s~;NumG% literal 0 HcmV?d00001 diff --git a/src/assets/images/room-widgets/wordquiz-widget/thumbs-up-small.png b/src/assets/images/room-widgets/wordquiz-widget/thumbs-up-small.png new file mode 100644 index 0000000000000000000000000000000000000000..b93111f0cc078bd21ac90ce83f59ce4663474d53 GIT binary patch literal 135 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4fex5FlAr-fh6BLC0v@@|~G0&3r zDLwo$$zUt5x!UOu|5KP|N%~wU@Zvp|-f74ad^KU#&Wab3Hd4o&EqXL{^;hH>T$#?2 iEs<F!Z>KwQF(~pde^&qh zf7`pzl&z;$ a8+P{toZC}5t{w$CfWgz%&t;ucLK6V707rlT literal 0 HcmV?d00001 diff --git a/src/views/room/widgets/RoomWidgetsView.tsx b/src/views/room/widgets/RoomWidgetsView.tsx index 0a94e885..4f205b1d 100644 --- a/src/views/room/widgets/RoomWidgetsView.tsx +++ b/src/views/room/widgets/RoomWidgetsView.tsx @@ -1,4 +1,4 @@ -import { RoomEngineEvent, RoomEngineObjectEvent, RoomEngineRoomAdEvent, RoomEngineTriggerWidgetEvent, RoomEngineUseProductEvent, RoomId, RoomObjectCategory, RoomObjectOperationType, RoomObjectVariable, RoomSessionChatEvent, RoomSessionDanceEvent, RoomSessionDimmerPresetsEvent, RoomSessionDoorbellEvent, RoomSessionErrorMessageEvent, RoomSessionEvent, RoomSessionFriendRequestEvent, RoomSessionPetInfoUpdateEvent, RoomSessionPresentEvent, RoomSessionUserBadgesEvent, RoomZoomEvent } from '@nitrots/nitro-renderer'; +import { RoomEngineEvent, RoomEngineObjectEvent, RoomEngineRoomAdEvent, RoomEngineTriggerWidgetEvent, RoomEngineUseProductEvent, RoomId, RoomObjectCategory, RoomObjectOperationType, RoomObjectVariable, RoomSessionChatEvent, RoomSessionDanceEvent, RoomSessionDimmerPresetsEvent, RoomSessionDoorbellEvent, RoomSessionErrorMessageEvent, RoomSessionEvent, RoomSessionFriendRequestEvent, RoomSessionPetInfoUpdateEvent, RoomSessionPollEvent, RoomSessionPresentEvent, RoomSessionUserBadgesEvent, RoomSessionWordQuizEvent, RoomZoomEvent } from '@nitrots/nitro-renderer'; import { FC, useCallback } from 'react'; import { CanManipulateFurniture, GetRoomEngine, GetSessionDataManager, IsFurnitureSelectionDisabled, LocalizeText, ProcessRoomObjectOperation, RoomWidgetFurniToWidgetMessage, RoomWidgetUpdateRoomEngineEvent, RoomWidgetUpdateRoomObjectEvent } from '../../../api'; import { useRoomEngineEvent, useRoomSessionManagerEvent } from '../../../hooks/events'; @@ -269,6 +269,12 @@ export const RoomWidgetsView: FC = props => useRoomSessionManagerEvent(RoomSessionFriendRequestEvent.RSFRE_FRIEND_REQUEST, onRoomSessionEvent); useRoomSessionManagerEvent(RoomSessionPresentEvent.RSPE_PRESENT_OPENED, onRoomSessionEvent); useRoomSessionManagerEvent(RoomSessionPetInfoUpdateEvent.PET_INFO, onRoomSessionEvent); + useRoomSessionManagerEvent(RoomSessionWordQuizEvent.ANSWERED, onRoomSessionEvent); + useRoomSessionManagerEvent(RoomSessionWordQuizEvent.FINISHED, onRoomSessionEvent); + useRoomSessionManagerEvent(RoomSessionWordQuizEvent.QUESTION, onRoomSessionEvent); + useRoomSessionManagerEvent(RoomSessionPollEvent.OFFER, onRoomSessionEvent); + useRoomSessionManagerEvent(RoomSessionPollEvent.ERROR, onRoomSessionEvent); + useRoomSessionManagerEvent(RoomSessionPollEvent.CONTENT, onRoomSessionEvent); const onRoomSessionErrorMessageEvent = useCallback((event: RoomSessionErrorMessageEvent) => { diff --git a/src/views/room/widgets/word-quiz/WordQuizWidgetView.scss b/src/views/room/widgets/word-quiz/WordQuizWidgetView.scss index d4291278..5889d925 100644 --- a/src/views/room/widgets/word-quiz/WordQuizWidgetView.scss +++ b/src/views/room/widgets/word-quiz/WordQuizWidgetView.scss @@ -1,12 +1,39 @@ -.word-quiz-question-container { +.wordquiz-question { position: absolute; top: 10px; - left: 0px; - .wordquiz-question { - font-size: large; - background: rgba($dark, 0.90); - //box-shadow: inset 0px 5px lighten(rgba($dark,.6),2.5), inset 0 -4px darken(rgba($dark,.6),4); - border-radius: $border-radius; - transition: all 0.2s ease; + left: 50%; + transform: translateX(-50%); + font-size: large; + background: rgba($dark, 0.9); + //box-shadow: inset 0px 5px lighten(rgba($dark,.6),2.5), inset 0 -4px darken(rgba($dark,.6),4); + border-radius: $border-radius; + transition: all 0.2s ease; + + .question { + max-width: 300px; } } + +.word-quiz-dislike { + background: url("../../../../assets/images/room-widgets/wordquiz-widget/thumbs-down.png"); + width: 31px; + height: 34px; +} + +.word-quiz-like { + background: url("../../../../assets/images/room-widgets/wordquiz-widget/thumbs-up.png"); + width: 31px; + height: 34px; +} + +.word-quiz-dislike-sm { + background: url("../../../../assets/images/room-widgets/wordquiz-widget/thumbs-down-small.png"); + width: 22px; + height: 22px; +} + +.word-quiz-like-sm { + background: url("../../../../assets/images/room-widgets/wordquiz-widget/thumbs-up-small.png"); + height: 22px; + width: 22px; +} diff --git a/src/views/room/widgets/word-quiz/WordQuizWidgetView.tsx b/src/views/room/widgets/word-quiz/WordQuizWidgetView.tsx index a529f409..af258d59 100644 --- a/src/views/room/widgets/word-quiz/WordQuizWidgetView.tsx +++ b/src/views/room/widgets/word-quiz/WordQuizWidgetView.tsx @@ -1,17 +1,32 @@ import { IQuestion } from '@nitrots/nitro-renderer'; -import { FC, useCallback, useState } from 'react'; +import { FC, useCallback, useEffect, useState } from 'react'; import { RoomWidgetWordQuizUpdateEvent } from '../../../../api/nitro/room/widgets/events/RoomWidgetWordQuizUpdateEvent'; +import { RoomWidgetPollMessage } from '../../../../api/nitro/room/widgets/messages/RoomWidgetPollMessage'; import { BatchUpdates, CreateEventDispatcherHook } from '../../../../hooks'; import { useRoomContext } from '../../context/RoomContext'; +import { VALUE_KEY_DISLIKE, VALUE_KEY_LIKE, VoteValue } from './common/VoteValue'; import { QuestionView } from './views/question/QuestionView'; +import { VoteView } from './views/vote/VoteView'; + +const DEFAULT_DISPLAY_DELAY = 4000; +const SIGN_FADE_DELAY = 3; export const WordQuizWidgetView: FC<{}> = props => { - const { eventDispatcher = null, widgetHandler = null } = useRoomContext(); - const [pollId, setPollId ] = useState(-1); + const { eventDispatcher = null, widgetHandler = null, roomSession = null } = useRoomContext(); + const [pollId, setPollId] = useState(-1); const [question, setQuestion] = useState(null); - const [ answerSent, setAnswerSent ] = useState(false); - + const [answerSent, setAnswerSent] = useState(false); + const [questionClearTimeout, setQuestionClearTimeout] = useState(null); + const [answerCounts, setAnswerCounts] = useState>(new Map()); + const [userAnswers, setUserAnswers] = useState>(new Map()); + + const clearQuestion = useCallback(() => + { + setPollId(-1); + setQuestion(null); + }, []); + const onRoomWidgetWordQuizUpdateEvent = useCallback((event: RoomWidgetWordQuizUpdateEvent) => { switch(event.type) @@ -22,25 +37,131 @@ export const WordQuizWidgetView: FC<{}> = props => setPollId(event.id); setQuestion(event.question); setAnswerSent(false); + setAnswerCounts(new Map()); + setUserAnswers(new Map()); + if(questionClearTimeout) clearTimeout(questionClearTimeout); }); - //this._showSignCounters = new Dictionary(); - //this.showNewQuestion(this._question, k.duration); + + if(event.duration > 0) + { + const delay = event.duration < 1000 ? DEFAULT_DISPLAY_DELAY : event.duration; + setQuestionClearTimeout(prevValue => + { + if(prevValue) clearTimeout(prevValue); + + return setTimeout((clearQuestion as TimerHandler), delay); + }) + } + break; + case RoomWidgetWordQuizUpdateEvent.QUESTION_ANSWERED: + const userData = roomSession.userDataManager.getUserData(event.userId); + if(!userData) return; + + setAnswerCounts(event.answerCounts); + + if(!userAnswers.has(userData.roomIndex)) + { + const answersCopy = new Map(userAnswers); + answersCopy.set(userData.roomIndex, { value: event.value, secondsLeft: SIGN_FADE_DELAY }); + setUserAnswers(answersCopy); + } + break; + case RoomWidgetWordQuizUpdateEvent.QUESTION_FINISHED: + if(question && question.id === event.questionId) + { + BatchUpdates(() => + { + setAnswerCounts(event.answerCounts); + setAnswerSent(true); + setQuestionClearTimeout(prevValue => + { + if(prevValue) clearTimeout(prevValue); + + return setTimeout((clearQuestion as TimerHandler), DEFAULT_DISPLAY_DELAY); + }); + }) + } + setUserAnswers(new Map()); break; } - }, []); - - const vote = useCallback((vote: string) => - { - - }, []); + }, [clearQuestion, question, questionClearTimeout, roomSession.userDataManager, userAnswers]); CreateEventDispatcherHook(RoomWidgetWordQuizUpdateEvent.NEW_QUESTION, eventDispatcher, onRoomWidgetWordQuizUpdateEvent); CreateEventDispatcherHook(RoomWidgetWordQuizUpdateEvent.QUESTION_ANSWERED, eventDispatcher, onRoomWidgetWordQuizUpdateEvent); CreateEventDispatcherHook(RoomWidgetWordQuizUpdateEvent.QUESTION_FINISHED, eventDispatcher, onRoomWidgetWordQuizUpdateEvent); + const vote = useCallback((vote: string) => + { + if(answerSent || !question) return; + + const updateMessage = new RoomWidgetPollMessage(RoomWidgetPollMessage.ANSWER, pollId); + updateMessage.questionId = question.id; + updateMessage.answers = [vote]; + widgetHandler.processWidgetMessage(updateMessage); + setAnswerSent(true); + + }, [answerSent, pollId, question, widgetHandler]); + + const checkSignFade = useCallback(() => + { + setUserAnswers(prev => + { + const copy = new Map(prev); + const keysToRemove: number[] = []; + copy.forEach((value, key) => + { + value.secondsLeft--; + + if(value.secondsLeft <= 0) + { + keysToRemove.push(key); + } + }); + + keysToRemove.forEach(key => copy.delete(key)); + + return copy; + }) + + }, []); + + useEffect(() => + { + const interval = setInterval(() => + { + checkSignFade(); + }, 1000) + + return () => + { + clearInterval(interval); + } + }, [checkSignFade]); + + useEffect(() => + { + return () => + { + setQuestionClearTimeout(prev => + { + if(prev) clearTimeout(prev); + + return null; + }); + } + }, []); + return ( - <> - {question && } - + <> + {question && + + } + {userAnswers && + Array.from(userAnswers.entries()).map(([key, value], index) => + { + return + }) + } + ); } diff --git a/src/views/room/widgets/word-quiz/common/VoteValue.ts b/src/views/room/widgets/word-quiz/common/VoteValue.ts index ef84aaff..ecf4336e 100644 --- a/src/views/room/widgets/word-quiz/common/VoteValue.ts +++ b/src/views/room/widgets/word-quiz/common/VoteValue.ts @@ -1,2 +1,8 @@ export const VALUE_KEY_DISLIKE = '0'; export const VALUE_KEY_LIKE = '1'; + +export interface VoteValue +{ + value: string; + secondsLeft: number; +} diff --git a/src/views/room/widgets/word-quiz/views/question/QuestionView.tsx b/src/views/room/widgets/word-quiz/views/question/QuestionView.tsx index 13bbf225..2d2b5d17 100644 --- a/src/views/room/widgets/word-quiz/views/question/QuestionView.tsx +++ b/src/views/room/widgets/word-quiz/views/question/QuestionView.tsx @@ -1,14 +1,24 @@ import { FC } from 'react'; +import { VALUE_KEY_DISLIKE, VALUE_KEY_LIKE } from '../../common/VoteValue'; import { QuestionViewProps } from './QuestionView.types'; export const QuestionView:FC = props => { - const { question = null, canVote = null } = props; + const { question = null, canVote = null, vote = null, noVotes = null, yesVotes = null } = props; return ( -
-
{question}
+
+
+ { !canVote && } +
{question}
+ { !canVote && } +
+ {canVote && +
+ + +
+ }
- ) } diff --git a/src/views/room/widgets/word-quiz/views/question/QuestionView.types.ts b/src/views/room/widgets/word-quiz/views/question/QuestionView.types.ts index 09fda7b4..fde51dba 100644 --- a/src/views/room/widgets/word-quiz/views/question/QuestionView.types.ts +++ b/src/views/room/widgets/word-quiz/views/question/QuestionView.types.ts @@ -4,4 +4,6 @@ export interface QuestionViewProps question: string; canVote: boolean; vote(value: string): void; + noVotes: number; + yesVotes: number; } diff --git a/src/views/room/widgets/word-quiz/views/vote/VoteView.tsx b/src/views/room/widgets/word-quiz/views/vote/VoteView.tsx new file mode 100644 index 00000000..bee02143 --- /dev/null +++ b/src/views/room/widgets/word-quiz/views/vote/VoteView.tsx @@ -0,0 +1,16 @@ +import { RoomObjectCategory } from '@nitrots/nitro-renderer/src'; +import { FC } from 'react'; +import { ObjectLocationView } from '../../../object-location/ObjectLocationView'; +import { VALUE_KEY_DISLIKE } from '../../common/VoteValue'; +import { VoteViewProps } from './VoteView.types'; + +export const VoteView:FC = props => +{ + const { userIndex = null , vote = null } = props; + + return ( + + + + ) +} diff --git a/src/views/room/widgets/word-quiz/views/vote/VoteView.types.ts b/src/views/room/widgets/word-quiz/views/vote/VoteView.types.ts new file mode 100644 index 00000000..17062cc6 --- /dev/null +++ b/src/views/room/widgets/word-quiz/views/vote/VoteView.types.ts @@ -0,0 +1,5 @@ +export interface VoteViewProps +{ + userIndex: number; + vote: string; +}