mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 10:47:04 +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,
|
||||
WidthIcon,
|
||||
} 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 { ReactNode, useEffect, useRef, useState } from 'react';
|
||||
import { CopyButton } from '../../../../../components/CopyButton';
|
||||
@@ -30,6 +39,7 @@ import { Size } from './components/Size';
|
||||
import { SizeWithout0 } from './components/SizeWithout0';
|
||||
import { Slider } from './components/Slider';
|
||||
import { Text as TextController } from './components/Text';
|
||||
import { Import } from './components/Import';
|
||||
|
||||
export interface EmbedPreviewControllerProps {
|
||||
configKey: string;
|
||||
@@ -66,7 +76,12 @@ export default function Page({
|
||||
style={{ height: '100%', maxWidth: 320 }}
|
||||
>
|
||||
<Flex direction="column" gap="2" p="4">
|
||||
<Import/>
|
||||
|
||||
<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">
|
||||
<CopyButton
|
||||
@@ -126,6 +141,9 @@ export default function Page({
|
||||
</Flex>
|
||||
|
||||
<Heading>Customize</Heading>
|
||||
<Text size="2" color="gray" mb="2">
|
||||
Bells and whistles of your embed
|
||||
</Text>
|
||||
|
||||
{Object.keys(config).map((configKey) => {
|
||||
const item = config[configKey];
|
||||
|
||||
@@ -21,7 +21,7 @@ const compositeStatsKeysOptions = compositeStatsKeys.map((value) => ({
|
||||
|
||||
export const breakdownConfig = {
|
||||
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 },
|
||||
|
||||
|
||||
@@ -24,12 +24,7 @@ export function BreakdownEmbedWrapper({
|
||||
const { useState } = useEmbedStateCurry<typeof breakdownConfig>();
|
||||
|
||||
return (
|
||||
<Flex
|
||||
direction="column"
|
||||
gap={useState('listGap')}
|
||||
justify="center"
|
||||
height="100%"
|
||||
>
|
||||
<Flex direction="column" gap={useState('listGap')} height="100%">
|
||||
{children}
|
||||
</Flex>
|
||||
);
|
||||
@@ -45,6 +40,7 @@ export function BreakdownEmbedCard({ tank }: BreakdownEmbedCardProps) {
|
||||
|
||||
return (
|
||||
<Flex
|
||||
flexShrink="0"
|
||||
direction="column"
|
||||
style={{
|
||||
borderRadius: toRadiusVar(useState('cardRadius')),
|
||||
|
||||
Reference in new issue
Block a user