Skip to content
This repository has been archived by the owner on Mar 2, 2024. It is now read-only.

Commit

Permalink
split process into 4 steps
Browse files Browse the repository at this point in the history
  • Loading branch information
avoonix committed Jun 17, 2023
1 parent 4a3fc66 commit 998aa79
Show file tree
Hide file tree
Showing 24 changed files with 781 additions and 270 deletions.
36 changes: 36 additions & 0 deletions packages/frontend/src/layouts/MainLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { View } from "@adobe/react-spectrum";
import { PropsWithChildren } from "react";

export default function MainLayout({ children }: PropsWithChildren) {
return (
<>
<main>{children}</main>
{/* footer */}
<View padding="size-100">
<a
href="https://github.com/avoonix/tg-sticker-creator/tree/master/packages/frontend"
target="_blank"
rel="noreferrer noopener"
>
sauce
</a>{" "}
&bull;{" "}
<a
href="https://www.gnu.org/licenses/agpl-3.0.en.html"
target="_blank"
rel="noreferrer noopener"
>
code license
</a>{" "}
&bull;{" "}
<a
href="https://creativecommons.org/publicdomain/zero/1.0/"
target="_blank"
rel="noreferrer noopener"
>
template license
</a>
</View>
</>
);
}
72 changes: 72 additions & 0 deletions packages/frontend/src/layouts/StickerEditLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import SpectrumLink from "@/modules/editor/SpectrumLink";
import { useApiSettings } from "@/modules/stickers/useApiSettings";
import { useSticker } from "@/modules/stickers/useSticker";
import { Button, Meter, Text, View } from "@adobe/react-spectrum";
import ArrowLeft from "@spectrum-icons/workflow/ArrowLeft";
import ArrowRight from "@spectrum-icons/workflow/ArrowRight";
import Head from "next/head";
import Link from "next/link";
import { useRouter } from "next/router";
import { PropsWithChildren } from "react";

export default function StickerEditLayout({ children }: PropsWithChildren) {
const router = useRouter();
const step = Number(router.asPath.match(/step\/(\d)/)?.[1]);
const prev = step == 1 ? null : step - 1;
const next = step == 4 ? null : step + 1;
const stickerId = String(router.query.stickerId);
const { sticker } = useSticker(stickerId);
const configString = router.query.config
? `?config=${router.query.config}`
: "";

useApiSettings();

return (
<>
<Head>
<title>
{sticker.displayName} Telegram Sticker Template - Avoo's Sticker Stash
</title>
</Head>
<View padding="size-300">
<Meter
width="100%"
label="Step"
value={(100 * step) / 4}
valueLabel={`${step} of 4`}
variant="positive"
/>
</View>
{prev && (
<Button
elementType={SpectrumLink}
variant="cta"
href={`/edit/${stickerId}/step/${prev}${configString}`}
>
<ArrowLeft />
<Text>Back to Step {prev}</Text>
</Button>
)}
<View padding="size-100">
<div>{children}</div>
</View>

{next ? (
<Button
elementType={SpectrumLink}
variant="cta"
href={`/edit/${stickerId}/step/${next}${configString}`}
>
<ArrowRight />
<Text>Continue to the Next Step</Text>
</Button>
) : (
<Button elementType={SpectrumLink} variant="cta" href="/">
<ArrowRight />
<Text>Finish</Text>
</Button>
)}
</>
);
}
23 changes: 23 additions & 0 deletions packages/frontend/src/modules/editor/SpectrumLink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import Link from "next/link";
import { AnchorHTMLAttributes, FC, PropsWithChildren } from "react";

interface Props
extends PropsWithChildren,
AnchorHTMLAttributes<HTMLAnchorElement> {
href: string;
}

/**
* Link that is compatible with spectrum buttons
*/
const SpectrumLink: FC<Props> = ({ href, children, ...rest }) => {
return (
<Link href={href}>
<a href={href} {...rest}>
{children}
</a>
</Link>
);
};

export default SpectrumLink;
10 changes: 10 additions & 0 deletions packages/frontend/src/modules/editor/StepDescription.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Well } from "@react-spectrum/well";
import { FC, PropsWithChildren } from "react";

interface Props extends PropsWithChildren {}

const StepDescription: FC<Props> = (props) => {
return <Well margin="single-line-height">{props.children}</Well>;
};

export default StepDescription;
48 changes: 48 additions & 0 deletions packages/frontend/src/modules/editor/StepStickerView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import StickerRenderer from "@/modules/editor/StickerRenderer";
import { View } from "@adobe/react-spectrum";
import { FC } from "react";
import { InView } from "react-intersection-observer";
import { Lottie } from "tg-sticker-creator";

interface Props {
lottie: Lottie | null;
sticky: boolean;
}

const StepStickerView: FC<Props> = (props) => {
return (
<div
style={{
display: "flex",
justifyContent: "center",
position: props.sticky ? "sticky" : "initial",
top: 0,
zIndex: 3,
backgroundColor: "var(--spectrum-alias-background-color-default)",
}}
>
<View maxWidth="size-5000" width="size-5000" margin="size-100">
<InView>
{({ inView, ref, entry }) => (
<div
style={{
backgroundColor: "var(--spectrum-global-color-static-blue-600)",
borderRadius:
"var(--spectrum-button-primary-border-radius,var(--spectrum-alias-border-radius-large))",
}}
ref={ref}
>
{inView ? (
<StickerRenderer sticker={props.lottie} animate />
) : (
<div style={{ aspectRatio: 1, width: "100%" }}></div>
)}
</div>
)}
</InView>
</View>
</div>
);
};

