Skip to content

Commit 0c85e11

Browse files
committed
update user flow and prompts
1 parent 8147412 commit 0c85e11

File tree

7 files changed

+98
-35
lines changed

7 files changed

+98
-35
lines changed

apps/quick-dapp/src/actions/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,11 +250,13 @@ export const emptyInstance = async () => {
250250
address: '',
251251
network: '',
252252
htmlTemplate: '',
253+
pages: {},
253254
abi: {},
254255
items: {},
255256
containers: [],
256257
title: '',
257258
details: '',
259+
logo: null,
258260
theme: 'Dark',
259261
userInput: { methods: {} },
260262
natSpec: { checked: false, methods: {} },

apps/quick-dapp/src/components/DeployPanel/index.tsx

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useContext, useState, useEffect } from 'react';
1+
import React, { useContext, useState, useEffect, useRef } from 'react';
22
import { Form, Button, Alert, Card, Row, Col, Collapse } from 'react-bootstrap';
33
import { ethers, namehash } from 'ethers';
44
import { FormattedMessage, useIntl } from 'react-intl';
@@ -46,6 +46,15 @@ function DeployPanel(): JSX.Element {
4646
const [isPublishOpen, setIsPublishOpen] = useState(true);
4747
const [isEnsOpen, setIsEnsOpen] = useState(true);
4848

49+
const logoInputRef = useRef<HTMLInputElement>(null);
50+
51+
const handleRemoveLogo = () => {
52+
dispatch({ type: 'SET_INSTANCE', payload: { logo: null } });
53+
if (logoInputRef.current) {
54+
logoInputRef.current.value = '';
55+
}
56+
};
57+
4958
const handleImageChange = (e) => {
5059
if (e.target.files && e.target.files[0]) {
5160
const reader: any = new FileReader()
@@ -370,7 +379,18 @@ function DeployPanel(): JSX.Element {
370379
<Card.Body id="dapp-details-collapse">
371380
<Form.Group className="mb-3" controlId="formDappLogo">
372381
<Form.Label className="text-uppercase mb-0">Dapp logo</Form.Label>
382+
{logo && logo.byteLength > 0 && (
383+
<span
384+
onClick={handleRemoveLogo}
385+
style={{ cursor: 'pointer', fontSize: '0.8rem' }}
386+
className="ms-1"
387+
title="Remove logo"
388+
>
389+
<i className="fas fa-trash me-1"></i>
390+
</span>
391+
)}
373392
<Form.Control
393+
ref={logoInputRef}
374394
type="file"
375395
accept="image/*"
376396
onChange={handleImageChange}

apps/quick-dapp/src/components/EditHtmlTemplate/index.tsx

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ function EditHtmlTemplate(): JSX.Element {
4343
const [showIframe, setShowIframe] = useState(true);
4444
const [isBuilderReady, setIsBuilderReady] = useState(false);
4545
const [isBuilding, setIsBuilding] = useState(false);
46+
const [isAiUpdating, setIsAiUpdating] = useState(false);
4647

4748
const iframeRef = useRef<HTMLIFrameElement>(null);
4849
const builderRef = useRef<InBrowserVite | null>(null);
@@ -188,6 +189,8 @@ function EditHtmlTemplate(): JSX.Element {
188189
}
189190

190191
const handleChatMessage = async (message: string) => {
192+
setIsAiUpdating(true);
193+
191194
try {
192195
const currentFiles = new Map<string, string>();
193196
await readDappFiles('dapp', currentFiles);
@@ -243,12 +246,13 @@ function EditHtmlTemplate(): JSX.Element {
243246
}
244247

245248
await Promise.all(writePromises);
246-
runBuild();
247249

248250
} catch (error) {
249251
const errorMsg = (error instanceof Error) ? error.message : String(error);
250252
console.error('[DEBUG-LOG E] (ERROR) handleChatMessage:', errorMsg);
251253
setIframeError('Failed to update DApp via AI: ' + errorMsg);
254+
} finally {
255+
setIsAiUpdating(false);
252256
}
253257
};
254258

@@ -289,6 +293,14 @@ function EditHtmlTemplate(): JSX.Element {
289293
}
290294
}, [isBuilderReady, htmlTemplate]);
291295

296+
useEffect(() => {
297+
if (isBuilderReady && !isAiUpdating && htmlTemplate) {
298+
setTimeout(() => {
299+
runBuild();
300+
}, 0);
301+
}
302+
}, [isBuilderReady, isAiUpdating, htmlTemplate]);
303+
292304
return (
293305
<Row className="m-0 h-100">
294306
<Col xs={12} lg={8} className="pe-3 d-flex flex-column h-100">
@@ -315,7 +327,14 @@ function EditHtmlTemplate(): JSX.Element {
315327
</div>
316328
<Card className="border flex-grow-1 d-flex">
317329
<Card.Body className="p-0 d-flex flex-column">
318-
{showIframe ? (
330+
{isAiUpdating ? (
331+
<div className="d-flex flex-column align-items-center justify-content-center h-100 text-center p-4" style={{ minHeight: '400px' }}>
332+
<i className="fas fa-spinner fa-spin fa-2x mb-3 text-primary"></i>
333+
<h6 className="text-muted">
334+
Your dapp is being created by RemixAI Assistant.
335+
</h6>
336+
</div>
337+
) : showIframe ? (
319338
<iframe
320339
ref={iframeRef}
321340
style={{

apps/quick-dapp/src/reducers/state.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export const appInitialState: any = {
1111
theme: 'Dark',
1212
userInput: { methods: {} },
1313
natSpec: { checked: false, methods: {} },
14+
logo: null,
1415
},
1516
};
1617

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import { PluginClient } from '@remixproject/plugin';
22
import { createClient } from '@remixproject/plugin-webview';
3-
import { initInstance } from './actions';
3+
import { initInstance, emptyInstance } from './actions';
44

55
class RemixClient extends PluginClient {
66
constructor() {
77
super();
8+
this.methods = ['edit', 'clearInstance'];
89
createClient(this);
910
}
1011

11-
edit({ address, abi, network, name, devdoc, methodIdentifiers, solcVersion, htmlTemplate }: any): void {
12+
edit({ address, abi, network, name, devdoc, methodIdentifiers, solcVersion, htmlTemplate, pages }: any): void {
1213
initInstance({
1314
address,
1415
abi,
@@ -17,9 +18,14 @@ class RemixClient extends PluginClient {
1718
devdoc,
1819
methodIdentifiers,
1920
solcVersion,
20-
htmlTemplate
21+
htmlTemplate,
22+
pages
2123
});
2224
}
25+
26+
clearInstance(): void {
27+
emptyInstance();
28+
}
2329
}
2430

2531
export default new RemixClient();

apps/remix-ide/src/app/plugins/prompt.ts

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ You MUST generate separate files for HTML, CSS, and JavaScript (JSX).
2323
You MUST use React with JSX syntax (not "text/babel" scripts).
2424
You MUST use ethers.js (v6) for all blockchain interactions.
2525
The user's contract address, ABI, and network info will be provided in the main prompt.
26+
**Design Requirement:** You MUST intelligently place the 'logo', 'title', and 'details' from \`window.__QUICK_DAPP_CONFIG__\` into the UI (e.g., placing the logo/title in a Navbar and details in a Hero section), do not just dump them at the top.
2627
2728
Return EACH file using the specified "TITLE_PAGE_START" format.
2829
The file structure MUST be:
@@ -94,20 +95,23 @@ const App = () => {
9495
const dappTitle = config.title || "My DApp";
9596
const dappDetails = config.details || "My DApp Description";
9697
97-
// AI-generated React logic will go here
98+
// AI-generated React logic will go here.
99+
// IMPORTANT: Use the variables above in a nice layout (Navbar, Hero, etc).
98100
return (
99-
<div>
100-
{logoDataUrl && (
101-
<img
102-
src={logoDataUrl}
103-
alt="DApp Logo"
104-
style={{ maxHeight: '80px', margin: '1rem auto' }}
105-
/>
106-
)}
107-
<h1>{dappTitle}</h1>
108-
<p>{dappDetails}</p>
109-
110-
{/* AI-generated UI will go here */}
101+
<div className="min-h-screen bg-gray-50">
102+
{/* Dynamic Navbar Example */}
103+
<nav className="bg-white shadow p-4 flex items-center justify-between">
104+
<div className="flex items-center">
105+
{logoDataUrl && <img src={logoDataUrl} alt="Logo" className="h-8 w-auto mr-3" />}
106+
<h1 className="text-xl font-bold">{dappTitle}</h1>
107+
</div>
108+
</nav>
109+
110+
<main className="container mx-auto p-6">
111+
<p className="text-gray-600 mb-8">{dappDetails}</p>
112+
113+
{/* AI-generated UI interaction logic will go here */}
114+
</main>
111115
</div>
112116
);
113117
};
@@ -123,6 +127,7 @@ You MUST generate separate files for HTML, CSS, and JavaScript (JSX).
123127
You MUST use React with JSX syntax (not "text/babel" scripts).
124128
You MUST use ethers.js (v6) for all blockchain interactions.
125129
The user's contract address, ABI, and network info will be provided in the main prompt.
130+
**Design Requirement:** You MUST intelligently place the 'logo', 'title', and 'details' from \`window.__QUICK_DAPP_CONFIG__\` into the UI (e.g., placing the logo/title in a Navbar and details in a Hero section), do not just dump them at the top.
126131
127132
Return EACH file using the specified "TITLE_PAGE_START" format.
128133
The file structure MUST be:
@@ -194,20 +199,23 @@ const App = () => {
194199
const dappTitle = config.title || "My DApp";
195200
const dappDetails = config.details || "My DApp Description";
196201
197-
// AI-generated React logic will go here
202+
// AI-generated React logic will go here.
203+
// IMPORTANT: Use the variables above in a nice layout (Navbar, Hero, etc).
198204
return (
199-
<div>
200-
{logoDataUrl && (
201-
<img
202-
src={logoDataUrl}
203-
alt="DApp Logo"
204-
style={{ maxHeight: '80px', margin: '1rem auto' }}
205-
/>
206-
)}
207-
<h1>{dappTitle}</h1>
208-
<p>{dappDetails}</p>
209-
210-
{/* AI-generated UI will go here */}
205+
<div className="min-h-screen bg-gray-50">
206+
{/* Dynamic Navbar Example */}
207+
<nav className="bg-white shadow p-4 flex items-center justify-between">
208+
<div className="flex items-center">
209+
{logoDataUrl && <img src={logoDataUrl} alt="Logo" className="h-8 w-auto mr-3" />}
210+
<h1 className="text-xl font-bold">{dappTitle}</h1>
211+
</div>
212+
</nav>
213+
214+
<main className="container mx-auto p-6">
215+
<p className="text-gray-600 mb-8">{dappDetails}</p>
216+
217+
{/* AI-generated UI interaction logic will go here */}
218+
</main>
211219
</div>
212220
);
213221
};

libs/remix-ui/run-tab/src/lib/components/universalDappUI.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -316,13 +316,13 @@ export function UniversalDappUI(props: UdappProps) {
316316
<div className="mb-2">
317317
<span>Please describe how you would want the design to look like.</span>
318318
</div>
319-
<div>A new tab with the new website when the generation is done. This might take up to 2 minutes.</div>
320-
<button className="btn btn-secondary btn-sm ms-2" onClick={async () => {
319+
<div>This might take up to 2 minutes.</div>
320+
{/* <button className="btn btn-secondary btn-sm ms-2" onClick={async () => {
321321
await props.plugin.call('ai-dapp-generator', 'resetDapp', address)
322322
const lastGenerated = await props.plugin.call('ai-dapp-generator', 'getLastGeneratedDapp', address)
323323
props.editInstance(address, props.instance.abi, props.instance.name, data.artefact.devdoc, data.artefact.metadata, lastGenerated)
324324
props.plugin.call('manager', 'deactivatePlugin', 'iframeContent')
325-
}}>Reset Dapp</button>
325+
}}>Reset Dapp</button> */}
326326
</ul>
327327
)
328328
const modalContent = {
@@ -341,6 +341,13 @@ export function UniversalDappUI(props: UdappProps) {
341341
props.plugin.call('notification', 'modal', modalContent)
342342
})
343343

344+
await props.plugin.call('ai-dapp-generator', 'resetDapp', address)
345+
try {
346+
await props.plugin.call('quick-dapp', 'clearInstance')
347+
} catch (e) {
348+
console.warn('Quick Dapp clean up failed (plugin might not be loaded yet):', e)
349+
}
350+
344351
// Use the AI DApp Generator plugin
345352
await generateAIDappWithPlugin(description, address, data, props)
346353
} catch (error) {

0 commit comments

Comments
 (0)