1 2!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="a53a8c8b-8f8d-5405-9b10-4843fff2ff9f")}catch(e){}}(); 3import { a as __toCommonJS, n as __esmMin, o as __toESM, r as __exportAll, t as __commonJSMin } from "./rolldown-runtime.D1cXj70v.js"; 4import { U as keyframes, V as init_emotion_react_browser_esm, X as require_jsx_runtime, dt as require_react, t as require_material } from "./vendor~index~newNavigation~AccountTierManagementPage~AdminContainer~AISystemPromptManager~C~h0mf93xb.B-8UGg7U.js"; 5import { Gn as v4 } from "./vendor~index~newNavigation~AccountTierManagementPage~AdminContainer~AISystemPromptManager~C~hh2h6ti1.CxCdS9_4.js"; 6import { V as require_faCircleCheck, d as quill_default, f as Embed, h as require_faSparkles, n as require_faArrowDown, p as init_embed, t as require_dist$2, u as init_quill, x as require_faAngleRight, y as require_faArrowUp } from "./vendor~index~newNavigation~AccountTierManagementPage~AdminContainer~AISystemPromptManager~S~d59nl763.C6LdGoX3.js"; 7import { At as gqlEditorProgramToEditorVideoItem, Br as isFeatureEnabled, Dr as localEditorUserNameVar, Fi as PendoService, Ks as isEditorAccountLibraryProgram, Ni as UploadOrigin, Oc as isPlaceholderValueNotEmpty, Ol as ORIGIN_LANGUAGE, Ot as gqlAccountProgramFolderToVideoFolderItem, Pi as UploadedGettyUrlTarget, Rr as getApolloClient, Tc as isPlaceholderContentNoRulesWithPersonalization, Vd as aiVideoGeneratedSnackbarVar, Vr as getUserData, at as upsertEditorUploadedGettyUrl, dt as ARCHIVE_FOLDER_NAME, if as programAccessVar, it as removeEditorUploadedGettyUrl, kt as gqlBuilderProgramToBuilderVideoItem, sh as EditorLibraryMediaType, so as featureFlagConst, tt as setSuccessNotification, uf as videosAndFoldersVar, ut as AI_VIDEO_DRAFTS_FOLDER_NAME, yr as localEditorSelectedSceneIdVar, zd as activeAccountIdVar } from "./logReportUtils.Ca-hg6bk.js"; 8import { a as SskyErrorCode } from "./errors.BNgEQKEw.js"; 9import { a as useMutation } from "./vendor~index~newNavigation~AccountTierManagementPage~AdminContainer~AISystemPromptManager~C~lx5ijrxx.Ds2KGt5R.js"; 10import { t as useReactiveVar } from "./useReactiveVar.mh1GCYBn.js"; 11import { $r as GqlClientAiGeneratedAssetAspectRatio, Cp as useEditorProgramQuery, Ha as GqlClientMediaOrigin, Mu as VideoListWithUserAccessDocument, Oa as GqlClientGenerateMotionPromptFromVideoPromptResult, Os as GqlClientUploadEditorAssetFromUrlMediaSource, Ps as GqlClientUserRole, Sa as GqlClientFeatureTypeDefinition, Tr as GetVideoListDocument, Ua as GqlClientMediaType, Xr as GqlClientAiCameraAngle, Yr as GqlClientAiAspectRatio, Zr as GqlClientAiCameraMotion, _ as AiVideoAssetGeneratedDocument, a as AccountTemplatesDocument, ao as GqlClientProgramAccessLevel, ar as GenerateAiVideoFirstFrameDocument, bn as EditAiVideoFirstFrameDocument, cg as useUserSettingsQuery, ei as GqlClientAiImageService, fi as GqlClientAssetLifecycleStage, ia as GqlClientEditAiImageResult, ir as GenerateAiVideoAssetDocument, js as GqlClientUserAccountRole, nr as GenerateAiImageDocument, o as AccountTemplatesWithUserAccessDocument, oa as GqlClientEditorFlexiblePlaceholderParentType, oo as GqlClientProgramDefaultAccessLevel, rr as GenerateAiImageFromTextDocument, sr as GenerateMotionPromptFromVideoPromptDocument, ti as GqlClientAiImageStyle, wi as GqlClientCcWireframeCategory, yn as EditAiImageDocument } from "./graphqlClient.B8mBnpI6.js"; 12import { t as require_faInfoCircle } from "./faInfoCircle.D2subuiD.js"; 13import { t as FontAwesomeIcon } from "./dist.D6-c0JAy.js"; 14import { n as require_faPlus } from "./faStar.DAIrK_E4.js"; 15import { i as require_faComments, l as require_faBell } from "./faLinkedinIn.SKs0Z1rb.js"; 16import { t as require_faArrowLeft } from "./faArrowLeft.D1FHtZ5c.js"; 17import { n as require_faCopy } from "./faArrowsRotate.DLJqrJfV.js"; 18import { n as addTokenHeadersAndFullStory } from "./BaseServices.4Ft7aD2s.js"; 19import { t as executeBackgroundMutation } from "./backgroundMutation.BU4o3Ftb.js"; 20import { At as FinalStep, Bn as useAssetLibraryMedia, C as getNarrationTextAndRate, Fn as getFolderName, Ft as useAiGenerationDialogOpen, G as useStudioElements, Gn as MoveToFolderDialog, It as useSetAiGenerationDialogInfo, Kn as MoveToFolderDialogActions, L as isContentEmpty, Mt as PreviewTrigger, Nn as createEditorAssetFolder, Nt as VideoDurationEnum, Ot as AiMediaGenerationMode, Pt as getVideoDurationSeconds, Q as setUserSettings, Rn as moveEditorAssetToFolder, S as getNarrationPlaceholder, Vt as AssetPreviewDialog, X as useScene, Xn as require_faFolderPlus, Xr as selectScene, Xt as AssetThumbnail, Y as useSelectedFrame, Z as getAssetSourceContributions, _n as PreviewAssetDialogPaperProps, cn as uploadEditorAssetMediaFromUrl, er as disableUndoKeyboardShortcuts, gn as ItemType, in as require_faArrowUpRightAndArrowDownLeftFromCenter, jt as OperationType, kt as AiVideoGenerationStep, on as handleExternalAssetUpload, rn as require_faSparkles$1, sn as handleUploadAiImageAsset, vn as validateEditedFolderName, y as AI_error_optimized_default } from "./useRecordingToolPermissionDenied.92r8bUgj.js"; 21import { N as isPlaceholderUsingRules } from "./FileUploadUtils.BXOloZR_.js"; 22import { o as useUserData } from "./model.fbsYc69Q.js"; 23import { t as require_faPaperPlane } from "./faPaperPlane.BGGODIHD.js"; 24import { d as isAiFeatureBlocked, n as useAccountCreditsAndFeatures, r as TierRestrictionOutOfUsageDialog, t as require_faImage } from "./faImage.B8oHjXUm.js"; 25import { a as useNumericFeatureRestriction, c as useAccountFeatureFullData, i as useCreditsCostForFeature, t as require_faFilm } from "./faFilm.Dzt69dT8.js"; 26import { A as AiCreditsFeatureConfigurations, D as AiCreditsLabel, O as AiCreditsLabelDisplayMode, j as getCurrentBalance, k as useAiCreditsEmail } from "./DataLibraryUtils.Bu8dkwMa.js"; 27import { t as TruffleCircularProgress } from "./TruffleCircularProgress.C8BTwqVq.js"; 28import { o as openArticleInHelpCenter, t as InAppHelpCenterTrackingSource } from "./helpCenter.B-FM_f9-.js"; 29import { t as require_faCoins } from "./faCoins.BkMSaDpc.js"; 30import { t as useToggle } from "./useToggle.VWzJCIzv.js"; 31import { t as getUserInitials } from "./usersUtils.Dy0drKvc.js"; 32//#region node_modules/@microsoft/fetch-event-source/lib/esm/parse.js 33async function getBytes(stream, onChunk) { 34 const reader = stream.getReader(); 35 let result; 36 while (!(result = await reader.read()).done) onChunk(result.value); 37} 38function getLines(onLine) { 39 let buffer; 40 let position; 41 let fieldLength; 42 let discardTrailingNewline = false;
43 return function onChunk(arr) { 44 if (buffer === void 0) { 45 buffer = arr; 46 position = 0; 47 fieldLength = -1; 48 } else buffer = concat(buffer, arr); 49 const bufLength = buffer.length; 50 let lineStart = 0; 51 while (position < bufLength) { 52 if (discardTrailingNewline) { 53 if (buffer[position] === 10) lineStart = ++position; 54 discardTrailingNewline = false; 55 } 56 let lineEnd = -1; 57 for (; position < bufLength && lineEnd === -1; ++position) switch (buffer[position]) { 58 case 58: 59 if (fieldLength === -1) fieldLength = position - lineStart; 60 break; 61 case 13: discardTrailingNewline = true; 62 case 10: 63 lineEnd = position; 64 break; 65 } 66 if (lineEnd === -1) break; 67 onLine(buffer.subarray(lineStart, lineEnd), fieldLength); 68 lineStart = position; 69 fieldLength = -1; 70 } 71 if (lineStart === bufLength) buffer = void 0; 72 else if (lineStart !== 0) { 73 buffer = buffer.subarray(lineStart); 74 position -= lineStart; 75 } 76 }; 77} 78function getMessages(onId, onRetry, onMessage) { 79 let message = newMessage(); 80 const decoder = new TextDecoder(); 81 return function onLine(line, fieldLength) { 82 if (line.length === 0) { 83 onMessage === null || onMessage === void 0 || onMessage(message); 84 message = newMessage(); 85 } else if (fieldLength > 0) { 86 const field = decoder.decode(line.subarray(0, fieldLength)); 87 const valueOffset = fieldLength + (line[fieldLength + 1] === 32 ? 2 : 1); 88 const value = decoder.decode(line.subarray(valueOffset)); 89 switch (field) { 90 case "data": 91 message.data = message.data ? message.data + "\n" + value : value; 92 break; 93 case "event": 94 message.event = value; 95 break; 96 case "id": 97 onId(message.id = value); 98 break; 99 case "retry": 100 const retry = parseInt(value, 10); 101 if (!isNaN(retry)) onRetry(message.retry = retry); 102 break; 103 } 104 } 105 }; 106} 107function concat(a, b) { 108 const res = new Uint8Array(a.length + b.length); 109 res.set(a); 110 res.set(b, a.length); 111 return res; 112} 113function newMessage() { 114 return { 115 data: "", 116 event: "", 117 id: "", 118 retry: void 0 119 }; 120} 121var init_parse = __esmMin((() => {})); 122//#endregion 123//#region node_modules/@microsoft/fetch-event-source/lib/esm/fetch.js 124function fetchEventSource(input, _a) { 125 var { signal: inputSignal, headers: inputHeaders, onopen: inputOnOpen, onmessage, onclose, onerror, openWhenHidden, fetch: inputFetch } = _a, rest = __rest(_a, [ 126 "signal", 127 "headers", 128 "onopen", 129 "onmessage", 130 "onclose", 131 "onerror", 132 "openWhenHidden", 133 "fetch" 134 ]); 135 return new Promise((resolve, reject) => { 136 const headers = Object.assign({}, inputHeaders); 137 if (!headers.accept) headers.accept = EventStreamContentType; 138 let curRequestController; 139 function onVisibilityChange() { 140 curRequestController.abort(); 141 if (!document.hidden) create(); 142 } 143 if (!openWhenHidden) document.addEventListener("visibilitychange", onVisibilityChange); 144 let retryInterval = DefaultRetryInterval; 145 let retryTimer = 0; 146 function dispose() { 147 document.removeEventListener("visibilitychange", onVisibilityChange); 148 window.clearTimeout(retryTimer); 149 curRequestController.abort(); 150 } 151 inputSignal === null || inputSignal === void 0 || inputSignal.addEventListener("abort", () => { 152 dispose(); 153 resolve(); 154 }); 155 const fetch = inputFetch !== null && inputFetch !== void 0 ? inputFetch : window.fetch; 156 const onopen = inputOnOpen !== null && inputOnOpen !== void 0 ? inputOnOpen : defaultOnOpen; 157 async function create() { 158 var _a; 159 curRequestController = new AbortController(); 160 try { 161 const response = await fetch(input, Object.assign(Object.assign({}, rest), { 162 headers, 163 signal: curRequestController.signal 164 })); 165 await onopen(response); 166 await getBytes(response.body, getLines(getMessages((id) => { 167 if (id) headers[LastEventId] = id; 168 else delete headers[LastEventId]; 169 }, (retry) => { 170 retryInterval = retry; 171 }, onmessage))); 172 onclose === null || onclose === void 0 || onclose(); 173 dispose(); 174 resolve(); 175 } catch (err) { 176 if (!curRequestController.signal.aborted) try { 177 const interval = (_a = onerror === null || onerror === void 0 ? void 0 : onerror(err)) !== null && _a !== void 0 ? _a : retryInterval;
178 window.clearTimeout(retryTimer); 179 retryTimer = window.setTimeout(create, interval); 180 } catch (innerErr) { 181 dispose(); 182 reject(innerErr); 183 } 184 } 185 } 186 create(); 187 }); 188} 189function defaultOnOpen(response) { 190 const contentType = response.headers.get("content-type"); 191 if (!(contentType === null || contentType === void 0 ? void 0 : contentType.startsWith("text/event-stream"))) throw new Error(`Expected content-type to be ${EventStreamContentType}, Actual: ${contentType}`); 192} 193var __rest, EventStreamContentType, DefaultRetryInterval, LastEventId; 194var init_fetch = __esmMin((() => { 195 init_parse(); 196 __rest = function(s, e) { 197 var t = {}; 198 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; 199 if (s != null && typeof Object.getOwnPropertySymbols === "function") { 200 for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; 201 } 202 return t; 203 }; 204 EventStreamContentType = "text/event-stream"; 205 DefaultRetryInterval = 1e3; 206 LastEventId = "last-event-id"; 207})); 208//#endregion 209//#region node_modules/@microsoft/fetch-event-source/lib/esm/index.js 210var esm_exports = /* @__PURE__ */ __exportAll({ 211 EventStreamContentType: () => EventStreamContentType, 212 fetchEventSource: () => fetchEventSource 213}); 214var init_esm = __esmMin((() => { 215 init_fetch(); 216})); 217//#endregion 218//#region node_modules/@sundaysky/chatbot-client/dist/chatbotClient.js 219var require_chatbotClient = /* @__PURE__ */ __commonJSMin(((exports) => { 220 var __awaiter = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) { 221 function adopt(value) { 222 return value instanceof P ? value : new P(function(resolve) { 223 resolve(value); 224 }); 225 } 226 return new (P || (P = Promise))(function(resolve, reject) { 227 function fulfilled(value) { 228 try { 229 step(generator.next(value)); 230 } catch (e) { 231 reject(e); 232 } 233 } 234 function rejected(value) { 235 try { 236 step(generator["throw"](value)); 237 } catch (e) { 238 reject(e); 239 } 240 } 241 function step(result) { 242 result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); 243 } 244 step((generator = generator.apply(thisArg, _arguments || [])).next()); 245 }); 246 }; 247 var __classPrivateFieldSet = exports && exports.__classPrivateFieldSet || function(receiver, state, value, kind, f) { 248 if (kind === "m") throw new TypeError("Private method is not writable"); 249 if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); 250 if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); 251 return kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value), value; 252 }; 253 var __classPrivateFieldGet = exports && exports.__classPrivateFieldGet || function(receiver, state, kind, f) { 254 if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); 255 if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); 256 return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); 257 }; 258 var _ChatbotClient_endpoint; 259 var _ChatbotClient_eventHandler; 260 Object.defineProperty(exports, "__esModule", { value: true }); 261 exports.ChatbotClient = void 0; 262 var fetch_event_source_1 = (init_esm(), __toCommonJS(esm_exports)); 263 var ChatbotClient = class { 264 constructor({ endpoint, eventHandler }) { 265 _ChatbotClient_endpoint.set(this, void 0); 266 _ChatbotClient_eventHandler.set(this, void 0); 267 __classPrivateFieldSet(this, _ChatbotClient_endpoint, endpoint, "f"); 268 __classPrivateFieldSet(this, _ChatbotClient_eventHandler, eventHandler, "f"); 269 } 270 prompt(promptToVideoInput, headers = {}) { 271 return __awaiter(this, void 0, void 0, function* () { 272 return (0, fetch_event_source_1.fetchEventSource)(__classPrivateFieldGet(this, _ChatbotClient_endpoint, "f"), { 273 method: "POST", 274 body: JSON.stringify(promptToVideoInput), 275 headers: Object.assign(Object.assign({}, headers), { 276 "Content-Type": "application/json", 277 "Accept": "text/event-stream" 278 }), 279 openWhenHidden: true, 280 onopen: (res) => __awaiter(this, void 0, void 0, function* () { 281 if (res.ok && res.status === 200) {} else if (res.status >= 400 && res.status < 500 && res.status !== 429) {} 282 }), 283 onmessage: (event) => { 284 const parsedData = JSON.parse(event.data); 285 __classPrivateFieldGet(this, _ChatbotClient_eventHandler, "f").call(this, parsedData); 286 }, 287 onclose() {},
288 onerror(err) {} 289 }); 290 }); 291 } 292 }; 293 exports.ChatbotClient = ChatbotClient; 294 _ChatbotClient_endpoint = /* @__PURE__ */ new WeakMap(), _ChatbotClient_eventHandler = /* @__PURE__ */ new WeakMap(); 295})); 296//#endregion 297//#region node_modules/@sundaysky/chatbot-client/dist/types.js 298var require_types = /* @__PURE__ */ __commonJSMin(((exports) => { 299 Object.defineProperty(exports, "__esModule", { value: true }); 300})); 301//#endregion 302//#region node_modules/@sundaysky/chatbot-client/dist/index.js 303var require_dist$1 = /* @__PURE__ */ __commonJSMin(((exports) => { 304 var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) { 305 if (k2 === void 0) k2 = k; 306 var desc = Object.getOwnPropertyDescriptor(m, k); 307 if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) desc = { 308 enumerable: true, 309 get: function() { 310 return m[k]; 311 } 312 }; 313 Object.defineProperty(o, k2, desc); 314 }) : (function(o, m, k, k2) { 315 if (k2 === void 0) k2 = k; 316 o[k2] = m[k]; 317 })); 318 var __exportStar = exports && exports.__exportStar || function(m, exports$2) { 319 for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports$2, p)) __createBinding(exports$2, m, p); 320 }; 321 Object.defineProperty(exports, "__esModule", { value: true }); 322 __exportStar(require_chatbotClient(), exports); 323 __exportStar(require_types(), exports); 324})); 325//#endregion 326//#region client/logic/common/aiImageGenPromptChatService.ts 327var import_react = /* @__PURE__ */ __toESM(require_react()); 328var import_jsx_runtime = require_jsx_runtime(); 329var import_material = require_material(); 330var import_dist$1 = require_dist$2(); 331var import_dist$2 = require_dist$1(); 332var AIImageGenPromptChatService = class { 333 constructor(authService) { 334 this.authService = authService; 335 } 336 async sendMessage(input, eventHandler) { 337 const accountId = activeAccountIdVar(); 338 const headers = addTokenHeadersAndFullStory({}, await this.authService.getUserAccessToken()); 339 await new import_dist$2.ChatbotClient({ 340 endpoint: `/rest/${accountId}/aiImageGenPromptChat`, 341 eventHandler 342 }).prompt(input, headers); 343 } 344}; 345var aiImageGenPromptChatServiceInstance; 346function initAIImageGenPromptChatService(authService) { 347 aiImageGenPromptChatServiceInstance = new AIImageGenPromptChatService(authService); 348} 349function getAIImageGenPromptChatService() { 350 return aiImageGenPromptChatServiceInstance; 351} 352//#endregion 353//#region client/components/newNav/accessControls/videoAccessUtils.ts 354/** The video/template noun used across the dialog's copy. */ 355var assetNoun = (isTemplate) => isTemplate ? "template" : "video"; 356/** Role label for an explicit grant. Requests (`requested_*`) belong to the requests queue, not the grant list. */ 357var grantAccessLevelLabel = { 358 [GqlClientProgramAccessLevel.EDITOR]: "Can edit", 359 [GqlClientProgramAccessLevel.VIEWER]: "Can view", 360 [GqlClientProgramAccessLevel.REQUESTED_EDITING]: null, 361 [GqlClientProgramAccessLevel.REQUESTED_VIEWING]: null 362}; 363/** Role label for the "all other users in the account" default. */ 364var defaultAccessLabel = { 365 [GqlClientProgramDefaultAccessLevel.EDITOR]: "Can edit", 366 [GqlClientProgramDefaultAccessLevel.VIEWER]: "Can view", 367 [GqlClientProgramDefaultAccessLevel.NO_ACCESS]: "No access" 368}; 369/** An entry is a real grant (shown in the list) only when it is not a pending request. */ 370var isGrant = (entry) => entry.accessLevel === GqlClientProgramAccessLevel.EDITOR || entry.accessLevel === GqlClientProgramAccessLevel.VIEWER; 371var getInitials = (name) => { 372 const words = name.trim().split(/\s+/); 373 return words.length >= 2 ? (words[0][0] + words[1][0]).toUpperCase() : name[0]?.toUpperCase() ?? "?"; 374}; 375/** "First Last", falling back to the email. Accepts the GraphQL nullable name shape. When `currentUserId` 376* is passed and matches the user, a " (You)" suffix is appended â omit it for the raw name (e.g. initials). */ 377var displayUserName = (user, currentUserId) => { 378 const name = `${user.firstName ?? ""} ${user.lastName ?? ""}`.trim() || user.email; 379 return currentUserId !== void 0 && user.id === currentUserId ? `${name} (You)` : name; 380}; 381var ACCESS_RANK = { 382 none: 0, 383 viewer: 1, 384 editor: 2, 385 owner: 3 386}; 387var GRANT_TO_ACCESS = { 388 [GqlClientProgramAccessLevel.EDITOR]: "editor", 389 [GqlClientProgramAccessLevel.VIEWER]: "viewer", 390 [GqlClientProgramAccessLevel.REQUESTED_EDITING]: "none", 391 [GqlClientProgramAccessLevel.REQUESTED_VIEWING]: "none" 392}; 393var DEFAULT_TO_ACCESS = { 394 [GqlClientProgramDefaultAccessLevel.EDITOR]: "editor", 395 [GqlClientProgramDefaultAccessLevel.VIEWER]: "viewer", 396 [GqlClientProgramDefaultAccessLevel.NO_ACCESS]: "none" 397}; 398/** 399* The caller's effective access to a program (D-08/D-09/D-26/D-43). A wrong answer is silent â a wrongly 400* visible program is a privacy leak and nothing fails loudly â so the order matters: 401* 1. the display owner (D-43) and any Account Owner manage everything â `owner`; 402* 2. internal SundaySky users get automatic access, but only in external accounts (D-26), capped by their 403* role â `editor` with an editor role, else `viewer`; never `owner` (ownership/management stay with real 404* owners, N-05); 405* 3. otherwise the account default is the floor and grants only raise access above it â the result is the
406* highest of the default and any grant reaching the caller (individually or through a group; no precedence 407* between them), then capped by the caller's role ceiling (without an editor role you cannot exceed 408* `viewer`). 409* `"none"` means the program is hidden from the caller. 410*/ 411var effectiveUserProgramAccess = ({ program, caller, displayOwner, callerGroupIds, accountType }) => { 412 if (caller && (displayOwner?.id === caller.id || caller.isAccountOwner)) return "owner"; 413 if (caller?.isInternal && accountType !== "Internal") return caller.isEditor ? "editor" : "viewer"; 414 const ceiling = caller?.isEditor ? "editor" : "viewer"; 415 const floor = DEFAULT_TO_ACCESS[program.defaultAccess]; 416 if (ACCESS_RANK[floor] >= ACCESS_RANK[ceiling]) return ceiling; 417 let bestGrant = "none"; 418 for (const entry of program.accessList) { 419 if (bestGrant === "editor") break; 420 const reachesCaller = caller !== void 0 && entry.user?.user.id === caller.id || !!entry.group && callerGroupIds.has(entry.group.id); 421 if (isGrant(entry) && reachesCaller) { 422 const level = GRANT_TO_ACCESS[entry.accessLevel]; 423 if (ACCESS_RANK[level] > ACCESS_RANK[bestGrant]) bestGrant = level; 424 } 425 } 426 const rawAccess = ACCESS_RANK[bestGrant] > ACCESS_RANK[floor] ? bestGrant : floor; 427 return ACCESS_RANK[rawAccess] <= ACCESS_RANK[ceiling] ? rawAccess : ceiling; 428}; 429/** 430* The owner to DISPLAY for a program (D-43 / Q-14). The stored owner stands only while they still hold an 431* Editor role in the account; a null owner, a deleted owner, or one demoted out of an editor role all fall 432* back to the Account Owner. That fallback is the same for every program in the account, so it is resolved 433* once per pass and passed in here rather than re-derived per program. 434*/ 435var getDisplayOwner = (ownerUserId, usersById, accountOwnerFallback) => { 436 if (ownerUserId) { 437 const owner = usersById.get(ownerUserId); 438 if (owner && owner.isEditor) return owner; 439 } 440 return accountOwnerFallback; 441}; 442var normalizeUser = (accountUser) => ({ 443 id: accountUser.user.id, 444 firstName: accountUser.user.firstName, 445 lastName: accountUser.user.lastName, 446 email: accountUser.user.email, 447 isEditor: accountUser.roles.includes(GqlClientUserAccountRole.PLATFORMEDITOR), 448 isAccountOwner: accountUser.roles.includes(GqlClientUserAccountRole.ACCOUNTOWNER), 449 isInternal: (accountUser.user.roles ?? []).includes(GqlClientUserRole.INTERNAL) 450}); 451/** 452* Resolve one loader's programs into `programAccessVar` records and upsert them, returning the records so the 453* caller can filter its own list by `record.visible`. Everything is computed here, once, from a single query 454* that carries the programs, the account roster and the groups together: the caller's group memberships (the 455* group half of visibility â filtering on individual grants alone hides every group-only program, silently), 456* each grant's principal joined to a person or named group, and the D-43 display owner. Unresolvable 457* principals (deleted user, unseen group) drop from the row rather than render nameless. 458* 459* The map is upserted (copy, replace, write a new reference) because the video and template loaders share it; 460* building a fresh map would wipe the other half, and a reactive var only notifies on a new reference. 461* Programs are stored UNFILTERED â the dialog must still resolve a program the owner can manage even when it 462* is hidden from a viewer; `visible` on each record is the filter the lists apply. 463*/ 464var processAccessPrograms = (programs, accountUsers, groups, accountType, loadingFlag) => { 465 const currentUserId = getUserData()?.userName ?? ""; 466 const users = accountUsers.map(normalizeUser); 467 const usersById = new Map(users.map((user) => [user.id, user])); 468 const caller = usersById.get(currentUserId); 469 const groupsById = new Map(groups.map((group) => [group.id, group])); 470 const callerGroupIds = new Set(groups.filter((group) => group.members.some((member) => member.userId === currentUserId)).map((group) => group.id)); 471 const accountOwners = users.filter((user) => user.isAccountOwner); 472 const accountOwnerFallback = accountOwners.find((user) => !user.isInternal) ?? accountOwners[0] ?? null; 473 const resolveEntry = (entry) => { 474 if (entry.group) { 475 const group = groupsById.get(entry.group.id); 476 if (group === void 0) return null; 477 const members = group.members.map((member) =>
477 usersById.get(member.userId)).filter((user) => user !== void 0); 478 return { 479 id: entry.id, 480 accessLevel: entry.accessLevel, 481 comment: entry.comment, 482 user: null, 483 group: { 484 id: group.id, 485 name: group.name, 486 members 487 } 488 }; 489 } 490 if (entry.user) { 491 const managed = usersById.get(entry.user.user.id); 492 return managed === void 0 ? null : { 493 id: entry.id, 494 accessLevel: entry.accessLevel, 495 comment: entry.comment, 496 user: managed, 497 group: null 498 }; 499 } 500 return null; 501 }; 502 const records = /* @__PURE__ */ new Map(); 503 for (const program of programs) { 504 const displayOwner = getDisplayOwner(program.owner?.user.id ?? null, usersById, accountOwnerFallback); 505 const grants = program.programAccessList.filter(isGrant); 506 const requests = program.programAccessList.filter((entry) => !isGrant(entry)); 507 const effectiveAccess = effectiveUserProgramAccess({ 508 program: { 509 defaultAccess: program.defaultAccess, 510 accessList: program.programAccessList 511 }, 512 caller, 513 displayOwner, 514 callerGroupIds, 515 accountType 516 }); 517 records.set(program.id, { 518 programId: program.id, 519 name: program.name, 520 defaultAccess: program.defaultAccess, 521 owner: displayOwner, 522 accessList: grants.map(resolveEntry).filter((entry) => entry !== null), 523 accessRequests: requests.map(resolveEntry).filter((entry) => entry !== null), 524 effectiveAccess, 525 visible: effectiveAccess !== "none" 526 }); 527 } 528 const current = programAccessVar(); 529 const accessByProgramId = new Map(current.accessByProgramId); 530 for (const [programId, record] of records) accessByProgramId.set(programId, record); 531 programAccessVar({ 532 ...current, 533 accessByProgramId, 534 [loadingFlag]: false 535 }); 536 return records; 537}; 538//#endregion 539//#region client/components/newNav/nooks/videosAndFolders.ts 540var addPathFromRootToFolderItem = (initialFolder, foldersById) => { 541 let folder = initialFolder; 542 while (folder) if (folder.pathFromRoot.length) { 543 initialFolder.pathFromRoot = [...folder.pathFromRoot, ...initialFolder.pathFromRoot]; 544 folder = null; 545 } else { 546 initialFolder.pathFromRoot = [{ 547 id: folder.id, 548 name: folder.name 549 }, ...initialFolder.pathFromRoot]; 550 folder = folder.parentFolder ? foldersById.get(folder.parentFolder.id) : null; 551 } 552}; 553var isAiVideoDraftVideo = (video) => { 554 return "lifecycleStage" in video && video.lifecycleStage === GqlClientAssetLifecycleStage.PREVIEW; 555}; 556var getVideosByParentFolderId = (map, videoItem) => { 557 if (videoItem.isArchive) map.set(ARCHIVE_FOLDER_NAME, [...map.get("Archive") || [], videoItem]); 558 else if (isAiVideoDraftVideo(videoItem.video)) map.set(AI_VIDEO_DRAFTS_FOLDER_NAME, [...map.get("AI Video Drafts") || [], videoItem]); 559 else if (videoItem.video.folder) map.set(videoItem.video.folder.id, [...map.get(videoItem.video.folder.id) || [], videoItem]); 560 return map; 561}; 562var writeVideosAndFolders = (editorProgramsData, builderProgramsData, foldersData) => { 563 const editorPrograms = editorProgramsData.map(gqlEditorProgramToEditorVideoItem).sort((a, b) => new Date(b.lastEdited).getTime() - new Date(a.lastEdited).getTime()); 564 const builderPrograms = builderProgramsData.map(gqlBuilderProgramToBuilderVideoItem).filter((videoItem) => !isEditorAccountLibraryProgram(videoItem.name)).sort((a, b) => new Date(b.lastEdited).getTime() - new Date(a.lastEdited).getTime()); 565 const videoItemsById = new Map([...editorPrograms, ...builderPrograms].map((video) => [video.id, video])); 566 const folders = foldersData.map(gqlAccountProgramFolderToVideoFolderItem); 567 const rootFolder = folders.find((folder) => folder.isRoot); 568 const foldersById = new Map(folders.map((folder) => [folder.id, folder])); 569 let foldersByParentFolderId = /* @__PURE__ */ new Map(); 570 for (const folderItem of folders) { 571 addPathFromRootToFolderItem(folderItem, foldersById); 572 if (!folderItem.isRoot) foldersByParentFolderId.set(folderItem.parentFolder.id, [...foldersByParentFolderId.get(folderItem.parentFolder.id) || [], folderItem]); 573 } 574 const accountHasPreviewLifecycleStageVideos = editorPrograms.some((video) => video.video.lifecycleStage === GqlClientAssetLifecycleStage.PREVIEW); 575 videosAndFoldersVar({ 576 loading: false, 577 videoItemsById, 578 videosByParentFolderId: [...editorPrograms, ...builderPrograms].reduce(getVideosByParentFolderId, /* @__P
578URE__ */ new Map()), 579 rootFolder, 580 foldersById, 581 foldersByParentFolderId, 582 accountHasPreviewLifecycleStageVideos 583 }); 584}; 585var loadVideosAndFolderData = () => { 586 const client = getApolloClient(); 587 if (!isFeatureEnabled(featureFlagConst._EDITOR_ACCESS_CONTROL_R2)) { 588 client.watchQuery({ query: GetVideoListDocument }).subscribe(({ data }) => { 589 writeVideosAndFolders(data?.currentAccount.editorPrograms ?? [], data?.currentAccount.builderPrograms ?? [], data?.currentAccount.folders ?? []); 590 }); 591 return; 592 } 593 client.watchQuery({ query: VideoListWithUserAccessDocument }).subscribe(({ data }) => { 594 const rawEditorPrograms = data?.currentAccount.editorPrograms ?? []; 595 const records = processAccessPrograms(rawEditorPrograms, data?.currentAccount.users ?? [], data?.currentAccount.userGroups ?? [], data?.currentAccount.type, "videosLoading"); 596 writeVideosAndFolders(rawEditorPrograms.filter((program) => records.get(program.id)?.visible), data?.currentAccount.builderPrograms ?? [], data?.currentAccount.folders ?? []); 597 }); 598}; 599var reloadVideosAndFolderData = () => { 600 const { query } = getApolloClient(); 601 if (isFeatureEnabled(featureFlagConst._EDITOR_ACCESS_CONTROL_R2)) return query({ 602 query: VideoListWithUserAccessDocument, 603 fetchPolicy: "network-only" 604 }); 605 return query({ 606 query: GetVideoListDocument, 607 fetchPolicy: "network-only" 608 }); 609}; 610var reloadAccountTemplates = () => { 611 const { query } = getApolloClient(); 612 if (isFeatureEnabled(featureFlagConst._EDITOR_ACCESS_CONTROL_R2)) return query({ 613 query: AccountTemplatesWithUserAccessDocument, 614 fetchPolicy: "network-only" 615 }); 616 return query({ 617 query: AccountTemplatesDocument, 618 fetchPolicy: "network-only" 619 }); 620}; 621//#endregion 622//#region client/components/editor/Hooks/UseGenerativeAIUsageAcceptance/useGenerativeAIUsageAcceptance.ts 623var useGenerativeAIUsageAcceptance = (userName) => { 624 const { loading, data } = useUserSettingsQuery({ variables: { id: userName || localEditorUserNameVar() } }); 625 const hasUserAcceptedTerms = !!data?.userSettings?.acceptedGenerativeAiTerms; 626 const acceptUsage = async () => { 627 setUserSettings({ acceptedGenerativeAiTerms: true }); 628 }; 629 const declineUsage = async () => {}; 630 return { 631 isLoadingUserAcceptedTerms: loading, 632 hasUserAcceptedTerms, 633 acceptUsage, 634 declineUsage 635 }; 636}; 637//#endregion 638//#region client/components/editor/Components/Components/CountdownBadge.tsx 639init_emotion_react_browser_esm(); 640var import_faCoins = require_faCoins(); 641var bounceAnimation = keyframes` 642 0% { transform: scale(1); } 643 40% { transform: scale(1.1); } 644 65% { transform: scale(0.98); } 645 85% { transform: scale(1.04); } 646 100% { transform: scale(1); } 647`; 648var ONE_SECOND = 1e3; 649var CountdownBadge = ({ startValue, stopAt, completeColor = "error" }) => { 650 const [currentValue, setCurrentValue] = (0, import_react.useState)(startValue); 651 const [isComplete, setIsComplete] = (0, import_react.useState)(false); 652 (0, import_react.useEffect)(() => { 653 const steps = startValue - stopAt; 654 if (steps <= 0) { 655 setIsComplete(true); 656 return; 657 } 658 const intervalMs = ONE_SECOND / steps; 659 const interval = setInterval(() => setCurrentValue((prev) => { 660 const next = prev - 1; 661 if (next <= stopAt) { 662 clearInterval(interval); 663 setIsComplete(true); 664 return stopAt; 665 } 666 return next; 667 }), intervalMs); 668 return () => clearInterval(interval); 669 }, []); 670 return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { 671 sx: sxBadge(isComplete, completeColor), 672 children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 673 sx: sxContent, 674 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { 675 sx: sxIconWrapper, 676 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.SvgIcon, { 677 color: isComplete ? completeColor : "gradient", 678 fontSize: "large", 679 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FontAwesomeIcon, { icon: import_faCoins.faCoins }) 680 }) 681 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Typography, { 682 variant: "body1", 683 color: isComplete ? completeColor : "primary", 684 sx: { fontSize: "34px" }, 685 children: currentValue 686 })] 687 }) 688 }); 689}; 690var sxBadge = (isComplete, completeColor) => ({ 691 minWidth: "134px",
692 height: "80px", 693 padding: "0 28px", 694 borderRadius: "16px", 695 display: "inline-flex", 696 alignItems: "center", 697 justifyContent: "center", 698 backgroundColor: ({ palette }) => isComplete ? palette[completeColor].light : palette.primary.light, 699 transition: "background-color 200ms ease-out", 700 ...isComplete && { animation: `${bounceAnimation} 520ms cubic-bezier(.25, 1.2, .4, 1)` } 701}); 702var sxContent = { 703 display: "flex", 704 alignItems: "center", 705 justifyContent: "center", 706 gap: "10px" 707}; 708var sxIconWrapper = { 709 width: "36px", 710 display: "flex", 711 alignItems: "center", 712 justifyContent: "center" 713}; 714//#endregion 715//#region client/components/editor/Components/Components/AiCreditsContactSalesDialog.tsx 716var AiCreditsContactSalesDialogDisplayMode = /* @__PURE__ */ function(AiCreditsContactSalesDialogDisplayMode) { 717 AiCreditsContactSalesDialogDisplayMode["approve"] = "approve"; 718 AiCreditsContactSalesDialogDisplayMode["immediateAction"] = "immediateAction"; 719 return AiCreditsContactSalesDialogDisplayMode; 720}({}); 721var EXTRA_CREDITS_COST = 200; 722var AiCreditsContactSalesDialog = (props) => { 723 const { sendEmail } = useAiCreditsEmail(); 724 const isBalanceMode = props.displayMode === "immediateAction" && props.balanceProps; 725 const isLowBalanceMode = props.displayMode === "immediateAction" && !props.balanceProps && !!props.lowBalanceState; 726 const { accountFeaturesAndPacksData } = useAccountCreditsAndFeatures(); 727 const firstFeatureName = props.displayMode === "approve" ? props.approveFeatures[0] : props.immediateActionFeatures[0]; 728 const balance = getCurrentBalance(accountFeaturesAndPacksData?.find((feature) => feature.featureTypeDefinition === firstFeatureName)); 729 const balanceNumber = balance > 0 ? balance : 0; 730 const isLowBalanceWithCredits = isLowBalanceMode && balanceNumber > 0; 731 const getPrimaryText = () => { 732 if (props.displayMode === "approve") return `${`~${props.cost} `} AI credits needed to ${props.action}`; 733 if (isBalanceMode && props.balanceProps.balance > 0) return `${props.balanceProps.cost} AI credits needed to ${props.balanceProps.action}`; 734 if (isLowBalanceWithCredits) return props.lowBalanceState === "nearly_depleted" ? "Your AI credits are nearly depleted." : "Your AI credits are running low."; 735 return "You've run out of AI credits."; 736 }; 737 const getSecondaryText = () => { 738 const featureNames = (props.displayMode === "approve" ? props.approveFeatures : props.immediateActionFeatures).map((f) => AiCreditsFeatureConfigurations[f].feature).join(", "); 739 if (props.displayMode === "approve") return `You don't have enough AI credits to complete this action. 740Contact sales for more credits, or remove ${featureNames} from this video to continue.`; 741 if (isBalanceMode && props.balanceProps.balance > 0) return "You don't have enough AI credits to complete this action. Contact sales for more credits."; 742 if (isLowBalanceWithCredits) return "Contact sales for more credits to keep using SundaySky AI capabilities without interruption."; 743 return `To continue using ${featureNames} and other SundaySky AI capabilities, contact our sales team.`; 744 }; 745 const isLoading = props.displayMode === "approve" && !props.cost; 746 const getStartValue = () => { 747 if (props.displayMode === "approve") return props.cost + EXTRA_CREDITS_COST; 748 if (isBalanceMode) return props.balanceProps.cost + EXTRA_CREDITS_COST; 749 if (isLowBalanceWithCredits) return balanceNumber + EXTRA_CREDITS_COST; 750 return balanceNumber; 751 }; 752 return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TierRestrictionOutOfUsageDialog, { 753 icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CountdownBadge, { 754 stopAt: balanceNumber, 755 startValue: getStartValue(), 756 completeColor: isLowBalanceWithCredits ? "warning" : "error" 757 }), 758 open: props.open, 759 onClose: props.onClose, 760 primaryText: getPrimaryText(), 761 secondaryText: getSecondaryText(), 762 helpCenterArticleButtonId: "160c93ec-4d7e-4c0c-8f0d-9ce31913f5b0", 763 onContactSalesButtonClick: sendEmail, 764 contactSalesButtonText: "Contact sales for more credits", 765 dataTrackingId: props.dataTrackingId, 766 loading: isLoading 767 }); 768}; 769//#endregion 770//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/Dialogs/AiGeneratorTermsDialog.tsx 771var AiGeneratorTermsDialog = ({ open, onClose, onAcceptTerms, onCancel }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dist$1.ConfirmationDialog, { 772 maxWidth: "sm", 773 open, 774 primaryActionButtonText: "Accept", 775 secondaryActionButtonText: "Cancel", 776 CloseIconButtonProps: { onClick: onCancel }, 777 onClose, 778 SecondaryActionButtonProps: { onClick: onCancel }, 779 PrimaryActionButtonProps: { onClick: onAcceptTerms }, 780 dialogTitle: "Google AI Services terms and conditions", 781 DialogContentProps: { sx: { 782 maxHeight: "428px", 783 ...import_dist$1.scrollOnHoverSxProps, 784 paddingRight: "20px" 785 } }, 786 children: [
787 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Typography, { 788 variant: "body1", 789 children: "As a user of the SundaySky Platform, Customer and its Users (\"you\") may elect to use Google's generative AI service, Imagen and potentially other Google AI services (together, the \"Google AI Services\") to generate images from text prompts provided by you as part of use of the SundaySky Platform for inclusion in your Videos." 790 }), 791 /* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {}), 792 /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Typography, { 793 variant: "body1", 794 children: [ 795 "SundaySky makes the Google AI Services available to you on the same terms as you would receive if you contracted directly with Google. By using the Google AI Services you agree to comply with the following Google terms: Google Cloud Platform Terms currently located at", 796 " ", 797 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Link, { 798 target: "_blank", 799 href: "https://cloud.google.com/terms/services", 800 children: "https://cloud.google.com/terms/services" 801 }), 802 "; Google Service Specific Terms for AI Services currently located at", 803 " ",
804 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Link, { 805 target: "_blank", 806 href: "https://cloud.google.com/terms/service-terms", 807 children: "https://cloud.google.com/terms/service-terms" 808 }), 809 "; Google Generative AI Use Policy currently located at", 810 " ", 811 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Link, { 812 target: "_blank", 813 href: "https://policies.google.com/terms/generative-ai/use-policy", 814 children: "https://policies.google.com/terms/generative-ai/use-policy" 815 }), 816 "; and each of the other policies and terms referenced in those terms, as they may be in effect from time to time (together, the \"Google Terms\")" 817 ] 818 }), 819 /* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {}), 820 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Typography, { 821 variant: "body1", 822 children: "If you believe you have a claim under the Google Terms arising from your permitted use of the Google AI Services with the SundaySky Platform, you must give SundaySky prompt written notice of that claim. SundaySky will use reasonable efforts to seek indemnification from Google on your behalf and will pass through to you the indemnification (if any) SundaySky receives from Google in respect of such claim. The foregoing is SundaySky's sole obligation and liability to you in connection with the Google AI Services. SundaySky makes no representations or warranties regarding the Google AI Services or your use of the Google AI Services in connection with the SundaySky Platform, and SundaySky reserves the right to discontinue making the Google AI Services available to you as part of the SundaySky Platform at any time." 823 }) 824 ] 825}); 826//#endregion 827//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/Dialogs/WarningConfirmationDialog.tsx 828var WarningConfirmationDialog = ({ open, title, description, primaryButtonProps, secondaryButtonProps, onClose, onConfirm }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Dialog, { 829 open, 830 onClose, 831 maxWidth: "sm", 832 children: [ 833 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dist$1.TruffleDialogTitle, { 834 CloseIconButtonProps: { onClick: onClose }, 835 multiline: true, 836 children: title 837 }),
838 description && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.DialogContent, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Typography, { 839 variant: "body1", 840 children: description 841 }) }), 842 /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dist$1.TruffleDialogActions, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Button, { 843 variant: "text", 844 size: "large", 845 color: "primary", 846 onClick: onClose, 847 "data-tracking-id": secondaryButtonProps.trackingId, 848 children: secondaryButtonProps.text 849 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Button, { 850 variant: "contained", 851 size: "large", 852 color: "primary", 853 onClick: onConfirm, 854 "data-tracking-id": primaryButtonProps.trackingId, 855 children: primaryButtonProps.text 856 })] }) 857 ] 858}); 859//#endregion 860//#region client/components/editor/Nooks/GenerateAiImages/generateAiImages.ts 861var generateAiImagesLegacy = async (service, numberOfImages, prompt, style, aspectRatio) => { 862 return generateAiTextToImageWithQuery({ 863 service, 864 numberOfImages, 865 prompt, 866 style, 867 aspectRatio 868 }); 869}; 870var generateAiImages = async (service, numberOfImages, prompt, style, aspectRatio, cameraAngle) => { 871 return generateAiTextToImageWithMutation({ 872 service, 873 numberOfImages, 874 prompt, 875 style, 876 aspectRatio, 877 cameraAngle 878 }); 879}; 880var generateAiVideoFirstFrame = async (service, numberOfImages, prompt, style, aspectRatio, cameraAngle) => { 881 const input = { 882 service, 883 numberOfImages, 884 prompt, 885 style, 886 aspectRatio, 887 cameraAngle 888 }; 889 const { data } = await getApolloClient().mutate({ 890 mutation: GenerateAiVideoFirstFrameDocument, 891 variables: { input }, 892 fetchPolicy: "no-cache" 893 }); 894 return data.generateAiVideoFirstFrameFromText; 895}; 896var editAiImage = async (imageUrl, prompt) => { 897 const input = { 898 imageUrl, 899 prompt 900 }; 901 const { data } = await getApolloClient().mutate({ 902 mutation: EditAiImageDocument, 903 variables: { input }, 904 fetchPolicy: "no-cache" 905 }); 906 return data.editAiImage; 907}; 908var editAiVideoFirstFrame = async (imageUrl, prompt) => { 909 const input = { 910 imageUrl, 911 prompt 912 }; 913 const { data } = await getApolloClient().mutate({ 914 mutation: EditAiVideoFirstFrameDocument, 915 variables: { input }, 916 fetchPolicy: "no-cache" 917 }); 918 return data.editAiVideoFirstFrame; 919}; 920var generateAiTextToImageWithQuery = async ({ service, numberOfImages, prompt, style, aspectRatio }) => { 921 const input = { 922 service, 923 numberOfImages, 924 prompt, 925 style, 926 aspectRatio 927 }; 928 const { data } = await getApolloClient().query({ 929 query: GenerateAiImageDocument, 930 variables: { input }, 931 fetchPolicy: "no-cache" 932 }); 933 return data.generateAiImageFromText; 934}; 935var generateAiTextToImageWithMutation = async ({ service, numberOfImages, prompt, style, aspectRatio, cameraAngle }) => { 936 const input = { 937 service, 938 numberOfImages, 939 prompt, 940 style, 941 aspectRatio, 942 cameraAngle 943 }; 944 const { data } = await getApolloClient().mutate({ 945 mutation: GenerateAiImageFromTextDocument, 946 variables: { input }, 947 fetchPolicy: "no-cache" 948 }); 949 return data.generateAiImageFromText; 950}; 951var downloadGeneratedAssetAndAppendToPlaceholder = async (asset, placeholder, byAudienceCaseIndex, onError, applyMedia) => { 952 upsertEditorUploadedGettyUrl({ 953 target: UploadedGettyUrlTarget.PLACEHOLDER, 954 placeholderId: placeholder.id, 955 byAudienceCaseIndex, 956 assetId: asset?.id, 957 mediaUrl: asset?.mediaUrl, 958 thumbnailUrl: asset?.thumbnailUrl 959 }); 960 const mediaInfo = { 961 url: asset?.mediaUrl, 962 filenameWithoutExtension: asset?.name, 963 mediaSource: GqlClientUploadEditorAssetFromUrlMediaSource.AI_GENERATED, 964 aiGeneratedMediaDetails: { 965 prompt: asset?.prompt, 966 system: asset?.service 967 } 968 }; 969 const onUploadError = (error) => { 970 onError(error); 971 removeEditorUploadedGettyUrl({ 972 target: UploadedGettyUrlTarget.PLACEHOLDER, 973 placeholderId: placeholder.id, 974 byAudienceCaseIndex 975 }); 976 }; 977 const onUploadSuccess = (uploadedAsset) => { 978 applyMedia(uploadedAsset.id); 979 PendoService.getInstance().trackEvent("Media lib add asset", { 980 mediaType: uploadedAsset.mediaMetadata.mediaType, 981 mediaSize: Math.round(uploadedAsset.mediaMetadata.size / 1024).toString(), 982 mediaAddOrigin: UploadOrigin.AI_IMAGE_THROUGH_USAGE, 983 mediaAddTarget: "lib root" 984 }); 985 removeEditorUploadedGettyUrl({ 986 target: UploadedGettyUrlTarget.PLACEHOLDER, 987 placeholderId: placeholder.id, 988 byAudienceCaseIndex 989 }); 990 }; 991 await uploadEditorAssetMediaFromUrl(mediaInfo, onUploadSuccess, onUploadError); 992}; 993//#endregion 994//#region client/components/editor/Nooks/GenerateAiVideo/generateAiVideoAsset.ts 995var generateAiVideoAsset = async (firstFrameImageUrl, durationSeconds, firstFramePrompt, motionDescription, aspectRatio, style, cameraMotion, cameraAngle, onProgress, onFailure, onSuccess, requestId, sourceAssetName, sourceAssetDescription, targetFolderId, sourceAssetContributions) => { 996 try { 997 const mutationId = requestId ?? v4();
998 return executeBackgroundMutation({ 999 mutation: GenerateAiVideoAssetDocument, 1000 variables: { 1001 input: { 1002 firstFrameImageUrl, 1003 durationSeconds, 1004 firstFramePrompt, 1005 motionDescription, 1006 aspectRatio, 1007 style, 1008 cameraMotion, 1009 cameraAngle, 1010 sourceAssetName, 1011 sourceAssetDescription, 1012 targetFolderId, 1013 sourceMediaContributions: sourceAssetContributions 1014 }, 1015 mutationId 1016 } 1017 }, { 1018 query: AiVideoAssetGeneratedDocument, 1019 variables: { mutationId } 1020 }, { 1021 onProgress, 1022 onFailure, 1023 onSuccess 1024 }, mutationId); 1025 } catch (err) {} 1026}; 1027//#endregion 1028//#region client/components/editor/Hooks/UseAiVideoNotification/useAiVideoNotification.ts 1029var useAiVideoNotification = () => { 1030 const notificationState = useReactiveVar(aiVideoGeneratedSnackbarVar); 1031 const hideNotification = () => aiVideoGeneratedSnackbarVar({ 1032 ...notificationState, 1033 show: false 1034 }); 1035 const updateNotificationState = (newState) => aiVideoGeneratedSnackbarVar(newState); 1036 return { 1037 notificationState, 1038 updateNotificationState, 1039 hideNotification 1040 }; 1041}; 1042//#endregion 1043//#region node_modules/@sundaysky/ai-common-types/dist/aiClientTypes.js 1044var require_aiClientTypes = /* @__PURE__ */ __commonJSMin(((exports) => { 1045 Object.defineProperty(exports, "__esModule", { value: true }); 1046})); 1047//#endregion 1048//#region node_modules/@sundaysky/ai-common-types/dist/aiTextClientTypes.js 1049var require_aiTextClientTypes = /* @__PURE__ */ __commonJSMin(((exports) => { 1050 Object.defineProperty(exports, "__esModule", { value: true }); 1051})); 1052//#endregion 1053//#region node_modules/@sundaysky/ai-common-types/dist/ccDataTypes.js 1054var require_ccDataTypes = /* @__PURE__ */ __commonJSMin(((exports) => { 1055 Object.defineProperty(exports, "__esModule", { value: true }); 1056})); 1057//#endregion 1058//#region node_modules/@sundaysky/ai-common-types/dist/eventTypes.js 1059var require_eventTypes = /* @__PURE__ */ __commonJSMin(((exports) => { 1060 Object.defineProperty(exports, "__esModule", { value: true }); 1061 exports.ChatEventType = void 0; 1062 var ChatEventType; 1063 (function(ChatEventType) { 1064 ChatEventType["Delta"] = "delta"; 1065 ChatEventType["MessageEnded"] = "messageEnded"; 1066 ChatEventType["ChatEnded"] = "chatEnded"; 1067 ChatEventType["Error"] = "error"; 1068 })(ChatEventType || (exports.ChatEventType = ChatEventType = {})); 1069})); 1070//#endregion 1071//#region node_modules/@sundaysky/ai-common-types/dist/mediaTypes.js 1072var require_mediaTypes = /* @__PURE__ */ __commonJSMin(((exports) => { 1073 Object.defineProperty(exports, "__esModule", { value: true }); 1074})); 1075//#endregion 1076//#region node_modules/@sundaysky/ai-common-types/dist/realPromptToVideoTypes.js 1077var require_realPromptToVideoTypes = /* @__PURE__ */ __commonJSMin(((exports) => { 1078 Object.defineProperty(exports, "__esModule", { value: true }); 1079})); 1080//#endregion 1081//#region node_modules/@sundaysky/ai-common-types/dist/sceneTemplateTypes.js 1082var require_sceneTemplateTypes = /* @__PURE__ */ __commonJSMin(((exports) => { 1083 Object.defineProperty(exports, "__esModule", { value: true }); 1084})); 1085//#endregion 1086//#region node_modules/@sundaysky/ai-common-types/dist/studioTypes.js 1087var require_studioTypes = /* @__PURE__ */ __commonJSMin(((exports) => { 1088 Object.defineProperty(exports, "__esModule", { value: true }); 1089 exports.parseBrief = exports.wrapBriefInitialMessage = void 0; 1090 var MOCK_INITIAL_MESSAGE_TEMPLATE = "Given the following video brief please reply a message with following structure\n1. No opening line.\n2. Repeat exact brief.\n3. The sentence 'This is where we left off. If you'd like to create this video type \"Create\" or you can ask to do things like add scenes, change the tone or even the goal' :\nUse this format strictly on your first message. Otherwise use the system.\n"; 1091 var CTA_PREFIX = "Call to Action:"; 1092 var REGEX_BRIEF = /Video subject: (.+)\s+Video goal: (.+)\s+Company: (.+)\s+Tone: (.+)\s+Topics\(Scenes\):\s+((?:[\s\S])+)\s*\n\n\s*Your current video duration will be approx.(.+(?:SEC|MIN))\n/; 1093 var wrapBriefInitialMessage = (briefText) => { 1094 return `${MOCK_INITIAL_MESSAGE_TEMPLATE}${briefText}`; 1095 }; 1096 exports.wrapBriefInitialMessage = wrapBriefInitialMessage; 1097 var parseBrief = (brief) => { 1098 const match = brief.match(REGEX_BRIEF); 1099 if (!match) return; 1100 const durationParts = match[6].replace(/[^0-9\s]/g, "").replace(/\s+/g, " ").trim().split(" "); 1101 if (durationParts.length <= 0 || durationParts.length > 2) return; 1102 const durationInSeconds = parseInt(durationParts[0]) * 60 + (durationParts[1] ? parseInt(durationParts[1]) : 0); 1103 const topics = match[5].split("\n").map((topic) => topic.trim()).map((topic) => topic.replace(/\d+\.\s+/, "")).map((topic) => { 1104 const cta = topic.startsWith(CTA_PREFIX) ? topic.replace(CTA_PREFIX, "").trim() : void 0; 1105 return { 1106 title: topic.replace(CTA_PREFIX, "").trim(), 1107 detailedDescription: topic, 1108 cta 1109 }; 1110 }); 1111 let company; 1112 let industry; 1113 let industryMatch = match[3].match(/^(.+)\((.+)\)\s*$/); 1114 if (industryMatch) { 1115 company = industryMatch[1].trim(); 1116 industry = industryMatch[2].trim(); 1117 } else {
1118 company = match[3]; 1119 industry = ""; 1120 } 1121 return { 1122 version: 1, 1123 subject: match[1], 1124 goal: match[2], 1125 industry, 1126 company, 1127 tone: match[4], 1128 topics, 1129 durationInSeconds, 1130 text: match[0].trim() 1131 }; 1132 }; 1133 exports.parseBrief = parseBrief; 1134})); 1135//#endregion 1136//#region node_modules/@sundaysky/ai-common-types/dist/videoTypes.js 1137var require_videoTypes = /* @__PURE__ */ __commonJSMin(((exports) => { 1138 Object.defineProperty(exports, "__esModule", { value: true }); 1139})); 1140//#endregion 1141//#region client/components/common/copilotChat/types.ts 1142var import_dist = (/* @__PURE__ */ __commonJSMin(((exports) => { 1143 var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) { 1144 if (k2 === void 0) k2 = k; 1145 var desc = Object.getOwnPropertyDescriptor(m, k); 1146 if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) desc = { 1147 enumerable: true, 1148 get: function() { 1149 return m[k]; 1150 } 1151 }; 1152 Object.defineProperty(o, k2, desc); 1153 }) : (function(o, m, k, k2) { 1154 if (k2 === void 0) k2 = k; 1155 o[k2] = m[k]; 1156 })); 1157 var __exportStar = exports && exports.__exportStar || function(m, exports$1) { 1158 for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports$1, p)) __createBinding(exports$1, m, p); 1159 }; 1160 Object.defineProperty(exports, "__esModule", { value: true }); 1161 __exportStar(require_aiClientTypes(), exports); 1162 __exportStar(require_aiTextClientTypes(), exports); 1163 __exportStar(require_ccDataTypes(), exports); 1164 __exportStar(require_eventTypes(), exports); 1165 __exportStar(require_mediaTypes(), exports); 1166 __exportStar(require_realPromptToVideoTypes(), exports); 1167 __exportStar(require_sceneTemplateTypes(), exports); 1168 __exportStar(require_studioTypes(), exports); 1169 __exportStar(require_videoTypes(), exports); 1170})))(); 1171var ClientChatRoleEnum = /* @__PURE__ */ function(ClientChatRoleEnum) { 1172 ClientChatRoleEnum["ASSISTANT"] = "assistant"; 1173 ClientChatRoleEnum["USER"] = "user"; 1174 return ClientChatRoleEnum; 1175}({}); 1176//#endregion 1177//#region client/components/editor/Hooks/UseProjectSelectedEntities/useProjectSelectedSceneId.ts 1178var useProjectSelectedSceneId = () => { 1179 return { 1180 projectSelectedSceneId: useReactiveVar(localEditorSelectedSceneIdVar), 1181 setProjectSelectedSceneId: selectScene 1182 }; 1183}; 1184//#endregion 1185//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/usePromptGeneratorChat.ts 1186function usePromptGeneratorChat(imagePrompt, language) { 1187 const { projectSelectedSceneId } = useProjectSelectedSceneId(); 1188 const { scene } = useScene(projectSelectedSceneId); 1189 const { frameIndex } = useSelectedFrame(scene?.id); 1190 const { studioElements } = useStudioElements(); 1191 let narrationText = ""; 1192 let usesNarration = false; 1193 if (scene) { 1194 const narrationsPlaceholder = getNarrationPlaceholder(scene, frameIndex); 1195 const isUsingRules = isPlaceholderUsingRules(narrationsPlaceholder); 1196 ({text: narrationText} = getNarrationTextAndRate(narrationsPlaceholder.placeholderContent, isUsingRules, studioElements, language)); 1197 usesNarration = narrationText && narrationText !== narrationsPlaceholder.ccPlaceholder.intent.defaultTextValue; 1198 } 1199 const cleanImagePrompt = imagePrompt.trim(); 1200 let initialMessage = "Hi! Please describe the image you have in mind."; 1201 if (cleanImagePrompt) initialMessage += " Or, if you'd rather I generate a **new** prompt based on the prompt you've already written, type **'prompt'**."; 1202 else if (usesNarration) initialMessage = "Hi! If you'd like me to generate a prompt based on the narration in this scene, type **'narration'** otherwise, describe the image you have in mind to get started."; 1203 const inputRef = (0, import_react.useRef)(null); 1204 const [sessionId, setSessionId] = (0, import_react.useState)(v4()); 1205 const [startingPoint, setStartingPoint] = (0, import_react.useState)(null); 1206 const [messages, setMessages] = (0, import_react.useState)([{ 1207 role: ClientChatRoleEnum.ASSISTANT, 1208 content: initialMessage, 1209 displayContent: initialMessage 1210 }]); 1211 const [isWaitingForAssistant, setIsWaitingForAssistant] = (0, import_react.useState)(false); 1212 const [isAssistantTyping, setIsAssistantTyping] = (0, import_react.useState)(false); 1213 const [proposedPrompt, setProposedPrompt] = (0, import_react.useState)(null); 1214 const restart = (0, import_react.useCallback)(() => { 1215 setSessionId(v4()); 1216 setStartingPoint(null); 1217 setProposedPrompt(null); 1218 setIsWaitingForAssistant(false); 1219 setIsAssistantTyping(false); 1220 setMessages([{ 1221 role: ClientChatRoleEnum.ASSISTANT, 1222 content: initialMessage, 1223 displayContent: initialMessage 1224 }]); 1225 }, [initialMessage]); 1226 (0, import_react.useEffect)(() => { 1227 restart(); 1228 }, [initialMessage]); 1229 return { 1230 messages, 1231 restart, 1232 sendMessage: (0, import_react.useCallback)((inputMessage) => { 1233 setProposedPrompt(null); 1234 setIsWaitingForAssistant(true); 1235 const cleanMessage = inputMessage.toLowerCase().trim(); 1236 const useNarration = usesNarration && cleanMessage === "narration"; 1237 let sentMessage = inputMessage; 1238 if (messages.length === 1) { 1239 let startingPointType = "answer to copilot"; 1240 if (useNarration) { 1241 sentMessage = narrationText; 1242 startingPointType = "narration"; 1243 } else if (cleanImagePrompt && cleanMessage === "prompt") { 1244 sentMessage = cleanImagePrompt; 1245 startingPointType = "prompt box text"; 1246 } 1247 setStartingPoint({ 1248 type: startingPointType, 1249 value: inputMessage 1250 }); 1251 } 1252 let localMessages = [...messages, { 1253 role: ClientChatRoleEnum.USER, 1254 content: sentMessage, 1255 displayContent: inputMessage 1256 }]; 1257 setMessages(localMessages); 1258 getAIImageGenPromptChatService().sendMessage({ 1259 sessionId, 1260 userMessage: sentMessage, 1261 messageHistory: messages, 1262 useVoiceOver: useNarration 1263 }, (event) => { 1264 setIsWaitingForAssistant(false);
1265 const lastMessage = localMessages[localMessages.length - 1]; 1266 if (event.eventType === import_dist.ChatEventType.Delta) { 1267 setIsAssistantTyping(true); 1268 const data = JSON.parse(event.data); 1269 localMessages = data.isInitialDelta ? [...localMessages, { 1270 role: ClientChatRoleEnum.ASSISTANT, 1271 content: data.delta, 1272 displayContent: data.delta 1273 }] : [...localMessages.slice(0, -1), { 1274 role: ClientChatRoleEnum.ASSISTANT, 1275 content: lastMessage.content + data.delta, 1276 displayContent: lastMessage.displayContent + data.delta 1277 }]; 1278 setMessages(localMessages); 1279 } else if (event.eventType === import_dist.ChatEventType.MessageEnded) { 1280 setIsAssistantTyping(false); 1281 const proposedPromptMatch = lastMessage.content.match(/\n\*\*(.*?)\*\*\n/); 1282 if (proposedPromptMatch) setProposedPrompt(proposedPromptMatch[1]); 1283 if (inputRef.current) inputRef.current.focus(); 1284 } 1285 }); 1286 }, [ 1287 sessionId, 1288 messages, 1289 cleanImagePrompt, 1290 usesNarration, 1291 narrationText 1292 ]), 1293 isAssistantTyping, 1294 isWaitingForAssistant, 1295 proposedPrompt, 1296 inputRef, 1297 startingPoint 1298 }; 1299} 1300//#endregion 1301//#region client/images/mediaGenStyles/real-life.png 1302var real_life_default = "/client/images/real-life.CQP8fnfZ.png"; 1303//#endregion 1304//#region client/images/mediaGenStyles/interface.png 1305var interface_default = "/client/images/interface.BzvzeI8b.png"; 1306//#endregion 1307//#region client/images/mediaGenStyles/3d.png 1308var _3d_default = "/client/images/3d.BbTdE6DX.png"; 1309//#endregion 1310//#region client/images/mediaGenStyles/object.png 1311var object_default = "/client/images/object.DdN4x8Q6.png"; 1312//#endregion 1313//#region client/images/mediaGenStyles/drawing.png 1314var drawing_default = "/client/images/drawing.Sp--AvyY.png"; 1315//#endregion 1316//#region client/images/mediaGenStyles/abstract.png 1317var abstract_default = "/client/images/abstract.BmlIv9B5.png"; 1318//#endregion 1319//#region client/images/cameraAngles/eye-level.svg 1320var eye_level_default = "data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cmask%20id='mask0_23442_36'%20style='mask-type:luminance'%20maskUnits='userSpaceOnUse'%20x='0'%20y='0'%20width='16'%20height='16'%3e%3cpath%20d='M16%200H0V16H16V0Z'%20fill='white'/%3e%3c/mask%3e%3cg%20mask='url(%23mask0_23442_36)'%3e%3cpath%20d='M8.11621%202.00684C11.3087%202.14422%2014.0831%204.38852%2015.4844%207.58008L15.4883%207.58789C15.5445%207.72833%2015.6113%207.94773%2015.6113%208.12695C15.6112%208.30146%2015.5463%208.544%2015.4873%208.69141L15.4844%208.69922C14.0373%2011.9952%2011.1269%2014.2528%207.80566%2014.2529C4.4586%2014.2529%201.54786%2011.9957%200.100586%208.69922L0.0966797%208.69141C0.0454228%208.56312%200.0170883%208.39358%200.00585938%208.25391L0%208.12695C1.01172e-05%207.97269%200.0296118%207.75565%200.0966797%207.58789L0.0996094%207.58008C1.54633%204.28498%204.45745%202.00006%207.80566%202L8.11621%202.00684ZM7.80566%203.5C5.20502%203.50006%202.77391%205.27295%201.5%208.12109C1.49971%208.12352%201.5%208.12793%201.5%208.12793C1.50023%208.13035%201.50075%208.13303%201.50098%208.13574C1.50193%208.14735%201.50216%208.15616%201.50293%208.16309C2.77464%2011.0016%205.20068%2012.7529%207.80566%2012.7529C10.3897%2012.7528%2012.8221%2010.9936%2014.0918%208.13867C12.819%205.27812%2010.3832%203.5001%207.80566%203.5ZM7.80566%204.01855C10.0598%204.01867%2011.9138%205.87956%2011.9141%208.15234C11.9141%2010.4107%2010.0484%2012.2343%207.80566%2012.2344C5.52907%2012.2343%203.6975%2010.4037%203.69727%208.12695C3.69731%205.88024%205.52505%204.01862%207.80566%204.01855ZM7.80566%205.51855C6.36108%205.51862%205.19731%206.70105%205.19727%208.12695C5.19747%209.57514%206.35737%2010.7343%207.80566%2010.7344C9.2353%2010.7343%2010.4141%209.56699%2010.4141%208.15234C10.4138%206.70051%209.22392%205.51867%207.80566%205.51855Z'%20fill='%23323338'/%3e%3cpath%20d='M2.80468%207.41357C3.2189%207.41357%203.55468%207.74936%203.55468%208.16357C3.55468%208.57779%203.2189%208.91357%202.80468%208.91357H0.804687C0.390473%208.91357%200.0546875%208.57779%200.0546875%208.16357C0.0546875%207.74936%200.390473%207.41357%200.804687%207.41357H2.80468Z'%20fill='%2382828E'/%3e%3cpath%20d='M6.80469%207.41357C7.21891%207.41357%207.55469%207.74936%207.55469%208.16357C7.55469%208.57779%207.21891%208.91357%206.80469%208.91357H4.80469C4.39048%208.91357%204.05469%208.57779%204.05469%208.16357C4.05469%207.74936%204.39048%207.41357%204.80469%207.41357H6.80469Z'
1320%20fill='%2382828E'/%3e%3cpath%20d='M10.8047%207.41357C11.2189%207.41357%2011.5547%207.74936%2011.5547%208.16357C11.5547%208.57779%2011.2189%208.91357%2010.8047%208.91357H8.80469C8.39048%208.91357%208.05469%208.57779%208.05469%208.16357C8.05469%207.74936%208.39048%207.41357%208.80469%207.41357H10.8047Z'%20fill='%2382828E'/%3e%3cpath%20d='M14.8047%207.41357C15.2189%207.41357%2015.5547%207.74936%2015.5547%208.16357C15.5547%208.57779%2015.2189%208.91357%2014.8047%208.91357H12.8047C12.3905%208.91357%2012.0547%208.57779%2012.0547%208.16357C12.0547%207.74936%2012.3905%207.41357%2012.8047%207.41357H14.8047Z'%20fill='%2382828E'/%3e%3c/g%3e%3c/svg%3e"; 1321//#endregion 1322//#region client/images/cameraAngles/close-up.svg 1323var close_up_default = "data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M7.67937%209.95C5.43937%209.95%203.60938%208.13%203.60938%205.88C3.60938%203.63%205.42937%201.81%207.67937%201.81C9.92937%201.81%2011.7494%203.63%2011.7494%205.88C11.7494%208.13%209.92937%209.95%207.67937%209.95ZM7.67937%203.32C6.25937%203.32%205.10938%204.47%205.10938%205.89C5.10938%207.31%206.25937%208.46%207.67937%208.46C9.09937%208.46%2010.2494%207.31%2010.2494%205.89C10.2494%204.47%209.09937%203.32%207.67937%203.32Z'%20fill='%23323338'/%3e%3cpath%20d='M4.03923%2013.09C3.84923%2013.09%203.65923%2013.02%203.51923%2012.88C3.21923%2012.59%203.21923%2012.12%203.50923%2011.82C4.54923%2010.75%206.06923%2010.14%207.67923%2010.14C9.28923%2010.14%2010.8092%2010.75%2011.8492%2011.82C12.1392%2012.12%2012.1292%2012.59%2011.8392%2012.88C11.5392%2013.17%2011.0692%2013.16%2010.7792%2012.87C10.0192%2012.09%208.88923%2011.65%207.67923%2011.65C6.46923%2011.65%205.33923%2012.1%204.57923%2012.88C4.42923%2013.03%204.23923%2013.11%204.03923%2013.11V13.09Z'%20fill='%23323338'/%3e%3cpath%20d='M4.3%2015.34H0.75C0.34%2015.34%200%2015%200%2014.59V10.97C0%2010.56%200.34%2010.22%200.75%2010.22C1.16%2010.22%201.5%2010.56%201.5%2010.97V13.84H4.3C4.71%2013.84%205.05%2014.18%205.05%2014.59C5.05%2015%204.71%2015.34%204.3%2015.34Z'%20fill='%2382828E'/%3e%3cpath%20d='M0.75%205.09999C0.34%205.09999%200%204.75999%200%204.34999V0.789993C0%200.379993%200.34%200.0399933%200.75%200.0399933H4.37C4.78%200.0399933%205.12%200.379993%205.12%200.789993C5.12%201.19999%204.78%201.53999%204.37%201.53999H1.5V4.33999C1.5%204.74999%201.16%205.08999%200.75%205.08999V5.09999Z'%20fill='%2382828E'/%3e%3cpath%20d='M14.4602%2015.3H10.9102C10.5002%2015.3%2010.1602%2014.96%2010.1602%2014.55C10.1602%2014.14%2010.5002%2013.8%2010.9102%2013.8H13.7102V10.93C13.7102%2010.52%2014.0502%2010.18%2014.4602%2010.18C14.8702%2010.18%2015.2102%2010.52%2015.2102%2010.93V14.55C15.2102%2014.96%2014.8702%2015.3%2014.4602%2015.3Z'%20fill='%2382828E'/%3e%3cpath%20d='M14.4598%205.06C14.0498%205.06%2013.7098%204.72%2013.7098%204.31V1.5H10.8398C10.4298%201.5%2010.0898%201.16%2010.0898%200.75C10.0898%200.34%2010.4298%200%2010.8398%200H14.4598C14.8698%200%2015.2098%200.34%2015.2098%200.75V4.3C15.2098%204.71%2014.8698%205.05%2014.4598%205.05V5.06Z'%20fill='%2382828E'/%3e%3c/svg%3e"; 1324//#endregion 1325//#region client/images/cameraAngles/wide-shot.svg 1326var wide_shot_default = "data:image/svg+xml,%3csvg%20width='16'%20height='16'%20viewBox='0%200%2016%2016'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cmask%20id='mask0_24382_118381'%20style='mask-type:luminance'%20maskUnits='userSpaceOnUse'%20x='0'%20y='0'%20width='16'%20height='16'%3e%3cpath%20d='M16%200H0V16H16V0Z'%20fill='white'/%3e%3c/mask%3e%3cg%20mask='url(%23mask0_24382_118381)'%3e%3cpath%20d='M12.9505%2012.07H3.23047C2.82047%2012.07%202.48047%2011.73%202.48047%2011.32C2.48047%2010.91%202.82047%2010.57%203.23047%2010.57H12.9505C13.3605%2010.57%2013.7005%2010.91%2013.7005%2011.32C13.7005%2011.73%2013.3605%2012.07%2012.9505%2012.07Z'%20fill='%23323338'/%3e%3cpath%20d='M8.09281%204.67C7.56281%204.67%207.13281%204.24%207.13281%203.71C7.13281%203.18%207.56281%202.75%208.09281%202.75C8.62281%202.75%209.05281%203.18%209.05281%203.71C9.05281%204.24%208.62281%204.67%208.09281%204.67Z'%20fill='%23323338'/%3e%3cpath%20d='M4.75141%2015.7H1.19141C0.781406%2015.7%200.441406%2015.36%200.441406%2014.95V11.33C0.441406%2010.92%200.781406%2010.58%201.19141%2010.58C1.60141%2010.58%201.94141%2010.92%201.94141%2011.33V14.2H4.74141C5.15141%2014.2%205.49141%2014.54%205.49141%2014.95C5.49141%2015.36%205.15141%2015.7%204.74141%2015.7H4.75141Z'%20fill='%2382828E'/%3e%3cpath%20d='M1.19141%205.45999C0.781406%205.45999%200.441406%205.11999%200.441406%204.70999V1.14999C0.441406%200.739994%200.781406%200.399994%201.19141%200.399994H4.81141C5.22141%200.399994%205.56141%200.739994%205.56141%201.14999C5.56141%201.55999%205.22141%201.89999%204.8114
13261%201.89999H1.94141V4.69999C1.94141%205.10999%201.60141%205.44999%201.19141%205.44999V5.45999Z'%20fill='%2382828E'/%3e%3cpath%20d='M14.9133%2015.66H11.3633C10.9533%2015.66%2010.6133%2015.32%2010.6133%2014.91C10.6133%2014.5%2010.9533%2014.16%2011.3633%2014.16H14.1633V11.29C14.1633%2010.88%2014.5033%2010.54%2014.9133%2010.54C15.3233%2010.54%2015.6633%2010.88%2015.6633%2011.29V14.91C15.6633%2015.32%2015.3233%2015.66%2014.9133%2015.66Z'%20fill='%2382828E'/%3e%3cpath%20d='M14.913%205.42C14.503%205.42%2014.163%205.08%2014.163%204.67V1.86H11.293C10.883%201.86%2010.543%201.52%2010.543%201.11C10.543%200.700001%2010.883%200.360001%2011.293%200.360001H14.913C15.323%200.360001%2015.663%200.700001%2015.663%201.11V4.66C15.663%205.07%2015.323%205.41%2014.913%205.41V5.42Z'%20fill='%2382828E'/%3e%3cpath%20d='M8.09125%205.55H8.08125C7.77749%205.55%207.53125%205.79625%207.53125%206.1V7.54C7.53125%207.84376%207.77749%208.09%208.08125%208.09H8.09125C8.39501%208.09%208.64125%207.84376%208.64125%207.54V6.1C8.64125%205.79625%208.39501%205.55%208.09125%205.55Z'%20fill='black'/%3e%3cpath%20d='M8.09297%208.84C7.37297%208.84%206.79297%208.26%206.79297%207.54V6.11C6.79297%205.39%207.37297%204.81%208.09297%204.81C8.81297%204.81%209.39297%205.39%209.39297%206.11V7.54C9.39297%208.26%208.81297%208.84%208.09297%208.84Z'%20fill='%23323338'/%3e%3cpath%20d='M7.53125%2011.04C7.12125%2011.04%206.78125%2010.7%206.78125%2010.29V7.56C6.78125%207.15%207.12125%206.81%207.53125%206.81C7.94125%206.81%208.28125%207.15%208.28125%207.56V10.29C8.28125%2010.7%207.94125%2011.04%207.53125%2011.04Z'%20fill='%23323338'/%3e%3cpath%20d='M8.64063%2011.04C8.23063%2011.04%207.89062%2010.7%207.89062%2010.29V7.56C7.89062%207.15%208.23063%206.81%208.64063%206.81C9.05063%206.81%209.39063%207.15%209.39063%207.56V10.29C9.39063%2010.7%209.05063%2011.04%208.64063%2011.04Z'%20fill='%23323338'/%3e%3cpath%20d='M7.05203%208.02C6.96203%208.02%206.87203%208%206.78203%207.97C6.39203%207.82%206.20203%207.39%206.35203%207L6.87203%205.64C7.02203%205.25%207.45203%205.06%207.84203%205.21C8.23203%205.36%208.42203%205.79%208.27203%206.18L7.75203%207.54C7.63203%207.84%207.35203%208.02%207.05203%208.02Z'%20fill='%23323338'/%3e%3cpath%20d='M9.12281%207.98001C8.82281%207.98001%208.54281%207.80001%208.42281%207.50001L7.90281%206.14001C7.75281%205.75001%207.94281%205.32001%208.33281%205.17001C8.72281%205.02001%209.15281%205.21001%209.30281%205.60001L9.82281%206.96001C9.97281%207.35001%209.78281%207.78001%209.39281%207.93001C9.30281%207.96001%209.21281%207.98001%209.12281%207.98001Z'%20fill='%23323338'/%3e%3c/g%3e%3c/svg%3e"; 1327//#endregion 1328//#region client/images/cameraAngles/high-angle.svg 1329var high_angle_default = "data:image/svg+xml,%3csvg%20width='17'%20height='17'%20viewBox='0%200%2017%2017'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cmask%20id='mask0_23442_122'%20style='mask-type:luminance'%20maskUnits='userSpaceOnUse'%20x='0'%20y='0'%20width='16'%20height='17'%3e%3cpath%20d='M16%200.235016H0V16.235H16V0.235016Z'%20fill='white'/%3e%3c/mask%3e%3cg%20mask='url(%23mask0_23442_122)'%3e%3cpath%20d='M4.75141%2015.935H1.19141C0.781406%2015.935%200.441406%2015.595%200.441406%2015.185V11.565C0.441406%2011.155%200.781406%2010.815%201.19141%2010.815C1.60141%2010.815%201.94141%2011.155%201.94141%2011.565V14.435H4.74141C5.15141%2014.435%205.49141%2014.775%205.49141%2015.185C5.49141%2015.595%205.15141%2015.935%204.74141%2015.935H4.75141Z'%20fill='%2382828E'/%3e%3cpath%20d='M1.19141%205.69501C0.781406%205.69501%200.441406%205.35501%200.441406%204.94501V1.38501C0.441406%200.97501%200.781406%200.63501%201.19141%200.63501H4.81141C5.22141%200.63501%205.56141%200.97501%205.56141%201.38501C5.56141%201.79501%205.22141%202.13501%204.81141%202.13501H1.94141V4.93501C1.94141%205.34501%201.60141%205.68501%201.19141%205.68501V5.69501Z'%20fill='%2382828E'/%3e%3cpath%20d='M14.9133%2015.895H11.3633C10.9533%2015.895%2010.6133%2015.555%2010.6133%2015.145C10.6133%2014.735%2010.9533%2014.395%2011.3633%2014.395H14.1633V11.525C14.1633%2011.115%2014.5033%2010.775%2014.9133%2010.775C15.3233%2010.775%2015.6633%2011.115%2015.6633%2011.525V15.145C15.6633%2015.555%2015.3233%2015.895%2014.9133%2015.895Z'%20fill='%2382828E'/%3e%3c/g%3e%3cpath%20d='M11.6328%208.08659C11.8438%208.43816%2011.7266%208.90691%2011.375%209.14128C11.2578%209.21159%2011.1172%209.23503%2011%209.23503C10.7422%209.23503%2010.4844%209.11784%2010.3203%208.88347L9.64062%207.80534L9.64063%2012.985C9.64063%2013.4069%209.28906%2013.735%208.89063%2013.735C8.46875%2013.735%208.14063%2013.4069%208.14063%2012.985L8.14062%209.61003H7.76563V12.985C7.76563%2013.4069%207.4375%2013.735%207.03906%2013.735C6.61719%2013.735%206.28906%2013.4069%206.28906%2012.985L6.3125%207.80534L5.63281%208.88347C5.39844%209.23503%204.95313%209.35222%204.60156%209.14128C4.25%208.90691%204.13281%208.43816%204.34375%208.08659L6.
132900781%205.46159C6.28906%205.01628%206.75781%204.73503%207.27344%204.73503L8.70312%204.73503C9.21875%204.73503%209.6875%205.01628%209.96875%205.46159L11.6328%208.08659ZM8%203.98503C7.36719%203.98503%206.875%203.49284%206.875%202.86003C6.875%202.25066%207.36719%201.73503%208%201.73503C8.60938%201.73503%209.125%202.25066%209.125%202.86003C9.125%203.49284%208.60938%203.98503%208%203.98503Z'%20fill='%23323338'/%3e%3cpath%20d='M11.6227%200.000478232C11.7884%200.000478217%2011.9403%200.0695314%2012.0508%200.180017C12.1751%200.304313%2012.2442%200.456231%2012.2442%200.621959L12.2442%203.5222L15.088%200.642216C15.3366%200.393624%2015.7659%200.407435%2016.0007%200.642216C16.2217%200.863187%2016.2493%201.34439%2016.0007%201.59298L13.1281%204.40608L16.0421%204.4199C16.3874%204.40608%2016.6774%204.69611%2016.6636%205.04138C16.6774%205.38664%2016.3874%205.67667%2016.0421%205.66286L11.6227%205.66286C11.2774%205.67667%2010.9874%205.38664%2011.0012%205.04138L11.0012%200.621959C10.9874%200.276692%2011.2774%20-0.0133324%2011.6227%200.000478232Z'%20fill='%23323338'/%3e%3c/svg%3e"; 1330//#endregion 1331//#region client/images/cameraAngles/low-angle.svg 1332var low_angle_default = "data:image/svg+xml,%3csvg%20width='17'%20height='18'%20viewBox='0%200%2017%2018'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M5.04137%201
13327.6629C4.87564%2017.6629%204.72373%2017.5938%204.61324%2017.4834C4.48895%2017.3591%204.41989%2017.2071%204.41989%2017.0414V14.1412L1.5761%2017.0212C1.32751%2017.2697%200.898148%2017.2559%200.663367%2017.0212C0.442396%2016.8002%200.414768%2016.319%200.66336%2016.0704L3.53601%2013.2573L0.621954%2013.2435C0.276687%2013.2573%20-0.0133369%2012.9673%200.000473779%2012.622C-0.0133369%2012.2767%200.276687%2011.9867%200.621954%2012.0005H5.04137C5.38664%2011.9867%205.67666%2012.2767%205.66285%2012.622V17.0414C5.67666%2017.3867%205.38664%2017.6767%205.04137%2017.6629Z'%20fill='%23323338'/%3e%3cpath%20d='M12.6324%207.85156C12.8434%208.20312%2012.7262%208.67188%2012.3746%208.90625C12.2574%208.97656%2012.1168%209%2011.9996%209C11.7418%209%2011.484%208.88281%2011.3199%208.64844L10.6402%207.57031V12.75C10.6402%2013.1719%2010.2887%2013.5%209.89021%2013.5C9.46833%2013.5%209.14021%2013.1719%209.14021%2012.75L9.1402%209.375H8.76521V12.75C8.76521%2013.1719%208.43708%2013.5%208.03864%2013.5C7.61677%2013.5%207.28864%2013.1719%207.28864%2012.75L7.31208%207.57031L6.63239%208.64844C6.39802%209%205.95271%209.11719%205.60114%208.90625C5.24958%208.67188%205.13239%208.20312%205.34333%207.85156L7.00739%205.22656C7.28864%204.78125%207.75739%204.5%208.27302%204.5H9.7027C10.2184%204.5%2010.6871%204.78125%2010.9684%205.22656L12.6324%207.85156ZM8.99958%203.75C8.36677%203.75%207.87458%203.25781%207.87458%202.625C7.87458%202.01562%208.36677%201.5%208.99958%201.5C9.60896%201.5%2010.1246%202.01562%2010.1246%202.625C10.1246%203.25781%209.60896%203.75%208.99958%203.75Z'%20fill='%23323338'/%3e%3cpath%20d='M2.14064%205.10001C1.73064%205.10001%201.39062%204.76001%201.39062%204.35001V0.790009C1.39062%200.380009%201.73064%200.0400085%202.14064%200.0400085H5.76062C6.17062%200.0400085%206.51062%200.380009%206.51062%200.790009C6.51062%201.20001%206.17062%201.54001%205.76062%201.54001H2.89062V4.34001C2.89062%204.75001%202.55063%205.09001%202.14064%205.09001V5.10001Z'%20fill='%2382828E'/%3e%3cpath%20d='M15.8625%2015.3H12.3125C11.9025%2015.3%2011.5625%2014.96%2011.5625%2014.55C11.5625%2014.14%2011.9025%2013.8%2012.3125%2013.8H15.1125V10.93C15.1125%2010.52%2015.4525%2010.18%2015.8625%2010.18C16.2725%2010.18%2016.6125%2010.52%2016.6125%2010.93V14.55C16.6125%2014.96%2016.2725%2015.3%2015.8625%2015.3Z'%20fill='%2382828E'/%3e%3cpath%20d='M15.8622%205.06C15.4522%205.06%2015.1122%204.72%2015.1122%204.31V1.5H12.2422C11.8322%201.5%2011.4922%201.16%2011.4922%200.75C11.4922%200.34%2011.8322%200%2012.2422%200H15.8622C16.2722%200%2016.6122%200.34%2016.6122%200.75V4.3C16.6122%204.71%2016.2722%205.05%2015.8622%205.05V5.06Z'%20fill='%2382828E'/%3e%3c/svg%3e"; 1333//#endregion 1334//#region client/images/cameraAngles/birds-eye-view.svg 1335var birds_eye_view_default = "data:image/svg+xml,%3csvg%20width='17'%20height='17'%20viewBox='0%200%2017%2017'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M7.99848%2015.3967C7.99848%2015.3967%207.42057%2015.3967%204.41797%2015.3967C4.41797%2015.3967%204.751%2013.8944%205.4815%2012.9877C5.83893%2012.5424%206.43467%2012.2611%207.08998%2012.2611H7.99848V15.3967Z'%20fill='%23323338'/%3e%3cpath%20d='M7.99848%2015.3967C7.99848%2015.3967%207.42057%2015.3967%204.41797%2015.3967C4.41797%2015.3967%204.751%2013.8944%205.4815%2012.9877C5.83893%2012.5424%206.43467%2012.2611%207.08998%2012.2611H7.99848V15.3967Z'%20fill='%23323338'/%3e%3cpath%20d='M8%2015.3967C8%2015.3967%208.5779%2015.3967%2011.5806%2015.3967C11.5806%2015.3967%2011.2475%2013.8944%2010.517%2012.9877C10.1595%2012.5424%209.5638%2012.2611%208.9085%2012.2611H8V15.3967Z'%20fill='%23323338'/%3e%3cpath%20d='M8%2015.3967C8%2015.3967%208.5779%2015.3967%2011.5806%2015.3967C11.5806%2015.3967%2011.2475%2013.8944%2010.517%2012.9877C10.1595%2012.5424%209.5638%2012.2611%208.9085%2012.2611H8V15.3967Z'%20fill='%23323338'/%3e%3cpath%20d='M5.01172%203.64062C5.11027%203.54688%205.24168%203.5%205.37308%203.5C5.52091%203.5%205.65232%203.54688%205.75087%203.64062L7.47558%205.28125V0.5C7.47558%200.21875%207.72196%200%208.0012%200C8.26402%200%208.52683%200.21875%208.52683%200.5V5.28125L10.268%203.64062C10.4651%203.4375%2010.81%203.4375%2011.0071%203.64062C11.2206%203.82812%2011.2206%204.15625%2011.0071%204.34375L8.37899%206.84375C8.18188%207.04688%207.83695%207.04688%207.63984%206.84375L5.01172%204.34375C4.79818%204.15625%204.79818%203.82812%205.01172%203.64062Z'%20fill='%23323338'/%3e%3cpath%20d='M7.99894%2011.4824C9.03821%2011.4824%209.8807%2010.681%209.8807%209.69239C9.8807%208.70379%209.03821%207.90237%207.99894%207.90237C6.95968%207.90237%206.11719%208.70379%206.11719%209.69239C6.11719%2010.681%206.95968%2011.4824%207.99894%2011.4824Z'%20fill='%23323338'/%3e%3cpath%20d='M4.53088%2016H0.788436C0.357424%2016%200%2015.66%200%2015.25V11.63C0%2011.22%200.357424%2010.88%200.788436%2010.88C1.21945%2010.88%201.57687%2011.22%201.57687%2011.63V14.5H4.52037C4.95138%2014.5%205.3088%2014.84%205.3088%2015.25C5.3088%2015.66%204.95138%2016%204.52037%2016H4.53088Z'%20fill='%2382828E'/%3e%3cpath%20d='M0.788436%205.76001C0.357424%205.76001%200%205.42001%200%205.01001V1.45001C0%201.04001%200.357424%200.700012%200.788436%200.700012H4.59395C5.02497%200.700012%205.38239%201.04001%205.38239%201.45001C5.38239%201.86001%205.02497%202.20001%204.59395%202.20001H1.57687V5.00001C1.57687%205.41001%201.21945%205.75001%200.788436%205.75001V5.76001Z'%20fill='%2382828E'/%3e%3cpath%20d='M15.2118%2015.96H11.4798C11.0488%2015.96%2010.6914%2015.62%2010.6914%2015.21C10.6914%2014.8%2011.0488%2014.46%2011.4798%2014.46H14.4233V11.59C14.4233%2011.18%2014.7808%2010.84%2015.2118%2010.84C15.6428%2010.84%2016.0002%2011.18%2016.0002%2011.59V15.21C16.0002%2015.62%2015.6428%2015.96%2015.2118%2015.96Z'%20fill='%2382828E'/%3e%3cpath%20d='M15.2111%205.72C14.7801%205.72%2014.4227%205.38%2014.4227%204.97V2.16H11.4056C10.9746%202.16%2010.6172%201.82%2010.6172%201.41C10.6172%201%2010.9746%200.660004%2011.4056%200.660004H15.2111C15.6422%200.660004%2015.9996%201%2015.9996%201.41V4.96C15.9996%205.37%2015.6422%205.71%2015.2111%205.71V5.72Z'%20fill='%2382828E'/%3e%3c/svg%3e";
1336//#endregion 1337//#region client/images/svg/truffle/ai-image-static-camera.svg 1338var ai_image_static_camera_default = "data:image/svg+xml,%3csvg%20width='67'%20height='67'%20viewBox='0%200%2067%2067'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3crect%20width='67'%20height='67'%20fill='%23FAFAFA'/%3e%3cg%20opacity='0.4'%3e%3cpath%20d='M39.2682%2020.9041H16.8734C15.3285%2020.9041%2014.0762%2022.1564%2014.0762%2023.7013V43.2955C14.0762%2044.8403%2015.3285%2046.0927%2016.8734%2046.0927H39.2682C40.813%2046.0927%2042.0654%2044.8403%2042.0654%2043.2955V23.7013C42.0654%2022.1564%2040.813%2020.9041%2039.2682%2020.9041Z'%20fill='%237F8CED'/%3e%3cpath%20d='M43.7676%2037.6976L52.8494%2043.0978C53.0571%2043.2251%2053.295%2043.2954%2053.563%2043.2954C54.3335%2043.2954%2054.9633%2042.6656%2054.9633%2041.8951V25.1016C54.9633%2024.3344%2054.3335%2023.7013%2053.563%2023.7013C53.295%2023.7013%2053.0571%2023.7716%2052.8494%2023.8989L43.7676%2029.2991V37.6942V37.6976Z'%20fill='%237F8CED'/%3e%3c/g%3e%3c/svg%3e"; 1339//#endregion 1340//#region client/images/svg/truffle/ai-image-static-gif.gif 1341var ai_image_static_gif_default = "/client/images/ai-image-static-gif.D4y7YONb.gif"; 1342//#endregion 1343//#region client/images/svg/truffle/ai-image-zoom-in.svg 1344var ai_image_zoom_in_default = "data:image/svg+xml,%3csvg%20width='67'%20height='67'%20viewBox='0%200%2067%2067'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3crect%20width='67'%20height='67'%20fill='%23FAFAFA'/%3e%3cpath%20d='M28.8482%2029.5938H21.7428C21.0963%2029.5938%2020.5703%2029.0678%2020.5703%2028.4213C20.5703%2027.7747%2021.0963%2027.2488%2021.7428%2027.2488H27.6757V21.5973C27.6757%2020.9508%2028.2016%2020.4248%2028.8482%2020.4248C29.4947%2020.4248%2030.0207%2020.9508%2030.0207%2021.5973V28.4213C30.0207%2029.0678%2029.4947%2029.5938%2028.8482%2029.5938Z'%20fill='%230053E5'/%3e%3cpath%20d='M27.2806%2028.0896C27.0159%2028.0896%2026.7513%2027.9992%2026.5302%2027.8183L18.4232%2021.0747C17.924%2020.6593%2017.857%2019.9223%2018.2724%2019.4232C18.6878%2018.924%2019.4248%2018.857%2019.924%2019.2724L28.031%2026.016C28.5301%2026.4314%2028.5971%2027.1684%2028.1817%2027.6675C27.9506%2027.9456%2027.6156%2028.0896%2027.2806%2028.0896Z'%20fill='%230053E5'/%3e%3cpath%20d='M45.4808%2029.5938H38.6569C38.0103%2029.5938%2037.4844%2029.0678%2037.4844%2028.4213V21.3159C37.4844%2020.6694%2038.0103%2020.1434%2038.6569%2020.1434C39.3034%2020.1434%2039.8294%2020.6694%2039.8294%2021.3159V27.2488H45.4808C46.1274%2027.2488%2046.6533%2027.7747%2046.6533%2028.4213C46.6533%2029.0678%2046.1274%2029.5938%2045.4808%2029.5938Z'%20fill='%230053E5'/%3e%3cpath%20d='M40.1571%2028.026C39.8355%2028.026%2039.5173%2027.8954%2039.2861%2027.6374C38.854%2027.155%2038.8942%2026.4147%2039.3732%2025.9825L46.8069%2019.3026C47.2893%2018.8705%2048.0296%2018.9107%2048.4618%2019.3897C48.8939%2019.8721%2048.8537%2020.6125%2048.3747%2021.0446L40.941%2027.7245C40.7166%2027.9255%2040.4352%2028.026%2040.1571%2028.026Z'%20fill='%230053E5'/%3e%3cpath%20d='M28.8462%2046.1797C28.1997%2046.1797%2027.6737%2045.6538%2027.6737%2045.0072V39.3524H21.7409C21.0943%2039.3524%2020.5684%2038.8265%2020.5684%2038.1799C20.5684%2037.5334%2021.0943%2037.0074%2021.7409%2037.0074H28.8462C29.4928%2037.0074%2030.0187%2037.5334%2030.0187%2038.1799V45.0072C30.0187%2045.6538%2029.4928%2046.1797%2028.8462%2046.1797Z'%20fill='%230053E5'/%3e%3cpath%20d='M19.1755%2047.972C18.8505%2047.972%2018.5256%2047.838%2018.2944%2047.5734C17.869%2047.0876%2017.9159%2046.3439%2018.4016%2045.9185L26.5086%2038.8064C26.9944%2038.3776%2027.7347%2038.4279%2028.1635%2038.9136C28.589%2039.3994%2028.5421%2040.1431%2028.0563%2040.5685L19.9493%2047.6806C19.7249%2047.8749%2019.4502%2047.972%2019.1755%2047.972Z'%20fill='%230053E5'/%3e%3cpath%20d='M38.653%2046.4611C38.0064%2046.4611%2037.4805%2045.9351%2037.4805%2045.2886V38.1832C37.4805%2037.5367%2038.0064%2037.0107%2038.653%2037.0107H45.4769C46.1235%2037.0107%2046.6494%2037.5367%2046.6494%2038.1832C46.6494%2038.8298%2046.1235%2039.3557%2045.4769%2039.3557H39.8255V45.2886C39.8255%2045.9351%2039.2995%2046.4611%2038.653%2046.4611Z'%20fill='%230053E5'/%3e%3cpath%20d='M47.5905%2047.9719C47.3024%2047.9719%2047.011%2047.8647%2046.7832%2047.6503L39.3495%2040.6019C38.8805%2040.1563%2038.8604%2039.4126%2039.306%2038.9436C39.7515%2038.4746%2040.4952%2038.4545%2040.9642%2038.9001L48.3979%2045.9485C48.8669%2046.394%2048.887%2047.1377%2048.4414%2047.6067C48.2103%2047.8513%2047.9021%2047.9719%2047.5905%2047.9719Z'%20fill='%230053E5'/%3e%3c/svg%3e";
1345//#endregion 1346//#region client/images/svg/truffle/ai-image-zoom-in-gif.gif 1347var ai_image_zoom_in_gif_default = "/client/images/ai-image-zoom-in-gif.BKiU2wW3.gif"; 1348//#endregion 1349//#region client/images/svg/truffle/ai-image-zoom-out.svg 1350var ai_image_zoom_out_default = "data:image/svg+xml,%3csvg%20width='67'%20height='67'%20viewBox='0%200%2067%2067'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3crect%20width='67'%20height='67'%20fill='%23FAFAFA'/%3e%3cpath%20d='M48.3208%2028.1723C47.6743%2028.1723%2047.1483%2027.6464%2047.1483%2026.9998V21.345H41.2155C40.5689%2021.345%2040.043%2020.8191%2040.043%2020.1725C40.043%2019.526%2040.5689%2019%2041.2155%2019H48.3208C48.9674%2019%2049.4933%2019.526%2049.4933%2020.1725V26.9998C49.4933%2027.6464%2048.9674%2028.1723%2048.3208%2028.1723Z'%20fill='%230053E5'/%3e%3cpath%20d='M38.6501%2029.9611C38.3252%2029.9611%2038.0002%2029.8271%2037.7691%2029.5625C37.3436%2029.0767%2037.3905%2028.3364%2037.8763%2027.9076L45.9833%2020.7955C46.469%2020.3701%2047.2094%2020.417%2047.6382%2020.9027C48.0636%2021.3885%2048.0167%2022.1288%2047.531%2022.5576L39.424%2029.6697C39.2029%2029.864%2038.9248%2029.9611%2038.6501%2029.9611Z'%20fill='%230053E5'/%3e%3cpath%20d='M19.1725%2028.1723C18.526%2028.1723%2018%2027.6464%2018%2026.9998V20.1725C18%2019.526%2018.526%2019%2019.1725%2019H26.2779C26.9244%2019%2027.4503%2019.526%2027.4503%2020.1725C27.4503%2020.8191%2026.9244%2021.345%2026.2779%2021.345H20.345V26.9998C20.345%2027.6464%2019.8191%2028.1723%2019.1725%2028.1723Z'%20fill='%230053E5'/%3e%3cpath%20d='M28.8444%2029.9612C28.5697%2029.9612%2028.295%2029.864%2028.0705%2029.6697L19.9635%2022.5577C19.4778%2022.1289%2019.4275%2021.3885%2019.8563%2020.9028C20.2851%2020.417%2021.0255%2020.3668%2021.5112%2020.7956L29.6182%2027.9076C30.104%2028.3364%2030.1542%2029.0768%2029.7254%2029.5625C29.4943%2029.8272%2029.1693%2029.9612%2028.8444%2029.9612Z'%20fill='%230053E5'/%3e%3cpath%20d='M26.2779%2048.5336H19.1725C18.526%2048.5336%2018%2048.0077%2018%2047.3611V40.5338C18%2039.8873%2018.526%2039.3613%2019.1725%2039.3613C19.8191%2039.3613%2020.345%2039.8873%2020.345%2040.5338V46.1886H26.2779C26.9244%2046.1886%2027.4503%2046.7146%2027.4503%2047.3611C27.4503%2048.0077%2026.9244%2048.5336%2026.2779%2048.5336Z'%20fill='%230053E5'/%3e%3cpath%20d='M20.7399%2047.0295C20.415%2047.0295%2020.0901%2046.8955%2019.8589%2046.6309C19.4335%2046.1451%2019.4804%2045.4048%2019.9661%2044.976L28.0731%2037.8639C28.5589%2037.4351%2029.2992%2037.4854%2029.728%2037.9711C30.1534%2038.4569%2030.1065%2039.1972%2029.6208%2039.626L21.5138%2046.7381C21.2927%2046.9324%2021.0146%2047.0295%2020.7399%2047.0295Z'%20fill='%230053E5'/%3e%3cpath%20d='M48.3208%2048.5336H41.2155C40.5689%2048.5336%2040.043%2048.0077%2040.043%2047.3611C40.043%2046.7146%2040.5689%2046.1886%2041.2155%2046.1886H47.1483V40.5338C47.1483%2039.8873%2047.6743%2039.3613%2048.3208%2039.3613C48.9674%2039.3613%2049.4933%2039.8873%2049.4933%2040.5338V47.3611C49.4933%2048.0077%2048.9674%2048.5336%2048.3208%2048.5336Z'%20fill='%230053E5'/%3e%3cpath%20d='M46.7565%2047.0295C46.4818%2047.0295%2046.2071%2046.9324%2045.9827%2046.7381L37.8757%2039.626C37.3899%2039.1972%2037.3397%2038.4569%2037.7685%2037.9711C38.1973%2037.4854%2038.9376%2037.4351%2039.4234%2037.8639L47.5304%2044.976C48.0161%2045.4048%2048.0664%2046.1451%2047.6376%2046.6309C47.4064%2046.8955%2047.0815%2047.0295%2046.7565%2047.0295Z'%20fill='%230053E5'/%3e%3c/svg%3e"; 1351//#endregion 1352//#region client/images/svg/truffle/ai-image-zoom-out-gif.gif 1353var ai_image_zoom_out_gif_default = "/client/images/ai-image-zoom-out-gif.ep7Zjn1N.gif"; 1354//#endregion 1355//#region client/images/svg/truffle/ai-image-pan-left.svg 1356var ai_image_pan_left_default = "data:image/svg+xml,%3csvg%20width='67'%20height='67'%20viewBox='0%200%2067%2067'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3crect%20width='67'%20height='67'%20fill='%23FAFAFA'/%3e%3cg%20opacity='0.4'%3e%3cpath%20d='M40.5943%2016.6495H18.1996C16.6547%2016.6495%2015.4023%2017.9019%2015.4023%2019.4468V39.0409C15.4023%2040.5858%2016.6547%2041.8382%2018.1996%2041.8382H40.5943C42.1392%2041.8382%2043.3916%2040.5858%2043.3916%2039.0409V19.4468C43.3916%2017.9019%2042.1392%2016.6495%2040.5943%2016.6495Z'%20fill='%237F8CED'/%3e%3cpath%20d='M45.0938%2025.0446L54.1756%2019.6444C54.3833%2019.5171%2054.6212%2019.4468%2054.8892%2019.4468C55.6597%2019.4468%2056.2894%2020.0766%2056.2894%2020.8471V37.6406C56.2894%2038.4111%2055.6597%2039.0409%2054.8892%2039.0409C54.6212%2039.0409%2054.3833%2038.9739%2054.1756%2038.8433L45.0938%2033.4431'%20fill='%237F8CED'/%3e%3c/g%3e%3cpath%20d='M32.3099%2052.5448C23.6669%2052.5448%207.32227%2051.178%207.32227%2046.0089C7.32227%2044.3909%208.80297%2043.0844%2011.8515%2042.0124C12.4612%2041.798%2013.1312%2042.1196%2013.3456%2042.7293C13.56%2043.339%2013.2384%2044.009%2012.6287%2044.2234C10.1664%2045.0877%209.66392%2045.8515%209.66392%2046.0089C9.66392%2046.2803%2010.6924%2047.5265%2015.7241%2048.6588C20.1394%2049.6537%2026.0287%2050.1998%2032.3066%2050.1998C32.9531%2050.1998%2033.4791%2050.7257%2033.4791%2051.3723C33.4791%2052.0188%2032.9531%2052.5448%2032.3066%2052.5448H32.3099Z'%20fill='%230053E5'/%3e%3cpath%20d='M40.3964%2052.2265C39.7934%2052.2265%2039.2775%2051.7608%2039.2306%2051.1478C39.177%2050.5012%2039.6594%2049.9351%2040.3026%2049.8848C51.3442%2048.987%2054.9522%2046.6956%2054.9522%2046.0055C54.9522%2045.6906%2053.5519%2044.1697%2047.083%2042.9872C46.4465%2042.8699%2046.0244%2042.2602%2046.1417%2041.6237C46.2589%2040.9872%2046.8686%2040.5685%2047.5051%2040.6824C54.0041%2041.8683%2057.3005%2043.6605%2057.3005%2046.0055C57.3005%2050.384%2045.5487%2051.8111%2040.4969%2052.2231C40.4634%2052.2231%2040.4333%2052.2265%2040.3998%2052.2265H40.3964Z'%20fill='%230053E5'/%3e%3cpath%20d='M30.2825%2056.1159C29.9174%2056.
13561159%2029.5589%2055.9484%2029.3311%2055.6301C28.9526%2055.1042%2029.0698%2054.3739%2029.5958%2053.992L32.9659%2051.5565L28.9559%2048.7626C28.4266%2048.3908%2028.296%2047.6605%2028.6645%2047.1312C29.0363%2046.5985%2029.7666%2046.4712%2030.2959%2046.8397L35.6593%2050.5783C35.9708%2050.7961%2036.1584%2051.1512%2036.1618%2051.5297C36.1651%2051.9083%2035.9842%2052.2667%2035.676%2052.4912L30.9659%2055.8948C30.7582%2056.0455%2030.517%2056.1159%2030.2792%2056.1159H30.2825Z'%20fill='%230053E5'/%3e%3c/svg%3e"; 1357//#endregion 1358//#region client/images/svg/truffle/ai-image-pan-left-gif.gif 1359var ai_image_pan_left_gif_default = "/client/images/ai-image-pan-left-gif.BNDi1pk0.gif"; 1360//#endregion 1361//#region client/images/svg/truffle/ai-image-pan-right.svg 1362var ai_image_pan_right_default = "data:image/svg+xml,%3csvg%20width='67'%20height='67'%20viewBox='0%200%2067%2067'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3crect%20width='67'%20height='67'%20fill='%23FAFAFA'/%3e%3cg%20opacity='0.4'%3e%3cpath%20d='M41.0611%2016.6495H18.6664C17.1215%2016.6495%2015.8691%2017.9019%2015.8691%2019.4468V39.0409C15.8691%2040.5858%2017.1215%2041.8382%2018.6664%2041.8382H41.0611C42.606%2041.8382%2043.8584%2040.5858%2043.8584%2039.0409V19.4468C43.8584%2017.9019%2042.606%2016.6495%2041.0611%2016.6495Z'%20fill='%237F8CED'/%3e%3cpath%20d='M45.5605%2025.0446L54.6424%2019.6444C54.8501%2019.5171%2055.0879%2019.4468%2055.3559%2019.4468C56.1264%2019.4468%2056.7562%2020.0766%2056.7562%2020.8471V37.6406C56.7562%2038.4111%2056.1264%2039.0409%2055.3559%2039.0409C55.0879%2039.0409%2054.8501%2038.9739%2054.6424%2038.8433L45.5605%2033.4431'%20fill='%237F8CED'/%3e%3c/g%3e%3cpath%20d='M34.7065%2052.2265H32.472C23.829%2052.2265%207.48438%2050.8564%207.48438%2045.6706C7.48438%2043.9922%209.07562%2042.6455%2012.3519%2041.5501C12.965%2041.3457%2013.6316%2041.6774%2013.836%2042.2904C14.0403%2042.9035%2013.7087%2043.5701%2013.0956%2043.7745C10.3821%2044.6823%209.82937%2045.5031%209.82937%2045.6706C9.82937%2045.9419%2010.8578%2047.1948%2015.8895%2048.3338C2
13620.3048%2049.3321%2026.1941%2049.8815%2032.472%2049.8815H34.7065C35.353%2049.8815%2035.879%2050.4075%2035.879%2051.054C35.879%2051.7006%2035.353%2052.2265%2034.7065%2052.2265Z'%20fill='%230053E5'/%3e%3cpath%20d='M43.8552%2051.5732C43.2723%2051.5732%2042.7664%2051.1378%2042.6927%2050.5448C42.6123%2049.9016%2043.0713%2049.3153%2043.7145%2049.2383C52.4144%2048.1663%2055.1179%2046.2501%2055.1179%2045.6739C55.1179%2045.3623%2053.7444%2043.8548%2047.4062%2042.6723C46.7697%2042.555%2046.3509%2041.942%2046.4682%2041.3055C46.5854%2040.669%2047.1985%2040.2469%2047.835%2040.3675C54.2234%2041.5601%2057.4629%2043.3423%2057.4629%2045.6739C57.4629%2049.1746%2050.1431%2050.8094%2044.0026%2051.5665C43.9557%2051.5732%2043.9054%2051.5766%2043.8585%2051.5766L43.8552%2051.5732Z'%20fill='%230053E5'/%3e%3cpath%20d='M45.5457%2054.9098C45.3313%2054.9098%2045.1169%2054.8529%2044.9226%2054.7323L39.9177%2051.5967C39.5894%2051.3923%2039.385%2051.0372%2039.3683%2050.652C39.3515%2050.2667%2039.5291%2049.8949%2039.8373%2049.6637L44.5708%2046.1295C45.0901%2045.7409%2045.8237%2045.8481%2046.2123%2046.3673C46.6009%2046.8866%2046.4937%2047.6202%2045.9745%2048.0088L42.6111%2050.518L46.1654%2052.7457C46.7148%2053.0908%2046.879%2053.8144%2046.5373%2054.3604C46.3162%2054.7155%2045.9343%2054.9098%2045.5423%2054.9098H45.5457Z'%20fill='%230053E5'/%3e%3c/svg%3e"; 1363//#endregion 1364//#region client/images/svg/truffle/ai-image-pan-right-gif.gif 1365var ai_image_pan_right_gif_default = "/client/images/ai-image-pan-right-gif.qw5JTPwt.gif"; 1366//#endregion 1367//#region client/images/svg/truffle/ai-image-tilt-up.svg 1368var ai_image_tilt_up_default = "data:image/svg+xml,%3csvg%20width='67'%20height='67'%20viewBox='0%200%2067%2067'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cg%20clip-path='url(%23clip0_23730_118989)'%3e%3crect%20width='67'%20height='67'%20fill='%23FAFAFA'/%3e%3cg%20opacity='0.4'%3e%3cpath%20d='M32.5143%2020.6696H10.1195C8.57464%2020.6696%207.32227%2021.9219%207.32227%2023.4668V43.061C7.32227%2044.6058%208.57464%2045.8582%2010.1195%2045.8582H32.5143C34.0591%2045.8582%2035.3115%2044.6058%2035.3115%2043.061V23.4668C35.3115%2021.9219%2034.0591%2020.6696%2032.5143%2020.6696Z'%20fill='%237F8CED'/%3e%3cpath%20d='M36.9766%2029.0646L46.0584%2023.6644C46.2661%2023.5371%2046.504%2023.4668%2046.772%2023.4668C47.5425%2023.4668%2048.1723%2024.0966%2048.1723%2024.8671V41.6606C48.1723%2042.4311%2047.5425%2043.0609%2046.772%2043.0609C46.504%2043.0609%2046.2661%2042.9939%2046.0584%2042.8633L36.9766%2037.4631'%20fill='%237F8CED'/%3e%3c/g%3e%3cpath%20d='M51.4632%2024.2875C51.0612%2024.2875%2050.6659%2024.0798%2050.4482%2023.7046L47.4734%2018.6025C47.2791%2018.2675%2047.2623%2017.8588%2047.4265%2017.5104C47.594%2017.162%2047.9189%2016.9141%2048.3008%2016.8538L54.1365%2015.9259C54.773%2015.822%2055.376%2016.2609%2055.4799%2016.9007C55.5804%2017.5406%2055.1449%2018.1402%2054.505%2018.2441L50.3611%2018.904L52.4716%2022.5287C52.7965%2023.0882%2052.6089%2023.8051%2052.0495%2024.1334C51.8652%2024.2406%2051.6609%2024.2942%2051.4599%2024.2942L51.4632%2024.2875Z'%20fill='%230053E5'/%3e%3cpath%20d='M51.4975%2048.2199C51.0653%2048.2199%2050.6533%2047.982%2050.4489%2047.57C50.1608%2046.9904%2050.3953%2046.2869%2050.9749%2045.9988C55.829%2043.5768%2058.844%2038.7059%2058.844%2033.2856C58.844%2029.9255%2057.6481%2026.666%2055.4806%2024.1099C54.2043%2022.6024%2052.6599%2021.3998%2050.8978%2020.5355C50.3183%2020.2507%2050.0771%2019.5472%2050.3618%2018.9677C50.6466%2018.3881%2051.3501%2018.1469%2051.9296%2018.4317C53.9865%2019.44%2055.7821%2020.8437%2057.2695%2022.5957C59.7988%2025.5772%2061.189%2029.3728%2061.189%2033.2889C61.189%2039.6037%2057.6749%2045.2786%2052.0201%2048.0993C51.8526%2048.183%2051.6717%2048.2232%2051.4975%2048.2232V48.2199Z'%20fill='%230053E5'/%3e%3c/g%3e%3cdefs%3e%3cclipPath%20id='clip0_23730_118989'%3e%3crect%20width='67'%20height='67'%20fill='white'/%3e%3c/clipPath%3e%3c/defs%3e%3c/svg%3e"; 1369//#endregion 1370//#region client/images/svg/truffle/ai-image-tilt-up-gif.gif 1371var ai_image_tilt_up_gif_default = "/client/images/ai-image-tilt-up-gif.r4G1_SQI.gif"; 1372//#endregion 1373//#region client/images/svg/truffle/ai-image-tilt-down.svg 1374var ai_image_tilt_down_default = "data:image/svg+xml,%3csvg%20width='67'%20height='67'%20viewBox='0%200%2067%2067'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3crect%20width='67'%20height='67'%20fill='%23FAFAFA'/%3e%3cg%20opacity='0.4'%3e%3cpath%20d='M32.5143%2020.6696H10.1195C8.57464%202
13740.6696%207.32227%2021.9219%207.32227%2023.4668V43.061C7.32227%2044.6058%208.57464%2045.8582%2010.1195%2045.8582H32.5143C34.0591%2045.8582%2035.3115%2044.6058%2035.3115%2043.061V23.4668C35.3115%2021.9219%2034.0591%2020.6696%2032.5143%2020.6696Z'%20fill='%237F8CED'/%3e%3cpath%20d='M37.0137%2029.0646L46.0955%2023.6644C46.3032%2023.5371%2046.5411%2023.4668%2046.8091%2023.4668C47.5796%2023.4668%2048.2094%2024.0966%2048.2094%2024.8671V41.6606C48.2094%2042.4311%2047.5796%2043.0609%2046.8091%2043.0609C46.5411%2043.0609%2046.3032%2042.9939%2046.0955%2042.8633L37.0137%2037.4631'%20fill='%237F8CED'/%3e%3c/g%3e%3cpath%20d='M54.7424%2050.3002C54.7022%2050.3002%2054.6586%2050.3002%2054.6184%2050.2935L48.7459%2049.6738C48.3606%2049.6336%2048.0223%2049.4058%2047.838%2049.0641C47.6538%2048.7224%2047.6504%2048.3137%2047.828%2047.972L50.5281%2042.7158C50.8229%2042.1396%2051.5331%2041.9118%2052.1059%2042.21C52.6821%2042.5048%2052.9099%2043.2116%2052.6118%2043.7878L50.6922%2047.5197L54.863%2047.9586C55.5062%2048.0256%2055.9752%2048.6018%2055.9048%2049.2483C55.8412%2049.8513%2055.332%2050.2969%2054.739%2050.2969L54.7424%2050.3002Z'%20fill='%230053E5'/%3e%3cpath%20d='M51.7006%2048.2199C51.2685%2048.2199%2050.8564%2047.982%2050.6521%2047.57C50.364%2046.9904%2050.5985%2046.2869%2051.178%2045.9988C56.0322%2043.5768%2059.0472%2038.7059%2059.0472%2033.2856C59.0472%2029.9255%2057.8512%2026.666%2055.6838%2024.1099C54.4074%2022.6024%2052.8631%2021.3998%2051.101%2020.5355C50.5214%2020.2507%2050.2802%2019.5472%2050.565%2018.9677C50.8497%2018.3881%2051.5532%2018.1469%2052.1328%2018.4317C54.1897%2019.44%2055.9853%2020.8437%2057.4727%2022.5957C60.0019%2025.5772%2061.3922%2029.3728%2061.3922%2033.2889C61.3922%2039.6037%2057.878%2045.2786%2052.2232%2048.0993C52.0557%2048.183%2051.8748%2048.2232%2051.7006%2048.2232V48.2199Z'%20fill='%230053E5'/%3e%3c/svg%3e"; 1375//#endregion 1376//#region client/images/svg/truffle/ai-image-tilt-down-gif.gif 1377var ai_image_tilt_down_gif_default = "/client/images/ai-image-tilt-down-gif.C-bSto3I.gif"; 1378//#endregion 1379//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/AiMediaGenerationFields.tsx 1380var getAiGeneratedAssetAspectRatioLabel = (aspectRatio) => { 1381 switch (aspectRatio) { 1382 case GqlClientAiGeneratedAssetAspectRatio.RATIO_16_9: return "16:9"; 1383 case GqlClientAiGeneratedAssetAspectRatio.RATIO_9_16: return "9:16"; 1384 case GqlClientAiGeneratedAssetAspectRatio.RATIO_1_1: return "1:1"; 1385 case GqlClientAiGeneratedAssetAspectRatio.RATIO_3_4: return "3:4"; 1386 case GqlClientAiGeneratedAssetAspectRatio.RATIO_4_3: return "4:3"; 1387 default: return ""; 1388 } 1389}; 1390var aspectRatioOptions = [ 1391 { 1392 value: GqlClientAiGeneratedAssetAspectRatio.RATIO_16_9, 1393 numericValue: 16 / 9, 1394 imageOnly: false, 1395 label: getAiGeneratedAssetAspectRatioLabel(GqlClientAiGeneratedAssetAspectRatio.RATIO_16_9) 1396 }, 1397 { 1398 value: GqlClientAiGeneratedAssetAspectRatio.RATIO_9_16, 1399 numericValue: 9 / 16, 1400 imageOnly: false, 1401 label: getAiGeneratedAssetAspectRatioLabel(GqlClientAiGeneratedAssetAspectRatio.RATIO_9_16) 1402 }, 1403 { 1404 value: GqlClientAiGeneratedAssetAspectRatio.RATIO_1_1, 1405 numericValue: 1, 1406 imageOnly: true, 1407 label: getAiGeneratedAssetAspectRatioLabel(GqlClientAiGeneratedAssetAspectRatio.RATIO_1_1) 1408 }, 1409 { 1410 value: GqlClientAiGeneratedAssetAspectRatio.RATIO_3_4, 1411 numericValue: 3 / 4, 1412 imageOnly: true, 1413 label: getAiGeneratedAssetAspectRatioLabel(GqlClientAiGeneratedAssetAspectRatio.RATIO_3_4) 1414 }, 1415 { 1416 value: GqlClientAiGeneratedAssetAspectRatio.RATIO_4_3, 1417 numericValue: 4 / 3, 1418 imageOnly: true, 1419 label: getAiGeneratedAssetAspectRatioLabel(GqlClientAiGeneratedAssetAspectRatio.RATIO_4_3) 1420 } 1421]; 1422var getAspectRatioNumericValue = (aspectRatioValue) => aspectRatioOptions.find((option) => option.value === aspectRatioValue).numericValue ?? 1; 1423var isPortraitLayout = (aspectRatioValue) => aspectRatioValue === GqlClientAiGeneratedAssetAspectRatio.RATIO_9_16 || aspectRatioValue === GqlClientAiGeneratedAssetAspectRatio.RATIO_3_4; 1424var createTransparentSvgDataUri = (width, height) => `data:image/svg+xml,${encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}"><rect width="${width}" height="${height}" fill="transparent"/></svg>`)}`; 1425var aspectRatioPlaceholders = { 1426 [GqlClientAiGeneratedAssetAspectRatio.RATIO_16_9]: createTransparentSvgDataUri(16, 9), 1427 [GqlClientAiGeneratedAssetAspectRatio.RATIO_9_16]: createTransparentSvgDataUri(9, 16), 1428 [GqlClientAiGeneratedAssetAspectRatio.RATIO_1_1]: createTransparentSvgDataUri(1, 1), 1429 [GqlClientAiGeneratedAssetAspectRatio.RATIO_3_4]: createTransparentSvgDataUri(3, 4), 1430 [GqlClientAiGeneratedAssetAspectRatio.RATIO_4_3]: createTransparentSvgDataUri(4, 3) 1431}; 1432var getAspectRatioPlaceholder = (aspectRatio) => aspectRatioPlaceholders[aspectRatio] ?? aspectRatioPlaceholders[GqlClientAiGeneratedAssetAspectRatio.RATIO_16_9]; 1433var cameraAngles = [ 1434 { 1435 title: "Eye level", 1436 icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { 1437 src: eye_level_default, 1438 alt: "Eye level", 1439 style: { 1440 width: 16, 1441 height: 16 1442 } 1443 }), 1444 value: GqlClientAiCameraAngle.EYE_LEVEL 1445 }, 1446 { 1447 title: "Close up", 1448 icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { 1449 src: close_up_default, 1450 alt: "Close up", 1451 style: { 1452 width: 16, 1453 height: 16 1454 } 1455 }), 1456 value: GqlClientAiCameraAngle.CLOSE_UP 1457 }, 1458 { 1459 title: "Wide shot", 1460 icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { 1461 src: wide_shot_default, 1462 alt: "Wide shot", 1463 style: { 1464 width: 16, 1465 height: 16 1466 } 1467 }), 1468 value: GqlClientAiCameraAngle.WIDE_SHOT 1469 }, 1470 { 1471 title: "High angle", 1472 icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { 1473 src: high_angle_default, 1474 alt: "High angle", 1475 style: { 1476 width: 16, 1477 height: 16 1478 } 1479 }), 1480 value: GqlClientAiCameraAngle.HIGH_ANGLE 1481 }, 1482 { 1483 title: "Low angle", 1484 icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { 1485 src: low_angle_default, 1486 alt: "Low angle", 1487 style: { 1488 width: 16, 1489 height: 16 1490 } 1491 }), 1492 value: GqlClientAiCameraAngle.LOW_ANGLE 1493 }, 1494 { 1495 title: "Bird's eye view", 1496 icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { 1497 src: birds_eye_view_default, 1498 alt: "Bird's eye view", 1499 style: { 1500 width: 16, 1501 height: 16 1502 } 1503 }), 1504 value: GqlClientAiCameraAngle.BIRDS_EYE_VIEW 1505 } 1506]; 1507var imageStyles = [ 1508 { 1509 type: GqlClientAiImageStyle.REAL_LIFE, 1510 name: "Real life", 1511 img: real_life_default, 1512 alt: "Real life" 1513 }, 1514 { 1515 type: GqlClientAiImageStyle.OBJECT, 1516 name: "Object", 1517 img: object_default, 1518 alt: "Object" 1519 }, 1520 { 1521 type: GqlClientAiImageStyle.DRAWING, 1522 name: "Drawing", 1523 img: drawing_default, 1524 alt: "Drawing" 1525 }, 1526 { 1527 type: GqlClientAiImageStyle.THREE_D, 1528 name: "3D", 1529 img: _3d_default, 1530 alt: "3D" 1531 }, 1532 { 1533 type: GqlClientAiImageStyle.ABSTRACT, 1534 name: "Abstract", 1535 img: abstract_default, 1536 alt: "Abstract" 1537 }, 1538 { 1539 type: GqlClientAiImageStyle.INTERFACE, 1540 name: "Interface", 1541 img: interface_default, 1542 alt: "Interface" 1543 } 1544]; 1545var motionStyles = [ 1546 { 1547 type: GqlClientAiCameraMotion.STATIC, 1548 name: "Static Camera", 1549 img: ai_image_static_camera_default, 1550 gif: ai_image_static_gif_default, 1551 alt: "Static Camera" 1552 }, 1553 { 1554 type: GqlClientAiCameraMotion.ZOOM_IN, 1555 name: "Zoom In", 1556 img: ai_image_zoom_in_default, 1557 gif: ai_image_zoom_in_gif_default, 1558 alt: "Zoom In" 1559 }, 1560 { 1561 type: GqlClientAiCameraMotion.ZOOM_OUT, 1562 name: "Zoom Out", 1563 img: ai_image_zoom_out_default, 1564 gif: ai_image_zoom_out_gif_default, 1565 alt: "Zoom Out" 1566 }, 1567 { 1568 type: GqlClientAiCameraMotion.PAN_LEFT, 1569 name: "Pan Left", 1570 img: ai_image_pan_left_default, 1571 gif: ai_image_pan_left_gif_default, 1572 alt: "Pan Left" 1573 }, 1574 { 1575 type: GqlClientAiCameraMotion.PAN_RIGHT, 1576 name: "Pan Right", 1577 img: ai_image_pan_right_default, 1578 gif: ai_image_pan_right_gif_default, 1579 alt: "Pan Right" 1580 }, 1581 { 1582 type: GqlClientAiCameraMotion.TILT_UP, 1583 name: "Tilt Up", 1584 img: ai_image_tilt_up_default, 1585 gif: ai_image_tilt_up_gif_default, 1586 alt: "Tilt Up" 1587 }, 1588 { 1589 type: GqlClientAiCameraMotion.TILT_DOWN, 1590 name: "Tilt Down", 1591 img: ai_image_tilt_down_default, 1592 gif: ai_image_tilt_down_gif_default, 1593 alt: "Tilt Down" 1594 } 1595]; 1596//#endregion 1597//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/PlaceHolderTools/utils/utils.ts 1598var PlaceholderToolbarOffset = [{ 1599 name: "offset", 1600 options: { offset: [0, 8] } 1601}]; 1602function getAspectRatioForAssetGeneration(placeholderPosition) { 1603 return placeholderPosition.width === placeholderPosition.height || placeholderPosition.width > placeholderPosition.height && placeholderPosition.width / placeholderPosition.height <= 1.15 || placeholderPosition.height > placeholderPosition.width && placeholderPosition.height / placeholderPosition.width <= 1.15 ? GqlClientAiAspectRatio.SQUARE : placeholderPosition.width > placeholderPosition.height ? GqlClientAiAspectRatio.LANDSCAPE : GqlClientAiAspectRatio.PORTRAIT; 1604} 1605function getBestFitAspectRatio(assetDimensions, isVideoMode) { 1606 const placeholderAspectRatio = assetDimensions.width / assetDimensions.height; 1607 const availableOptions = aspectRatioOptions.filter((option) => !isVideoMode || !option.imageOnly); 1608 let bestMatch = availableOptions[0].value; 1609 let smallestDifference = Infinity; 1610 for (const option of availableOptions) { 1611 const difference = Math.abs(placeholderAspectRatio - option.numericValue); 1612 if (difference < smallestDifference) { 1613 smallestDifference = difference; 1614 bestMatch = option.value; 1615 } 1616 } 1617 return bestMatch; 1618} 1619var getAnimationCueDisabledTooltipForPlaceholderTimingTool = (editorTtsFullEnablement, isNonElevenLabsVoice, additionalLanguages, narrationPlaceholder, scene, placeholderType) => { 1620 const isNarrationUsingRules = narrationPlaceholder?.placeholderContent.useRules; 1621 const isNarrationPersonalized = !isNarrationUsingRules && isPlaceholderContentNoRulesWithPersonalization(narrationPlaceholder?.placeholderContent); 1622 const narrationPlaceholderShowText = (narrationPlaceholder?.placeholderContent).noRules.show[ORIGIN_LANGUAGE].text; 1623 return getAnimationCueDisabledTooltip(editorTtsFullEnablement, isNonElevenLabsVoice, additionalLanguages, scene, isNarrationUsingRules, isNarrationPersonalized, !isNarrationUsingRules && !isNarrationPersonalized && !isPlaceholderValueNotEmpty(narrationPlaceholderShowText), placeholderType); 1624}; 1625var getAnimationCueDisabledTooltipForNarration = (editorTtsFullEnablement, isNonElevenLabsVoice, additionalLanguages, narrationPlaceholder, scene, narrationContents, isFallback) => { 1626 const isNarrationUsingRules = narrationPlaceholder?.placeholderContent.useRules; 1627 const isNarrationPersonalized = !isNarrationUsingRules && (isFallback || narrationContents.ops.some(import_dist$1.isMentionOperation)); 1628 return getAnimationCueDisabledTooltip(editorTtsFullEnablement, isNonElevenLabsVoice, additionalLanguages, scene, isNarrationUsingRules, isNarrationPersonalized, !isNarrationUsingRules && !isNarrationPersonalized && isContentEmpty(narrationContents)); 1629}; 1630var getAnimationCueDisabledTooltip = (editorTtsFullEnablement, isNonElevenLabsVoice, additionalLanguages, scene, isNarrationUsingRules, isNarrationPersonalized, isNarrationContentEmpty, placeholderType) => { 1631 if (!editorTtsFullEnablement) return placeholderType ? `A ${placeholderType} can't be connected to an animation cue because the video uses a re
1631corded voice.` : "Animation cues aren't currently supported in videos using a recorded voice."; 1632 if (isNonElevenLabsVoice) { 1633 const enhancedVoiceHint = "To enable animation cues, change the video voice to an Enhanced voice."; 1634 return placeholderType ? `A ${placeholderType} can't be connected to an animation cue because the video doesn't use an Enhanced voice. ${enhancedVoiceHint}` : `Animation cues aren't currently supported in videos that don't use an Enhanced voice. ${enhancedVoiceHint}`; 1635 } 1636 if (additionalLanguages.length) return placeholderType ? `A ${placeholderType} can't be connected to an animation cue. Animation cues aren't currently supported in videos with additional languages.` : "Animation cues aren't currently supported in videos with additional languages."; 1637 if (isNarrationUsingRules) return placeholderType ? `A ${placeholderType} can't be connected to an animation cue when 'Message by audience' is used in the narration.` : "Animation cues aren't currently supported when the narration includes 'Message by audience'."; 1638 if (isNarrationPersonalized) return placeholderType ? `A ${placeholderType} can't be connected to an animation cue when the narration includes personalization.` : "Animation cues aren't currently supported when the narration includes personalization."; 1639 if (!(scene.ccWireframe.category === GqlClientCcWireframeCategory.CUSTOM)) return "Animation cues can only be added in custom scenes."; 1640 if (!placeholderType && !scene.placeholders.some((placeholder) => placeholder.parentType === GqlClientEditorFlexiblePlaceholderParentType.CANVAS)) return "An animation cue can only be added after at least one placeholder is added to the scene."; 1641 if (isNarrationContentEmpty) return "Animation cues require narration text. Add narration to enable animation cues."; 1642 return ""; 1643}; 1644//#endregion 1645//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/AiMediaGenerationDialogUtils.ts 1646var ASPECT_RATIO_TOLERANCE = .1; 1647/** 1648* Loads an image from `url` and resolves its closest supported video aspect ratio. 1649* Returns `null` when the image cannot be loaded or has no measurable dimensions, 1650* indicating the caller should fall back to a default (16:9). 1651* Returns a cleanup function that cancels the in-flight load. 1652*/ 1653var loadImageAspectRatio = (url, onResult) => { 1654 const img = new Image(); 1655 img.onload = () => { 1656 if (!img.naturalWidth || !img.naturalHeight) { 1657 onResult(null); 1658 return; 1659 } 1660 const naturalRatio = img.naturalWidth / img.naturalHeight; 1661 if (Math.abs(naturalRatio - 9 / 16) <= ASPECT_RATIO_TOLERANCE) onResult(GqlClientAiGeneratedAssetAspectRatio.RATIO_9_16); 1662 else if (Math.abs(naturalRatio - 16 / 9) <= ASPECT_RATIO_TOLERANCE) onResult(GqlClientAiGeneratedAssetAspectRatio.RATIO_16_9); 1663 else onResult(null); 1664 }; 1665 img.onerror = () => onResult(null); 1666 img.src = url; 1667 return () => { 1668 img.onload = null; 1669 img.onerror = null; 1670 }; 1671}; 1672var getBackButtonText = (videoStep) => { 1673 switch (videoStep) { 1674 case AiVideoGenerationStep.CONFIGURE_VIDEO: return "Back to prompt and first frame"; 1675 case AiVideoGenerationStep.GENERATE_VIDEO: return "Back to add motion prompt"; 1676 case AiVideoGenerationStep.GENERATE_IMAGE: 1677 default: return ""; 1678 } 1679}; 1680var getCancelButtonTrackingId = (mode, videoStep) => { 1681 if (mode === AiMediaGenerationMode.IMAGE) return "tracking-id-ai-image-generator-cancel-btn"; 1682 switch (videoStep) { 1683 case AiVideoGenerationStep.GENERATE_IMAGE: return "tracking-id-ai-video-generator-first-frame-cancel-btn"; 1684 case AiVideoGenerationStep.CONFIGURE_VIDEO: return "tracking-id-ai-video-generator-define-motion-cancel-btn"; 1685 case AiVideoGenerationStep.GENERATE_VIDEO: return "tracking-id-ai-video-generator-result-preview-revise-video-motion-btn"; 1686 } 1687}; 1688var getConfirmationDialogTitle = (mode, loading) => { 1689 if (loading && mode === AiMediaGenerationMode.IMAGE) return "Leave AI Image Generator?"; 1690 return "Leave without saving?"; 1691}; 1692var getConfirmationDialogContent = (mode, loading) => { 1693 if (loading && mode === AiMediaGenerationMode.IMAGE) return "Your images are currently being generated and credits have already been used.\n\nLeaving now means you won't be able to view the results."; 1694 return "Any unused media will be lost.\nThis action can't be und
1694one."; 1695}; 1696var getConfirmationDialogPrimaryButtonText = (mode, loading) => { 1697 if (loading && mode === AiMediaGenerationMode.IMAGE) return "Stay and view results"; 1698 return "Leave without saving"; 1699}; 1700var getConfirmationDialogSecondaryButtonText = (mode, loading) => { 1701 if (loading && mode === AiMediaGenerationMode.IMAGE) return "Leave anyway"; 1702 return "Continue editing"; 1703}; 1704var getConfirmationDialogButtonsTrackingId = (mode, loading, videoStep, state) => { 1705 if (mode === AiMediaGenerationMode.IMAGE) return loading ? `tracking-id-ai-image-generator-close-while-generating-confirmation-${state}` : `tracking-id-ai-image-generator-close-post-generation-confirmation-${state}`; 1706 switch (videoStep) { 1707 case AiVideoGenerationStep.GENERATE_IMAGE: return `tracking-id-ai-video-generator-close-video-first-frame-confirmation-${state}`; 1708 case AiVideoGenerationStep.CONFIGURE_VIDEO: return `tracking-id-ai-video-generator-close-video-define-motion-confirmation-${state}`; 1709 case AiVideoGenerationStep.GENERATE_VIDEO: return `tracking-id-ai-video-generator-close-dialog-confirmation-${state}`; 1710 } 1711}; 1712var getClosingDialogButtonTrackingId = (isVideoPreviewStep, generatedVideoUrl) => { 1713 if (isVideoPreviewStep && !generatedVideoUrl) return "tracking-id-ai-video-generator-result-preview-x-btn"; 1714}; 1715var getGenerateButtonText = (mode, hasData) => { 1716 const isImage = mode === AiMediaGenerationMode.IMAGE; 1717 if (hasData) return isImage ? "Generate images again" : "Generate first frame again"; 1718 return isImage ? "Generate images" : "Generate first frame"; 1719}; 1720var getGenerateButtonTrackingId = (mode, hasData) => { 1721 const isImage = mode === AiMediaGenerationMode.IMAGE; 1722 if (hasData) return isImage ? "tracking-id-ai-image-generator-regenerate-btn" : "tracking-id-ai-video-generator-regenerate-first-frame-btn"; 1723 return isImage ? "tracking-id-ai-image-generator-generate-images-btn" : "tracking-id-ai-video-generator-generate-first-frame-btn"; 1724}; 1725var getVideoTabTooltip = (disabledTabConfig, isAiVideoBlocked) => { 1726 if (disabledTabConfig?.disabledTab === AiMediaGenerationMode.VIDEO) return disabledTabConfig.tooltip; 1727 if (isAiVideoBlocked) return "AI Video Generator is disabled. To enable this feature, contact your account owner."; 1728 return ""; 1729}; 1730var getContactSalesTrackingId = (isConvertToVideoFlow, creditsBalance) => { 1731 if (isConvertToVideoFlow) return creditsBalance > 0 ? "tracking-id-convert-to-video-need-more-credits-contact-sales-btn" : "tracking-id-convert-to-video-out-of-credits-contact-sales-btn"; 1732 return creditsBalance > 0 ? "tracking-id-ai-media-generator-need-more-credits-dialog-contact-sales-btn" : "tracking-id-ai-media-generator-no-credits-dialog-contact-sales-btn"; 1733}; 1734var getSelectedAssetUrl = (assets, selectedAssetId) => { 1735 if (assets && assets.length > 0) return assets.find((asset) => asset.id === selectedAssetId)?.mediaUrl ?? assets[0].mediaUrl; 1736 return ""; 1737}; 1738//#endregion 1739//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/aiMediaGenerationStateUtils.ts 1740var ASPECT_RATIO_DIMENSIONS = { 1741 [GqlClientAiGeneratedAssetAspectRatio.RATIO_16_9]: { 1742 minWidth: 260, 1743 maxWidth: null, 1744 maxHeight: null, 1745 breakpointMaxWidth: 320, 1746 breakpointMaxHeight: null, 1747 editLoadingHeight: null 1748 }, 1749 [GqlClientAiGeneratedAssetAspectRatio.RATIO_4_3]: { 1750 minWidth: 189, 1751 maxWidth: 230, 1752 maxHeight: null, 1753 breakpointMaxWidth: 320, 1754 breakpointMaxHeight: null, 1755 editLoadingHeight: 292 1756 }, 1757 [GqlClientAiGeneratedAssetAspectRatio.RATIO_1_1]: { 1758 minWidth: 142, 1759 maxWidth: 200, 1760 maxHeight: null, 1761 breakpointMaxWidth: 300, 1762 breakpointMaxHeight: null, 1763 editLoadingHeight: 292 1764 }, 1765 [GqlClientAiGeneratedAssetAspectRatio.RATIO_3_4]: { 1766 minWidth: 142, 1767 maxWidth: 160, 1768 maxHeight: null, 1769 breakpointMaxWidth: 200, 1770 breakpointMaxHeight: null, 1771 editLoadingHeight: 362 1772 }, 1773 [GqlClientAiGeneratedAssetAspectRatio.RATIO_9_16]: { 1774 minWidth: 120, 1775 maxWidth: null, 1776 maxHeight: 300, 1777 breakpointMaxWidth: 200, 1778 breakpointMaxHeight: 250, 1779 editLoadingHeight: 288 1780 } 1781}; 1782var LEGACY_ASPECT_RATIO_DIMENSIONS = { 1783 [GqlClientAiGeneratedAssetAspectRatio.RATIO_16_9]: { 1784 minWidth: 260, 1785 maxWidth: null, 1786 maxHeight: null, 1787 breakpointMaxWidth: 320, 1788 breakpointMaxHeight: null, 1789 editLoadingHeight: null 1790 }, 1791 [GqlClientAiGeneratedAssetAspectRatio.RATIO_4_3]: { 1792 minWidth: 260, 1793 maxWidth: null, 1794 maxHeight: null, 1795 breakpointMaxWidth: 320, 1796 breakpointMaxHeight: null, 1797 editLoadingHeight: null 1798 }, 1799 [GqlClientAiGeneratedAssetAspectRatio.RATIO_1_1]: { 1800 minWidth: 255, 1801 maxWidth: null, 1802 maxHeight: 255, 1803 breakpointMaxWidth: null, 1804 breakpointMaxHeight: null, 1805 editLoadingHeight: null 1806 }, 1807 [GqlClientAiGeneratedAssetAspectRatio.RATIO_3_4]: { 1808 minWidth: 120, 1809 maxWidth: null, 1810 maxHeight: 255, 1811 breakpointMaxWidth: 200, 1812 breakpointMaxHeight: null, 1813 editLoadingHeight: null 1814 }, 1815 [GqlClientAiGeneratedAssetAspectRatio.RATIO_9_16]: { 1816 minWidth: 120, 1817 maxWidth: null, 1818 maxHeight: 300, 1819 breakpointMaxWidth: 200, 1820 breakpointMaxHeight: 250, 1821 editLoadingHeight: null 1822 } 1823}; 1824var getThumbnailDimensions = (aspectRatio) => { 1825 const dimensions = isFeatureEnabled(featureFlagConst._EDITOR_GEN_AI_EDIT_AND_CONVERT) ? ASPECT_RATIO_DIMENSIONS[aspectRatio] : LEGACY_ASPECT_RATIO_DIMENSIONS[aspectRatio]; 1826 const aspectRatioValue = getAspectRatioNumericValue(aspectRatio); 1827 return { 1828 ...dimensions, 1829 aspectRatio: aspectRatioValue 1830 }; 1831}; 1832var DEFAULT_CAMERA_MOTION = GqlClientAiCameraMotion.STATIC; 1833var resetVideoState = (setVideoStep, setGeneratedVideoUrl, setGeneratedVideoAsset, initialVideoStep) => { 1834 setVideoStep(initialVideoStep); 1835 setGeneratedVideoUrl(void 0); 1836 setGeneratedVideoAsset(null); 1837}; 1838var restoreTabConfiguration = (targetTabState, setters, isVideoMode, initialVideoStep) => { 1839 setters.setPrompt(targetTabState.prompt); 1840 setters.setStyle(targetTabState.style); 1841 setters.setCameraAngle(targetTabState.cameraAngle); 1842 setters.setData(targetTabState.data); 1843 setters.setGeneratedAspectRatio(targetTabState.generatedAspectRatio); 1844 setters.setSelectedAssetId(targetTabState.selectedAssetId); 1845 setters.setGenerationFailed(targetTabState.generationFailed); 1846 setters.setErrorMessage(targetTabState.errorMessage); 1847 setters.setPreviousBatches(targetTabState.previousBatches); 1848 setters.setCurrentBatchPrompt(targetTabState.currentBatchPrompt); 1849 setters.setIsCurrentBatchEdit(targetTabState.isCurrentBatchEdit); 1850 if (isVideoMode) { 1851 setters.setVideoStep(targetTabState.videoStep ?? initialVideoStep); 1852 setters.setMotionDescription(targetTabState.motionDescription ?? ""); 1853 setters.setCameraMotion(targetTabState.cameraMotion ?? DEFAULT_CAMERA_MOTION); 1854 setters.setSelectedDuration(targetTabState.selectedDuration); 1855 setters.setGeneratedVideoUrl(targetTabState.generatedVideoUrl); 1856 setters.setGeneratedVideoAsset(targetTabState.generatedVideoAsset ?? null); 1857 } 1858}; 1859var copyConfigurationToTargetTab = (setters, isVideoMode, defaultDuration) => { 1860 if (isVideoMode) { 1861 setters.setMotionDescription(""); 1862 setters.setCameraMotion(DEFAULT_CAMERA_MOTION); 1863 setters.setSelectedDuration(defaultDuration); 1864 } 1865 setters.setData(void 0); 1866 setters.setGeneratedAspectRatio(null); 1867 setters.setSelectedAssetId(null); 1868 setters.setGenerationFailed(false); 1869 setters.setErrorMessage(null); 1870 setters.setPreviousBatches([]); 1871 setters.setCurrentBatchPrompt(""); 1872 setters.setIsCurrentBatchEdit(false); 1873}; 1874//#endregion 1875//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/AiMediaGenerationContext.tsx 1876var getShouldConfirmCancel = (videoStep, loading, selectedAssetId, generationFailed, generatedVideoUrl, isConvertToVideoFlow, motionDescription) => { 1877 if (videoStep === AiVideoGenerationStep.GENERATE_IMAGE) return loading || !!selectedAssetId && !generationFailed; 1878 if (videoStep === AiVideoGenerationStep.GENERATE_VIDEO) return !generatedVideoUrl && !generationFailed; 1879 if (videoStep === AiVideoGenerationStep.CONFIGURE_VIDEO && isConvertToVideoFlow) return motionDescription.trim().length > 0; 1880 return videoStep === AiVideoGenerationStep.CONFIGURE_VIDEO; 1881}; 1882var getShouldConfirmCancelForSavedTabState = (tabState) => { 1883 if (!tabState) return false;
1884 return !!tabState.selectedAssetId && !tabState.generationFailed; 1885}; 1886var screenFromModeAndStep = (mode, videoStep) => { 1887 if (mode === AiMediaGenerationMode.IMAGE) return "IMAGE_GENERATE"; 1888 switch (videoStep) { 1889 case AiVideoGenerationStep.GENERATE_IMAGE: return "VIDEO_FIRST_FRAME"; 1890 case AiVideoGenerationStep.CONFIGURE_VIDEO: return "VIDEO_DEFINE_MOTION"; 1891 case AiVideoGenerationStep.GENERATE_VIDEO: return "VIDEO_PREVIEW"; 1892 } 1893}; 1894var AiMediaGenerationContext = (0, import_react.createContext)(null); 1895var useAiMediaGenerationContext = () => { 1896 const ctx = (0, import_react.useContext)(AiMediaGenerationContext); 1897 if (!ctx) throw new Error("useAiMediaGenerationContext must be used within AiMediaGenerationProvider"); 1898 return ctx; 1899}; 1900var AiMediaGenerationProvider = ({ children }) => { 1901 const assetGenerationDialogInfo = useAiGenerationDialogOpen(); 1902 const setAssetGenerationDialogInfo = useSetAiGenerationDialogInfo(); 1903 const { cost: imageGenerationCost } = useCreditsCostForFeature(GqlClientFeatureTypeDefinition.LIMIT_GENERATE_AI_ASSET_IMAGE, 1); 1904 const { balance: creditsBalance } = useNumericFeatureRestriction(GqlClientFeatureTypeDefinition.LIMIT_GENERATE_AI_ASSET_IMAGE); 1905 const { accountFeatureFullData } = useAccountFeatureFullData(); 1906 const isAiImageBlocked = isAiFeatureBlocked(accountFeatureFullData, GqlClientFeatureTypeDefinition.USER_BLOCK_AI_IMAGE_GENERATION); 1907 const isAiVideoBlocked = isAiFeatureBlocked(accountFeatureFullData, GqlClientFeatureTypeDefinition.USER_BLOCK_AI_VIDEO_GENERATION); 1908 const isAiImageEditingBlocked = isAiFeatureBlocked(accountFeatureFullData, GqlClientFeatureTypeDefinition.USER_BLOCK_AI_IMAGE_EDITING); 1909 const isEditWithAiEnabled = isFeatureEnabled(featureFlagConst._EDITOR_GEN_AI_EDIT_AND_CONVERT); 1910 const { isDialogOpen, assetDimensions, onDialogConfirmation, isGenerateFromLibrary, flowTrigger, disabledTabConfig, initialVideoStep, externalImageUrl, sourceImageMediaId } = assetGenerationDialogInfo ?? {}; 1911 const isVideoTabDisabled = disabledTabConfig?.disabledTab === AiMediaGenerationMode.VIDEO; 1912 const isConvertToVideo = !!externalImageUrl; 1913 const flowTriggerAction = isConvertToVideo ? "convert to video" : "generate media"; 1914 const { rootFolder, foldersByParentFolderId, foldersById, mediaByFolderId, assetLibraryMediaByGqlMediaId } = useAssetLibraryMedia(); 1915 const [loading, setLoading] = (0, import_react.useState)(false); 1916 const [prompt, setPrompt] = (0, import_react.useState)(""); 1917 const [style, setStyle] = (0, import_react.useState)(GqlClientAiImageStyle.REAL_LIFE); 1918 const [cameraMotion, setCameraMotion] = (0, import_react.useState)(DEFAULT_CAMERA_MOTION); 1919 const [imageAspectRatio, setImageAspectRatio] = (0, import_react.useState)(GqlClientAiGeneratedAssetAspectRatio.RATIO_16_9); 1920 const [videoAspectRatio, setVideoAspectRatio] = (0, import_react.useState)(GqlClientAiGeneratedAssetAspectRatio.RATIO_16_9); 1921 const [generatedAspectRatio, setGeneratedAspectRatio] = (0, import_react.useState)(null); 1922 const [cameraAngle, setCameraAngle] = (0, import_react.useState)(GqlClientAiCameraAngle.EYE_LEVEL); 1923 const [data, setData] = (0, import_react.useState)(); 1924 const [generationFailed, setGenerationFailed] = (0, import_react.useState)(false); 1925 const [errorMessage, setErrorMessage] = (0, import_react.useState)(null); 1926 const [assetForActionId, setAssetForActionId] = (0, import_react.useState)(null); 1927 const [selectedAssetId, setSelectedAssetId] = (0, import_react.useState)(null); 1928 const [isPromptDialogOpen, togglePromptDialog] = useToggle(false); 1929 const promptGeneratorChat = usePromptGeneratorChat(prompt, ORIGIN_LANGUAGE); 1930 const [previewAssetIndex, setPreviewAssetIndex] = (0, import_react.useState)(-1); 1931 const [selectFolderDialogOpen, setSelectFolderDialogOpen] = (0, import_react.useState)(false); 1932 const pendo = PendoService.getInstance(); 1933 const usesGeneratedPrompt = prompt === (promptGeneratorChat.proposedPrompt ?? ""); 1934 const [isLeaveConfirmationOpen, setLeaveConfirmationOpen] = (0, import_react.useState)(false); 1935 const [motionDescription, setMotionDescription] = (0, import_react.useState)(""); 1936 const [selectedDuration, setSelectedDuration] = (0, import_react.useState)(VideoDurationEnum.SIX_SEC); 1937 const [generatedVideoUrl, setGeneratedVideoUrl] = (0, import_react.useState)(void 0); 1938 const [videoProgress, setVideoProgress] = (0, import_react.useState)(0); 1939 const [isSnackbarOpen, setIsSnackbarOpen] = (0, import_react.useState)(false); 1940 const [generatedVideoAsset, setGeneratedVideoAsset] = (0, import_react.useState)(null); 1941 const [videoMoveDialogOpen, setVideoMoveDialogOpen] = (0, import_react.useState)(false); 1942 const [videoRequestId, setVideoRequestId] = (0, import_react.useState)(null); 1943 const [isPreviewVideoStepDialogOpen, setIsPreviewVideoStepDialogOpen] = (0, import_react.useState)(false); 1944 const showSnackbarOnVideoReadyRef = (0, import_react.useRef)(false); 1945 const lastSelectedImageRef = (0, import_react.useRef)(null); 1946 const [firstFramesGenNum, setFirstFramesGenNum] = (0, import_react.useState)(0); 1947 const [firstFramesEditsNum, setFirstFramesEditsNum] = (0, import_react.useState)(0); 1948 const { updateNotificationState } = useAiVideoNotification(); 1949 const generationTokenRef = (0, import_react.useRef)(v4()); 1950 const [mode, setMode] = (0, import_react.useState)(AiMediaGenerationMode.VIDEO); 1951 const aspectRatio = mode === AiMediaGenerationMode.VIDEO ? videoAspectRatio : imageAspectRatio; 1952 const setAspectRatio = mode === AiMediaGenerationMode.VIDEO ? setVideoAspectRatio : setImageAspectRatio; 1953 const [videoStep, setVideoStep] = (0, import_react.useState)(initialVideoStep ?? AiVideoGenerationStep.GENERATE_IMAGE); 1954 const [motionScreenLoading, setMotionScreenLoading] = (0, import_react.useState)(false); 1955 const [assetGenerationErrorCode, setAssetGenerationErrorCode] = (0, import_react.useState)(null); 1956 const [lastOperationType, setLastOperationType] = (0, import_react.useState)(OperationType.GENERATE); 1957 const [savedAssetIds, setSavedAssetIds] = (0, import_react.useState)(/* @__PURE__ */ new Set()); 1958 const imageLastGeneratedSettingsRef = (0, import_react.useRef)(null); 1959 const videoLastGeneratedSettingsRef = (0, import_react.useRef)(null); 1960 const [savedAssetEditorMediaIds, setSavedAssetEditorMediaIds] = (0, import_react.useState)(/* @__PURE__ */ new Map()); 1961 const [isEditLoading, setIsEditLoading] = (0, import_react.useState)(false); 1962 const [creditsContactSalesDialogConfig, setCreditsContactSalesDialogConfig] = (0, import_react.useState)(null); 1963 const [previousBatches, setPreviousBatches] = (0, import_react.useState)([]); 1964 const [currentBatchPrompt, setCurrentBatchPrompt] = (0, import_react.useState)(""); 1965 const [isCurrentBatchEdit, setIsCurrentBatchEdit] = (0, import_react.useState)(false); 1966 const [editSourceImageUrl, setEditSourceImageUrl] = (0, import_react.useState)(null); 1967 const [isExternalImageNonStandardRatio, setIsExternalImageNonStandardRatio] = (0, import_react.useState)(false); 1968 const [imageTabState, setImageTabState] = (0, import_react.useState)(null); 1969 const [videoTabState, setVideoTabState] = (0, import_react.useState)(null); 1970 const isVideoPreviewStep = mode === AiMediaGenerationMode.VIDEO && videoStep === AiVideoGenerationStep.GENERATE_VIDEO; 1971 const isGenerateVideoInProgress = isVideoPreviewStep && !generatedVideoUrl; 1972 const assets = (0, import_react.useMemo)(() => loading ? null : (data ?? []).map((res, index) => ({ 1973 type: ItemType.AI_IMAGE, 1974 id: `${res.sessionId}-${index}`, 1975 name: prompt?.split(".")[0], 1976 mediaType: EditorLibraryMediaType.Image, 1977 mediaUrl: res.url, 1978 thumbnailUrl: res.url, 1979 duration: 0, 1980 service: GqlClientAiImageService.GOOGLE, 1981 prompt 1982 })), [loading, data]); 1983 const currentAspectRatio = generatedAspectRatio ?? aspectRatio; 1984 const allDisplayedAssets = (0, import_react.useMemo)(() => isEditWithAiEnabled ? [...previousBatches.flatMap((b) => b.assets), ...assets ?? []] : assets ?? [], [previousBatches, assets]); 1985 const assetForAction = (0, import_react.useMemo)(() => assets?.find((asset) => asset.id === assetForActionId) ?? (isEditWithAiEnabled ? previousBatches.flatMap((b) => b.assets).find((asset) => asset.id === assetForActionId) : void 0), [ 1986 assets, 1987 assetForActionId, 1988 previousBatches 1989 ]); 1990 const currentScreen = screenFromModeAndStep(mode, videoStep); 1991 const shouldConfirmCancel = getShouldConfirmCancel(videoStep, loading || isEditLoading, selectedAssetId, generationFailed, generatedVideoUrl, isConvertToVideo, motionDescription) || mode === AiMediaGenerationMode.IMAGE && getShouldConfirmCancelForSavedTabState(videoTabState) || mode === AiMediaGenerationMode.VIDEO && getShouldConfirmCancelForSavedTabState(imageTabState); 1992 const lastGeneratedSettings = mode === AiMediaGenerationMode.IMAGE ? imageLastGeneratedSettingsRef.current : videoLastGeneratedSettingsRef.current; 1993 const generateImageButtonColor = data && lastGeneratedSettings?.prompt === prompt && lastGeneratedSettings?.style === style && lastGeneratedSettings?.aspectRatio === aspectRatio && lastGeneratedSettings?.cameraAngle === cameraAngle ? "default" : "gradient"; 1994 (0, import_react.useEffect)(() => { 1995 if (!isDialogOpen || !assetDimensions) return; 1996 setVideoAspectRatio(getBestFitAspectRatio(assetDimensions, true)); 1997 setImageAspectRatio(getBestFitAspectRatio(assetDimensions, false)); 1998 }, [isDialogOpen, assetDimensions]); 1999 (0, import_react.useEffect)(() => { 2000 if (assetGenerationDialogInfo?.isDialogOpen) {
2001 if ((isAiVideoBlocked || isVideoTabDisabled) && !isAiImageBlocked) setMode(AiMediaGenerationMode.IMAGE); 2002 else if (isAiImageBlocked && !isAiVideoBlocked && !isVideoTabDisabled) setMode(AiMediaGenerationMode.VIDEO); 2003 } 2004 }, [ 2005 assetGenerationDialogInfo?.isDialogOpen, 2006 isAiImageBlocked, 2007 isAiVideoBlocked, 2008 disabledTabConfig 2009 ]); 2010 (0, import_react.useEffect)(() => { 2011 if (data && assets) { 2012 if (allDisplayedAssets.find((asset) => asset.id === selectedAssetId) === void 0) setSelectedAssetId(assets[0].id); 2013 } 2014 }, [allDisplayedAssets]); 2015 (0, import_react.useEffect)(() => { 2016 if (!externalImageUrl) { 2017 setIsExternalImageNonStandardRatio(false); 2018 return; 2019 } 2020 return loadImageAspectRatio(externalImageUrl, (ratio) => { 2021 const resolvedRatio = ratio ?? GqlClientAiGeneratedAssetAspectRatio.RATIO_16_9; 2022 setGeneratedAspectRatio(resolvedRatio); 2023 setIsExternalImageNonStandardRatio(ratio === null); 2024 }); 2025 }, [externalImageUrl]); 2026 const resetState = (finalStep) => { 2027 generationTokenRef.current = v4(); 2028 if (data) pendo.trackEvent("AI generated image result", { 2029 finalStep: finalStep.toString(), 2030 promptText: prompt, 2031 style 2032 }); 2033 if (getShouldConfirmCancel(videoStep, loading || isEditLoading, selectedAssetId, generationFailed, generatedVideoUrl, isConvertToVideo, motionDescription) && finalStep === FinalStep.NO_USE && videoStep !== AiVideoGenerationStep.GENERATE_VIDEO) pendo.trackEvent("AI video gen dropped", { 2034 flowTrigger, 2035 flowTriggerAction, 2036 requestID: videoRequestId, 2037 dropStep: videoStep === AiVideoGenerationStep.GENERATE_IMAGE ? "first frames" : "add motion", 2038 firstFramesGenNum: firstFramesGenNum.toString(), 2039 firstFramesEditsNum: firstFramesEditsNum.toString() 2040 }); 2041 const isVideoGenerationStepCompleted = videoStep === AiVideoGenerationStep.GENERATE_VIDEO && finalStep === FinalStep.NO_USE; 2042 const userEngagedWithVideoFlow = !!videoRequestId || mode === AiMediaGenerationMode.VIDEO && !!data; 2043 if (finalStep !== FinalStep.NO_USE && userEngagedWithVideoFlow || isVideoGenerationStepCompleted) { 2044 const finalAction = finalStep === FinalStep.USE_BTN ? isGenerateFromLibrary ? "Done" : "Use" : "Close x"; 2045 pendo.trackEvent("AI video gen flow completed", { 2046 finalAction, 2047 flowTrigger, 2048 flowTriggerAction, 2049 requestID: videoRequestId, 2050 firstFramesEditsNum: firstFramesEditsNum.toString() 2051 }); 2052 } 2053 setAssetGenerationDialogInfo(null); 2054 }; 2055 const onCloseClick = () => { 2056 resetState(FinalStep.NO_USE); 2057 }; 2058 const requestClose = () => { 2059 if (isGenerateVideoInProgress && !generationFailed) { 2060 setIsPreviewVideoStepDialogOpen(true); 2061 return; 2062 } 2063 if (shouldConfirmCancel) setLeaveConfirmationOpen(true); 2064 else onCloseClick(); 2065 }; 2066 const openCreditsContactSalesDialog = (features, trackingId) => { 2067 setCreditsContactSalesDialogConfig({ 2068 features, 2069 trackingId 2070 }); 2071 }; 2072 const closeCreditsContactSalesDialog = () => { 2073 setCreditsContactSalesDialogConfig(null); 2074 }; 2075 async function handleGenerateImage() { 2076 setLastOperationType(OperationType.GENERATE); 2077 generationTokenRef.current = v4(); 2078 const currentToken = generationTokenRef.current; 2079 const lastRef = mode === AiMediaGenerationMode.VIDEO ? videoLastGeneratedSettingsRef.current : imageLastGeneratedSettingsRef.current; 2080 const batchToPush = isEditWithAiEnabled && assets && assets.length > 0 ? { 2081 assets, 2082 aspectRatio: currentAspectRatio, 2083 prompt: currentBatchPrompt, 2084 style: lastRef?.style ?? style, 2085 cameraAngle: lastRef?.cameraAngle ?? cameraAngle, 2086 isEditBatch: isCurrentBatchEdit 2087 } : null; 2088 if (batchToPush) setPreviousBatches((prev) => [...prev, batchToPush]); 2089 const previousSelectedAssetId = isEditWithAiEnabled ? selectedAssetId : null; 2090 const previousIsCurrentBatchEdit = isCurrentBatchEdit; 2091 const previousCurrentBatchPrompt = currentBatchPrompt; 2092 const previousGeneratedAspectRatio = generatedAspectRatio; 2093 setIsCurrentBatchEdit(false); 2094 setCurrentBatchPrompt(prompt); 2095 setSelectedAssetId(null); 2096 setLoading(true); 2097 setGeneratedAspectRatio(aspectRatio); 2098 const timer = setTimeout(() => { 2099 if (generationTokenRef.current !== currentToken) return; 2100 }, 15e3); 2101 const generatedData = await (mode === AiMediaGenerationMode.VIDEO ? generateAiVideoFirstFrame(GqlClientAiImageService.GOOGLE, 4, prompt, style, aspectRatio, cameraAngle) : generateAiImages(GqlClientAiImageService.GOOGLE, 4, prompt, style, aspectRatio, cameraAngle)); 2102 if (generationTokenRef.current !== currentToken) { 2103 clearTimeout(timer); 2104 return; 2105 } 2106 if (generatedData.error || !generatedData.images || generatedData.images.length === 0) { 2107 const isImageMode = mode === AiMediaGenerationMode.IMAGE; 2108 if (batchToPush) setPreviousBatches((prev) => prev.slice(0, -1)); 2109 setIsCurrentBatchEdit(previousIsCurrentBatchEdit); 2110 setCurrentBatchPrompt(previousCurrentBatchPrompt); 2111 setGeneratedAspectRatio(previousGeneratedAspectRatio); 2112 setSelectedAssetId(previousSelectedAssetId); 2113 if (generatedData.badPrompt) { 2114 if (isEditWithAiEnabled) setAssetGenerationErrorCode(SskyErrorC
2114ode.AiAssetGenerationFailedSafety); 2115 setGenerationFailed(true); 2116 setErrorMessage("Image generation failed due to restricted language in prompt." + (isImageMode ? "\nNo credits were used." : "")); 2117 } else { 2118 setData(void 0); 2119 if (isEditWithAiEnabled) setAssetGenerationErrorCode(SskyErrorCode.AiAssetGenerationFailedGeneral); 2120 else { 2121 setGenerationFailed(true); 2122 setErrorMessage(isImageMode ? "We couldn't generate the images.\nNo credits were deducted." : "We couldn't generate the first frame."); 2123 } 2124 } 2125 pendo.trackEvent("AI image generation failed", { 2126 prompt, 2127 style, 2128 badPrompt: (!!generatedData.badPrompt).toString() 2129 }); 2130 } else { 2131 setGenerationFailed(false); 2132 setErrorMessage(null); 2133 setData(generatedData.images); 2134 setSelectedAssetId(`${generatedData.images[0].sessionId}-0`); 2135 const generatedSettingsSnapshot = { 2136 prompt, 2137 style, 2138 aspectRatio, 2139 cameraAngle 2140 }; 2141 if (mode === AiMediaGenerationMode.IMAGE) imageLastGeneratedSettingsRef.current = generatedSettingsSnapshot; 2142 else videoLastGeneratedSettingsRef.current = generatedSettingsSnapshot; 2143 if (mode === AiMediaGenerationMode.VIDEO) setFirstFramesGenNum((prev) => prev + 1); 2144 } 2145 setLoading(false); 2146 clearTimeout(timer); 2147 } 2148 const getVideoErrorMessage = (sskyCode) => { 2149 if (sskyCode === SskyErrorCode.AiAssetGenerationFailedSafety) return "Video generation failed because the prompt contains text that violates the Terms of Use. \nNo credits were deducted."; 2150 else if (sskyCode === SskyErrorCode.AiAssetGenerationFailedCopyright) return "Video generation failed due to copyrighted content in the first frame. \nNo credits were deducted."; 2151 else if (sskyCode === SskyErrorCode.AiAssetGenerationFailedImageContent) return "Video generation failed because the first frame violates the Terms of Use. \nNo credits were deducted."; 2152 else return "We couldn't generate the video.\nNo credits were deducted."; 2153 }; 2154 const handleVideoGenerationError = (errorPayload) => { 2155 const sskyCode = errorPayload.error?.sskyCode; 2156 const googleSessionId = errorPayload.error?.clientData?.sessionId; 2157 const message = getVideoErrorMessage(sskyCode); 2158 if (showSnackbarOnVideoReadyRef.current) { 2159 updateNotificationState({ 2160 show: true, 2161 errorMessage: message, 2162 assetId: null, 2163 creditsUsed: 0, 2164 thumbnailUrl: null, 2165 savedFolderName: null 2166 }); 2167 showSnackbarOnVideoReadyRef.current = false; 2168 return; 2169 } 2170 setLoading(false); 2171 setMotionScreenLoading(false); 2172 if (sskyCode === SskyErrorCode.AiAssetGenerationFailedSafety) { 2173 setVideoStep(AiVideoGenerationStep.CONFIGURE_VIDEO); 2174 setAssetGenerationErrorCode(sskyCode); 2175 pendo.trackEvent("AI video generation RAI error dialog shown", { 2176 prompt, 2177 motionDescription, 2178 googleSessionId 2179 }); 2180 } else if (sskyCode === SskyErrorCode.AiAssetGenerationFailedCopyright || sskyCode === SskyErrorCode.AiAssetGenerationFailedImageContent) { 2181 setVideoStep(initialVideoStep ?? AiVideoGenerationStep.GENERATE_IMAGE); 2182 setAssetGenerationErrorCode(sskyCode); 2183 pendo.trackEvent("AI video generation copyright error dialog shown", { 2184 prompt, 2185 motionDescription, 2186 googleSessionId 2187 }); 2188 } else { 2189 setGenerationFailed(true); 2190 pendo.trackEvent("AI video generation general error dialog shown", { 2191 prompt, 2192 motionDescription, 2193 googleSessionId 2194 }); 2195 } 2196 setErrorMessage(message); 2197 }; 2198 const onGenerateVideoClick = async () => { 2199 setLastOperationType(OperationType.GENERATE); 2200 const thumbUrl = allDisplayedAssets.find((asset) => asset.id === selectedAssetId)?.mediaUrl ?? allDisplayedAssets[0]?.mediaUrl ?? externalImageUrl; 2201 if (!thumbUrl) return; 2202 const durationSeconds = getVideoDurationSeconds(selectedDuration); 2203 const requestId = v4(); 2204 setVideoRequestId(requestId); 2205 const selectedAssetBatch = selectedAssetId ? previousBatches.find((batch) => batch.assets.some((asset) => asset.id === selectedAssetId)) : void 0; 2206 const currentBatchSettings = videoLastGeneratedSettingsRef.current; 2207 const selectedAspectRatio = selectedAssetBatch?.aspectRatio ?? currentBatchSettings?.aspectRatio ?? generatedAspectRatio ?? aspectRatio; 2208 const firstFramePrompt = selectedAssetBatch?.prompt ?? currentBatchSettings?.prompt ?? prompt; 2209 const firstFrameStyle = selectedAssetBatch?.style ?? currentBatchSettings?.style ?? style; 2210 const firstFrameCameraAngle = selectedAssetBatch?.cameraAngle ?? currentBatchSettings?.cameraAngle ?? cameraAngle; 2211 const noneConvertValue = "none - convert image to video"; 2212 pendo.trackEvent("Gen AI video request submitted", { 2213 requestID: requestId, 2214 firstFramePrompt: isConvertToVideo ? noneConvertValue : firstFramePrompt, 2215 aspectRatio: isConvertToVideo ? noneConvertValue : selectedAspectRatio, 2216 cameraAngle: isConvertToVideo ? noneConvertValue : firstFrameCameraAngle, 2217 motionPrompt: motionDescription, 2218 videoDuration: durationSeconds.toString(), 2219 cameraMotion, 2220 style: firstFrameStyle, 2221 flowTriggerAction 2222 }); 2223 setVideoProgress(0); 2224 setGeneratedVideoUrl(void 0); 2225 setGenerationFailed(false); 2226 setErrorMessage(null); 2227 setVideoStep(AiVideoGenerationStep.GENERATE_VIDEO); 2228 const handleVideoGenerationProgress = (pending) => { 2229 setVideoProgress(pending.progress || 0); 2230 }; 2231 const handleVideoGenerationSuccess = (successPayload) => { 2232 const editorAssetMedia = successPayload?.data?.editorAssetMedia; 2233 if (editorAssetMedia) { 2234 setGeneratedVideoUrl(editorAssetMedia?.mediaUrl); 2235 setIsSnackbarOpen(true); 2236 setGeneratedVideoAsset({ 2237 id: editorAssetMedia?.id, 2238 name: editorAssetMedia?.name, 2239 folderId: editorAssetMedia?.folder?.id, 2240 folderName: editorAssetMedia?.folder?.name, 2241 creditsUsed: successPayload?.data.creditsUsed 2242 }); 2243 const size = editorAssetMedia?.mediaMetadata?.size; 2244 pendo.trackEvent("Media lib add asset", { 2245 mediaType: EditorLibraryMediaType.Video, 2246 mediaSize: size ? Math.round(size / 1024).toString() : void 0, 2247 mediaAddOrigin: isConvertToVideo ? UploadOrigin.CONVERT_IMAGE_TO_VIDEO : UploadOrigin.AI_VIDEO_GENERATED, 2248 mediaAddTarget: editorAssetMedia?.folder?.id ? "folder" : "lib root" 2249 }); 2250 if (showSnackbarOnVideoReadyRef.current) { 2251 updateNotificationState({ 2252 show: true, 2253 errorMessage: null, 2254 assetId: editorAssetMedia?.id, 2255 creditsUsed: successPayload?.data.creditsUsed, 2256 thumbnailUrl: lastSelectedImageRef.current, 2257 savedFolderName: editorAssetMedia?.folder?.name ?? null 2258 }); 2259 showSnackbarOnVideoReadyRef.current = false;
2260 } 2261 } 2262 }; 2263 const sourceAssetInCache = sourceImageMediaId && assetLibraryMediaByGqlMediaId[sourceImageMediaId]?.lifecycleStage === GqlClientAssetLifecycleStage.ENABLED ? assetLibraryMediaByGqlMediaId[sourceImageMediaId] : void 0; 2264 const sourceAssetContributions = [{ 2265 mediaOrigin: GqlClientMediaOrigin.AI_GENERATED, 2266 mediaType: GqlClientMediaType.VIDEO 2267 }, ...sourceAssetInCache ? getAssetSourceContributions(sourceAssetInCache) : []]; 2268 await generateAiVideoAsset(thumbUrl, durationSeconds, firstFramePrompt, motionDescription || void 0, selectedAspectRatio, firstFrameStyle, cameraMotion, firstFrameCameraAngle, handleVideoGenerationProgress, handleVideoGenerationError, handleVideoGenerationSuccess, requestId, sourceAssetInCache?.name ?? void 0, sourceAssetInCache?.description ?? void 0, sourceAssetInCache?.folder?.id ?? void 0, sourceAssetContributions); 2269 }; 2270 const handleEditImage = async (prompt, imageUrl, aspectRatio) => { 2271 setLastOperationType(OperationType.EDIT); 2272 const editLastRef = mode === AiMediaGenerationMode.VIDEO ? videoLastGeneratedSettingsRef.current : imageLastGeneratedSettingsRef.current; 2273 const batchToPush = assets && assets.length > 0 ? { 2274 assets, 2275 aspectRatio: currentAspectRatio, 2276 prompt: currentBatchPrompt, 2277 style: editLastRef?.style ?? style, 2278 cameraAngle: editLastRef?.cameraAngle ?? cameraAngle, 2279 isEditBatch: isCurrentBatchEdit 2280 } : null; 2281 const previousData = data; 2282 const previousPrompt = currentBatchPrompt; 2283 const previousIsCurrentBatchEdit = isCurrentBatchEdit; 2284 const previousGeneratedAspectRatio = generatedAspectRatio; 2285 const previousSelectedAssetId = selectedAssetId; 2286 if (batchToPush) { 2287 setPreviousBatches((prev) => [...prev, batchToPush]); 2288 setData(void 0); 2289 } 2290 setIsCurrentBatchEdit(true); 2291 setEditSourceImageUrl(imageUrl); 2292 setCurrentBatchPrompt(prompt); 2293 setGeneratedAspectRatio(aspectRatio); 2294 setSelectedAssetId(null); 2295 setIsEditLoading(true); 2296 const result = await (mode === AiMediaGenerationMode.VIDEO ? editAiVideoFirstFrame(imageUrl, prompt) : editAiImage(imageUrl, prompt)); 2297 if (result.result === GqlClientEditAiImageResult.SUCCESS) { 2298 const { imageUrl, sessionId } = result; 2299 setData([{ 2300 url: imageUrl, 2301 sessionId, 2302 indexInBatch: 0 2303 }]); 2304 setSelectedAssetId(`${sessionId}-0`); 2305 setErrorMessage(null); 2306 setIsEditLoading(false); 2307 mode === AiMediaGenerationMode.VIDEO && setFirstFramesEditsNum((prev) => prev + 1); 2308 pendo.trackEvent("AI media edit with prompt", { 2309 flow: mode === AiMediaGenerationMode.IMAGE ? "image result" : "video first frame", 2310 prompt 2311 }); 2312 return true; 2313 } 2314 if (batchToPush) { 2315 setPreviousBatches((prev) => prev.slice(0, -1)); 2316 setData(previousData); 2317 } 2318 setCurrentBatchPrompt(previousPrompt); 2319 setIsCurrentBatchEdit(previousIsCurrentBatchEdit); 2320 setGeneratedAspectRatio(previousGeneratedAspectRatio); 2321 setSelectedAssetId(previousSelectedAssetId); 2322 if (result.result === GqlClientEditAiImageResult.ERROR) { 2323 const { errorCode } = result; 2324 setAssetGenerationErrorCode(errorCode); 2325 } 2326 setIsEditLoading(false); 2327 return false; 2328 }; 2329 const handleModeChange = (event, newMode) => { 2330 if (!newMode || newMode === mode) return; 2331 const hasGeneratedImages = !!data; 2332 if (hasGeneratedImages) { 2333 const currentTabState = { 2334 prompt, 2335 style, 2336 cameraAngle, 2337 data, 2338 generatedAspectRatio, 2339 selectedAssetId, 2340 generationFailed, 2341 errorMessage, 2342 previousBatches, 2343 currentBatchPrompt, 2344 isCurrentBatchEdit, 2345 hasGeneratedImages, 2346 videoStep, 2347 motionDescription, 2348 cameraMotion, 2349 selectedDuration, 2350 generatedVideoUrl, 2351 generatedVideoAsset 2352 }; 2353 if (mode === AiMediaGenerationMode.IMAGE) setImageTabState(currentTabState); 2354 else setVideoTabState(currentTabState); 2355 } 2356 const targetTabState = newMode === AiMediaGenerationMode.IMAGE ? imageTabState : videoTabState; 2357 const hasGeneratedInTargetTab = targetTabState?.hasGeneratedImages === true; 2358 const isVideoMode = newMode === AiMediaGenerationMode.VIDEO; 2359 resetVideoState(setVideoStep, setGeneratedVideoUrl, setGeneratedVideoAsset, AiVideoGenerationStep.GENERATE_IMAGE); 2360 const setters = { 2361 setPrompt, 2362 setStyle, 2363 setCameraAngle, 2364 setData, 2365 setGeneratedAspectRatio, 2366 setSelectedAssetId, 2367 setGenerationFailed, 2368 setErrorMessage, 2369 setVideoStep, 2370 setMotionDescription, 2371 setCameraMotion, 2372 setSelectedDuration, 2373 setGeneratedVideoUrl, 2374 setGeneratedVideoAsset, 2375 setPreviousBatches, 2376 setCurrentBatchPrompt, 2377 setIsCurrentBatchEdit 2378 }; 2379 if (hasGeneratedInTargetTab && targetTabState) restoreTabConfiguration(targetTabState, setters, isVideoMode, AiVideoGenerationStep.GENERATE_IMAGE); 2380 else copyConfigurationToTargetTab(setters, isVideoMode, VideoDurationEnum.SIX_SEC);
2381 setMode(newMode); 2382 setPreviewAssetIndex(-1); 2383 setAssetForActionId(null); 2384 }; 2385 const handleCopilotClick = () => { 2386 togglePromptDialog.on(); 2387 }; 2388 const handlePromptDialogClose = () => { 2389 togglePromptDialog.off(); 2390 if (!promptGeneratorChat.proposedPrompt || !usesGeneratedPrompt) promptGeneratorChat.restart(); 2391 }; 2392 const handlePromptDialogInsertPrompt = (newPrompt) => { 2393 setPrompt(newPrompt); 2394 togglePromptDialog.off(); 2395 }; 2396 const onAssetPreview = (index, previewTrigger) => { 2397 setPreviewAssetIndex(index); 2398 pendo.trackEvent("AI Generator Asset Preview", { 2399 assetType: "image", 2400 trigger: previewTrigger.toString() 2401 }); 2402 }; 2403 const onMoveConfirm = (targetFolderId) => { 2404 handleExternalAssetUpload({ 2405 asset: assetForAction, 2406 destinationFolderId: targetFolderId 2407 }); 2408 setAssetForActionId(null); 2409 }; 2410 const addAssetToLibrary = (asset) => { 2411 handleUploadAiImageAsset({ 2412 asset, 2413 onUploadSuccess: (editorAssetMediaId) => { 2414 setSavedAssetEditorMediaIds((prev) => new Map(prev).set(asset.id, editorAssetMediaId)); 2415 } 2416 }); 2417 }; 2418 const markAsSaved = (assetId) => { 2419 setSavedAssetIds((prev) => new Set(prev).add(assetId)); 2420 }; 2421 const value = { 2422 isDialogOpen, 2423 currentScreen, 2424 mode, 2425 videoStep, 2426 prompt, 2427 setPrompt, 2428 style, 2429 setStyle, 2430 aspectRatio, 2431 setAspectRatio, 2432 cameraAngle, 2433 setCameraAngle, 2434 loading, 2435 assets, 2436 previousBatches, 2437 currentBatchPrompt, 2438 allDisplayedAssets, 2439 generationFailed, 2440 errorMessage, 2441 generatedAspectRatio, 2442 selectedAssetId, 2443 setSelectedAssetId, 2444 currentAspectRatio, 2445 cameraMotion, 2446 setCameraMotion, 2447 motionDescription, 2448 setMotionDescription, 2449 selectedDuration, 2450 setSelectedDuration, 2451 generatedVideoUrl, 2452 videoProgress, 2453 generatedVideoAsset, 2454 isSnackbarOpen, 2455 setIsSnackbarOpen, 2456 videoMoveDialogOpen, 2457 setVideoMoveDialogOpen, 2458 videoRequestId, 2459 isPreviewVideoStepDialogOpen, 2460 setIsPreviewVideoStepDialogOpen, 2461 motionScreenLoading, 2462 savedAssetIds, 2463 markAsSaved, 2464 setAssetForActionId, 2465 assetForAction, 2466 selectFolderDialogOpen, 2467 setSelectFolderDialogOpen, 2468 isLeaveConfirmationOpen, 2469 setLeaveConfirmationOpen, 2470 assetGenerationErrorCode, 2471 setAssetGenerationErrorCode, 2472 lastOperationType, 2473 previewAssetIndex, 2474 setPreviewAssetIndex, 2475 isExternalImageNonStandardRatio, 2476 isPromptDialogOpen, 2477 promptGeneratorChat, 2478 usesGeneratedPrompt, 2479 handleCopilotClick, 2480 handlePromptDialogClose, 2481 handlePromptDialogInsertPrompt, 2482 isVideoPreviewStep, 2483 generateImageButtonColor, 2484 isGenerateFromLibrary, 2485 disabledTabConfig, 2486 externalImageUrl, 2487 isConvertToVideo, 2488 isAiImageBlocked, 2489 isAiVideoBlocked, 2490 isAiImageEditingBlocked, 2491 isVideoTabDisabled, 2492 imageGenerationCost, 2493 creditsBalance, 2494 creditsContactSalesDialogConfig, 2495 openCreditsContactSalesDialog, 2496 closeCreditsContactSalesDialog, 2497 onDialogConfirmation, 2498 savedAssetEditorMediaIds, 2499 setVideoStep, 2500 setGenerationFailed, 2501 setErrorMessage, 2502 setMotionScreenLoading, 2503 handleGenerateImage, 2504 handleModeChange, 2505 onAssetPreview, 2506 onMoveConfirm, 2507 addAssetToLibrary, 2508 requestClose, 2509 onCloseClick, 2510 onGenerateVideoClick, 2511 isEditLoading, 2512 editSourceImageUrl, 2513 isCurrentBatchEdit, 2514 handleEditImage, 2515 resetState, 2516 showSnackbarOnVideoReadyRef, 2517 lastSelectedImageRef, 2518 rootFolder, 2519 foldersByParentFolderId, 2520 foldersById, 2521 mediaByFolderId 2522 }; 2523 return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AiMediaGenerationContext.Provider, { 2524 value, 2525 children 2526 }); 2527}; 2528//#endregion 2529//#region client/components/common/copilotChat/messages/message/common.ts 2530var import_faSparkles$1 = require_faSparkles(); 2531var MessageContainer = (0, import_material.styled)(import_material.Box)({ 2532 flexGrow: 0, 2533 flexShrink: 0, 2534 flexBasis: "auto", 2535 margin: "8px 0", 2536 display: "flex", 2537 flexDirection: "row", 2538 alignItems: "baseline", 2539 justifyContent: "flex-start" 2540}); 2541var AvatarContainer = (0, import_material.styled)(import_material.Box)({ 2542 position: "relative", 2543 top: "6px", 2544 display: "flex", 2545 alignItems: "center" 2546}); 2547var Triangle = (0, import_material.styled)(import_material.Box)({ 2548 width: "6px", 2549 height: "12px", 2550 borderStyle: "solid", 2551 borderWidth: `6px`, 2552 borderColor: "transparent", 2553 borderLeftWidth: 0, 2554 marginLeft: `8px` 2555}); 2556var TextBubble = (0, import_material.styled)(import_material.Typography)({ 2557 maxWidth: "fit-content", 2558 minWidth: "min-content", 2559 whiteSpace: "pre-line", 2560 borderRadius: "16px", 2561 padding: "16px" 2562}); 2563//#endregion 2564//#region client/components/common/copilotChat/messages/message/assistant/common.tsx 2565var AssistantAvatar = (0, import_material.styled)(import_material.Avatar)(({ theme }) => ({ 2566 backgroundImage: `linear-gradient(to bottom right, ${theme.palette.brand.gradientMagentaBlue})`, 2567 color: theme.palette.common.white 2568})); 2569var AssistantAvatarImage = () => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.SvgIcon, { 2570 fontSize: "small", 2571 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FontAwesomeIcon, { icon: import_faSparkles$1.faSparkles }) 2572}); 2573var AssistantTriangle = (0, import_material.styled)(Triangle)(({ theme }) => ({ borderRightColor: theme.palette.divider })); 2574var AssistantTextBubble = (0, import_material.styled)(TextBubble)(({ theme }) => ({ backgroundColor: theme.palette.divider })); 2575//#endregion 2576//#region client/components/common/copilotChat/messages/message/assistant/AssistantMessage.tsx 2577var AssistantMessage = (props) => { 2578 return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(MessageContainer, { 2579 "data-testid": "copilot-chat-message", 2580 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AvatarContainer, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AssistantAvatar, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AssistantAvatarImage, {}) }
2580), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AssistantTriangle, { sx: props.assistantBubbleColor ? { borderRightColor: props.assistantBubbleColor } : void 0 })] }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AssistantTextBubble, { 2581 variant: "body1", 2582 sx: props.assistantBubbleColor ? { backgroundColor: props.assistantBubbleColor } : void 0, 2583 children: [props.text, props.typing ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Caret, { children: "|" }) : null] 2584 })] 2585 }), props.actions] }); 2586}; 2587var Caret = (0, import_material.styled)("span")(({ theme }) => ({ color: theme.palette.primary.main })); 2588var CHAT_MESSAGE_MAX_WIDTH_PX = 894; 2589//#endregion 2590//#region client/components/common/copilotChat/prompt/PromptInput.tsx 2591var import_faPaperPlane = require_faPaperPlane(); 2592var textMarginRight = 12; 2593var iconSize = 24; 2594var INPUT_PROMPT_MAX_WIDTH = 840 + textMarginRight + iconSize + 16; 2595var PromptInput = (props) => { 2596 function handleInputFieldChange(event) { 2597 props.setInputText(event.target.value); 2598 } 2599 function handleSubmit() { 2600 if (!props.disabled && props.inputText) props.onSubmit(); 2601 } 2602 function handleKeyDown(event) { 2603 const modified = event.altKey || event.shiftKey || event.ctrlKey || event.metaKey; 2604 if ((event.code === "Enter" || event.code === "NumpadEnter") && !modified) { 2605 event.preventDefault(); 2606 handleSubmit(); 2607 } 2608 } 2609 return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { 2610 sx: sxInputPrompt, 2611 children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 2612 sx: sxInputTextAndSubmit, 2613 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.TextField, { 2614 fullWidth: true, 2615 sx: sxText, 2616 placeholder: "Start typing", 2617 value: props.inputText, 2618 onChange: handleInputFieldChange, 2619 multiline: true, 2620 rows: 2, 2621 inputRef: props.inputRef, 2622 disabled: props.disabled, 2623 onKeyDown: handleKeyDown, 2624 autoFocus: props.autoFocus 2625 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Tooltip, { 2626 placement: "top", 2627 title: "Submit", 2628 arrow: true, 2629 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.IconButton, { 2630 "aria-label": "Submit", 2631 color: "primary", 2632 "data-tracking-id": props.submitButtonTrackingId, 2633 sx: { fontSize: `${iconSize}px` }, 2634 disabled: props.disabled || !props.inputText, 2635 onClick: handleSubmit, 2636 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FontAwesomeIcon, { icon: import_faPaperPlane.faPaperPlane }) 2637 }) }) 2638 })] 2639 }) 2640 }); 2641}; 2642var sxInputPrompt = { 2643 flexGrow: 0, 2644 flexShrink: 0, 2645 flexBasis: "auto", 2646 width: "100%", 2647 display: "flex", 2648 flexDirection: "column" 2649}; 2650var sxInputTextAndSubmit = { 2651 flexGrow: 0, 2652 flexShrink: 0, 2653 flexBasis: "73px", 2654 width: "100%", 2655 display: "flex", 2656 flexDirection: "row", 2657 justifyContent: "center", 2658 alignItems: "center" 2659}; 2660var sxText = { 2661 maxWidth: 840, 2662 marginRight: `${textMarginRight}px`, 2663 backgroundColor: "common.white", 2664 flexGrow: 1, 2665 flexShrink: 1, 2666 flexBasis: "0px" 2667}; 2668//#endregion 2669//#region client/components/common/copilotChat/chatContainer.ts 2670var TopSection = (0, import_material.styled)(import_material.Box)({ 2671 paddingRight: `${INPUT_PROMPT_MAX_WIDTH - 840}px`, 2672 width: "100%", 2673 display: "flex", 2674 flexDirection: "column", 2675 justifyContent: "flex-end" 2676}); 2677var bottomPanelHeight = "151px"; 2678var BottomSection = (0, import_material.styled)(import_material.Box)(({ theme }) => ({ 2679 paddingLeft: `${CHAT_MESSAGE_MAX_WIDTH_PX - 840}px`, 2680 position: "sticky", 2681 bottom: 0, 2682 height: `${bottomPanelHeight}`, 2683 width: "100%", 2684 display: "flex", 2685 flexDirection: "column", 2686 alignItems: "center", 2687 backgroundColor: theme.palette.other.editorBackground 2688})); 2689//#endregion 2690//#region client/components/common/copilotChat/messages/messages.ts 2691var Messages = (0, import_material.styled)(import_material.Box)({ 2692 flex: "0 0 auto", 2693 maxWidth: CHAT_MESSAGE_MAX_WIDTH_PX, 2694 width: "100%", 2695 maxHeight: "100%", 2696 display: "flex", 2697 flexDirection: "column" 2698}); 2699var MessagesContainer = (0, import_material.styled)(import_material.Box)({ 2700 height: "100%", 2701 width: "100%", 2702 display: "flex", 2703 flexDirection: "column", 2704 justifyContent: "flex-end", 2705 alignItems: "center" 2706}); 2707//#endregion 2708//#region client/images/dots_01.gif 2709var dots_01_default = "/client/images/dots_01.Bf3eAREC.gif"; 2710//#endregion 2711//#region client/components/common/copilotChat/messages/message/assistant/PendingAssistantMessage.tsx 2712var PendingAssistantMessage = (props) => { 2713 return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(MessageContainer, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AvatarContainer, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AssistantAvatar, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AssistantAvatarImage, {}) }
2713), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AssistantTriangle, { sx: props.assistantBubbleColor ? { borderRightColor: props.assistantBubbleColor } : void 0 })] }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AssistantTextBubble, { 2714 sx: props.assistantBubbleColor ? { backgroundColor: props.assistantBubbleColor } : void 0, 2715 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(WaitingImage, { 2716 alt: "Waiting for Assistant", 2717 src: dots_01_default 2718 }) 2719 })] }); 2720}; 2721var WaitingImage = (0, import_material.styled)("img")({ width: "34px" }); 2722//#endregion 2723//#region client/components/common/copilotChat/prompt/promptContainer.ts 2724var PromptContainer = (0, import_material.styled)(import_material.Box)({ 2725 height: "100%", 2726 width: "100%", 2727 maxWidth: INPUT_PROMPT_MAX_WIDTH, 2728 alignItems: "center", 2729 display: "flex", 2730 flexDirection: "column", 2731 padding: "16px 0" 2732}); 2733//#endregion 2734//#region client/components/common/copilotChat/prompt/RestartButton.tsx 2735var RestartButton = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { 2736 sx: sxCommands, 2737 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Button, { 2738 size: "medium", 2739 "data-tracking-id": props.trackingId, 2740 startIcon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FontAwesomeIcon, { icon: import_faSparkles$1.faSparkles }), 2741 sx: { textTransform: "none" }, 2742 disabled: props.disabled, 2743 onClick: props.onClick, 2744 children: "Start New Prompt" 2745 }) 2746}); 2747var sxCommands = { 2748 flex: "0 0 22px", 2749 marginTop: "16px", 2750 alignSelf: "flex-start", 2751 display: "flex", 2752 flexDirection: "row", 2753 alignItems: "center" 2754}; 2755//#endregion 2756//#region client/components/common/copilotChat/messages/message/UserMessage.tsx 2757var UserMessage = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(MessageContainer, { 2758 "data-testid": "copilot-chat-message", 2759 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AvatarContainer, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Avatar, { 2760 sx: { 2761 backgroundColor: "secondary.main", 2762 color: "common.white" 2763 }, 2764 children: props.initials 2765 }
2765), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Triangle, { sx: { borderRightColor: "common.white" } })] }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TextBubble, { 2766 variant: "body1", 2767 sx: { backgroundColor: "common.white" }, 2768 children: props.text 2769 })] 2770}); 2771//#endregion 2772//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/Dialogs/AiImagePromptGeneratorDialog.tsx 2773var AiImagePromptGeneratorDialog = (props) => { 2774 const { userName, firstName, lastName } = useUserData(); 2775 const userInitials = getUserInitials(userName, firstName, lastName); 2776 const [inputText, setInputText] = (0, import_react.useState)(""); 2777 const endOfMessagesRef = (0, import_react.useRef)(null); 2778 (0, import_react.useEffect)(() => { 2779 setTimeout(() => { 2780 if (endOfMessagesRef.current) endOfMessagesRef.current.scrollIntoView({ behavior: "smooth" }); 2781 }, 0); 2782 }, [ 2783 endOfMessagesRef, 2784 props.chat.messages, 2785 props.open 2786 ]); 2787 function resetState() { 2788 setInputText(""); 2789 } 2790 function handleSubmit() { 2791 const message = inputText.trim(); 2792 if (message) { 2793 props.chat.sendMessage(message); 2794 setInputText(""); 2795 } 2796 } 2797 function handleInsertClick() { 2798 if (props.chat.proposedPrompt) { 2799 props.onInsertPrompt(props.chat.proposedPrompt); 2800 PendoService.getInstance().trackEvent("Use copilot generated prompt", { 2801 copilotStartingPoint: props.chat.startingPoint?.type, 2802 copilotStartingText: props.chat.startingPoint?.value, 2803 copilotGeneratedPrompt: props.chat.proposedPrompt 2804 }); 2805 } 2806 } 2807 return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dist$1.ComplexInputDialog, { 2808 maxWidth: "md", 2809 open: props.open, 2810 onClose: props.onClose, 2811 TransitionProps: { onExited: resetState }, 2812 PaperProps: { sx: { 2813 height: "100%", 2814 width: "900px", 2815 backgroundColor: "other.editorBackground" 2816 } }, 2817 dialogTitle: "AI Prompt Generator", 2818 DialogTitleProps: { sx: { backgroundColor: "white !important" } }, 2819 DialogActionsProps: { sx: { backgroundColor: "white !important" } }, 2820 primaryActionButtonText: "Insert prompt", 2821 PrimaryActionButtonProps: { 2822 "data-tracking-id": "tracking-id-copilot-prompt-generator-use
2822-button", 2823 disabled: !props.chat.proposedPrompt, 2824 onClick: handleInsertClick 2825 }, 2826 secondaryActionButtonText: "Cancel", 2827 SecondaryActionButtonProps: { 2828 "data-tracking-id": "tracking-id-copilot-prompt-generator-cancel-button", 2829 onClick: props.onClose 2830 }, 2831 confirmCancelText: "Navigating away will result in any progress being lost", 2832 ConfirmCancelDialogProps: { 2833 dialogTitle: "Leaving AI Prompt Generator?", 2834 primaryActionButtonText: "Leave", 2835 PrimaryActionButtonProps: { "data-tracking-id": "tracking-id-copilot-prompt-generator-close-dialog-confirmation-leave" }, 2836 secondaryActionButtonText: "Stay", 2837 SecondaryActionButtonProps: { "data-tracking-id": "tracking-id-copilot-prompt-generator-close-dialog-confirmation-stay" } 2838 }, 2839 shouldConfirmCancel: props.shouldConfirmClose, 2840 CloseIconButtonProps: { onClick: props.onClose }, 2841 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TopSection, { 2842 sx: { minHeight: `calc(100% - ${bottomPanelHeight})` }, 2843 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MessagesContainer, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Messages, { children: [ 2844 props.chat.messages.map((chatMessage, index) => chatMessage.role === ClientChatRoleEnum.USER ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(UserMessage, { 2845 initials: userInitials, 2846 text: chatMessage.displayContent 2847 }, index) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AssistantMessage, { 2848 text: formatAssistantMessage(chatMessage.displayContent), 2849 typing: index === props.chat.messages.length - 1 && props.chat.isAssistantTyping 2850 }, index)), 2851 props.chat.isWaitingForAssistant && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PendingAssistantMessage, {}),
2852 /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: endOfMessagesRef }) 2853 ] }) }) 2854 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BottomSection, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(PromptContainer, { 2855 sx: { padding: "8px 0" }, 2856 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(PromptInput, { 2857 submitButtonTrackingId: "tracking-id-copilot-prompt-generator-submit-button", 2858 inputText, 2859 setInputText, 2860 inputRef: props.chat.inputRef, 2861 disabled: props.chat.isWaitingForAssistant || props.chat.isAssistantTyping, 2862 onSubmit: handleSubmit, 2863 autoFocus: true 2864 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RestartButton, { 2865 trackingId: "tracking-id-copilot-prompt-generator-restart-button", 2866 disabled: props.chat.messages.length < 2, 2867 onClick: props.chat.restart 2868 })] 2869 }) })] 2870 }); 2871}; 2872function formatAssistantMessage(message) { 2873 return message.split("**").map((part, index) => { 2874 if (part === "") return null; 2875 if (index % 2 === 0) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: part }, index); 2876 return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: part }, index); 2877 }); 2878} 2879//#endregion 2880//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/Dialogs/AiGeneratorLeaveConfirmationDialog.tsx 2881var AiGeneratorLeaveConfirmationDialog = ({ open, mode, loading, videoStep, onClose, onLeave, onStay }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dist$1.ConfirmationDialog, { 2882 dialogTitle: getConfirmationDialogTitle(mode, loading), 2883 open, 2884 onClose, 2885 CloseIconButtonProps: { onClick: onClose }, 2886 primaryActionButtonText: getConfirmationDialogPrimaryButtonText(mode, loading), 2887 PrimaryActionButtonProps: { 2888 onClick: onLeave, 2889 "data-tracking-id": getConfirmationDialogButtonsTrackingId(mode, loading, videoStep, "leave") 2890 }, 2891 secondaryActionButtonText: getConfirmationDialogSecondaryButtonText(mode, loading), 2892 SecondaryActionButtonProps: { 2893 onClick: onStay, 2894 "data-tracking-id": getConfirmationDialogButtonsTrackingId(mode, loading, videoStep, "stay") 2895 }, 2896 sx: { whiteSpace: "pre-line" }, 2897 children: getConfirmationDialogContent(mode, loading) 2898}); 2899//#endregion 2900//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/Dialogs/AiGeneratorFailedDialog.tsx 2901var termsOfUseBody = (onTermsClick, showNoCreditsDeducted) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Typography, { 2902 variant: "body1", 2903 children: [ 2904 "Please see the ", 2905 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Link, { 2906 target: "_blank", 2907 href: "https://cloud.google.com/terms/service-terms", 2908 onClick: onTermsClick, 2909 sx: { 2910 cursor: "pointer", 2911 textDecoration: "underline", 2912 fontSize: "14px" 2913 }, 2914 children: "Terms of Use" 2915 }), 2916 " for details.",
2917 showNoCreditsDeducted && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {}), "No credits were deducted."] }) 2918 ] 2919}); 2920var noCreditsDeductedBody = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Typography, { 2921 variant: "body1", 2922 children: "No credits were deducted." 2923}); 2924var getDialogContent = ({ sskyErrorCode, mode, operationType, onTermsClick }) => { 2925 const isConvert = operationType === OperationType.CONVERT; 2926 const isEdit = operationType === OperationType.EDIT; 2927 switch (sskyErrorCode) { 2928 case SskyErrorCode.AiAssetGenerationFailedCopyright: 2929 if (isEdit) return { 2930 title: "This image or prompt contains copyrighted content", 2931 body: noCreditsDeductedBody, 2932 pendoConfirmEvent: `AI ${mode} image edit copyright error got it clicked`, 2933 trackingId: "tracking-id-ai-media-generator-edit-image-copyright-error-got-it-btn", 2934 buttonText: "Got it" 2935 }; 2936 return { 2937 title: `The ${isConvert ? "image" : "first frame"} can't be converted into a video due to a copyright violation`, 2938 body: noCreditsDeductedBody, 2939 pendoConfirmEvent: `AI ${mode} generation copyright error got it clicked`, 2940 trackingId: "tracking-id-ai-media-generator-generate-video-copyright-error-got-it-btn", 2941 buttonText: isConvert ? "Got it" : "Create a new first frame" 2942 }; 2943 case SskyErrorCode.AiAssetGenerationFailedImageContent: return { 2944 title: `The ${isConvert ? "image" : "first frame"} can't be converted into a video because it violates the Terms of Use`, 2945 body: termsOfUseBody(onTermsClick, true), 2946 pendoConfirmEvent: `AI ${mode} generation illegal image content got it clicked`, 2947 trackingId: "tracking-id-ai-media-generator-generate-image-illegal-image-content-got-it-btn", 2948 buttonText: isConvert ? "Got it" : "Create a new first frame" 2949 }; 2950 case SskyErrorCode.AiAssetGenerationFailedGeneral: return { 2951 title: `We couldn't generate the ${isEdit ? "image" : mode === AiMediaGenerationMode.IMAGE ? "images" : "frames"}`, 2952 body: noCreditsDeductedBody, 2953 pendoConfirmEvent: `AI ${mode} generation general error got it clicked`, 2954 trackingId: "tracking-id-ai-media-generator-generate-general-error-got-it-btn", 2955 buttonText: "Got it" 2956 }; 2957 case SskyErrorCode.AiAssetGenerationFailedSafety: 2958 default: return { 2959 title: "Prompt contains text that violates the Terms of Use", 2960 body: termsOfUseBody(onTermsClick, isConvert || isEdit), 2961 pendoConfirmEvent: isEdit ? `AI ${mode} image edit prompt violates terms of use error got it clicked` : `AI ${mode} generation illegal prompt got it clicked`, 2962 trackingId: isEdit ? "tracking-id-ai-media-generator-edit-image-illegal-prompt-got-it-btn" : mode === AiMediaGenerationMode.IMAGE ? "tracking-id-ai-media-generator-generate-image-illegal-prompt-got-it-btn" : "tracking-id-ai-media-generator-generate-video-illegal-motion-prompt-got-it-btn", 2963 buttonText: "Got it" 2964 }; 2965 } 2966}; 2967var AiGeneratorFailedDialog = ({ open, onClose, onConfirm, mode, sskyErrorCode, operationType }) => { 2968 const pendo = PendoService.getInstance(); 2969 const [displayedErrorCode, setDisplayedErrorCode] = (0, import_react.useState)(sskyErrorCode); 2970 (0, import_react.useEffect)(() => { 2971 if (sskyErrorCode !== null) setDisplayedErrorCode(sskyErrorCode); 2972 }, [sskyErrorCode]); 2973 const content = getDialogContent({ 2974 sskyErrorCode: displayedErrorCode, 2975 mode, 2976 operationType, 2977 onTermsClick: () => pendo.trackEvent(`AI ${mode} generation illegal prompt terms of use clicked`) 2978 }); 2979 return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Dialog, { 2980 open, 2981 onClose, 2982 maxWidth: "md", 2983 fullWidth: true, 2984 PaperProps: { sx: { 2985 width: "600px", 2986 maxWidth: "600px" 2987 } }, 2988 children: [ 2989 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dist$1.TruffleDialogTitle, { 2990 multiline: true, 2991 CloseIconButtonProps: { onClick: onClose }, 2992 children: content.title 2993 }), 2994 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.DialogContent, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { 2995 sx: { 2996 display: "flex", 2997 flexDirection: "column", 2998 gap: "16px" 2999 }, 3000 children: content.body 3001 }) }),
3002 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.DialogActions, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Button, { 3003 variant: "contained", 3004 color: "primary", 3005 onClick: () => { 3006 onConfirm(); 3007 pendo.trackEvent(content.pendoConfirmEvent); 3008 }, 3009 "data-tracking-id": content.trackingId, 3010 children: content.buttonText 3011 }) }) 3012 ] 3013 }); 3014}; 3015//#endregion 3016//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/AiMediaGenerationFields/AiMediaGenerationStyles.tsx 3017var import_faArrowUp = require_faArrowUp(); 3018var import_faArrowDown = require_faArrowDown(); 3019var WRAP_STYLES_BOX_SIZE = "67px"; 3020var DEFAULT_BOX_SIZE = "57.5px"; 3021var AiMediaGenerationStyles = (props) => { 3022 const { title, selectedStyleType, setStyle, disabled, styleOptions, wrapStyles = false, loading } = props; 3023 const [hoveredStyle, setHoveredStyle] = import_react.useState(null); 3024 const boxSize = wrapStyles ? WRAP_STYLES_BOX_SIZE : DEFAULT_BOX_SIZE; 3025 const handleTileClick = (style) => { 3026 if (!disabled) setStyle(style); 3027 }; 3028 const showGifInPreviewCards = (style) => { 3029 return style.gif && hoveredStyle === style.type; 3030 }; 3031 const getThumbnailTrackingId = (type) => { 3032 if (Object.values(GqlClientAiCameraMotion).includes(type)) { 3033 const motion = type.toString().toLowerCase().replace(/_/g, "-"); 3034 return `tracking-id-ai-video-generator-camera-movement-${motion === "static" ? "static-camera" : motion}-btn`; 3035 } 3036 return `tracking-id-ai-image-generator-style-btn-${type}`; 3037 }; 3038 return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 3039 sx: { 3040 display: "flex", 3041 flexDirection: "column", 3042 gap: "12px", 3043 width: "100%" 3044 }, 3045 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { 3046 sx: { 3047 display: "flex", 3048 justifyContent: "space-between", 3049 alignItems: "center" 3050 },
3051 children: loading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Skeleton, { 3052 variant: "rounded", 3053 width: "110px", 3054 height: "24px" 3055 }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Typography, { 3056 variant: "h5", 3057 children: title 3058 }) 3059 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { 3060 sx: thumbnailsBoxSxProps(!!loading, wrapStyles), 3061 children: styleOptions.map((style) => { 3062 return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.ButtonBase, { 3063 onClick: !loading ? () => handleTileClick(style.type) : void 0, 3064 onMouseEnter: !loading ? () => setHoveredStyle(style.type) : void 0, 3065 onMouseLeave: !loading ? () => setHoveredStyle(null) : void 0, 3066 "data-tracking-id": getThumbnailTrackingId(style.type), 3067 children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dist$1.ThumbnailActions, { 3068 label: loading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Skeleton, { 3069 variant: "text", 3070 sx: { 3071 width: "67px", 3072 lineHeight: "21px" 3073 } 3074 }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Typography, { 3075 variant: "caption", 3076 sx: { 3077 textAlign: "left", 3078 width: boxSize 3079 }, 3080 children: style.name 3081 }), 3082 selected: style.type === selectedStyleType, 3083 disabled, 3084 ContentProps: { sx: { 3085 width: boxSize, 3086 height: boxSize 3087 } }, 3088 loading, 3089 children: [style.gif && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { 3090 component: "img", 3091 src: style.gif, 3092 alt: style.alt, 3093 sx: gifSxProps(showGifInPreviewCards(style), boxSize) 3094 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { 3095 component: "img", 3096 src: style.img, 3097 alt: style.alt, 3098 sx: imageSxProps(!showGifInPreviewCards(style)) 3099 })] 3100 }) 3101 }, style.type); 3102 }) 3103 })] 3104 }); 3105}; 3106var thumbnailsBoxSxProps = (loading, isWrap) => ({ 3107 overflow: "auto", 3108 display: "flex", 3109 alignItems: "flex-start", 3110 flexWrap: isWrap ? "wrap" : void 0, 3111 columnGap: isWrap ? "12px" : "8px", 3112 rowGap: loading ? "27px" : "12px", 3113 padding: "2px" 3114}); 3115var imageSxProps = (visible) => ({ 3116 opacity: visible ? 1 : 0, 3117 transition: "opacity 1s ease" 3118}); 3119var gifSxProps = (visible, size) => ({ 3120 ...imageSxProps(visible), 3121 position: "absolute", 3122 width: size, 3123 height: size, 3124 zIndex: 1e3 3125}); 3126//#endregion 3127//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/AiMediaGenerationFields/CameraAngleSelect.tsx 3128var import_faInfoCircle = require_faInfoCircle(); 3129var CameraAngleSelect = (props) => { 3130 const { mode, disabled, cameraAngle, onChange, options } = props; 3131 const renderOption = (option) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 3132 sx: { 3133 display: "flex", 3134 alignItems: "center", 3135 gap: "6px" 3136 }, 3137 children: [option.icon, /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Typography, { 3138 variant: "body1", 3139 children: option.title 3140 })] 3141 }); 3142 return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 3143 sx: { 3144 display: "flex", 3145 justifyContent: "space-between", 3146 alignItems: "center" 3147 }, 3148 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 3149 sx: { 3150 display: "flex", 3151 alignItems: "center", 3152 gap: "4px" 3153 }, 3154 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Typography, { 3155 variant: "h5", 3156 children: "Camera angle" 3157 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Tooltip, { 3158 title: "The position and orientation of the camera relative to the subject.", 3159 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FontAwesomeIcon, { 3160 fontSize: "14px", 3161 icon: import_faInfoCircle.faInfoCircle 3162 }) 3163 })] 3164 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Select, { 3165 value: cameraAngle.title, 3166 size: "medium", 3167 disabled, 3168 onChange: (e) => onChange(e.target.value), 3169 renderValue: () => renderOption(cameraAngle), 3170 sx: { width: "244px" }, 3171 "data-tracking-id": `tracking-id-ai-${mode}-generator-camera-angle`, 3172 children: options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dist$1.TruffleMenuItem, { 3173 value: option.title, 3174 children: renderOption(option) 3175 }, option.title)) 3176 })] 3177 }); 3178}; 3179//#endregion 3180//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/AiMediaGenerationFields/AspectRatioToggle.tsx 3181var AspectRatioToggle = (props) => { 3182 const { mode, disabled, aspectRatio, setAspectRatio, options } = props; 3183 return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 3184 sx: { 3185 display: "flex", 3186 justifyContent: "space-between", 3187 alignItems: "center" 3188 }, 3189 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Typography, { 3190 variant: "h5", 3191 children: "Aspect ratio" 3192 }
3192), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dist$1.TruffleToggleButtonGroup, { 3193 onChange: (_, value) => { 3194 if (value !== null) setAspectRatio(value); 3195 }, 3196 value: aspectRatio, 3197 exclusive: true, 3198 disabled, 3199 size: "large", 3200 sx: { width: "244px" }, 3201 children: options.filter((option) => mode === AiMediaGenerationMode.IMAGE || !option.imageOnly).map((option) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.ToggleButton, { 3202 value: option.value, 3203 "data-tracking-id": `tracking-id-ai-${mode}-generator-aspect-ratio-${option.value}-btn`, 3204 sx: { flex: "1 0 0" }, 3205 children: option.label 3206 }, option.value)) 3207 })] 3208 }); 3209}; 3210//#endregion 3211//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/AiMediaGenerationFields/AiMediaGenerationPrompt.tsx 3212var import_faComments = require_faComments(); 3213var AiMediaGenerationPrompt = (props) => { 3214 const { mode, disabled, prompt, onPromptChange, onCopilotClick, textFieldSxProps } = props; 3215 const handleTextInputChange = (event) => { 3216 onPromptChange(event.target.value); 3217 }; 3218 const label = mode === AiMediaGenerationMode.IMAGE ? "Tell us about the image" : "Tell us the content of your video"; 3219 const placeholder = `Who or what's in it 3220Where it takes place 3221What's happening in the ${mode}`; 3222 const copilotButtonText = "Help me write a prompt"; 3223 const trackingId = `tracking-id-ai-${mode === AiMediaGenerationMode.IMAGE ? "image" : "video"}-generator-prompt-copilot-btn`; 3224 return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 3225 sx: { 3226 display: "flex", 3227 flexDirection: "column", 3228 gap: "16px", 3229 paddingBottom: "24px" 3230 }, 3231 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.TextField, { 3232 disabled, 3233 onChange: handleTextInputChange, 3234 rows: 3, 3235 fullWidth: true, 3236 multiline: true, 3237 variant: "outlined", 3238 size: "medium", 3239 placeholder, 3240 value: prompt, 3241 label, 3242 sx: textFieldSxProps 3243 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Button, { 3244 variant: "outlined", 3245 color: "default", 3246 size: "medium", 3247 sx: { alignSelf: "stretch" }, 3248 startIcon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.SvgIcon, { 3249 fontSize: "small", 3250 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FontAwesomeIcon, { icon: import_faComments.faComments }) 3251 }), 3252 onClick: onCopilotClick, 3253 "data-tracking-id": trackingId, 3254 disabled, 3255 children: copilotButtonText 3256 })] 3257 }); 3258}; 3259//#endregion 3260//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/AiMediaGenerationFields/AiMediaGenerationModeToggle.tsx 3261var import_faImage = require_faImage(); 3262var import_faFilm = require_faFilm(); 3263var AiMediaGenerationModeToggle = (props) => { 3264 const { mode, onChange, loading, disabledTabConfig, isAiVideoBlocked, isAiImageBlocked, isVideoTabDisabled } = props; 3265 return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dist$1.TruffleToggleButtonGroup, { 3266 value: mode, 3267 exclusive: true, 3268 onChange, 3269 size: "large", 3270 fullWidth: true, 3271 disabled: loading, 3272 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Tooltip, { 3273 title: getVideoTabTooltip(disabledTabConfig, isAiVideoBlocked), 3274 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { 3275 style: { width: "100%" }, 3276 children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.ToggleButton, { 3277 value: AiMediaGenerationMode.VIDEO, 3278 "data-tracking-id": "tracking-id-ai-media-generator-video-tab", 3279 disabled: loading || isAiVideoBlocked || isVideoTabDisabled, 3280 sx: { width: "100%" }, 3281 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(FontAwesomeIcon, { icon: import_faFilm.faFilm }), "Video"] 3282 }) 3283 }) 3284 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Tooltip, { 3285 title: isAiImageBlocked ? "AI Image Generator is disabled. To enable this feature, contact your account owner." : "", 3286 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { 3287 style: { width: "100%" }, 3288 children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.ToggleButton, { 3289 value: AiMediaGenerationMode.IMAGE, 3290 "data-tracking-id": "tracking-id-ai-media-generator-image-tab", 3291 disabled: loading || isAiImageBlocked, 3292 sx: { width: "100%" }, 3293 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(FontAwesomeIcon, { icon: import_faImage.faImage }), "Image"] 3294 }) 3295 }) 3296 })] 3297 }); 3298}; 3299//#endregion 3300//#region client/images/video-gen-illustration.gif 3301var video_gen_illustration_default = "/client/images/video-gen-illustration.zh0q6njY.gif"; 3302//#endregion 3303//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/screens/ImageGenerationScreen/AiGeneratorVideoInitialState.tsx 3304var generateVideoSteps = [ 3305 "Describe the video you want to create", 3306 "Select the first frame", 3307 "Add motion to the frame" 3308]; 3309var AiGeneratorVideoInitialState = () => { 3310 const [gifKey, setGifKey] = (0, import_react.useState)(0); 3311 const handleReplayGif = () => { 3312 setGifKey((prev) => prev + 1); 3313 }; 3314 return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { 3315 sx: videoModeRightSideContainerSxProps, 3316 children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 3317 sx: videoModeInitialStateSxProps, 3318 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { 3319 src: `${video_gen_illustration_default}?t=${gifKey}`, 3320 alt: "Asset generation illustration", 3321 onClick: handleReplayGif, 3322 style: videoIllustrationSxProps 3323 }
3323, gifKey), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 3324 sx: { 3325 display: "flex", 3326 flexDirection: "column", 3327 alignItems: "center", 3328 gap: "8px" 3329 }, 3330 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Typography, { 3331 variant: "h3", 3332 children: "Generate a video" 3333 }), generateVideoSteps.map((step, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.ListItem, { 3334 dense: true, 3335 sx: { height: "37px" }, 3336 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.ListItemAvatar, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dist$1.TruffleAvatar, { 3337 text: `${index + 1}`, 3338 sx: { 3339 backgroundColor: "primary.contrastText", 3340 color: "text.primary" 3341 } 3342 }) }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.ListItemText, { primary: step })] 3343 }, index))] 3344 })] 3345 }) 3346 }); 3347}; 3348var videoModeRightSideContainerSxProps = { 3349 height: "100%", 3350 width: "100%", 3351 display: "flex", 3352 flexDirection: "column", 3353 alignItems: "center", 3354 padding: "32px", 3355 overflowY: "auto", 3356 ...import_dist$1.scrollOnHoverSxProps 3357}; 3358var videoModeInitialStateSxProps = { 3359 margin: "auto", 3360 display: "flex", 3361 flexDirection: "column", 3362 alignItems: "center", 3363 gap: "32px" 3364}; 3365var videoIllustrationSxProps = { 3366 maxWidth: "400px", 3367 width: "100%", 3368 height: "auto", 3369 cursor: "pointer", 3370 flexShrink: 1 3371}; 3372//#endregion 3373//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/EditPopover/PromptEditorQuill.tsx 3374var import_faCircleCheck = require_faCircleCheck(); 3375var import_faCopy = require_faCopy(); 3376var import_faPlus = require_faPlus(); 3377var import_faFolderPlus = require_faFolderPlus(); 3378var import_faArrowUpRightAndArrowDownLeftFromCenter = require_faArrowUpRightAndArrowDownLeftFromCenter(); 3379var import_faSparkles = require_faSparkles$1(); 3380init_embed(); 3381init_quill(); 3382var HELPER_TEXT_DEFAULT = "To save credits, include multiple changes in one prompt."; 3383var HELPER_TEXT_ERROR = "Add more detail to the prompt to apply changes"; 3384var PlaceholderBlot = class extends Embed { 3385 static { 3386 this.blotName = "placeholder"; 3387 } 3388 static { 3389 this.tagName = "span"; 3390 } 3391 static { 3392 this.className = "ql-placeholder"; 3393 } 3394 static create(value) { 3395 const node = super.create(); 3396 node.setAttribute("data-value", value); 3397 node.textContent = value; 3398 node.setAttribute("contenteditable", "false"); 3399 return node; 3400 } 3401 static value(node) { 3402 return node.getAttribute("data-value"); 3403 } 3404}; 3405var isPlaceholderOp = (op) => typeof op.insert === "object" && op.insert !== null && "placeholder" in op.insert; 3406var deltaToText = (delta) => { 3407 return (delta.ops ?? []).map((op) => { 3408 if (typeof op.insert === "string") return op.insert; 3409 if (isPlaceholderOp(op)) return op.insert.placeholder; 3410 return ""; 3411 }).join("").replace(/\n$/, ""); 3412}; 3413var parseContent = (quill) => { 3414 const ops = quill.getContents().ops ?? []; 3415 return { 3416 hasContent: ops.some((op) => typeof op.insert === "string" && op.insert.replace(/\n/g, "").trim() || isPlaceholderOp(op)), 3417 hasUnresolved: ops.some(isPlaceholderOp) 3418 }; 3419}; 3420var selectPlaceholderBlot = (quill, blot) => { 3421 const index = quill.getIndex(blot); 3422 quill.setSelection(index + 1, 0, "user"); 3423 blot.domNode.classList.add("ql-placeholder--selected"); 3424 return index; 3425}; 3426var PromptEditorQuill = ({ chipToAppend, onChange, placeholder, error = false, defaultContent = null, showCreditsHelper }) => { 3427 const { palette } = (0, import_material.useTheme)(); 3428 const containerRef = (0, import_react.useRef)(null); 3429 const quillRef = (0, import_react.useRef)(null); 3430 const selectedTokenIndexRef = (0, import_react.useRef)(null); 3431 const [isFocused, setIsFocused] = (0, import_react.useState)(false); 3432 const helperText = error ? HELPER_TEXT_ERROR : HELPER_TEXT_DEFAULT; 3433 const tokenColor = palette.secondary.light; 3434 (0, import_react.useEffect)(() => { 3435 if (!containerRef.current || quillRef.current) return; 3436 try { 3437 quill_default.register({ "blots/placeholder": PlaceholderBlot }); 3438 } catch {} 3439 const container = containerRef.current; 3440 const quill = new quill_default(container, { 3441 theme: "default", 3442 formats: ["placeholder"], 3443 placeholder 3444 }); 3445 quillRef.current = quill; 3446 if (defaultContent) quill.setContents(defaultContent, "api"); 3447 quill.on("text-change", () => { 3448 const { hasContent, hasUnresolved } = parseContent(quill); 3449 onChange(hasContent, hasUnresolved, quill.getContents()); 3450 }); 3451 quill.on("selection-change", () => { 3452 setIsFocused(quill.hasFocus()); 3453 container.querySelectorAll(".ql-placeholder").forEach((el) => el.classList.remove("ql-placeholder--selected")); 3454 selectedTokenIndexRef.current = null; 3455 }); 3456 const handlePlaceholderClick = (e) => { 3457 if (!(e.target instanceof Element)) return; 3458 const placeholderEl = e.target.closest(".ql-placeholder"); 3459 if (placeholderEl) setTimeout(() => { 3460 const blot = quill_default.find(placeholderEl); 3461 if (blot) selectedTokenIndexRef.current = selectPlaceholderBlot(quill, blot); 3462 }, 0); 3463 }; 3464 const handleKeyDown = (e) => { 3465 const idx = selectedTokenIndexRef.current; 3466 if (idx === null) return; 3467 if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) { 3468 e.preventDefault(); 3469 e.stopPropagation(); 3470 quill.deleteText(idx, 1, "user"); 3471 quill.insertText(idx, e.key, "user"); 3472 quill.setSelection(idx + 1, 0, "user"); 3473 } else if (e.key === "Backspace" || e.key === "Delete") { 3474 e.preventDefault(); 3475 e.stopPropagation(); 3476 quill.deleteText(idx, 1, "user"); 3477 quill.setSelection(idx, 0, "user"); 3478 } 3479 }; 3480 container.addEventListener("click", handlePlaceholderClick); 3481 container.addEventListener("keydown", handleKeyDown, true); 3482 return () => { 3483 container.removeEventListener("click", handlePlaceholderClick); 3484 container.removeEventListener("keydown", handleKeyDown, true); 3485 quillRef.current = null; 3486 }; 3487 }, []); 3488 (0, import_react.useEffect)(() => { 3489 if (!chipToAppend || !quillRef.current) return; 3490 const quill = quillRef.current; 3491 const { hasContent } = parseContent(quill); 3492 let insertAt = quill.getLength() - 1; 3493 if (hasContent && (insertAt === 0 || quill.getText(insertAt - 1, 1) !== "\n")) { 3494 quill.insertText(insertAt, "\n", "api"); 3495 insertAt += 1; 3496 } 3497 let firstTokenBlot = null; 3498 let firstTokenIndex = null; 3499 chipToAppend.prompt.split(/'([^']+)'/g).forEach((part, i) => { 3500 if (i % 2 === 1) { 3501 if (firstTokenIndex === null) firstTokenIndex = insertAt; 3502 quill.insertEmbed(insertAt, "placeholder", part, "api"); 3503 insertAt += 1; 3504 } else if (part) { 3505 quill.insertText(insertAt, part, "api"); 3506 insertAt += part.length; 3507 } 3508 }); 3509 quill.insertText(insertAt, "\n", "api"); 3510 insertAt += 1; 3511 const { hasContent: newHasContent, hasUnresolved } = parseContent(quill); 3512 onChange(newHasContent, hasUnresolved, quill.getContents()); 3513 if (firstTokenIndex !== null) for (const el of Array.from(quill.root.querySelectorAll(".ql-placeholder"))) { 3514 const blot = quill_default.find(el); 3515 if (blot) { 3516 if (quill.getIndex(blot) === firstTokenIndex) { 3517 firstTokenBlot = blot; 3518 break; 3519 } 3520 } 3521 } 3522 if (firstTokenBlot !== null) selectedTokenIndexRef.current = selectPlaceholderBlot(quill, firstTokenBlot); 3523 else quill.focus(); 3524 }
3524, [chipToAppend?.version]); 3525 return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.FormControl, { 3526 error, 3527 focused: isFocused, 3528 fullWidth: true, 3529 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { 3530 sx: getEditorWrapperSx(isFocused, error, tokenColor), 3531 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { ref: containerRef }) 3532 }), (isFocused && showCreditsHelper || error) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.FormHelperText, { children: helperText })] 3533 }); 3534}; 3535var getEditorWrapperSx = (focused, error, tokenColor) => ({ 3536 borderRadius: "8px", 3537 boxSizing: "border-box", 3538 ...error ? { 3539 border: (theme) => `1px solid ${theme.palette.error.main}`, 3540 boxShadow: (theme) => `0 0 4px 0 ${theme.palette.error.main}` 3541 } : { 3542 border: "1px solid transparent", 3543 backgroundImage: (theme) => `linear-gradient(${theme.palette.background.paper}, ${theme.palette.background.paper}), linear-gradient(to right, ${theme.palette.brand?.gradientMagentaBlue})`, 3544 backgroundOrigin: "border-box", 3545 backgroundClip: "padding-box, border-box", 3546 ...focused && { boxShadow: (theme) => `0 0 4px 0 ${theme.palette.primary.main}` }, 3547 ...!focused && { "&:hover .ql-editor": { backgroundColor: (theme) => theme.palette.action.hover } } 3548 }, 3549 ".ql-editor": { 3550 minHeight: "136px", 3551 overflowY: "hidden", 3552 padding: "8px 12px", 3553 fontSize: (theme) => theme.typography.body1.fontSize, 3554 fontFamily: (theme) => theme.typography.body1.fontFamily, 3555 lineHeight: "24px", 3556 letterSpacing: "0.15px", 3557 color: "text.primary", 3558 outline: "none", 3559 wordBreak: "break-word", 3560 whiteSpace: "pre-wrap" 3561 }, 3562 ".ql-editor.ql-blank::before": { 3563 color: (theme) => theme.palette.text.disabled, 3564 fontStyle: "italic" 3565 }, 3566 ".ql-placeholder": { 3567 color: tokenColor, 3568 cursor: "pointer" 3569 }, 3570 ".ql-placeholder--selected": { 3571 backgroundColor: (theme) => (0, import_material.alpha)(theme.palette.primary.main, .25), 3572 borderRadius: "2px" 3573 } 3574}); 3575//#endregion 3576//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/AiMediaGenerationDialogStyles.ts 3577init_emotion_react_browser_esm(); 3578var creditsButtonContentSxProps = { 3579 display: "flex", 3580 flexDirection: "row", 3581 gap: "8px", 3582 alignItems: "center", 3583 justifyContent: "center" 3584}; 3585var InputBoxSxProps = (isGenerateImageButtonVisible) => ({ 3586 height: isGenerateImageButtonVisible ? "calc(100% - 48px)" : "100%", 3587 width: "408px", 3588 position: "relative", 3589 display: "flex", 3590 flexDirection: "column", 3591 gap: "24px", 3592 padding: "0px 2px", 3593 flexShrink: 0, 3594 overflowX: "hidden", 3595 overflowY: "auto", 3596 ...import_dist$1.scrollOnHoverSxProps 3597}); 3598var ResultsPanel = (0, import_material.styled)(import_material.Box, { shouldForwardProp: (prop) => prop !== "aspectRatio" })(({ theme }) => { 3599 return { 3600 height: "100%", 3601 borderRadius: "8px", 3602 flexGrow: 1, 3603 alignItems: "center", 3604 backgroundColor: theme.palette.other.editorBackground, 3605 display: "flex", 3606 flexDirection: "column", 3607 overflow: "auto", 3608 ...import_dist$1.scrollOnHoverSxProps 3609 }; 3610}); 3611var animatedGradient = keyframes({ 3612 "0%": { backgroundPosition: "0% 50%" }, 3613 "50%": { backgroundPosition: "100% 50%" }, 3614 "100%": { backgroundPosition: "0% 50%" } 3615}); 3616var gradientLoadingImageLayer = (borderRadius) => ({ 3617 position: "absolute", 3618 top: 0, 3619 left: 0, 3620 width: "100%", 3621 height: "100%", 3622 backgroundSize: "400% 400%", 3623 backgroundImage: (theme) => `linear-gradient(114deg, ${theme.palette.brand.gradientMagentaBlue})`, 3624 animation: `${animatedGradient} 5s ease infinite`, 3625 opacity: .75, 3626 borderRadius 3627}); 3628var gradientLoadingImageContent = { 3629 position: "absolute", 3630 display: "flex", 3631 alignItems: "center", 3632 justifyContent: "center", 3633 top: 0, 3634 left: 0, 3635 width: "100%", 3636 height: "100%" 3637}; 3638var NARROW_LAYOUT_BREAKPOINT = 1157; 3639//#endregion 3640//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/EditPopover/AiEditMediaPopover.tsx 3641var AiEditPopoverSource = /* @__PURE__ */ function(AiEditPopoverSource) { 3642 AiEditPopoverSource["ImageGenerationResult"] = "ImageGenerationResult"; 3643 return AiEditPopoverSource; 3644}({});
3645var containsBackgroundRemovalPrompt = (text) => { 3646 return text.toLowerCase().split("\n").some((line) => { 3647 if (/\b(alpha\s+(channel|transparency)|png\s+transparency)\b/.test(line)) return true; 3648 if (!/\b(background|bg|image)\b/.test(line)) return false; 3649 if (/\btransparent\s+(background|bg|image)\b/.test(line)) return true; 3650 if (/\b(background|bg)\s+(to\s+)?transpar(ent|ency)\b/.test(line)) return true; 3651 if (/\b(make|set|turn|render|change|convert|add)\s+(the\s+|a\s+|my\s+|its\s+|this\s+|to\s+)?transpar(ent|ency)\b/.test(line)) return true; 3652 if (/\b(see[\s-]?through|translucent)\s+(background|bg)\b/.test(line)) return true; 3653 if (/\b(background|bg)\s+(see[\s-]?through|translucent)\b/.test(line)) return true; 3654 if (/\b(make|set|turn|render|change|convert)\s+(the\s+|a\s+|my\s+|its\s+|this\s+)?(background|bg)\s+(see[\s-]?through|translucent)\b/.test(line)) return true; 3655 if (/\b(no|without)\s+(a\s+)?background\b/.test(line)) return true; 3656 if (/\bempty\s+(background|bg)\b/.test(line)) return true; 3657 if (/\bcutout\s+(background|bg)\b/.test(line)) return true; 3658 return /\b(remove|erase|delete|clear|cut\s*out|get\s*rid\s*of)\s+(the\s+|a\s+|my\s+|its\s+|this\s+)?(background|bg)\b/.test(line); 3659 }); 3660}; 3661var ALL_EDIT_CHIPS = [ 3662 { 3663 label: "Remove object", 3664 prompt: "Remove 'object'", 3665 trackingId: "tracking-id-ai-media-generator-edit-remove-object-btn" 3666 }, 3667 { 3668 label: "Change object", 3669 prompt: "Change 'describe the object' to 'describe the new object'", 3670 trackingId: "tracking-id-ai-media-generator-edit-change-object-btn" 3671 }, 3672 { 3673 label: "Add object", 3674 prompt: "Add 'describe the object' to 'position'", 3675 trackingId: "tracking-id-ai-media-generator-edit-add-object-btn" 3676 }, 3677 { 3678 label: "Change color", 3679 prompt: "Change color of 'object' to 'color'", 3680 trackingId: "tracking-id-ai-media-generator-edit-change-color-btn" 3681 }, 3682 { 3683 label: "Change background", 3684 prompt: "Change background to 'describe the background'", 3685 trackingId: "tracking-id-ai-media-generator-edit-change-bg-btn" 3686 } 3687]; 3688var chipsBySource = { ["ImageGenerationResult"]: ALL_EDIT_CHIPS.filter((chip) => chip.label !== "Enhance quality") }; 3689var AiEditMediaPopover = ({ anchorEl, onClose, source, imageUrl, aspectRatio }) => { 3690 const chips = chipsBySource[source]; 3691 const { handleEditImage, mode } = useAiMediaGenerationContext(); 3692 const { cost: imageEditCost } = useCreditsCostForFeature(GqlClientFeatureTypeDefinition.LIMIT_AI_IMAGE_EDITING, 1); 3693 const { balance: creditsBalance } = useNumericFeatureRestriction(GqlClientFeatureTypeDefinition.LIMIT_AI_IMAGE_EDITING); 3694 const [hasContent, setHasContent] = (0, import_react.useState)(false); 3695 const [hasUnresolved, setHasUnresolved] = (0, import_react.useState)(false); 3696 const [applyError, setApplyError] = (0, import_react.useState)(false); 3697 const [shakeKey, setShakeKey] = (0, import_react.useState)(0); 3698 const [isBackgroundRemovalWarningOpen, setIsBackgroundRemovalWarningOpen] = (0, import_react.useState)(false); 3699 const [chipToAppend, setChipToAppend] = (0, import_react.useState)(null); 3700 const savedContentRef = (0, import_react.useRef)(null); 3701 (0, import_react.useEffect)(() => { 3702 if (!anchorEl) { 3703 setChipToAppend(null); 3704 setApplyError(false); 3705 setShakeKey(0); 3706 } 3707 }, [anchorEl]); 3708 const handleChipClick = (chip) => { 3709 setChipToAppend((prev) => ({ 3710 prompt: chip.prompt, 3711 version: (prev?.version ?? 0) + 1 3712 })); 3713 }; 3714 const handlePromptChange = (newHasContent, newHasUnresolved, delta) => { 3715 setHasContent(newHasContent); 3716 setHasUnresolved(newHasUnresolved); 3717 setApplyError(false); 3718 setIsBackgroundRemovalWarningOpen(false); 3719 savedContentRef.current = delta; 3720 }; 3721 const executeEdit = async (promptText) => { 3722 if (!imageUrl) return; 3723 onClose(); 3724 if (await handleEditImage(promptText, imageUrl, aspectRatio)) { 3725 savedContentRef.current = null; 3726 setHasContent(false); 3727 setHasUnresolved(false); 3728 setChipToAppend(null); 3729 setApplyError(false); 3730 } 3731 }; 3732 const handleApply = async () => { 3733 if (hasUnresolved) { 3734 setApplyError(true); 3735 setShakeKey((prev) => prev + 1); 3736 return; 3737 } 3738 const promptText = deltaToText(savedContentRef.current);
3739 if (containsBackgroundRemovalPrompt(promptText)) { 3740 setIsBackgroundRemovalWarningOpen(true); 3741 return; 3742 } 3743 await executeEdit(promptText); 3744 }; 3745 const handleGenerateWithSolidBackground = async () => { 3746 setIsBackgroundRemovalWarningOpen(false); 3747 await executeEdit(deltaToText(savedContentRef.current)); 3748 }; 3749 if (mode === AiMediaGenerationMode.IMAGE && Boolean(anchorEl) && creditsBalance <= 0) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AiCreditsContactSalesDialog, { 3750 displayMode: AiCreditsContactSalesDialogDisplayMode.immediateAction, 3751 open: true, 3752 onClose, 3753 immediateActionFeatures: [GqlClientFeatureTypeDefinition.LIMIT_AI_IMAGE_EDITING], 3754 dataTrackingId: "tracking-id-ai-image-generator-result-edit-out-of-credits-contact-sales-btn" 3755 }); 3756 return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dist$1.TrufflePopover, { 3757 open: Boolean(anchorEl), 3758 anchorEl, 3759 onClose, 3760 anchorOrigin: { 3761 vertical: "top", 3762 horizontal: "left" 3763 }, 3764 transformOrigin: { 3765 vertical: "top", 3766 horizontal: "right" 3767 }, 3768 slotProps: { paper: { 3769 sx: (0, import_dist$1.combineSxProps)(popoverPaperSx, shakeKey > 0 ? shakeAnimationSx : null), 3770 onAnimationEnd: () => setShakeKey(0) 3771 } }, 3772 children: [ 3773 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dist$1.TruffleModalTitle, { 3774 startIcon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.SvgIcon, { 3775 fontSize: "small", 3776 color: "gradient", 3777 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FontAwesomeIcon, { icon: import_faSparkles.faSparkles }) 3778 }), 3779 CloseIconButtonProps: { onClick: onClose }, 3780 children: "Edit image" 3781 }), 3782 /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dist$1.TruffleModalContent, { 3783 sx: contentSx, 3784 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { 3785 sx: chipsContainerSx, 3786 children: chips.map((chip) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Chip, { 3787 label: chip.label, 3788 size: "small", 3789 clickable: true, 3790 onClick: () => handleChipClick(chip), 3791 "data-tracking-id": chip.trackingId 3792 }, chip.label)) 3793 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PromptEditorQuill, { 3794 chipToAppend, 3795 onChange: handlePromptChange, 3796 placeholder: "Describe the change you want e.g., \"Remove the tree in the background\".\n\nTo save credits, include multiple changes in one prompt.", 3797 error: applyError, 3798 defaultContent: savedContentRef.current, 3799 showCreditsHelper: mode === AiMediaGenerationMode.IMAGE 3800 })] 3801 }), 3802 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dist$1.TruffleModalActions, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Button, { 3803 fullWidth: true, 3804 variant: "contained", 3805 color: "gradient", 3806 disabled: !hasContent, 3807 onMouseDown: (e) => e.preventDefault(), 3808 onClick: handleApply, 3809 startIcon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.SvgIcon, { 3810 fontSize: "small", 3811 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FontAwesomeIcon, { icon: import_faSparkles.faSparkles }) 3812 }), 3813 "data-tracking-id": `tracking-id-ai-${mode === AiMediaGenerationMode.IMAGE ? "image" : "video"}-generator-result-edit-apply-changes-btn`, 3814 children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 3815 sx: creditsButtonContentSxProps, 3816 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Typography, { 3817 component: "span", 3818 children: "Apply changes" 3819 }), mode === AiMediaGenerationMode.IMAGE && imageEditCost !== null && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AiCreditsLabel, { 3820 displayMode: AiCreditsLabelDisplayMode.cost, 3821 featureName: GqlClientFeatureTypeDefinition.LIMIT_AI_IMAGE_EDITING, 3822 cost: imageEditCost, 3823 isEstimate: false, 3824 contactSalesDataTrackingId: "tracking-id-ai-image-generator-result-edit-apply-changes-tooltip-contact-sales-btn", 3825 showTooltip: true 3826 })] 3827 }) 3828 }) }), 3829 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(WarningConfirmationDialog, {
3830 open: isBackgroundRemovalWarningOpen, 3831 title: "Transparency isn't supported yet, use a solid background instead?", 3832 secondaryButtonProps: { 3833 text: "Back to edit the prompt", 3834 trackingId: "tracking-id-ai-media-generator-edit-no-remove-bg-notification-cancel-btn" 3835 }, 3836 primaryButtonProps: { 3837 text: "Generate with solid background instead", 3838 trackingId: "tracking-id-ai-media-generator-edit-no-remove-bg-notification-proceed-btn" 3839 }, 3840 onClose: () => setIsBackgroundRemovalWarningOpen(false), 3841 onConfirm: handleGenerateWithSolidBackground 3842 }) 3843 ] 3844 }); 3845}; 3846var popoverPaperSx = { width: "432px" }; 3847var contentSx = { 3848 display: "flex", 3849 flexDirection: "column", 3850 gap: "20px" 3851}; 3852var chipsContainerSx = { 3853 display: "flex", 3854 flexWrap: "wrap", 3855 gap: "12px 8px" 3856}; 3857var shakeAnimationSx = { 3858 animation: "popover-shake 0.5s ease-in-out", 3859 "@keyframes popover-shake": { 3860 "0%": { transform: "translate(0.5px, 0.5px) rotate(0deg)" }, 3861 "10%": { transform: "translate(-0.5px, -1px) rotate(-0.5deg)" }, 3862 "20%": { transform: "translate(-1.5px, 0px) rotate(0.5deg)" }, 3863 "30%": { transform: "translate(1.5px, 1px) rotate(0deg)" }, 3864 "40%": { transform: "translate(0.5px, -0.5px) rotate(0.5deg)" }, 3865 "50%": { transform: "translate(-0.5px, 1px) rotate(-0.5deg)" }, 3866 "60%": { transform: "translate(-1.5px, 0.5px) rotate(0deg)" }, 3867 "70%": { transform: "translate(1.5px, 0.5px) rotate(-0.5deg)" }, 3868 "80%": { transform: "translate(-0.5px, -0.5px) rotate(0.5deg)" }, 3869 "90%": { transform: "translate(0.5px, 1px) rotate(0deg)" }, 3870 "100%": { transform: "translate(0.5px, -1px) rotate(-0.5deg)" } 3871 } 3872}; 3873//#endregion 3874//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/screens/ImageGenerationScreen/AiGeneratorImageGrid.tsx 3875var AiGeneratorImageGrid = ({ assets, loading, mode, selectedAssetId, isActiveBatch, currentAspectRatio, thumbnailDimensions, isEditBatch, onSelectAsset, onDoubleClickAsset, onPreviewAsset, onAddToFolder, onSaveToLibrary, savedAssetIds, markAsSaved }) => { 3876 const [editAnchorEl, setEditAnchorEl] = (0, import_react.useState)(null); 3877 const [editPopoverImageUrl, setEditPopoverImageUrl] = (0, import_react.useState)(null); 3878 const [editPopoverAspectRatio, setEditPopoverAspectRatio] = (0, import_react.useState)(currentAspectRatio); 3879 const { loading: isGenerationProcessLoading, isEditLoading, editSourceImageUrl, isAiImageEditingBlocked } = useAiMediaGenerationContext(); 3880 const [fakeProgress, setFakeProgress] = (0, import_react.useState)(0); 3881 const fakeProgressIntervalRef = (0, import_react.useRef)(null); 3882 const isEditWithAiEnabled = isFeatureEnabled(featureFlagConst._EDITOR_GEN_AI_EDIT_AND_CONVERT); 3883 const numberOfThumbnails = loading ? 4 : assets?.length ?? 0; 3884 const BORDER_RADIUS = "5px"; 3885 (0, import_react.useEffect)(() => { 3886 if (isEditLoading) { 3887 setFakeProgress(0); 3888 fakeProgressIntervalRef.current = setInterval(() => { 3889 setFakeProgress((prev) => Math.min(prev + (prev < 70 ? 2 : .6), 90)); 3890 }, 300); 3891 } else { 3892 if (fakeProgressIntervalRef.current) { 3893 clearInterval(fakeProgressIntervalRef.current); 3894 fakeProgressIntervalRef.current = null; 3895 } 3896 setFakeProgress(0); 3897 } 3898 return () => { 3899 if (fakeProgressIntervalRef.current) clearInterval(fakeProgressIntervalRef.current); 3900 }; 3901 }, [isEditLoading]); 3902 const renderThumbnailItem = (index) => { 3903 const asset = assets?.[index]; 3904 const isLoading = loading || !asset; 3905 const isSaved = !isLoading && savedAssetIds.has(asset.id); 3906 return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { 3907 "data-asset-id": asset?.id, 3908 onClick: () => !isLoading && onSelectAsset(asset.id), 3909 onDoubleClick: () => { 3910 if (!isLoading) onDoubleClickAsset(asset.id, index); 3911 }, 3912 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dist$1.ThumbnailActions, { 3913 sx: isEditBatch ? getEditLoadingContainerSxProps(thumbnailDimensions) : getThumbnailActionsSxProps(thumbnailDimensions), 3914 selected: !isLoading && (selectedAssetId ? asset.id === selectedAssetId : isActiveBatch && index === 0), 3915 showActions: selectedAssetId === asset?.id ? "always" : "onHover", 3916 rightActions: !isLoading && mode === AiMediaGenerationMode.IMAGE && /* @__P
3916URE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Tooltip, { 3917 title: "Add to folder", 3918 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dist$1.ThumbnailActionsIconButton, { 3919 sx: { pointerEvents: "auto" }, 3920 onClick: (e) => { 3921 e.stopPropagation(); 3922 onAddToFolder(asset.id); 3923 }, 3924 "data-tracking-id": "tracking-id-ai-image-generator-result-add-to-folder", 3925 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FontAwesomeIcon, { icon: import_faFolderPlus.faFolderPlus }) 3926 }) 3927 }), isEditWithAiEnabled ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Tooltip, { 3928 title: isSaved ? "Saved" : "Save to library", 3929 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dist$1.ThumbnailActionsIconButton, { 3930 sx: { 3931 pointerEvents: "auto", 3932 ...isSaved && { 3933 cursor: "default", 3934 "&:hover": { 3935 backgroundColor: "success.light", 3936 color: "success.main" 3937 } 3938 } 3939 }, 3940 onClick: (e) => { 3941 e.stopPropagation(); 3942 if (!isSaved) { 3943 markAsSaved(asset.id); 3944 onSaveToLibrary(asset); 3945 } 3946 }, 3947 disableRipple: isSaved, 3948 color: isSaved ? "success" : "white", 3949 "data-tracking-id": "tracking-id-ai-image-generator-result-add-to-your-media", 3950 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FontAwesomeIcon, { icon: isSaved ? import_faCircleCheck.faCircleCheck : import_faPlus.faPlus }) 3951 }) 3952 }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dist$1.ThumbnailActionsButton, { 3953 sx: { 3954 pointerEvents: "auto", 3955 ...isSaved && { 3956 cursor: "default", 3957 "&:hover": { backgroundColor: "common.white" } 3958 } 3959 }, 3960 startIcon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FontAwesomeIcon, { icon: isSaved ? import_faCircleCheck.faCircleCheck : import_faPlus.faPlus }), 3961 onClick: (e) => { 3962 e.stopPropagation(); 3963 if (!isSaved) { 3964 markAsSaved(asset.id); 3965 onSaveToLibrary(asset); 3966 } 3967 }, 3968 disableRipple: isSaved, 3969 color: isSaved ? "success" : "default", 3970 variant: isSaved ? "outlined" : "contained", 3971 "data-tracking-id": "tracking-id-ai-image-generator-result-add-to-your-media", 3972 children: isSaved ? "Saved" : "Save" 3973 })] }), 3974 leftActions: !isLoading && isEditWithAiEnabled ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Tooltip, { 3975 title: getEditButtonTooltip(isAiImageEditingBlocked, isEditLoading, isGenerationProcessLoading), 3976 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dist$1.ThumbnailActionsButton, { 3977 sx: { pointerEvents: isEditLoading || isGenerationProcessLoading || isAiImageEditingBlocked ? "none" : "auto" }, 3978 disabled: isEditLoading || isGenerationProcessLoading || isAiImageEditingBlocked, 3979 onClick: (e) => { 3980 e.stopPropagation(); 3981 setEditAnchorEl(e.currentTarget); 3982 setEditPopoverImageUrl(asset.mediaUrl); 3983 setEditPopoverAspectRatio(currentAspectRatio); 3984 }, 3985 "data-tracking-id": mode === AiMediaGenerationMode.VIDEO ? "tracking-id-ai-video-generator-first-frame-edit-btn" : "tracking-id-ai-image-generator-result-edit-btn", 3986 startIcon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.SvgIcon, { 3987 fontSize: "small", 3988 color: "gradient", 3989 sx: sparklesIconSx, 3990 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FontAwesomeIcon, { icon: import_faSparkles.faSparkles }) 3991 }), 3992 children: "Edit" 3993 }) }) 3994 }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Tooltip, { 3995 title: "Preview", 3996 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dist$1.ThumbnailActionsIconButton, { 3997 sx: { pointerEvents: "auto" }, 3998 onClick: (e) => { 3999 e.stopPropagation(); 4000 onPreviewAsset(index, PreviewTrigger.BUTTON); 4001 }, 4002 "data-tracking-id": mode === AiMediaGenerationMode.VIDEO ? "tracking-id-ai-video-generator-first-frame-preview-btn" : "tracking-id-ai-image-generator-preview-btn", 4003 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FontAwesomeIcon, { icon: import_faArrowUpRightAndArrowDownLeftFromCenter.faArrowUpRightAndArrowDownLeftFromCenter }) 4004 }) 4005 }), 4006 loading: isLoading, 4007 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AssetThumbnail, { 4008 mediaType: asset?.mediaType ?? EditorLibraryMediaType.Image, 4009 thumbnailUrl: isLoading ? getAspectRatioPlaceholder(currentAspectRatio) : asset.thumbnailUrl, 4010 description: asset?.name ?? "", 4011 sx: { 4012 "& img": { borderRadius: "5px" }, 4013 "&& img": { objectFit: "cover" } 4014 }, 4015 loading: false 4016 }) 4017 }) 4018 }, index); 4019 }; 4020 return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [isEditLoading && !assets?.length ? /* @__P
4020URE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 4021 sx: getEditLoadingContainerSxProps(thumbnailDimensions), 4022 children: [ 4023 editSourceImageUrl && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { 4024 src: editSourceImageUrl, 4025 alt: "", 4026 style: { 4027 width: "100%", 4028 height: "100%", 4029 objectFit: "cover", 4030 borderRadius: BORDER_RADIUS 4031 } 4032 }), 4033 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { sx: gradientLoadingImageLayer(BORDER_RADIUS) }), 4034 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { 4035 sx: gradientLoadingImageContent, 4036 children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 4037 sx: { 4038 display: "flex", 4039 flexDirection: "column", 4040 alignItems: "center", 4041 gap: "8px" 4042 }, 4043 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Typography, { 4044 variant: "h5", 4045 sx: { 4046 color: "common.white", 4047 textAlign: "center", 4048 whiteSpace: "pre-line" 4049 }, 4050 children: currentAspectRatio === GqlClientAiGeneratedAssetAspectRatio.RATIO_9_16 ? "Applying\nchanges..." : "Applying changes..." 4051 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.LinearProgress, { 4052 variant: "determinate", 4053 value: fakeProgress, 4054 sx: { width: currentAspectRatio === GqlClientAiGeneratedAssetAspectRatio.RATIO_9_16 ? "106px" : "184px" } 4055 })] 4056 }) 4057 }) 4058 ] 4059 }) : isEditBatch && assets?.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { 4060 sx: { width: "100%" }, 4061 children: renderThumbnailItem(0) 4062 }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GridContainer, { 4063 aspectRatio: currentAspectRatio, 4064 thumbnailDimensions, 4065 children: [...Array(numberOfThumbnails).keys()].map(renderThumbnailItem) 4066 }
4066), isEditWithAiEnabled && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AiEditMediaPopover, { 4067 anchorEl: editAnchorEl, 4068 onClose: () => { 4069 setEditAnchorEl(null); 4070 }, 4071 source: AiEditPopoverSource.ImageGenerationResult, 4072 imageUrl: editPopoverImageUrl, 4073 aspectRatio: editPopoverAspectRatio 4074 })] }); 4075}; 4076var getEditButtonTooltip = (isImageEditingBlocked, isEditLoading, isGenerationProcessLoading) => { 4077 if (isImageEditingBlocked) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [ 4078 "AI image editing is disabled.", 4079 /* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {}), 4080 "Ask your account owner to enable this feature." 4081 ] }); 4082 if (isEditLoading || isGenerationProcessLoading) return `Editing isn't available while ${isGenerationProcessLoading ? "media is being generated" : "image edits are being applied"}.`; 4083 return ""; 4084}; 4085var GridContainer = (0, import_material.styled)(import_material.Box, { shouldForwardProp: (prop) => prop !== "aspectRatio" && prop !== "thumbnailDimensions" })(({ aspectRatio, thumbnailDimensions }) => { 4086 const { minWidth, maxWidth, breakpointMaxWidth, breakpointMaxHeight, aspectRatio: aspectRatioValue } = thumbnailDimensions; 4087 const columnMax = maxWidth ? `${maxWidth}px` : "1fr"; 4088 const is9x16 = aspectRatio === GqlClientAiGeneratedAssetAspectRatio.RATIO_9_16; 4089 const breakpointColumnMax = breakpointMaxHeight ? `${Math.floor(breakpointMaxHeight * aspectRatioValue)}px` : breakpointMaxWidth ? `${breakpointMaxWidth}px` : columnMax; 4090 return { 4091 display: "grid", 4092 gap: "24px", 4093 height: "fit-content", 4094 justifyContent: "center", 4095 gridTemplateColumns: is9x16 ? `repeat(4, minmax(${minWidth}px, 1fr))` : `repeat(2, minmax(${minWidth}px, ${columnMax}))`, 4096 [`@media (max-width: ${NARROW_LAYOUT_BREAKPOINT}px)`]: { gridTemplateColumns: is9x16 ? `repeat(2, minmax(${minWidth}px, ${breakpointColumnMax}))` : `repeat(1, minmax(${minWidth}px, ${breakpointColumnMax}))` }, 4097 gridAutoRows: "max-content" 4098 }; 4099}); 4100var sparklesIconSx = { 4101 "@keyframes sparklesFlip": { 4102 "0%": { transform: "rotateY(0deg)" }, 4103 "100%": { transform: "rotateY(-360deg)" } 4104 }, 4105 ".MuiButtonBase-root:hover &": { animation: "sparklesFlip 0.8s ease-in-out 1" } 4106}; 4107var getEditLoadingContainerSxProps = (dimensions) => { 4108 return dimensions.editLoadingHeight ? { 4109 height: dimensions.editLoadingHeight, 4110 width: `${dimensions.editLoadingHeight * dimensions.aspectRatio}px`, 4111 position: "relative", 4112 margin: "0 auto" 4113 } : { 4114 width: "100%", 4115 aspectRatio: `${dimensions.aspectRatio}`, 4116 position: "relative" 4117 }; 4118}; 4119var getThumbnailActionsSxProps = (dimensions) => ({ 4120 minWidth: dimensions.minWidth, 4121 ...dimensions.maxHeight && { maxHeight: dimensions.maxHeight }, 4122 width: "100%", 4123 aspectRatio: `${dimensions.aspectRatio}`, 4124 ...(dimensions.breakpointMaxWidth || dimensions.breakpointMaxHeight) && { [`@media (max-width: 1157px)`]: { 4125 ...dimensions.breakpointMaxWidth && { maxWidth: dimensions.breakpointMaxWidth }, 4126 ...dimensions.breakpointMaxHeight && { maxHeight: dimensions.breakpointMaxHeight } 4127 } } 4128}); 4129//#endregion 4130//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/screens/ImageGenerationScreen/AiGeneratorImageBatch.tsx 4131var AiGeneratorImageBatch = (0, import_react.forwardRef)(({ prompt, assets, loading, aspectRatio, assetIndexOffset, isActiveBatch, isEditBatch }, ref) => { 4132 const { mode, selectedAssetId, setSelectedAssetId, onAssetPreview, setAssetForActionId, setSelectFolderDialogOpen, addAssetToLibrary, savedAssetIds, markAsSaved } = useAiMediaGenerationContext(); 4133 const thumbnailDimensions = getThumbnailDimensions(aspectRatio); 4134 return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 4135 sx: containerSxProps, 4136 ref, 4137 "data-batch": "true", 4138 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 4139 sx: promptHeaderSxProps, 4140 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Typography, { 4141 variant: "h5", 4142 children: "Prompt" 4143 }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 4144 sx: promptRowSxProps, 4145 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Typography, { 4146 variant: "body1", 4147 children: prompt 4148 }
4148), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dist$1.TruffleIconButton, { 4149 onClick: () => void navigator.clipboard.writeText(prompt), 4150 "data-tracking-id": `tracking-id-ai-${mode === AiMediaGenerationMode.IMAGE ? "image" : "video"}-generator-result-copy-prompt-btn`, 4151 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FontAwesomeIcon, { icon: import_faCopy.faCopy }) 4152 })] 4153 })] 4154 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AiGeneratorImageGrid, { 4155 assets, 4156 loading, 4157 mode, 4158 selectedAssetId, 4159 isActiveBatch, 4160 currentAspectRatio: aspectRatio, 4161 thumbnailDimensions, 4162 isEditBatch, 4163 onSelectAsset: setSelectedAssetId, 4164 onDoubleClickAsset: (assetId, index) => { 4165 setSelectedAssetId(assetId); 4166 onAssetPreview(assetIndexOffset + index, PreviewTrigger.DOUBLE_CLICK); 4167 }, 4168 onPreviewAsset: (index, trigger) => onAssetPreview(assetIndexOffset + index, trigger), 4169 onAddToFolder: (assetId) => { 4170 setAssetForActionId(assetId); 4171 setSelectFolderDialogOpen(true); 4172 }, 4173 onSaveToLibrary: addAssetToLibrary, 4174 savedAssetIds, 4175 markAsSaved 4176 })] 4177 }); 4178}); 4179AiGeneratorImageBatch.displayName = "AiGeneratorImageBatch"; 4180var containerSxProps = { 4181 display: "flex", 4182 flexDirection: "column", 4183 width: "100%" 4184}; 4185var promptHeaderSxProps = { 4186 display: "flex", 4187 flexDirection: "column", 4188 width: "100%", 4189 gap: "4px" 4190}; 4191var promptRowSxProps = { 4192 display: "flex", 4193 flexDirection: "row", 4194 justifyContent: "space-between", 4195 alignItems: "center", 4196 paddingBottom: "12px" 4197}; 4198//#endregion 4199//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/screens/ImageGenerationScreen/ImageGenerationScreen.tsx 4200var BATCH_GAP = 64; 4201var scrollBatchIntoCenter = (container, targetEl, spacerEl) => { 4202 const freeSpace = container.clientHeight - targetEl.offsetHeight - 2 * BATCH_GAP; 4203 const peek = Math.max(32, freeSpace * .5); 4204 if (spacerEl) spacerEl.style.height = `${Math.max(0, freeSpace - peek)}px`; 4205 const delta = targetEl.getBoundingClientRect().top - container.getBoundingClientRect().top - peek - BATCH_GAP; 4206 container.scrollBy({ 4207 top: delta, 4208 behavior: "smooth" 4209 }); 4210}; 4211/** 4212* Renders the left-panel form and right-panel results for both IMAGE_GENERATE and VIDEO_SELECT_FRAME screens. 4213* Both screens share identical JSX, differentiated only by the `mode` value from context. 4214*/ 4215var ImageGenerationScreen = () => { 4216 const { mode, prompt, setPrompt, style, setStyle, aspectRatio, setAspectRatio, cameraAngle, setCameraAngle, loading, assets, allDisplayedAssets, previousBatches, currentBatchPrompt, generationFailed, errorMessage, currentAspectRatio, selectedAssetId, setSelectedAssetId, savedAssetIds, markAsSaved, setAssetForActionId, setSelectFolderDialogOpen, onAssetPreview, addAssetToLibrary, handleGenerateImage, handleModeChange, generateImageButtonColor, disabledTabConfig, isAiVideoBlocked, isAiImageBlocked, isVideoTabDisabled, handleCopilotClick, imageGenerationCost, isEditLoading, isCurrentBatchEdit, creditsBalance, openCreditsContactSalesDialog } = useAiMediaGenerationContext(); 4217 const { palette } = (0, import_material.useTheme)(); 4218 const resultsPanelRef = (0, import_react.useRef)(null); 4219 const currentBatchRef = (0, import_react.useRef)(null); 4220 const bottomSpacerRef = (0, import_react.useRef)(null); 4221 const videoStickyHeaderRef = (0, import_react.useRef)(null); 4222 const isEditWithAiEnabled = isFeatureEnabled(featureFlagConst._EDITOR_GEN_AI_EDIT_AND_CONVERT); 4223 const isVideo = mode === AiMediaGenerationMode.VIDEO; 4224 const thumbnailDimensions = getThumbnailDimensions(currentAspectRatio); 4225 const [scrollToSelectedDirection, setScrollToSelectedDirection] = (0, import_react.useState)(null); 4226 (0, import_react.useEffect)(() => { 4227 if (!isEditWithAiEnabled || previousBatches.length === 0) return; 4228 const container = resultsPanelRef.current; 4229 const currentBatch = currentBatchRef.current; 4230 if (!container || !currentBatch) return; 4231 scrollBatchIntoCenter(container, currentBatch, bottomSpacerRef.current); 4232 }, [previousBatches.length]); 4233 const checkSelectedVisibility = (0, import_react.useCallback)(() => { 4234 if (!selectedAssetId || !resultsPanelRef.current || !isEditWithAiEnabled) { 4235 setScrollToSelectedDirection(null); 4236 return; 4237 } 4238 const container = resultsPanelRef.current; 4239 const assetEl = container.querySelector(`[data-asset-id="${selectedAssetId}"]`); 4240 if (!assetEl) { 4241 setScrollToSelectedDirection(null); 4242 return; 4243 } 4244 const containerRect = container.getBoundingClientRect(); 4245 const assetRect = assetEl.getBoundingClientRect(); 4246 const visibleTop = videoStickyHeaderRef.current ? videoStickyHeaderRef.current.getBoundingClientRect().bottom : containerRect.top; 4247 if (assetRect.bottom <= visibleTop) setScrollToSelectedDirection("up"); 4248 else if (assetRect.top >= containerRect.bottom) setScrollToSelectedDirection("down"); 4249 else setScrollToSelectedDirection(null); 4250 }, [selectedAssetId]); 4251 (0, import_react.useEffect)(() => { 4252 const container = resultsPanelRef.current; 4253 if (!container) return; 4254 container.addEventListener("scroll", checkSelectedVisibility, { passive: true }); 4255 checkSelectedVisibility(); 4256 return () => container.removeEventListener("scroll", checkSelectedVisibility); 4257 }, [checkSelectedVisibility]); 4258 const scrollToSelected = () => { 4259 if (!selectedAssetId || !resultsPanelRef.current) return; 4260 const container = resultsPanelRef.current; 4261 const assetEl = container.querySelector(`[data-asset-id="${selectedAssetId}"]`); 4262 if (!assetEl) return; 4263 const batchEl = assetEl.closest("[data-batch]"); 4264 scrollBatchIntoCenter(container, window.innerWidth <= NARROW_LAYOUT_BREAKPOINT || !batchEl ? assetEl : batchEl); 4265 }; 4266 const handleGenerateClick = () => { 4267 if (!isVideo && creditsBalance <= 0) { 4268 openCreditsContactSalesDialog([GqlClientFeatureTypeDefinition.LIMIT_GENERATE_AI_ASSET_IMAGE, GqlClientFeatureTypeDefinition.LIMIT_GENERATE_AI_ASSET_VIDEO], "tracking-id-ai-media-generator-no-credits-dialog-contact-sales-btn"); 4269 return; 4270 } 4271 handleGenerateImage(); 4272 }; 4273 const hasData = !!allDisplayedAssets.length && !loading; 4274 const hasResults = !!allDisplayedAssets.length || loading; 4275 const currentBatchOffset = previousBatches.reduce((sum, b) => sum + b.assets.length, 0); 4276 const buttonText = getGenerateButtonText(mode, hasData); 4277 const generateButtonTrackingId = getGenerateButtonTrackingId(mode, hasData); 4278 const renderPreviousBatches = () => { 4279 let batchOffset = 0; 4280 return previousBatches.map((batch, batchIndex) => { 4281 const assetIndexOffset = batchOffset; 4282 batchOffset += batch.assets.length; 4283 return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AiGeneratorImageBatch, { 4284 prompt: batch.prompt, 4285 assets: batch.assets, 4286 loading: false, 4287 aspectRatio: batch.aspectRatio, 4288 assetIndexOffset, 4289 isActiveBatch: false, 4290 isEditBatch: batch.isEditBatch 4291 }
4291, batch.assets[0]?.id ?? batchIndex); 4292 }); 4293 }; 4294 return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 4295 sx: { position: "relative" }, 4296 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 4297 sx: InputBoxSxProps(true), 4298 children: [ 4299 /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 4300 sx: { 4301 display: "flex", 4302 flexDirection: "column", 4303 gap: "24px" 4304 }, 4305 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AiMediaGenerationModeToggle, { 4306 mode, 4307 onChange: handleModeChange, 4308 loading: loading || isEditLoading, 4309 disabledTabConfig, 4310 isAiVideoBlocked, 4311 isAiImageBlocked, 4312 isVideoTabDisabled 4313 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AiMediaGenerationPrompt, { 4314 mode, 4315 disabled: loading, 4316 prompt, 4317 onPromptChange: setPrompt, 4318 onCopilotClick: handleCopilotClick, 4319 textFieldSxProps 4320 })] 4321 }),
4322 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AspectRatioToggle, { 4323 mode, 4324 disabled: loading, 4325 aspectRatio, 4326 setAspectRatio, 4327 options: aspectRatioOptions 4328 }), 4329 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CameraAngleSelect, { 4330 mode, 4331 disabled: loading, 4332 cameraAngle: cameraAngles.find((option) => option.value === cameraAngle) ?? cameraAngles[0], 4333 onChange: (selectedAngle) => { 4334 const selectedOption = cameraAngles.find((option) => option.title === selectedAngle); 4335 if (selectedOption) setCameraAngle(selectedOption.value); 4336 }, 4337 options: cameraAngles 4338 }), 4339 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AiMediaGenerationStyles, { 4340 title: "Style", 4341 selectedStyleType: style, 4342 setStyle: (s) => setStyle(s), 4343 disabled: loading, 4344 styleOptions: imageStyles 4345 }) 4346 ] 4347 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { 4348 sx: imageGenerateButtonContainerSxProps, 4349 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Tooltip, { 4350 title: isEditLoading ? `${isVideo ? "Frame" : "Image"} generation isn't available while image edits are being applied.` : "", 4351 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Button, { 4352 variant: "contained", 4353 onClick: handleGenerateClick, 4354 startIcon: !loading && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FontAwesomeIcon, { icon: import_faSparkles$1.faSparkles }), 4355 disabled: !prompt?.trim() || isEditLoading, 4356 sx: { width: "100%" }, 4357 "data-tracking-id": generateButtonTrackingId, 4358 loading, 4359 color: generateImageButtonColor, 4360 children: !loading && (isVideo ? buttonText : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 4361 sx: creditsButtonContentSxProps, 4362 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Typography, { 4363 component: "span", 4364 children: buttonText 4365 }), imageGenerationCost !== null && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AiCreditsLabel, { 4366 displayMode: AiCreditsLabelDisplayMode.cost, 4367 featureName: GqlClientFeatureTypeDefinition.LIMIT_GENERATE_AI_ASSET_IMAGE, 4368 cost: imageGenerationCost, 4369 isEstimate: false, 4370 contactSalesDataTrackingId: "tracking-id-ai-image-generator-no-credits-contact-sales-btn", 4371 showTooltip: true 4372 })] 4373 })) 4374 }) }) 4375 }) 4376 })] 4377 }
4377), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 4378 sx: rightPanelWrapperSxProps, 4379 children: [!isEditWithAiEnabled && generationFailed && !loading ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 4380 sx: FailureResultsPanelSxProps, 4381 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { 4382 src: AI_error_optimized_default, 4383 alt: "Asset generation failed", 4384 width: 461, 4385 height: 127 4386 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Typography, { 4387 color: "text.primary", 4388 variant: "h3", 4389 textAlign: "center", 4390 children: errorMessage 4391 })] 4392 }) : hasResults ? isEditWithAiEnabled ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ResultsPanel, { 4393 aspectRatio: currentAspectRatio, 4394 ref: resultsPanelRef, 4395 sx: { 4396 padding: "0px 16px 0px 32px", 4397 position: "relative" 4398 }, 4399 children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 4400 sx: (0, import_dist$1.combineSxProps)(resultsPanelContentSxProps, isVideo && previousBatches.length === 0 && { gap: "8px" }, !isVideo && previousBatches.length > 0 && { paddingTop: "32px" }, previousBatches.length > 0 && { margin: 0 }), 4401 children: [
4402 isVideo && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Typography, { 4403 ref: videoStickyHeaderRef, 4404 variant: "h3", 4405 sx: videoStickyHeaderSxProps, 4406 children: "Select a frame to add motion" 4407 }), 4408 renderPreviousBatches(), 4409 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AiGeneratorImageBatch, { 4410 ref: currentBatchRef, 4411 prompt: currentBatchPrompt, 4412 assets, 4413 loading, 4414 aspectRatio: currentAspectRatio, 4415 assetIndexOffset: currentBatchOffset, 4416 isActiveBatch: true, 4417 isEditBatch: isCurrentBatchEdit 4418 }), 4419 previousBatches.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { ref: bottomSpacerRef }) 4420 ] 4421 }) 4422 }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ResultsPanel, { 4423 aspectRatio: currentAspectRatio, 4424 sx: { 4425 padding: "32px 20px 32px 32px", 4426 position: "unset" 4427 }, 4428 children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 4429 sx: legacyResultsPanelContentSxProps,
4430 children: [isVideo && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Typography, { 4431 variant: "h3", 4432 sx: { textAlign: "center" }, 4433 children: "Select a frame to add motion" 4434 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AiGeneratorImageGrid, { 4435 assets, 4436 loading, 4437 mode, 4438 selectedAssetId, 4439 isActiveBatch: true, 4440 currentAspectRatio, 4441 thumbnailDimensions, 4442 isEditBatch: false, 4443 onSelectAsset: setSelectedAssetId, 4444 onDoubleClickAsset: (assetId, index) => { 4445 setSelectedAssetId(assetId); 4446 onAssetPreview(index, PreviewTrigger.DOUBLE_CLICK); 4447 }, 4448 onPreviewAsset: (index, trigger) => onAssetPreview(index, trigger), 4449 onAddToFolder: (assetId) => { 4450 setAssetForActionId(assetId); 4451 setSelectFolderDialogOpen(true); 4452 }, 4453 onSaveToLibrary: addAssetToLibrary, 4454 savedAssetIds, 4455 markAsSaved 4456 })] 4457 }) 4458 }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { 4459 sx: InitialResultsPanelSxProps, 4460 children: !isVideo ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FontAwesomeIcon, { 4461 icon: import_faSparkles$1.faSparkles, 4462 color: palette.grey["300"] 4463 }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AiGeneratorVideoInitialState, {}) 4464 }), isEditWithAiEnabled && scrollToSelectedDirection && selectedAssetId && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Tooltip, { 4465 title: "Go to selected image", 4466 placement: "top", 4467 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dist$1.TruffleIconButton, { 4468 variant: "contained", 4469 size: "large", 4470 color: "white", 4471 onClick: scrollToSelected, 4472 sx: scrollToSelectedButtonSxProps(scrollToSelectedDirection), 4473 "data-tracking-id": `tracking-id-ai-${mode === AiMediaGenerationMode.IMAGE ? "image" : "video"}-generator-result-scroll-to-selected-btn`, 4474 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FontAwesomeIcon, { icon: scrollToSelectedDirection === "up" ? import_faArrowUp.faArrowUp : import_faArrowDown.faArrowDown }) 4475 }) 4476 })] 4477 })] }); 4478}; 4479var InitialResultsPanelSxProps = { 4480 borderRadius: "8px", 4481 backgroundColor: "other.editorBackground", 4482 flexGrow: 1, 4483 display: "flex", 4484 alignItems: "center", 4485 justifyContent: "center", 4486 "& > svg": { 4487 width: "63px", 4488 height: "63px" 4489 } 4490}; 4491var FailureResultsPanelSxProps = { 4492 display: "flex", 4493 flexDirection: "column", 4494 flexGrow: 1, 4495 justifyContent: "center", 4496 alignItems: "center", 4497 gap: "16px", 4498 backgroundColor: "other.editorBackground" 4499}; 4500var resultsPanelContentSxProps = { 4501 margin: "auto 0", 4502 display: "flex", 4503 flexDirection: "column", 4504 alignItems: "center", 4505 gap: "64px", 4506 width: "100%", 4507 maxWidth: "720px", 4508 minWidth: "min-content", 4509 alignSelf: "flex-start" 4510}; 4511var legacyResultsPanelContentSxProps = { 4512 margin: "auto 0", 4513 display: "flex", 4514 flexDirection: "column", 4515 alignItems: "center", 4516 gap: "24px", 4517 width: "100%", 4518 maxWidth: "720px", 4519 minWidth: "min-content", 4520 alignSelf: "flex-start" 4521}; 4522var textFieldSxProps = (theme) => ({ "& .MuiOutlinedInput-root": { 4523 borderRadius: "8px", 4524 border: "1px solid transparent", 4525 backgroundImage: `linear-gradient(white, white), linear-gradient(to right, ${theme.palette.brand.gradientMagentaBlue})`, 4526 backgroundOrigin: "border-box", 4527 backgroundClip: "padding-box, border-box" 4528} }); 4529var videoStickyHeaderSxProps = (theme) => ({ 4530 textAlign: "left", 4531 whiteSpace: "nowrap", 4532 position: "sticky", 4533 top: 0, 4534 zIndex: 1, 4535 alignSelf: "stretch", 4536 padding: "32px 4px 12px 4px", 4537 marginLeft: "-4px", 4538 marginRight: "-4px", 4539 backgroundColor: (0, import_material.alpha)(theme.palette.primary.light, .85), 4540 backdropFilter: "blur(5px)" 4541}); 4542var imageGenerateButtonContainerSxProps = { 4543 width: "calc(100% - 16px)", 4544 paddingTop: "8px", 4545 backgroundColor: "common.white", 4546 position: "absolute", 4547 bottom: 0 4548}; 4549var rightPanelWrapperSxProps = { 4550 position: "relative", 4551 display: "flex", 4552 flexGrow: 1, 4553 minWidth: 0 4554}; 4555var scrollToSelectedButtonSxProps = (scrollToSelectedDirection) => ({ 4556 position: "absolute", 4557 left: "50%", 4558 transform: "translateX(-50%)", 4559 ...scrollToSelectedDirection === "up" ? { top: "16px" } : { bottom: "16px" }, 4560 zIndex: 2 4561}); 4562//#endregion 4563//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/screens/VideoDefineMotionScreen/AiVideoDefineMotionStep.tsx 4564var AiVideoDefineMotionStepLeftPanel = ({ loading, motionPrompt, onMotionPromptChange, selectedDuration, onSelectedDurationChange, cameraMotion, setCameraMotion }) => { 4565 return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 4566 sx: { 4567 display: "flex", 4568 flexDirection: "column", 4569 gap: "40px" 4570 }, 4571 children: [
4572 loading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Skeleton, { 4573 variant: "rounded", 4574 width: "100%", 4575 height: "185px" 4576 }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.TextField, { 4577 label: "Describe the subjectâs motion (optional)", 4578 placeholder: "For example, the subject slowly walks forward with natural body movement", 4579 disabled: false, 4580 onChange: (event) => onMotionPromptChange(event.target.value), 4581 rows: 6, 4582 fullWidth: true, 4583 multiline: true, 4584 variant: "outlined", 4585 size: "medium", 4586 value: motionPrompt, 4587 color: "gradient", 4588 "data-tracking-id": "tracking-id-ai-video-generator-motion-prompt-field" 4589 }), 4590 /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 4591 sx: { 4592 display: "flex", 4593 justifyContent: "space-between", 4594 alignItems: "center" 4595 }, 4596 children: [loading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Skeleton, { 4597 variant: "rounded", 4598 width: "110px", 4599 height: "24px" 4600 }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Typography, { 4601 variant: "h5", 4602 children: "Video duration" 4603 }
4603), loading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Skeleton, { 4604 variant: "rounded", 4605 width: "224px", 4606 height: "40px" 4607 }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dist$1.TruffleToggleButtonGroup, { 4608 "aria-label": "multiple toggle buttons", 4609 onChange: (_, value) => onSelectedDurationChange(value), 4610 value: selectedDuration, 4611 exclusive: true, 4612 size: "large", 4613 children: [ 4614 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.ToggleButton, { 4615 value: VideoDurationEnum.FOUR_SEC, 4616 "data-tracking-id": "tracking-id-ai-video-generator-duration-4-sec-btn", 4617 children: VideoDurationEnum.FOUR_SEC 4618 }), 4619 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.ToggleButton, { 4620 value: VideoDurationEnum.SIX_SEC, 4621 "data-tracking-id": "tracking-id-ai-video-generator-duration-6-sec-btn", 4622 children: VideoDurationEnum.SIX_SEC 4623 }), 4624 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.ToggleButton, { 4625 value: VideoDurationEnum.EIGHT_SEC, 4626 "data-tracking-id": "tracking-id-ai-video-generator-duration-8-sec-btn", 4627 children: VideoDurationEnum.EIGHT_SEC 4628 }) 4629 ] 4630 })] 4631 }), 4632 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AiMediaGenerationStyles, { 4633 title: "Camera motion", 4634 selectedStyleType: cameraMotion, 4635 setStyle: setCameraMotion, 4636 styleOptions: motionStyles, 4637 wrapStyles: true, 4638 loading 4639 }) 4640 ] 4641 }); 4642}; 4643var AiVideoDefineMotionStepRightPanel = ({ imageUrl, showBlackBackground }) => { 4644 return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { 4645 sx: { 4646 display: "flex", 4647 alignItems: "center", 4648 justifyContent: "center", 4649 height: "100%", 4650 overflow: "hidden" 4651 }, 4652 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { 4653 sx: { ...showBlackBackground ? { 4654 aspectRatio: "16/9", 4655 maxHeight: "100%", 4656 maxWidth: "100%", 4657 backgroundColor: "black", 4658 display: "flex", 4659 alignItems: "center", 4660 justifyContent: "center" 4661 } : { 4662 width: "100%", 4663 height: "100%", 4664 display: "flex", 4665 alignItems: "center", 4666 justifyContent: "center" 4667 } }, 4668 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { 4669 src: imageUrl, 4670 alt: "Frame preview", 4671 style: { 4672 width: "100%", 4673 height: "100%", 4674 objectFit: "contain" 4675 } 4676 }) 4677 }) 4678 }); 4679}; 4680//#endregion 4681//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/screens/VideoDefineMotionScreen/VideoDefineMotionScreen.tsx 4682var VideoDefineMotionScreen = () => { 4683 const { motionScreenLoading, motionDescription, setMotionDescription, selectedDuration, setSelectedDuration, cameraMotion, setCameraMotion, aspectRatio, allDisplayedAssets, selectedAssetId, externalImageUrl, isExternalImageNonStandardRatio } = useAiMediaGenerationContext(); 4684 return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { 4685 sx: { position: "relative" }, 4686 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { 4687 sx: InputBoxSxProps(false), 4688 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AiVideoDefineMotionStepLeftPanel, { 4689 loading: motionScreenLoading, 4690 motionPrompt: motionDescription, 4691 onMotionPromptChange: setMotionDescription, 4692 selectedDuration, 4693 onSelectedDurationChange: setSelectedDuration, 4694 cameraMotion, 4695 setCameraMotion 4696 }) 4697 }) 4698 }
4698), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ResultsPanel, { 4699 aspectRatio, 4700 sx: { 4701 padding: "32px 20px 32px 32px", 4702 position: "unset" 4703 }, 4704 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AiVideoDefineMotionStepRightPanel, { 4705 imageUrl: getSelectedAssetUrl(allDisplayedAssets, selectedAssetId) || externalImageUrl || "", 4706 showBlackBackground: isExternalImageNonStandardRatio 4707 }) 4708 })] }); 4709}; 4710//#endregion 4711//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/screens/VideoPreviewScreen/LeaveConfirmationDialog.tsx 4712var import_faBell = require_faBell(); 4713var LeaveConfirmationDialog = ({ isDialogOpen, closeDialog, onLeaveDialog }) => { 4714 return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Dialog, { 4715 open: isDialogOpen, 4716 onClose: closeDialog, 4717 children: [ 4718 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dist$1.TruffleDialogTitle, { 4719 CloseIconButtonProps: { onClick: closeDialog }, 4720 children: "You can't refine the result if you leave now" 4721 }), 4722 /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.DialogContent, { 4723 sx: { maxWidth: "536px" }, 4724 children: [ 4725 "The AI video will continue generating in the background.", 4726 /* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {}), 4727 "Youâll be notified when itâs ready to review.", 4728 /* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {}), 4729 /* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {}), 4730 "If you leave now, you wonât be able to refine the result once itâs ready." 4731 ] 4732 }), 4733 /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dist$1.TruffleDialogActions, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Button, { 4734 "data-tracking-id": "tracking-id-ai-video-generator-close-video-generation-in-progress-confirmation-stay", 4735 onClick: closeDialog, 4736 children: "Stay" 4737 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Button, { 4738 onClick: onLeaveDialog, 4739 variant: "contained", 4740 startIcon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FontAwesomeIcon, { icon: import_faBell.faBell }), 4741 "data-tracking-id": "tracking-id-ai-video-generator-close-video-generation-in-progress-confirmation-leave", 4742 children: "Leave and notify me" 4743 })] }) 4744 ] 4745 }); 4746}; 4747//#endregion 4748//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/screens/VideoPreviewScreen/AiVideoPreviewVideoStep.tsx 4749var BORDER_RADIUS$1 = "8px"; 4750var AiVideoPreviewVideoStep = ({ loading, videoSrc, posterSrc, videoProgress, savedFolderName, isSnackbarOpen, closeSnackbar, openMoveToFolderDialog, requestId, isPortrait, showBlackBackground, isDialogOpen, closeDialog, onLeaveDialog }) => { 4751 const videoRef = (0, import_react.useRef)(null); 4752 const hasTrackedPlayRef = (0, import_react.useRef)(false); 4753 (0, import_react.useEffect)(() => { 4754 hasTrackedPlayRef.current = false; 4755 }, [videoSrc]); 4756 const folderText = savedFolderName === "Root" ? "Media library" : `"${savedFolderName || "AI Media Assets"}" folder`; 4757 return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [loading ? /* @__P
4757URE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { 4758 sx: loadingContainer(isPortrait), 4759 children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 4760 sx: showBlackBackground ? { 4761 aspectRatio: "16/9", 4762 maxHeight: "100%", 4763 maxWidth: "100%", 4764 backgroundColor: "black", 4765 position: "relative", 4766 borderRadius: BORDER_RADIUS$1 4767 } : { 4768 position: "relative", 4769 height: "100%", 4770 maxHeight: "fit-content" 4771 }, 4772 children: [ 4773 /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { 4774 src: posterSrc, 4775 alt: "Frame preview", 4776 style: { 4777 width: "100%", 4778 height: "100%", 4779 overflow: "hidden", 4780 objectFit: "contain", 4781 borderRadius: BORDER_RADIUS$1 4782 } 4783 }), 4784 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { sx: gradientImageLayer }), 4785 /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 4786 sx: gradientImageContent, 4787 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Typography, { 4788 variant: "h3", 4789 sx: { 4790 textAlign: "center", 4791 color: "common.white" 4792 }, 4793 children: [ 4794 "Generating your video...", 4795 /* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {}), 4796 "This can take up to 2 minutes" 4797 ] 4798 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.LinearProgress, { 4799 variant: "buffer", 4800 valueBuffer: 100, 4801 value: videoProgress, 4802 sx: { 4803 width: "100%", 4804 maxWidth: "428px" 4805 } 4806 })] 4807 }) 4808 ] 4809 }) 4810 }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 4811 sx: { 4812 display: "flex", 4813 flexDirection: "column", 4814 alignItems: "stretch", 4815 justifyContent: "center", 4816 gap: "16px", 4817 width: "100%", 4818 height: "100%" 4819 }, 4820 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { 4821 component: "video", 4822 controls: true, 4823 controlsList: "nodownload noplaybackrate noremoteplayback", 4824 ref: videoRef, 4825 preload: "metadata", 4826 src: videoSrc, 4827 poster: posterSrc, 4828 "data-testid": "ai-video-preview-video", 4829 "aria-label": "Generated video preview", 4830 onPlay: () => { 4831 if (hasTrackedPlayRef.current || !requestId) return; 4832 hasTrackedPlayRef.current = true; 4833 PendoService.getInstance().trackEvent("Gen AI video result played", { requestID: requestId }); 4834 }, 4835 sx: { 4836 height: "100%", 4837 width: "100%", 4838 aspectRatio: "16 / 9", 4839 borderRadius: "8px", 4840 backgroundColor: "primary.light", 4841 objectFit: "contain" 4842 } 4843 }, videoSrc || "no-src"), !videoSrc && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Typography, { 4844 variant: "caption", 4845 color: "text.secondary", 4846 sx: { textAlign: "center" }, 4847 children: "Generated video preview will appear here" 4848 })] 4849 }
4849), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Snackbar, { 4850 open: isSnackbarOpen, 4851 onClose: (_, reason) => reason !== "clickaway" && closeSnackbar(), 4852 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dist$1.TruffleAlert, { 4853 variant: "filled", 4854 severity: "success", 4855 CloseIconButtonProps: { onClick: closeSnackbar }, 4856 action: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Button, { 4857 "data-tracking-id": "tracking-id-ai-video-generator-success-snackbar-move-to-folder-btn", 4858 color: "inherit", 4859 variant: "text", 4860 size: "small", 4861 onClick: openMoveToFolderDialog, 4862 children: "Move to folder" 4863 }), 4864 children: `The AI video was saved to the ${folderText}` 4865 }) 4866 })] }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LeaveConfirmationDialog, { 4867 isDialogOpen, 4868 closeDialog, 4869 onLeaveDialog 4870 })] }); 4871}; 4872var loadingContainer = (isPortrait) => ({ 4873 display: "flex", 4874 flexDirection: "column", 4875 alignItems: "center", 4876 justifyContent: "center", 4877 gap: "16px", 4878 width: "100%", 4879 height: "100%", 4880 backgroundColor: (theme) => isPortrait ? theme.palette.primary.light : void 0, 4881 padding: isPortrait ? "32px" : void 0, 4882 borderRadius: isPortrait ? BORDER_RADIUS$1 : void 0 4883}); 4884var gradientImageLayer = { 4885 ...gradientLoadingImageLayer(BORDER_RADIUS$1), 4886 display: "flex", 4887 flexDirection: "column", 4888 alignItems: "center", 4889 justifyContent: "center" 4890}; 4891var gradientImageContent = { 4892 ...gradientLoadingImageContent, 4893 flexDirection: "column", 4894 gap: "32px", 4895 padding: "32px" 4896}; 4897//#endregion 4898//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/screens/VideoPreviewScreen/AiVideoFailureStep.tsx 4899var BORDER_RADIUS = "8px"; 4900var AiVideoFailureStep = ({ errorMessage, posterSrc, isPortrait }) => { 4901 return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { 4902 sx: videoFailureContainer(isPortrait), 4903 children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 4904 sx: { 4905 position: "relative", 4906 height: "100%", 4907 maxHeight: "fit-content" 4908 }, 4909 children: [
4910 /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { 4911 src: posterSrc, 4912 alt: "Frame preview", 4913 style: { 4914 width: "100%", 4915 height: "100%", 4916 overflow: "hidden", 4917 objectFit: "contain", 4918 borderRadius: BORDER_RADIUS 4919 } 4920 }), 4921 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { sx: staticOverlay }), 4922 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { 4923 sx: contentLayer, 4924 children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 4925 sx: { 4926 display: "flex", 4927 flexDirection: "column", 4928 alignItems: "center", 4929 gap: "16px" 4930 }, 4931 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { 4932 src: AI_error_optimized_default, 4933 alt: "Asset generation failed", 4934 style: { 4935 maxWidth: "100%", 4936 height: "auto" 4937 } 4938 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Typography, { 4939 variant: isPortrait ? "h3" : "h1", 4940 sx: { 4941 textAlign: "center", 4942 color: "common.white", 4943 whiteSpace: "pre-line" 4944 }, 4945 children: errorMessage 4946 })] 4947 }) 4948 }) 4949 ] 4950 }) 4951 }); 4952}; 4953var videoFailureContainer = (isPortrait) => ({ 4954 display: "flex", 4955 flexDirection: "column", 4956 alignItems: "center", 4957 justifyContent: "center", 4958 gap: "16px", 4959 width: "100%", 4960 height: "100%", 4961 backgroundColor: (theme) => isPortrait ? theme.palette.primary.light : void 0, 4962 padding: isPortrait ? "32px" : void 0, 4963 borderRadius: isPortrait ? BORDER_RADIUS : void 0 4964}); 4965var staticOverlay = { 4966 position: "absolute", 4967 top: 0, 4968 left: 0, 4969 width: "100%", 4970 height: "100%", 4971 backgroundColor: "rgba(0, 0, 0, 0.5)", 4972 borderRadius: BORDER_RADIUS, 4973 zIndex: 1, 4974 pointerEvents: "none" 4975}; 4976var contentLayer = { 4977 position: "absolute", 4978 display: "flex", 4979 flexDirection: "column", 4980 alignItems: "center", 4981 justifyContent: "center", 4982 top: 0, 4983 left: 0, 4984 width: "100%", 4985 height: "100%", 4986 gap: "32px", 4987 padding: "32px", 4988 zIndex: 2, 4989 pointerEvents: "none", 4990 "& > *": { pointerEvents: "auto" } 4991}; 4992//#endregion 4993//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/screens/VideoPreviewScreen/VideoPreviewScreen.tsx 4994var VideoPreviewScreen = () => { 4995 const { generationFailed, errorMessage, allDisplayedAssets, selectedAssetId, generatedAspectRatio, generatedVideoUrl, videoProgress, generatedVideoAsset, isSnackbarOpen, setIsSnackbarOpen, setVideoMoveDialogOpen, videoRequestId, isPreviewVideoStepDialogOpen, setIsPreviewVideoStepDialogOpen, isVideoPreviewStep, onCloseClick, showSnackbarOnVideoReadyRef, lastSelectedImageRef, externalImageUrl, isExternalImageNonStandardRatio } = useAiMediaGenerationContext(); 4996 const isGenerateVideoInProgress = isVideoPreviewStep && !generatedVideoUrl; 4997 const posterSrc = getSelectedAssetUrl(allDisplayedAssets, selectedAssetId) || externalImageUrl; 4998 const isPortrait = isPortraitLayout(generatedAspectRatio); 4999 if (generationFailed) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AiVideoFailureStep, { 5000 errorMessage, 5001 posterSrc, 5002 isPortrait 5003 }); 5004 return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AiVideoPreviewVideoStep, { 5005 videoSrc: generatedVideoUrl, 5006 posterSrc, 5007 loading: !generatedVideoUrl, 5008 showBlackBackground: isExternalImageNonStandardRatio, 5009 videoProgress, 5010 savedFolderName: generatedVideoAsset?.folderName, 5011 isSnackbarOpen, 5012 closeSnackbar: () => setIsSnackbarOpen(false), 5013 openMoveToFolderDialog: () => { 5014 setVideoMoveDialogOpen(true); 5015 setIsSnackbarOpen(false); 5016 }, 5017 requestId: videoRequestId ?? void 0, 5018 isPortrait, 5019 isDialogOpen: isPreviewVideoStepDialogOpen, 5020 closeDialog: () => setIsPreviewVideoStepDialogOpen(false), 5021 onLeaveDialog: () => { 5022 onCloseClick(); 5023 setIsPreviewVideoStepDialogOpen(false); 5024 if (isGenerateVideoInProgress) { 5025 showSnackbarOnVideoReadyRef.current = true; 5026 lastSelectedImageRef.current = posterSrc; 5027 } 5028 } 5029 }); 5030}; 5031//#endregion 5032//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/DialogActions/BackButton.tsx 5033var import_faArrowLeft = require_faArrowLeft(); 5034var BackButton = () => { 5035 const { mode, videoStep, generationFailed, motionScreenLoading, setVideoStep, setGenerationFailed, setErrorMessage, externalImageUrl } = useAiMediaGenerationContext(); 5036 if (!(mode === AiMediaGenerationMode.VIDEO && (videoStep === AiVideoGenerationStep.CONFIGURE_VIDEO && !externalImageUrl || videoStep === AiVideoGenerationStep.GENERATE_VIDEO && generationFailed))) return null; 5037 const onClick = () => { 5038 if (generationFailed) { 5039 setGenerationFailed(false); 5040 setErrorMessage(""); 5041 } 5042 switch (videoStep) { 5043 case AiVideoGenerationStep.CONFIGURE_VIDEO: 5044 setVideoStep(AiVideoGenerationStep.GENERATE_IMAGE); 5045 break; 5046 case AiVideoGenerationStep.GENERATE_VIDEO: 5047 setVideoStep(AiVideoGenerationStep.CONFIGURE_VIDEO); 5048 break; 5049 default: break; 5050 } 5051 }; 5052 return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Button, { 5053 color: generationFailed ? "primary" : "default", 5054 size: "large", 5055 startIcon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FontAwesomeIcon, { icon: import_faArrowLeft.faArrowLeft }), 5056 variant: "contained", 5057 onClick, 5058 "data-tracking-id": generationFailed ? "tracking-id-ai-video-generator-generate-video-error-back-to-define-motion-btn" : `tracking-id-ai-video-generator-${videoStep}-back-btn`, 5059 disabled: motionScreenLoading, 5060 children: getBackButtonText(videoStep) 5061 }); 5062}; 5063//#endregion 5064//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/DialogActions/SecondaryButton.tsx 5065var SecondaryButton = () => { 5066 const { mode, videoStep, isVideoPreviewStep, generationFailed, generatedVideoUrl, requestClose, setVideoStep } = useAiMediaGenerationContext(); 5067 if (generationFailed) return null; 5068 const isOutlined = videoStep === AiVideoGenerationStep.CONFIGURE_VIDEO || videoStep === AiVideoGenerationStep.GENERATE_VIDEO; 5069 const trackingId = getCancelButtonTrackingId(mode, videoStep); 5070 const onClick = videoStep === AiVideoGenerationStep.GENERATE_VIDEO ? () => setVideoStep(AiVideoGenerationStep.CONFIGURE_VIDEO) : requestClose; 5071 return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Button, { 5072 variant: isOutlined ? "outlined" : "text", 5073 onClick, 5074 disabled: isVideoPreviewStep && !generatedVideoUrl, 5075 "data-tracking-id": trackingId, 5076 children: isVideoPreviewStep ? "Refine video motion" : "Cancel" 5077 }); 5078}; 5079//#endregion 5080//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/DialogActions/ImageGeneratePrimaryButton.tsx 5081var ImageGeneratePrimaryButton = () => { 5082 const { loading, isGenerateFromLibrary, selectedAssetId, savedAssetIds, allDisplayedAssets, resetState, onDialogConfirmation, savedAssetEditorMediaIds, generationFailed, isEditLoading } = useAiMediaGenerationContext(); 5083 const isGenerationInProgress = loading || isEditLoading; 5084 const selectedAsset = allDisplayedAssets.find((asset) => asset.id === selectedAssetId); 5085 const isSelectedAssetAlreadySaved = isGenerateFromLibrary && savedAssetIds.has(selectedAssetId); 5086 return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Button, { 5087 variant: "contained", 5088 onClick: isGenerateFromLibrary ? () => { 5089 if (selectedAsset) handleUploadAiImageAsset({ asset: selectedAsset }); 5090 resetState(FinalStep.USE_BTN); 5091 } : () => { 5092 const editorAssetMediaId = savedAssetEditorMediaIds.get(selectedAssetId); 5093 onDialogConfirmation?.({ 5094 ...selectedAsset, 5095 ...editorAssetMediaId ? { editorAssetMediaId } : {} 5096 }); 5097 resetState(FinalStep.USE_BTN); 5098 }, 5099 disabled: !selectedAssetId || generationFailed || isGenerationInProgress || isSelectedAssetAlreadySaved, 5100 "data-tracking-id": isGenerateFromLibrary ? "tracking-id-ai-image-generator-result-preview-from-lib-save-selected-btn" : "tracking-id-ai-image-generator-use
5100-btn", 5101 children: isGenerateFromLibrary ? "Save selected" : "Use image" 5102 }); 5103}; 5104//#endregion 5105//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/DialogActions/VideoDefineMotionPrimaryButton.tsx 5106var VideoDefineMotionPrimaryButton = () => { 5107 const { onGenerateVideoClick, motionScreenLoading, selectedDuration, creditsBalance, openCreditsContactSalesDialog, isConvertToVideo } = useAiMediaGenerationContext(); 5108 const { cost: videoGenerationCost } = useCreditsCostForFeature(GqlClientFeatureTypeDefinition.LIMIT_GENERATE_AI_ASSET_VIDEO, getVideoDurationSeconds(selectedDuration)); 5109 const handleGenerateVideoClick = () => { 5110 if (creditsBalance <= 0) { 5111 const trackingId = isConvertToVideo ? "tracking-id-convert-to-video-out-of-credits-contact-sales-btn" : "tracking-id-ai-video-generator-no-credits-dialog-contact-sales-btn"; 5112 openCreditsContactSalesDialog([GqlClientFeatureTypeDefinition.LIMIT_GENERATE_AI_ASSET_VIDEO], trackingId); 5113 return; 5114 } 5115 onGenerateVideoClick(); 5116 }; 5117 return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Button, { 5118 variant: "contained", 5119 onClick: handleGenerateVideoClick, 5120 disabled: motionScreenLoading, 5121 "data-tracking-id": "tracking-id-ai-video-generator-define-motion-generate-video-btn", 5122 children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 5123 sx: creditsButtonContentSxProps, 5124 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Typography, { 5125 component: "span", 5126 children: "Generate Video" 5127 }), videoGenerationCost !== null && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AiCreditsLabel, { 5128 displayMode: AiCreditsLabelDisplayMode.cost, 5129 featureName: GqlClientFeatureTypeDefinition.LIMIT_GENERATE_AI_ASSET_VIDEO, 5130 cost: videoGenerationCost, 5131 isEstimate: false, 5132 contactSalesDataTrackingId: "tracking-id-ai-video-generator-no-credits-contact-sales-btn", 5133 showTooltip: true 5134 })] 5135 }) 5136 }); 5137}; 5138//#endregion 5139//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/DialogActions/VideoPreviewPrimaryButton.tsx 5140var VideoPreviewPrimaryButton = () => { 5141 const { generatedVideoUrl, generatedVideoAsset, isGenerateFromLibrary, onDialogConfirmation, resetState, allDisplayedAssets, selectedAssetId, selectedDuration, prompt } = useAiMediaGenerationContext(); 5142 const onClick = () => { 5143 if (!generatedVideoUrl || !generatedVideoAsset || !generatedVideoAsset?.id) return; 5144 const videoAsset = { 5145 type: ItemType.AI_VIDEO, 5146 id: generatedVideoAsset.id, 5147 editorAssetMediaId: generatedVideoAsset.id, 5148 name: generatedVideoAsset.name, 5149 mediaType: EditorLibraryMediaType.Video, 5150 mediaUrl: generatedVideoUrl, 5151 thumbnailUrl: getSelectedAssetUrl(allDisplayedAssets, selectedAssetId), 5152 service: GqlClientAiImageService.GOOGLE, 5153 prompt, 5154 duration: getVideoDurationSeconds(selectedDuration) 5155 }; 5156 onDialogConfirmation?.(videoAsset); 5157 resetState(FinalStep.USE_BTN); 5158 }; 5159 return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Button, { 5160 variant: "contained", 5161 onClick, 5162 disabled: !generatedVideoUrl, 5163 "data-tracking-id": isGenerateFromLibrary ? "tracking-id-ai-video-generator-result-preview-from-lib-done-btn" : "tracking-id-ai-video-generator-result-preview-u
5163se-video-btn", 5164 children: isGenerateFromLibrary ? "Done" : "Use video" 5165 }); 5166}; 5167//#endregion 5168//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/DialogActions/VideoSelectFramePrimaryButton.tsx 5169var import_faAngleRight = require_faAngleRight(); 5170var VideoSelectFramePrimaryButton = () => { 5171 const { loading, selectedAssetId, allDisplayedAssets, setMotionScreenLoading, setVideoStep, setMotionDescription, generationFailed, isEditLoading } = useAiMediaGenerationContext(); 5172 const [generateMotionPromptFromVideoPrompt] = useMutation(GenerateMotionPromptFromVideoPromptDocument); 5173 const onClick = async () => { 5174 setMotionScreenLoading(true); 5175 setVideoStep(AiVideoGenerationStep.CONFIGURE_VIDEO); 5176 try { 5177 const videoPrompt = allDisplayedAssets.find((asset) => asset.id === selectedAssetId)?.prompt; 5178 const response = (await generateMotionPromptFromVideoPrompt({ variables: { input: { 5179 videoPrompt, 5180 timeoutMs: 5e3 5181 } } })).data?.generateMotionPromptFromVideoPrompt; 5182 if (response?.result === GqlClientGenerateMotionPromptFromVideoPromptResult.SUCCESS) setMotionDescription(response.motionPrompt); 5183 } finally { 5184 setMotionScreenLoading(false); 5185 } 5186 }; 5187 return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Button, { 5188 variant: "contained", 5189 onClick, 5190 disabled: !selectedAssetId || generationFailed || loading || isEditLoading, 5191 endIcon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FontAwesomeIcon, { icon: import_faAngleRight.faAngleRight }), 5192 "data-tracking-id": "tracking-id-ai-video-generator-define-motion-btn", 5193 children: "Add motion to the selected frame" 5194 }); 5195}; 5196//#endregion 5197//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/DialogActions/PrimaryButton.tsx 5198var PrimaryButton = () => { 5199 const { currentScreen, generationFailed } = useAiMediaGenerationContext(); 5200 if (generationFailed) return null; 5201 switch (currentScreen) { 5202 case "IMAGE_GENERATE": return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ImageGeneratePrimaryButton, {}); 5203 case "VIDEO_FIRST_FRAME": return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(VideoSelectFramePrimaryButton, {}); 5204 case "VIDEO_DEFINE_MOTION": return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(VideoDefineMotionPrimaryButton, {}); 5205 case "VIDEO_PREVIEW": return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(VideoPreviewPrimaryButton, {}); 5206 } 5207}; 5208//#endregion 5209//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/AiMediaGenerationDialogContent.tsx 5210var AI_VIDEO = "AI Video"; 5211var AiMediaGenerationDialogContent = ({ onDialogExited }) => { 5212 const { currentScreen, mode, loading, isVideoPreviewStep, generatedVideoUrl, isDialogOpen, assetForAction, selectFolderDialogOpen, setSelectFolderDialogOpen, onMoveConfirm, generatedVideoAsset, videoMoveDialogOpen, setVideoMoveDialogOpen, isPromptDialogOpen, promptGeneratorChat, usesGeneratedPrompt, handlePromptDialogClose, handlePromptDialogInsertPrompt, previewAssetIndex, setPreviewAssetIndex, allDisplayedAssets, prompt, isLeaveConfirmationOpen, setLeaveConfirmationOpen, videoStep, assetGenerationErrorCode, setAssetGenerationErrorCode, lastOperationType, externalImageUrl, rootFolder, foldersByParentFolderId, foldersById, mediaByFolderId, requestClose, onCloseClick, creditsContactSalesDialogConfig, closeCreditsContactSalesDialog } = useAiMediaGenerationContext(); 5213 const aiCreditsFeatureName = mode === AiMediaGenerationMode.IMAGE ? GqlClientFeatureTypeDefinition.LIMIT_GENERATE_AI_ASSET_IMAGE : GqlClientFeatureTypeDefinition.LIMIT_GENERATE_AI_ASSET_VIDEO; 5214 const aiCreditsContactSalesDataTrackingId = mode === AiMediaGenerationMode.IMAGE ? "tracking-id-ai-image-generator-0-credits-contact-sales-btn" : "tracking-id-ai-video-generator-0-credits-contact-sales-btn"; 5215 const nextPreviewIndex = previewAssetIndex >= 0 ? previewAssetIndex + 1 < (allDisplayedAssets?.length ?? 0) ? previewAssetIndex + 1 : 0 : -1; 5216 const prevPreviewIndex = previewAssetIndex >= 0 ? previewAssetIndex - 1 > 0 ? previewAssetIndex - 1 : (allDisplayedAssets?.length ?? 0) - 1 : -1;
5217 const onQuestionIconClick = (event) => { 5218 openArticleInHelpCenter({ 5219 buttonId: mode === AiMediaGenerationMode.IMAGE ? "f0d100d4-a8b1-4e6b-8c7a-43ce8be4d764" : "d5534f61-1061-4815-a343-ff1388cc1f62", 5220 anchorRef: event.currentTarget, 5221 trackingSource: InAppHelpCenterTrackingSource.Editor, 5222 trackingDialogName: mode === AiMediaGenerationMode.IMAGE ? "AI Image Generator" : "AI Video Generator" 5223 }); 5224 }; 5225 return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Dialog, { 5226 onKeyDown: disableUndoKeyboardShortcuts, 5227 fullWidth: true, 5228 maxWidth: "lg", 5229 open: !!isDialogOpen, 5230 onClose: requestClose, 5231 slotProps: { 5232 paper: { sx: dialogPaperProps }, 5233 transition: { onExited: onDialogExited } 5234 }, 5235 sx: { "& .MuiDialog-container": { overflow: "hidden" } }, 5236 children: [ 5237 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dist$1.TruffleDialogTitle, { 5238 ContentBoxProps: { sx: { width: "100%" } }, 5239 CloseIconButtonProps: { 5240 onClick: requestClose, 5241 "data-tracking-id": getClosingDialogButtonTrackingId(isVideoPreviewStep, generatedVideoUrl) 5242 }, 5243 HelpCenterIconButtonProps: { onClick: onQuestionIconClick }, 5244 children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 5245 sx: { 5246 display: "flex", 5247 alignItems: "center", 5248 justifyContent: "space-between", 5249 width: "100%" 5250 }, 5251 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 5252 sx: { 5253 display: "flex", 5254 alignItems: "center", 5255 gap: "8px" 5256 }, 5257 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.SvgIcon, { 5258 fontSize: "medium", 5259 color: "gradient", 5260 children: [" ", /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FontAwesomeIcon, { icon: import_faSparkles$1.faSparkles })] 5261 }), "AI Media Generator"] 5262 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { 5263 sx: { alignSelf: "baseline" }, 5264 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AiCreditsLabel, { 5265 displayMode: AiCreditsLabelDisplayMode.balance, 5266 featureName: aiCreditsFeatureName, 5267 showTooltip: true, 5268 contactSalesDataTrackingId: aiCreditsContactSalesDataTrackingId 5269 }) 5270 })] 5271 }) 5272 }), 5273 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.DialogContent, { children: currentScreen === "VIDEO_PREVIEW" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(VideoPreviewScreen, {}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { 5274 sx: DialogContentSxProps, 5275 children: currentScreen === "VIDEO_DEFINE_MOTION" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(VideoDefineMotionScreen, {}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ImageGenerationScreen, {}) 5276 }) }), 5277 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.DialogActions, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 5278 sx: { 5279 display: "flex", 5280 alignItems: "center", 5281 justifyContent: "space-between", 5282 width: "100%" 5283 }, 5284 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_material.Box, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BackButton, {}) }
5284), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_material.Box, { 5285 sx: { 5286 display: "flex", 5287 alignItems: "center", 5288 gap: "8px" 5289 }, 5290 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SecondaryButton, {}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PrimaryButton, {})] 5291 })] 5292 }) }), 5293 assetForAction && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MoveToFolderDialog, { 5294 open: selectFolderDialogOpen, 5295 onClose: () => setSelectFolderDialogOpen(false), 5296 itemsToMoveDetails: [{ 5297 isFolder: false, 5298 id: assetForAction.id, 5299 name: assetForAction.name, 5300 typeDetails: { 5301 capitalizedTypeName: "Asset", 5302 article: "An" 5303 } 5304 }], 5305 action: MoveToFolderDialogActions.ADD, 5306 rootFolderName: "Your Media", 5307 foldersById, 5308 foldersByParentFolderId, 5309 initialFolderId: rootFolder?.id, 5310 onCreateNewFolder: createEditorAssetFolder, 5311 getFolderNameErrorMessage: validateEditedFolderName, 5312 onMoveConfirm, 5313 itemsByParentFolderId: mediaByFolderId, 5314 trackingIdentifier: "ai-image-generator", 5315 skipSameNameAssetWarning: true 5316 }), 5317 generatedVideoAsset?.id && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MoveToFolderDialog, { 5318 open: videoMoveDialogOpen, 5319 onClose: () => setVideoMoveDialogOpen(false), 5320 itemsToMoveDetails: [{ 5321 isFolder: false, 5322 id: generatedVideoAsset.id, 5323 name: generatedVideoAsset.name || AI_VIDEO, 5324 parentFolderId: generatedVideoAsset.folderId ?? void 0, 5325 typeDetails: { 5326 capitalizedTypeName: "Asset", 5327 article: "An" 5328 } 5329 }], 5330 action: MoveToFolderDialogActions.MOVE,
5331 rootFolderName: "Your Media", 5332 foldersById, 5333 foldersByParentFolderId, 5334 itemsByParentFolderId: mediaByFolderId, 5335 initialFolderId: rootFolder?.id, 5336 onCreateNewFolder: createEditorAssetFolder, 5337 getFolderNameErrorMessage: validateEditedFolderName, 5338 onMoveConfirm: async (targetFolderId) => { 5339 await moveEditorAssetToFolder(generatedVideoAsset.id, generatedVideoAsset.name || AI_VIDEO, targetFolderId, () => {}, () => {}, (folderId) => setSuccessNotification({ message: `Media asset moved to "${getFolderName(folderId) || "Your Media"}" folder` }), false); 5340 setVideoMoveDialogOpen(false); 5341 }, 5342 trackingIdentifier: "ai-video-generator", 5343 skipSameNameAssetWarning: true 5344 }), 5345 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AiImagePromptGeneratorDialog, { 5346 open: isPromptDialogOpen, 5347 chat: promptGeneratorChat, 5348 shouldConfirmClose: !usesGeneratedPrompt && promptGeneratorChat.messages.length > 1, 5349 onClose: handlePromptDialogClose, 5350 onInsertPrompt: handlePromptDialogInsertPrompt 5351 }), 5352 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AssetPreviewDialog, { 5353 name: "Preview", 5354 url: previewAssetIndex >= 0 ? allDisplayedAssets?.[previewAssetIndex]?.mediaUrl : void 0, 5355 posterUrl: previewAssetIndex >= 0 ? allDisplayedAssets?.[previewAssetIndex]?.thumbnailUrl : void 0, 5356 isVideo: false, 5357 description: prompt, 5358 open: previewAssetIndex >= 0, 5359 onClose: () => setPreviewAssetIndex(-1), 5360 hasNext: nextPreviewIndex >= 0, 5361 onNext: () => setPreviewAssetIndex(nextPreviewIndex), 5362 hasPrev: prevPreviewIndex >= 0, 5363 onPrev: () => setPreviewAssetIndex(prevPreviewIndex), 5364 PaperProps: PreviewAssetDialogPaperProps 5365 }), 5366 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AiGeneratorLeaveConfirmationDialog, { 5367 open: isLeaveConfirmationOpen, 5368 mode, 5369 loading, 5370 videoStep, 5371 onClose: () => setLeaveConfirmationOpen(false), 5372 onLeave: () => { 5373 setLeaveConfirmationOpen(false); 5374 if (mode === AiMediaGenerationMode.VIDEO || !loading) onCloseClick(); 5375 }, 5376 onStay: () => { 5377 setLeaveConfirmationOpen(false); 5378 if (mode === AiMediaGenerationMode.IMAGE && loading) onCloseClick(); 5379 } 5380 }), 5381 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AiGeneratorFailedDialog, { 5382 mode, 5383 sskyErrorCode: assetGenerationErrorCode, 5384 open: !!assetGenerationErrorCode, 5385 onClose: () => setAssetGenerationErrorCode(null), 5386 onConfirm: () => setAssetGenerationErrorCode(null), 5387 operationType: externalImageUrl ? OperationType.CONVERT : lastOperationType 5388 }) 5389 ] 5390 }), creditsContactSalesDialogConfig && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AiCreditsContactSalesDialog, { 5391 displayMode: AiCreditsContactSalesDialogDisplayMode.immediateAction, 5392 open: true, 5393 onClose: closeCreditsContactSalesDialog, 5394 immediateActionFeatures: creditsContactSalesDialogConfig.features, 5395 dataTrackingId: creditsContactSalesDialogConfig.trackingId 5396 })] }); 5397}; 5398var DialogContentSxProps = { 5399 display: "flex", 5400 flexDirection: "row", 5401 gap: "8px", 5402 flexGrow: 1, 5403 overflow: "hidden" 5404}; 5405var dialogPaperProps = (theme) => ({ 5406 height: "100%", 5407 minWidth: "700px", 5408 "& .MuiDialogContent-root": { 5409 display: "flex", 5410 flexDirection: "column" 5411 }, 5412 [theme.breakpoints.up("lg")]: { maxHeight: "868px" } 5413}); 5414//#endregion 5415//#region client/components/editor/Components/TruffleEditingWorkSpace/Components/LivePreview/Components/AiMediaGenerationDialog/AiMediaGenerationDialog.tsx 5416var AiMediaGenerationDialog = () => { 5417 const { userName } = useUserData(); 5418 const assetGenerationDialogInfo = useAiGenerationDialogOpen(); 5419 const setAssetGenerationDialogInfo = useSetAiGenerationDialogInfo(); 5420 const { isDialogOpen, externalImageUrl } = assetGenerationDialogInfo ?? {}; 5421 const [keepAlive, setKeepAlive] = (0, import_react.useState)(false); 5422 const isConvertToVideoFlow = !!externalImageUrl; 5423 const isPngImage = /\.png(\?|$)/i.test(externalImageUrl ?? ""); 5424 const { isLoadingUserAcceptedTerms, hasUserAcceptedTerms, acceptUsage } = useGenerativeAIUsageAcceptance(userName); 5425 const { balance: creditsBalance, loading: creditsBalanceLoading } = useNumericFeatureRestriction(GqlClientFeatureTypeDefinition.LIMIT_GENERATE_AI_ASSET_IMAGE); 5426 const { cost: imageGenerationCost, loading: creditsCostLoading }
5426 = useCreditsCostForFeature(GqlClientFeatureTypeDefinition.LIMIT_GENERATE_AI_ASSET_IMAGE, 1); 5427 const { cost: videoGenerationCost, loading: videoCreditsCostLoading } = useCreditsCostForFeature(GqlClientFeatureTypeDefinition.LIMIT_GENERATE_AI_ASSET_VIDEO, getVideoDurationSeconds(VideoDurationEnum.SIX_SEC)); 5428 const isLoadingAiGenRequirements = isLoadingUserAcceptedTerms || creditsCostLoading || creditsBalanceLoading || isConvertToVideoFlow && videoCreditsCostLoading; 5429 const relevantGenerationCost = isConvertToVideoFlow ? videoGenerationCost : imageGenerationCost; 5430 const hasEnoughCreditsToGenerate = creditsBalance >= relevantGenerationCost; 5431 const [isLimitedByCreditsOnOpen, setIsLimitedByCreditsOnOpen] = (0, import_react.useState)(null); 5432 const [isConvertToVideoWarningConfirmed, setIsConvertToVideoWarningConfirmed] = (0, import_react.useState)(false); 5433 const [isNonStandardAspectRatio, setIsNonStandardAspectRatio] = (0, import_react.useState)(null); 5434 const [isNonStandardRatioConfirmed, setIsNonStandardRatioConfirmed] = (0, import_react.useState)(false); 5435 (0, import_react.useEffect)(() => { 5436 if (!externalImageUrl) { 5437 setIsNonStandardAspectRatio(null); 5438 return; 5439 } 5440 return loadImageAspectRatio(externalImageUrl, (ratio) => { 5441 setIsNonStandardAspectRatio(ratio === null); 5442 }); 5443 }, [externalImageUrl]); 5444 (0, import_react.useEffect)(() => { 5445 if (isDialogOpen) { 5446 if (!isConvertToVideoFlow) setKeepAlive(true); 5447 else if (isNonStandardAspectRatio !== null) { 5448 if ((!isNonStandardAspectRatio || isNonStandardRatioConfirmed) && (!isPngImage || isNonStandardAspectRatio || isConvertToVideoWarningConfirmed)) setKeepAlive(true); 5449 } 5450 } else { 5451 setIsConvertToVideoWarningConfirmed(false); 5452 setIsNonStandardRatioConfirmed(false); 5453 } 5454 }, [ 5455 isDialogOpen, 5456 isConvertToVideoFlow, 5457 isPngImage, 5458 isConvertToVideoWarningConfirmed, 5459 isNonStandardAspectRatio, 5460 isNonStandardRatioConfirmed 5461 ]); 5462 (0, import_react.useEffect)(() => { 5463 if (assetGenerationDialogInfo?.isDialogOpen) { 5464 if (!isLoadingAiGenRequirements && isLimitedByCreditsOnOpen === null) setIsLimitedByCreditsOnOpen(!hasEnoughCreditsToGenerate); 5465 } else setIsLimitedByCreditsOnOpen(null); 5466 }, [ 5467 assetGenerationDialogInfo?.isDialogOpen, 5468 isLoadingAiGenRequirements, 5469 hasEnoughCreditsToGenerate, 5470 isLimitedByCreditsOnOpen 5471 ]); 5472 const closeDialog = () => setAssetGenerationDialogInfo(null); 5473 if (!!isDialogOpen && isLoadingAiGenRequirements) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TruffleCircularProgress, { size: 48 }); 5474 if (isLimitedByCreditsOnOpen) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AiCreditsContactSalesDialog, { 5475 displayMode: AiCreditsContactSalesDialogDisplayMode.immediateAction, 5476 open: !!assetGenerationDialogInfo?.isDialogOpen, 5477 onClose: closeDialog, 5478 immediateActionFeatures: isConvertToVideoFlow ? [GqlClientFeatureTypeDefinition.LIMIT_GENERATE_AI_ASSET_VIDEO] : [GqlClientFeatureTypeDefinition.LIMIT_GENERATE_AI_ASSET_IMAGE, GqlClientFeatureTypeDefinition.LIMIT_GENERATE_AI_ASSET_VIDEO], 5479 dataTrackingId: getContactSalesTrackingId(isConvertToVideoFlow, creditsBalance), 5480 balanceProps: { 5481 cost: relevantGenerationCost, 5482 balance: creditsBalance, 5483 action: isConvertToVideoFlow ? "generate videos" : "generate media" 5484 } 5485 }); 5486 if (!!isDialogOpen && isConvertToVideoFlow && isNonStandardAspectRatio === true && !isNonStandardRatioConfirmed) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(WarningConfirmationDialog, { 5487 open: true, 5488 title: "Video will be set to 16:9 with a black background", 5489 description: "Convert to Video supports 16:9 or 9:16 only.", 5490 secondaryButtonProps: { 5491 text: "Cancel", 5492 trackingId: "tracking-id-ai-video-generator-non-standard-ratio-cancel-btn" 5493 }, 5494 primaryButtonProps: { 5495 text: "Set to 16:9 with a black background", 5496 trackingId: "tracking-id-ai-video-generator-non-standard-ratio-confirm-btn" 5497 }, 5498 onClose: closeDialog, 5499 onConfirm: () => setIsNonStandardRatioConfirmed(true) 5500 }); 5501 if (!!isDialogOpen && isConvertToVideoFlow && isPngImage && !isConvertToVideoWarningConfirmed && isNonStandardAspectRatio === false) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(WarningConfirmationDialog, { 5502 open: true, 5503 title: "Transparent backgrounds will appear white in the final video when motion is added.", 5504 secondaryButtonProps: { 5505 text: "Cancel",
5506 trackingId: "tracking-id-convert-image-to-video-transparent-background-dialog-cancel-btn" 5507 }, 5508 primaryButtonProps: { 5509 text: "Add motion", 5510 trackingId: "tracking-id-convert-image-to-video-transparent-background-dialog-add-motion-btn" 5511 }, 5512 onClose: closeDialog, 5513 onConfirm: () => setIsConvertToVideoWarningConfirmed(true) 5514 }); 5515 if (!hasUserAcceptedTerms) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AiGeneratorTermsDialog, { 5516 open: isDialogOpen, 5517 onClose: () => closeDialog(), 5518 onAcceptTerms: acceptUsage, 5519 onCancel: closeDialog 5520 }); 5521 if (!keepAlive) return null; 5522 return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AiMediaGenerationProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AiMediaGenerationDialogContent, { onDialogExited: () => setKeepAlive(false) }) }); 5523}; 5524//#endregion 5525//#region client/components/editor/Hooks/UseEditorProgram/useEditorProgram.ts 5526var useEditorProgram = (programId) => { 5527 const { data, loading, refetch } = useEditorProgramQuery({ variables: { programId } }); 5528 const editorProgram = data?.editorProgram; 5529 return { 5530 loading: loading || !editorProgram, 5531 notFound: !loading && data?.editorProgram === null, 5532 editorProgram, 5533 refetchEditorProgram: refetch 5534 }; 5535}; 5536//#endregion 5537export { require_dist$1 as A, defaultAccessLabel as C, isGrant as D, grantAccessLevelLabel as E, processAccessPrograms as O, assetNoun as S, getInitials as T, useGenerativeAIUsageAcceptance as _, AssistantMessage as a, reloadAccountTemplates as b, getAnimationCueDisabledTooltipForPlaceholderTimingTool as c, useProjectSelectedSceneId as d, useAiVideoNotification as f, AiCreditsContactSalesDialogDisplayMode as g, AiCreditsContactSalesDialog as h, PendingAssistantMessage as i, initAIImageGenPromptChatService as k, getAspectRatioForAssetGeneration as l, generateAiImagesLegacy as m, AiMediaGenerationDialog as n, PlaceholderToolbarOffset as o, downloadGeneratedAssetAndAppendToPlaceholder as p, AiImagePromptGeneratorDialog as r, getAnimationCueDisabledTooltipForNarration as s, useEditorProgram as t, usePromptGeneratorChat as u, isAiVideoDraftVideo as v, displayUserName as w, reloadVideosAndFolderData as x, loadVideosAndFolderData as y }; 5538 5539//# sourceMappingURL=useEditorProgram.BAMpRfxw.js.map 5540//# debugId=a53a8c8b-8f8d-5405-9b10-4843fff2ff9f
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.