From 564e4e496b237a29383d724b9772d390a63aacd5 Mon Sep 17 00:00:00 2001 From: KingRainbow44 Date: Thu, 11 May 2023 22:52:09 -0400 Subject: [PATCH] Check if a command should be copied or HTTP should be used --- src/handbook/src/backend/commands.ts | 23 ++++++++++ src/handbook/src/backend/server.ts | 7 ++- src/handbook/src/ui/components/TextState.tsx | 47 ++++++++++++++++++++ src/handbook/src/ui/widgets/ItemCard.tsx | 32 +++++++++---- src/handbook/src/utils.ts | 10 +++++ 5 files changed, 110 insertions(+), 9 deletions(-) create mode 100644 src/handbook/src/backend/commands.ts create mode 100644 src/handbook/src/ui/components/TextState.tsx diff --git a/src/handbook/src/backend/commands.ts b/src/handbook/src/backend/commands.ts new file mode 100644 index 000000000..e7571d33c --- /dev/null +++ b/src/handbook/src/backend/commands.ts @@ -0,0 +1,23 @@ +/** + * Validates a number. + * + * @param value The number to validate. + */ +function invalid(value: number): boolean { + return isNaN(value) || value < 0; +} + +/** + * Generates a basic give command. + */ +function basicGive(item: number, amount = 1): string { + // Validate the numbers. + if (invalid(item) || invalid(amount)) + return "Invalid arguments."; + + return `/give ${item} x${amount}`; +} + +export const give = { + basic: basicGive +}; diff --git a/src/handbook/src/backend/server.ts b/src/handbook/src/backend/server.ts index f317e73b5..7bf1240ee 100644 --- a/src/handbook/src/backend/server.ts +++ b/src/handbook/src/backend/server.ts @@ -1,6 +1,8 @@ import type { CommandResponse } from "@backend/types"; +import emitter from "@backend/events"; let targetPlayer = 0; // The UID of the target player. +export let connected = false; // Whether the server is connected. /** * Sets the target player. @@ -9,7 +11,10 @@ let targetPlayer = 0; // The UID of the target player. */ export function setTargetPlayer(player: number): void { targetPlayer = player; - console.log(`Target Player is now: ${targetPlayer}`); + connected = !isNaN(player) && player > 0; + + // Emit the connected event. + emitter.emit("connected", connected); } /** diff --git a/src/handbook/src/ui/components/TextState.tsx b/src/handbook/src/ui/components/TextState.tsx new file mode 100644 index 000000000..7ab52fcef --- /dev/null +++ b/src/handbook/src/ui/components/TextState.tsx @@ -0,0 +1,47 @@ +import React from "react"; + +import emitter from "@backend/events"; + +interface IProps { + event: string; + text1: string; + text2: string; +} + +interface IState { + state: boolean; +} + +class TextState extends React.Component { + constructor(props: IProps) { + super(props); + + this.state = { + state: false + }; + } + + /** + * Updates the current state. + * @private + */ + private update(state: boolean): void { + this.setState({ state }); + } + + componentDidMount(): void { + emitter.on(this.props.event, this.update.bind(this)); + } + + componentWillUnmount(): void { + emitter.off(this.props.event, this.update); + } + + render() { + return this.state.state ? + this.props.text2 : + this.props.text1; + } +} + +export default TextState; diff --git a/src/handbook/src/ui/widgets/ItemCard.tsx b/src/handbook/src/ui/widgets/ItemCard.tsx index af42dd7fe..ff47ec9f2 100644 --- a/src/handbook/src/ui/widgets/ItemCard.tsx +++ b/src/handbook/src/ui/widgets/ItemCard.tsx @@ -1,9 +1,12 @@ import React from "react"; +import TextState from "@components/TextState"; + import type { Item as ItemType, ItemInfo } from "@backend/types"; import { itemTypeToString } from "@backend/types"; -import { itemIcon } from "@app/utils"; -import { giveItem } from "@backend/server"; +import { copyToClipboard, itemIcon } from "@app/utils"; +import { connected, giveItem } from "@backend/server"; +import { give } from "@backend/commands"; import "@css/widgets/ItemCard.scss"; @@ -82,10 +85,17 @@ class ItemCard extends React.Component { * @private */ private async addToInventory(): Promise { - await giveItem( - this.props.item?.id ?? 102, - typeof this.state.count == "string" ? parseInt(this.state.count) : this.state.count - ); + const item = this.props.item?.id ?? 102; + const amount = typeof this.state.count == "string" ? + parseInt(this.state.count) : + this.state.count; + + if (connected) { + await giveItem(item, amount); + } else { + await copyToClipboard( + give.basic(item, amount)); + } } componentDidUpdate(prevProps: Readonly, prevState: Readonly, snapshot?: any) { @@ -155,8 +165,14 @@ class ItemCard extends React.Component { - diff --git a/src/handbook/src/utils.ts b/src/handbook/src/utils.ts index 5ec928217..39e2ca9cd 100644 --- a/src/handbook/src/utils.ts +++ b/src/handbook/src/utils.ts @@ -134,3 +134,13 @@ export async function fetchEntityData(entity: Entity): Promise { .then((res) => res.json()) .catch(() => {}); } + +/** + * Attempts to copy text to the clipboard. + * Uses the Clipboard API. + * + * @param text The text to copy. + */ +export async function copyToClipboard(text: string): Promise { + await navigator.clipboard.writeText(text); +}