From e583133c8bbcc3971ef37eb7bb1e191ce9f0fb4d Mon Sep 17 00:00:00 2001
From: Daniel Scalzi <d_scalzi@yahoo.com>
Date: Tue, 24 Jul 2018 01:14:26 -0400
Subject: [PATCH] Initial work on mod toggle UI.

This still needs a lot of work.
---
 app/assets/css/launcher.css       | 105 ++++++++++++++++++++++++++++--
 app/assets/js/scripts/settings.js |  93 ++++++++++++++++++++++++++
 app/settings.ejs                  |  14 ++++
 3 files changed, 207 insertions(+), 5 deletions(-)

diff --git a/app/assets/css/launcher.css b/app/assets/css/launcher.css
index 97aa0a31..251980dd 100644
--- a/app/assets/css/launcher.css
+++ b/app/assets/css/launcher.css
@@ -1113,8 +1113,8 @@ body, button {
 .toggleSwitch {
     position: relative;
     display: inline-block;
-    width: 50px;
-    height: 25px;
+    width: 40px;
+    height: 20px;
     border-radius: 50px;
     box-sizing: border-box;
 }
@@ -1136,8 +1136,8 @@ body, button {
 .toggleSwitchSlider:before {
     position: absolute;
     content: "";
-    height: 17px;
-    width: 21px;
+    height: 13px;
+    width: 16px;
     left: 3px;
     bottom: 3px;
     background-color: white;
@@ -1147,9 +1147,11 @@ body, button {
 }
 input:checked + .toggleSwitchSlider {
     background-color: rgb(31, 140, 11);
+    /* box-shadow: inset 2px 1px 20px black; */
+    border: 1px solid rgb(31, 140, 11);
 }
 input:checked + .toggleSwitchSlider:before {
-    transform: translateX(21px);
+    transform: translateX(15px);
 }
 
 /* Range Slider styles. */
@@ -1357,6 +1359,99 @@ input:checked + .toggleSwitchSlider:before {
     width: 75px;
 }
 
+/* * *
+* Settings View (Mods Tab)
+* * */
+
+#settingsReqModsContent,
+#settingsOptModsContent {
+    font-size: 12px;
+    background: rgba(0, 0, 0, 0.25);
+    border-radius: 3px;
+    color: white;
+}
+
+#settingsModsContainer {
+    width: 75%;
+}
+
+.settingsModsHeader {
+    padding-bottom: 10px;
+    border-bottom: 1px solid rgba(255, 255, 255, 0.5);
+    margin-bottom: 10px;
+}
+
+#settingsReqModsContainer,
+#settingsOptModsContainer {
+    padding-bottom: 25px;
+}
+
+.settingsMod {
+    padding: 10px;
+}
+
+.settingsSubMod {
+    padding: 10px 0px 10px 15px;
+    margin-left: 20px;
+    border-left: 1px solid rgba(255, 255, 255, 0.5);
+}
+
+.settingsModStatus {
+    width: 7px;
+    height: 7px;
+    border-radius: 50%;
+    background-color: #c32625;
+    margin-right: 15px;
+}
+
+.settingsModContent {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+}
+
+.settingsModMainWrapper {
+    display: flex;
+    align-items: center;
+}
+
+.settingsModVersion {
+    color: grey;
+    font-size: 10px;
+}
+
+.settingsModDetails {
+    display: flex;
+    flex-direction: column;
+}
+
+.toggleSwitch[reqmod] {
+    filter: grayscale(49%) brightness(60%);
+    pointer-events: none;
+}
+
+.settingsMod[enabled] .settingsModStatus,
+.settingsSubMod[enabled] .settingsModStatus{
+    background-color: rgb(165, 195, 37);
+}
+
+.settingsSubModContainer > .settingsSubMod:first-child {
+    border-top-left-radius: 10px;
+}
+
+.settingsSubModContainer > .settingsSubMod:last-child {
+    border-bottom-left-radius: 10px;
+}
+
+settingsSubModContainer > .settingsSubMod:only-child {
+    border-top-left-radius: 10px;
+    border-bottom-left-radius: 10px;
+}
+
+.settingsSubModContainer {
+    margin-top: 10px;
+}
+
 /* * *
 * Settings View (Java Tab)
 * * */
diff --git a/app/assets/js/scripts/settings.js b/app/assets/js/scripts/settings.js
index ded2eacd..e5c96a8e 100644
--- a/app/assets/js/scripts/settings.js
+++ b/app/assets/js/scripts/settings.js
@@ -422,6 +422,97 @@ document.getElementById('settingsGameHeight').addEventListener('keydown', (e) =>
     }
 })
 
