Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Whitelist #2569

Merged
merged 2 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions client/src/dojo/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ export async function setup(config: DojoConfig & { state: AppStore }) {
"s0_eternum-Trade",
"s0_eternum-Structure",
"s0_eternum-Battle",
"s0_eternum-Guild",
],
},
},
Expand Down
2 changes: 2 additions & 0 deletions client/src/hooks/helpers/use-resource-arrivals.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export type ArrivalInfo = {
isOwner: boolean;
hasResources: boolean;
isHome: boolean;
originOwner: string;
// resources: Resource[];
};

Expand Down Expand Up @@ -95,6 +96,7 @@ const usePlayerArrivals = () => {
isOwner: true,
position: { x: position.x, y: position.y },
hasResources,
originOwner: owner?.address.toString(),
isHome,
};
},
Expand Down
1 change: 1 addition & 0 deletions client/src/hooks/helpers/useGuilds.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -308,5 +308,6 @@ export const useGuilds = () => {
usePlayerWhitelist,
getGuildFromEntityId,
getPlayersInPlayersGuild,
getPlayerListInGuild,
};
};
59 changes: 50 additions & 9 deletions client/src/ui/components/trading/ResourceArrivals.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { addToSubscription } from "@/dojo/queries";
import { useDojo } from "@/hooks/context/DojoContext";
import { ArrivalInfo } from "@/hooks/helpers/use-resource-arrivals";
import { useGuilds } from "@/hooks/helpers/useGuilds";
import useNextBlockTimestamp from "@/hooks/useNextBlockTimestamp";
import Button from "@/ui/elements/Button";
import { Checkbox } from "@/ui/elements/Checkbox";
import { Headline } from "@/ui/elements/Headline";
import { HintModalButton } from "@/ui/elements/HintModalButton";
import { memo, useEffect, useState } from "react";
import { memo, useEffect, useMemo, useState } from "react";
import { create } from "zustand";
import { EntityArrival } from "../entities/Entity";
import { HintSection } from "../hints/HintModal";
Expand All @@ -27,16 +28,39 @@ const useSubscribedIdsStore = create<SubscribedIdsStore>((set) => ({

export const AllResourceArrivals = memo(
({ arrivals, className = "" }: { arrivals: ArrivalInfo[]; className?: string }) => {
const dojo = useDojo();
const [displayCount, setDisplayCount] = useState(DISPLAYED_ARRIVALS);
const [showOnlyArrived, setShowOnlyArrived] = useState(true);
const [showOnlyGuildMembers, setShowOnlyGuildMembers] = useState(false);

const { nextBlockTimestamp } = useNextBlockTimestamp();
const { subscribedIds, addSubscribedIds } = useSubscribedIdsStore();

const { getPlayersInPlayersGuild, getPlayerListInGuild } = useGuilds();

const {
account: { account },
network: { toriiClient, contractComponents },
} = useDojo();

const savedGuilds = localStorage.getItem("WHITELIST")?.split(",");

const whitelistedGuilds = useMemo(() => {
return [
...(savedGuilds?.flatMap((guildId) => getPlayerListInGuild(Number(guildId))) || []),
...getPlayersInPlayersGuild(BigInt(account?.address || 0n)).map((player) => player.address),
];
}, [account?.address, savedGuilds]);

useEffect(() => {
// Create a single Set from newIds for O(1) lookup
const newIdsSet = new Set(arrivals.map((arrival) => arrival.entityId.toString()));

const newIdsSet = new Set(
arrivals
.filter(
(arrival) => whitelistedGuilds.includes(arrival.originOwner) || arrival.originOwner === account.address,
)
.map((arrival) => arrival.entityId.toString()),
);

// Find ids that aren't already subscribed
const unsubscribedIds = Array.from(newIdsSet).filter((id) => !subscribedIds.has(id));
Expand All @@ -47,15 +71,28 @@ export const AllResourceArrivals = memo(
addSubscribedIds(unsubscribedIds);

// Move API call outside of state updates
addToSubscription(dojo.network.toriiClient, dojo.network.contractComponents as any, unsubscribedIds).catch(
(error) => console.error("Fetch failed", error),
addToSubscription(toriiClient, contractComponents as any, unsubscribedIds).catch((error) =>
console.error("Fetch failed", error),
);
console.log("AddToSubscriptionStart - 5");
}, [arrivals, subscribedIds, addSubscribedIds]);

const filteredArrivals = showOnlyArrived
? arrivals.filter((arrival) => arrival.arrivesAt < nextBlockTimestamp)
: arrivals;
const guildPlayers = getPlayersInPlayersGuild(BigInt(account?.address || 0n)).map((player) => player.address);

const filteredArrivals = useMemo(
() =>
arrivals.filter((arrival) => {
const timeCondition = showOnlyArrived ? arrival.arrivesAt < nextBlockTimestamp : true;
// Add a check for empty guildPlayers array
const guildCondition = showOnlyGuildMembers
? guildPlayers.length === 0
? true // If no guild players, show all arrivals
: guildPlayers.includes(arrival.originOwner)
: true;
return timeCondition && guildCondition;
}),
[arrivals, showOnlyArrived, showOnlyGuildMembers, nextBlockTimestamp, guildPlayers],
);

const displayedArrivals = filteredArrivals.slice(0, displayCount);
const hasMore = displayCount < filteredArrivals.length;
Expand All @@ -72,11 +109,15 @@ export const AllResourceArrivals = memo(
<HintModalButton section={HintSection.Transfers} />
</div>
</Headline>
<div className="px-2 pb-2">
<div className="px-2 pb-2 flex flex-col gap-2">
<label className="flex items-center space-x-1 text-xs">
<Checkbox enabled={showOnlyArrived} onClick={() => setShowOnlyArrived(!showOnlyArrived)} />
<span>Show only arrived</span>
</label>
<label className="flex items-center space-x-1 text-xs">
<Checkbox enabled={showOnlyGuildMembers} onClick={() => setShowOnlyGuildMembers(!showOnlyGuildMembers)} />
<span>Show only guild members</span>
</label>
</div>
{displayedArrivals.map((arrival) => (
<EntityArrival arrival={arrival} key={arrival.entityId} />
Expand Down
48 changes: 46 additions & 2 deletions client/src/ui/modules/settings/Settings.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { ReactComponent as Controller } from "@/assets/icons/Controller.svg";
import { ReactComponent as Copy } from "@/assets/icons/common/copy.svg";
import { ReactComponent as Next } from "@/assets/icons/common/fast-forward.svg";
import { ReactComponent as Muted } from "@/assets/icons/common/muted.svg";
import { ReactComponent as Unmuted } from "@/assets/icons/common/unmuted.svg";
import { ReactComponent as Controller } from "@/assets/icons/Controller.svg";
import { ReactComponent as DojoMark } from "@/assets/icons/dojo-mark-full-dark.svg";
import { ReactComponent as RealmsWorld } from "@/assets/icons/rw-logo.svg";
import { useDojo } from "@/hooks/context/DojoContext";
import { useGuilds } from "@/hooks/helpers/useGuilds";
import { useRealm } from "@/hooks/helpers/useRealm";
import useUIStore from "@/hooks/store/useUIStore";
import { useMusicPlayer } from "@/hooks/useMusic";
Expand Down Expand Up @@ -61,7 +62,29 @@ export const SettingsWindow = () => {

const isOpen = useUIStore((state) => state.isPopupOpen(settings));

const GRAPHICS_SETTING = localStorage.getItem("GRAPHICS_SETTING") as GraphicsSettings || GraphicsSettings.HIGH;
const GRAPHICS_SETTING = (localStorage.getItem("GRAPHICS_SETTING") as GraphicsSettings) || GraphicsSettings.HIGH;

const { useGuildQuery } = useGuilds();
const { guilds } = useGuildQuery();
const [selectedGuilds, setSelectedGuilds] = useState<string[]>(() => {
const savedGuilds = localStorage.getItem("WHITELIST");
return savedGuilds ? savedGuilds.split(",") : [];
});

const handleGuildSelect = (guildId: string) => {
setSelectedGuilds((prev) => {
const newGuilds = prev.includes(guildId) ? prev.filter((id) => id !== guildId) : [...prev, guildId];
localStorage.setItem("WHITELIST", newGuilds.join(","));
toast(prev.includes(guildId) ? "Guild removed from whitelist!" : "Guild added to whitelist!");
return newGuilds;
});
};

const handleClearGuilds = () => {
setSelectedGuilds([]);
localStorage.removeItem("WHITELIST");
toast("Guild whitelist cleared!");
};

return (
<OSWindow onClick={() => togglePopup(settings)} show={isOpen} title={settings}>
Expand Down Expand Up @@ -126,6 +149,27 @@ export const SettingsWindow = () => {
</div>
<Headline>Sound</Headline>

<div className="flex flex-col gap-2">
<h5>Whitelist guilds</h5>
<div className="flex flex-wrap gap-2">
{guilds.map((guild) => (
<Button
size="xs"
key={guild.entityId}
variant={selectedGuilds.includes(guild.entityId.toString()) ? "success" : "outline"}
onClick={() => handleGuildSelect(guild.entityId.toString())}
>
{guild.name}
</Button>
))}
</div>
{selectedGuilds.length > 0 && (
<Button size="xs" variant="danger" onClick={handleClearGuilds} className="self-start">
Clear All
</Button>
)}
</div>

<div className="flex space-x-2">
{isSoundOn ? (
<Button variant="outline" onClick={() => toggleSound()}>
Expand Down
Loading