@jeremyckahn/farmhand 1.23.2 → 1.23.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/dist/assets/index-4ynbl-GC.js +392 -0
- package/dist/assets/index-4ynbl-GC.js.map +1 -0
- package/dist/assets/index-CaYdR-lC.css +1 -0
- package/dist/assets/jersey-10-latin-400-normal-DrL73VYW.woff2 +0 -0
- package/dist/assets/jersey-10-latin-ext-400-normal-uIKqQSaG.woff2 +0 -0
- package/dist/assets/jersey-20-latin-400-normal-bNi78tgO.woff2 +0 -0
- package/dist/assets/jersey-20-latin-ext-400-normal-BO3lmWef.woff2 +0 -0
- package/dist/assets/jersey-25-latin-400-normal-BuYJnnt7.woff2 +0 -0
- package/dist/assets/jersey-25-latin-ext-400-normal-CP5Jl3WN.woff2 +0 -0
- package/dist/index.html +2 -2
- package/dist/service-worker.js +1 -1
- package/dist/service-worker.js.map +1 -1
- package/package.json +7 -12
- package/src/common/services/randomNumber.test.ts +61 -1
- package/src/common/services/randomNumber.ts +36 -1
- package/src/common/utils.ts +22 -13
- package/src/components/AccountingView/AccountingView.tsx +7 -13
- package/src/components/Achievement/Achievement.tsx +2 -15
- package/src/components/AchievementsView/AchievementsView.tsx +2 -7
- package/src/components/AnimatedNumber/AnimatedNumber.tsx +0 -6
- package/src/components/AppBar/AppBar.tsx +21 -17
- package/src/components/Cellar/Cellar.tsx +0 -2
- package/src/components/Cellar/CellarInventoryTabPanel.tsx +0 -6
- package/src/components/Cellar/FermentationTabPanel.tsx +0 -6
- package/src/components/Cellar/Keg.tsx +0 -5
- package/src/components/Cellar/TabPanel/index.tsx +0 -7
- package/src/components/Cellar/WinemakingTabPanel.tsx +0 -6
- package/src/components/ContextPane/ContextPane.tsx +0 -6
- package/src/components/CowCard/Bloodline/Bloodline.tsx +0 -6
- package/src/components/CowCard/CowCard.tsx +7 -39
- package/src/components/CowCard/Subheader/Subheader.tsx +21 -44
- package/src/components/CowPen/Cow.tsx +5 -11
- package/src/components/CowPen/CowPen.test.tsx +4 -4
- package/src/components/CowPen/CowPen.tsx +5 -16
- package/src/components/CowPenContextMenu/CowPenContextMenu.tsx +2 -18
- package/src/components/CowPenContextMenu/TabPanel/index.tsx +0 -7
- package/src/components/Farmhand/Farmhand.context.tsx +4 -3
- package/src/components/Farmhand/Farmhand.tsx +11 -15
- package/src/components/Farmhand/FarmhandReducers.tsx +1 -2
- package/src/components/Farmhand/FarmhandService.test.ts +6 -9
- package/src/components/Farmhand/hooks/useFarmhandDayAdvancement.ts +2 -6
- package/src/components/Farmhand/hooks/useFarmhandNetwork.test.ts +2 -2
- package/src/components/Farmhand/hooks/useFarmhandNetwork.ts +15 -31
- package/src/components/Farmhand/useFarmhand.test.ts +7 -5
- package/src/components/Farmhand/useFarmhand.ts +24 -15
- package/src/components/FermentationRecipeList/FermentationRecipe.tsx +0 -5
- package/src/components/FermentationRecipeList/FermentationRecipeList.test.tsx +10 -11
- package/src/components/FermentationRecipeList/FermentationRecipeList.tsx +2 -3
- package/src/components/Field/Field.tsx +15 -50
- package/src/components/Forest/Forest.tsx +10 -7
- package/src/components/ForestPlot/ForestPlot.tsx +5 -5
- package/src/components/ForestQuickSelect/ForestQuickSelect.tsx +0 -12
- package/src/components/Home/Home.tsx +2 -7
- package/src/components/Home/SnowBackground.tsx +1 -1
- package/src/components/IngredientsList/IngredientsList.tsx +0 -7
- package/src/components/Inventory/Inventory.test.tsx +4 -4
- package/src/components/Inventory/Inventory.tsx +5 -12
- package/src/components/Item/Item.tsx +11 -29
- package/src/components/ItemList/ItemList.tsx +4 -11
- package/src/components/KeybindingsView/KeybindingsView.tsx +0 -2
- package/src/components/LogView/LogView.tsx +6 -28
- package/src/components/Navigation/DayAndProgressContainer.tsx +0 -8
- package/src/components/Navigation/Navigation.tsx +12 -33
- package/src/components/NotificationSystem/NotificationSystem.test.tsx +45 -3
- package/src/components/NotificationSystem/NotificationSystem.tsx +45 -32
- package/src/components/OnlinePeersView/OnlinePeer/OnlinePeer.test.tsx +2 -2
- package/src/components/OnlinePeersView/OnlinePeer/OnlinePeer.tsx +0 -11
- package/src/components/OnlinePeersView/OnlinePeersView.tsx +0 -10
- package/src/components/PixelIcon/createPixelIcon.test.tsx +59 -0
- package/src/components/PixelIcon/createPixelIcon.tsx +97 -0
- package/src/components/PixelIcon/icons.ts +445 -0
- package/src/components/PixelIcon/index.ts +3 -0
- package/src/components/Plot/Plot.tsx +3 -3
- package/src/components/PriceEventView/PriceEventView.tsx +0 -6
- package/src/components/ProgressBar/ProgressBar.tsx +9 -8
- package/src/components/QuantityInput/QuantityInput.tsx +6 -11
- package/src/components/QuickSelect/QuickSelect.tsx +0 -10
- package/src/components/Recipe/Recipe.tsx +0 -9
- package/src/components/RecipeList/RecipeList.tsx +0 -6
- package/src/components/SearchBar/SearchBar.tsx +4 -10
- package/src/components/SettingsView/RandomSeedInput.test.tsx +2 -4
- package/src/components/SettingsView/RandomSeedInput.tsx +5 -8
- package/src/components/SettingsView/SettingsView.test.tsx +21 -0
- package/src/components/SettingsView/SettingsView.tsx +24 -18
- package/src/components/Shop/Shop.tsx +0 -20
- package/src/components/Shop/TabPanel/index.tsx +0 -7
- package/src/components/Stage/Stage.tsx +11 -20
- package/src/components/StatsView/StatsView.tsx +0 -18
- package/src/components/TierPurchase/TierPurchase.tsx +0 -12
- package/src/components/Toolbelt/Toolbelt.tsx +5 -10
- package/src/components/UpdateNotifier/UpdateNotifier.tsx +33 -5
- package/src/components/UpgradePurchase/UpgradePurchase.tsx +0 -10
- package/src/components/WineRecipeList/WineRecipe.test.tsx +2 -2
- package/src/components/WineRecipeList/WineRecipe.tsx +0 -5
- package/src/components/WineRecipeList/WineRecipeList.tsx +2 -3
- package/src/components/Workshop/ForgeTabPanel.tsx +0 -8
- package/src/components/Workshop/KitchenTabPanel.tsx +0 -7
- package/src/components/Workshop/RecyclingTabPanel.tsx +0 -7
- package/src/components/Workshop/TabPanel/index.tsx +0 -7
- package/src/components/Workshop/WoodChipperTabPanel.tsx +0 -7
- package/src/components/Workshop/Workshop.tsx +0 -9
- package/src/components/Workshop/getUpgradesAvailable.ts +1 -1
- package/src/constants.ts +18 -13
- package/src/data/crops/grape.ts +13 -15
- package/src/data/maps.test.ts +3 -4
- package/src/data/maps.ts +27 -29
- package/src/enums.ts +47 -19
- package/src/factories/OreFactory.ts +2 -1
- package/src/farmhand.d.ts +6 -3
- package/src/game-logic/reducers/applyPrecipitation.ts +4 -4
- package/src/game-logic/reducers/generatePriceEvents.ts +6 -3
- package/src/game-logic/reducers/harvestForestPlot.ts +1 -2
- package/src/game-logic/reducers/makeFermentationRecipe.ts +2 -3
- package/src/game-logic/reducers/minePlot.test.ts +2 -2
- package/src/game-logic/reducers/minePlot.ts +1 -1
- package/src/game-logic/reducers/processCowFertilizerProduction.test.ts +16 -14
- package/src/game-logic/reducers/processFeedingCows.test.ts +2 -5
- package/src/game-logic/reducers/purchaseCow.ts +2 -7
- package/src/game-logic/reducers/showNotification.test.ts +20 -0
- package/src/game-logic/reducers/showNotification.ts +4 -2
- package/src/game-logic/reducers/updateAchievements.ts +1 -1
- package/src/game-logic/reducers/updateFinancialRecords.test.ts +21 -25
- package/src/game-logic/reducers/updateFinancialRecords.ts +2 -5
- package/src/game-logic/reducers/updateInventoryRecordsForNextDay.test.ts +12 -14
- package/src/handlers/ui-events.test.ts +44 -42
- package/src/handlers/ui-events.tsx +18 -3
- package/src/hooks/usePrefersReducedMotion.ts +10 -6
- package/src/index.tsx +0 -2
- package/src/mui-theme.ts +258 -37
- package/src/scripts/generate-crop-table.ts +3 -2
- package/src/setupTests.ts +18 -12
- package/src/strings.ts +1 -1
- package/src/styles/fonts.ts +73 -0
- package/src/styles/pixel.ts +151 -0
- package/src/styles/sx.ts +46 -33
- package/src/styles/tokens.ts +11 -0
- package/src/test-utils/index.ts +1 -0
- package/src/utils/chooseRandom.ts +4 -1
- package/src/utils/chooseRandomIndex.ts +6 -2
- package/src/utils/getCowImage.ts +22 -27
- package/src/utils/getMaxYieldOfFermentationRecipe.ts +2 -2
- package/src/utils/getPeerMetadata.ts +1 -1
- package/src/utils/getPlotImage.test.ts +14 -14
- package/src/utils/getPlotImage.ts +10 -10
- package/src/utils/getRandomUnlockedCrop.ts +5 -3
- package/src/utils/getRandomizedLifespan.test.ts +2 -8
- package/src/utils/getValueAdjustmentStream.test.ts +9 -0
- package/src/utils/getValueAdjustmentStream.ts +5 -0
- package/src/utils/isItemAFarmProduct.ts +2 -2
- package/src/utils/shouldPrecipitateToday.ts +3 -1
- package/src/utils/shouldStormToday.ts +2 -1
- package/src/utils/transformStateDataForImport.ts +3 -5
- package/dist/assets/francois-one-latin-400-normal-DD1rFI7H.woff2 +0 -0
- package/dist/assets/francois-one-latin-400-normal-DNXs7uOx.woff +0 -0
- package/dist/assets/francois-one-latin-ext-400-normal-CwRdWRZD.woff2 +0 -0
- package/dist/assets/francois-one-latin-ext-400-normal-JvkpT0Av.woff +0 -0
- package/dist/assets/francois-one-vietnamese-400-normal-BLIKeG5Y.woff2 +0 -0
- package/dist/assets/francois-one-vietnamese-400-normal-CuWeHlXs.woff +0 -0
- package/dist/assets/index-CNcrTYN-.css +0 -1
- package/dist/assets/index-DNPchtK9.js +0 -844
- package/dist/assets/index-DNPchtK9.js.map +0 -1
- package/dist/assets/public-sans-latin-400-normal-8Rpg0ruU.woff2 +0 -0
- package/dist/assets/public-sans-latin-400-normal-SBbinRkI.woff +0 -0
- package/dist/assets/public-sans-latin-ext-400-normal-B02wwOdZ.woff +0 -0
- package/dist/assets/public-sans-latin-ext-400-normal-mk90oQqJ.woff2 +0 -0
- package/dist/assets/public-sans-vietnamese-400-normal-BO1meqcx.woff +0 -0
- package/dist/assets/public-sans-vietnamese-400-normal-TxZB8OSn.woff2 +0 -0
- package/src/fontsource.d.ts +0 -3
|
@@ -17,10 +17,12 @@ const defaultProps = {
|
|
|
17
17
|
handleExportDataClick: noop,
|
|
18
18
|
handleImportDataClick: noop,
|
|
19
19
|
handleSaveButtonClick: noop,
|
|
20
|
+
handleNotificationDurationChange: noop,
|
|
20
21
|
handleShowNotificationsChange: noop,
|
|
21
22
|
handleUseAlternateEndDayButtonPositionChange: noop,
|
|
22
23
|
handleShowHomeScreenChange: noop,
|
|
23
24
|
showNotifications: true,
|
|
25
|
+
notificationDuration: 6000,
|
|
24
26
|
useAlternateEndDayButtonPosition: false,
|
|
25
27
|
showHomeScreen: false,
|
|
26
28
|
}
|
|
@@ -144,6 +146,25 @@ test('handles switch toggling', async () => {
|
|
|
144
146
|
expect(handleAllowCustomPeerCowNamesChange).toHaveBeenCalledTimes(1)
|
|
145
147
|
})
|
|
146
148
|
|
|
149
|
+
test('handles notification duration changes', async () => {
|
|
150
|
+
const user = userEvent.setup()
|
|
151
|
+
const handleNotificationDurationChange = vitest.fn()
|
|
152
|
+
|
|
153
|
+
render(
|
|
154
|
+
<SettingsView
|
|
155
|
+
{...defaultProps}
|
|
156
|
+
handleNotificationDurationChange={handleNotificationDurationChange}
|
|
157
|
+
/>
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
const slider = screen.getByRole('slider')
|
|
161
|
+
|
|
162
|
+
await user.click(slider)
|
|
163
|
+
await user.keyboard('{ArrowRight}')
|
|
164
|
+
|
|
165
|
+
expect(handleNotificationDurationChange).toHaveBeenCalled()
|
|
166
|
+
})
|
|
167
|
+
|
|
147
168
|
test('opens delete confirmation dialog when delete button is clicked', async () => {
|
|
148
169
|
const user = userEvent.setup()
|
|
149
170
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React, { useState } from 'react'
|
|
2
|
-
import { bool, func } from 'prop-types'
|
|
3
2
|
import Button from '@mui/material/Button/index.js'
|
|
4
3
|
import Dialog from '@mui/material/Dialog/index.js'
|
|
5
4
|
import DialogActions from '@mui/material/DialogActions/index.js'
|
|
@@ -11,11 +10,16 @@ import FormControlLabel from '@mui/material/FormControlLabel/index.js'
|
|
|
11
10
|
import FormGroup from '@mui/material/FormGroup/index.js'
|
|
12
11
|
import FormLabel from '@mui/material/FormLabel/index.js'
|
|
13
12
|
import Switch from '@mui/material/Switch/index.js'
|
|
13
|
+
import Slider from '@mui/material/Slider/index.js'
|
|
14
14
|
import Tooltip from '@mui/material/Tooltip/index.js'
|
|
15
15
|
import FileReaderInput from 'react-file-reader-input'
|
|
16
16
|
|
|
17
17
|
import FarmhandContext from '../Farmhand/Farmhand.context.js'
|
|
18
18
|
import { Div } from '../Elements/index.js'
|
|
19
|
+
import {
|
|
20
|
+
NOTIFICATION_DURATION_MAX,
|
|
21
|
+
NOTIFICATION_DURATION_MIN,
|
|
22
|
+
} from '../../constants.js'
|
|
19
23
|
|
|
20
24
|
import { RandomSeedInput } from './RandomSeedInput.js'
|
|
21
25
|
|
|
@@ -26,10 +30,12 @@ const SettingsView = ({
|
|
|
26
30
|
handleExportDataClick,
|
|
27
31
|
handleImportDataClick,
|
|
28
32
|
handleSaveButtonClick,
|
|
33
|
+
handleNotificationDurationChange,
|
|
29
34
|
handleShowNotificationsChange,
|
|
30
35
|
handleUseAlternateEndDayButtonPositionChange,
|
|
31
36
|
handleShowHomeScreenChange,
|
|
32
37
|
showNotifications,
|
|
38
|
+
notificationDuration,
|
|
33
39
|
useAlternateEndDayButtonPosition,
|
|
34
40
|
showHomeScreen,
|
|
35
41
|
}: {
|
|
@@ -41,6 +47,10 @@ const SettingsView = ({
|
|
|
41
47
|
handleExportDataClick: () => void
|
|
42
48
|
handleImportDataClick: (results: any) => void
|
|
43
49
|
handleSaveButtonClick: () => void
|
|
50
|
+
handleNotificationDurationChange: (
|
|
51
|
+
event: React.SyntheticEvent | Event,
|
|
52
|
+
value: number | number[]
|
|
53
|
+
) => void
|
|
44
54
|
handleShowNotificationsChange: (
|
|
45
55
|
event: React.ChangeEvent<HTMLInputElement>
|
|
46
56
|
) => void
|
|
@@ -51,6 +61,7 @@ const SettingsView = ({
|
|
|
51
61
|
event: React.ChangeEvent<HTMLInputElement>
|
|
52
62
|
) => void
|
|
53
63
|
showNotifications: boolean
|
|
64
|
+
notificationDuration: number
|
|
54
65
|
useAlternateEndDayButtonPosition: boolean
|
|
55
66
|
showHomeScreen: boolean
|
|
56
67
|
}) => {
|
|
@@ -110,6 +121,18 @@ const SettingsView = ({
|
|
|
110
121
|
}
|
|
111
122
|
label="Show new notifications"
|
|
112
123
|
/>
|
|
124
|
+
<FormLabel component="legend">Notification display time</FormLabel>
|
|
125
|
+
<Slider
|
|
126
|
+
aria-label="Notification display time"
|
|
127
|
+
marks
|
|
128
|
+
min={NOTIFICATION_DURATION_MIN / 1000}
|
|
129
|
+
max={NOTIFICATION_DURATION_MAX / 1000}
|
|
130
|
+
onChange={handleNotificationDurationChange}
|
|
131
|
+
sx={{ margin: '0 auto', width: '90%' }}
|
|
132
|
+
value={notificationDuration / 1000}
|
|
133
|
+
valueLabelDisplay="auto"
|
|
134
|
+
valueLabelFormat={value => `${value} seconds`}
|
|
135
|
+
/>
|
|
113
136
|
<FormControlLabel
|
|
114
137
|
control={
|
|
115
138
|
<Switch
|
|
@@ -139,7 +162,6 @@ const SettingsView = ({
|
|
|
139
162
|
<div className="button-row">
|
|
140
163
|
<Tooltip
|
|
141
164
|
{...{
|
|
142
|
-
arrow: true,
|
|
143
165
|
placement: 'top',
|
|
144
166
|
title: 'Save your game data as a file on your device',
|
|
145
167
|
}}
|
|
@@ -164,7 +186,6 @@ const SettingsView = ({
|
|
|
164
186
|
>
|
|
165
187
|
<Tooltip
|
|
166
188
|
{...{
|
|
167
|
-
arrow: true,
|
|
168
189
|
placement: 'top',
|
|
169
190
|
title: 'Load game data that was previously saved',
|
|
170
191
|
}}
|
|
@@ -230,21 +251,6 @@ const SettingsView = ({
|
|
|
230
251
|
)
|
|
231
252
|
}
|
|
232
253
|
|
|
233
|
-
SettingsView.propTypes = {
|
|
234
|
-
allowCustomPeerCowNames: bool.isRequired,
|
|
235
|
-
handleAllowCustomPeerCowNamesChange: func.isRequired,
|
|
236
|
-
handleClearPersistedDataClick: func.isRequired,
|
|
237
|
-
handleExportDataClick: func.isRequired,
|
|
238
|
-
handleImportDataClick: func.isRequired,
|
|
239
|
-
handleSaveButtonClick: func.isRequired,
|
|
240
|
-
handleShowHomeScreenChange: func.isRequired,
|
|
241
|
-
handleShowNotificationsChange: func.isRequired,
|
|
242
|
-
handleUseAlternateEndDayButtonPositionChange: func.isRequired,
|
|
243
|
-
showHomeScreen: bool.isRequired,
|
|
244
|
-
showNotifications: bool.isRequired,
|
|
245
|
-
useAlternateEndDayButtonPosition: bool.isRequired,
|
|
246
|
-
}
|
|
247
|
-
|
|
248
254
|
export { SettingsView }
|
|
249
255
|
|
|
250
256
|
export default function Consumer(
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
-
import { array, func, number, object } from 'prop-types'
|
|
3
2
|
import Button from '@mui/material/Button/index.js'
|
|
4
3
|
import Card from '@mui/material/Card/index.js'
|
|
5
4
|
import CardActions from '@mui/material/CardActions/index.js'
|
|
@@ -395,25 +394,6 @@ export const Shop = ({
|
|
|
395
394
|
)
|
|
396
395
|
}
|
|
397
396
|
|
|
398
|
-
Shop.propTypes = {
|
|
399
|
-
handleCombinePurchase: func.isRequired,
|
|
400
|
-
handleCowPenPurchase: func.isRequired,
|
|
401
|
-
handleCellarPurchase: func.isRequired,
|
|
402
|
-
handleFieldPurchase: func.isRequired,
|
|
403
|
-
handleStorageExpansionPurchase: func.isRequired,
|
|
404
|
-
inventoryLimit: number.isRequired,
|
|
405
|
-
money: number.isRequired,
|
|
406
|
-
purchasedCowPen: number.isRequired,
|
|
407
|
-
purchasedCellar: number.isRequired,
|
|
408
|
-
purchasedField: number.isRequired,
|
|
409
|
-
purchasedSmelter: number.isRequired,
|
|
410
|
-
purchasedWoodChipper: number.isRequired,
|
|
411
|
-
purchasedCombine: number.isRequired,
|
|
412
|
-
shopInventory: array.isRequired,
|
|
413
|
-
toolLevels: object.isRequired,
|
|
414
|
-
valueAdjustments: object.isRequired,
|
|
415
|
-
}
|
|
416
|
-
|
|
417
397
|
export default function Consumer(props: Partial<Parameters<typeof Shop>[0]>) {
|
|
418
398
|
return (
|
|
419
399
|
<FarmhandContext.Consumer>
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
-
import { node, number } from 'prop-types'
|
|
3
2
|
|
|
4
3
|
export const TabPanel = (
|
|
5
4
|
props: React.PropsWithChildren<
|
|
@@ -21,12 +20,6 @@ export const TabPanel = (
|
|
|
21
20
|
)
|
|
22
21
|
}
|
|
23
22
|
|
|
24
|
-
TabPanel.propTypes = {
|
|
25
|
-
children: node,
|
|
26
|
-
index: number.isRequired,
|
|
27
|
-
value: number.isRequired,
|
|
28
|
-
}
|
|
29
|
-
|
|
30
23
|
export const a11yProps = (index: number) => ({
|
|
31
24
|
id: `shop-tab-${index}`,
|
|
32
25
|
'aria-controls': `shop-tabpanel-${index}`,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import React, { useEffect, useRef } from 'react'
|
|
2
2
|
import classNames from 'classnames'
|
|
3
|
-
import { array, arrayOf, bool, number, string } from 'prop-types'
|
|
4
3
|
import { Theme } from '@mui/material/styles/index.js'
|
|
5
4
|
|
|
6
5
|
import FarmhandContext from '../Farmhand/Farmhand.context.js'
|
|
@@ -45,9 +44,8 @@ export const Stage = ({
|
|
|
45
44
|
useAlternateEndDayButtonPosition = false,
|
|
46
45
|
viewTitle,
|
|
47
46
|
}: StageProps) => {
|
|
48
|
-
const ref =
|
|
49
|
-
null
|
|
50
|
-
)
|
|
47
|
+
const ref =
|
|
48
|
+
/** @type {React.MutableRefObject<HTMLDivElement | null>} */ useRef(null)
|
|
51
49
|
|
|
52
50
|
useEffect(() => {
|
|
53
51
|
if (ref.current) {
|
|
@@ -67,8 +65,8 @@ export const Stage = ({
|
|
|
67
65
|
[stageFocusType.HOME]: isOctober()
|
|
68
66
|
? jackOLanternBg
|
|
69
67
|
: isDecember()
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
? winterBg
|
|
69
|
+
: brownDotBg,
|
|
72
70
|
[stageFocusType.SHOP]: yellowDotBg,
|
|
73
71
|
[stageFocusType.WORKSHOP]: lavenderDotBg,
|
|
74
72
|
[stageFocusType.CELLAR]: floorboardBg,
|
|
@@ -81,11 +79,13 @@ export const Stage = ({
|
|
|
81
79
|
// filter (see seasonFilterMap) applied via the `.stage-background` layer
|
|
82
80
|
// below - scoped to just the background, not the crop/cow/tree sprites
|
|
83
81
|
// rendered on top of it.
|
|
84
|
-
const hasSeasonalColorShift = (
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
82
|
+
const hasSeasonalColorShift = (
|
|
83
|
+
[
|
|
84
|
+
stageFocusType.FIELD,
|
|
85
|
+
stageFocusType.COW_PEN,
|
|
86
|
+
stageFocusType.FOREST,
|
|
87
|
+
] as string[]
|
|
88
|
+
).includes(stageFocus)
|
|
89
89
|
|
|
90
90
|
return (
|
|
91
91
|
<Div
|
|
@@ -230,15 +230,6 @@ export const Stage = ({
|
|
|
230
230
|
)
|
|
231
231
|
}
|
|
232
232
|
|
|
233
|
-
Stage.propTypes = {
|
|
234
|
-
dayCount: number.isRequired,
|
|
235
|
-
field: arrayOf(array).isRequired,
|
|
236
|
-
isMenuOpen: bool,
|
|
237
|
-
stageFocus: string.isRequired,
|
|
238
|
-
useAlternateEndDayButtonPosition: bool,
|
|
239
|
-
viewTitle: string.isRequired,
|
|
240
|
-
}
|
|
241
|
-
|
|
242
233
|
export default function Consumer(props: Partial<Parameters<typeof Stage>[0]>) {
|
|
243
234
|
return (
|
|
244
235
|
<FarmhandContext.Consumer>
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
-
import { array, object, number, string } from 'prop-types'
|
|
3
2
|
import classNames from 'classnames'
|
|
4
3
|
import Table from '@mui/material/Table/index.js'
|
|
5
4
|
import TableBody from '@mui/material/TableBody/index.js'
|
|
@@ -83,7 +82,6 @@ export const StatsView = ({
|
|
|
83
82
|
</TableRow>
|
|
84
83
|
<Tooltip
|
|
85
84
|
{...{
|
|
86
|
-
arrow: true,
|
|
87
85
|
placement: 'top',
|
|
88
86
|
title: FARM_PRODUCTS_TOOLTIP_TEXT,
|
|
89
87
|
}}
|
|
@@ -99,7 +97,6 @@ export const StatsView = ({
|
|
|
99
97
|
</Tooltip>
|
|
100
98
|
<Tooltip
|
|
101
99
|
{...{
|
|
102
|
-
arrow: true,
|
|
103
100
|
placement: 'top',
|
|
104
101
|
title: FARM_PRODUCTS_TOOLTIP_TEXT,
|
|
105
102
|
}}
|
|
@@ -123,7 +120,6 @@ export const StatsView = ({
|
|
|
123
120
|
</TableRow>
|
|
124
121
|
<Tooltip
|
|
125
122
|
{...{
|
|
126
|
-
arrow: true,
|
|
127
123
|
placement: 'top',
|
|
128
124
|
title: COW_SOLD_TOOLTIP_TEXT,
|
|
129
125
|
}}
|
|
@@ -262,20 +258,6 @@ export const StatsView = ({
|
|
|
262
258
|
</Div>
|
|
263
259
|
)
|
|
264
260
|
|
|
265
|
-
StatsView.propTypes = {
|
|
266
|
-
cowsTraded: number.isRequired,
|
|
267
|
-
farmName: string.isRequired,
|
|
268
|
-
historicalDailyLosses: array.isRequired,
|
|
269
|
-
historicalDailyRevenue: array.isRequired,
|
|
270
|
-
itemsSold: object.isRequired,
|
|
271
|
-
profitabilityStreak: number.isRequired,
|
|
272
|
-
record7dayProfitAverage: number.isRequired,
|
|
273
|
-
recordProfitabilityStreak: number.isRequired,
|
|
274
|
-
revenue: number.isRequired,
|
|
275
|
-
todaysLosses: number.isRequired,
|
|
276
|
-
todaysRevenue: number.isRequired,
|
|
277
|
-
}
|
|
278
|
-
|
|
279
261
|
export default function Consumer(props: Partial<StatsViewProps>) {
|
|
280
262
|
return (
|
|
281
263
|
<FarmhandContext.Consumer>
|
|
@@ -7,7 +7,6 @@ import CardContent from '@mui/material/CardContent/index.js'
|
|
|
7
7
|
import CardHeader from '@mui/material/CardHeader/index.js'
|
|
8
8
|
import CardActions from '@mui/material/CardActions/index.js'
|
|
9
9
|
import Typography from '@mui/material/Typography/index.js'
|
|
10
|
-
import { func, instanceOf, node, number, string } from 'prop-types'
|
|
11
10
|
|
|
12
11
|
import FarmhandContext from '../Farmhand/Farmhand.context.js'
|
|
13
12
|
|
|
@@ -130,17 +129,6 @@ export function TierPurchase({
|
|
|
130
129
|
)
|
|
131
130
|
}
|
|
132
131
|
|
|
133
|
-
TierPurchase.propTypes = {
|
|
134
|
-
description: string,
|
|
135
|
-
onBuyClick: func.isRequired,
|
|
136
|
-
maxedOutPlaceholder: node,
|
|
137
|
-
money: number.isRequired,
|
|
138
|
-
purchasedTier: number.isRequired,
|
|
139
|
-
renderTierLabel: func.isRequired,
|
|
140
|
-
tiers: instanceOf(Map),
|
|
141
|
-
title: string.isRequired,
|
|
142
|
-
}
|
|
143
|
-
|
|
144
132
|
export default function Consumer(
|
|
145
133
|
props: Partial<Parameters<typeof TierPurchase>[0]>
|
|
146
134
|
) {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
-
import PropTypes from 'prop-types'
|
|
3
2
|
import classNames from 'classnames'
|
|
4
3
|
import ReactMarkdown from 'react-markdown'
|
|
5
4
|
|
|
@@ -20,7 +19,7 @@ import { breakpoints } from '../../styles/tokens.js'
|
|
|
20
19
|
|
|
21
20
|
const getTools = memoize(
|
|
22
21
|
(toolLevels: Record<toolType, toolLevel>, stageFocus?: stageFocusType) => {
|
|
23
|
-
const tools: typeof toolsData[keyof typeof toolsData][] = []
|
|
22
|
+
const tools: (typeof toolsData)[keyof typeof toolsData][] = []
|
|
24
23
|
|
|
25
24
|
for (let tool of Object.values(toolsData)) {
|
|
26
25
|
if (toolLevels[tool.type] === toolLevel.UNAVAILABLE) continue
|
|
@@ -66,9 +65,10 @@ export const Toolbelt = ({
|
|
|
66
65
|
sx={{
|
|
67
66
|
display: 'flex',
|
|
68
67
|
flexFlow: 'row',
|
|
69
|
-
[`@media (orientation: landscape) and (min-height: ${breakpoints.largePhone}px)`]:
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
[`@media (orientation: landscape) and (min-height: ${breakpoints.largePhone}px)`]:
|
|
69
|
+
{
|
|
70
|
+
flexFlow: 'column',
|
|
71
|
+
},
|
|
72
72
|
'& button': { flexGrow: 1, margin: '0 0.5em' },
|
|
73
73
|
}}
|
|
74
74
|
>
|
|
@@ -146,11 +146,6 @@ export const Toolbelt = ({
|
|
|
146
146
|
)
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
-
Toolbelt.propTypes = {
|
|
150
|
-
fieldMode: PropTypes.string.isRequired,
|
|
151
|
-
handleFieldModeSelect: PropTypes.func,
|
|
152
|
-
}
|
|
153
|
-
|
|
154
149
|
Toolbelt.defaultProps = {
|
|
155
150
|
handleFieldModeSelect: noop,
|
|
156
151
|
toolLevels: {},
|
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
import { useContext, useEffect } from 'react'
|
|
1
|
+
import { useContext, useEffect, useRef } from 'react'
|
|
2
2
|
// eslint-disable-next-line import/extensions
|
|
3
3
|
import { useRegisterSW } from 'virtual:pwa-register/react'
|
|
4
4
|
|
|
5
5
|
import FarmhandContext from '../Farmhand/Farmhand.context.js'
|
|
6
6
|
|
|
7
|
+
// How long to wait for the new service worker to take over and reload the
|
|
8
|
+
// page before reloading it directly.
|
|
9
|
+
const RELOAD_FALLBACK_DELAY = 1000
|
|
10
|
+
|
|
7
11
|
const UpdateNotifier = () => {
|
|
8
12
|
const {
|
|
13
|
+
gameState: { hasBooted },
|
|
9
14
|
handlers: { handleGameUpdateAvailable },
|
|
10
15
|
} = useContext(FarmhandContext)
|
|
11
16
|
|
|
@@ -14,18 +19,41 @@ const UpdateNotifier = () => {
|
|
|
14
19
|
updateServiceWorker,
|
|
15
20
|
} = useRegisterSW()
|
|
16
21
|
|
|
22
|
+
const hasNotifiedRef = useRef(false)
|
|
23
|
+
|
|
17
24
|
useEffect(() => {
|
|
18
|
-
|
|
25
|
+
// Wait for the saved game to load: restoring it replaces
|
|
26
|
+
// todaysNotifications, which would drop this notification from the
|
|
27
|
+
// Farmer's Log.
|
|
28
|
+
if (!appNeedsUpdate || !hasBooted || hasNotifiedRef.current) {
|
|
19
29
|
return
|
|
20
30
|
}
|
|
21
31
|
|
|
22
|
-
handleGameUpdateAvailable
|
|
32
|
+
// handleGameUpdateAvailable isn't referentially stable, so without this
|
|
33
|
+
// guard every re-render would show the notification again (and the
|
|
34
|
+
// resulting state update would re-render, looping forever).
|
|
35
|
+
hasNotifiedRef.current = true
|
|
36
|
+
|
|
37
|
+
handleGameUpdateAvailable(async () => {
|
|
38
|
+
await updateServiceWorker(true)
|
|
23
39
|
|
|
24
|
-
|
|
40
|
+
// updateServiceWorker only reloads the page once a waiting service
|
|
41
|
+
// worker takes control, which might never happen (e.g. if it was
|
|
42
|
+
// already activated by another tab). Reload anyway so the button
|
|
43
|
+
// always does something.
|
|
44
|
+
setTimeout(() => window.location.reload(), RELOAD_FALLBACK_DELAY)
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
// NOTE: This ensures the game is updated when the user next opens it.
|
|
25
48
|
window.addEventListener('beforeunload', () => {
|
|
26
49
|
updateServiceWorker(true)
|
|
27
50
|
})
|
|
28
|
-
}, [
|
|
51
|
+
}, [
|
|
52
|
+
appNeedsUpdate,
|
|
53
|
+
hasBooted,
|
|
54
|
+
handleGameUpdateAvailable,
|
|
55
|
+
updateServiceWorker,
|
|
56
|
+
])
|
|
29
57
|
|
|
30
58
|
return null
|
|
31
59
|
}
|
|
@@ -4,7 +4,6 @@ import Button from '@mui/material/Button/index.js'
|
|
|
4
4
|
import Card from '@mui/material/Card/index.js'
|
|
5
5
|
import CardHeader from '@mui/material/CardHeader/index.js'
|
|
6
6
|
import CardActions from '@mui/material/CardActions/index.js'
|
|
7
|
-
import { array, func, number, object } from 'prop-types'
|
|
8
7
|
|
|
9
8
|
import IngredientsList from '../IngredientsList/index.js'
|
|
10
9
|
|
|
@@ -85,15 +84,6 @@ export function UpgradePurchase({
|
|
|
85
84
|
)
|
|
86
85
|
}
|
|
87
86
|
|
|
88
|
-
UpgradePurchase.propTypes = {
|
|
89
|
-
handleUpgradeTool: func.isRequired,
|
|
90
|
-
inventory: array.isRequired,
|
|
91
|
-
inventoryLimit: number.isRequired,
|
|
92
|
-
playerInventoryQuantities: object.isRequired,
|
|
93
|
-
toolLevels: object,
|
|
94
|
-
upgrade: object,
|
|
95
|
-
}
|
|
96
|
-
|
|
97
87
|
export default function Consumer(
|
|
98
88
|
props: Partial<Parameters<typeof UpgradePurchase>[0]>
|
|
99
89
|
) {
|
|
@@ -56,14 +56,14 @@ const WineRecipeStub = (
|
|
|
56
56
|
return (
|
|
57
57
|
<FarmhandContext.Provider
|
|
58
58
|
value={
|
|
59
|
-
|
|
59
|
+
{
|
|
60
60
|
gameState: { ...stubGameState, ...state },
|
|
61
61
|
handlers: {
|
|
62
62
|
...stubHandlers,
|
|
63
63
|
...handlers,
|
|
64
64
|
debounced: { ...stubHandlers, ...handlers },
|
|
65
65
|
},
|
|
66
|
-
} as unknown
|
|
66
|
+
} as unknown as React.ContextType<typeof FarmhandContext>
|
|
67
67
|
}
|
|
68
68
|
>
|
|
69
69
|
<WineRecipe
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React, { useContext, useEffect, useState } from 'react'
|
|
2
|
-
import { oneOf } from 'prop-types'
|
|
3
2
|
import Card from '@mui/material/Card/index.js'
|
|
4
3
|
import CardHeader from '@mui/material/CardHeader/index.js'
|
|
5
4
|
import CardActions from '@mui/material/CardActions/index.js'
|
|
@@ -142,7 +141,3 @@ export const WineRecipe = ({ wineVariety }: { wineVariety: grapeVariety }) => {
|
|
|
142
141
|
</Card>
|
|
143
142
|
)
|
|
144
143
|
}
|
|
145
|
-
|
|
146
|
-
WineRecipe.propTypes = {
|
|
147
|
-
wineVariety: oneOf(Object.keys(grapeVariety)),
|
|
148
|
-
}
|
|
@@ -15,9 +15,8 @@ export const WineRecipeList = () => {
|
|
|
15
15
|
gameState: { itemsSold },
|
|
16
16
|
} = useContext(FarmhandContext)
|
|
17
17
|
|
|
18
|
-
const wineVarietiesAvailableToMake =
|
|
19
|
-
itemsSold
|
|
20
|
-
)
|
|
18
|
+
const wineVarietiesAvailableToMake =
|
|
19
|
+
getWineVarietiesAvailableToMake(itemsSold)
|
|
21
20
|
|
|
22
21
|
const [searchQuery, setSearchQuery] = useState('')
|
|
23
22
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
-
import { number, array, object } from 'prop-types'
|
|
3
2
|
|
|
4
3
|
import Card from '@mui/material/Card/index.js'
|
|
5
4
|
import CardContent from '@mui/material/CardContent/index.js'
|
|
@@ -73,10 +72,3 @@ export function ForgeTabPanel({
|
|
|
73
72
|
</TabPanel>
|
|
74
73
|
)
|
|
75
74
|
}
|
|
76
|
-
|
|
77
|
-
ForgeTabPanel.propTypes = {
|
|
78
|
-
currentTab: number.isRequired,
|
|
79
|
-
index: number.isRequired,
|
|
80
|
-
learnedForgeRecipes: array.isRequired,
|
|
81
|
-
toolLevels: object.isRequired,
|
|
82
|
-
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
-
import { number, array } from 'prop-types'
|
|
3
2
|
|
|
4
3
|
import Card from '@mui/material/Card/index.js'
|
|
5
4
|
import CardContent from '@mui/material/CardContent/index.js'
|
|
@@ -48,9 +47,3 @@ export function KitchenTabPanel({
|
|
|
48
47
|
</TabPanel>
|
|
49
48
|
)
|
|
50
49
|
}
|
|
51
|
-
|
|
52
|
-
KitchenTabPanel.propTypes = {
|
|
53
|
-
currentTab: number.isRequired,
|
|
54
|
-
index: number.isRequired,
|
|
55
|
-
learnedKitchenRecipes: array.isRequired,
|
|
56
|
-
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
-
import { number, array } from 'prop-types'
|
|
3
2
|
|
|
4
3
|
import Card from '@mui/material/Card/index.js'
|
|
5
4
|
import CardContent from '@mui/material/CardContent/index.js'
|
|
@@ -48,9 +47,3 @@ export function RecyclingTabPanel({
|
|
|
48
47
|
</TabPanel>
|
|
49
48
|
)
|
|
50
49
|
}
|
|
51
|
-
|
|
52
|
-
RecyclingTabPanel.propTypes = {
|
|
53
|
-
currentTab: number.isRequired,
|
|
54
|
-
index: number.isRequired,
|
|
55
|
-
learnedRecipes: array.isRequired,
|
|
56
|
-
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
-
import { node, number } from 'prop-types'
|
|
3
2
|
|
|
4
3
|
interface TabPanelProps {
|
|
5
4
|
children?: React.ReactNode
|
|
@@ -24,12 +23,6 @@ export const TabPanel = (props: TabPanelProps) => {
|
|
|
24
23
|
)
|
|
25
24
|
}
|
|
26
25
|
|
|
27
|
-
TabPanel.propTypes = {
|
|
28
|
-
children: node,
|
|
29
|
-
index: number.isRequired,
|
|
30
|
-
value: number.isRequired,
|
|
31
|
-
}
|
|
32
|
-
|
|
33
26
|
export const a11yProps = (index: number) => ({
|
|
34
27
|
id: `workshop-tab-${index}`,
|
|
35
28
|
'aria-controls': `workshop-tabpanel-${index}`,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
-
import { number, array } from 'prop-types'
|
|
3
2
|
|
|
4
3
|
import Card from '@mui/material/Card/index.js'
|
|
5
4
|
import CardContent from '@mui/material/CardContent/index.js'
|
|
@@ -48,9 +47,3 @@ export function WoodChipperTabPanel({
|
|
|
48
47
|
</TabPanel>
|
|
49
48
|
)
|
|
50
49
|
}
|
|
51
|
-
|
|
52
|
-
WoodChipperTabPanel.propTypes = {
|
|
53
|
-
currentTab: number.isRequired,
|
|
54
|
-
index: number.isRequired,
|
|
55
|
-
learnedRecipes: array.isRequired,
|
|
56
|
-
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
-
import { number, object } from 'prop-types'
|
|
3
2
|
import Tab from '@mui/material/Tab/index.js'
|
|
4
3
|
import Tabs from '@mui/material/Tabs/index.js'
|
|
5
4
|
|
|
@@ -115,14 +114,6 @@ const Workshop = ({
|
|
|
115
114
|
)
|
|
116
115
|
}
|
|
117
116
|
|
|
118
|
-
Workshop.propTypes = {
|
|
119
|
-
learnedRecipes: object.isRequired,
|
|
120
|
-
purchasedComposter: number,
|
|
121
|
-
purchasedSmelter: number,
|
|
122
|
-
purchasedWoodChipper: number,
|
|
123
|
-
toolLevels: object.isRequired,
|
|
124
|
-
}
|
|
125
|
-
|
|
126
117
|
export default function Consumer(
|
|
127
118
|
props: Partial<Parameters<typeof Workshop>[0]>
|
|
128
119
|
) {
|
|
@@ -17,7 +17,7 @@ export function getUpgradesAvailable({
|
|
|
17
17
|
}: GetUpgradesAvailableArgs): farmhand.upgradesMetadatum[] {
|
|
18
18
|
let upgradesAvailable: farmhand.upgradesMetadatum[] = []
|
|
19
19
|
|
|
20
|
-
const typedToolUpgrades =
|
|
20
|
+
const typedToolUpgrades = toolUpgrades as unknown as Record<
|
|
21
21
|
string,
|
|
22
22
|
Record<string, farmhand.upgradesMetadatum>
|
|
23
23
|
>
|