mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-23 19:49:50 +02:00
feat: import
This commit is contained in:
1 parent
1359452f67
commit
34c2cfdb2a
4 files changed
+102
-8
No files matched your search
@@ -0,0 +1,80 @@
|
|||||||
|
import {
|
||||||
|
AlertDialog,
|
||||||
|
Button,
|
||||||
|
Flex,
|
||||||
|
Heading,
|
||||||
|
Text,
|
||||||
|
TextField,
|
||||||
|
Tooltip,
|
||||||
|
} from '@radix-ui/themes';
|
||||||
|
import { useRef, useState } from 'react';
|
||||||
|
import * as EmbedState from '../../../../../../stores/embedState';
|
||||||
|
|
||||||
|
export function Import() {
|
||||||
|
const importInput = useRef<HTMLInputElement>(null);
|
||||||
|
const [showInvalidURLPrompt, setShowInvalidURLPrompt] = useState(false);
|
||||||
|
const [showConfirmation, setConfirmation] = useState(false);
|
||||||
|
const mutateEmbedState = EmbedState.useMutation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Heading>Import</Heading>
|
||||||
|
<Text size="2" color="gray" mb="2">
|
||||||
|
Paste your current URL if you have one already to import your settings
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<AlertDialog.Root
|
||||||
|
open={showInvalidURLPrompt}
|
||||||
|
onOpenChange={setShowInvalidURLPrompt}
|
||||||
|
>
|
||||||
|
<AlertDialog.Content>
|
||||||
|
<AlertDialog.Title>Invalid URL</AlertDialog.Title>
|
||||||
|
<AlertDialog.Description>
|
||||||
|
Try pasting the URL that BlitzKit previously generated, you silly
|
||||||
|
goose!
|
||||||
|
</AlertDialog.Description>
|
||||||
|
|
||||||
|
<Flex gap="3" mt="4" justify="end">
|
||||||
|
<AlertDialog.Cancel>
|
||||||
|
<Button>Okay, my bad</Button>
|
||||||
|
</AlertDialog.Cancel>
|
||||||
|
</Flex>
|
||||||
|
</AlertDialog.Content>
|
||||||
|
</AlertDialog.Root>
|
||||||
|
|
||||||
|
<Flex gap="2" mb="6">
|
||||||
|
<TextField.Root
|
||||||
|
ref={importInput}
|
||||||
|
placeholder="Paste URL..."
|
||||||
|
style={{ flex: 1 }}
|
||||||
|
/>
|
||||||
|
<Tooltip content="Applied!" open={showConfirmation}>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
if (!importInput.current) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const url = new URL(importInput.current.value);
|
||||||
|
const state = url.searchParams.get('state');
|
||||||
|
if (state === null) throw undefined;
|
||||||
|
const json = JSON.parse(state);
|
||||||
|
|
||||||
|
mutateEmbedState((draft) => {
|
||||||
|
Object.assign(draft, json);
|
||||||
|
});
|
||||||
|
|
||||||
|
importInput.current.value = '';
|
||||||
|
setConfirmation(true);
|
||||||
|
setTimeout(() => setConfirmation(false), 2000);
|
||||||
|
} catch {
|
||||||
|
setShowInvalidURLPrompt(true);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Apply
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
</Flex>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -8,7 +8,16 @@ import {
|
|||||||
TimerIcon,
|
TimerIcon,
|
||||||
WidthIcon,
|
WidthIcon,
|
||||||
} from '@radix-ui/react-icons';
|
} from '@radix-ui/react-icons';
|
||||||
import { Box, Button, Flex, Heading, ScrollArea, Text } from '@radix-ui/themes';
|
import {
|
||||||
|
AlertDialog,
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
Flex,
|
||||||
|
Heading,
|
||||||
|
ScrollArea,
|
||||||
|
Text,
|
||||||
|
TextField,
|
||||||
|
} from '@radix-ui/themes';
|
||||||
import { capitalize, startCase } from 'lodash';
|
import { capitalize, startCase } from 'lodash';
|
||||||
import { ReactNode, useEffect, useRef, useState } from 'react';
|
import { ReactNode, useEffect, useRef, useState } from 'react';
|
||||||
import { CopyButton } from '../../../../../components/CopyButton';
|
import { CopyButton } from '../../../../../components/CopyButton';
|
||||||
@@ -30,6 +39,7 @@ import { Size } from './components/Size';
|
|||||||
import { SizeWithout0 } from './components/SizeWithout0';
|
import { SizeWithout0 } from './components/SizeWithout0';
|
||||||
import { Slider } from './components/Slider';
|
import { Slider } from './components/Slider';
|
||||||
import { Text as TextController } from './components/Text';
|
import { Text as TextController } from './components/Text';
|
||||||
|
import { Import } from './components/Import';
|
||||||
|
|
||||||
export interface EmbedPreviewControllerProps {
|
export interface EmbedPreviewControllerProps {
|
||||||
configKey: string;
|
configKey: string;
|
||||||
@@ -66,7 +76,12 @@ export default function Page({
|
|||||||
style={{ height: '100%', maxWidth: 320 }}
|
style={{ height: '100%', maxWidth: 320 }}
|
||||||
>
|
>
|
||||||
<Flex direction="column" gap="2" p="4">
|
<Flex direction="column" gap="2" p="4">
|
||||||
|
<Import/>
|
||||||
|
|
||||||
<Heading>Export</Heading>
|
<Heading>Export</Heading>
|
||||||
|
<Text size="2" color="gray" mb="2">
|
||||||
|
Copy all properties for you streaming software
|
||||||
|
</Text>
|
||||||
|
|
||||||
<Flex mb="6" gap="2" wrap="wrap">
|
<Flex mb="6" gap="2" wrap="wrap">
|
||||||
<CopyButton
|
<CopyButton
|
||||||
@@ -126,6 +141,9 @@ export default function Page({
|
|||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
<Heading>Customize</Heading>
|
<Heading>Customize</Heading>
|
||||||
|
<Text size="2" color="gray" mb="2">
|
||||||
|
Bells and whistles of your embed
|
||||||
|
</Text>
|
||||||
|
|
||||||
{Object.keys(config).map((configKey) => {
|
{Object.keys(config).map((configKey) => {
|
||||||
const item = config[configKey];
|
const item = config[configKey];
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ const compositeStatsKeysOptions = compositeStatsKeys.map((value) => ({
|
|||||||
|
|
||||||
export const breakdownConfig = {
|
export const breakdownConfig = {
|
||||||
width: { type: EmbedItemType.Slider, default: 320, min: 128, max: 640 },
|
width: { type: EmbedItemType.Slider, default: 320, min: 128, max: 640 },
|
||||||
height: { type: EmbedItemType.Slider, default: 640, min: 128, max: 1024 },
|
height: { type: EmbedItemType.Slider, default: 492, min: 128, max: 1024 },
|
||||||
|
|
||||||
showTotal: { type: EmbedItemType.Boolean, default: true, pad: true },
|
showTotal: { type: EmbedItemType.Boolean, default: true, pad: true },
|
||||||
|
|
||||||
|
|||||||
@@ -24,12 +24,7 @@ export function BreakdownEmbedWrapper({
|
|||||||
const { useState } = useEmbedStateCurry<typeof breakdownConfig>();
|
const { useState } = useEmbedStateCurry<typeof breakdownConfig>();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex direction="column" gap={useState('listGap')} height="100%">
|
||||||
direction="column"
|
|
||||||
gap={useState('listGap')}
|
|
||||||
justify="center"
|
|
||||||
height="100%"
|
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
@@ -45,6 +40,7 @@ export function BreakdownEmbedCard({ tank }: BreakdownEmbedCardProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
|
flexShrink="0"
|
||||||
direction="column"
|
direction="column"
|
||||||
style={{
|
style={{
|
||||||
borderRadius: toRadiusVar(useState('cardRadius')),
|
borderRadius: toRadiusVar(useState('cardRadius')),
|
||||||
|
|||||||
Reference in new issue
Block a user