Przeglądaj źródła

Move status refresh intervals to App component (resolves #107).

Daniel Scalzi 5 lat temu
rodzic
commit
0cbd39b79c

Plik diff jest za duży
+ 425 - 171
package-lock.json


+ 9 - 9
package.json

@@ -31,14 +31,14 @@
   "dependencies": {
     "adm-zip": "^0.4.16",
     "async": "^3.2.0",
-    "discord-rpc": "^3.1.3",
+    "discord-rpc": "^3.1.4",
     "electron-updater": "^4.3.4",
     "fs-extra": "^9.0.1",
     "github-syntax-dark": "^0.5.0",
-    "got": "^11.6.0",
+    "got": "^11.6.2",
     "jquery": "^3.5.1",
     "lodash": "^4.17.20",
-    "moment": "^2.27.0",
+    "moment": "^2.28.0",
     "request": "^2.88.2",
     "semver": "^7.3.2",
     "tar-fs": "^2.1.0",
@@ -58,7 +58,7 @@
     "@types/jquery": "^3.5.1",
     "@types/lodash": "^4.14.161",
     "@types/mocha": "^8.0.3",
-    "@types/node": "^12.12.55",
+    "@types/node": "^12.12.58",
     "@types/react": "^16.9.49",
     "@types/react-dom": "^16.9.8",
     "@types/react-redux": "^7.1.9",
@@ -67,19 +67,19 @@
     "@types/tar-fs": "^2.0.0",
     "@types/triple-beam": "^1.3.2",
     "@types/winreg": "^1.2.30",
-    "@typescript-eslint/eslint-plugin": "^3.10.1",
-    "@typescript-eslint/parser": "^3.10.1",
+    "@typescript-eslint/eslint-plugin": "^4.1.0",
+    "@typescript-eslint/parser": "^4.1.0",
     "chai": "^4.2.0",
     "chai-as-promised": "^7.1.1",
     "cross-env": "^7.0.2",
-    "electron": "^9.2.1",
+    "electron": "^9.3.0",
     "electron-builder": "^22.8.0",
     "electron-devtools-installer": "^3.1.1",
     "electron-webpack": "^2.8.2",
     "electron-webpack-ts": "^4.0.1",
-    "eslint": "^7.8.1",
+    "eslint": "^7.9.0",
     "eslint-plugin-react": "^7.20.6",
-    "helios-distribution-types": "1.0.0-pre.1",
+    "helios-distribution-types": "1.0.0-rc.1",
     "mocha": "^8.1.3",
     "nock": "^13.0.4",
     "react": "^16.13.0",

+ 2 - 0
src/common/mojang/net/ServerStatusAPI.ts

@@ -29,6 +29,7 @@ export interface ServerStatus {
             version: string
         }[]
     }
+    retrievedAt: number     // Internal tracking
 }
 
 /**
@@ -77,6 +78,7 @@ function unifyStatusResponse(resp: ServerStatus): ServerStatus {
             text: resp.description
         }
     }
+    resp.retrievedAt = (new Date()).getTime()
     return resp
 }
 

+ 42 - 38
src/common/mojang/rest/MojangRestAPI.ts

@@ -30,44 +30,48 @@ export class MojangRestAPI {
         version: 1
     }
 
-    protected static statuses: MojangStatus[] = [
-        {
-            service: 'sessionserver.mojang.com',
-            status: MojangStatusColor.GREY,
-            name: 'Multiplayer Session Service',
-            essential: true
-        },
-        {
-            service: 'authserver.mojang.com',
-            status: MojangStatusColor.GREY,
-            name: 'Authentication Service',
-            essential: true
-        },
-        {
-            service: 'textures.minecraft.net',
-            status: MojangStatusColor.GREY,
-            name: 'Minecraft Skins',
-            essential: false
-        },
-        {
-            service: 'api.mojang.com',
-            status: MojangStatusColor.GREY,
-            name: 'Public API',
-            essential: false
-        },
-        {
-            service: 'minecraft.net',
-            status: MojangStatusColor.GREY,
-            name: 'Minecraft.net',
-            essential: false
-        },
-        {
-            service: 'account.mojang.com',
-            status: MojangStatusColor.GREY,
-            name: 'Mojang Accounts Website',
-            essential: false
-        }
-    ]
+    protected static statuses: MojangStatus[] = MojangRestAPI.getDefaultStatuses()
+
+    public static getDefaultStatuses(): MojangStatus[] {
+        return [
+            {
+                service: 'sessionserver.mojang.com',
+                status: MojangStatusColor.GREY,
+                name: 'Multiplayer Session Service',
+                essential: true
+            },
+            {
+                service: 'authserver.mojang.com',
+                status: MojangStatusColor.GREY,
+                name: 'Authentication Service',
+                essential: true
+            },
+            {
+                service: 'textures.minecraft.net',
+                status: MojangStatusColor.GREY,
+                name: 'Minecraft Skins',
+                essential: false
+            },
+            {
+                service: 'api.mojang.com',
+                status: MojangStatusColor.GREY,
+                name: 'Public API',
+                essential: false
+            },
+            {
+                service: 'minecraft.net',
+                status: MojangStatusColor.GREY,
+                name: 'Minecraft.net',
+                essential: false
+            },
+            {
+                service: 'account.mojang.com',
+                status: MojangStatusColor.GREY,
+                name: 'Mojang Accounts Website',
+                essential: false
+            }
+        ]
+    }
 
     /**
      * Converts a Mojang status color to a hex value. Valid statuses

+ 99 - 6
src/renderer/components/Application.tsx

@@ -24,6 +24,10 @@ import { DistributionAPI } from 'common/distribution/DistributionAPI'
 import { getServerStatus, ServerStatus } from 'common/mojang/net/ServerStatusAPI'
 import { Distribution } from 'helios-distribution-types'
 import { HeliosDistribution, HeliosServer } from 'common/distribution/DistributionFactory'
+import { MojangResponse } from 'common/mojang/rest/internal/MojangResponse'
+import { MojangStatus, MojangStatusColor } from 'common/mojang/rest/internal/MojangStatus'
+import { MojangRestAPI } from 'common/mojang/rest/MojangRestAPI'
+import { RestResponseStatus } from 'common/got/RestResponse'
 
 import './Application.css'
 
@@ -39,8 +43,9 @@ interface ApplicationProps {
     currentView: View
     overlayQueue: OverlayPushAction<unknown>[]
     distribution: HeliosDistribution
-    selectedServer: HeliosServer
-    selectedServerStatus: ServerStatus
+    selectedServer?: HeliosServer
+    selectedServerStatus?: ServerStatus
+    mojangStatuses: MojangStatus[]
 }
 
 interface ApplicationState {
@@ -54,8 +59,9 @@ const mapState = (state: StoreType): Partial<ApplicationProps> => {
     return {
         currentView: state.currentView,
         overlayQueue: state.overlayQueue,
-        distribution: state.app.distribution!,
-        selectedServer: state.app.selectedServer!
+        distribution: state.app.distribution,
+        selectedServer: state.app.selectedServer,
+        mojangStatuses: state.app.mojangStatuses
     }
 }
 const mapDispatch = {
@@ -64,13 +70,18 @@ const mapDispatch = {
     ...OverlayActionDispatch
 }
 
-class Application extends React.Component<ApplicationProps & typeof mapDispatch, ApplicationState> {
+type InternalApplicationProps = ApplicationProps & typeof mapDispatch
+
+class Application extends React.Component<InternalApplicationProps, ApplicationState> {
 
     private static readonly logger = LoggerUtil.getLogger('ApplicationTSX')
 
+    private mojangStatusInterval!: NodeJS.Timeout
+    private serverStatusInterval!: NodeJS.Timeout
+
     private bkid!: number
 
-    constructor(props: ApplicationProps & typeof mapDispatch) {
+    constructor(props: InternalApplicationProps) {
         super(props)
         this.state = {
             loading: true,
@@ -80,6 +91,83 @@ class Application extends React.Component<ApplicationProps & typeof mapDispatch,
         }
     }
 
+    async componentDidMount(): Promise<void> {
+
+        this.mojangStatusInterval = setInterval(async () => {
+            Application.logger.info('Refreshing Mojang Statuses..')
+            await this.loadMojangStatuses()
+        }, 300000)
+
+        this.serverStatusInterval = setInterval(async () => {
+            Application.logger.info('Refreshing selected server status..')
+            await this.syncServerStatus()
+        }, 300000)
+
+    }
+
+    componentWillUnmount(): void {
+
+        // Clean up intervals.
+        clearInterval(this.mojangStatusInterval)
+        clearInterval(this.serverStatusInterval)
+
+    }
+
+    async componentDidUpdate(prevProps: InternalApplicationProps): Promise<void> {
+
+        if(this.props.selectedServer?.rawServer.id !== prevProps.selectedServer?.rawServer.id) {
+            await this.syncServerStatus()
+        }
+
+    }
+
+    /**
+     * Load the mojang statuses and add them to the global store.
+     */
+    private loadMojangStatuses = async (): Promise<void> => {
+        const response: MojangResponse<MojangStatus[]> = await MojangRestAPI.status()
+
+        if(response.responseStatus !== RestResponseStatus.SUCCESS) {
+            Application.logger.warn('Failed to retrieve Mojang Statuses.')
+        }
+
+        // TODO Temp workaround because their status checker always shows
+        // this as red. https://bugs.mojang.com/browse/WEB-2303
+        const statuses = response.data
+        for(const status of statuses) {
+            if(status.service === 'sessionserver.mojang.com' || status.service === 'minecraft.net') {
+                status.status = MojangStatusColor.GREEN
+            }
+        }
+
+        this.props.setMojangStatuses(response.data)
+    }
+
+    /**
+     * Fetch the status of the selected server and store it in the global store.
+     */
+    private syncServerStatus = async (): Promise<void> => {
+        let serverStatus: ServerStatus | undefined
+
+        if(this.props.selectedServer != null) {
+            const { hostname, port } = this.props.selectedServer
+            try {
+                serverStatus = await getServerStatus(
+                    47,
+                    hostname,
+                    port
+                )
+            } catch(err) {
+                Application.logger.error('Error while refreshing server status', err)
+            }
+            
+        } else {
+            serverStatus = undefined
+        }
+
+        this.props.setSelectedServerStatus(serverStatus)
+    }
+
     private getViewElement = (): JSX.Element => {
         // TODO debug remove
         console.log('loading', this.props.currentView, this.state.workingView)
@@ -94,6 +182,7 @@ class Application extends React.Component<ApplicationProps & typeof mapDispatch,
                         distribution={this.props.distribution}
                         selectedServer={this.props.selectedServer}
                         selectedServerStatus={this.props.selectedServerStatus}
+                        mojangStatuses={this.props.mojangStatuses}
                     />
                 </>
             case View.LOGIN:
@@ -184,6 +273,10 @@ class Application extends React.Component<ApplicationProps & typeof mapDispatch,
                 this.props.setSelectedServerStatus(selectedServerStatus)
             }
 