+/**
+ * Mods Tab
+ */
+
+function resolveModsForUI(){
+    const serv = ConfigManager.getSelectedServer()
+
+    const distro = DistroManager.getDistribution()
+    const servConf = ConfigManager.getModConfiguration(serv)
+
+    const modStr = parseModulesForUI(distro.getServer(serv).getModules(), false, servConf.mods)
+
+    document.getElementById('settingsReqModsContent').innerHTML = modStr.reqMods
+    document.getElementById('settingsOptModsContent').innerHTML = modStr.optMods
+
+}
+
+function parseModulesForUI(mdls, submodules = false, servConf){
+
+    let reqMods = ''
+    let optMods = ''
+
+    for(const mdl of mdls){
+
+        if(mdl.getType() === DistroManager.Types.ForgeMod || mdl.getType() === DistroManager.Types.LiteMod || mdl.getType() === DistroManager.Types.LiteLoader){
+
+            if(mdl.getRequired().isRequired()){
+
+                reqMods += `<div id="${mdl.getVersionlessID()}" class="settings${submodules ? 'Sub' : ''}Mod" enabled>
+                    <div class="settingsModContent">
+                        <div class="settingsModMainWrapper">
+                            <div class="settingsModStatus"></div>
+                            <div class="settingsModDetails">
+                                <span class="settingsModName">${mdl.getName().substring(0, mdl.getName().indexOf('('))}</span>
+                                <span class="settingsModVersion">v${mdl.getVersion()}</span>
+                            </div>
+                        </div>
+                        <label class="toggleSwitch" reqmod>
+                            <input type="checkbox" checked>
+                            <span class="toggleSwitchSlider"></span>
+                        </label>
+                    </div>
+                    ${mdl.hasSubModules() ? `<div class="settingsSubModContainer">
+                        ${Object.values(parseModulesForUI(mdl.getSubModules(), true)).join('')}
+                    </div>` : ''}
+                </div>`
+
+            } else {
+
+                const conf = servConf[mdl.getVersionlessID()]
+                const val = typeof conf === 'object' ? conf.value : conf
+
+                optMods += `<div id="${mdl.getVersionlessID()}" class="settings${submodules ? 'Sub' : ''}Mod" ${val ? 'enabled' : ''}>
+                    <div class="settingsModContent">
+                        <div class="settingsModMainWrapper">
+                            <div class="settingsModStatus"></div>
+                            <div class="settingsModDetails">
+                                <span class="settingsModName">${mdl.getName().substring(0, mdl.getName().indexOf('('))}</span>
+                                <span class="settingsModVersion">v${mdl.getVersion()}</span>
+                            </div>
+                        </div>
+                        <label class="toggleSwitch">
+                            <input type="checkbox" ${val ? 'checked' : ''}>
+                            <span class="toggleSwitchSlider"></span>
+                        </label>
+                    </div>
+                    ${mdl.hasSubModules() ? `<div class="settingsSubModContainer">
+                        ${mdl.hasSubModules() ? Object.values(parseModulesForUI(mdl.getSubModules(), true, conf.mods)).join('') : ''}
+                    </div>` : ''}
+                </div>`
+
+            }
+
+        }
+
+    }
+
+    return {
+        reqMods,
+        optMods
+    }
+
+}
+
+/**
+ * Prepare the Java tab for display.
+ */
+function prepareModsTab(){
+    resolveModsForUI()
+}
+
 /**
  * Java Tab
  */
@@ -739,6 +830,8 @@ function prepareSettings(first = false) {
     if(first){
         setupSettingsTabs()
         initSettingsValidators()
+    } else {
+        prepareModsTab()
     }
     initSettingsValues()
     prepareAccountsTab()
diff --git a/app/settings.ejs b/app/settings.ejs
index eca33a53..b7abb17e 100644
--- a/app/settings.ejs
+++ b/app/settings.ejs
@@ -96,6 +96,20 @@
                 <span class="settingsTabHeaderText">Mod Settings</span>
                 <span class="settingsTabHeaderDesc">Enable or disable mods.</span>
             </div>
+            <div id="settingsModsContainer">
+                <div id="settingsReqModsContainer">
+                    <div class="settingsModsHeader">Required Mods</div>
+                    <div id="settingsReqModsContent">
+
+                    </div>
+                </div>
+                <div id="settingsOptModsContainer">
+                    <div class="settingsModsHeader">Optional Mods</div>
+                    <div id="settingsOptModsContent">
+                        
+                    </div>
+                </div>
+            </div>
         </div>
         <div id="settingsTabJava" class="settingsTab" style="display: none;">
             <div class="settingsTabHeader">