Move status refresh intervals to App component (resolves #107).
This commit is contained in:
parent
67e42ead78
commit
0cbd39b79c
2344
package-lock.json
generated
2344
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
18
package.json
18
package.json
@ -31,14 +31,14 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"adm-zip": "^0.4.16",
|
"adm-zip": "^0.4.16",
|
||||||
"async": "^3.2.0",
|
"async": "^3.2.0",
|
||||||
"discord-rpc": "^3.1.3",
|
"discord-rpc": "^3.1.4",
|
||||||
"electron-updater": "^4.3.4",
|
"electron-updater": "^4.3.4",
|
||||||
"fs-extra": "^9.0.1",
|
"fs-extra": "^9.0.1",
|
||||||
"github-syntax-dark": "^0.5.0",
|
"github-syntax-dark": "^0.5.0",
|
||||||
"got": "^11.6.0",
|
"got": "^11.6.2",
|
||||||
"jquery": "^3.5.1",
|
"jquery": "^3.5.1",
|
||||||
"lodash": "^4.17.20",
|
"lodash": "^4.17.20",
|
||||||
"moment": "^2.27.0",
|
"moment": "^2.28.0",
|
||||||
"request": "^2.88.2",
|
"request": "^2.88.2",
|
||||||
"semver": "^7.3.2",
|
"semver": "^7.3.2",
|
||||||
"tar-fs": "^2.1.0",
|
"tar-fs": "^2.1.0",
|
||||||
@ -58,7 +58,7 @@
|
|||||||
"@types/jquery": "^3.5.1",
|
"@types/jquery": "^3.5.1",
|
||||||
"@types/lodash": "^4.14.161",
|
"@types/lodash": "^4.14.161",
|
||||||
"@types/mocha": "^8.0.3",
|
"@types/mocha": "^8.0.3",
|
||||||
"@types/node": "^12.12.55",
|
"@types/node": "^12.12.58",
|
||||||
"@types/react": "^16.9.49",
|
"@types/react": "^16.9.49",
|
||||||
"@types/react-dom": "^16.9.8",
|
"@types/react-dom": "^16.9.8",
|
||||||
"@types/react-redux": "^7.1.9",
|
"@types/react-redux": "^7.1.9",
|
||||||
@ -67,19 +67,19 @@
|
|||||||
"@types/tar-fs": "^2.0.0",
|
"@types/tar-fs": "^2.0.0",
|
||||||
"@types/triple-beam": "^1.3.2",
|
"@types/triple-beam": "^1.3.2",
|
||||||
"@types/winreg": "^1.2.30",
|
"@types/winreg": "^1.2.30",
|
||||||
"@typescript-eslint/eslint-plugin": "^3.10.1",
|
"@typescript-eslint/eslint-plugin": "^4.1.0",
|
||||||
"@typescript-eslint/parser": "^3.10.1",
|
"@typescript-eslint/parser": "^4.1.0",
|
||||||
"chai": "^4.2.0",
|
"chai": "^4.2.0",
|
||||||
"chai-as-promised": "^7.1.1",
|
"chai-as-promised": "^7.1.1",
|
||||||
"cross-env": "^7.0.2",
|
"cross-env": "^7.0.2",
|
||||||
"electron": "^9.2.1",
|
"electron": "^9.3.0",
|
||||||
"electron-builder": "^22.8.0",
|
"electron-builder": "^22.8.0",
|
||||||
"electron-devtools-installer": "^3.1.1",
|
"electron-devtools-installer": "^3.1.1",
|
||||||
"electron-webpack": "^2.8.2",
|
"electron-webpack": "^2.8.2",
|
||||||
"electron-webpack-ts": "^4.0.1",
|
"electron-webpack-ts": "^4.0.1",
|
||||||
"eslint": "^7.8.1",
|
"eslint": "^7.9.0",
|
||||||
"eslint-plugin-react": "^7.20.6",
|
"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",
|
"mocha": "^8.1.3",
|
||||||
"nock": "^13.0.4",
|
"nock": "^13.0.4",
|
||||||
"react": "^16.13.0",
|
"react": "^16.13.0",
|
||||||
|
@ -29,6 +29,7 @@ export interface ServerStatus {
|
|||||||
version: string
|
version: string
|
||||||
}[]
|
}[]
|
||||||
}
|
}
|
||||||
|
retrievedAt: number // Internal tracking
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -77,6 +78,7 @@ function unifyStatusResponse(resp: ServerStatus): ServerStatus {
|
|||||||
text: resp.description
|
text: resp.description
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
resp.retrievedAt = (new Date()).getTime()
|
||||||
return resp
|
return resp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,44 +30,48 @@ export class MojangRestAPI {
|
|||||||
version: 1
|
version: 1
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static statuses: MojangStatus[] = [
|
protected static statuses: MojangStatus[] = MojangRestAPI.getDefaultStatuses()
|
||||||
{
|
|
||||||
service: 'sessionserver.mojang.com',
|
public static getDefaultStatuses(): MojangStatus[] {
|
||||||
status: MojangStatusColor.GREY,
|
return [
|
||||||
name: 'Multiplayer Session Service',
|
{
|
||||||
essential: true
|
service: 'sessionserver.mojang.com',
|
||||||
},
|
status: MojangStatusColor.GREY,
|
||||||
{
|
name: 'Multiplayer Session Service',
|
||||||
service: 'authserver.mojang.com',
|
essential: true
|
||||||
status: MojangStatusColor.GREY,
|
},
|
||||||
name: 'Authentication Service',
|
{
|
||||||
essential: true
|
service: 'authserver.mojang.com',
|
||||||
},
|
status: MojangStatusColor.GREY,
|
||||||
{
|
name: 'Authentication Service',
|
||||||
service: 'textures.minecraft.net',
|
essential: true
|
||||||
status: MojangStatusColor.GREY,
|
},
|
||||||
name: 'Minecraft Skins',
|
{
|
||||||
essential: false
|
service: 'textures.minecraft.net',
|
||||||
},
|
status: MojangStatusColor.GREY,
|
||||||
{
|
name: 'Minecraft Skins',
|
||||||
service: 'api.mojang.com',
|
essential: false
|
||||||
status: MojangStatusColor.GREY,
|
},
|
||||||
name: 'Public API',
|
{
|
||||||
essential: false
|
service: 'api.mojang.com',
|
||||||
},
|
status: MojangStatusColor.GREY,
|
||||||
{
|
name: 'Public API',
|
||||||
service: 'minecraft.net',
|
essential: false
|
||||||
status: MojangStatusColor.GREY,
|
},
|
||||||
name: 'Minecraft.net',
|
{
|
||||||
essential: false
|
service: 'minecraft.net',
|
||||||
},
|
status: MojangStatusColor.GREY,
|
||||||
{
|
name: 'Minecraft.net',
|
||||||
service: 'account.mojang.com',
|
essential: false
|
||||||
status: MojangStatusColor.GREY,
|
},
|
||||||
name: 'Mojang Accounts Website',
|
{
|
||||||
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
|
* Converts a Mojang status color to a hex value. Valid statuses
|
||||||
|
@ -24,6 +24,10 @@ import { DistributionAPI } from 'common/distribution/DistributionAPI'
|
|||||||
import { getServerStatus, ServerStatus } from 'common/mojang/net/ServerStatusAPI'
|
import { getServerStatus, ServerStatus } from 'common/mojang/net/ServerStatusAPI'
|
||||||
import { Distribution } from 'helios-distribution-types'
|
import { Distribution } from 'helios-distribution-types'
|
||||||
import { HeliosDistribution, HeliosServer } from 'common/distribution/DistributionFactory'
|
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'
|
import './Application.css'
|
||||||
|
|
||||||
@ -39,8 +43,9 @@ interface ApplicationProps {
|
|||||||
currentView: View
|
currentView: View
|
||||||
overlayQueue: OverlayPushAction<unknown>[]
|
overlayQueue: OverlayPushAction<unknown>[]
|
||||||
distribution: HeliosDistribution
|
distribution: HeliosDistribution
|
||||||
selectedServer: HeliosServer
|
selectedServer?: HeliosServer
|
||||||
selectedServerStatus: ServerStatus
|
selectedServerStatus?: ServerStatus
|
||||||
|
mojangStatuses: MojangStatus[]
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ApplicationState {
|
interface ApplicationState {
|
||||||
@ -54,8 +59,9 @@ const mapState = (state: StoreType): Partial<ApplicationProps> => {
|
|||||||
return {
|
return {
|
||||||
currentView: state.currentView,
|
currentView: state.currentView,
|
||||||
overlayQueue: state.overlayQueue,
|
overlayQueue: state.overlayQueue,
|
||||||
distribution: state.app.distribution!,
|
distribution: state.app.distribution,
|
||||||
selectedServer: state.app.selectedServer!
|
selectedServer: state.app.selectedServer,
|
||||||
|
mojangStatuses: state.app.mojangStatuses
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const mapDispatch = {
|
const mapDispatch = {
|
||||||
@ -64,13 +70,18 @@ const mapDispatch = {
|
|||||||
...OverlayActionDispatch
|
...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 static readonly logger = LoggerUtil.getLogger('ApplicationTSX')
|
||||||
|
|
||||||
|
private mojangStatusInterval!: NodeJS.Timeout
|
||||||
|
private serverStatusInterval!: NodeJS.Timeout
|
||||||
|
|
||||||
private bkid!: number
|
private bkid!: number
|
||||||
|
|
||||||
constructor(props: ApplicationProps & typeof mapDispatch) {
|
constructor(props: InternalApplicationProps) {
|
||||||
super(props)
|
super(props)
|
||||||
this.state = {
|
this.state = {
|
||||||
loading: true,
|
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 => {
|
private getViewElement = (): JSX.Element => {
|
||||||
// TODO debug remove
|
// TODO debug remove
|
||||||
console.log('loading', this.props.currentView, this.state.workingView)
|
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}
|
distribution={this.props.distribution}
|
||||||
selectedServer={this.props.selectedServer}
|
selectedServer={this.props.selectedServer}
|
||||||
selectedServerStatus={this.props.selectedServerStatus}
|
selectedServerStatus={this.props.selectedServerStatus}
|
||||||
|
mojangStatuses={this.props.mojangStatuses}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
case View.LOGIN:
|
case View.LOGIN:
|
||||||
@ -184,6 +273,10 @@ class Application extends React.Component<ApplicationProps & typeof mapDispatch,
|
|||||||
this.props.setSelectedServerStatus(selectedServerStatus)
|
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.
|
// TODO Setup hook for distro refresh every ~ 5 mins.
|
||||||
|
|
||||||
// Pick a background id.
|
// Pick a background id.
|
||||||
|
@ -6,11 +6,9 @@ import { StoreType } from '../../redux/store'
|
|||||||
import { AppActionDispatch } from '../..//redux/actions/appActions'
|
import { AppActionDispatch } from '../..//redux/actions/appActions'
|
||||||
import { OverlayActionDispatch } from '../../redux/actions/overlayActions'
|
import { OverlayActionDispatch } from '../../redux/actions/overlayActions'
|
||||||
import { HeliosDistribution, HeliosServer } from 'common/distribution/DistributionFactory'
|
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 { MojangStatus, MojangStatusColor } from 'common/mojang/rest/internal/MojangStatus'
|
||||||
import { MojangResponse } from 'common/mojang/rest/internal/MojangResponse'
|
|
||||||
import { MojangRestAPI } from 'common/mojang/rest/MojangRestAPI'
|
import { MojangRestAPI } from 'common/mojang/rest/MojangRestAPI'
|
||||||
import { RestResponseStatus } from 'common/got/RestResponse'
|
|
||||||
import { LoggerUtil } from 'common/logging/loggerutil'
|
import { LoggerUtil } from 'common/logging/loggerutil'
|
||||||
|
|
||||||
import News from '../news/News'
|
import News from '../news/News'
|
||||||
@ -19,20 +17,21 @@ import './Landing.css'
|
|||||||
|
|
||||||
interface LandingProps {
|
interface LandingProps {
|
||||||
distribution: HeliosDistribution
|
distribution: HeliosDistribution
|
||||||
selectedServer: HeliosServer
|
selectedServer?: HeliosServer
|
||||||
selectedServerStatus: ServerStatus
|
selectedServerStatus?: ServerStatus
|
||||||
|
mojangStatuses: MojangStatus[]
|
||||||
}
|
}
|
||||||
|
|
||||||
interface LandingState {
|
interface LandingState {
|
||||||
mojangStatuses: MojangStatus[]
|
workingServerStatus?: ServerStatus
|
||||||
outdatedServerStatus: boolean
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapState = (state: StoreType): Partial<LandingProps> => {
|
const mapState = (state: StoreType): Partial<LandingProps> => {
|
||||||
return {
|
return {
|
||||||
distribution: state.app.distribution!,
|
distribution: state.app.distribution!,
|
||||||
selectedServer: state.app.selectedServer!,
|
selectedServer: state.app.selectedServer,
|
||||||
selectedServerStatus: state.app.selectedServerStatus!
|
selectedServerStatus: state.app.selectedServerStatus,
|
||||||
|
mojangStatuses: state.app.mojangStatuses
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const mapDispatch = {
|
const mapDispatch = {
|
||||||
@ -44,102 +43,21 @@ type InternalLandingProps = LandingProps & typeof mapDispatch
|
|||||||
|
|
||||||
class Landing extends React.Component<InternalLandingProps, LandingState> {
|
class Landing extends React.Component<InternalLandingProps, LandingState> {
|
||||||
|
|
||||||
private static readonly logger = LoggerUtil.getLogger('LandingTSX')
|
private static readonly logger = LoggerUtil.getLogger('Landing')
|
||||||
|
|
||||||
private mojangStatusInterval!: NodeJS.Timeout
|
|
||||||
private serverStatusInterval!: NodeJS.Timeout
|
|
||||||
|
|
||||||
constructor(props: InternalLandingProps) {
|
constructor(props: InternalLandingProps) {
|
||||||
super(props)
|
super(props)
|
||||||
this.state = {
|
this.state = {
|
||||||
mojangStatuses: [],
|
workingServerStatus: props.selectedServerStatus
|
||||||
outdatedServerStatus: false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount(): Promise<void> {
|
/* Mojang Status Methods */
|
||||||
|
|
||||||
// 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
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private getMainMojangStatusColor = (): string => {
|
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)
|
return MojangRestAPI.statusToHex(MojangStatusColor.GREY)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,11 +70,11 @@ class Landing extends React.Component<InternalLandingProps, LandingState> {
|
|||||||
return MojangRestAPI.statusToHex(MojangStatusColor.YELLOW)
|
return MojangRestAPI.statusToHex(MojangStatusColor.YELLOW)
|
||||||
}
|
}
|
||||||
// If any non-essential are not green, return 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)
|
return MojangRestAPI.statusToHex(MojangStatusColor.YELLOW)
|
||||||
}
|
}
|
||||||
// if all are grey, return grey.
|
// 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)
|
return MojangRestAPI.statusToHex(MojangStatusColor.GREY)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,7 +84,7 @@ class Landing extends React.Component<InternalLandingProps, LandingState> {
|
|||||||
private getMojangStatusesAsJSX = (essential: boolean): JSX.Element[] => {
|
private getMojangStatusesAsJSX = (essential: boolean): JSX.Element[] => {
|
||||||
|
|
||||||
const statuses: 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(
|
statuses.push(
|
||||||
<div className="mojangStatusContainer" key={status.service}>
|
<div className="mojangStatusContainer" key={status.service}>
|
||||||
<span className="mojangStatusIcon" style={{color: MojangRestAPI.statusToHex(status.status)}}>•</span>
|
<span className="mojangStatusIcon" style={{color: MojangRestAPI.statusToHex(status.status)}}>•</span>
|
||||||
@ -177,18 +95,23 @@ class Landing extends React.Component<InternalLandingProps, LandingState> {
|
|||||||
return statuses
|
return statuses
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Selected Server Methods */
|
||||||
|
|
||||||
|
private updateWorkingServerStatus = (): void => {
|
||||||
|
this.setState({
|
||||||
|
...this.state,
|
||||||
|
workingServerStatus: this.props.selectedServerStatus
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
private openServerSelect = (): void => {
|
private openServerSelect = (): void => {
|
||||||
this.props.pushServerSelectOverlay({
|
this.props.pushServerSelectOverlay({
|
||||||
servers: this.props.distribution.servers,
|
servers: this.props.distribution.servers,
|
||||||
selectedId: this.props.selectedServer.rawServer.id,
|
selectedId: this.props.selectedServer?.rawServer.id,
|
||||||
onSelection: async (serverId: string) => {
|
onSelection: async (serverId: string) => {
|
||||||
Landing.logger.info('Server Selection Change:', serverId)
|
Landing.logger.info('Server Selection Change:', serverId)
|
||||||
const next: HeliosServer = this.props.distribution.getServerById(serverId)!
|
const next: HeliosServer = this.props.distribution.getServerById(serverId)!
|
||||||
this.props.setSelectedServer(next)
|
this.props.setSelectedServer(next)
|
||||||
this.setState({
|
|
||||||
...this.state,
|
|
||||||
outdatedServerStatus: true
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -202,18 +125,20 @@ class Landing extends React.Component<InternalLandingProps, LandingState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private getSelectedServerStatusText = (): string => {
|
private getSelectedServerStatusText = (): string => {
|
||||||
return this.props.selectedServerStatus != null ? 'PLAYERS' : 'SERVER'
|
return this.state.workingServerStatus != null ? 'PLAYERS' : 'SERVER'
|
||||||
}
|
}
|
||||||
|
|
||||||
private getSelectedServerCount = (): string => {
|
private getSelectedServerCount = (): string => {
|
||||||
if(this.props.selectedServerStatus != null) {
|
if(this.state.workingServerStatus != null) {
|
||||||
const { online, max } = this.props.selectedServerStatus.players
|
const { online, max } = this.state.workingServerStatus.players
|
||||||
return `${online}/${max}`
|
return `${online}/${max}`
|
||||||
} else {
|
} else {
|
||||||
return 'OFFLINE'
|
return 'OFFLINE'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Render */
|
||||||
|
|
||||||
render(): JSX.Element {
|
render(): JSX.Element {
|
||||||
return <>
|
return <>
|
||||||
|
|
||||||
@ -316,12 +241,11 @@ class Landing extends React.Component<InternalLandingProps, LandingState> {
|
|||||||
<div id="content">
|
<div id="content">
|
||||||
|
|
||||||
<CSSTransition
|
<CSSTransition
|
||||||
in={!this.state.outdatedServerStatus}
|
in={this.props.selectedServerStatus?.retrievedAt === this.state.workingServerStatus?.retrievedAt}
|
||||||
timeout={500}
|
timeout={500}
|
||||||
classNames="serverStatusWrapper"
|
classNames="serverStatusWrapper"
|
||||||
unmountOnExit
|
unmountOnExit
|
||||||
onEnter={this.syncServerStatus}
|
onExited={this.updateWorkingServerStatus}
|
||||||
onExited={this.finishServerSync}
|
|
||||||
>
|
>
|
||||||
<div id="server_status_wrapper">
|
<div id="server_status_wrapper">
|
||||||
<span className="bot_label" id="landingPlayerLabel">{this.getSelectedServerStatusText()}</span>
|
<span className="bot_label" id="landingPlayerLabel">{this.getSelectedServerStatusText()}</span>
|
||||||
|
@ -9,7 +9,7 @@ import '../shared-select/SharedSelect.css'
|
|||||||
|
|
||||||
export interface ServerSelectOverlayProps {
|
export interface ServerSelectOverlayProps {
|
||||||
servers: HeliosServer[]
|
servers: HeliosServer[]
|
||||||
selectedId: string
|
selectedId?: string
|
||||||
onSelection: (serverId: string) => Promise<void>
|
onSelection: (serverId: string) => Promise<void>
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ class ServerSelectOverlay extends React.Component<InternalServerSelectOverlayPro
|
|||||||
constructor(props: InternalServerSelectOverlayProps) {
|
constructor(props: InternalServerSelectOverlayProps) {
|
||||||
super(props)
|
super(props)
|
||||||
this.state = {
|
this.state = {
|
||||||
selectedId: props.selectedId
|
selectedId: props.selectedId!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ ReactDOM.render(
|
|||||||
distribution={store.getState().app.distribution!}
|
distribution={store.getState().app.distribution!}
|
||||||
selectedServer={store.getState().app.selectedServer!}
|
selectedServer={store.getState().app.selectedServer!}
|
||||||
selectedServerStatus={store.getState().app.selectedServerStatus!}
|
selectedServerStatus={store.getState().app.selectedServerStatus!}
|
||||||
|
mojangStatuses={store.getState().app.mojangStatuses!}
|
||||||
/>
|
/>
|
||||||
</Provider>
|
</Provider>
|
||||||
</AppContainer>,
|
</AppContainer>,
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
import { Action } from 'redux'
|
import { Action } from 'redux'
|
||||||
import { HeliosDistribution, HeliosServer } from 'common/distribution/DistributionFactory'
|
import { HeliosDistribution, HeliosServer } from 'common/distribution/DistributionFactory'
|
||||||
import { ServerStatus } from 'common/mojang/net/ServerStatusAPI'
|
import { ServerStatus } from 'common/mojang/net/ServerStatusAPI'
|
||||||
|
import { MojangStatus } from 'common/mojang/rest/internal/MojangStatus'
|
||||||
|
|
||||||
export enum AppActionType {
|
export enum AppActionType {
|
||||||
SetDistribution = 'SET_DISTRIBUTION',
|
SetDistribution = 'SET_DISTRIBUTION',
|
||||||
SetSelectedServer = 'SET_SELECTED_SERVER',
|
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
|
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||||
@ -23,6 +25,10 @@ export interface SetSelectedServerStatusAction extends AppAction {
|
|||||||
payload?: ServerStatus
|
payload?: ServerStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SetMojangStatusesAction extends AppAction {
|
||||||
|
payload: MojangStatus[]
|
||||||
|
}
|
||||||
|
|
||||||
export function setDistribution(distribution?: HeliosDistribution): SetDistributionAction {
|
export function setDistribution(distribution?: HeliosDistribution): SetDistributionAction {
|
||||||
return {
|
return {
|
||||||
type: AppActionType.SetDistribution,
|
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 = {
|
export const AppActionDispatch = {
|
||||||
setDistribution: (d?: HeliosDistribution): SetDistributionAction => setDistribution(d),
|
setDistribution: (d?: HeliosDistribution): SetDistributionAction => setDistribution(d),
|
||||||
setSelectedServer: (s?: HeliosServer): SetSelectedServerAction => setSelectedServer(s),
|
setSelectedServer: (s?: HeliosServer): SetSelectedServerAction => setSelectedServer(s),
|
||||||
setSelectedServerStatus: (ss?: ServerStatus): SetSelectedServerStatusAction => setSelectedServerStatus(ss)
|
setSelectedServerStatus: (ss?: ServerStatus): SetSelectedServerStatusAction => setSelectedServerStatus(ss),
|
||||||
|
setMojangStatuses: (ms: MojangStatus[]): SetMojangStatusesAction => setMojangStatuses(ms)
|
||||||
}
|
}
|
@ -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 { Reducer } from 'redux'
|
||||||
import { HeliosDistribution, HeliosServer } from 'common/distribution/DistributionFactory'
|
import { HeliosDistribution, HeliosServer } from 'common/distribution/DistributionFactory'
|
||||||
import { ServerStatus } from 'common/mojang/net/ServerStatusAPI'
|
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 {
|
export interface AppState {
|
||||||
distribution?: HeliosDistribution
|
distribution?: HeliosDistribution
|
||||||
selectedServer?: HeliosServer
|
selectedServer?: HeliosServer
|
||||||
selectedServerStatus?: ServerStatus
|
selectedServerStatus?: ServerStatus
|
||||||
|
mojangStatuses: MojangStatus[]
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultAppState: AppState = {
|
const defaultAppState: AppState = {
|
||||||
distribution: undefined,
|
distribution: undefined,
|
||||||
selectedServer: undefined,
|
selectedServer: undefined,
|
||||||
selectedServerStatus: undefined
|
selectedServerStatus: undefined,
|
||||||
|
mojangStatuses: MojangRestAPI.getDefaultStatuses()
|
||||||
}
|
}
|
||||||
|
|
||||||
const AppReducer: Reducer<AppState, AppAction> = (state = defaultAppState, action) => {
|
const AppReducer: Reducer<AppState, AppAction> = (state = defaultAppState, action) => {
|
||||||
@ -32,6 +36,11 @@ const AppReducer: Reducer<AppState, AppAction> = (state = defaultAppState, actio
|
|||||||
...state,
|
...state,
|
||||||
selectedServerStatus: (action as SetSelectedServerStatusAction).payload
|
selectedServerStatus: (action as SetSelectedServerStatusAction).payload
|
||||||
}
|
}
|
||||||
|
case AppActionType.SetMojangStatuses:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
mojangStatuses: (action as SetMojangStatusesAction).payload
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user