Skip to content

Commit

Permalink
Merge pull request #52 from SoyZhou/main
Browse files Browse the repository at this point in the history
fix: type error
  • Loading branch information
zcpua authored Sep 28, 2023
2 parents 823125e + 44dadb5 commit e8e6a73
Show file tree
Hide file tree
Showing 13 changed files with 3,436 additions and 3,214 deletions.
Binary file added images/mj-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
39 changes: 27 additions & 12 deletions layouts/main.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import dynamic from 'next/dynamic'
import Link from 'next/link'
import React, { useEffect, useState } from 'react';
import React, { useEffect, useState, useContext } from 'react';

import {
SmileOutlined,
GithubFilled,
PictureFilled,

} from '@ant-design/icons'
} from '@ant-design/icons';
import { Image, Button } from 'antd';
import MJLogo from '../images/mj-logo.png';

import { Route, MenuDataItem } from '@ant-design/pro-layout/lib/typing'
import { PageContainer, ProConfigProvider } from '@ant-design/pro-components';
import { ProConfigProvider } from '@ant-design/pro-components';

import AuthContext from "../stores/authContext";
import { useRouter } from 'next/router';


const ProLayout = dynamic(() => import('@ant-design/pro-layout'), {
ssr: false,
})
Expand All @@ -19,9 +23,9 @@ const ROUTES: Route = {
path: '/',
routes: [
{
path: '/',
path: '/midjourney',
name: 'MidJourney',
icon: <SmileOutlined />,
icon: <Image src={MJLogo.src} alt='midjourney' width={15} height={15} />,
},
],
}
Expand All @@ -44,6 +48,16 @@ const menuItemRender = (options: MenuDataItem, element: React.ReactNode) => (

export default function Main(children: JSX.Element) {
const [dark, setDark] = useState(false);
const { user, authReady, logout } = useContext(AuthContext);
const router = useRouter();

useEffect(() => {
console.log(user, authReady);
if (authReady && !user) {
router.push('/');
}
}, [authReady, user, router])

useEffect(() => {
// Check the theme when the user first visits the page
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
Expand All @@ -66,17 +80,18 @@ export default function Main(children: JSX.Element) {
dark={dark}
hashed={false}>
<ProLayout
logo={"logo.png"}
logo={"/logo.png"}
title="AI Draw"
style={{ minHeight: '100vh' }}
route={ROUTES}
avatarProps={{
src: 'logo.png',
title: 'Eric',
src: '/logo.png',
title: user?.user_metadata?.full_name,
}}
actionsRender={(props) => {
if (props.isMobile) return [];
if (props.isMobile) return [<Button type="primary" danger ghost onClick={logout} key="logout">Logout</Button>];
return [
<Button type="primary" danger ghost onClick={logout} key="logout">Logout</Button>,
<Link href="https://github.com/erictik/midjourney-ui" key="about">
<GithubFilled style={{
fontSize: 24,
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,11 @@
"dependencies": {
"@ant-design/pro-components": "^2.4.9",
"@ant-design/pro-layout": "^7.10.3",
"@types/netlify-identity-widget": "^1.9.4",
"@vercel/analytics": "^1.0.1",
"eventsource-parser": "^1.0.0",
"midjourney": "^4.3.12",
"netlify-identity-widget": "^1.9.2",
"next": "^13.4.13"
},
"keywords": [
Expand Down
26 changes: 20 additions & 6 deletions pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,28 @@ import "../public/antd.min.css";
import "../styles/globals.css";
import withTheme from "../theme";
import { Analytics } from "@vercel/analytics/react";
import { AuthContextProvider } from "../stores/authContext";
import { useRouter } from 'next/router';

export default function App({ Component, pageProps }: AppProps) {
const router = useRouter();
const useMainLayout = router.pathname !== '/';

return withTheme(
MainLayout(
<>
<Component {...pageProps} />
<Analytics />
</>
)
<AuthContextProvider>
{useMainLayout ?
MainLayout(
<>
<Component {...pageProps} />
<Analytics />
</>
) : (
<>
<Component {...pageProps} />
<Analytics />
</>
)
}
</AuthContextProvider>
);
}
194 changes: 20 additions & 174 deletions pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,183 +1,29 @@
import React, { useState } from "react";
import { Input, Button, List, Image, Typography, Skeleton } from "antd";
import { SendOutlined } from "@ant-design/icons";
import { Imagine, Custom } from "../request";
import { MJMessage } from "midjourney";
import { Message } from "../interfaces/message";

const { TextArea } = Input;
const { Text } = Typography;
import React, { useContext, useEffect } from "react";
import { Divider, Typography } from "antd";
import AuthContext from "../stores/authContext";
import { useRouter } from 'next/router';

const Index: React.FC = () => {
const [inputValue, setInputValue] = useState("");
const [inputDisable, setInputDisable] = useState(false);
const [messages, setMessages] = useState<Message[]>([]);

const handleMessageSend = async () => {
let newMessage: Message = {
text: inputValue.trim(),
prompt: inputValue.trim(),
progress: "waiting start",
img: "",
};

if (newMessage.text) {
const oldMessages = messages;
setInputDisable(true);
setMessages([...oldMessages, newMessage]);
await Imagine(
JSON.stringify({ prompt: newMessage.text }),
(data: MJMessage) => {
console.log(data);
newMessage.img = data.uri;
newMessage.msgHash = data.hash;
newMessage.msgID = data.id;
newMessage.progress = data.progress;
newMessage.content = data.content;
newMessage.flags = data.flags;
newMessage.options = data.options;
setMessages([...oldMessages, newMessage]);
}
);
setInputValue("");
setInputDisable(false);
}
};
const router = useRouter();
const { user, login, authReady } = useContext(AuthContext);

const clickLabel = async (content: string, msgId: string, flags: string, customId: string, label: string, prompt?: string) => {
let newMessage: Message = {
text: `${content} ${label}`,
prompt,
progress: "waiting start",
img: "",
};

const oldMessages = messages;
setInputDisable(true);
setMessages([...oldMessages, newMessage]);
await Custom(
JSON.stringify({ content, msgId, flags, customId, label }),
(data: MJMessage) => {
newMessage.img = data.uri;
newMessage.msgHash = data.hash;
newMessage.msgID = data.id;
newMessage.content = data.content;
newMessage.progress = data.progress;
newMessage.flags = data.flags;
newMessage.options = data.options;
setMessages([...oldMessages, newMessage]);
}
);
setInputDisable(false);
}
const renderMessage = ({
text,
img,
flags,
msgID,
progress,
content,
options,
prompt,
}: Message) => {
if (process.env.NEXT_PUBLIC_IMAGE_PREFIX) {
img = img.replace(
"https://cdn.discordapp.com/",
process.env.NEXT_PUBLIC_IMAGE_PREFIX
);
useEffect(() => {
if (authReady && user) {
router.push('/midjourney');
}
return (
<List.Item
className="flex flex-col space-y-4 justify-start items-start"
style={{
alignItems: "flex-start",
}}
>
<Text>
{text} {`(${progress})`}
</Text>

{
img ? (
<Image className="ml-2 rounded-xl" width={400} src={img} alt="" />
) : (
<Skeleton.Image active />
)
}

<div className="flex flex-wrap">
{
options && options.map(option => (
<Button
key={option.label}
className="m-2"
type="primary"
disabled={["Vary (Region)","Custom Zoom"].indexOf(option.label) > -1}
onClick={() => {
clickLabel(
String(content),
String(msgID),
String(flags),
option.custom,
option.label,
prompt,
);
}}
>
{option.label}
</Button>
))
}
</div>
</List.Item>
);
};
}, [authReady, login, router, user]);

return (
<div className="w-full mx-auto px-4 h-full relative">
<List
style={{
height: "calc(100vh - 96px)",
}}
className="overflow-y-auto w-full"
dataSource={messages}
renderItem={renderMessage}
/>
<div className="absolute z-10 w-3/4 xl:w-3/5 right-0 bottom-10 left-0 mx-auto">
<TextArea
className="w-full"
disabled={inputDisable}
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
onKeyDown={(e) => {
if (e.key === "Enter" && e.shiftKey) {
setInputValue(`${inputValue}\n`);
e.preventDefault();
} else if (e.key === "Enter") {
handleMessageSend();
e.preventDefault();
}
}}
placeholder="Start typing your main idea..."
autoSize={{ minRows: 1, maxRows: 6 }}
style={{ paddingRight: 30 }}
/>
<Button
className="absolute"
type="primary"
onClick={handleMessageSend}
loading={inputDisable}
icon={<SendOutlined style={{ color: "#000" }} />}
title="Send"
style={{
position: "absolute",
bottom: 0,
right: 0,
background: "transparent",
border: "none",
boxShadow: "none",
}}
/>
<div className="login-background p-10 flex items-center justify-around">
<div>
<Typography.Title>AI | MidJourney</Typography.Title>
<Typography.Title>Powered Life</Typography.Title>
</div>
<Divider type="vertical" />
<div>
<button onClick={login} className="bg-white bg-opacity-20 hover:bg-opacity-50 text-white border-white border-2 p-5 rounded-lg text-3xl cursor-pointer">
Launch App
</button>
</div>
</div>
);
Expand Down
Loading

1 comment on commit e8e6a73

@vercel
Copy link

@vercel vercel bot commented on e8e6a73 Sep 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.