From 061669a4f6e6b3c21a67f4e731bfb62f59a8ff35 Mon Sep 17 00:00:00 2001 From: leeyi45 Date: Wed, 6 Sep 2023 03:15:59 +0800 Subject: [PATCH 001/112] Add typeguards --- src/typings/anim_types.tsx | 2 +- src/typings/type_helpers.ts | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/typings/anim_types.tsx b/src/typings/anim_types.tsx index 5afa02de8..d7d9115b7 100644 --- a/src/typings/anim_types.tsx +++ b/src/typings/anim_types.tsx @@ -9,7 +9,7 @@ export abstract class glAnimation { public abstract getFrame(timestamp: number): AnimFrame; - public static isAnimation = (obj: any) => obj.fps !== undefined; + public static isAnimation = (obj: any): obj is glAnimation => obj.fps !== undefined; } export interface AnimFrame { diff --git a/src/typings/type_helpers.ts b/src/typings/type_helpers.ts index 2c300ca3f..fb55cf22d 100644 --- a/src/typings/type_helpers.ts +++ b/src/typings/type_helpers.ts @@ -19,4 +19,10 @@ export type ModuleContexts = Context['moduleContexts']; */ export interface ReplResult { toReplString: () => string; -} \ No newline at end of file +} + +export type TabProps = { + context: DebuggerContext; +}; + +export const getModuleState = ({ context: { moduleContexts } }: DebuggerContext, moduleName: string) => moduleContexts[moduleName].state as T; From 5a3decf8c86ac1abd4478103b6fe52db163e143e Mon Sep 17 00:00:00 2001 From: leeyi45 Date: Wed, 6 Sep 2023 03:16:14 +0800 Subject: [PATCH 002/112] Use typeguards with rune module --- src/bundles/rune/functions.ts | 7 ++++ src/tabs/Rune/index.tsx | 71 ++++++++++++++++------------------- 2 files changed, 40 insertions(+), 38 deletions(-) diff --git a/src/bundles/rune/functions.ts b/src/bundles/rune/functions.ts index 71b3c7fe7..e7c7079ff 100644 --- a/src/bundles/rune/functions.ts +++ b/src/bundles/rune/functions.ts @@ -43,6 +43,10 @@ context.moduleContexts.rune.state = { drawnRunes, }; +export type RuneModuleState = { + drawnRunes: (DrawnRune | AnimatedRune)[] +}; + // ============================================================================= // Basic Runes // ============================================================================= @@ -951,6 +955,9 @@ export class HollusionRune extends DrawnRune { }; } +/** @hidden */ +export const isHollusionRune = (rune: DrawnRune): rune is HollusionRune => rune.isHollusion; + /** * Renders the specified Rune in a tab as a hollusion, using the specified * magnitude. diff --git a/src/tabs/Rune/index.tsx b/src/tabs/Rune/index.tsx index 9141a841b..3d0618cde 100644 --- a/src/tabs/Rune/index.tsx +++ b/src/tabs/Rune/index.tsx @@ -1,16 +1,41 @@ -import React from 'react'; -import { type HollusionRune } from '../../bundles/rune/functions'; -import type { - AnimatedRune, - DrawnRune, -} from '../../bundles/rune/rune'; +import { type RuneModuleState, isHollusionRune } from '../../bundles/rune/functions'; import { glAnimation } from '../../typings/anim_types'; import MultiItemDisplay from '../common/multi_item_display'; -import { type DebuggerContext } from '../../typings/type_helpers'; +import { getModuleState, type DebuggerContext, type TabProps } from '../../typings/type_helpers'; import AnimationCanvas from '../common/animation_canvas'; import HollusionCanvas from './hollusion_canvas'; import WebGLCanvas from '../common/webgl_canvas'; +const RuneTab = ({ context }: TabProps) => { + const { drawnRunes } = getModuleState(context, 'rune'); + const runeCanvases = drawnRunes.map((rune, i) => { + const elemKey = i.toString(); + + if (glAnimation.isAnimation(rune)) { + return ( + + ); + } + if (isHollusionRune(rune)) { + return ( + + ); + } + return ( + { + if (r) { + rune.draw(r); + } + }} + key={elemKey} + /> + ); + }); + + return ; +}; + export default { /** * This function will be called to determine if the component will be @@ -30,37 +55,7 @@ export default { * @param {DebuggerContext} context */ body(context: DebuggerContext) { - const { context: { moduleContexts: { rune: { state: { drawnRunes } } } } } = context; - - // Based on the toSpawn conditions, it should be safe to assume - // that neither moduleContext or moduleState are null - const runeCanvases = drawnRunes.map((rune, i) => { - const elemKey = i.toString(); - - if (glAnimation.isAnimation(rune)) { - return ( - - ); - } - const drawnRune = rune as DrawnRune; - if (drawnRune.isHollusion) { - return ( - - ); - } - return ( - { - if (r) { - drawnRune.draw(r); - } - }} - key={elemKey} - /> - ); - }); - - return ; + return ; }, /** From d91ed7d16cc677d1cb31d8d29cb344ea130fb76b Mon Sep 17 00:00:00 2001 From: leeyi45 Date: Wed, 6 Sep 2023 03:16:26 +0800 Subject: [PATCH 003/112] Use typeguards with curve module --- src/bundles/curve/types.ts | 4 ++ src/tabs/Curve/index.tsx | 75 +++++++++++++++++++------------------- 2 files changed, 41 insertions(+), 38 deletions(-) diff --git a/src/bundles/curve/types.ts b/src/bundles/curve/types.ts index 787c55235..79ef6a50b 100644 --- a/src/bundles/curve/types.ts +++ b/src/bundles/curve/types.ts @@ -2,6 +2,10 @@ import { glAnimation, type AnimFrame } from '../../typings/anim_types'; import type { ReplResult } from '../../typings/type_helpers'; import type { Curve, CurveDrawn } from './curves_webgl'; +export type CurveModuleState = { + drawnCurves: (CurveDrawn | AnimatedCurve)[] +}; + /** A function that takes in CurveFunction and returns a tranformed CurveFunction. */ export type CurveTransformer = (c: Curve) => Curve; diff --git a/src/tabs/Curve/index.tsx b/src/tabs/Curve/index.tsx index c5ff94d2f..05e5c7aee 100644 --- a/src/tabs/Curve/index.tsx +++ b/src/tabs/Curve/index.tsx @@ -1,54 +1,53 @@ -import React from 'react'; -import type { CurveDrawn } from '../../bundles/curve/curves_webgl'; -import type { AnimatedCurve } from '../../bundles/curve/types'; +import type { CurveModuleState } from '../../bundles/curve/types'; import { glAnimation } from '../../typings/anim_types'; import MultiItemDisplay from '../common/multi_item_display'; -import type { DebuggerContext } from '../../typings/type_helpers'; +import { getModuleState, type DebuggerContext, type TabProps } from '../../typings/type_helpers'; import Curve3DAnimationCanvas from './3Dcurve_anim_canvas'; import CurveCanvas3D from './curve_canvas3d'; import AnimationCanvas from '../common/animation_canvas'; import WebGLCanvas from '../common/webgl_canvas'; -export default { - toSpawn(context: DebuggerContext) { - const drawnCurves = context.context?.moduleContexts?.curve?.state?.drawnCurves; - return drawnCurves.length > 0; - }, - body(context: DebuggerContext) { - const { context: { moduleContexts: { curve: { state: { drawnCurves } } } } } = context; +const CurveTab = ({ context }: TabProps) => { + const { drawnCurves } = getModuleState(context, 'curve'); + const canvases = drawnCurves.map((curve, i) => { + const elemKey = i.toString(); - const canvases = drawnCurves.map((curve, i) => { - const elemKey = i.toString(); - - if (glAnimation.isAnimation(curve)) { - const anim = curve as AnimatedCurve; - return anim.is3D - ? ( - - ) - : ( - - ); - } - const curveDrawn = curve as CurveDrawn; - return curveDrawn.is3D() + if (glAnimation.isAnimation(curve)) { + return curve.is3D ? ( - + ) : ( - { - if (r) { - curveDrawn.init(r); - curveDrawn.redraw(0); - } - }} - key={elemKey} - /> + ); - }); + } + return curve.is3D() + ? ( + + ) + : ( + { + if (r) { + curve.init(r); + curve.redraw(0); + } + }} + key={elemKey} + /> + ); + }); - return ; + return ; +}; + +export default { + toSpawn(context: DebuggerContext) { + const drawnCurves = context.context?.moduleContexts?.curve?.state?.drawnCurves; + return drawnCurves.length > 0; + }, + body(context: DebuggerContext) { + return ; }, label: 'Curves Tab', iconName: 'media', // See https://blueprintjs.com/docs/#icons for more options From 5198b172e5ff160d0dd9ca6e4dda928f149c9dd8 Mon Sep 17 00:00:00 2001 From: leeyi45 Date: Wed, 6 Sep 2023 03:29:57 +0800 Subject: [PATCH 004/112] Update other modules to have separate JSX components --- src/bundles/sound/types.ts | 4 +++ src/bundles/stereo_sound/types.ts | 4 +++ src/tabs/Sound/index.tsx | 55 +++++++++++++++++-------------- src/tabs/StereoSound/index.tsx | 49 +++++++++++++-------------- 4 files changed, 64 insertions(+), 48 deletions(-) diff --git a/src/bundles/sound/types.ts b/src/bundles/sound/types.ts index 9b360ada1..ead2fd9ff 100644 --- a/src/bundles/sound/types.ts +++ b/src/bundles/sound/types.ts @@ -12,3 +12,7 @@ export type AudioPlayed = { toReplString: () => string; dataUri: string; }; + +export type SoundModuleState = { + audioPlayed: AudioPlayed[] +}; diff --git a/src/bundles/stereo_sound/types.ts b/src/bundles/stereo_sound/types.ts index e0ce3bfbd..4f5da85a6 100644 --- a/src/bundles/stereo_sound/types.ts +++ b/src/bundles/stereo_sound/types.ts @@ -12,3 +12,7 @@ export type AudioPlayed = { toReplString: () => string; dataUri: string; }; + +export type StereoSoundModuleState = { + audioPlayed: AudioPlayed[]; +}; diff --git a/src/tabs/Sound/index.tsx b/src/tabs/Sound/index.tsx index 4ed5007fe..b955212da 100644 --- a/src/tabs/Sound/index.tsx +++ b/src/tabs/Sound/index.tsx @@ -1,12 +1,40 @@ -import React from 'react'; -import type { DebuggerContext } from '../../typings/type_helpers'; +import type { AudioPlayed, SoundModuleState } from '../../bundles/sound/types'; +import { getModuleState, type DebuggerContext } from '../../typings/type_helpers'; import MultiItemDisplay from '../common/multi_item_display'; +export type SoundTabProps = { + getAudioPlayed: () => T[] +}; + /** * Tab for Source Academy Sounds Module * @author Koh Shang Hui * @author Samyukta Sounderraman */ +export const SoundTab = ({ getAudioPlayed }: SoundTabProps) => { + const audioPlayed = getAudioPlayed(); + const elements = audioPlayed.map((audio) => ( +