From 3aad98a982ce9654f754b3f898c2fcec6c085862 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=A3o=20Magalh=C3=A3es?= <joamag@gmail.com>
Date: Mon, 14 Nov 2022 13:16:08 +0000
Subject: [PATCH] refactor: changed repository structure

---
 Cargo.toml                    |   2 +-
 examples/web/gb.ts            |  50 ++++++++--------
 examples/web/package.json     |   2 +-
 examples/web/react/app.tsx    |  26 ++++-----
 examples/web/react/structs.ts | 105 ++++++++++++++++------------------
 5 files changed, 88 insertions(+), 97 deletions(-)

diff --git a/Cargo.toml b/Cargo.toml
index a93f5f83..1273cacc 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,7 +4,7 @@ description = "A Game Boy emulator that is written in Rust."
 version = "0.5.1"
 authors = ["João Magalhães <joamag@gmail.com>"]
 license = "Apache-2.0"
-repository = "https://gitlab.stage.hive.pt/joamag/boytacean"
+repository = "https://github.com/joamag/boytacean"
 keywords = ["gameboy", "emulator", "rust"]
 edition = "2018"
 
diff --git a/examples/web/gb.ts b/examples/web/gb.ts
index c627f11d..229873bf 100644
--- a/examples/web/gb.ts
+++ b/examples/web/gb.ts
@@ -1,6 +1,7 @@
 import {
     Emulator,
     EmulatorBase,
+    Entry,
     Feature,
     PixelFormat,
     RomInfo
@@ -349,36 +350,25 @@ export class GameboyEmulator extends EmulatorBase implements Emulator {
         return "Boytacean";
     }
 
-    get device(): string {
-        return "Game Boy";
-    }
-
-    get deviceUrl(): string {
-        return "https://en.wikipedia.org/wiki/Game_Boy";
-    }
-
-    get engines() {
-        return ["neo"];
-    }
-
-    get engine() {
-        return this._engine;
-    }
-
-    get version(): string {
-        return info.version;
-    }
-
-    get versionUrl(): string {
-        return "https://github.com/joamag/boytacean/blob/master/CHANGELOG.md";
+    get device(): Entry {
+        return {
+            text: "Game Boy",
+            url: "https://en.wikipedia.org/wiki/Game_Boy"
+        };
     }
 
-    get repository(): string | undefined {
-        return "GitHub";
+    get version(): Entry | undefined {
+        return {
+            text: info.version,
+            url: "https://github.com/joamag/boytacean/blob/master/CHANGELOG.md"
+        };
     }
 
-    get repositoryUrl(): string | undefined {
-        return "https://github.com/joamag/boytacean";
+    get repository(): Entry {
+        return {
+            text: "GitHub",
+            url: "https://github.com/joamag/boytacean"
+        };
     }
 
     get features(): Feature[] {
@@ -391,6 +381,14 @@ export class GameboyEmulator extends EmulatorBase implements Emulator {
         ];
     }
 
+    get engines() {
+        return ["neo"];
+    }
+
+    get engine() {
+        return this._engine;
+    }
+
     get romExts(): string[] {
         return ["gb"];
     }
diff --git a/examples/web/package.json b/examples/web/package.json
index 13ea9090..14aa7889 100644
--- a/examples/web/package.json
+++ b/examples/web/package.json
@@ -4,7 +4,7 @@
     "description": "The web version of Boytacean",
     "repository": {
         "type": "git",
-        "url": "git+https://gitlab.stage.hive.pt/joamag/boytacean.git"
+        "url": "git+https://github.com/joamag/boytacean.git"
     },
     "license": "Apache-2.0",
     "scripts": {
diff --git a/examples/web/react/app.tsx b/examples/web/react/app.tsx
index 0a0229a9..eaf26070 100644
--- a/examples/web/react/app.tsx
+++ b/examples/web/react/app.tsx
@@ -204,7 +204,7 @@ export const App: FC<AppProps> = ({
         const fileExtension = file.name.split(".").pop() ?? "";
         if (!emulator.romExts.includes(fileExtension)) {
             showToast(
-                `This is probably not a ${emulator.device} ROM file!`,
+                `This is probably not a ${emulator.device.text} ROM file!`,
                 true
             );
             return;
@@ -287,7 +287,7 @@ export const App: FC<AppProps> = ({
     const onEngineChange = (engine: string) => {
         emulator.boot({ engine: engine.toLowerCase() });
         showToast(
-            `${emulator.device} running in engine "${engine}" from now on!`
+            `${emulator.device.text} running in engine "${engine}" from now on!`
         );
     };
     const onFrequencyChange = (value: number) => {
@@ -374,21 +374,19 @@ export const App: FC<AppProps> = ({
                 </Section>
                 <Title
                     text={emulator.name}
-                    version={emulator.version}
-                    versionUrl={
-                        emulator.versionUrl ? emulator.versionUrl : undefined
-                    }
+                    version={emulator.version?.text}
+                    versionUrl={emulator.version?.url}
                     iconSrc={require("../res/thunder.png")}
                 ></Title>
                 <Section>
                     <Paragraph>
                         This is a{" "}
-                        {emulator.deviceUrl ? (
-                            <Link href={emulator.deviceUrl} target="_blank">
-                                {emulator.device}
+                        {emulator.device.url ? (
+                            <Link href={emulator.device.url} target="_blank">
+                                {emulator.device.text}
                             </Link>
                         ) : (
-                            emulator.device
+                            emulator.device.text
                         )}{" "}
                         emulator built using the{" "}
                         <Link href="https://www.rust-lang.org" target="_blank">
@@ -403,15 +401,15 @@ export const App: FC<AppProps> = ({
                     {emulator.repository && (
                         <Paragraph>
                             You can check the source code of it at{" "}
-                            {emulator.repositoryUrl ? (
+                            {emulator.repository.url ? (
                                 <Link
-                                    href={emulator.repositoryUrl}
+                                    href={emulator.repository.url}
                                     target="_blank"
                                 >
-                                    {emulator.repository}
+                                    {emulator.repository.text}
                                 </Link>
                             ) : (
-                                <>{emulator.repository}</>
+                                <>{emulator.repository.text}</>
                             )}
                             .
                         </Paragraph>
diff --git a/examples/web/react/structs.ts b/examples/web/react/structs.ts
index 714d6f42..465ff0a4 100644
--- a/examples/web/react/structs.ts
+++ b/examples/web/react/structs.ts
@@ -2,36 +2,6 @@ export const FREQUENCY_DELTA = 100000;
 
 export type Callback<T> = (owner: T, params?: any) => void;
 
-/**
- * Abstract class that implements the basic functionality
- * part of the definition of the Observer pattern.
- *
- * @see {@link https://en.wikipedia.org/wiki/Observer_pattern}
- */
-export class Observable {
-    private events: Record<string, [Callback<this>]> = {};
-
-    bind(event: string, callback: Callback<this>) {
-        const callbacks = this.events[event] ?? [];
-        if (callbacks.includes(callback)) return;
-        callbacks.push(callback);
-        this.events[event] = callbacks;
-    }
-
-    unbind(event: string, callback: Callback<this>) {
-        const callbacks = this.events[event] ?? [];
-        if (!callbacks.includes(callback)) return;
-        const index = callbacks.indexOf(callback);
-        callbacks.splice(index, 1);
-        this.events[event] = callbacks;
-    }
-
-    trigger(event: string, params?: any) {
-        const callbacks = this.events[event] ?? [];
-        callbacks.forEach((c) => c(this, params));
-    }
-}
-
 export type RomInfo = {
     name?: string;
     data?: Uint8Array;
@@ -46,6 +16,16 @@ export type BenchmarkResult = {
     frequency_mhz: number;
 };
 
+export type Entry = {
+    text: string;
+    url?: string;
+};
+
+/**
+ * Enumeration to be used to describe the set of
+ * features that a certain emulator supports, this
+ * is going to condition its runtime execution.
+ */
 export enum Feature {
     Debug = 1,
     Palettes,
@@ -82,34 +62,27 @@ export interface Emulator extends ObservableI {
     get name(): string;
 
     /**
-     * The name of the the hardware that is being emulated
-     * by the emulator (eg: Super Nintendo).
+     * The information on the hardware that is being emulated
+     * by the emulator (eg: Super Nintendo), can contain a URL
+     * that describes the device that is being emulated by
+     * the emulator (eg: Wikipedia link).
      */
-    get device(): string;
-
-    /**
-     * A URL to a website that describes the device that is
-     * being emulated by the emulator (eg: Wikipedia link).
-     */
-    get deviceUrl(): string | undefined;
+    get device(): Entry;
 
     /**
      * A semantic version string for the current version
-     * of the emulator.
+     * of the emulator, can include a URL pointing to a
+     * changelog or equivalent document.
      *
      * @see {@link https://semver.org}
      */
-    get version(): string;
+    get version(): Entry | undefined;
 
     /**
-     * The URL to the page describing the current version
-     * of the emulator.
+     * Information about the source code repository where
+     * the emulator source code is being stored.
      */
-    get versionUrl(): string | undefined;
-
-    get repository(): string | undefined;
-
-    get repositoryUrl(): string | undefined;
+    get repository(): Entry | undefined;
 
     /**
      * The features available and compatible with the emulator,
@@ -236,20 +209,42 @@ export interface Emulator extends ObservableI {
     benchmark?: { (count?: number): BenchmarkResult };
 }
 
-export class EmulatorBase extends Observable {
-    get deviceUrl(): string | undefined {
-        return undefined;
+/**
+ * Abstract class that implements the basic functionality
+ * part of the definition of the Observer pattern.
+ *
+ * @see {@link https://en.wikipedia.org/wiki/Observer_pattern}
+ */
+export class Observable {
+    private events: Record<string, [Callback<this>]> = {};
+
+    bind(event: string, callback: Callback<this>) {
+        const callbacks = this.events[event] ?? [];
+        if (callbacks.includes(callback)) return;
+        callbacks.push(callback);
+        this.events[event] = callbacks;
     }
 
-    get versionUrl(): string | undefined {
-        return undefined;
+    unbind(event: string, callback: Callback<this>) {
+        const callbacks = this.events[event] ?? [];
+        if (!callbacks.includes(callback)) return;
+        const index = callbacks.indexOf(callback);
+        callbacks.splice(index, 1);
+        this.events[event] = callbacks;
+    }
+
+    trigger(event: string, params?: any) {
+        const callbacks = this.events[event] ?? [];
+        callbacks.forEach((c) => c(this, params));
     }
+}
 
-    get repository(): string | undefined {
+export class EmulatorBase extends Observable {
+    get version(): Entry | undefined {
         return undefined;
     }
 
-    get repositoryUrl(): string | undefined {
+    get repository(): Entry | undefined {
         return undefined;
     }
 
-- 
GitLab