Skip to content

Commit

Permalink
Bubble of a growing population (#627)
Browse files Browse the repository at this point in the history
Closes #607

#### What else should be done
- [x] Setting the correct animation for bubbles.
- [x] If possible, add animations for `RealmsBar`. `RealmBarIcon` should
move more smoothly when the population is changed.
- [ ] After joining the realm, show a bubble instantly.
- [ ] Improve intervals for realms.
- [x] Adding bubble to the modal window.


### What

The app should be more lively. This PR adds +1 bubble over a realm every
time somebody joins. The bubble should be visible over the realm on the
map but also in the modal window. The population is fetched from the
contracts every minute. We shouldn't show 20 bubbles at the same time
and then not show anything for 1 minute. We should spread out the number
of bubbles we show.

- So let's add a variable `displayedPopulation` to increment it and show
the bubbles with the correct interval.
- Intervals should be different for the realms to make the app more
lively.
- When we init game data, we should refresh the `displayedPopulation`
and align it with the true number.

### Testing

Let's use a patch file to increase the population and do tests. Use the
following file:

[increase-population.patch](https://github.com/tahowallet/dapp/files/13249010/increase-population.patch)
The population is increased randomly every minute.

```
git apply increase-population.patch
```

- [ ] When a user joins the region, a bubble should show up immediately
in the modal.
- [ ] Bubbles should occur at different intervals between realms.
- [ ] After refreshing the page, the population should show the correct
number.
  • Loading branch information
jagodarybacka authored Nov 16, 2023
2 parents 5b6cc94 + 4851cbe commit 28b01f4
Show file tree
Hide file tree
Showing 33 changed files with 643 additions and 180 deletions.
56 changes: 42 additions & 14 deletions src/redux-state/selectors/population.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,33 @@
import { createSelector } from "@reduxjs/toolkit"
import { RealmData } from "shared/types"
import {
getDisplayedPopulationOfRealms,
getPopulationOfRealms,
} from "redux-state/utils/population"
import { selectRealmById, selectRealms } from "./realm"

const getPopulationOfRealms = (realms: RealmData[]) =>
realms.map((realm) => realm.population)
type PopulationKey = "population" | "displayedPopulation"

export const selectSortedPopulation = createSelector(selectRealms, (realms) => {
const realmsData = Object.entries(realms).map(([id, data]) => ({
id,
...data,
}))
const getPopulationById = (key: PopulationKey) =>
createSelector(selectRealmById, (realm) => realm?.[key] ?? 0)

return realmsData.sort((a, b) => a.population - b.population)
})
const sortPopulation = (key: PopulationKey) =>
createSelector(selectRealms, (realms) => {
const realmsData = Object.entries(realms).map(([id, data]) => ({
id,
...data,
}))

export const selectPopulationById = createSelector(
selectRealmById,
(realm) => realm?.population ?? 0
return realmsData.sort((a, b) => a[key] - b[key])
})

export const selectSortedPopulation = sortPopulation("population")
export const selectSortedDisplayedPopulation = sortPopulation(
"displayedPopulation"
)

export const selectPopulationById = getPopulationById("population")
export const selectDisplayedPopulationById = getPopulationById(
"displayedPopulation"
)

export const selectTotalPopulation = createSelector(
Expand All @@ -25,7 +36,24 @@ export const selectTotalPopulation = createSelector(
realms.length ? getPopulationOfRealms(realms).reduce((a, b) => a + b) : 0
)

export const selectTotalDisplayedPopulation = createSelector(
selectSortedDisplayedPopulation,
(realms) =>
realms.length
? getDisplayedPopulationOfRealms(realms).reduce((a, b) => a + b)
: 0
)

export const selectMaxPopulation = createSelector(
selectSortedPopulation,
(realms) => (realms.length ? Math.max(...getPopulationOfRealms(realms)) : 0)
(realms) =>
realms.length ? getPopulationOfRealms(realms)[realms.length - 1] : 0
)

export const selectMaxDisplayedPopulation = createSelector(
selectSortedDisplayedPopulation,
(realms) =>
realms.length
? getDisplayedPopulationOfRealms(realms)[realms.length - 1]
: 0
)
14 changes: 12 additions & 2 deletions src/redux-state/slices/island.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ import {
LeaderboardData,
UnclaimedXpData,
OverlayType,
RealmData,
RealmDataWithId,
SeasonInfo,
RealmDataById,
} from "shared/types"

export type IslandModeType = "default" | "join-realm"

export type IslandState = {
mode: IslandModeType
overlay: OverlayType
realms: { [id: string]: RealmData }
realms: RealmDataById
leaderboards: { [id: string]: LeaderboardData }
unclaimedXp: { [id: string]: UnclaimedXpData[] }
stakingRealmId: string | null
Expand Down Expand Up @@ -75,6 +75,15 @@ const islandSlice = createSlice({
immerState.realms[realmPopulation.id].population =
realmPopulation.population
},
setRealmDisplayedPopulation: (
immerState,
{
payload: realmPopulation,
}: { payload: { id: string; population: number } }
) => {
immerState.realms[realmPopulation.id].displayedPopulation =
realmPopulation.population
},
setRealmXpAllocatable: (
immerState,
{
Expand Down Expand Up @@ -139,6 +148,7 @@ export const {
resetIslandDisplay,
resetIslandAccount,
setRealmPopulation,
setRealmDisplayedPopulation,
setRealmXpAllocatable,
setRealmsData,
setDisplayedRealmId,
Expand Down
15 changes: 13 additions & 2 deletions src/redux-state/thunks/island.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
setRealmXpAllocatable,
setRealmsData,
setSeasonInfo,
setRealmDisplayedPopulation,
} from "redux-state/slices/island"
import {
REALMS_WITH_CONTRACT_NAME,
Expand All @@ -29,7 +30,11 @@ import {
UnclaimedXpData,
} from "shared/types"
import { updateTransactionStatus } from "redux-state/slices/wallet"
import { bigIntToUserAmount, getAllowanceTransactionID } from "shared/utils"
import {
bigIntToUserAmount,
getAllowanceTransactionID,
isDisplayedPopulationAvailable,
} from "shared/utils"
import {
getRealmLeaderboardData,
getUserLeaderboardRank,
Expand Down Expand Up @@ -107,8 +112,14 @@ export const fetchPopulation = createDappAsyncThunk(
realmsWithAddress,
})

const displayedPopulationAvailable = isDisplayedPopulationAvailable(realms)

if (result) {
result.forEach((data) => dispatch(setRealmPopulation(data)))
result.forEach((data) => {
dispatch(setRealmPopulation(data))
if (!displayedPopulationAvailable)
dispatch(setRealmDisplayedPopulation(data))
})
}

return !!result
Expand Down
7 changes: 7 additions & 0 deletions src/redux-state/utils/population.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { RealmData } from "shared/types"

export const getPopulationOfRealms = (realms: RealmData[]) =>
realms.map((realm) => realm.population)

export const getDisplayedPopulationOfRealms = (realms: RealmData[]) =>
realms.map((realm) => realm.displayedPopulation)
31 changes: 31 additions & 0 deletions src/shared/assets/partners/arbitrum-population.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 31 additions & 0 deletions src/shared/assets/partners/cyberconnect-population.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 31 additions & 0 deletions src/shared/assets/partners/frax-population.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 31 additions & 0 deletions src/shared/assets/partners/galxe-population.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 31 additions & 0 deletions src/shared/assets/partners/gitcoin-population.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
48 changes: 48 additions & 0 deletions src/shared/components/RealmCutout/Bubble.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { animated, easings, useSpring } from "@react-spring/web"
import React, { useEffect, useState } from "react"
import { getRealmPopulationIcon } from "shared/constants"
import { usePopulationBubble } from "shared/hooks"

export const STYLE = {
default: { opacity: 0, transform: "translateY(150px)" },
highlight: { opacity: 1, transform: "translateY(50px)" },
}

export const BUBBLE_CONFIG = {
precision: 0.1,
duration: 2000,
easing: easings.easeOutCubic,
}

export default function Bubble({ realmId }: { realmId: string }) {
const { showBubble, setShowBubble } = usePopulationBubble(realmId)

const [iconSrc, setIconSrc] = useState<string | null>(null)

useEffect(() => {
const icon = getRealmPopulationIcon(realmId)
setIconSrc(icon)
}, [realmId])

const [bubbleProps] = useSpring(
() => ({
from: STYLE.default,
to: showBubble ? STYLE.highlight : STYLE.default,
config: BUBBLE_CONFIG,
onRest: () => setShowBubble(false),
}),
[showBubble]
)

if (!iconSrc) return null

return (
<animated.div
style={{ ...bubbleProps, left: "220px", position: "absolute", zIndex: 2 }}
>
<div>
<img src={iconSrc} height={24} width={24} alt="Bubble" />
</div>
</animated.div>
)
}
2 changes: 2 additions & 0 deletions src/shared/components/RealmCutout/RealmCutout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
useDappSelector,
} from "redux-state"
import RealmPin from "./RealmPin"
import Bubble from "./Bubble"

const CUTOUT_HEIGHT = 208
const CUTOUT_WIDTH = 356
Expand All @@ -27,6 +28,7 @@ export default function RealmCutout() {
return (
<>
<div className="realm_cutout">
<Bubble realmId={realmId} />
{isStakedRealm && <RealmPin avatar={walletAvatar} />}
<svg
viewBox={`0 0 ${Math.ceil(pathData.w * 0.25)} ${Math.ceil(
Expand Down
4 changes: 3 additions & 1 deletion src/shared/components/RealmModal/RealmHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ export default function RealmHeader() {
/>
Population
</span>
<span>{separateThousandsByComma(realm?.population ?? 0)}</span>
<span>
{separateThousandsByComma(realm?.displayedPopulation ?? 0)}
</span>
</div>
<div className="tag column">
<span
Expand Down
Loading

0 comments on commit 28b01f4

Please sign in to comment.