+            // Load initial mojang statuses.
+            Application.logger.info('Loading mojang statuses..')
+            await this.loadMojangStatuses()
+
             // TODO Setup hook for distro refresh every ~ 5 mins.
 
             // Pick a background id.

+ 33 - 109
src/renderer/components/landing/Landing.tsx

@@ -6,11 +6,9 @@ import { StoreType } from '../../redux/store'
 import { AppActionDispatch } from '../..//redux/actions/appActions'
 import { OverlayActionDispatch } from '../../redux/actions/overlayActions'
 import { HeliosDistribution, HeliosServer } from 'common/distribution/DistributionFactory'
-import { ServerStatus, getServerStatus } from 'common/mojang/net/ServerStatusAPI'
+import { ServerStatus } from 'common/mojang/net/ServerStatusAPI'
 import { MojangStatus, MojangStatusColor } from 'common/mojang/rest/internal/MojangStatus'
-import { MojangResponse } from 'common/mojang/rest/internal/MojangResponse'
 import { MojangRestAPI } from 'common/mojang/rest/MojangRestAPI'
-import { RestResponseStatus } from 'common/got/RestResponse'
 import { LoggerUtil } from 'common/logging/loggerutil'
 
 import News from '../news/News'
@@ -19,20 +17,21 @@ import './Landing.css'
 
 interface LandingProps {
     distribution: HeliosDistribution
-    selectedServer: HeliosServer
-    selectedServerStatus: ServerStatus
+    selectedServer?: HeliosServer
+    selectedServerStatus?: ServerStatus
+    mojangStatuses: MojangStatus[]
 }
 
 interface LandingState {
-    mojangStatuses: MojangStatus[]
-    outdatedServerStatus: boolean
+    workingServerStatus?: ServerStatus
 }
 
 const mapState = (state: StoreType): Partial<LandingProps> => {
     return {
         distribution: state.app.distribution!,
-        selectedServer: state.app.selectedServer!,
-        selectedServerStatus: state.app.selectedServerStatus!
+        selectedServer: state.app.selectedServer,
+        selectedServerStatus: state.app.selectedServerStatus,
+        mojangStatuses: state.app.mojangStatuses
     }
 }
 const mapDispatch = {
@@ -44,102 +43,21 @@ type InternalLandingProps = LandingProps & typeof mapDispatch
 
 class Landing extends React.Component<InternalLandingProps, LandingState> {
 
-    private static readonly logger = LoggerUtil.getLogger('LandingTSX')
-
-    private mojangStatusInterval!: NodeJS.Timeout
-    private serverStatusInterval!: NodeJS.Timeout
+    private static readonly logger = LoggerUtil.getLogger('Landing')
 
     constructor(props: InternalLandingProps) {
         super(props)
         this.state = {
-            mojangStatuses: [],
-            outdatedServerStatus: false
+            workingServerStatus: props.selectedServerStatus
         }
     }
 
-    async componentDidMount(): Promise<void> {
-
-        // Load Mojang statuses and setup refresh interval.
-        Landing.logger.info('Loading mojang statuses..')
-        await this.loadMojangStatuses()
-        this.mojangStatusInterval = setInterval(async () => {
-            Landing.logger.info('Refreshing Mojang Statuses..')
-            await this.loadMojangStatuses()
-        }, 300000)
-
-        this.serverStatusInterval = setInterval(async () => {
-            Landing.logger.info('Refreshing selected server status..')
-            this.setState({
-                ...this.state,
-                outdatedServerStatus: true
-            })
-        }, 300000)
-
-    }
-
-    componentWillUnmount(): void {
-
-        // Clean up intervals.
-        clearInterval(this.mojangStatusInterval)
-        clearInterval(this.serverStatusInterval)
-
-    }
-
-    private loadMojangStatuses = async (): Promise<void> => {
-        const response: MojangResponse<MojangStatus[]> = await MojangRestAPI.status()
-
-        if(response.responseStatus !== RestResponseStatus.SUCCESS) {
-            Landing.logger.warn('Failed to retrieve Mojang Statuses.')
-        }
-
-        // TODO Temp workaround because their status checker always shows
-        // this as red. https://bugs.mojang.com/browse/WEB-2303
-        const statuses = response.data
-        for(const status of statuses) {
-            if(status.service === 'sessionserver.mojang.com' || status.service === 'minecraft.net') {
-                status.status = MojangStatusColor.GREEN
-            }
-        }
-
-        this.setState({
-            ...this.state,
-            mojangStatuses: response.data
-        })
-
-    }
-
-    private syncServerStatus = async (): Promise<void> => {
-        let serverStatus: ServerStatus | undefined
-
-        if(this.props.selectedServer != null) {
-            const { hostname, port } = this.props.selectedServer
-            try {
-                serverStatus = await getServerStatus(
-                    47,
-                    hostname,
-                    port
-                )
-            } catch(err) {
-                Landing.logger.error('Error while refreshing server status', err)
-            }
-            
-        } else {
-            serverStatus = undefined
-        }
-
-        this.props.setSelectedServerStatus(serverStatus)
-    }
-    private finishServerSync = async (): Promise<void> => {
-        this.setState({
-            ...this.state,
-            outdatedServerStatus: false
-        })
-    }
+    /* Mojang Status Methods */
 
     private getMainMojangStatusColor = (): string => {
-        const essential = this.state.mojangStatuses.filter(s => s.essential)
+        const essential = this.props.mojangStatuses.filter(s => s.essential)
 
-        if(this.state.mojangStatuses.length === 0) {
+        if(this.props.mojangStatuses.length === 0) {
             return MojangRestAPI.statusToHex(MojangStatusColor.GREY)
         }
 
@@ -152,11 +70,11 @@ class Landing extends React.Component<InternalLandingProps, LandingState> {
             return MojangRestAPI.statusToHex(MojangStatusColor.YELLOW)
         }
         // If any non-essential are not green, return yellow.
-        if(this.state.mojangStatuses.filter(s => s.status !== MojangStatusColor.GREEN && s.status !== MojangStatusColor.GREY).length > 0) {
+        if(this.props.mojangStatuses.filter(s => s.status !== MojangStatusColor.GREEN && s.status !== MojangStatusColor.GREY).length > 0) {
             return MojangRestAPI.statusToHex(MojangStatusColor.YELLOW)
         }
         // if all are grey, return grey.
-        if(this.state.mojangStatuses.filter(s => s.status === MojangStatusColor.GREY).length === this.state.mojangStatuses.length) {
+        if(this.props.mojangStatuses.filter(s => s.status === MojangStatusColor.GREY).length === this.props.mojangStatuses.length) {
             return MojangRestAPI.statusToHex(MojangStatusColor.GREY)
         }
 
@@ -166,7 +84,7 @@ class Landing extends React.Component<InternalLandingProps, LandingState> {
     private getMojangStatusesAsJSX = (essential: boolean): JSX.Element[] => {
         
         const statuses: JSX.Element[] = []
-        for(const status of this.state.mojangStatuses.filter(s => s.essential === essential)) {
+        for(const status of this.props.mojangStatuses.filter(s => s.essential === essential)) {
             statuses.push(
                 <div className="mojangStatusContainer" key={status.service}>
                     <span className="mojangStatusIcon" style={{color: MojangRestAPI.statusToHex(status.status)}}>&#8226;</span>
@@ -177,18 +95,23 @@ class Landing extends React.Component<InternalLandingProps, LandingState> {
         return statuses
     }
 
+    /* Selected Server Methods */
+
+    private updateWorkingServerStatus = (): void => {
+        this.setState({
+            ...this.state,
+            workingServerStatus: this.props.selectedServerStatus
+        })
+    }
+
     private openServerSelect = (): void => {
         this.props.pushServerSelectOverlay({
             servers: this.props.distribution.servers,
-            selectedId: this.props.selectedServer.rawServer.id,
+            selectedId: this.props.selectedServer?.rawServer.id,
             onSelection: async (serverId: string) => {
                 Landing.logger.info('Server Selection Change:', serverId)
                 const next: HeliosServer = this.props.distribution.getServerById(serverId)!
                 this.props.setSelectedServer(next)
-                this.setState({
-                    ...this.state,
-                    outdatedServerStatus: true
-                })
             }
         })
     }
@@ -202,18 +125,20 @@ class Landing extends React.Component<InternalLandingProps, LandingState> {
     }
 
     private getSelectedServerStatusText = (): string => {
-        return this.props.selectedServerStatus != null ? 'PLAYERS' : 'SERVER'
+        return this.state.workingServerStatus != null ? 'PLAYERS' : 'SERVER'
     }
 
     private getSelectedServerCount = (): string => {
-        if(this.props.selectedServerStatus != null) {
-            const { online, max } = this.props.selectedServerStatus.players
+        if(this.state.workingServerStatus != null) {
+            const { online, max } = this.state.workingServerStatus.players
             return `${online}/${max}`
         } else {
             return 'OFFLINE'
         }
     }
 
+    /* Render */
+
     render(): JSX.Element {
         return <>
             
@@ -316,12 +241,11 @@ class Landing extends React.Component<InternalLandingProps, LandingState> {
                             <div id="content">
                                 
                                 <CSSTransition
-                                    in={!this.state.outdatedServerStatus}
+                                    in={this.props.selectedServerStatus?.retrievedAt === this.state.workingServerStatus?.retrievedAt}
                                     timeout={500}
                                     classNames="serverStatusWrapper"
                                     unmountOnExit
-                                    onEnter={this.syncServerStatus}
-                                    onExited={this.finishServerSync}
+                                    onExited={this.updateWorkingServerStatus}
                                 >
                                     <div id="server_status_wrapper">
                                         <span className="bot_label" id="landingPlayerLabel">{this.getSelectedServerStatusText()}</span>

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

@@ -9,7 +9,7 @@ import '../shared-select/SharedSelect.css'
 
 export interface ServerSelectOverlayProps {
     servers: HeliosServer[]
-    selectedId: string
+    selectedId?: string
     onSelection: (serverId: string) => Promise<void>
 }
 
@@ -30,7 +30,7 @@ class ServerSelectOverlay extends React.Component<InternalServerSelectOverlayPro
     constructor(props: InternalServerSelectOverlayProps) {
         super(props)
         this.state = {
-            selectedId: props.selectedId
+            selectedId: props.selectedId!
         }
     }
 

+ 1 - 0
src/renderer/index.tsx

@@ -31,6 +31,7 @@ ReactDOM.render(
                 distribution={store.getState().app.distribution!}
                 selectedServer={store.getState().app.selectedServer!}
                 selectedServerStatus={store.getState().app.selectedServerStatus!}
+                mojangStatuses={store.getState().app.mojangStatuses!}
             />
         </Provider>
     </AppContainer>,

+ 16 - 2
src/renderer/redux/actions/appActions.ts

@@ -1,11 +1,13 @@
 import { Action } from 'redux'
 import { HeliosDistribution, HeliosServer } from 'common/distribution/DistributionFactory'
 import { ServerStatus } from 'common/mojang/net/ServerStatusAPI'
+import { MojangStatus } from 'common/mojang/rest/internal/MojangStatus'
 
 export enum AppActionType {
     SetDistribution = 'SET_DISTRIBUTION',
     SetSelectedServer = 'SET_SELECTED_SERVER',
-    SetSelectedServerStatus = 'SET_SELECTED_SERVER_STATUS'
+    SetSelectedServerStatus = 'SET_SELECTED_SERVER_STATUS',
+    SetMojangStatuses = 'SET_MOJANG_STATUSES'
 }
 
 // eslint-disable-next-line @typescript-eslint/no-empty-interface
@@ -23,6 +25,10 @@ export interface SetSelectedServerStatusAction extends AppAction {
     payload?: ServerStatus
 }
 
+export interface SetMojangStatusesAction extends AppAction {
+    payload: MojangStatus[]
+}
+
 export function setDistribution(distribution?: HeliosDistribution): SetDistributionAction {
     return {
         type: AppActionType.SetDistribution,
@@ -44,8 +50,16 @@ export function setSelectedServerStatus(serverStatus?: ServerStatus): SetSelecte
     }
 }
 
+export function setMojangStatuses(mojangStatuses: MojangStatus[]): SetMojangStatusesAction {
+    return {
+        type: AppActionType.SetMojangStatuses,
+        payload: mojangStatuses
+    }
+}
+
 export const AppActionDispatch = {
     setDistribution: (d?: HeliosDistribution): SetDistributionAction => setDistribution(d),
     setSelectedServer: (s?: HeliosServer): SetSelectedServerAction => setSelectedServer(s),
-    setSelectedServerStatus: (ss?: ServerStatus): SetSelectedServerStatusAction => setSelectedServerStatus(ss)
+    setSelectedServerStatus: (ss?: ServerStatus): SetSelectedServerStatusAction => setSelectedServerStatus(ss),
+    setMojangStatuses: (ms: MojangStatus[]): SetMojangStatusesAction => setMojangStatuses(ms)
 }

+ 11 - 2
src/renderer/redux/reducers/appReducer.ts

@@ -1,18 +1,22 @@
-import { AppActionType, AppAction, SetDistributionAction, SetSelectedServerAction, SetSelectedServerStatusAction } from '../actions/appActions'
+import { AppActionType, AppAction, SetDistributionAction, SetSelectedServerAction, SetSelectedServerStatusAction, SetMojangStatusesAction } from '../actions/appActions'
 import { Reducer } from 'redux'
 import { HeliosDistribution, HeliosServer } from 'common/distribution/DistributionFactory'
 import { ServerStatus } from 'common/mojang/net/ServerStatusAPI'
+import { MojangStatus } from 'common/mojang/rest/internal/MojangStatus'
+import { MojangRestAPI } from 'common/mojang/rest/MojangRestAPI'
 
 export interface AppState {
     distribution?: HeliosDistribution
     selectedServer?: HeliosServer
     selectedServerStatus?: ServerStatus
+    mojangStatuses: MojangStatus[]
 }
 
 const defaultAppState: AppState = {
     distribution: undefined,
     selectedServer: undefined,
-    selectedServerStatus: undefined
+    selectedServerStatus: undefined,
+    mojangStatuses: MojangRestAPI.getDefaultStatuses()
 }
 
 const AppReducer: Reducer<AppState, AppAction> = (state = defaultAppState, action) => {
@@ -32,6 +36,11 @@ const AppReducer: Reducer<AppState, AppAction> = (state = defaultAppState, actio
                 ...state,
                 selectedServerStatus: (action as SetSelectedServerStatusAction).payload
             }
+        case AppActionType.SetMojangStatuses:
+            return {
+                ...state,
+                mojangStatuses: (action as SetMojangStatusesAction).payload
+            }
     }
     return state
 }

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików