templates/template/reels.html.twig line 1

Open in your IDE?
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.   <meta charset="UTF-8" />
  5.   <title>Consentz Editor</title>
  6.   <meta name="viewport" content="width=device-width, initial-scale=1" />
  7.   <!-- Bootstrap 5 -->
  8.   <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
  9.    <link rel="preconnect" href="https://fonts.googleapis.com">
  10.    <link>
  11. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
  12.   <link
  13.     href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&family=Noto+Serif:ital,wght@0,100..900;1,100..900&family=Oswald:wght@200..700&display=swap"
  14.     rel="stylesheet">
  15.   <!-- GrapesJS -->
  16.   <style>
  17.     body, html {
  18.       margin: 0;
  19.       overflow-x: hidden;
  20.     }
  21.     /* Dark mode input styles */
  22.     .bg-dark input,
  23.     .bg-dark select,
  24.     .bg-dark textarea {
  25.         background-color: #1e1e1e;
  26.         color: #ffffff;
  27.         border: 1px solid #444;
  28.     }
  29.     .bg-dark input::placeholder,
  30.     .bg-dark textarea::placeholder {
  31.         color: #aaa;
  32.     }
  33.     .bg-dark .form-control:focus {
  34.         border-color: #007bff;
  35.         box-shadow: 0 0 0 0.2rem rgba(0,123,255,0.25);
  36.     }
  37.     .bg-dark .form-group,
  38.     .bg-dark .card,
  39.     .bg-dark .editor-section {
  40.         background-color: #2b2b2b;
  41.         border-color: #444;
  42.     }
  43.     .wrapper {
  44.       display: flex;
  45.       height: 100vh;
  46.       flex-direction: column;
  47.     }
  48.       .topbar {
  49.       height: 40px;
  50.       background-color: #000;
  51.       color: white;
  52.       display: flex;
  53.       align-items: center;
  54.       justify-content: space-between;
  55.       padding: 0 10px;
  56.     }
  57.     .main {
  58.       display: flex;
  59.       flex: 1;
  60.       overflow: hidden;
  61.     }
  62.     .sidebar {
  63.       width: 350px;
  64.       background-color: #000000ff;
  65.       padding: 20px;
  66.       border-right: 1px solid #000000ff;
  67.       color:white;
  68.       overflow-y:auto;
  69.     }
  70.     .content {
  71.       flex: 1;
  72.       overflow-y: auto;
  73.       padding: 20px;
  74.       background: #fff;
  75.       text-align:-webkit-center;
  76.     }
  77.     .page-header {
  78.       background-color: #343a40;
  79.       color: #fff;
  80.       padding: 20px;
  81.     }
  82.     #gjs {
  83.       min-height: 70vh;
  84.       padding: 10px;
  85.       background: #fefefe;
  86.     }
  87.     .dropdown-box a {
  88.       display: block;
  89.       padding: 6px 12px;
  90.       color: #000;
  91.       text-decoration: none;
  92.     }
  93.     .dropdown-box a:hover {
  94.       background-color: #f1f1f1;
  95.     }
  96.     #preview-options {
  97.       position: absolute;
  98.       top: 80px;
  99.       right: 40px;
  100.       background: white;
  101.       border: 1px solid rgb(221, 221, 221);
  102.       padding: 5px;
  103.       z-index: 999;
  104.       display: none;
  105.     }
  106.     button{
  107.       background-color: #000000ff;
  108.       color:#f1f1f1;
  109.       border:none;
  110.     }
  111.      .edit-button {
  112.     position: absolute;
  113.     top: 8px;
  114.     right: 0;
  115.     background-color: rgba(0, 0, 0, 0.6);
  116.     color: white;
  117.     padding: 5px 8px;
  118.     border: none;
  119.     border-radius: 4px;
  120.     font-size: 14px;
  121.     cursor: pointer;
  122.         left: 38%;
  123.     width: fit-content;
  124.   }
  125.   .editable-image {
  126.   position: relative;
  127.   display: inline-block;
  128. }  
  129. .fa-eye{
  130.   color:#f1f1f1 !important;
  131. }
  132.   </style>
  133. </head>
  134. <body>
  135. <div class="wrapper">
  136.   <!-- HEADER -->
  137.   <div class="topbar">
  138.     <div>
  139.       <strong>Consentz</strong>
  140.     </div>
  141.     <div>
  142.           <button type="button" onclick="toggleFullScreen()" title="Full Screen"><i class="fa fa-arrows-alt"></i></button>
  143.       <button type="button" title="Pages">Pages</button>
  144.       <button type="button" title="Preview"><a href="{{ path('temp_preview',{'clinic':clinic.id,'template':template.id}) }}" target="_blank"><i class="fa fa-eye"></i></a></button>
  145.       <button type="button" onclick="processVideo()" title="Save Template"><i class="fa fa-save"></i></button>
  146.     </div>
  147.   </div>
  148.   <!-- MAIN -->
  149.   <div class="main">
  150.     <!-- Sidebar -->
  151.     <!-- Content -->
  152.     <div class="content">
  153.                 <div id="alerts-container"></div>
  154.       <div id="gjs">{{ template.body|raw }}</div>
  155.       <!-- Preview Dropdown -->
  156.       <div id="preview-options">
  157.         <div class="dropdown-link">
  158.           <div class="dropdown-content">
  159.             {% for key, allTemplate in allTemplates %}
  160.               {% if allTemplate.id != template.id %}
  161.                 <div class="dropdown-box">
  162.                   <a href="{{ path('temp_index', { 'clinic': clinic.id, 'template': allTemplate.id }) }}">
  163.                     Page {{ key + 1 }}
  164.                   </a>
  165.                 </div>
  166.               {% endif %}
  167.             {% endfor %}
  168.           </div>
  169.         </div>
  170.       </div>
  171.     </div>
  172.   <div class="sidebar bg-dark text-white ">
  173.       <h4 class="text-white">Style Manager</h4>
  174.       <p>Select an element before using</p>
  175.       <form id="text-image-form" style="display:none;">
  176.        <div>
  177.        <button class="btn btn-primary" type="button" onclick="generateTextImage(this)">Submit</button>
  178.        </div>
  179.        
  180.           <div class="accordion" id="styleAccordion">
  181.               <!-- 1. Text Content -->
  182.               <div class="accordion-item bg-dark text-white border-0">
  183.                   <h2 class="accordion-header" id="headingText">
  184.                       <button class="accordion-button bg-dark text-white collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseText" aria-expanded="true" aria-controls="#collapseText">
  185.                           <i class="bi bi-type-bold me-2"></i>Text Content
  186.                       </button>
  187.                   </h2>
  188.                   <div id="collapseText" class="accordion-collapse collapse show" >
  189.                       <div class="accordion-body">
  190.                           <div class="mb-3">
  191.                               <textarea class="form-control form-control-lg"   rows="4"
  192.                                   placeholder="Enter your text here..." required
  193.                                   style="resize: vertical; min-height: 100px;" id="modal-text">Hello</textarea>
  194.                               <p>This text will appear as an overlay on your video</p>
  195.                           </div>
  196.                       </div>
  197.                   </div>
  198.               </div>
  199.               <!-- 2. Typography -->
  200.               <div class="accordion-item bg-dark text-white border-0">
  201.                   <h2 class="accordion-header" id="headingTypography">
  202.                       <button class="accordion-button bg-dark text-white collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseTypography" aria-expanded="true" aria-controls="#collapseTypography">
  203.                           <i class="bi bi-fonts me-2"></i>Typography
  204.                       </button>
  205.                   </h2>
  206.                   <div id="collapseTypography" class="accordion-collapse collapse" >
  207.                       <div class="accordion-body">
  208.                           {# Place your Typography section here #}
  209.                             <div class="row mb-3">
  210.                               <div class="col-md-6">
  211.                                   <label for="modal-fontType" class="form-label fw-semibold">Font Source</label>
  212.                                   <select class="form-select" id="modal-fontType" onchange="handleModalFontTypeChange(this)">
  213.                                       <option value="google">Google Fonts</option>
  214.                                       <option value="upload">Custom Font Upload</option>
  215.                                   </select>
  216.                               </div>
  217.                               <div class="col-md-6" id="modal-google-font-section">
  218.                                   <label for="modal-googleFont" class="form-label fw-semibold">Google Font</label>
  219.                                   <select class="form-select" id="modal-googleFont">
  220.                                       <option value="Roboto">Roboto (Default)</option>
  221.                                       <option value="Open Sans">Open Sans</option>
  222.                                       <option value="Lato">Lato</option>
  223.                                       <option value="Montserrat">Montserrat</option>
  224.                                       <option value="Oswald">Oswald</option>
  225.                                       <option value="Source Sans Pro">Source Sans Pro</option>
  226.                                       <option value="Raleway">Raleway</option>
  227.                                       <option value="Poppins">Poppins</option>
  228.                                       <option value="Nunito">Nunito</option>
  229.                                       <option value="Playfair Display">Playfair Display</option>
  230.                                       <option value="Inter">Inter</option>
  231.                                       <option value="Roboto Slab">Roboto Slab</option>
  232.                                   </select>
  233.                               </div>
  234.                               <div class="col-12 mt-3" id="modal-font-upload-section" style="display: none;">
  235.                                   <label for="modal-fontFile" class="form-label fw-semibold">Upload Font File</label>
  236.                                   <input type="file" class="form-control" id="modal-fontFile" accept=".ttf,.otf,.woff,.woff2">
  237.                                   <div class="form-text">Supported formats: TTF, OTF, WOFF, WOFF2</div>
  238.                               </div>
  239.                           </div>
  240.                           <!-- Font Size & Colors -->
  241.                           <div class="row mb-3">
  242.                               <div class="col-md-6">
  243.                                   <label for="modal-fontSize" class="form-label fw-semibold">Font Size</label>
  244.                                   <div class="input-group">
  245.                                       <input type="range" class="form-range" id="modal-fontSize-range"
  246.                                           min="8" max="200"  oninput="updateFontSizeInput(this.value)">
  247.                                       <input type="number" class="form-control form-control-sm" id="modal-fontSize"
  248.                                           min="8" max="200"  style="max-width: 80px;"
  249.                                           oninput="updateFontSizeRange(this.value)">
  250.                                       <span class="input-group-text">px</span>
  251.                                   </div>
  252.                               </div>
  253.                               <div class="col-md-6">
  254.                                   <label for="modal-fontColor" class="form-label fw-semibold">Text Color</label>
  255.                                   <div class="input-group">
  256.                                       <input type="color" class="form-control form-control-color" id="modal-fontColor"
  257.                                           title="Choose text color">
  258.                                       <input type="text" class="form-control form-control-sm" id="modal-fontColor-text"
  259.                                             maxlength="7"
  260.                                           oninput="updateColorFromText('fontColor', this.value)">
  261.                                   </div>
  262.                               </div>
  263.                               <div class="col-md-6">
  264.                                   <label for="modal-backgroundColor" class="form-label fw-semibold">Background</label>
  265.                                   <div class="input-group">
  266.                                       <input type="color" class="form-control form-control-color" id="modal-backgroundColor"
  267.                                           title="Choose background color">
  268.                                       <input type="text" class="form-control form-control-sm" id="modal-backgroundColor-text"
  269.                                           placeholder="transparent"
  270.                                           oninput="updateColorFromText('backgroundColor', this.value)">
  271.                                   </div>
  272.                                   <div class="form-check mt-2">
  273.                                       <input class="form-check-input" type="checkbox" id="modal-transparentBg" checked>
  274.                                       <label class="form-check-label" for="modal-transparentBg">Transparent</label>
  275.                                   </div>
  276.                               </div>
  277.                           </div>
  278.                           <!-- Text Spacing -->
  279.                           <div class="row">
  280.                               <div class="col-md-6">
  281.                                   <label for="modal-letterSpacing" class="form-label fw-semibold">Letter Spacing</label>
  282.                                   <div class="input-group">
  283.                                       <input type="range" class="form-range" id="modal-letterSpacing-range"
  284.                                           min="0" max="50"  oninput="updateInputFromRange('letterSpacing', this.value)">
  285.                                       <input type="number" class="form-control form-control-sm" id="modal-letterSpacing"
  286.                                           min="0" max="50"  style="max-width: 80px;">
  287.                                       <span class="input-group-text">px</span>
  288.                                   </div>
  289.                               </div>
  290.                               <div class="col-md-6">
  291.                                   <label for="modal-lineHeight" class="form-label fw-semibold">Line Height</label>
  292.                                   <div class="input-group">
  293.                                       <input type="range" class="form-range" id="modal-lineHeight-range"
  294.                                           min="0.5" max="3" step="0.1"  oninput="updateInputFromRange('lineHeight', this.value)">
  295.                                       <input type="number" class="form-control form-control-sm" id="modal-lineHeight"
  296.                                           min="0.5" max="3" step="0.1"  style="max-width: 80px;">
  297.                                   </div>
  298.                               </div>
  299.                               <div class="col-md-6">
  300.                                   <label for="modal-rotation" class="form-label fw-semibold">Rotation</label>
  301.                                   <div class="input-group">
  302.                                       <input type="range" class="form-range" id="modal-rotation-range"
  303.                                           min="-360" max="360"  oninput="updateInputFromRange('rotation', this.value)">
  304.                                       <input type="number" class="form-control form-control-sm" id="modal-rotation"
  305.                                           min="-360" max="360"  style="max-width: 80px;">
  306.                                       <span class="input-group-text">°</span>
  307.                                   </div>
  308.                               </div>
  309.                           </div>
  310.                       </div>
  311.                   </div>
  312.               </div>
  313.               <!-- 3. Layout & Positioning -->
  314.               <div class="accordion-item bg-dark text-white border-0">
  315.                   <h2 class="accordion-header" id="headingLayout">
  316.                       <button class="accordion-button bg-dark text-white collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseLayout" aria-expanded="true" aria-controls="#collapseLayout">
  317.                           <i class="bi bi-grid-3x3 me-2"></i>Layout & Positioning
  318.                       </button>
  319.                   </h2>
  320.                   <div id="collapseLayout" class="accordion-collapse collapse">
  321.                       <div class="accordion-body">
  322.                           {# Place your Layout & Positioning section here #}
  323.                           <div class="row mb-3">
  324.                               <div class="col-md-12">
  325.                                   <label class="form-label fw-semibold">Text Alignment</label>
  326.                                   <div class="btn-group w-100" role="group" aria-label="Text alignment">
  327.                                       <input type="radio" class="btn-check" name="textAlign" id="align-left" value="left">
  328.                                       <label class="btn btn-outline-primary" for="align-left">
  329.                                           <i class="bi bi-text-left"></i> Left
  330.                                       </label>
  331.                                       <input type="radio" class="btn-check" name="textAlign" id="align-center" value="center" checked>
  332.                                       <label class="btn btn-outline-primary" for="align-center">
  333.                                           <i class="bi bi-text-center"></i> Center
  334.                                       </label>
  335.                                       <input type="radio" class="btn-check" name="textAlign" id="align-right" value="right">
  336.                                       <label class="btn btn-outline-primary" for="align-right">
  337.                                           <i class="bi bi-text-right"></i> Right
  338.                                       </label>
  339.                                   </div>
  340.                               </div>
  341.                               <div class="col-md-12 pt-2">
  342.                                   <label class="form-label fw-semibold">Vertical Position</label>
  343.                                   <div class="btn-group w-100" role="group" aria-label="Vertical alignment">
  344.                                       <input type="radio" class="btn-check" name="verticalAlign" id="valign-top" value="top">
  345.                                       <label class="btn btn-outline-secondary" for="valign-top">
  346.                                           <i class="bi bi-align-top"></i> Top
  347.                                       </label>
  348.                                       <input type="radio" class="btn-check" name="verticalAlign" id="valign-middle" value="middle" checked>
  349.                                       <label class="btn btn-outline-secondary" for="valign-middle">
  350.                                           <i class="bi bi-align-middle"></i> Middle
  351.                                       </label>
  352.                                       <input type="radio" class="btn-check" name="verticalAlign" id="valign-bottom" value="bottom">
  353.                                       <label class="btn btn-outline-secondary" for="valign-bottom">
  354.                                           <i class="bi bi-align-bottom"></i> Bottom
  355.                                       </label>
  356.                                   </div>
  357.                               </div>
  358.                           </div>
  359.                           <!-- Dimensions -->
  360.                           <div class="row mb-3">
  361.                               <div class="col-md-6 pt-2">
  362.                                   <label for="modal-width" class="form-label fw-semibold">Width</label>
  363.                                   <div class="input-group">
  364.                                       <input type="number" class="form-control" id="modal-width" placeholder="Auto" min="1" >
  365.                                       <span class="input-group-text">px</span>
  366.                                   </div>
  367.                               </div>
  368.                               <div class="col-md-6 pt-2">
  369.                                   <label for="modal-height" class="form-label fw-semibold">Height</label>
  370.                                   <div class="input-group">
  371.                                       <input type="number" class="form-control" id="modal-height" placeholder="Auto" min="1">
  372.                                       <span class="input-group-text">px</span>
  373.                                   </div>
  374.                               </div>
  375.                               <div class="col-md-6 pt-2">
  376.                                   <label for="modal-padding" class="form-label fw-semibold">Padding</label>
  377.                                   <div class="input-group">
  378.                                       <input type="number" class="form-control" id="modal-padding"  min="0">
  379.                                       <span class="input-group-text">px</span>
  380.                                   </div>
  381.                               </div>
  382.                           </div>
  383.                           <!-- Text Options -->
  384.                           <div class="row">
  385.                               <div class="col-md-12 pt-2">
  386.                                   <label for="modal-maxWidth" class="form-label fw-semibold">Max Width</label>
  387.                                   <div class="input-group">
  388.                                       <input type="number" class="form-control" id="modal-maxWidth"  min="100">
  389.                                       <span class="input-group-text">px</span>
  390.                                   </div>
  391.                               </div>
  392.                               <div class="col-md-12 pt-2">
  393.                                   <label class="form-label fw-semibold">Text Options</label>
  394.                                   <div class="d-flex gap-3">
  395.                                       <div class="form-check">
  396.                                           <input class="form-check-input" type="checkbox" id="modal-wordWrap">
  397.                                           <label class="form-check-label" for="modal-wordWrap">Word Wrap</label>
  398.                                       </div>
  399.                                       <div class="form-check">
  400.                                           <input class="form-check-input" type="radio" name="orientation" id="modal-horizontal" value="horizontal" checked>
  401.                                           <label class="form-check-label" for="modal-horizontal">Horizontal</label>
  402.                                       </div>
  403.                                       <div class="form-check">
  404.                                           <input class="form-check-input" type="radio" name="orientation" id="modal-vertical" value="vertical">
  405.                                           <label class="form-check-label" for="modal-vertical">Vertical</label>
  406.                                       </div>
  407.                                   </div>
  408.                               </div>
  409.                           </div>
  410.                       </div>
  411.                   </div>
  412.               </div>
  413.               <!-- 4. Effects & Styling -->
  414.               <div class="accordion-item bg-dark text-white border-0">
  415.                   <h2 class="accordion-header" id="headingEffects">
  416.                       <button class="accordion-button bg-dark text-white collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseEffects"  aria-expanded="true" aria-controls="#collapseEffects">
  417.                           <i class="bi bi-magic me-2"></i>Effects & Styling
  418.                       </button>
  419.                   </h2>
  420.                   <div id="collapseEffects" class="accordion-collapse collapse" >
  421.                       <div class="accordion-body">
  422.                           {# Place your Effects section here #}
  423.                         <div class="row mb-3">
  424.                               <div class="col-md-6">
  425.                                   <div class="form-check form-switch">
  426.                                       <input class="form-check-input" type="checkbox" id="modal-shadow">
  427.                                       <label class="form-check-label fw-semibold" for="modal-shadow">
  428.                                           <i class="bi bi-droplet-half me-1"></i>Text Shadow
  429.                                       </label>
  430.                                   </div>
  431.                               </div>
  432.                               <div class="col-md-6">
  433.                                   <div class="form-check form-switch">
  434.                                       <input class="form-check-input" type="checkbox" id="modal-border">
  435.                                       <label class="form-check-label fw-semibold" for="modal-border">
  436.                                           <i class="bi bi-border-all me-1"></i>Text Border
  437.                                       </label>
  438.                                   </div>
  439.                               </div>
  440.                               <div class="col-md-6">
  441.                                   <div class="form-check form-switch">
  442.                                       <input class="form-check-input" type="checkbox" id="modal-gradient">
  443.                                       <label class="form-check-label fw-semibold" for="modal-gradient">
  444.                                           <i class="bi bi-palette me-1"></i>Gradient
  445.                                       </label>
  446.                                   </div>
  447.                               </div>
  448.                           </div>
  449.                           <!-- Shadow Settings -->
  450.                           <div id="shadow-settings" style="display: none;">
  451.                               <div class="alert alert-light border-start border-3 bg-dark text-white ">
  452.                                   <h6 class="alert-heading">Shadow Settings</h6>
  453.                                   <div class="row g-2">
  454.                                       <div class="col-md-6">
  455.                                           <label for="modal-shadowColor" class="form-label">Color</label>
  456.                                           <input type="color" class="form-control form-control-color" id="modal-shadowColor">
  457.                                       </div>
  458.                                       <div class="col-md-6">
  459.                                           <label for="modal-shadowOffsetX" class="form-label">Offset X</label>
  460.                                           <input type="number" class="form-control form-control-sm" id="modal-shadowOffsetX" >
  461.                                       </div>
  462.                                       <div class="col-md-6">
  463.                                           <label for="modal-shadowOffsetY" class="form-label">Offset Y</label>
  464.                                           <input type="number" class="form-control form-control-sm" id="modal-shadowOffsetY">
  465.                                       </div>
  466.                                       <div class="col-md-6">
  467.                                           <label for="modal-shadowBlur" class="form-label">Blur</label>
  468.                                           <input type="range" class="form-range" id="modal-shadowBlur" min="0" max="20" >
  469.                                       </div>
  470.                                   </div>
  471.                               </div>
  472.                           </div>
  473.                           <!-- Border Settings -->
  474.                           <div id="border-settings" style="display: none;">
  475.                               <div class="alert alert-light border-start border-3 bg-dark text-white ">
  476.                                   <h6 class="alert-heading">Border Settings</h6>
  477.                                   <div class="row g-2">
  478.                                       <div class="col-md-6">
  479.                                           <label for="modal-borderColor" class="form-label">Color</label>
  480.                                           <input type="color" class="form-control form-control-color" id="modal-borderColor">
  481.                                       </div>
  482.                                       <div class="col-md-6">
  483.                                           <label for="modal-borderWidth" class="form-label">Width</label>
  484.                                           <input type="range" class="form-range" id="modal-borderWidth" min="1" max="20" >
  485.                                       </div>
  486.                                   </div>
  487.                               </div>
  488.                           </div>
  489.                           <!-- Gradient Settings -->
  490.                           <div id="gradient-settings" style="display: none;">
  491.                               <div class="alert alert-light border-start border-3 bg-dark text-white ">
  492.                                   <h6 class="alert-heading">Gradient Settings</h6>
  493.                                   <div class="row g-2">
  494.                                       <div class="col-md-6">
  495.                                           <label for="modal-gradientFrom" class="form-label">From Color</label>
  496.                                           <input type="color" class="form-control form-control-color" id="modal-gradientFrom" >
  497.                                       </div>
  498.                                       <div class="col-md-6">
  499.                                           <label for="modal-gradientTo" class="form-label">To Color</label>
  500.                                           <input type="color" class="form-control form-control-color" id="modal-gradientTo" >
  501.                                       </div>
  502.                                       <div class="col-md-6">
  503.                                           <label for="modal-gradientDirection" class="form-label">Direction</label>
  504.                                           <select class="form-select form-select-sm" id="modal-gradientDirection">
  505.                                               <option value="horizontal">Horizontal</option>
  506.                                               <option value="vertical" selected>Vertical</option>
  507.                                               <option value="diagonal">Diagonal</option>
  508.                                           </select>
  509.                                       </div>
  510.                                   </div>
  511.                               </div>
  512.                           </div>
  513.                           <!-- Opacity -->
  514.                           <div class="mt-3">
  515.                               <label for="modal-opacity" class="form-label fw-semibold">Overall Opacity</label>
  516.                               <div class="d-flex align-items-center gap-3">
  517.                                   <input type="range" class="form-range flex-grow-1" id="modal-opacity"
  518.                                       min="0" max="1" step="0.1" value="1.0" oninput="updateOpacityDisplay(this.value)">
  519.                                   <span class="badge bg-secondary" id="opacity-display">100%</span>
  520.                               </div>
  521.                           </div>
  522.                       </div>
  523.                   </div>
  524.               </div>
  525.               <!-- 5. Video & Styling -->
  526.               <div class="accordion-item bg-dark text-white border-0" style="display:none;">
  527.                   <h2 class="accordion-header" id="headingVideoData">
  528.                       <button class="accordion-button bg-dark text-white collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseVideo" aria-expanded="true" aria-controls="#collapseVideo">
  529.                           <i class="bi bi-grid-3x3 me-2"></i>Video Overlay Options
  530.                       </button>
  531.                   </h2>
  532.                   <div id="collapseVideo" class="accordion-collapse collapse">
  533.                       <div class="accordion-body">
  534.                       <div class="row g-4">
  535.                             <div class="col-md-12">
  536.                                 <div class="card border-0 shadow-sm  bg-dark text-white">
  537.                                     <div class="card-header">
  538.                                         <h6 class="mb-0">
  539.                                             <i class="bi bi-clock me-2"></i>Timing Settings
  540.                                         </h6>
  541.                                     </div>
  542.                                     <div class="card-body">
  543.                                         <div class="mb-3">
  544.                                             <label for="modal-startTime" class="form-label fw-semibold">Start Time (seconds)</label>
  545.                                             <input type="number" class="form-control" id="modal-startTime" min="0" step="0.1" value="0">
  546.                                             <p>When to start showing this overlay</p>
  547.                                         </div>
  548.                                         <div class="mb-3">
  549.                                             <label for="modal-endTime" class="form-label fw-semibold">End Time (seconds)</label>
  550.                                             <input type="number" class="form-control" id="modal-endTime" min="0" step="0.1" value="5">
  551.                                             <p>When to stop showing this overlay (leave empty for entire video)</p>
  552.                                         </div>
  553.                                         <div class="mb-3">
  554.                                             <label for="modal-duration" class="form-label fw-semibold">Duration</label>
  555.                                             <input type="text" class="form-control" id="modal-duration" readonly>
  556.                                             <p>Calculated duration of overlay</p>
  557.                                         </div>
  558.                                     </div>
  559.                                 </div>
  560.                             </div>
  561.                             <div class="col-md-12">
  562.                                 <div class="card border-0 shadow-sm  bg-dark text-white">
  563.                                     <div class="card-header">
  564.                                         <h6 class="mb-0 text-primary">
  565.                                             <i class="bi bi-pin-map me-2"></i>Position Settings
  566.                                         </h6>
  567.                                     </div>
  568.                                     <div class="card-body">
  569.                                         <div class="mb-3">
  570.                                             <label class="form-label fw-semibold">Position Preset</label>
  571.                                             <div class="row g-2">
  572.                                                 <div class="col-6">
  573.                                                     <input type="radio" class="btn-check" name="position" id="pos-top-left" value="top-left" checked>
  574.                                                     <label class="btn btn-outline-primary btn-sm w-100" for="pos-top-left">↖ Top Left</label>
  575.                                                 </div>
  576.                                                 <div class="col-6">
  577.                                                     <input type="radio" class="btn-check" name="modal-position" id="pos-top-center" value="top-center">
  578.                                                     <label class="btn btn-outline-primary btn-sm w-100" for="pos-top-center">↑ Top Center</label>
  579.                                                 </div>
  580.                                                 <div class="col-6">
  581.                                                     <input type="radio" class="btn-check" name="position" id="pos-top-right" value="top-right">
  582.                                                     <label class="btn btn-outline-primary btn-sm w-100" for="pos-top-right">↗ Top Right</label>
  583.                                                 </div>
  584.                                                 <div class="col-6">
  585.                                                     <input type="radio" class="btn-check" name="position" id="pos-center-left" value="center-left">
  586.                                                     <label class="btn btn-outline-primary btn-sm w-100" for="pos-center-left">← Left</label>
  587.                                                 </div>
  588.                                                 <div class="col-6">
  589.                                                     <input type="radio" class="btn-check" name="position" id="pos-center" value="center">
  590.                                                     <label class="btn btn-outline-primary btn-sm w-100" for="pos-center">⊙ Center</label>
  591.                                                 </div>
  592.                                                 <div class="col-6">
  593.                                                     <input type="radio" class="btn-check" name="position" id="pos-center-right" value="center-right">
  594.                                                     <label class="btn btn-outline-primary btn-sm w-100" for="pos-center-right">→ Right</label>
  595.                                                 </div>
  596.                                                 <div class="col-6">
  597.                                                     <input type="radio" class="btn-check" name="position" id="pos-bottom-left" value="bottom-left">
  598.                                                     <label class="btn btn-outline-primary btn-sm w-100" for="pos-bottom-left">↙ Bottom Left</label>
  599.                                                 </div>
  600.                                                 <div class="col-6">
  601.                                                     <input type="radio" class="btn-check" name="position" id="pos-bottom-center" value="bottom-center">
  602.                                                     <label class="btn btn-outline-primary btn-sm w-100" for="pos-bottom-center">↓ Bottom Center</label>
  603.                                                 </div>
  604.                                                 <div class="col-6">
  605.                                                     <input type="radio" class="btn-check" name="position" id="pos-bottom-right" value="bottom-right">
  606.                                                     <label class="btn btn-outline-primary btn-sm w-100" for="pos-bottom-right">↘ Bottom Right</label>
  607.                                                 </div>
  608.                                             </div>
  609.                                         </div>
  610.                                         <div class="mb-3">
  611.                                             <label for="video-customPosition" class="form-label fw-semibold">Custom Position (x:y)</label>
  612.                                             <input type="text" class="form-control" id="modal-customPosition" placeholder="e.g., 100:50">
  613.                                             <small class="text-muted">Override preset with custom coordinates</small>
  614.                                         </div>
  615.                                     </div>
  616.                                 </div>
  617.                             </div>
  618.                         </div>
  619.                       </div>
  620.                   </div>
  621.               </div>         
  622.           </div>
  623.       </form>
  624.   </div>
  625.   </div>
  626. </div>
  627.     <div class="modal fade" id="loadingModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1">
  628.         <div class="modal-dialog modal-dialog-centered">
  629.             <div class="modal-content border-0 shadow">
  630.                 <div class="modal-body text-center p-5">
  631.                     <div class="spinner-border text-primary mb-3" role="status" style="width: 3rem; height: 3rem;">
  632.                         <span class="visually-hidden">Loading...</span>
  633.                     </div>
  634.                     <h5 id="loading-text">Processing your request...</h5>
  635.                     <p class="text-muted mb-0" id="loading-subtext">Please wait while we process your request</p>
  636.                 </div>
  637.             </div>
  638.         </div>
  639.     </div>
  640. <style>
  641. body{
  642.   display:block !important;
  643. }
  644. </style>
  645. <!-- Scripts -->
  646. <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
  647. <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
  648. </body>
  649. </html>
  650. <script>
  651.     function handleModalFontTypeChange(selectElement) {
  652.         const googleSection = document.getElementById('modal-google-font-section');
  653.         const uploadSection = document.getElementById('modal-font-upload-section');
  654.         const isGoogle = selectElement.value === 'google';
  655.         googleSection.style.display = isGoogle ? 'block' : 'none';
  656.         uploadSection.style.display = isGoogle ? 'none' : 'block';
  657.     }
  658.     function updateFontSizeInput(value) {
  659.         document.getElementById('modal-fontSize').value = value;
  660.     }
  661.     function updateFontSizeRange(value) {
  662.         document.getElementById('modal-fontSize-range').value = value;
  663.     }
  664.     function updateColorFromText(type, value) {
  665.         const colorInput = document.getElementById(`modal-${type}`);
  666.         if (/^#([0-9A-F]{3}){1,2}$/i.test(value)) {
  667.             colorInput.value = value;
  668.         }
  669.     }
  670.     function updateInputFromRange(id, value) {
  671.         const input = document.getElementById(`modal-${id}`);
  672.         input.value = value;
  673.     }
  674.     function updateOpacityDisplay(value) {
  675.         const percent = Math.round(value * 100);
  676.         document.getElementById('opacity-display').innerText = `${percent}%`;
  677.     }
  678.     // Show loading modal
  679.     function showLoading(title, subtitle) {
  680.         $('#loading-text').text(title);
  681.         $('#loading-subtext').text(subtitle);
  682.         $('#loadingModal').modal('show');
  683.     }
  684.     // Hide loading modal
  685.     function hideLoading() {
  686.         console.log('hideLoading() called');
  687.     
  688.         // Multiple approaches to ensure modal is hidden
  689.         $('#loadingModal').modal('hide');
  690.     
  691.         // Force hide with direct manipulation
  692.         $('#loadingModal').removeClass('show').addClass('fade');
  693.         $('#loadingModal').attr('aria-hidden', 'true');
  694.         $('#loadingModal').css('display', 'none');
  695.     
  696.         // Force hide backdrop if it's stuck
  697.         $('.modal-backdrop').remove();
  698.         $('body').removeClass('modal-open').css('overflow', '').css('padding-right', '');
  699.     
  700.         // Extra safety timeout
  701.         setTimeout(function() {
  702.             $('#loadingModal').hide();
  703.             $('.modal-backdrop').remove();
  704.             $('body').removeClass('modal-open').css('overflow', '').css('padding-right', '');
  705.         }, 100);
  706.     }
  707.     // Show/hide settings
  708.     document.addEventListener('DOMContentLoaded', () => {
  709.         const toggles = [
  710.             { id: 'modal-shadow', target: 'shadow-settings' },
  711.             { id: 'modal-border', target: 'border-settings' },
  712.             { id: 'modal-gradient', target: 'gradient-settings' }
  713.         ];
  714.         toggles.forEach(toggle => {
  715.             const checkbox = document.getElementById(toggle.id);
  716.             const targetDiv = document.getElementById(toggle.target);
  717.             checkbox.addEventListener('change', () => {
  718.                 targetDiv.style.display = checkbox.checked ? 'block' : 'none';
  719.             });
  720.         });
  721.     });
  722.     var templateData = {{ (template.data != '')?template.data|json_encode|raw:'[]' }};
  723.     if (templateData.startsWith("'") && templateData.endsWith("'")) {
  724.         templateData = templateData.slice(1, -1);
  725.     }
  726.     templateData = JSON.parse(templateData);
  727.     let defaltImage = false;
  728.     function getModalFormValues() {
  729.         const values = {
  730.             text: $('#modal-text').val(),
  731.             fontSize: $('#modal-fontSize').val(),
  732.             fontColor: $('#modal-fontColor-text').val(),
  733.             backgroundColor: $('#modal-transparentBg').is(':checked') ? 'transparent' : $('#modal-backgroundColor-text').val(),
  734.             textAlign: $('input[name="textAlign"]:checked').val(),
  735.             verticalAlign: $('input[name="verticalAlign"]:checked').val(),
  736.             orientation: $('input[name="orientation"]:checked').val(),
  737.             padding: $('#modal-padding').val(),
  738.             letterSpacing: $('#modal-letterSpacing').val(),
  739.             lineHeight: $('#modal-lineHeight').val(),
  740.             rotation: $('#modal-rotation').val(),
  741.             opacity: $('#modal-opacity').val(),
  742.             maxWidth: $('#modal-maxWidth').val(),
  743.             wordWrap: $('#modal-wordWrap').is(':checked'),
  744.             fontType: $('#modal-fontType').val(),
  745.             googleFont: $('#modal-googleFont').val(),
  746.             shadow: $('#modal-shadow').is(':checked'),
  747.             shadowColor: $('#modal-shadowColor').val(),
  748.             shadowOffsetX: $('#modal-shadowOffsetX').val(),
  749.             shadowOffsetY: $('#modal-shadowOffsetY').val(),
  750.             shadowBlur: $('#modal-shadowBlur').val(),
  751.             border: $('#modal-border').is(':checked'),
  752.             borderColor: $('#modal-borderColor').val(),
  753.             borderWidth: $('#modal-borderWidth').val(),
  754.             gradient: $('#modal-gradient').is(':checked'),
  755.             gradientFrom: $('#modal-gradientFrom').val(),
  756.             gradientTo: $('#modal-gradientTo').val(),
  757.             gradientDirection: $('#modal-gradientDirection').val(),
  758.             startTime:$('#modal-startTime').val(),
  759.             endTime:$('#modal-endTime').val(),
  760.             duration:videoDuration,
  761.             customPosition:$('#modal-customPosition').val(),
  762.             position:$('input[name="position"]:checked').val()
  763.         };
  764.         // Only include width and height if they have values
  765.         const width = $('#modal-width').val();
  766.         const height = $('#modal-height').val();
  767.         
  768.         if (width !== null && width !== '' && width !== undefined) {
  769.             values.width = width;
  770.         }
  771.         
  772.         if (height !== null && height !== '' && height !== undefined) {
  773.             values.height = height;
  774.         }
  775.         return values;
  776.     }
  777. function generateTextImage(obj) {
  778.     $obj = $(obj);
  779.     const text = $('#modal-text').val().trim();
  780.     if (!text) {
  781.         showAlert('error', 'Please enter some text content.');
  782.         return;
  783.     }
  784.     $obj.attr('disabled',true); 
  785.     $obj.html('Loading...'); 
  786.     const formValues = getModalFormValues();
  787.     console.log(formValues);
  788.     function sendJsonToApi(jsonData) {
  789.         $.ajax({
  790.             url: '/mytemplates/images/create',
  791.             type: 'POST',
  792.             data: JSON.stringify(jsonData),
  793.             processData: false,
  794.             contentType: 'application/json',
  795.             dataType: 'json',
  796.             timeout: 30000,
  797.             beforeSend: function () {
  798.                 console.log('Sending image generation request...');
  799.             },
  800.             success: function (response) {
  801.                 console.log('AJAX Success callback triggered');
  802.                 console.log('API Response:', response);
  803.                 templateData[defaltImage] = jsonData;
  804.                 $obj.attr('disabled',false); 
  805.                 $obj.html('Submit'); 
  806.                 try {
  807.                     if (typeof response === 'string') {
  808.                         response = JSON.parse(response);
  809.                     }
  810.                     const success = response.success || response.status === 1 || response.status === "1" || response.status === true;
  811.                     const imageUrl = response.url || response.previewUrl || response.imagePath;
  812.                     const message = response.message || 'Text image created successfully!';
  813.                     if (success && imageUrl) {
  814.                         $('#image-' + defaltImage).find('img').attr('src', imageUrl+ '?v=' + Date.now());
  815.                     } else {
  816.                         showAlert('error', 'Error: ' + (response.error || message || 'Failed to generate image'));
  817.                     }
  818.                 } catch (e) {
  819.                     $obj.attr('disabled',false); 
  820.                     $obj.html('Submit'); 
  821.                     console.error('Error processing response:', e, response);
  822.                     showAlert('error', 'Error processing server response: ' + e.message);
  823.                 }
  824.             },
  825.             error: function (xhr, status, error) {
  826.                $obj.attr('disabled',false); 
  827.                 $obj.html('Submit'); 
  828.                 console.error('AJAX Error:', error);
  829.                 if (status === 'timeout') {
  830.                     showAlert('error', 'Request timed out. Please try again.');
  831.                 } else {
  832.                     showAlert('error', 'Network error: ' + error);
  833.                 }
  834.             },
  835.             complete: function () {
  836.                 console.log('AJAX Complete callback triggered');
  837.                 $obj.attr('disabled',false); 
  838.                 $obj.html('Submit'); 
  839.             }
  840.         });
  841.     }
  842.     const img = $('#image-' + defaltImage).find('img');
  843.     const src = img.attr('src');
  844.     const cleanSrc = src.split('?')[0];
  845.     const jsonData = { ...formValues,"image":cleanSrc };
  846.     if (formValues.fontType === 'google') {
  847.         delete jsonData.fontData;
  848.         sendJsonToApi(jsonData);
  849.     } else {
  850.         const fileInput = document.getElementById('modal-fontFile');
  851.         if (fileInput && fileInput.files.length > 0) {
  852.             const file = fileInput.files[0];
  853.             const reader = new FileReader();
  854.             reader.onload = function (e) {
  855.                 const base64 = e.target.result.split(',')[1]; // Strip "data:...base64," prefix
  856.                 jsonData.fontData = base64;
  857.                 // Remove googleFont if exists
  858.                 delete jsonData.googleFont;
  859.                 sendJsonToApi(jsonData);
  860.             };
  861.             reader.readAsDataURL(file); // Converts file to base64
  862.        } else if (templateData[defaltImage] && templateData[defaltImage].fontData) {
  863.             // Use existing fontData from template
  864.             jsonData.fontData = templateData[defaltImage].fontData;
  865.             sendJsonToApi(jsonData);
  866.         }else {
  867.             showAlert('error', 'Please upload a font file.');
  868.             $obj.attr('disabled',false); 
  869.             $obj.html('Submit'); 
  870.         }
  871.     }
  872. }
  873. function showAlert(type, message) {
  874.     const alertClass = type === 'success' ? 'alert-success' : 'alert-danger';
  875.     const iconClass = type === 'success' ? 'bi-check-circle' : 'bi-exclamation-triangle';
  876.     const alertHtml = `
  877.         <div class="alert ${alertClass} alert-dismissible fade show" role="alert">
  878.             <i class="${iconClass} me-2"></i>${message}
  879.             <button type="button" class="btn-close" data-bs-dismiss="alert"></button>
  880.         </div>
  881.     `;
  882.     $('#alerts-container').html(alertHtml);
  883.     // Auto-dismiss after 5 seconds
  884.     setTimeout(() => {
  885.         $('.alert').alert('close');
  886.     }, 5000);
  887. }
  888. let videoDuration = 0;
  889.     const video = document.getElementsByTagName('video')[0];
  890.     
  891. document.addEventListener('DOMContentLoaded', () => {
  892.     let videoDuration = 0;
  893.     if (!video) {
  894.         console.error('Video element not found');
  895.         return;
  896.     }
  897.     
  898.     if (video.readyState >= 1) {
  899.     // Metadata is already loaded, handle accordingly
  900.         onMetadataLoaded();
  901.     } else {
  902.         video.addEventListener('loadedmetadata', onMetadataLoaded);
  903.     }
  904. });
  905. function onMetadataLoaded(){
  906.         videoDuration = parseInt(video.duration.toFixed()) + 1;
  907.         if (isNaN(videoDuration)) videoDuration = 0;
  908.         $('#video-endTime').val(videoDuration);
  909.         $('#video-duration').val(videoDuration);
  910.         // Wait until all .editable-image elements are rendered
  911.         const wrappers = document.querySelectorAll('.editable-image');
  912.         if (wrappers.length === 0) {
  913.             console.warn('No editable-image elements found');
  914.             return;
  915.         }
  916.         wrappers.forEach(wrapper => {
  917.             const button = document.createElement('button');
  918.             button.className = 'edit-button';
  919.             button.textContent = 'Edit';
  920.             button.style.display = 'none';
  921.             // Append button to wrapper first
  922.             wrapper.appendChild(button);
  923.             // Hover logic
  924.             wrapper.addEventListener('mouseenter', () => {
  925.                 button.style.display = 'block';
  926.             });
  927.             wrapper.addEventListener('mouseleave', () => {
  928.                 button.style.display = 'none';
  929.             });
  930.             // Click handler logic
  931.             button.addEventListener('click', (e) => {
  932.                 e.stopPropagation();
  933.                 const idPart = wrapper.getAttribute('id')?.replace('image-', '');
  934.                 if (!templateData || !templateData[idPart]) {
  935.                     console.warn('templateData not ready or missing for:', idPart);
  936.                     return;
  937.                 }
  938.                 defaltImage = idPart;
  939.                 $('#text-image-form').show();
  940.                 Object.entries(templateData[idPart]).forEach(([key, value]) => {
  941.                     $(`#modal-${key}, #modal-${key}-text, #modal-${key}-range`).val(value);
  942.                     const $input = $(`input[name="${key}"]`);
  943.                     if ($input.length) {
  944.                         if ($input.attr('type') === 'radio') {
  945.                             $(`input[name="${key}"][value="${value}"]`).prop('checked', true);
  946.                         } else {
  947.                             $input.val(value);
  948.                         }
  949.                     }
  950.                 });
  951.                 $('#modal-endTime, #modal-duration').val(videoDuration);
  952.                 templateData[idPart].endTime = videoDuration;
  953.                 // Position logic (customPosition)
  954.                 if (!templateData[idPart].customPosition) {
  955.                     const imageRect = wrapper.getBoundingClientRect();
  956.                     const videoRect = video.getBoundingClientRect();
  957.                     const relativeX = imageRect.left - videoRect.left;
  958.                     const relativeY = imageRect.top - videoRect.top;
  959.                     const mainWidth = video.videoWidth;
  960.                     const mainHeight = video.videoHeight;
  961.                     const percentWidth = relativeX !== 0 ? videoRect.width / relativeX : 0;
  962.                     const percentHeight = relativeY !== 0 ? videoRect.height / relativeY : 0;
  963.                     const renderTextRenderWidth = percentWidth !== 0 ? (mainWidth / percentWidth) : 0;
  964.                     const renderTextRenderHeight = percentHeight !== 0 ? (mainHeight / percentHeight) : 0;
  965.                     const pos = renderTextRenderWidth.toFixed() + ':' + renderTextRenderHeight.toFixed();
  966.                     $('#modal-customPosition').val(pos);
  967.                     templateData[idPart].customPosition = pos;
  968.                 }
  969.             });
  970.             // Auto trigger first button click (optional – delay a bit)
  971.             setTimeout(() => button.click(), 100);
  972.         });
  973. }
  974. let isProcessing = false;
  975. async function processVideo() {
  976.      if(templateData.length < 0){
  977.        return false;
  978.      }
  979.  
  980.     if (isProcessing) return;
  981.     
  982.     isProcessing = true;
  983.      showLoading('Generating video template...', 'Creating your custom text overlay with advanced styling');
  984.   
  985.     
  986.     try {
  987.         var videoTextParams = [];
  988.        
  989.         templateData.forEach(function(value, index) {
  990.             const img = $('#image-' + index).find('img');
  991.             const src = img.attr('src');
  992.             const cleanSrc = src.split('?')[0];
  993.             const temp = {
  994.                 imagePath: cleanSrc.replace('https://demo.tribital.com/test/video_editor/api/',''),
  995.                 startTime: value.startTime || 0,
  996.                 endTime: value.endTime || videoDuration,
  997.                 position: (value.customPosition !== '') ? value.customPosition : (value.position || 'center'),
  998.                 width: video.videoWidth*($('#image-'+index).width()/$('.background-video').width()),
  999.                 height: video.videoHeight*($('#image-'+index).height()/$('.background-video').height()),
  1000.             };
  1001.             videoTextParams.push(temp); 
  1002.         });
  1003.         
  1004.      
  1005.         const finalVideo = await processVideoWithMultipleOverlays(
  1006.             videoTextParams
  1007.         );
  1008.        hideLoading();
  1009.         showAlert('success', 'Template updated successfully');
  1010.         isProcessing = false;             
  1011.         
  1012.     } catch (error) {
  1013.         hideLoading();
  1014.         isProcessing = false;
  1015.         showAlert('error',`Error processing video`);
  1016.         console.error('Error processing video:', error);
  1017.     } finally {
  1018.         isProcessing = false;
  1019.     }
  1020. }
  1021. const mytemplate = {{template.id}};
  1022. const myclinic = {{template.clinic.id}};
  1023. async function processVideoWithMultipleOverlays(textImages) {
  1024.     try {
  1025.         const requestData = {
  1026.             textImages: textImages,
  1027.             mytemplate:mytemplate,
  1028.             myclinic:myclinic,
  1029.             templateData:templateData,
  1030.             body:$('#video-container').html()
  1031.         };
  1032.         
  1033.         const response = await fetch('/admin/mytemplates/reels/edit', {
  1034.             method: 'POST',
  1035.             headers: {
  1036.                 'Content-Type': 'application/json'
  1037.             },
  1038.             body: JSON.stringify(requestData)
  1039.         });
  1040.         
  1041.         if (!response.ok) {
  1042.             hideLoading();
  1043.             showAlert('error',`HTTP error! status: ${response.status}`);
  1044.             throw new Error(`HTTP error! status: ${response.status}`);
  1045.         }
  1046.         
  1047.         const result = await response.json();
  1048.         
  1049.         if (!result.success) {
  1050.             hideLoading();
  1051.             showAlert('error',result.message || 'Failed to process video with multiple overlays');
  1052.             throw new Error(result.message || 'Failed to process video with multiple overlays');
  1053.         }
  1054.         
  1055.         return result;
  1056.         
  1057.     } catch (error) {
  1058.          hideLoading();
  1059.          showAlert('error',`Multiple overlay processing failed: ${error.message}`);
  1060.         throw new Error(`Multiple overlay processing failed: ${error.message}`);
  1061.     }
  1062. }
  1063. function toggleFullScreen() {
  1064.       if (!document.fullscreenElement &&  // Check if not in fullscreen
  1065.           !document.mozFullScreenElement && !document.webkitFullscreenElement && !document.msFullscreenElement) {
  1066.         // If not in fullscreen, request fullscreen
  1067.         if (document.documentElement.requestFullscreen) {
  1068.           document.documentElement.requestFullscreen();
  1069.         } else if (document.documentElement.mozRequestFullScreen) { // Firefox
  1070.           document.documentElement.mozRequestFullScreen();
  1071.         } else if (document.documentElement.webkitRequestFullscreen) { // Chrome, Safari, Opera
  1072.           document.documentElement.webkitRequestFullscreen();
  1073.         } else if (document.documentElement.msRequestFullscreen) { // IE/Edge
  1074.           document.documentElement.msRequestFullscreen();
  1075.         }
  1076.         fullscreenBtn.textContent = "Exit Full Screen"; // Change button text
  1077.       } else {
  1078.         // If in fullscreen, exit fullscreen
  1079.         if (document.exitFullscreen) {
  1080.           document.exitFullscreen();
  1081.         } else if (document.mozCancelFullScreen) { // Firefox
  1082.           document.mozCancelFullScreen();
  1083.         } else if (document.webkitExitFullscreen) { // Chrome, Safari, Opera
  1084.           document.webkitExitFullscreen();
  1085.         } else if (document.msExitFullscreen) { // IE/Edge
  1086.           document.msExitFullscreen();
  1087.         }
  1088.         fullscreenBtn.textContent = "Go Full Screen"; // Change button text back
  1089.       }
  1090.     }
  1091. </script>