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

fix: saveable share qr code #4191

Merged
merged 13 commits into from
Jul 23, 2024
Merged
22 changes: 3 additions & 19 deletions src/components/SettingsDialog/ShareSession/ShareSession.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,10 @@ $header-menu__item-border-width: 1px;
$header-menu-border-bottom-color: #efefef;

.share-qr-code-option__qrcode {
height: 100%;
width: 100%;
}

.share-qr-code-option__qrcode path:first-child {
fill: $gray--100;
}

.share-qr-code-option__qrcode path:last-child {
fill: $navy--700;
height: 100%;
max-height: 100%;
max-width: 100%;
}

.share-session__background {
Expand Down Expand Up @@ -70,13 +64,3 @@ $header-menu-border-bottom-color: #efefef;
flex-direction: column;
border-radius: 8px;
}

[theme="dark"] {
.share-qr-code-option__qrcode path:first-child {
fill: $navy--600;
}

.share-qr-code-option__qrcode path:last-child {
fill: $gray--100;
}
}
23 changes: 19 additions & 4 deletions src/components/SettingsDialog/ShareSession/ShareSession.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import classNames from "classnames";
import QRCode from "qrcode.react";
import {useTranslation} from "react-i18next";
import "./ShareSession.scss";
import {useState, VFC} from "react";
import {useState} from "react";
import {useAppSelector} from "store";
import {useAutoTheme} from "utils/hooks/useAutoTheme";
import {getCSSCustomPropertyValue} from "utils/computedStyles";
import "./ShareSession.scss";

