Skip to content

Commit

Permalink
Refactor: QrCode & Markdown components (#97)
Browse files Browse the repository at this point in the history
* feat: unify qrcode and improve UI

* feat: unify markdown and fixes
  • Loading branch information
paulclindo authored Nov 29, 2023
1 parent 36173a5 commit bb461f0
Show file tree
Hide file tree
Showing 12 changed files with 129 additions and 90 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ export const ActionButton = () => {
const settings = useSettings((settingsStore) => settingsStore.settings);

const togglePopupVisibility = async () => {
console.log('clicked!');
sendContentScriptMessage({
type: ContentScriptBridgeMessageType.TogglePopupVisibility,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,19 @@ import {
FormItem,
FormLabel,
FormMessage,
QrCodeModal,
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
TextField,
} from '@shinkai_network/shinkai-ui';
import { Download } from 'lucide-react';
import { QRCodeCanvas } from 'qrcode.react';
import { useEffect, useRef, useState } from 'react';
import { useEffect, useState } from 'react';
import { useForm, useWatch } from 'react-hook-form';
import { FormattedMessage, useIntl } from 'react-intl';
import { z } from 'zod';

import shinkaiLogo from '../../assets/icons/shinkai-min.svg';
import { SetupData, useAuth } from '../../store/auth/auth';
import { Header } from '../header/header';

Expand All @@ -47,7 +45,6 @@ export const CreateRegistrationCode = () => {
const intl = useIntl();
type FormSchemaType = z.infer<typeof formSchema>;
const auth = useAuth((state) => state.auth);
const canvasContainer = useRef<HTMLDivElement>(null);
const form = useForm<FormSchemaType>({
resolver: zodResolver(formSchema),
defaultValues: {
Expand All @@ -64,6 +61,8 @@ export const CreateRegistrationCode = () => {
| Partial<SetupData & { registration_code: string; identity_type: string }>
| undefined
>();
const [qrCodeModalOpen, setQrCodeModalOpen] = useState(false);

const { mutateAsync: createRegistrationCode, isPending } =
useCreateRegistrationCode({
onSuccess: (registrationCode) => {
Expand All @@ -90,6 +89,7 @@ export const CreateRegistrationCode = () => {
: {}),
};
setGeneratedSetupData(setupData);
setQrCodeModalOpen(true);
},
});
const identityTypeOptions: { value: IdentityType; label: string }[] = [
Expand Down Expand Up @@ -117,7 +117,7 @@ export const CreateRegistrationCode = () => {
},
];
const submit = async (values: FormSchemaType): Promise<void> => {
createRegistrationCode({
await createRegistrationCode({
permissionsType: values.permissionType,
identityType: values.identityType,
setupPayload: {
Expand All @@ -136,14 +136,9 @@ export const CreateRegistrationCode = () => {
profileName: values.profile,
});
};
const download = (): void => {
const canvas =
canvasContainer?.current?.getElementsByTagName('canvas')?.[1];
if (!canvas) {
return;
}
const download = (dataUrl: string): void => {
const link = document.createElement('a');
link.href = canvas.toDataURL();
link.href = dataUrl;
link.download = 'registration_code.shinkai.png';
link.click();
URL.revokeObjectURL(link.href);
Expand Down Expand Up @@ -256,55 +251,15 @@ export const CreateRegistrationCode = () => {
</form>
</Form>

{generatedSetupData && (
<div className=" flex grow flex-col items-center justify-center space-y-3">
<div className="flex flex-col space-y-1">
<span className="font-semibold">
<FormattedMessage id="scan-or-download-registration-code" />
</span>
<span>
<FormattedMessage id="use-it-to-register-and-connect" />
</span>
</div>
<div className="flex w-full flex-row items-center justify-center">
<div
className="group relative flex flex-col"
ref={canvasContainer}
>
<QRCodeCanvas
imageSettings={{
src: shinkaiLogo,
excavate: true,
height: 24,
width: 24,
}}
level="H"
size={128}
value={JSON.stringify(generatedSetupData)}
/>
<QRCodeCanvas
className="hidden"
imageSettings={{
src: shinkaiLogo,
excavate: true,
height: 24,
width: 24,
}}
level="H"
size={512}
value={JSON.stringify(generatedSetupData)}
/>
<Button
className="invisible absolute bottom-1 right-1 group-hover:visible"
onClick={() => download()}
size="icon"
>
<Download className="h-4 w-4" />
</Button>
</div>
</div>
</div>
)}
<QrCodeModal
description={<FormattedMessage id="use-it-to-register-and-connect" />}
modalClassName={'w-[85%]'}
onOpenChange={setQrCodeModalOpen}
onSave={download}
open={qrCodeModalOpen}
title={<FormattedMessage id="scan-or-download-registration-code" />}
value={JSON.stringify(generatedSetupData)}
/>
</div>
</div>
);
Expand Down
4 changes: 2 additions & 2 deletions apps/shinkai-visor/src/components/inbox/inbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ export const Inbox = () => {
ref={chatContainerRef}
>
{isChatConversationSuccess && (
<div className="py-2 text-center text-xs">
<div className="py-2 text-center text-xs text-gray-100">
{isFetchingPreviousPage && (
<Loader2 className="flex animate-spin justify-center text-white" />
)}
Expand All @@ -199,7 +199,7 @@ export const Inbox = () => {
)}
<div className="">
{isChatConversationLoading && (
<div className="flex flex-col space-y-2">
<div className="flex flex-col space-y-3">
{[...Array(5).keys()].map((index) => (
<div
className={cn(
Expand Down
8 changes: 2 additions & 6 deletions apps/shinkai-visor/src/components/message/message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import {
AvatarFallback,
AvatarImage,
CopyToClipboardIcon,
MarkdownPreview,
} from '@shinkai_network/shinkai-ui';
import { cn } from '@shinkai_network/shinkai-ui/utils';
import MarkdownPreview from '@uiw/react-markdown-preview';

import shinkaiMiniLogo from '../../assets/icons/shinkai-min.svg';
import { srcUrlResolver } from '../../helpers/src-url-resolver';
Expand Down Expand Up @@ -57,11 +57,7 @@ export const Message = ({ message }: MessageProps) => {
string={message.content}
/>
)}
<MarkdownPreview
className="wmde-markdown-var"
source={message.content}
wrapperElement={{ 'data-color-mode': 'dark' }}
/>
<MarkdownPreview source={message.content} />
{!!message.fileInbox?.files?.length && (
<FileList
actions={[]}
Expand Down
4 changes: 2 additions & 2 deletions apps/shinkai-visor/src/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@
"admin": "Admin",
"standard": "Standard",
"none": "None",
"scan-or-download-registration-code": "Scan or download this registration code",
"use-it-to-register-and-connect": "Use this QR code to register a new profile or device and connect to your Shinkai Node",
"scan-or-download-registration-code": "Here's your QR Code",
"use-it-to-register-and-connect": "Scan the QR code with your Shinkai app or download it to register",
"identity-type": "Identity type",
"disconnect-warning-link": "Export your connection",
"disconnect-warning-link-description": "If you want to use it later",
Expand Down
9 changes: 5 additions & 4 deletions apps/shinkai-visor/src/theme/styles.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@import 'tailwindcss/base';
@import 'tailwindcss/utilities';
@import 'tailwindcss/components';
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
@font-face {
Expand All @@ -17,7 +17,8 @@
:host,
body {
.wmde-markdown-var[data-color-mode*='dark'] {
--color-canvas-default: var(--background);
--color-canvas-default: transparent;
--color-border-default: theme('colors.gray.400');
--color-fg-default: theme('colors.white');
@apply text-[15px];
}
Expand Down
2 changes: 1 addition & 1 deletion apps/shinkai-visor/tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ module.exports = {
content: [
join(
__dirname,
'{src,pages,components,app}/**/*!(*.stories|*.spec).{ts,tsx,html}',
'{src,pages,components,app}/**/*!(*.stories|*.spec).{ts,tsx,html,css}',
),
...createGlobPatternsForDependencies(__dirname),
],
Expand Down
22 changes: 22 additions & 0 deletions libs/shinkai-ui/src/components/markdown-preview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import ReactMarkdownPreview from '@uiw/react-markdown-preview';

import { cn } from '../utils';

export const MarkdownPreview = ({
className,
source,
}: {
className?: string;
source?: string;
}) => {
return (
<ReactMarkdownPreview
className={cn(
'wmde-markdown-var prose prose-gray prose-code:text-white prose-blockquote:text-gray-50 prose-blockquote:bg-gray-200',
className,
)}
source={source}
wrapperElement={{ 'data-color-mode': 'dark' }}
/>
);
};
75 changes: 73 additions & 2 deletions libs/shinkai-ui/src/components/qr-code.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import React from 'react';
import { DownloadIcon } from '@radix-ui/react-icons';
import { Check } from 'lucide-react';
import React, { useState } from 'react';
import type { IProps } from 'react-qrcode-logo';
import { QRCode as ReactQRCode } from 'react-qrcode-logo';

import shinkaiLogo from '../assets/app-icon.png';
import { Button } from './button';
import { Dialog, DialogContent } from './dialog';

export default function QRCode({
export function QRCode({
value,
size,
id,
Expand All @@ -30,3 +34,70 @@ export default function QRCode({
/>
);
}

export function QrCodeModal({
open,
onOpenChange,
value,
onSave,
title,
description,
modalClassName,
}: {
open: boolean;
onOpenChange: (open: boolean) => void;
value: IProps['value'];
onSave: (key: string) => void;
title: React.ReactNode;
description: React.ReactNode;
modalClassName?: string;
}) {
const [saved, setSaved] = useState(false);
const downloadCode = async () => {
const canvas = document.querySelector('#registration-code-qr');
if (canvas instanceof HTMLCanvasElement) {
try {
const pngUrl = canvas.toDataURL();
onSave(pngUrl);
setSaved(true);
} catch (error) {
console.error(error);
} finally {
setTimeout(() => {
setSaved(false);
}, 3000);
}
}
};

return (
<Dialog onOpenChange={onOpenChange} open={open}>
<DialogContent className={modalClassName}>
<div className="flex flex-col items-center py-4">
<h2 className="mb-1 text-lg font-semibold">{title}</h2>
<p className="text-foreground text-gray-80 mb-5 text-center text-xs">
{description}
</p>
<div className="mb-7 overflow-hidden rounded-lg shadow-2xl">
<QRCode id="registration-code-qr" size={190} value={value} />
</div>
<div className="flex flex-col gap-4">
<Button className="flex gap-1" onClick={downloadCode}>
{saved ? <Check /> : <DownloadIcon className="h-4 w-4" />}
{saved ? 'Saved' : 'Download'}
</Button>
<Button
className="flex gap-1"
onClick={() => {
onOpenChange(false);
}}
variant="ghost"
>
I saved it, close
</Button>
</div>
</div>
</DialogContent>
</Dialog>
);
}
1 change: 1 addition & 0 deletions libs/shinkai-ui/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ export * from './components/textarea';
export * from './components/tooltip';
export * from './components/dropdown-menu';
export * from './components/textfield';
export * from './components/markdown-preview';
11 changes: 2 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit bb461f0

Please sign in to comment.