export default StepStickerView;
37 changes: 37 additions & 0 deletions packages/frontend/src/modules/editor/StepTemplateChanger.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Item, Menu, MenuTrigger, Text } from "@adobe/react-spectrum";
import { ActionButton } from "@react-spectrum/button";
import SwitchIcon from "@spectrum-icons/workflow/Switch";
import { useRouter } from "next/router";
import { FC, PropsWithChildren } from "react";

interface Props {
step: number;
stickers: { id: string; name: string }[];
}

const StepTemplateChanger: FC<Props> = (props) => {
const router = useRouter();
const configString = router.query.config
? `?config=${router.query.config}`
: "";

return (
<MenuTrigger>
<ActionButton>
<SwitchIcon />
<Text>Change Template</Text>
</ActionButton>
<Menu
onAction={(key: any) =>
router.replace(`/edit/${key}/step/${props.step}${configString}`)
}
>
{props.stickers.map((s) => (
<Item key={s.id}>{s.name}</Item>
))}
</Menu>
</MenuTrigger>
);
};

export default StepTemplateChanger;
25 changes: 25 additions & 0 deletions packages/frontend/src/modules/editor/StepToolbarContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { View } from "@adobe/react-spectrum";
import { FC, PropsWithChildren } from "react";

interface Props extends PropsWithChildren {}

const StepToolbarContainer: FC<Props> = (props) => {
return (
<View
UNSAFE_style={{
display: "flex",
justifyContent: "center",
gap: "var(--spectrum-global-dimension-size-65)",
flexWrap: "wrap",
}}
borderWidth="thin"
borderColor="dark"
borderRadius="medium"
padding="size-250"
>
{props.children}
</View>
);
};

export default StepToolbarContainer;
86 changes: 39 additions & 47 deletions packages/frontend/src/modules/export/AddToSetButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
import Export from "@spectrum-icons/workflow/Export";
import { useAtom } from "jotai";
import { useRouter } from "next/router";
import { FC, useCallback, useState } from "react";
import { FC, ReactNode, useCallback, useState } from "react";
import { Lottie, optimizeFilesize } from "tg-sticker-creator";
import { paletteAtom } from "../palette/ColorList";
import { configAtom } from "../stickers/configAtom";
Expand All @@ -18,8 +18,12 @@ import { authAtom } from "./auth";
import { gzip } from "./gzip";
import { saveSticker } from "./requests";

type ActionType = "save" | "add" | "saveAndAdd";

interface Props {
lottie: Lottie;
action: ActionType;
children: ReactNode;
}

const AddToSetButton: FC<Props> = (props) => {
Expand All @@ -30,55 +34,43 @@ const AddToSetButton: FC<Props> = (props) => {
const router = useRouter();
const [loading, setLoading] = useState(false);

const save = useCallback(
async (key: string | number) => {
if (!auth.data || !auth.type) throw new Error("missing auth");
setLoading(true);
try {
const file = await gzip(optimizeFilesize(props.lottie.clone()));
// TODO: refactor
const response = await saveSticker({
settings: JSON.stringify(config),
palette: JSON.stringify(colors),
file,
emojis: sticker.emojis.map((e) => e.emoji).join(""),
authData: auth.data,
authType: auth.type,
sticker: sticker.id,
action: String(key) as "save" | "add" | "saveAndAdd",
});
if (key === "save" || key === "saveAndAdd") {
router.push("/"); // TODO: close gui if used from within bot?
}
console.log("response", response);
} catch (error: any) {
alert(error.message || error); // TODO: proper error handling
console.log(error);
} finally {
setLoading(false);
const save = useCallback(async () => {
if (!auth.data || !auth.type) throw new Error("missing auth");
setLoading(true);
try {
const file = await gzip(optimizeFilesize(props.lottie.clone()));
// TODO: refactor
const response = await saveSticker({
settings: JSON.stringify(config),
palette: JSON.stringify(colors),
file,
emojis: sticker.emojis.map((e) => e.emoji).join(""),
authData: auth.data,
authType: auth.type,
sticker: sticker.id,
action: props.action,
});
if (props.action === "save" || props.action === "saveAndAdd") {
router.push(router.asPath.replace(/step\/\d/, "step/4"));
}
},
[config, colors, sticker, auth, router, setLoading],
);
console.log("response", response);
} catch (error: any) {
alert(error.message || error); // TODO: proper error handling
console.log(error);
} finally {
setLoading(false);
}
}, [config, colors, sticker, auth, router, setLoading, props]);

return (
<div>
<MenuTrigger>
<Button elementType="a" variant="cta">
{loading ? (
<ProgressCircle isIndeterminate variant="overBackground" size="S" />
) : (
<Export />
)}
<Text marginStart="size-100">Save/Upload</Text>
</Button>
<Menu onAction={save}>
<Item key="save">Save</Item>
<Item key="add">Add to Set</Item>
<Item key="saveAndAdd">Save &amp; Add to Set</Item>
</Menu>
</MenuTrigger>
</div>
<Button variant="cta" onPress={save}>
{loading ? (
<ProgressCircle isIndeterminate variant="overBackground" size="S" />
) : (
<Export />
)}
<Text marginStart="size-100">{props.children}</Text>
</Button>
);
};

Expand Down
19 changes: 19 additions & 0 deletions packages/frontend/src/modules/export/ExportButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Button, Text } from "@adobe/react-spectrum";
import Gears from "@spectrum-icons/workflow/Gears";
import { FC } from "react";
import { useExport } from "./useExport";

const ExportButton: FC = () => {
const { downloadJson } = useExport();

return (
<>
<Button variant="secondary" onPress={downloadJson}>
<Gears />
<Text>Character Export to File</Text>
</Button>
</>
);
};

export default ExportButton;
Loading

0 comments on commit 998aa79

Please sign in to comment.