Skip to content
2 changes: 1 addition & 1 deletion views/components/etc/webview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ const ElectronWebView = forwardRef<ExtendedWebviewTag | undefined, Props>(
const errorScript = `document.write('<br>Webview load error<br>Error Code: ${e.errorCode}<br>Description: ${e.errorDescription}<br>URL: ${e.validatedURL}')\ndocument.body.style.backgroundColor = "white"`
const target = e.target
if (target && 'executeJavaScript' in target) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- target is narrowed by 'executeJavaScript' in check above
const webviewTarget = target as WebviewTag
webviewTarget.executeJavaScript(errorScript)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Tooltip, Tag, Position, Intent } from '@blueprintjs/core'
import { memoize, get } from 'lodash'
import React from 'react'
import { withNamespaces, Trans } from 'react-i18next'
import { useTranslation, Trans } from 'react-i18next'
import { connect } from 'react-redux'
import { createSelector } from 'reselect'
import {
Expand All @@ -14,7 +14,7 @@
import { getShipAACIs, getShipAllAACIs, AACITable } from 'views/utils/aaci'
import { shipDataSelectorFactory, shipEquipDataSelectorFactory } from 'views/utils/selectors'

const getAvailableTranslation = memoize((str) =>
const getAvailableTranslation = memoize((str: string) =>
i18next.translator.exists(`main:${str}`) ? (
<Trans>main:{str}</Trans>
) : i18next.translator.exists(`resources:${str}`) ? (
Expand All @@ -24,14 +24,20 @@
),
)

const __t = (name) =>
const __t = (name: string[]) =>
name.map((n, i) => (
<AACITypeName className="aaci-type-name" key={i}>
{getAvailableTranslation(n)}
</AACITypeName>
))

const AACISelectorFactory = memoize((shipId) =>
interface AACISelectorResult {
AACIs: number[]
maxShotdown: number
}


Check warning on line 39 in views/components/ship/aaci-indicator.tsx

View workflow job for this annotation

GitHub Actions / test

Delete `⏎`
const AACISelectorFactory = memoize((shipId: number) =>
createSelector(
[shipDataSelectorFactory(shipId), shipEquipDataSelectorFactory(shipId)],
([_ship = {}, $ship = {}] = [], _equips = []) => {
Expand All @@ -45,50 +51,53 @@
),
)

const maxAACIShotdownSelectorFactory = memoize((shipId) =>
const maxAACIShotdownSelectorFactory = memoize((shipId: number) =>
createSelector([shipDataSelectorFactory(shipId)], ([_ship = {}, $ship = {}] = []) => {
const AACIs = getShipAllAACIs({ ...$ship, ..._ship })
return Math.max(...AACIs.map((id) => AACITable[id].fixed || 0))
}),
)

export const AACIIndicator = withNamespaces(['main'])(
connect((state, { shipId }) => ({
AACIs: AACISelectorFactory(shipId)(state) || [],
maxShotdown: maxAACIShotdownSelectorFactory(shipId)(state),
}))(({ AACIs, maxShotdown, shipId, t }) => {
const currentMax = Math.max(...AACIs.map((id) => AACITable[id].fixed || 0))
const AACIIndicatorComponent: React.FC<AACISelectorResult> = ({ AACIs, maxShotdown }) => {
const { t } = useTranslation(['main'])
const currentMax = Math.max(...AACIs.map((id) => AACITable[id].fixed || 0))

const tooltip = AACIs.length && (
<InfoTooltip className="info-tooltip">
{AACIs.map((id) => (
<InfoTooltipEntry className="info-tooltip-entry" key={id}>
<InfoTooltipItem className="info-tooltip-item">
{t('main:AACIType', { count: id })}
<span>
{get(AACITable, `${id}.name.length`, 0) > 0 ? __t(AACITable[id].name) : ''}
</span>
</InfoTooltipItem>
<span>{t('main:Shot down', { count: AACITable[id].fixed })}</span>
<span style={{ marginLeft: '2ex' }}>
{t('main:Modifier', { count: AACITable[id].modifier })}
</span>
</InfoTooltipEntry>
))}
{currentMax < maxShotdown && <span>{t('main:Max shot down not reached')}</span>}
</InfoTooltip>
)
const tooltip = AACIs.length > 0 && (
<InfoTooltip className="info-tooltip">
{AACIs.map((id) => (
<InfoTooltipEntry className="info-tooltip-entry" key={id}>
<InfoTooltipItem className="info-tooltip-item">
{t('main:AACIType', { count: id })}
<span>{get(AACITable, `${id}.name.length`, 0) > 0 ? __t(AACITable[id].name) : ''}</span>
</InfoTooltipItem>
<span>{t('main:Shot down', { count: get(AACITable, `${id}.fixed`, 0) })}</span>
<span style={{ marginLeft: '2ex' }}>
{t('main:Modifier', { count: get(AACITable, `${id}.modifier`, 0) })}
</span>
</InfoTooltipEntry>
))}
{currentMax < maxShotdown && <span>{t('main:Max shot down not reached')}</span>}
</InfoTooltip>
)

return (
!!AACIs.length && (
return (
<>
{AACIs.length > 0 && (
<ShipLabel className="ship-skill-indicator ship-aaci" isTag>
<Tooltip position={Position.TOP} content={tooltip}>
<Tag minimal intent={Intent.WARNING}>
{t('main:AACI')}
</Tag>
</Tooltip>
</ShipLabel>
)
)
}),
)
)}
</>
)
}

const mapStateToProps = (state: unknown, { shipId }: { shipId: number }): AACISelectorResult => ({
AACIs: AACISelectorFactory(shipId)(state) || [],
maxShotdown: maxAACIShotdownSelectorFactory(shipId)(state),
})

export const AACIIndicator = connect(mapStateToProps)(AACIIndicatorComponent)
44 changes: 0 additions & 44 deletions views/components/ship/aapb-indicator.es

This file was deleted.

66 changes: 66 additions & 0 deletions views/components/ship/aapb-indicator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { Tag, Intent, Position, Tooltip } from '@blueprintjs/core'
import { compact, isFinite, memoize } from 'lodash'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { connect } from 'react-redux'
import { createSelector } from 'reselect'
import { ShipLabel } from 'views/components/ship-parts/styled-components'
import { getShipAAPB } from 'views/utils/aapb'
import { shipDataSelectorFactory, shipEquipDataSelectorFactory } from 'views/utils/selectors'

interface ShipInfo {
[key: string]: unknown
}

interface EquipInfo {
[key: string]: unknown
}

interface AAPBSelectorProps {
shipId: number
}

interface AAPBStateProps {
AAPB: number
}

interface AAPBIndicatorProps extends AAPBSelectorProps, AAPBStateProps {}

const AAPBSelectorFactory = memoize((shipId: number) =>
createSelector(
[shipDataSelectorFactory(shipId), shipEquipDataSelectorFactory(shipId)],
(shipInfo: [ShipInfo, ShipInfo] | undefined, equipsInfo: (EquipInfo[] | undefined)[]) => {
if (!shipInfo || !equipsInfo) return 0
/*
equipment position is irrelevant with regard to AAPB trigger rate,
so we might as well remove all `undefined` for getShipAAPB to
have a uniform structure to work with.
*/
return getShipAAPB(shipInfo, compact(equipsInfo))
},
Comment thread
KagamiChan marked this conversation as resolved.
),
)

const AAPBIndicatorComponent: React.FC<AAPBIndicatorProps> = ({ AAPB }) => {
const { t } = useTranslation(['main'])

if (!isFinite(AAPB) || AAPB <= 0) {
return null
}

return (
<ShipLabel className="ship-skill-indicator ship-aapb" isTag>
<Tooltip position={Position.TOP} content={<span>{`${AAPB.toFixed(2)}%`}</span>}>
<Tag minimal intent={Intent.WARNING}>
{t('main:AAPB')}
</Tag>
</Tooltip>
</ShipLabel>
)
}

const mapStateToProps = (state: unknown, ownProps: AAPBSelectorProps): AAPBStateProps => ({
AAPB: AAPBSelectorFactory(ownProps.shipId)(state) || 0,
})

export const AAPBIndicator = connect(mapStateToProps)(AAPBIndicatorComponent)
Loading
Loading