diff --git a/src/App.tsx b/src/App.tsx index e2119242..9808b83e 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -5,6 +5,8 @@ import { Base, TransitionAnimation, TransitionAnimationTypes } from './common'; import { LoadingView } from './components/loading/LoadingView'; import { MainView } from './components/main/MainView'; import { DispatchUiEvent, UseConfigurationEvent, UseLocalizationEvent, UseMainEvent, UseRoomEngineEvent } from './hooks'; +import IntervalWebWorker from './workers/IntervalWebWorker'; +import { WorkerBuilder } from './workers/WorkerBuilder'; NitroVersion.UI_VERSION = GetUIVersion(); @@ -18,7 +20,14 @@ export const App: FC<{}> = props => //@ts-ignore if(!NitroConfig) throw new Error('NitroConfig is not defined!'); - if(!GetNitroInstance()) Nitro.bootstrap(); + if(!GetNitroInstance()) + { + Nitro.bootstrap(); + + const worker = new WorkerBuilder(IntervalWebWorker); + + Nitro.instance.setWorker(worker); + } const getPreloadAssetUrls = useCallback(() => { diff --git a/src/api/nitro/AddWorkerEventTracker.ts b/src/api/nitro/AddWorkerEventTracker.ts new file mode 100644 index 00000000..0d81670b --- /dev/null +++ b/src/api/nitro/AddWorkerEventTracker.ts @@ -0,0 +1,7 @@ +import { IWorkerEventTracker } from '@nitrots/nitro-renderer'; +import { GetNitroInstance } from './GetNitroInstance'; + +export const AddWorkerEventTracker = (tracker: IWorkerEventTracker) => +{ + GetNitroInstance().addWorkerEventTracker(tracker); +} diff --git a/src/api/nitro/RemoveWorkerEventTracker.ts b/src/api/nitro/RemoveWorkerEventTracker.ts new file mode 100644 index 00000000..a1307118 --- /dev/null +++ b/src/api/nitro/RemoveWorkerEventTracker.ts @@ -0,0 +1,7 @@ +import { IWorkerEventTracker } from '@nitrots/nitro-renderer'; +import { GetNitroInstance } from './GetNitroInstance'; + +export const RemoveWorkerEventTracker = (tracker: IWorkerEventTracker) => +{ + GetNitroInstance().removeWorkerEventTracker(tracker); +} diff --git a/src/api/nitro/SendWorkerEvent.ts b/src/api/nitro/SendWorkerEvent.ts new file mode 100644 index 00000000..b0e32740 --- /dev/null +++ b/src/api/nitro/SendWorkerEvent.ts @@ -0,0 +1,6 @@ +import { GetNitroInstance } from './GetNitroInstance'; + +export const SendWorkerEvent = (message: { [index: string]: any }) => +{ + GetNitroInstance().sendWorkerEvent(message); +} diff --git a/src/api/nitro/index.ts b/src/api/nitro/index.ts index 18b2de0c..3e371d5d 100644 --- a/src/api/nitro/index.ts +++ b/src/api/nitro/index.ts @@ -1,4 +1,5 @@ export * from './AddLinkEventTracker'; +export * from './AddWorkerEventTracker'; export * from './avatar'; export * from './camera'; export * from './CreateLinkEvent'; @@ -9,10 +10,12 @@ export * from './GetLocalization'; export * from './GetNitroInstance'; export * from './GetTicker'; export * from './RemoveLinkEventTracker'; +export * from './RemoveWorkerEventTracker'; export * from './room'; export * from './room/widgets'; export * from './room/widgets/events'; export * from './room/widgets/handlers'; export * from './room/widgets/messages'; export * from './SendMessageComposer'; +export * from './SendWorkerEvent'; export * from './session'; diff --git a/src/components/room/widgets/chat/ChatWidgetView.tsx b/src/components/room/widgets/chat/ChatWidgetView.tsx index bf9d8a9e..d3ebb53e 100644 --- a/src/components/room/widgets/chat/ChatWidgetView.tsx +++ b/src/components/room/widgets/chat/ChatWidgetView.tsx @@ -1,16 +1,19 @@ -import { GetGuestRoomResultEvent, NitroPoint, RoomChatSettings, RoomChatSettingsEvent, RoomDragEvent } from '@nitrots/nitro-renderer'; +import { GetGuestRoomResultEvent, IWorkerEventTracker, NitroPoint, RoomChatSettings, RoomChatSettingsEvent, RoomDragEvent } from '@nitrots/nitro-renderer'; import { FC, useCallback, useEffect, useRef, useState } from 'react'; -import { GetConfiguration, RoomChatFormatter, RoomWidgetChatSelectAvatarMessage, RoomWidgetRoomObjectMessage, RoomWidgetUpdateChatEvent } from '../../../../api'; +import { AddWorkerEventTracker, GetConfiguration, RemoveWorkerEventTracker, RoomChatFormatter, RoomWidgetChatSelectAvatarMessage, RoomWidgetRoomObjectMessage, RoomWidgetUpdateChatEvent, SendWorkerEvent } from '../../../../api'; import { UseEventDispatcherHook, UseMessageEventHook, UseRoomEngineEvent } from '../../../../hooks'; import { useRoomContext } from '../../RoomContext'; import { ChatWidgetMessageView } from './ChatWidgetMessageView'; import { ChatBubbleMessage } from './common/ChatBubbleMessage'; import { DoChatsOverlap } from './common/DoChatsOverlap'; +let TIMER_TRACKER: number = 0; + export const ChatWidgetView: FC<{}> = props => { const [ chatSettings, setChatSettings ] = useState(null); const [ chatMessages, setChatMessages ] = useState([]); + const [ timerId, setTimerId ] = useState(TIMER_TRACKER++); const { roomSession = null, eventDispatcher = null, widgetHandler = null } = useRoomContext(); const elementRef = useRef(); @@ -182,16 +185,6 @@ export const ChatWidgetView: FC<{}> = props => UseMessageEventHook(RoomChatSettingsEvent, onRoomChatSettingsEvent); - useEffect(() => - { - const interval = setInterval(() => moveAllChatsUp(15), getScrollSpeed()); - - return () => - { - if(interval) clearInterval(interval); - } - }, [ moveAllChatsUp, getScrollSpeed ]); - useEffect(() => { if(!elementRef || !elementRef.current) return; @@ -199,6 +192,42 @@ export const ChatWidgetView: FC<{}> = props => elementRef.current.style.height = ((document.body.offsetHeight * GetConfiguration('chat.viewer.height.percentage')) + 'px'); }, []); + const workerMessageReceived = useCallback((message: { [index: string]: any }) => + { + switch(message.type) + { + case 'MOVE_CHATS': + moveAllChatsUp(15); + return; + } + }, [ moveAllChatsUp ]); + + useEffect(() => + { + const workerTracker: IWorkerEventTracker = { + workerMessageReceived + }; + + AddWorkerEventTracker(workerTracker); + + SendWorkerEvent({ + type: 'CREATE_INTERVAL', + time: getScrollSpeed(), + timerId: timerId, + response: { type: 'MOVE_CHATS' } + }); + + return () => + { + SendWorkerEvent({ + type: 'REMOVE_INTERVAL', + timerId + }); + + RemoveWorkerEventTracker(workerTracker); + } + }, [ timerId, workerMessageReceived, getScrollSpeed ]); + return (
{chatMessages.map(chat => )} diff --git a/src/workers/IntervalWebWorker.ts b/src/workers/IntervalWebWorker.ts new file mode 100644 index 00000000..4d5ddbc0 --- /dev/null +++ b/src/workers/IntervalWebWorker.ts @@ -0,0 +1,49 @@ +// eslint-disable-next-line import/no-anonymous-default-export +export default () => +{ + const intervals: { + id: number, + interval: ReturnType + }[] = []; + + // eslint-disable-next-line no-restricted-globals + self.onmessage = (message: MessageEvent) => + { + if(!message) return; + + const data: { [index: string]: any } = message.data; + + switch(data.type) + { + case 'CREATE_INTERVAL': { + const id = (data.timerId as number); + const time = (data.time as number); + const response = (data.response as string); + + const interval = setInterval(() => postMessage(response), time); + + intervals.push({ id, interval }); + return; + } + case 'REMOVE_INTERVAL': { + const id = (data.timerId as number); + + const i = 0; + + while(i < intervals.length) + { + const interval = intervals[i]; + + if(interval.id === id) + { + clearInterval(interval.interval); + + intervals.splice(i, 1); + + return; + } + } + } + } + } +} diff --git a/src/workers/WorkerBuilder.ts b/src/workers/WorkerBuilder.ts new file mode 100644 index 00000000..be3454ab --- /dev/null +++ b/src/workers/WorkerBuilder.ts @@ -0,0 +1,10 @@ +export class WorkerBuilder extends Worker +{ + constructor(worker) + { + const code = worker.toString(); + const blob = new Blob([`(${code})()`]); + + super(URL.createObjectURL(blob)); + } +}