소스 검색

Server select overlay working.

Daniel Scalzi 5 년 전
부모
커밋
574b362d12

+ 43 - 10
package-lock.json

@@ -1361,6 +1361,38 @@
         }
       }
     },
+    "@eslint/eslintrc": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.1.0.tgz",
+      "integrity": "sha512-bfL5365QSCmH6cPeFT7Ywclj8C7LiF7sO6mUGzZhtAMV7iID1Euq6740u/SRi4C80NOnVz/CEfK8/HO+nCAPJg==",
+      "dev": true,
+      "requires": {
+        "ajv": "^6.12.4",
+        "debug": "^4.1.1",
+        "import-fresh": "^3.2.1",
+        "strip-json-comments": "^3.1.1"
+      },
+      "dependencies": {
+        "ajv": {
+          "version": "6.12.4",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz",
+          "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==",
+          "dev": true,
+          "requires": {
+            "fast-deep-equal": "^3.1.1",
+            "fast-json-stable-stringify": "^2.0.0",
+            "json-schema-traverse": "^0.4.1",
+            "uri-js": "^4.2.2"
+          }
+        },
+        "strip-json-comments": {
+          "version": "3.1.1",
+          "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+          "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+          "dev": true
+        }
+      }
+    },
     "@sindresorhus/is": {
       "version": "3.1.2",
       "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-3.1.2.tgz",
@@ -1527,9 +1559,9 @@
       }
     },
     "@types/lodash": {
-      "version": "4.14.160",
-      "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.160.tgz",
-      "integrity": "sha512-aP03BShJoO+WVndoVj/WNcB/YBPt+CIU1mvaao2GRAHy2yg4pT/XS4XnVHEQBjPJGycWf/9seKEO9vopTJGkvA==",
+      "version": "4.14.161",
+      "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.161.tgz",
+      "integrity": "sha512-EP6O3Jkr7bXvZZSZYlsgt5DIjiGr0dXP1/jVEwVLTFgg0d+3lWVQkRavYVQszV7dYUwvg0B8R0MBDpcmXg7XIA==",
       "dev": true
     },
     "@types/minimatch": {
@@ -1556,9 +1588,9 @@
       "dev": true
     },
     "@types/react": {
-      "version": "16.9.48",
-      "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.48.tgz",
-      "integrity": "sha512-4ykBVswgYitPGMXFRxJCHkxJDU2rjfU3/zw67f8+dB7sNdVJXsrwqoYxz/stkAucymnEEbRPFmX7Ce5Mc/kJCw==",
+      "version": "16.9.49",
+      "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.49.tgz",
+      "integrity": "sha512-DtLFjSj0OYAdVLBbyjhuV9CdGVHCkHn2R+xr3XkBvK2rS1Y1tkc14XSGjYgm5Fjjr90AxH9tiSzc1pCFMGO06g==",
       "dev": true,
       "requires": {
         "@types/prop-types": "*",
@@ -4690,12 +4722,13 @@
       "dev": true
     },
     "eslint": {
-      "version": "7.7.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.7.0.tgz",
-      "integrity": "sha512-1KUxLzos0ZVsyL81PnRN335nDtQ8/vZUD6uMtWbF+5zDtjKcsklIi78XoE0MVL93QvWTu+E5y44VyyCsOMBrIg==",
+      "version": "7.8.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.8.0.tgz",
+      "integrity": "sha512-qgtVyLZqKd2ZXWnLQA4NtVbOyH56zivOAdBFWE54RFkSZjokzNrcP4Z0eVWsZ+84ByXv+jL9k/wE1ENYe8xRFw==",
       "dev": true,
       "requires": {
         "@babel/code-frame": "^7.0.0",
+        "@eslint/eslintrc": "^0.1.0",
         "ajv": "^6.10.0",
         "chalk": "^4.0.0",
         "cross-spawn": "^7.0.2",
@@ -4705,7 +4738,7 @@
         "eslint-scope": "^5.1.0",
         "eslint-utils": "^2.1.0",
         "eslint-visitor-keys": "^1.3.0",
-        "espree": "^7.2.0",
+        "espree": "^7.3.0",
         "esquery": "^1.2.0",
         "esutils": "^2.0.2",
         "file-entry-cache": "^5.0.1",

+ 3 - 3
package.json

@@ -56,10 +56,10 @@
     "@types/electron-devtools-installer": "^2.2.0",
     "@types/fs-extra": "^9.0.1",
     "@types/jquery": "^3.5.1",
-    "@types/lodash": "^4.14.160",
+    "@types/lodash": "^4.14.161",
     "@types/mocha": "^8.0.3",
     "@types/node": "^12.12.54",
-    "@types/react": "^16.9.48",
+    "@types/react": "^16.9.49",
     "@types/react-dom": "^16.9.8",
     "@types/react-redux": "^7.1.9",
     "@types/react-transition-group": "^4.4.0",
@@ -77,7 +77,7 @@
     "electron-devtools-installer": "^3.1.1",
     "electron-webpack": "^2.8.2",
     "electron-webpack-ts": "^4.0.1",
-    "eslint": "^7.7.0",
+    "eslint": "^7.8.0",
     "eslint-plugin-react": "^7.20.6",
     "helios-distribution-types": "1.0.0-pre.1",
     "mocha": "^8.1.3",

+ 23 - 8
src/common/distribution/DistributionFactory.ts

@@ -1,28 +1,43 @@
 import { Distribution, Server, Module, Type, Required as HeliosRequired } from 'helios-distribution-types'
 import { MavenComponents, MavenUtil } from 'common/util/MavenUtil'
 import { join } from 'path'
+import { LoggerUtil } from 'common/logging/loggerutil'
+
+const logger = LoggerUtil.getLogger('DistributionFactory')
 
 export class HeliosDistribution {
 
-    private mainServerIndex: number
+    private mainServerIndex!: number
 
     public readonly servers: HeliosServer[]
 
     constructor(
         public readonly rawDistribution: Distribution
     ) {
-
+        this.resolveMainServerIndex()
         this.servers = this.rawDistribution.servers.map(s => new HeliosServer(s))
-        this.mainServerIndex = this.indexOfMainServer()
     }
 
-    private indexOfMainServer(): number {
-        for(let i=0; i<this.servers.length; i++) {
-            if(this.servers[i].rawServer.mainServer) {
-                return i
+    private resolveMainServerIndex(): void {
+
+        if(this.rawDistribution.servers.length > 0) {
+            for(let i=0; i<this.rawDistribution.servers.length; i++) {
+                if(this.mainServerIndex == null) {
+                    if(this.rawDistribution.servers[i].mainServer) {
+                        this.mainServerIndex = i
+                    }
+                } else {
+                    this.rawDistribution.servers[i].mainServer = false
+                }
             }
+            if(this.mainServerIndex == null) {
+                this.mainServerIndex = 0
+                this.rawDistribution.servers[this.mainServerIndex].mainServer = true
+            }
+        } else {
+            logger.warn('Distribution has 0 configured servers. This doesnt seem right..')
+            this.mainServerIndex = 0
         }
-        return 0
     }
 
     public getMainServer(): HeliosServer | null {

+ 30 - 20
src/renderer/components/Application.tsx

@@ -19,6 +19,7 @@ import { join } from 'path'
 import { AppActionDispatch } from '../redux/actions/appActions'
 import { OverlayPushAction, OverlayActionDispatch } from '../redux/actions/overlayActions'
 
+import { LoggerUtil } from 'common/logging/loggerutil'
 import { DistributionAPI } from 'common/distribution/DistributionAPI'
 import { getServerStatus } from 'common/mojang/net/ServerStatusAPI'
 import { Distribution } from 'helios-distribution-types'
@@ -37,6 +38,7 @@ function setBackground(id: number) {
 interface ApplicationProps {
     currentView: View
     overlayQueue: OverlayPushAction<unknown>[]
+    distribution: HeliosDistribution
 }
 
 interface ApplicationState {
@@ -49,7 +51,8 @@ interface ApplicationState {
 const mapState = (state: StoreType): Partial<ApplicationProps> => {
     return {
         currentView: state.currentView,
-        overlayQueue: state.overlayQueue
+        overlayQueue: state.overlayQueue,
+        distribution: state.app.distribution!
     }
 }
 const mapDispatch = {
@@ -60,6 +63,8 @@ const mapDispatch = {
 
 class Application extends React.Component<ApplicationProps & typeof mapDispatch, ApplicationState> {
 
+    private readonly logger = LoggerUtil.getLogger('Application')
+
     private bkid!: number
 
     constructor(props: ApplicationProps & typeof mapDispatch) {
@@ -185,26 +190,31 @@ class Application extends React.Component<ApplicationProps & typeof mapDispatch,
                             console.log(serverStatus)
                         }
                     })
-                    this.props.pushGenericOverlay({
-                        title: 'Test Title 2',
-                        description: 'Test Description',
-                        dismissible: true
-                    })
-                    this.props.pushGenericOverlay({
-                        title: 'Test Title 3',
-                        description: 'Test Description',
-                        dismissible: true
+                    this.props.pushServerSelectOverlay({
+                        servers: this.props.distribution.servers,
+                        selectedId: this.props.distribution.servers[0].rawServer.id,
+                        onSelection: (serverId: string) => this.logger.info('Server Selection Change:', serverId)
                     })
-                    this.props.pushGenericOverlay({
-                        title: 'Test Title 4',
-                        description: 'Test Description',
-                        dismissible: true
-                    })
-                    this.props.pushGenericOverlay({
-                        title: 'Test Title IMPORTANT',
-                        description: 'Test Description',
-                        dismissible: true
-                    }, true)
+                    // this.props.pushGenericOverlay({
+                    //     title: 'Test Title 2',
+                    //     description: 'Test Description',
+                    //     dismissible: true
+                    // })
+                    // this.props.pushGenericOverlay({
+                    //     title: 'Test Title 3',
+                    //     description: 'Test Description',
+                    //     dismissible: true
+                    // })
+                    // this.props.pushGenericOverlay({
+                    //     title: 'Test Title 4',
+                    //     description: 'Test Description',
+                    //     dismissible: true
+                    // })
+                    // this.props.pushGenericOverlay({
+                    //     title: 'Test Title IMPORTANT',
+                    //     description: 'Test Description',
+                    //     dismissible: true
+                    // }, true)
                 }, 5000)
             }
             const diff = Date.now() - start

+ 2 - 0
src/renderer/components/overlay/Overlay.tsx

@@ -42,6 +42,8 @@ class Overlay extends React.Component<OverlayProps> {
             <>
                 <ServerSelectOverlay
                     servers={action.payload.servers}
+                    selectedId={action.payload.selectedId}
+                    onSelection={action.payload.onSelection}
                 />
             </>
         )

+ 82 - 7
src/renderer/components/overlay/server-select/ServerSelectOverlay.tsx

@@ -1,13 +1,86 @@
 import * as React from 'react'
+import { connect } from 'react-redux'
+
+import { HeliosServer } from 'common/distribution/DistributionFactory'
+import { LoggerUtil } from 'common/logging/loggerutil'
+import { OverlayActionDispatch } from '../../../redux/actions/overlayActions'
 
 import '../shared-select/SharedSelect.css'
-import { Server } from 'helios-distribution-types'
 
 export interface ServerSelectOverlayProps {
-    servers: Server[]
+    servers: HeliosServer[]
+    selectedId: string
+    onSelection: (serverId: string) => void
+}
+
+interface ServerSelectOverlayState {
+    selectedId: string
 }
 
-export default class ServerSelectOverlay extends React.Component<ServerSelectOverlayProps> {
+const mapDispatch = {
+    ...OverlayActionDispatch
+}
+
+type InternalServerSelectOverlayProps = ServerSelectOverlayProps & typeof mapDispatch
+
+class ServerSelectOverlay extends React.Component<InternalServerSelectOverlayProps, ServerSelectOverlayState> {
+
+    private readonly logger = LoggerUtil.getLogger('ServerSelectOverlay')
+
+    constructor(props: InternalServerSelectOverlayProps) {
+        super(props)
+        this.state = {
+            selectedId: props.selectedId
+        }
+    }
+
+    private onSelectClick = async (): Promise<void> => {
+        try {
+            this.props.onSelection(this.state.selectedId)
+        } catch(err) {
+            this.logger.error('Uncaught error in server select confirmation.', err)
+        }
+        this.props.popOverlayContent()
+    }
+
+    private onCancelClick = async (): Promise<void> => {
+        this.props.popOverlayContent()
+    }
+
+    getMainServerStar(): JSX.Element {
+        return (
+            <div className="serverListingStarWrapper">
+                <svg id="mainServerSVG" viewBox="0 0 107.45 104.74" width="20px" height="20px">
+                    <path fill="#fff" d="M100.93,65.54C89,62,68.18,55.65,63.54,52.13c2.7-5.23,18.8-19.2,28-27.55C81.36,31.74,63.74,43.87,58.09,45.3c-2.41-5.37-3.61-26.52-4.37-39-.77,12.46-2,33.64-4.36,39-5.7-1.46-23.3-13.57-33.49-20.72,9.26,8.37,25.39,22.36,28,27.55C39.21,55.68,18.47,62,6.52,65.55c12.32-2,33.63-6.06,39.34-4.9-.16,5.87-8.41,26.16-13.11,37.69,6.1-10.89,16.52-30.16,21-33.9,4.5,3.79,14.93,23.09,21,34C70,86.84,61.73,66.48,61.59,60.65,67.36,59.49,88.64,63.52,100.93,65.54Z"/>
+                    <circle fill="none" stroke="#fff" strokeMiterlimit="10" cx="53.73" cy="53.9" r="38"/>
+                </svg>
+                <span className="serverListingStarTooltip">Main Server</span>
+            </div>
+        )
+    }
+
+    getServers(): JSX.Element[] {
+        const servers: JSX.Element[] = []
+
+        for(const { rawServer: raw } of this.props.servers) {
+            servers.push(
+                <button onClick={() => this.setState({...this.state, selectedId: raw.id})} className="serverListing" {...(raw.id === this.state.selectedId ? {selectedserver: 'true'} : {})} {...{key: raw.id}}>
+                    <img className="serverListingImg" src={raw.icon}/>
+                    <div className="serverListingDetails">
+                        <span className="serverListingName">{raw.name}</span>
+                        <span className="serverListingDescription">{raw.description}</span>
+                        <div className="serverListingInfo">
+                            <div className="serverListingVersion">{raw.minecraftVersion}</div>
+                            <div className="serverListingRevision">{raw.version}</div>
+                            {raw.mainServer ? this.getMainServerStar() : ''}
+                        </div>
+                    </div>
+                </button>
+            )
+        }
+
+        return servers
+    }
 
     render(): JSX.Element {
         return (
@@ -16,13 +89,13 @@ export default class ServerSelectOverlay extends React.Component<ServerSelectOve
                     <span id="serverSelectHeader">Available Servers</span>
                     <div id="serverSelectList">
                         <div id="serverSelectListScrollable">
-                            {/* Server listings populated here. */}
+                            {this.getServers()}
                         </div>
                     </div>
                     <div id="serverSelectActions">
-                        <button id="serverSelectConfirm" className="overlayKeybindEnter" type="submit">Select</button>
+                        <button onClick={this.onSelectClick} id="serverSelectConfirm" className="overlayKeybindEnter" type="submit">Select</button>
                         <div id="serverSelectCancelWrapper">
-                            <button id="serverSelectCancel" className="overlayKeybindEsc">Cancel</button>
+                            <button onClick={this.onCancelClick} id="serverSelectCancel" className="overlayKeybindEsc">Cancel</button>
                         </div>
                     </div>
                 </div>
@@ -30,4 +103,6 @@ export default class ServerSelectOverlay extends React.Component<ServerSelectOve
         )
     }
 
-}
+}
+
+export default connect<unknown, typeof mapDispatch>(undefined, mapDispatch)(ServerSelectOverlay)

+ 1 - 1
src/renderer/components/overlay/shared-select/SharedSelect.css

@@ -68,7 +68,7 @@
     position: relative;
     background: rgba(131, 131, 131, 0.25);
 }
-.serverListing[selected] {
+.serverListing[selectedserver] {
     cursor: default;
     opacity: 1.0;
 }

+ 1 - 0
src/renderer/index.tsx

@@ -28,6 +28,7 @@ ReactDOM.render(
             <Application
                 currentView={store.getState().currentView}
                 overlayQueue={store.getState().overlayQueue}
+                distribution={store.getState().app.distribution!}
             />
         </Provider>
     </AppContainer>,