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

add copy link button to game update row #7

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
66 changes: 55 additions & 11 deletions reblase/src/components/game/UpdateRow.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { isGameUpdateImportant, getBattingTeam } from "blaseball-lib/games";
import { Circles } from "../elements/Circles";
import React, { useEffect, useRef } from "react";
import React, { useEffect, useRef, useState } from "react";
import dayjs from "dayjs";
import Emoji from "../elements/Emoji";
import { BlaseballGame } from "blaseball-lib/models";
import { ChronFightUpdate, ChronGameUpdate } from "blaseball-lib/chronicler";
import BaseDisplay from "../elements/BaseDisplay";
import { AiOutlineLink } from "react-icons/ai";
import { AiOutlineLink, AiOutlineCopy } from "react-icons/ai";
import Tooltip from "rc-tooltip";

interface WrappedUpdateProps {
update: ChronGameUpdate | ChronFightUpdate;
Expand All @@ -21,7 +22,7 @@ const ScoreGrid = "col-start-1 col-end-1 lg:col-start-2 lg:col-end-2";
const GameLogGrid = "col-start-1 col-end-4 lg:col-start-3 lg:col-end-3";
const BatterGrid = "col-start-2 col-end-2 justify-self-start lg:col-start-4 lg:col-end-4 lg:justify-self-end";
const AtBatGrid = "col-start-3 col-end-5 justify-self-end lg:col-start-5 lg:col-end-5";
const LinkGrid = "hidden lg:block lg:col-start-6 lg:col-end-6";
const ControlsGrid = "hidden lg:block lg:col-start-6 lg:col-end-6";

function Timestamp({ update }: WrappedUpdateProps) {
const updateTime = dayjs(update.timestamp);
Expand Down Expand Up @@ -93,12 +94,55 @@ interface UpdateRowProps extends WrappedUpdateProps {
highlight: boolean;
}

function UpdateLink(props: { hash: string }) {
const href = window.location.protocol + "//" + window.location.host + window.location.pathname + "#" + props.hash;
return (
<a href={href} className={`${LinkGrid} -mr-16 pl-4 cursor-pointer text-lg text-gray-500 hover:text-gray-900`}>
<AiOutlineLink />
</a>
function UpdateLinkControls(props: { hash: string }) {
// This should probably be using React refs???
const url = window.location.protocol + "//" + window.location.host + window.location.pathname + "#" + props.hash;

const updateRowHrefInputID = `update-row-input-${props.hash}`;

const [linkCopied, setLinkCopied] = useState(false);

function copyLink(updateRowHrefInputID: string) {
// Code copied from W3Schools https://www.w3schools.com/howto/howto_js_copy_clipboard.asp

const updateRowHrefInputElement = document.getElementById(updateRowHrefInputID) as HTMLInputElement;
updateRowHrefInputElement.select();
/* For mobile devices, although this button shouldn't show up on those. */
updateRowHrefInputElement.setSelectionRange(0, 99999);
document.execCommand('copy');

setLinkCopied(true);

// Arbitrary 3 second timeout to set text back to "Copy link".
setTimeout(() => {
setLinkCopied(false);
}, 3000);
}

return (
<div className={`${ControlsGrid} pl-r text-lg text-gray-500 -mr-16 pl-4`}>
<div className="flex items-center">
<a href={url} className={`cursor-pointer hover:text-gray-900`}>
<AiOutlineLink />
</a>
<div className="ml-1 flex items-center">
<Tooltip overlay={linkCopied ? "Link copied!" : "Copy link"}>
<button type="button" className="hover:text-gray-900" onClick={() => {
copyLink(updateRowHrefInputID);
}}>
<AiOutlineCopy />
</button>
</Tooltip>

{/* This is a kinda hacky sorta-but-not-quite-hidden input to copy the link from. It's
hiding behind the copy link button because I didn't want to show it, but
in order to copy text, you need to select the text first, and you cannot select
text in a hidden input. I tried display: none, width: 0, height: 0, and
type=hidden. - kadauber#7305 */}
<input id={updateRowHrefInputID} value={url} readOnly className="w-1 h-1 absolute top-0 left-0" />
</div>
</div>
</div>
);
}

Expand All @@ -120,15 +164,15 @@ export const UpdateRow = React.memo(
"grid grid-flow-row-dense gap-2 items-center px-2 py-2 border-b border-gray-300 " +
(highlight ? "bg-yellow-200" : "")
}
style={{ gridTemplateColumns: "auto auto 1fr" }}
style={{ gridTemplateColumns: "auto auto 1fr repeat(3, auto)" }}
>
<GameLog evt={evt} />
<Timestamp update={update} />
<Score evt={evt} />
<Batter evt={evt} />
<AtBatInfo evt={evt} />

<UpdateLink hash={update.hash} />
<UpdateLinkControls hash={update.hash} />
</div>
);
},
Expand Down