-
-
Commit Summary
-
- File: ${codeInfo.fileName}
- Type: ${codeInfo.artifactType}
- Size: ${(codeInfo.content.length / 1024).toFixed(1)} KB
- Lines: ${codeInfo.content.split("\n").length}
-
-
- `;
-
- if (checks.warnings.length > 0) {
- summaryHtml += `
-
-
Warnings (${checks.warnings.length})
-
- ${checks.warnings.map((w) => `- • ${w}
`).join("")}
-
-
- `;
- }
-
- if (checks.issues.length > 0) {
- summaryHtml += `
-
-
Issues (${checks.issues.length})
-
- ${checks.issues.map((i) => `- • ${i}
`).join("")}
-
-
- `;
- }
-
- summaryHtml += "
";
-
- console.log("Pre-commit summary:", summaryHtml);
-
- if (!checks.canProceed) {
- return false;
- }
-
- if (checks.warnings.length > 0) {
- return confirm(
- `Found ${checks.warnings.length} warning(s). Proceed with commit?\n\n${checks.warnings.join("\n")}`,
- );
- }
-
- return true;
-}
-
// --- FILE VALIDATION FUNCTIONS ---
/**
@@ -2732,7 +2763,8 @@ async function executeCommit(code, options = {}) {
// Step 3: Validate FlutterFlow credentials
commitState.setState(CommitState.VALIDATING);
const apiKey = await getApiKey("flutterflow");
- const projectId = await getApiKey("flutterflow_project_id");
+ const projectId =
+ commitTargetProjectId || (await getApiKey("flutterflow_project_id"));
if (!apiKey) {
throw new Error(
@@ -2918,7 +2950,8 @@ async function executeBundleCommit(bundlePlan, options = {}) {
commitState.setState(CommitState.VALIDATING);
const apiKey = await getApiKey("flutterflow");
- const projectId = await getApiKey("flutterflow_project_id");
+ const projectId =
+ commitTargetProjectId || (await getApiKey("flutterflow_project_id"));
if (!apiKey) {
throw new Error("FlutterFlow API Key not configured. Please add it in API Keys settings.");
@@ -3028,13 +3061,16 @@ async function executeBundleCommit(bundlePlan, options = {}) {
// --- PIPELINE FUNCTIONS ---
-async function runPromptArchitect(userInput) {
+async function runPromptArchitect(userInput, images = []) {
+ const context = createBuildShipContext("architect")
+ if (images.length) context.images = images
try {
const result = await callBuildShip(
"architect",
PROMPT_ARCHITECT_MODEL,
buildArchitectPrompt(userInput),
- createBuildShipContext("architect"),
+ context,
+ images,
)
return result
} catch (error) {
@@ -3501,7 +3537,10 @@ async function runThinkingPipeline() {
updatePipelineProgressStep(1);
showStepLoading(1, true);
- pipelineState.step1Result = await runPromptArchitect(userInput);
+ pipelineState.step1Result = await runPromptArchitect(
+ userInput,
+ promptImages.map((img) => img.dataUrl),
+ );
updateBundleSpecFromArchitectResult();
trackEvent("Prompt Architect Completed");
@@ -3684,36 +3723,14 @@ async function initiateCommitToFlutterFlow() {
const checks = runPreCommitChecks(codeInfo);
- const shouldProceed = await showPreCommitSummary(codeInfo, checks);
-
- if (!shouldProceed) {
- console.log("User cancelled commit");
+ if (!checks.canProceed) {
+ showToast(`Pre-commit checks failed: ${checks.issues.join("; ")}`, "error");
return;
}
- showCommitProgress({
- withProvisioning: codeInfo.codeType === CodeType.CODE_FILE,
- });
- trackEvent("Deploy to FlutterFlow Started", { artifactType, artifactName });
-
- const result = await executeCommit(code, {
- artifactType,
- artifactName,
- pipelineResult: {
- step1Result: pipelineState.step1Result,
- selectedModel: document.getElementById("code-generator-model")?.value,
- },
- });
-
- hideCommitProgress();
-
- if (result.success) {
- trackEvent("Deploy to FlutterFlow Success", { artifactType, artifactName });
- showCommitSuccessModal(result);
- } else {
- trackEvent("Deploy to FlutterFlow Failed", { artifactType, artifactName, error: result.error });
- showCommitFailureModal(result);
- }
+ // Route through the shared confirm modal so the user picks the target
+ // FlutterFlow project right before deploying.
+ openCommitConfirmModal(codeInfo, checks, null, null);
}
async function initiateBundleCommitToFlutterFlow() {
@@ -4410,6 +4427,7 @@ function updateModelSelectorGating() {
openPricingModal()
}
updateModelInfo(select.value)
+ updatePromptImageAvailability()
})
proGateAttachedSet.add(select)
}
@@ -4603,10 +4621,11 @@ async function openCustomerPortal() {
}
}
-async function callBuildShip(step, model, prompt, context = {}) {
+async function callBuildShip(step, model, prompt, context = {}, images = []) {
const BUILDSHIP_TIMEOUT_MS = 120000
const controller = new AbortController()
const timeoutId = setTimeout(() => controller.abort(), BUILDSHIP_TIMEOUT_MS)
+
try {
const res = await fetch(PIPELINE_ENDPOINT, {
method: 'POST',
@@ -4617,6 +4636,7 @@ async function callBuildShip(step, model, prompt, context = {}) {
step,
model,
prompt,
+ images,
context,
}),
})
@@ -4711,6 +4731,7 @@ function updateSubscriptionUI() {
updatePricingModalState(resolved ? tier : null)
updateModelSelectorGating()
+ updatePromptImageAvailability()
updateUsageDisplay()
}
@@ -4900,6 +4921,63 @@ function dismissWelcomeVideo() {
// Store commit data for confirmation
let pendingCommitData = null;
+/**
+ * Populates the deploy-time project dropdown in the commit confirm modal,
+ * defaulting to the project configured in API Keys so the stored choice is
+ * pre-selected but the final target can be changed before committing.
+ */
+async function populateConfirmProjectSelect() {
+ const select = document.getElementById("confirm-project-select");
+ if (!select) return;
+
+ const apiKey = await getApiKey("flutterflow");
+ const storedId = await getApiKey("flutterflow_project_id");
+
+ if (!apiKey) {
+ select.innerHTML =
+ '