From dad0418ab17f1e8145d28916f4ac0917e7485988 Mon Sep 17 00:00:00 2001 From: Scott Benton Date: Sun, 26 Nov 2023 10:36:38 -0500 Subject: [PATCH 1/2] feat(notes): Gave notes and roll log section a max height on mobile --- .../features/charactersAndCampaigns/GameLog/GameLog.tsx | 6 +++--- .../features/charactersAndCampaigns/Notes/Notes.tsx | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/components/features/charactersAndCampaigns/GameLog/GameLog.tsx b/src/components/features/charactersAndCampaigns/GameLog/GameLog.tsx index 30b2a3df..40194f9f 100644 --- a/src/components/features/charactersAndCampaigns/GameLog/GameLog.tsx +++ b/src/components/features/charactersAndCampaigns/GameLog/GameLog.tsx @@ -1,7 +1,7 @@ import { useEffect, useState } from "react"; import { useStore } from "stores/store"; import { Virtuoso } from "react-virtuoso"; -import { LinearProgress } from "@mui/material"; +import { Box, LinearProgress } from "@mui/material"; import { GameLogEntry } from "./GameLogEntry"; const MAX_ITEMS = 1000000000; @@ -30,7 +30,7 @@ export function GameLog() { }, [logLength]); return ( - <> + {loading && } } /> - + ); } diff --git a/src/components/features/charactersAndCampaigns/Notes/Notes.tsx b/src/components/features/charactersAndCampaigns/Notes/Notes.tsx index d53604ef..6740db8a 100644 --- a/src/components/features/charactersAndCampaigns/Notes/Notes.tsx +++ b/src/components/features/charactersAndCampaigns/Notes/Notes.tsx @@ -70,10 +70,9 @@ export function Notes(props: NotesProps) { return ( {(!condensedView || !selectedNoteId) && ( {condensedView && From 9823f3ddcdb95bd4aea09234682525accb7be4f6 Mon Sep 17 00:00:00 2001 From: Scott Benton Date: Mon, 27 Nov 2023 22:16:02 -0500 Subject: [PATCH 2/2] feat(rolls): Added ability to copy rolls to the clipboard --- CHANGELOG.MD | 1 + .../GameLog/GameLogEntry.tsx | 13 +- .../RollDisplay/NormalRollActions.tsx | 149 ++++++++++ .../RollDisplay/RollContainer.tsx | 11 + .../RollDisplay/RollDisplay.tsx | 122 ++++++++ .../RollDisplay/RollResult.tsx | 47 +++ .../RollDisplay/RollTitle.tsx | 47 +++ .../RollDisplay/RollValues.tsx | 102 +++++++ .../RollDisplay/clipboardFormatter.ts | 278 ++++++++++++++++++ .../RollDisplay}/getRollResultLabel.ts | 0 .../RollDisplay/index.ts | 2 + src/components/shared/Layout/Layout.tsx | 2 +- .../RollSnackbarSection.tsx} | 12 +- .../ClockProgressionRollSnackbar.tsx | 92 ------ .../RollSnackbar/OracleTableRollSnackbar.tsx | 90 ------ .../shared/RollSnackbar/RollSnackbar.tsx | 52 ---- .../shared/RollSnackbar/StatRollSnackbar.tsx | 146 --------- .../TrackProgressRollSnackbar.tsx | 99 ------- src/components/shared/RollSnackbar/index.ts | 3 - src/stores/appState/useRoller.ts | 2 +- 20 files changed, 775 insertions(+), 495 deletions(-) create mode 100644 src/components/features/charactersAndCampaigns/RollDisplay/NormalRollActions.tsx create mode 100644 src/components/features/charactersAndCampaigns/RollDisplay/RollContainer.tsx create mode 100644 src/components/features/charactersAndCampaigns/RollDisplay/RollDisplay.tsx create mode 100644 src/components/features/charactersAndCampaigns/RollDisplay/RollResult.tsx create mode 100644 src/components/features/charactersAndCampaigns/RollDisplay/RollTitle.tsx create mode 100644 src/components/features/charactersAndCampaigns/RollDisplay/RollValues.tsx create mode 100644 src/components/features/charactersAndCampaigns/RollDisplay/clipboardFormatter.ts rename src/components/{shared/RollSnackbar => features/charactersAndCampaigns/RollDisplay}/getRollResultLabel.ts (100%) create mode 100644 src/components/features/charactersAndCampaigns/RollDisplay/index.ts rename src/components/shared/{RollSnackbar/RollSnackbarSecton.tsx => Layout/RollSnackbarSection.tsx} (83%) delete mode 100644 src/components/shared/RollSnackbar/ClockProgressionRollSnackbar.tsx delete mode 100644 src/components/shared/RollSnackbar/OracleTableRollSnackbar.tsx delete mode 100644 src/components/shared/RollSnackbar/RollSnackbar.tsx delete mode 100644 src/components/shared/RollSnackbar/StatRollSnackbar.tsx delete mode 100644 src/components/shared/RollSnackbar/TrackProgressRollSnackbar.tsx delete mode 100644 src/components/shared/RollSnackbar/index.ts diff --git a/CHANGELOG.MD b/CHANGELOG.MD index 97fb552f..202f78e0 100644 --- a/CHANGELOG.MD +++ b/CHANGELOG.MD @@ -5,6 +5,7 @@ ### New Features - Added a new beta tests dialog in the user settings menu - this will allow me to test changes before fully releasing them +- Added the ability to copy rolls to the clipboard ### Changes diff --git a/src/components/features/charactersAndCampaigns/GameLog/GameLogEntry.tsx b/src/components/features/charactersAndCampaigns/GameLog/GameLogEntry.tsx index 10fa0efa..485c466b 100644 --- a/src/components/features/charactersAndCampaigns/GameLog/GameLogEntry.tsx +++ b/src/components/features/charactersAndCampaigns/GameLog/GameLogEntry.tsx @@ -1,8 +1,9 @@ import { Box, Typography } from "@mui/material"; -import { RollSnackbar } from "components/shared/RollSnackbar"; import { useEffect } from "react"; import { useStore } from "stores/store"; import { Roll } from "types/DieRolls.type"; +import { RollDisplay } from "../RollDisplay"; +import { NormalRollActions } from "../RollDisplay/NormalRollActions"; export interface GameLogEntryProps { log: Roll; @@ -67,11 +68,11 @@ export function GameLogEntry(props: GameLogEntryProps) { alignItems={isYourEntry ? "flex-end" : "flex-start"} > {rollerName} - - {/* ({ p: 2 })}> - {log.rollLabel} - {log.result} - */} + } + /> {getLogTimeString(log.timestamp)} diff --git a/src/components/features/charactersAndCampaigns/RollDisplay/NormalRollActions.tsx b/src/components/features/charactersAndCampaigns/RollDisplay/NormalRollActions.tsx new file mode 100644 index 00000000..ef254ae2 --- /dev/null +++ b/src/components/features/charactersAndCampaigns/RollDisplay/NormalRollActions.tsx @@ -0,0 +1,149 @@ +import { + Box, + ButtonBase, + ListItemIcon, + ListItemText, + Menu, + MenuItem, +} from "@mui/material"; +import { useId, useRef, useState } from "react"; +import { ROLL_TYPE, Roll } from "types/DieRolls.type"; +import MoreIcon from "@mui/icons-material/MoreHoriz"; +import CopyIcon from "@mui/icons-material/CopyAll"; +import { getRollResultLabel } from "./getRollResultLabel"; +import { useSnackbar } from "providers/SnackbarProvider"; +import { convertRollToClipboard } from "./clipboardFormatter"; + +export interface NormalRollActionsProps { + roll: Roll; +} + +async function pasteRich(rich: string, plain: string) { + if (typeof ClipboardItem !== "undefined") { + // Shiny new Clipboard API, not fully supported in Firefox. + // https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API#browser_compatibility + const html = new Blob([rich], { type: "text/html" }); + const text = new Blob([plain], { type: "text/plain" }); + const data = new ClipboardItem({ "text/html": html, "text/plain": text }); + await navigator.clipboard.write([data]); + } else { + // Fallback using the deprecated `document.execCommand`. + // https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand#browser_compatibility + const cb = (e: ClipboardEvent) => { + e.clipboardData?.setData("text/html", rich); + e.clipboardData?.setData("text/plain", plain); + e.preventDefault(); + }; + document.addEventListener("copy", cb); + document.execCommand("copy"); + document.removeEventListener("copy", cb); + } +} + +export function NormalRollActions(props: NormalRollActionsProps) { + const { roll } = props; + const id = useId(); + const blockQuoteId = `roll-action-copy-${id}`; + + const [isMenuOpen, setIsMenuOpen] = useState(false); + const menuParent = useRef(null); + + const { error, success } = useSnackbar(); + + const handleCopyRoll = () => { + const clipboardData = convertRollToClipboard(roll); + + if (clipboardData) { + pasteRich(clipboardData.rich, clipboardData.plain) + .then(() => { + success("Copied roll to clipboard."); + }) + .catch(() => { + error("Failed to copy roll"); + }); + } else { + error("Copying this roll type is not supported"); + } + }; + + let rollTitle = roll.rollLabel; + let actionContents: string | undefined = undefined; + let challengeContents: string | undefined = undefined; + let result: string | undefined = undefined; + + if (roll.type === ROLL_TYPE.STAT) { + if (roll.moveName) { + rollTitle = `${roll.moveName} (${roll.rollLabel})`; + } + + const rollTotal = roll.action + (roll.modifier ?? 0) + (roll.adds ?? 0); + actionContents = roll.action + ""; + if (roll.modifier || roll.adds) { + actionContents += + (roll.modifier ? ` + ${roll.modifier}` : "") + + (roll.adds ? ` + ${roll.adds}` : "") + + ` = ${rollTotal > 10 ? "10 (Max)" : rollTotal}`; + } + + challengeContents = roll.challenge1 + ", " + roll.challenge2; + + result = getRollResultLabel(roll.result).toLocaleUpperCase(); + } + + return ( + <> + { + evt.stopPropagation(); + setIsMenuOpen(true); + }} + > + + + {isMenuOpen && ( + setIsMenuOpen(false)} + anchorEl={menuParent.current} + > + { + evt.stopPropagation(); + handleCopyRoll(); + setIsMenuOpen(false); + }} + > + + + + Copy Roll Result + + + )} + {/* Copy to clipboard component */} + +

{rollTitle}

+ {actionContents && ( +

+ Action: {actionContents} +

+ )} + {challengeContents && ( +

+ Challenge: {challengeContents} +

+ )} + {result && ( +

+ {result} +

+ )} +
+ + ); +} diff --git a/src/components/features/charactersAndCampaigns/RollDisplay/RollContainer.tsx b/src/components/features/charactersAndCampaigns/RollDisplay/RollContainer.tsx new file mode 100644 index 00000000..b095deba --- /dev/null +++ b/src/components/features/charactersAndCampaigns/RollDisplay/RollContainer.tsx @@ -0,0 +1,11 @@ +import { Box } from "@mui/material"; +import { PropsWithChildren } from "react"; + +export function RollContainer(props: PropsWithChildren) { + const { children } = props; + return ( + + {children} + + ); +} diff --git a/src/components/features/charactersAndCampaigns/RollDisplay/RollDisplay.tsx b/src/components/features/charactersAndCampaigns/RollDisplay/RollDisplay.tsx new file mode 100644 index 00000000..362bc228 --- /dev/null +++ b/src/components/features/charactersAndCampaigns/RollDisplay/RollDisplay.tsx @@ -0,0 +1,122 @@ +import { Box, Card, CardActionArea } from "@mui/material"; +import { ROLL_TYPE, Roll } from "types/DieRolls.type"; +import { RollTitle } from "./RollTitle"; +import { RollValues } from "./RollValues"; +import { RollResult } from "./RollResult"; +import { getRollResultLabel } from "./getRollResultLabel"; +import { RollContainer } from "./RollContainer"; +import { ReactNode } from "react"; + +export interface RollDisplayProps { + roll: Roll; + onClick?: () => void; + isExpanded: boolean; + actions?: ReactNode; +} + +export function RollDisplay(props: RollDisplayProps) { + const { roll, onClick, isExpanded, actions } = props; + + return ( + ({ + backgroundColor: theme.palette.darkGrey.dark, + color: theme.palette.darkGrey.contrastText, + display: "flex", + flexDirection: "column", + alignItems: "flex-start", + })} + > + + {roll.type === ROLL_TYPE.STAT && ( + <> + + + + + + + )} + {roll.type === ROLL_TYPE.TRACK_PROGRESS && ( + <> + + + + + + + )} + {roll.type === ROLL_TYPE.ORACLE_TABLE && ( + <> + + + + + + + )} + {roll.type === ROLL_TYPE.CLOCK_PROGRESSION && ( + <> + + + + + + + )} + + + ); +} diff --git a/src/components/features/charactersAndCampaigns/RollDisplay/RollResult.tsx b/src/components/features/charactersAndCampaigns/RollDisplay/RollResult.tsx new file mode 100644 index 00000000..151ebcc7 --- /dev/null +++ b/src/components/features/charactersAndCampaigns/RollDisplay/RollResult.tsx @@ -0,0 +1,47 @@ +import { Box, Typography } from "@mui/material"; +import { MarkdownRenderer } from "components/shared/MarkdownRenderer"; + +export interface RollResultProps { + result?: string; + markdown?: string; + extras?: string[]; +} + +export function RollResult(props: RollResultProps) { + const { result, markdown, extras } = props; + + return ( + + {result && ( + theme.fontFamilyTitle} + > + {result} + + )} + {markdown && ( + + )} + {Array.isArray(extras) && + extras.map((extra) => ( + theme.palette.grey[200]} + variant={"caption"} + component={"p"} + fontFamily={(theme) => theme.fontFamilyTitle} + > + {extra} + + ))} + + ); +} diff --git a/src/components/features/charactersAndCampaigns/RollDisplay/RollTitle.tsx b/src/components/features/charactersAndCampaigns/RollDisplay/RollTitle.tsx new file mode 100644 index 00000000..05dab4ce --- /dev/null +++ b/src/components/features/charactersAndCampaigns/RollDisplay/RollTitle.tsx @@ -0,0 +1,47 @@ +import { Box, Stack, Typography } from "@mui/material"; +import { ReactNode } from "react"; + +export interface RollTitleProps { + overline?: string; + title: string; + isExpanded: boolean; + actions?: ReactNode; +} + +export function RollTitle(props: RollTitleProps) { + const { isExpanded, title, overline, actions } = props; + + return ( + +
+ {overline && isExpanded && ( + theme.fontFamilyTitle} + > + {overline} + + )} + theme.fontFamilyTitle} + sx={{ mr: 1 }} + > + {title} + +
+ {actions && isExpanded && ( + + {actions} + + )} +
+ ); +} diff --git a/src/components/features/charactersAndCampaigns/RollDisplay/RollValues.tsx b/src/components/features/charactersAndCampaigns/RollDisplay/RollValues.tsx new file mode 100644 index 00000000..7f2e979f --- /dev/null +++ b/src/components/features/charactersAndCampaigns/RollDisplay/RollValues.tsx @@ -0,0 +1,102 @@ +import { Box, Divider, Typography } from "@mui/material"; +import { D6Icon } from "assets/D6Icon"; +import { D10Icon } from "assets/D10Icon"; + +export interface RollValuesProps { + d10Results?: [number, number] | number; + d6Result?: { + action: number; + modifier?: number; + adds?: number; + rollTotal: number; + }; + fixedResult?: { + title: string; + value: string | number; + }; + isExpanded: boolean; +} +export function RollValues(props: RollValuesProps) { + const { d10Results, d6Result, fixedResult, isExpanded } = props; + + if (!isExpanded) { + return null; + } + + return ( + <> + + {d6Result && ( + + + theme.palette.grey[200]} + sx={ + d6Result.action === 1 + ? { + borderRadius: 1, + borderColor: "primary.light", + borderWidth: 1, + borderStyle: "solid", + px: 0.5, + mr: -0.5, + } + : {} + } + > + {d6Result.action} + + theme.palette.grey[200]}> + {d6Result.modifier ? ` + ${d6Result.modifier}` : ""} + {d6Result.adds ? ` + ${d6Result.adds}` : ""} + {d6Result.modifier || d6Result.adds + ? ` = ${ + d6Result.rollTotal > 10 ? "10 (Max)" : d6Result.rollTotal + }` + : ""} + + + )} + {fixedResult && ( + + theme.palette.grey[200]}> + {fixedResult.title}: {fixedResult.value} + + + )} + {d10Results && ( + + + theme.palette.grey[200]}> + {Array.isArray(d10Results) + ? `${d10Results[0]}, ${d10Results[1]}` + : d10Results} + + + )} + + ({ + alignSelf: "stretch", + borderColor: theme.palette.grey[400], + height: "auto", + mx: 2, + })} + /> + + ); +} diff --git a/src/components/features/charactersAndCampaigns/RollDisplay/clipboardFormatter.ts b/src/components/features/charactersAndCampaigns/RollDisplay/clipboardFormatter.ts new file mode 100644 index 00000000..7b7f63b8 --- /dev/null +++ b/src/components/features/charactersAndCampaigns/RollDisplay/clipboardFormatter.ts @@ -0,0 +1,278 @@ +import { + ClockProgressionRoll, + OracleTableRoll, + ROLL_TYPE, + Roll, + StatRoll, + TrackProgressRoll, +} from "types/DieRolls.type"; +import { getRollResultLabel } from "./getRollResultLabel"; +import { TRACK_TYPES } from "types/Track.type"; +import { LEGACY_TRACK_TYPES } from "types/LegacyTrack.type"; + +export function formatQuote(contents: string) { + return `
${contents}
`; +} + +export function formatBold(contents: string) { + return `${contents}`; +} + +export function formatItalic(contents: string) { + return `${contents}`; +} + +export function formatParagraph(contents: string) { + return `

${contents}

`; +} + +export function convertRollToClipboard(roll: Roll): + | { + rich: string; + plain: string; + } + | undefined { + switch (roll.type) { + case ROLL_TYPE.STAT: + const statContents = extractStatRollContents(roll); + return { + rich: convertStatRollToClipboardRich(statContents), + plain: convertStatRollToClipboardPlain(statContents), + }; + case ROLL_TYPE.ORACLE_TABLE: + const oracleContents = extractOracleRollContents(roll); + return { + rich: convertOracleRollToClipboardRich(oracleContents), + plain: convertOracleRollToClipboardPlain(oracleContents), + }; + case ROLL_TYPE.TRACK_PROGRESS: + const trackProgressContents = extractTrackProgressRollContents(roll); + return { + rich: convertTrackProgressRollToClipboardRich(trackProgressContents), + plain: convertTrackProgressRollToClipboardPlain(trackProgressContents), + }; + case ROLL_TYPE.CLOCK_PROGRESSION: + const clockProgressionContents = + extractClockProgressionRollContents(roll); + + return { + rich: convertClockProgressionRollToClipboardRich( + clockProgressionContents + ), + plain: convertClockProgressionRollToClipboardPlain( + clockProgressionContents + ), + }; + default: + return undefined; + } +} + +interface StatRollContents { + title: string; + actionContents: string; + challengeContents: string; + result: string; +} + +export function extractStatRollContents(roll: StatRoll): StatRollContents { + const title = roll.moveName + ? `${roll.moveName} (${roll.rollLabel})` + : roll.rollLabel; + let actionContents = roll.action + ""; + if (roll.modifier || roll.adds) { + const rollTotal = roll.action + (roll.modifier ?? 0) + (roll.adds ?? 0); + actionContents += + (roll.modifier ? ` + ${roll.modifier}` : "") + + (roll.adds ? ` + ${roll.adds}` : "") + + ` = ${rollTotal > 10 ? "10 (Max)" : rollTotal}`; + } + const challengeContents = `${roll.challenge1}, ${roll.challenge2}`; + + const result = getRollResultLabel(roll.result).toLocaleUpperCase(); + + return { + title, + actionContents, + challengeContents, + result, + }; +} + +export function convertStatRollToClipboardRich( + contents: StatRollContents +): string { + const title = formatParagraph(contents.title); + const action = formatParagraph( + formatItalic("Action: ") + contents.actionContents + ); + const challenge = formatParagraph( + formatItalic("Challenge: ") + contents.challengeContents + ); + const result = formatBold(contents.result); + + return formatQuote(title + action + challenge + result); +} + +export function convertStatRollToClipboardPlain(contents: StatRollContents) { + return ` +${contents.title} +Action: ${contents.actionContents} +Challenge: ${contents.challengeContents} +${contents.result} + `; +} + +interface OracleRollContents { + title: string; + roll: string; + result: string; +} + +export function extractOracleRollContents( + roll: OracleTableRoll +): OracleRollContents { + const title = roll.oracleCategoryName + ? `${roll.oracleCategoryName} ꞏ ${roll.rollLabel}` + : roll.rollLabel; + const rollSection = roll.roll + ""; + const result = roll.result; + + return { + title, + roll: rollSection, + result, + }; +} + +export function convertOracleRollToClipboardRich( + contents: OracleRollContents +): string { + const title = formatParagraph(contents.title); + const roll = formatParagraph(formatItalic("Roll: ") + contents.roll); + const result = formatBold(contents.result); + + return formatQuote(title + roll + result); +} + +export function convertOracleRollToClipboardPlain( + contents: OracleRollContents +) { + return ` +${contents.title} +Roll: ${contents.roll} +${contents.result} + `; +} + +interface TrackProgressRollContents { + title: string; + progress: string; + challenge: string; + result: string; +} + +function getTrackTypeLabel(type: TRACK_TYPES | LEGACY_TRACK_TYPES) { + switch (type) { + case TRACK_TYPES.VOW: + return "Vow"; + case TRACK_TYPES.BOND_PROGRESS: + return "Bond Progress"; + case TRACK_TYPES.CLOCK: + return "Clock Progress"; + case TRACK_TYPES.FRAY: + return "Fray"; + case TRACK_TYPES.JOURNEY: + return "Journey"; + case LEGACY_TRACK_TYPES.BONDS: + return "Bonds"; + case LEGACY_TRACK_TYPES.DISCOVERIES: + return "Discoveries"; + case LEGACY_TRACK_TYPES.QUESTS: + return "Quests"; + default: + return ""; + } +} + +export function extractTrackProgressRollContents( + roll: TrackProgressRoll +): TrackProgressRollContents { + const title = `${getTrackTypeLabel(roll.trackType)}: ${roll.rollLabel}`; + const progress = roll.trackProgress + ""; + const challenge = `${roll.challenge1}, ${roll.challenge2}`; + const result = getRollResultLabel(roll.result).toLocaleUpperCase(); + + return { + title, + progress, + challenge, + result, + }; +} + +export function convertTrackProgressRollToClipboardRich( + contents: TrackProgressRollContents +): string { + const title = formatParagraph(contents.title); + const progress = formatParagraph( + formatItalic("Progress: ") + contents.progress + ); + const challenge = formatParagraph( + formatItalic("Challenge: ") + contents.challenge + ); + const result = formatBold(contents.result); + + return formatQuote(title + progress + challenge + result); +} + +export function convertTrackProgressRollToClipboardPlain( + contents: TrackProgressRollContents +) { + return ` +${contents.title} +Progress: ${contents.progress} +Challenge: ${contents.challenge} +${contents.result} + `; +} + +interface ClockProgressionRollContents { + title: string; + roll: string; + result: string; +} + +export function extractClockProgressionRollContents( + roll: ClockProgressionRoll +): ClockProgressionRollContents { + const title = roll.rollLabel; + const rollResult = roll.roll + ""; + const result = roll.result.toLocaleUpperCase(); + + return { + title, + roll: rollResult, + result, + }; +} + +export function convertClockProgressionRollToClipboardRich( + contents: ClockProgressionRollContents +): string { + const title = formatParagraph(contents.title); + const roll = formatParagraph(formatItalic("Roll: ") + contents.roll); + const result = formatBold(contents.result); + + return formatQuote(title + roll + result); +} + +export function convertClockProgressionRollToClipboardPlain( + contents: ClockProgressionRollContents +) { + return ` +${contents.title} +Roll: ${contents.roll} +${contents.result} + `; +} diff --git a/src/components/shared/RollSnackbar/getRollResultLabel.ts b/src/components/features/charactersAndCampaigns/RollDisplay/getRollResultLabel.ts similarity index 100% rename from src/components/shared/RollSnackbar/getRollResultLabel.ts rename to src/components/features/charactersAndCampaigns/RollDisplay/getRollResultLabel.ts diff --git a/src/components/features/charactersAndCampaigns/RollDisplay/index.ts b/src/components/features/charactersAndCampaigns/RollDisplay/index.ts new file mode 100644 index 00000000..1c0cc6ca --- /dev/null +++ b/src/components/features/charactersAndCampaigns/RollDisplay/index.ts @@ -0,0 +1,2 @@ +export * from "./RollDisplay"; +export * from "./getRollResultLabel"; diff --git a/src/components/shared/Layout/Layout.tsx b/src/components/shared/Layout/Layout.tsx index bc6f9772..276120c1 100644 --- a/src/components/shared/Layout/Layout.tsx +++ b/src/components/shared/Layout/Layout.tsx @@ -20,7 +20,7 @@ import { SkipToContentButton } from "./SkipToContentButton"; import { useSyncFeatureFlags } from "hooks/featureFlags/useSyncFeatureFlags"; import { LinkedDialog } from "components/features/charactersAndCampaigns/LinkedDialog"; import { LiveRegion } from "../LiveRegion"; -import { RollSnackbarSection } from "../RollSnackbar"; +import { RollSnackbarSection } from "./RollSnackbarSection"; export function Layout() { useSyncFeatureFlags(); diff --git a/src/components/shared/RollSnackbar/RollSnackbarSecton.tsx b/src/components/shared/Layout/RollSnackbarSection.tsx similarity index 83% rename from src/components/shared/RollSnackbar/RollSnackbarSecton.tsx rename to src/components/shared/Layout/RollSnackbarSection.tsx index 11981f59..4c8d0b95 100644 --- a/src/components/shared/RollSnackbar/RollSnackbarSecton.tsx +++ b/src/components/shared/Layout/RollSnackbarSection.tsx @@ -1,9 +1,10 @@ import { Box, Fab, Slide } from "@mui/material"; import { useFooterState } from "hooks/useFooterState"; import { TransitionGroup } from "react-transition-group"; -import { RollSnackbar } from "./RollSnackbar"; import ClearIcon from "@mui/icons-material/Close"; import { useStore } from "stores/store"; +import { RollDisplay } from "components/features/charactersAndCampaigns/RollDisplay"; +import { NormalRollActions } from "components/features/charactersAndCampaigns/RollDisplay/NormalRollActions"; export function RollSnackbarSection() { const rolls = useStore((store) => store.appState.rolls); @@ -40,13 +41,14 @@ export function RollSnackbarSection() { direction={"left"} key={`${roll.rollLabel}.${roll.timestamp.getTime()}.${roll.type}`} > - - + clearRoll(index)} + onClick={() => clearRoll(index)} isExpanded={index === array.length - 1} + actions={} /> - +
))} diff --git a/src/components/shared/RollSnackbar/ClockProgressionRollSnackbar.tsx b/src/components/shared/RollSnackbar/ClockProgressionRollSnackbar.tsx deleted file mode 100644 index 164affb6..00000000 --- a/src/components/shared/RollSnackbar/ClockProgressionRollSnackbar.tsx +++ /dev/null @@ -1,92 +0,0 @@ -import { Box, ButtonBase, Card, Divider, Typography } from "@mui/material"; -import { ClockProgressionRoll } from "types/DieRolls.type"; -import { D10Icon } from "assets/D10Icon"; -import { MarkdownRenderer } from "components/shared/MarkdownRenderer"; - -export interface ClockProgressionRollSnackbarProps { - roll: ClockProgressionRoll; - clearRoll?: () => void; - expanded: boolean; -} - -export function ClockProgressionRollSnackbar( - props: ClockProgressionRollSnackbarProps -) { - const { roll, clearRoll, expanded } = props; - - return ( - ({ - px: 2, - py: 1, - backgroundColor: theme.palette.darkGrey.dark, - color: theme.palette.darkGrey.contrastText, - display: "flex", - flexDirection: "column", - alignItems: "flex-start", - mt: 1, - })} - component={clearRoll ? ButtonBase : "div"} - onClick={clearRoll ? () => clearRoll() : undefined} - > - {expanded && roll.oracleTitle && ( - theme.fontFamilyTitle} - > - {roll.oracleTitle} - - )} - theme.fontFamilyTitle} - > - {roll.rollLabel} - - - {expanded && ( - - -
- - -
- {roll.roll} -
-
- )} - {expanded && ( - ({ - alignSelf: "stretch", - borderColor: theme.palette.grey[200], - height: "auto", - mx: 2, - })} - /> - )} - - - -
-
- ); -} diff --git a/src/components/shared/RollSnackbar/OracleTableRollSnackbar.tsx b/src/components/shared/RollSnackbar/OracleTableRollSnackbar.tsx deleted file mode 100644 index 8d081e6a..00000000 --- a/src/components/shared/RollSnackbar/OracleTableRollSnackbar.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import { Box, ButtonBase, Card, Divider, Typography } from "@mui/material"; -import { OracleTableRoll } from "types/DieRolls.type"; -import { D10Icon } from "assets/D10Icon"; -import { MarkdownRenderer } from "components/shared/MarkdownRenderer"; - -export interface OracleTableRollSnackbarProps { - roll: OracleTableRoll; - clearRoll?: () => void; - expanded: boolean; -} - -export function OracleTableRollSnackbar(props: OracleTableRollSnackbarProps) { - const { roll, clearRoll, expanded } = props; - - return ( - ({ - px: 2, - py: 1, - backgroundColor: theme.palette.darkGrey.dark, - color: theme.palette.darkGrey.contrastText, - display: "flex", - flexDirection: "column", - alignItems: "flex-start", - mt: 1, - })} - component={clearRoll ? ButtonBase : "div"} - onClick={clearRoll ? () => clearRoll() : undefined} - > - {expanded && roll.oracleCategoryName && ( - theme.fontFamilyTitle} - > - {roll.oracleCategoryName} - - )} - theme.fontFamilyTitle} - > - {roll.rollLabel} - - - {expanded && ( - - -
- - -
- {roll.roll} -
-
- )} - {expanded && ( - ({ - alignSelf: "stretch", - borderColor: theme.palette.grey[200], - height: "auto", - mx: 2, - })} - /> - )} - - - -
-
- ); -} diff --git a/src/components/shared/RollSnackbar/RollSnackbar.tsx b/src/components/shared/RollSnackbar/RollSnackbar.tsx deleted file mode 100644 index e283c1b1..00000000 --- a/src/components/shared/RollSnackbar/RollSnackbar.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import { Roll, ROLL_TYPE } from "types/DieRolls.type"; -import { OracleTableRollSnackbar } from "./OracleTableRollSnackbar"; -import { StatRollSnackbar } from "./StatRollSnackbar"; -import { TrackProgressRollSnackbar } from "./TrackProgressRollSnackbar"; -import { ClockProgressionRollSnackbar } from "./ClockProgressionRollSnackbar"; - -export interface RollSnackbarProps { - roll: Roll; - clearRoll?: () => void; - isExpanded: boolean; -} - -export function RollSnackbar(props: RollSnackbarProps) { - const { roll, clearRoll, isExpanded } = props; - - switch (roll.type) { - case ROLL_TYPE.STAT: - return ( - - ); - case ROLL_TYPE.ORACLE_TABLE: - return ( - - ); - case ROLL_TYPE.TRACK_PROGRESS: - return ( - - ); - case ROLL_TYPE.CLOCK_PROGRESSION: - return ( - - ); - default: - return null; - } -} diff --git a/src/components/shared/RollSnackbar/StatRollSnackbar.tsx b/src/components/shared/RollSnackbar/StatRollSnackbar.tsx deleted file mode 100644 index 625f784c..00000000 --- a/src/components/shared/RollSnackbar/StatRollSnackbar.tsx +++ /dev/null @@ -1,146 +0,0 @@ -import { - Box, - ButtonBase, - Card, - Divider, - Typography, - useTheme, -} from "@mui/material"; -import { StatRoll } from "types/DieRolls.type"; -import { D6Icon } from "assets/D6Icon"; -import { D10Icon } from "assets/D10Icon"; -import { getRollResultLabel } from "./getRollResultLabel"; - -export interface StatRollSnackbarProps { - roll: StatRoll; - clearRoll?: () => void; - expanded: boolean; -} - -export function StatRollSnackbar(props: StatRollSnackbarProps) { - const { roll, clearRoll, expanded } = props; - const theme = useTheme(); - - const rollTotal = roll.action + (roll.modifier ?? 0) + (roll.adds ?? 0); - - let rollActionBorder = "none"; - let rollActionPadding = "0"; - let rollActionBorderRadius = "0"; - let rollActionMarginRight = "-4px"; - - if (roll.action === 1) { - rollActionBorder = "1px solid " + theme.palette.primary.light; - rollActionBorderRadius = "25%"; - rollActionPadding = "0px 5px 0 4px"; - rollActionMarginRight = "-6px"; - } - - return ( - ({ - px: 2, - py: 1, - backgroundColor: theme.palette.darkGrey.dark, - color: theme.palette.darkGrey.contrastText, - display: "flex", - flexDirection: "column", - alignItems: "flex-start", - mt: 1, - })} - component={clearRoll ? ButtonBase : "div"} - onClick={clearRoll ? () => clearRoll() : undefined} - > - theme.fontFamilyTitle} - > - {roll.moveName - ? `${roll.moveName} (${roll.rollLabel})` - : roll.rollLabel} - - - {expanded && ( - - - - theme.palette.grey[200]} - border={rollActionBorder} - borderRadius={rollActionBorderRadius} - padding={rollActionPadding} - marginRight={rollActionMarginRight} - > - {roll.action} - - theme.palette.grey[200]}> - {roll.modifier ? ` + ${roll.modifier}` : ""} - {roll.adds ? ` + ${roll.adds}` : ""} - {roll.modifier || roll.adds - ? ` = ${rollTotal > 10 ? "10 (Max)" : rollTotal}` - : ""} - - - - - theme.palette.grey[200]}> - {roll.challenge1}, {roll.challenge2} - - - - )} - {expanded && ( - ({ - alignSelf: "stretch", - borderColor: theme.palette.grey[400], - height: "auto", - mx: 2, - })} - /> - )} - - theme.fontFamilyTitle} - > - {getRollResultLabel(roll.result)} - - {roll.challenge1 === roll.challenge2 && ( - theme.palette.grey[200]} - variant={"caption"} - fontFamily={(theme) => theme.fontFamilyTitle} - > - Doubles - - )} - {roll.action === 1 && ( - theme.palette.grey[200]} - variant={"caption"} - fontFamily={(theme) => theme.fontFamilyTitle} - > - Natural 1 - - )} - - - - ); -} diff --git a/src/components/shared/RollSnackbar/TrackProgressRollSnackbar.tsx b/src/components/shared/RollSnackbar/TrackProgressRollSnackbar.tsx deleted file mode 100644 index 863071b9..00000000 --- a/src/components/shared/RollSnackbar/TrackProgressRollSnackbar.tsx +++ /dev/null @@ -1,99 +0,0 @@ -import { Box, ButtonBase, Card, Divider, Typography } from "@mui/material"; -import { TrackProgressRoll } from "types/DieRolls.type"; -import { D10Icon } from "assets/D10Icon"; -import { getRollResultLabel } from "./getRollResultLabel"; - -export interface TrackProgressRollSnackbarProps { - roll: TrackProgressRoll; - clearRoll?: () => void; - expanded: boolean; -} - -export function TrackProgressRollSnackbar( - props: TrackProgressRollSnackbarProps -) { - const { roll, clearRoll, expanded } = props; - - return ( - ({ - px: 2, - py: 1, - backgroundColor: theme.palette.darkGrey.dark, - color: theme.palette.darkGrey.contrastText, - display: "flex", - flexDirection: "column", - alignItems: "flex-start", - mt: 1, - })} - component={clearRoll ? ButtonBase : "div"} - onClick={clearRoll ? () => clearRoll() : undefined} - > - theme.fontFamilyTitle} - > - {roll.rollLabel} - - - {expanded && ( - - - theme.palette.grey[200]}> - Progress: {roll.trackProgress} - - - - - theme.palette.grey[200]}> - {roll.challenge1}, {roll.challenge2} - - - - )} - {expanded && ( - ({ - alignSelf: "stretch", - borderColor: theme.palette.grey[400], - height: "auto", - mx: 2, - })} - /> - )} - - theme.fontFamilyTitle} - > - {getRollResultLabel(roll.result)} - - {roll.challenge1 === roll.challenge2 && ( - theme.palette.grey[200]} - variant={"caption"} - fontFamily={(theme) => theme.fontFamilyTitle} - > - Doubles - - )} - - - - ); -} diff --git a/src/components/shared/RollSnackbar/index.ts b/src/components/shared/RollSnackbar/index.ts deleted file mode 100644 index 107add16..00000000 --- a/src/components/shared/RollSnackbar/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from "./RollSnackbar"; -export * from "./getRollResultLabel"; -export * from "./RollSnackbarSecton"; diff --git a/src/stores/appState/useRoller.ts b/src/stores/appState/useRoller.ts index 52c78173..b14b9836 100644 --- a/src/stores/appState/useRoller.ts +++ b/src/stores/appState/useRoller.ts @@ -10,7 +10,7 @@ import { StatRoll, TrackProgressRoll, } from "types/DieRolls.type"; -import { getRollResultLabel } from "components/shared/RollSnackbar"; +import { getRollResultLabel } from "components/features/charactersAndCampaigns/RollDisplay"; import { TRACK_TYPES } from "types/Track.type"; import { LEGACY_TRACK_TYPES } from "types/LegacyTrack.type";