export const ShareSession: VFC = () => {
export const ShareSession = () => {
const {t} = useTranslation();
const boardId = useAppSelector((state) => state.board.data?.id);
const theme = useAppSelector((state) => state.view.theme);
const autoTheme = useAutoTheme(theme);

const gray000 = getCSSCustomPropertyValue("--gray--000");
const navy900 = getCSSCustomPropertyValue("--navy--900");

const [urlInClipBoard, setUrlInClipBoard] = useState(false);

Expand All @@ -23,7 +30,15 @@ export const ShareSession: VFC = () => {
</div>
<div className={classNames("share-session__container", "accent-color__planning-pink")}>
<div className="share-session__background">
<QRCode value={`${window.location.origin}/board/${boardId}`} renderAs="svg" className="share-qr-code-option__qrcode" />
{/* using an upscaled canvas instead of svg to make it a savable image */}
<QRCode
value={`${window.location.origin}/board/${boardId}`}
renderAs="canvas"
size={1024}
fgColor={autoTheme === "dark" ? gray000 : navy900}
bgColor={autoTheme === "dark" ? navy900 : gray000}
className="share-qr-code-option__qrcode"
/>
</div>
<button className={classNames("share-qr-code-option__copy-to-clipboard", {"--copied": urlInClipBoard})} onClick={handleCopyToClipboard} disabled={urlInClipBoard}>
{urlInClipBoard ? t("ShareQrCodeOption.inviteUrlCopied") : t("ShareQrCodeOption.copyInviteURL")}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,12 @@ Object {
<div
class="share-session__background"
>
<svg
<canvas
class="share-qr-code-option__qrcode"
height="128"
viewBox="0 0 29 29"
width="128"
>
<path
d="M0,0 h29v29H0z"
fill="#FFFFFF"
shape-rendering="crispEdges"
/>
<path
d="M0 0h7v1H0zM8 0h2v1H8zM11 0h1v1H11zM13 0h1v1H13zM15 0h1v1H15zM17 0h3v1H17zM22,0 h7v1H22zM0 1h1v1H0zM6 1h1v1H6zM8 1h4v1H8zM13 1h1v1H13zM18 1h1v1H18zM20 1h1v1H20zM22 1h1v1H22zM28,1 h1v1H28zM0 2h1v1H0zM2 2h3v1H2zM6 2h1v1H6zM9 2h1v1H9zM12 2h1v1H12zM18 2h3v1H18zM22 2h1v1H22zM24 2h3v1H24zM28,2 h1v1H28zM0 3h1v1H0zM2 3h3v1H2zM6 3h1v1H6zM8 3h5v1H8zM14 3h2v1H14zM17 3h1v1H17zM22 3h1v1H22zM24 3h3v1H24zM28,3 h1v1H28zM0 4h1v1H0zM2 4h3v1H2zM6 4h1v1H6zM14 4h6v1H14zM22 4h1v1H22zM24 4h3v1H24zM28,4 h1v1H28zM0 5h1v1H0zM6 5h1v1H6zM13 5h1v1H13zM18 5h2v1H18zM22 5h1v1H22zM28,5 h1v1H28zM0 6h7v1H0zM8 6h1v1H8zM10 6h1v1H10zM12 6h1v1H12zM14 6h1v1H14zM16 6h1v1H16zM18 6h1v1H18zM20 6h1v1H20zM22,6 h7v1H22zM8 7h3v1H8zM17 7h1v1H17zM19 7h2v1H19zM0 8h1v1H0zM2 8h2v1H2zM5 8h3v1H5zM10 8h2v1H10zM13 8h1v1H13zM15 8h6v1H15zM22 8h1v1H22zM25 8h1v1H25zM27,8 h2v1H27zM0 9h5v1H0zM7 9h2v1H7zM10 9h1v1H10zM12 9h3v1H12zM16 9h1v1H16zM18 9h7v1H18zM28,9 h1v1H28zM4 10h1v1H4zM6 10h1v1H6zM8 10h2v1H8zM11 10h1v1H11zM13 10h1v1H13zM16 10h3v1H16zM22 10h2v1H22zM26 10h2v1H26zM0 11h1v1H0zM2 11h1v1H2zM4 11h1v1H4zM7 11h5v1H7zM18 11h2v1H18zM22 11h4v1H22zM28,11 h1v1H28zM0 12h1v1H0zM2 12h1v1H2zM5 12h2v1H5zM9 12h4v1H9zM14 12h1v1H14zM17 12h1v1H17zM25 12h2v1H25zM1 13h2v1H1zM4 13h1v1H4zM8 13h5v1H8zM14 13h2v1H14zM17 13h3v1H17zM22 13h1v1H22zM27,13 h2v1H27zM1 14h2v1H1zM6 14h2v1H6zM10 14h4v1H10zM16 14h2v1H16zM19 14h3v1H19zM23 14h1v1H23zM25,14 h4v1H25zM0 15h1v1H0zM4 15h2v1H4zM8 15h1v1H8zM11 15h2v1H11zM14 15h3v1H14zM19 15h2v1H19zM22 15h1v1H22zM24 15h1v1H24zM27 15h1v1H27zM1 16h1v1H1zM5 16h2v1H5zM8 16h3v1H8zM12 16h1v1H12zM14 16h1v1H14zM18 16h4v1H18zM23 16h2v1H23zM27 16h1v1H27zM1 17h1v1H1zM5 17h1v1H5zM7 17h3v1H7zM14 17h2v1H14zM18 17h1v1H18zM20 17h2v1H20zM23 17h1v1H23zM26 17h2v1H26zM0 18h1v1H0zM2 18h1v1H2zM4 18h3v1H4zM8 18h3v1H8zM12 18h4v1H12zM21 18h1v1H21zM23 18h1v1H23zM25 18h2v1H25zM2 19h1v1H2zM4 19h1v1H4zM7 19h1v1H7zM11 19h5v1H11zM17 19h1v1H17zM19 19h5v1H19zM26 19h1v1H26zM1 20h1v1H1zM4 20h3v1H4zM8 20h1v1H8zM10 20h1v1H10zM13 20h2v1H13zM17 20h1v1H17zM19 20h8v1H19zM8 21h2v1H8zM11 21h1v1H11zM16 21h3v1H16zM20 21h1v1H20zM24,21 h5v1H24zM0 22h7v1H0zM8 22h1v1H8zM11 22h2v1H11zM14 22h1v1H14zM16 22h5v1H16zM22 22h1v1H22zM24 22h2v1H24zM27 22h1v1H27zM0 23h1v1H0zM6 23h1v1H6zM8 23h7v1H8zM16 23h1v1H16zM18 23h1v1H18zM20 23h1v1H20zM24 23h1v1H24zM28,23 h1v1H28zM0 24h1v1H0zM2 24h3v1H2zM6 24h1v1H6zM10 24h3v1H10zM15 24h1v1H15zM17 24h1v1H17zM20 24h5v1H20zM26 24h1v1H26zM0 25h1v1H0zM2 25h3v1H2zM6 25h1v1H6zM8 25h2v1H8zM12 25h2v1H12zM15 25h3v1H15zM19 25h1v1H19zM21 25h1v1H21zM23 25h3v1H23zM28,25 h1v1H28zM0 26h1v1H0zM2 26h3v1H2zM6 26h1v1H6zM8 26h2v1H8zM11 26h1v1H11zM13 26h1v1H13zM17 26h1v1H17zM20 26h2v1H20zM23 26h1v1H23zM25 26h1v1H25zM28,26 h1v1H28zM0 27h1v1H0zM6 27h1v1H6zM11 27h1v1H11zM13 27h1v1H13zM16 27h1v1H16zM18 27h1v1H18zM20 27h1v1H20zM23 27h1v1H23zM25 27h1v1H25zM27 27h1v1H27zM0 28h7v1H0zM8 28h1v1H8zM10 28h1v1H10zM13 28h3v1H13zM18 28h1v1H18zM20 28h1v1H20zM24 28h1v1H24zM27 28h1v1H27z"
fill="#000000"
shape-rendering="crispEdges"
/>
</svg>
height="1024"
style="height: 1024px; width: 1024px;"
width="1024"
/>
</div>
<button
class="share-qr-code-option__copy-to-clipboard"
Expand Down Expand Up @@ -73,23 +62,12 @@ Object {
<div
class="share-session__background"
>
<svg
<canvas
class="share-qr-code-option__qrcode"
height="128"
viewBox="0 0 29 29"
width="128"
>
<path
d="M0,0 h29v29H0z"
fill="#FFFFFF"
shape-rendering="crispEdges"
/>
<path
d="M0 0h7v1H0zM8 0h2v1H8zM11 0h1v1H11zM13 0h1v1H13zM15 0h1v1H15zM17 0h3v1H17zM22,0 h7v1H22zM0 1h1v1H0zM6 1h1v1H6zM8 1h4v1H8zM13 1h1v1H13zM18 1h1v1H18zM20 1h1v1H20zM22 1h1v1H22zM28,1 h1v1H28zM0 2h1v1H0zM2 2h3v1H2zM6 2h1v1H6zM9 2h1v1H9zM12 2h1v1H12zM18 2h3v1H18zM22 2h1v1H22zM24 2h3v1H24zM28,2 h1v1H28zM0 3h1v1H0zM2 3h3v1H2zM6 3h1v1H6zM8 3h5v1H8zM14 3h2v1H14zM17 3h1v1H17zM22 3h1v1H22zM24 3h3v1H24zM28,3 h1v1H28zM0 4h1v1H0zM2 4h3v1H2zM6 4h1v1H6zM14 4h6v1H14zM22 4h1v1H22zM24 4h3v1H24zM28,4 h1v1H28zM0 5h1v1H0zM6 5h1v1H6zM13 5h1v1H13zM18 5h2v1H18zM22 5h1v1H22zM28,5 h1v1H28zM0 6h7v1H0zM8 6h1v1H8zM10 6h1v1H10zM12 6h1v1H12zM14 6h1v1H14zM16 6h1v1H16zM18 6h1v1H18zM20 6h1v1H20zM22,6 h7v1H22zM8 7h3v1H8zM17 7h1v1H17zM19 7h2v1H19zM0 8h1v1H0zM2 8h2v1H2zM5 8h3v1H5zM10 8h2v1H10zM13 8h1v1H13zM15 8h6v1H15zM22 8h1v1H22zM25 8h1v1H25zM27,8 h2v1H27zM0 9h5v1H0zM7 9h2v1H7zM10 9h1v1H10zM12 9h3v1H12zM16 9h1v1H16zM18 9h7v1H18zM28,9 h1v1H28zM4 10h1v1H4zM6 10h1v1H6zM8 10h2v1H8zM11 10h1v1H11zM13 10h1v1H13zM16 10h3v1H16zM22 10h2v1H22zM26 10h2v1H26zM0 11h1v1H0zM2 11h1v1H2zM4 11h1v1H4zM7 11h5v1H7zM18 11h2v1H18zM22 11h4v1H22zM28,11 h1v1H28zM0 12h1v1H0zM2 12h1v1H2zM5 12h2v1H5zM9 12h4v1H9zM14 12h1v1H14zM17 12h1v1H17zM25 12h2v1H25zM1 13h2v1H1zM4 13h1v1H4zM8 13h5v1H8zM14 13h2v1H14zM17 13h3v1H17zM22 13h1v1H22zM27,13 h2v1H27zM1 14h2v1H1zM6 14h2v1H6zM10 14h4v1H10zM16 14h2v1H16zM19 14h3v1H19zM23 14h1v1H23zM25,14 h4v1H25zM0 15h1v1H0zM4 15h2v1H4zM8 15h1v1H8zM11 15h2v1H11zM14 15h3v1H14zM19 15h2v1H19zM22 15h1v1H22zM24 15h1v1H24zM27 15h1v1H27zM1 16h1v1H1zM5 16h2v1H5zM8 16h3v1H8zM12 16h1v1H12zM14 16h1v1H14zM18 16h4v1H18zM23 16h2v1H23zM27 16h1v1H27zM1 17h1v1H1zM5 17h1v1H5zM7 17h3v1H7zM14 17h2v1H14zM18 17h1v1H18zM20 17h2v1H20zM23 17h1v1H23zM26 17h2v1H26zM0 18h1v1H0zM2 18h1v1H2zM4 18h3v1H4zM8 18h3v1H8zM12 18h4v1H12zM21 18h1v1H21zM23 18h1v1H23zM25 18h2v1H25zM2 19h1v1H2zM4 19h1v1H4zM7 19h1v1H7zM11 19h5v1H11zM17 19h1v1H17zM19 19h5v1H19zM26 19h1v1H26zM1 20h1v1H1zM4 20h3v1H4zM8 20h1v1H8zM10 20h1v1H10zM13 20h2v1H13zM17 20h1v1H17zM19 20h8v1H19zM8 21h2v1H8zM11 21h1v1H11zM16 21h3v1H16zM20 21h1v1H20zM24,21 h5v1H24zM0 22h7v1H0zM8 22h1v1H8zM11 22h2v1H11zM14 22h1v1H14zM16 22h5v1H16zM22 22h1v1H22zM24 22h2v1H24zM27 22h1v1H27zM0 23h1v1H0zM6 23h1v1H6zM8 23h7v1H8zM16 23h1v1H16zM18 23h1v1H18zM20 23h1v1H20zM24 23h1v1H24zM28,23 h1v1H28zM0 24h1v1H0zM2 24h3v1H2zM6 24h1v1H6zM10 24h3v1H10zM15 24h1v1H15zM17 24h1v1H17zM20 24h5v1H20zM26 24h1v1H26zM0 25h1v1H0zM2 25h3v1H2zM6 25h1v1H6zM8 25h2v1H8zM12 25h2v1H12zM15 25h3v1H15zM19 25h1v1H19zM21 25h1v1H21zM23 25h3v1H23zM28,25 h1v1H28zM0 26h1v1H0zM2 26h3v1H2zM6 26h1v1H6zM8 26h2v1H8zM11 26h1v1H11zM13 26h1v1H13zM17 26h1v1H17zM20 26h2v1H20zM23 26h1v1H23zM25 26h1v1H25zM28,26 h1v1H28zM0 27h1v1H0zM6 27h1v1H6zM11 27h1v1H11zM13 27h1v1H13zM16 27h1v1H16zM18 27h1v1H18zM20 27h1v1H20zM23 27h1v1H23zM25 27h1v1H25zM27 27h1v1H27zM0 28h7v1H0zM8 28h1v1H8zM10 28h1v1H10zM13 28h3v1H13zM18 28h1v1H18zM20 28h1v1H20zM24 28h1v1H24zM27 28h1v1H27z"
fill="#000000"
shape-rendering="crispEdges"
/>
</svg>
height="1024"
style="height: 1024px; width: 1024px;"
width="1024"
/>
</div>
<button
class="share-qr-code-option__copy-to-clipboard"
Expand Down
15 changes: 14 additions & 1 deletion src/constants/colors.scss
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ $base-colors: (
300: $gray--300,
200: $gray--200,
100: $gray--100,
000: $gray--000,
"000": $gray--000, // avoid trailing zeros normalization
),
);

Expand All @@ -227,6 +227,16 @@ $base-colors: (
--accent-color--dark-rgb: #{red($shade-dark)}, #{green($shade-dark)}, #{blue($shade-dark)};
}

// set base colors to be used at the root level
@mixin set-base-colors($color-map) {
@each $color-name, $shades in $color-map {
@each $shade, $color in $shades {
--#{$color-name}--#{$shade}: #{$color};
--#{$color-name}--#{$shade}-rgb: #{red($color)}, #{green($color)}, #{blue($color)};
}
}
}

// generates css classes which can be included in an element
// to use their different accent color shades
// e.g. .accent-color__backlog-blue
Expand All @@ -240,3 +250,6 @@ $base-colors: (

@include generate-accent-classes($primary-colors);
@include generate-accent-classes($secondary-colors);
:root {
@include set-base-colors($base-colors);
}
2 changes: 2 additions & 0 deletions src/utils/computedStyles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// get CSS custom property, e.g. "--gray--000" => "#ffffff"
export const getCSSCustomPropertyValue = (property: string) => getComputedStyle(document.documentElement).getPropertyValue(property).trim();
Loading