From 9abcd1cfc5b97badf8ae687439951273547227c6 Mon Sep 17 00:00:00 2001 From: Yukina Date: Sun, 21 Jun 2026 08:58:15 +0700 Subject: [PATCH 1/9] fix: prevent grid flicker during filtering and sorting --- core/ui/modules/grid-data.js | 5 ++++- core/ui/viewer.html | 20 ++++++++++---------- website/public/sqlite-viewer/viewer.html | 24 ++++++++++++------------ 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/core/ui/modules/grid-data.js b/core/ui/modules/grid-data.js index 72449d87..8ce641d5 100644 --- a/core/ui/modules/grid-data.js +++ b/core/ui/modules/grid-data.js @@ -52,8 +52,11 @@ export async function loadTableData(showSpinner = true, saveScrollPosition = tru if (showSpinner) { state.isLoadingData = true; - showLoading(); + if (!container || !container.querySelector('.data-grid')) { + showLoading(); + } } + updateToolbarButtons(); try { diff --git a/core/ui/viewer.html b/core/ui/viewer.html index 4a45d4a9..a3319fe6 100644 --- a/core/ui/viewer.html +++ b/core/ui/viewer.html @@ -364,7 +364,7 @@ diff --git a/website/public/sqlite-viewer/viewer.html b/website/public/sqlite-viewer/viewer.html index a4add1a8..54a7e6af 100644 --- a/website/public/sqlite-viewer/viewer.html +++ b/website/public/sqlite-viewer/viewer.html @@ -364,33 +364,33 @@ From 94eea88b7c5bd61c8272b6cb849d413b42104af0 Mon Sep 17 00:00:00 2001 From: Yukina Date: Sun, 21 Jun 2026 10:42:00 +0700 Subject: [PATCH 2/9] perf: reduce redundant DOM queries and array maps in loadTableData --- core/ui/modules/grid-data.js | 17 +++++++++++++---- core/ui/viewer.html | 8 ++++---- website/public/sqlite-viewer/viewer.html | 6 +++--- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/core/ui/modules/grid-data.js b/core/ui/modules/grid-data.js index 8ce641d5..b852b2a6 100644 --- a/core/ui/modules/grid-data.js +++ b/core/ui/modules/grid-data.js @@ -42,17 +42,22 @@ export async function loadTableData(showSpinner = true, saveScrollPosition = tru if (!state.selectedTable) return; const container = document.getElementById('gridContainer'); + // Whether a data grid is currently rendered (vs. a spinner/error/empty state). + // Cached once instead of re-querying the DOM at each decision point below. + const hasRenderedGrid = !!(container && container.querySelector('.data-grid')); // Only capture scroll position if the grid is currently visible (not loading/error state) // This prevents overwriting the saved position with 0 when reloading data while a spinner is shown. - if (saveScrollPosition && container && container.querySelector('.data-grid')) { + if (saveScrollPosition && hasRenderedGrid) { state.scrollPosition.left = container.scrollLeft; state.scrollPosition.top = container.scrollTop; } if (showSpinner) { state.isLoadingData = true; - if (!container || !container.querySelector('.data-grid')) { + // Keep the existing grid visible during refetch (prevents flicker); only + // show the spinner on a true first load when nothing is rendered yet. + if (!hasRenderedGrid) { showLoading(); } } @@ -69,10 +74,13 @@ export async function loadTableData(showSpinner = true, saveScrollPosition = tru } } + // Column names are needed both for the global-filter count and the data query. + const columnNames = state.tableColumns.map(c => c.name); + const countOptions = { filters, globalFilter: state.filterQuery, - columns: state.tableColumns.map(c => c.name) // Needed for global filter + columns: columnNames // Needed for global filter }; // Get total count @@ -85,7 +93,6 @@ export async function loadTableData(showSpinner = true, saveScrollPosition = tru // Get data const isTable = state.selectedTableType === 'table'; - const columnNames = state.tableColumns.map(c => c.name); // For tables, we need to explicitly request the 'rowid' column to handle row identification. // The frontend expects rowid at index 0 for tables (see `getRowId` and `getRowDataOffset`). @@ -110,6 +117,8 @@ export async function loadTableData(showSpinner = true, saveScrollPosition = tru // right before rendering. This ensures we use the latest scroll position, // which covers cases where the user scrolled during fetch or if an edit operation // updated the view (and restored scroll) while the fetch was pending. + // Re-check the DOM here (not the cached flag): this runs after the await, + // so the rendered state may differ from when the function started. if (!showSpinner && container && container.querySelector('.data-grid')) { state.scrollPosition.left = container.scrollLeft; state.scrollPosition.top = container.scrollTop; diff --git a/core/ui/viewer.html b/core/ui/viewer.html index a3319fe6..92c15333 100644 --- a/core/ui/viewer.html +++ b/core/ui/viewer.html @@ -381,11 +381,11 @@ Error ${X(e)} - `)}function R(){let e=t.selectedTable&&t.selectedTableType==="table",n=t.selectedRowIds.size>0,o=t.selectedColumns.size>0,l=document.getElementById("btnAddRow"),a=document.getElementById("btnAddColumn"),s=document.getElementById("btnDeleteRows"),i=document.getElementById("btnExport");l&&(l.disabled=!e),a&&(a.disabled=!e),s&&(s.disabled=!e||!n&&!o),i&&(i.disabled=!t.selectedTable)}function Me(){let e=document.getElementById("sidebarPanel"),n=document.getElementById("resizeHandle");if(!e||!n)return;let o=!1;n.addEventListener("mousedown",l=>{o=!0,document.body.style.cursor="col-resize",l.preventDefault()}),document.addEventListener("mousemove",l=>{if(!o)return;let a=Math.max(150,Math.min(400,l.clientX));e.style.width=a+"px"}),document.addEventListener("mouseup",()=>{o&&(o=!1,document.body.style.cursor="")})}function B(){return t.selectedTableType==="table"?1:0}function T(e,n){return t.selectedTableType==="table"?e[0]:t.currentPageIndex*t.rowsPerPage+n}function P(e,n){return e[n+B()]}function Ue(){document.addEventListener("click",e=>{let n=e.target,o=n.closest(".modal-close, .modal-cancel");if(o){let l=o.dataset.modal;l&&O(l)}n.classList.contains("modal-overlay")&&n.classList.add("hidden")}),document.addEventListener("keydown",e=>{if(e.key==="Escape"){let n=document.querySelector(".modal-overlay:not(.hidden)");n&&(n.classList.add("hidden"),e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation())}})}function W(e){let n=document.getElementById(e);if(n){n.classList.remove("hidden");let o=n.querySelector("input, select, textarea, button");o&&o.focus()}}function O(e){let n=document.getElementById(e);n&&n.classList.add("hidden")}function Oe(){document.getElementById("btnAddRow")?.addEventListener("click",zt),document.getElementById("btnDeleteRows")?.addEventListener("click",jt),document.getElementById("btnAddColumn")?.addEventListener("click",Ht),document.getElementById("btnSubmitAddRow")?.addEventListener("click",Vt),document.getElementById("btnSubmitDelete")?.addEventListener("click",ae),document.getElementById("btnSubmitCreateTable")?.addEventListener("click",Kt),document.getElementById("btnAddColumnDef")?.addEventListener("click",()=>je()),document.getElementById("columnDefinitions")?.addEventListener("click",e=>{let n=e.target.closest(".btn-remove-col");if(n){let o=n.dataset.colid;qt(o)}}),document.getElementById("btnSubmitAddColumn")?.addEventListener("click",Gt)}function zt(){if(!t.selectedTable||t.selectedTableType!=="table")return;let e=document.getElementById("addRowForm");e.replaceChildren(),t.tableColumns.forEach(n=>{let o=n.notnull===1&&!n.isPrimaryKey,l=document.createElement("div");l.className="form-field";let a=document.createElement("label");if(a.textContent=n.name,o){let r=document.createElement("span");r.style.color="var(--error-color)",r.textContent="*",a.appendChild(document.createTextNode(" ")),a.appendChild(r)}let s=document.createElement("span");s.style.opacity="0.5",s.textContent=` (${n.type})`,a.appendChild(document.createTextNode(" ")),a.appendChild(s);let i=document.createElement("input");i.type="text",i.dataset.column=n.name,i.dataset.required=o.toString(),n.isPrimaryKey?(i.placeholder="Auto (Primary Key)",i.disabled=!0):o?i.placeholder="Required":i.placeholder="NULL",l.appendChild(a),l.appendChild(i),e.appendChild(l)}),W("addRowModal")}async function Vt(){let e=document.querySelectorAll("#addRowForm input[data-column]:not([disabled])"),n=[];for(let l of e){let a=l.dataset.column,s=l.value.trim();l.dataset.required==="true"&&(s===""||s.toLowerCase()==="null")?(n.push(a),l.style.borderColor="var(--error-color)"):l.style.borderColor=""}if(n.length>0){u(`Required fields missing: ${n.join(", ")}`);return}let o={};for(let l of e){let a=l.dataset.column,s=l.value.trim();s!==""&&(s.toLowerCase()==="null"?o[a]=null:!isNaN(Number(s))&&s!==""?o[a]=Number(s):o[a]=s)}try{u("Inserting row..."),await C.insertRow(t.selectedTable,o),O("addRowModal"),await I(),u("Row inserted - Ctrl+S to save")}catch(l){console.error("Insert failed:",l),u(`Error: ${l.message}`)}}function jt(){if(t.selectedColumns.size>0){let e=Array.from(t.selectedColumns);document.getElementById("deleteConfirmText").textContent=`Are you sure you want to delete ${e.length} column${e.length>1?"s":""} (${e.join(", ")})? This will permanently remove the column${e.length>1?"s":""} and all their data.`}else if(t.selectedRowIds.size>0)document.getElementById("deleteConfirmText").textContent=`Are you sure you want to delete ${t.selectedRowIds.size} row${t.selectedRowIds.size>1?"s":""}?`;else return;W("deleteModal")}async function ae(){t.selectedColumns.size>0?await _t():t.selectedRowIds.size>0&&await Wt()}async function Wt(){if(t.selectedRowIds.size===0)return;let e=Array.from(t.selectedRowIds);try{u("Deleting rows..."),await C.deleteRows(t.selectedTable,e),O("deleteModal"),t.selectedRowIds.clear(),await I(),R(),u(`Deleted ${e.length} row${e.length>1?"s":""} - Ctrl+S to save`)}catch(n){console.error("Delete rows failed:",n),u(`Error: ${n.message}`)}}async function _t(){if(t.selectedColumns.size===0)return;let e=Array.from(t.selectedColumns);try{u("Deleting columns...");let n=await C.deleteColumns(t.selectedTable,e);if(n&&n.cancelled){u("Delete cancelled"),O("deleteModal");return}O("deleteModal"),t.selectedColumns.clear(),t.selectedCells=[],t.lastSelectedCell=null,await V(),await z(),await I(),R(),u(`Deleted ${e.length} column${e.length>1?"s":""} - Ctrl+S to save`)}catch(n){console.error("Delete columns failed:",n),u(`Error: ${n.message}`)}}var ze=0;function Ve(){document.getElementById("newTableName").value="",document.getElementById("columnDefinitions").replaceChildren(),ze=0,je(!0),W("createTableModal")}function je(e=!1){let n=document.getElementById("columnDefinitions"),o=++ze,l=document.createElement("div");l.className="column-def-row",l.id=`colDef_${o}`,Object.assign(l.style,{display:"flex",gap:"8px",marginBottom:"8px",alignItems:"center"});let a=document.createElement("input");a.type="text",a.placeholder="Column name",a.className="col-name",a.style.flex="2",e&&(a.value="id"),l.appendChild(a);let s=document.createElement("select");s.className="col-type",s.style.flex="1",["INTEGER","TEXT","REAL","BLOB","NUMERIC"].forEach(g=>{let p=document.createElement("option");p.value=g,p.textContent=g,e&&g==="INTEGER"&&(p.selected=!0),!e&&g==="TEXT"&&(p.selected=!0),s.appendChild(p)}),l.appendChild(s);let i=document.createElement("label");Object.assign(i.style,{display:"flex",alignItems:"center",gap:"4px",cursor:"pointer"});let r=document.createElement("input");r.type="checkbox",r.className="col-pk",r.style.margin="0",e&&(r.checked=!0),i.appendChild(r),i.appendChild(document.createTextNode(" PK")),l.appendChild(i);let c=document.createElement("label");Object.assign(c.style,{display:"flex",alignItems:"center",gap:"4px",cursor:"pointer"});let d=document.createElement("input");d.type="checkbox",d.className="col-nn",d.style.margin="0",c.appendChild(d),c.appendChild(document.createTextNode(" NN")),l.appendChild(c);let m=document.createElement("button");m.className="icon-button btn-remove-col",m.dataset.colid=o.toString(),m.title="Remove",e&&(m.disabled=!0);let f=document.createElement("span");f.className="codicon codicon-close",m.appendChild(f),l.appendChild(m),n.appendChild(l)}function qt(e){let n=document.getElementById(`colDef_${e}`);n&&n.remove()}async function Kt(){let e=document.getElementById("newTableName").value.trim();if(!e){u("Error: Table name is required");return}if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(e)){u("Error: Invalid table name");return}let n=[],o=document.querySelectorAll(".column-def-row");for(let l of o){let a=l.querySelector(".col-name").value.trim(),s=l.querySelector(".col-type").value,i=l.querySelector(".col-pk").checked,r=l.querySelector(".col-nn").checked;a&&n.push({name:a,type:s,primaryKey:i,notNull:r})}if(n.length===0){u("Error: At least one column is required");return}try{u("Creating table..."),await C.createTable(e,n),O("createTableModal"),await V(),u(`Table "${e}" created - Ctrl+S to save`)}catch(l){console.error("Create table failed:",l),u(`Error: ${l.message}`)}}function Ht(){!t.selectedTable||t.selectedTableType!=="table"||(document.getElementById("newColumnName").value="",document.getElementById("newColumnType").value="TEXT",document.getElementById("newColumnDefault").value="",W("addColumnModal"))}async function Gt(){let e=document.getElementById("newColumnName").value.trim(),n=document.getElementById("newColumnType").value,o=document.getElementById("newColumnDefault").value.trim();if(!e){u("Error: Column name is required");return}if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(e)){u("Error: Invalid column name");return}try{u("Adding column..."),await C.addColumn(t.selectedTable,e,n,o),O("addColumnModal"),await z(),await I(),u(`Column "${e}" added - Ctrl+S to save`)}catch(l){console.error("Add column failed:",l),u(`Error: ${l.message}`)}}function We(){let e=document.getElementById("pragmaSettingsContainer");e&&e.addEventListener("change",n=>{let o=n.target;if(o.matches(".setting-extension")){let l=o.dataset.key,a=o.type==="checkbox"?o.checked:o.value;Xt(l,a)}else if(o.matches(".setting-pragma")){let l=o.dataset.name,a=o.dataset.type,s=o.value;a==="number"?s=Number(s):a==="bool"&&(s=s==="true"?1:0),Yt(l,s)}})}async function _e(){let e=document.getElementById("settingsModal");e&&(e.classList.remove("hidden"),await xe())}async function xe(){let e=document.getElementById("pragmaSettingsContainer");e.textContent="Loading settings...";try{let[n,o]=await Promise.all([C.getPragmas(),C.getExtensionSettings()]);Jt(n,o)}catch(n){console.error("Failed to load settings:",n),e.textContent=`Error loading settings: ${n.message}`,e.style.color="var(--error-color)"}}function Jt(e,n){let o=document.getElementById("pragmaSettingsContainer");if(!o)return;let l=(y,x)=>y.map(k=>{let L=String(k),D=String(x).toUpperCase()===L.toUpperCase(),N=document.createElement("option");return N.value=L,N.selected=D,N.textContent=L,N});o.replaceChildren();let a=y=>{let x=document.createElement("div");x.className="setting-section-title",Object.assign(x.style,{fontWeight:"600",marginBottom:"8px",paddingBottom:"4px",borderBottom:"1px solid var(--border-color)"}),x.textContent=y,o.appendChild(x)},s=(y,x,k)=>{let L=document.createElement("div");L.className="form-field";let b=document.createElement("label");if(x.type==="checkbox"?(Object.assign(b.style,{display:"flex",alignItems:"center",gap:"4px",cursor:"pointer"}),x.style.margin="0",b.appendChild(x),b.appendChild(document.createTextNode(y)),L.appendChild(b)):(b.textContent=y,L.appendChild(b),L.appendChild(x)),k){let D=document.createElement("div");D.className="setting-desc",D.textContent=k,L.appendChild(D)}o.appendChild(L)};if(o.children.length>0){let y=document.createElement("div");y.style.height="16px",o.appendChild(y)}a("Extension Settings");let i=document.createElement("input");i.type="checkbox",i.className="setting-extension",i.dataset.key="autoCommit",i.checked=!!n.autoCommit,s("Auto-Commit Changes",i,"Automatically save changes to disk immediately. If disabled, you must save manually (Ctrl+S).");let r=document.createElement("select");r.className="setting-extension",r.dataset.key="doubleClickBehavior",l(["inline","modal","vscode"],n.cellEditBehavior).forEach(y=>r.appendChild(y)),s("Double Click Behavior",r,"Action when double-clicking a cell");let c=document.createElement("div");c.style.height="16px",o.appendChild(c),a("SQLite Settings (Pragmas)");let d=document.createElement("select");d.className="setting-pragma",d.dataset.name="journal_mode",l(["DELETE","TRUNCATE","PERSIST","MEMORY","WAL","OFF"],e.journal_mode).forEach(y=>d.appendChild(y)),s("Journal Mode",d,"Database journaling mode (WAL is recommended for concurrency)");let m=document.createElement("select");m.className="setting-pragma",m.dataset.name="foreign_keys",m.dataset.type="bool";let f=document.createElement("option");f.value="true",f.textContent="ON";let g=document.createElement("option");g.value="false",g.textContent="OFF",Number(e.foreign_keys)===1?f.selected=!0:g.selected=!0,m.appendChild(f),m.appendChild(g),s("Foreign Keys",m,"Enforce foreign key constraints");let p=document.createElement("select");p.className="setting-pragma",p.dataset.name="synchronous",p.dataset.type="number",[{v:0,t:"OFF (0)"},{v:1,t:"NORMAL (1)"},{v:2,t:"FULL (2)"},{v:3,t:"EXTRA (3)"}].forEach(y=>{let x=document.createElement("option");x.value=y.v,x.textContent=y.t,Number(e.synchronous)===y.v&&(x.selected=!0),p.appendChild(x)}),s("Synchronous",p,"Disk synchronization safety level");let h=document.createElement("select");h.className="setting-pragma",h.dataset.name="locking_mode",l(["NORMAL","EXCLUSIVE"],e.locking_mode).forEach(y=>h.appendChild(y)),s("Locking Mode",h,"");let w=document.createElement("select");w.className="setting-pragma",w.dataset.name="auto_vacuum",w.dataset.type="number",[{v:0,t:"NONE (0)"},{v:1,t:"FULL (1)"},{v:2,t:"INCREMENTAL (2)"}].forEach(y=>{let x=document.createElement("option");x.value=y.v,x.textContent=y.t,Number(e.auto_vacuum)===y.v&&(x.selected=!0),w.appendChild(x)}),s("Auto Vacuum",w,"");let v=document.createElement("input");v.type="number",v.className="setting-pragma",v.dataset.name="cache_size",v.dataset.type="number",v.value=e.cache_size,s("Cache Size",v,"Number of pages (positive) or kilobytes (negative)")}async function Xt(e,n){try{await C.updateExtensionSetting(e,n),u(`Updated ${e}`)}catch(o){console.error(`Failed to set ${e}:`,o),u(`Error: ${o.message}`),await xe()}}async function Yt(e,n){try{u(`Updating ${e}...`),await C.setPragma(e,n),u(`Updated ${e}`)}catch(o){console.error(`Failed to set ${e}:`,o),u(`Error: ${o.message}`),await xe()}}function qe(e,n){let o=new Map;for(let l of e){let a=n&&n[l.colIdx];a&&(o.has(l.colIdx)||o.set(l.colIdx,{name:a.name,type:a.type,values:new Set}),o.get(l.colIdx).values.add(l.value))}return o}function Ke(e){let n=Array.from(e||[]);if(n.length===0)return"";if(n.length>1)return"(mixed values)";let o=n[0];return o===null?"NULL":o instanceof Uint8Array?"[BLOB]":String(o)}function He(e,n,o){let l=[];for(let a of e){let s=n.get(a.colIdx);if(!s)continue;let i=s.dataset||{},r=i.isnull==="true",c=i.ispatch==="true",d=s.value;if(d===""&&!r)continue;let m=o&&o[a.colIdx];if(!m)continue;let f=d,g="set";if(r)f=null;else if(c)g="json_patch";else{let p=(m.type||"").toUpperCase();(p==="INTEGER"||p==="REAL"||p==="NUMERIC")&&!isNaN(Number(d))&&d.trim()!==""&&(f=Number(d))}l.push({rowId:a.rowId,column:m.name,value:f,originalValue:a.value,operation:g,rowIdx:a.rowIdx,colIdx:a.colIdx})}return l}function Je(){let e=document.getElementById("sidebarPanel");if(!e)return;let n=document.getElementById("sidebarFilterInput");n&&n.addEventListener("input",()=>{t.sidebarFilter=n.value,Y()}),e.addEventListener("click",o=>{let l=o.target;if(l.closest("#btnOpenSettings")){_e();return}if(l.closest("#btnOpenCreateTable")){o.stopPropagation(),Ve();return}if(l.closest("#btnReload")){ln();return}if(l.closest("#btnApplyBatchUpdate")){Zt();return}let a=l.closest(".list-item");if(a){let c=a.dataset.name,d=a.dataset.type;if(c&&d){on(c,d);return}}let s=l.closest(".section-title");if(s){if(l.closest(".icon-button")||s.id==="btnOpenSettings")return;let c=s.dataset.section;c&&nn(c)}let i=l.closest(".btn-batch-null");if(i){let c=i.closest(".batch-field");if(c){let d=parseInt(c.dataset.colidx,10);en(d)}return}let r=l.closest(".btn-batch-patch");if(r){let c=r.closest(".batch-field");if(c){let d=parseInt(c.dataset.colidx,10);tn(d,r)}return}})}async function V(){if(t.isDbConnected)try{let e=await C.fetchSchema();t.schemaCache.tables=(e.tables||[]).map(n=>({name:n.identifier})),t.schemaCache.views=(e.views||[]).map(n=>({name:n.identifier})),t.schemaCache.indexes=(e.indexes||[]).map(n=>({name:n.identifier,table:n.parentTable})),Y()}catch(e){console.error("Error loading schema:",e),u("Error loading schema")}}function be(e,n){return n?e.filter(o=>o.name.toLowerCase().includes(n)):e}function we(e,n,o,l){let a=document.getElementById(e);a&&(a.textContent=l?`${n}/${o}`:o)}function Ge(e,n,o,l,a){let s=document.getElementById(e);if(!s)return;if(s.replaceChildren(),n.length===0){let r=document.createElement("li");r.className="list-item",r.style.opacity="0.5",r.textContent=a,s.appendChild(r);return}let i=document.createDocumentFragment();n.forEach(r=>{let c=document.createElement("li");c.className="list-item",t.selectedTable===r.name&&t.selectedTableType===o&&c.classList.add("selected"),c.dataset.name=r.name,o&&(c.dataset.type=o),c.title=r.name;let d=document.createElement("span");d.className=`item-icon codicon ${l}`,c.appendChild(d);let m=document.createElement("span");m.className="item-name",m.textContent=r.name,c.appendChild(m),i.appendChild(c)}),s.appendChild(i)}function Qt(e,n,o){let l=document.getElementById(e);if(!l)return;if(l.replaceChildren(),n.length===0){let s=document.createElement("li");s.className="list-item",s.style.opacity="0.5",s.textContent=o,l.appendChild(s);return}let a=document.createDocumentFragment();n.forEach(s=>{let i=document.createElement("li");i.className="list-item",i.title=`${s.name} on ${s.table}`;let r=document.createElement("span");r.className="item-icon codicon codicon-list-selection",i.appendChild(r);let c=document.createElement("div");c.className="item-content";let d=document.createElement("span");d.className="item-name",d.textContent=s.name,c.appendChild(d);let m=document.createElement("span");m.className="item-detail",m.textContent=s.table,c.appendChild(m),i.appendChild(c),a.appendChild(i)}),l.appendChild(a)}function Y(){let e=t.sidebarFilter.toLowerCase(),n=e.length>0,o=be(t.schemaCache.tables,e),l=be(t.schemaCache.views,e),a=be(t.schemaCache.indexes,e);we("tablesBadge",o.length,t.schemaCache.tables.length,n),we("viewsBadge",l.length,t.schemaCache.views.length,n),we("indexesBadge",a.length,t.schemaCache.indexes.length,n),Ge("tablesList",o,"table","codicon-table",e?"No matching tables":"No tables"),Ge("viewsList",l,"view","codicon-eye",e?"No matching views":"No views"),Qt("indexesList",a,e?"No matching indexes":"No indexes")}function j(){let e=document.getElementById("batchUpdateSectionTitle"),n=document.getElementById("batchUpdateList"),o=document.getElementById("batchUpdateCount"),l=document.getElementById("batchUpdateFields");if(!e||!n||!o||!l)return;let a=t.selectedCells.length;if(a===0){e.classList.add("hidden"),n.classList.add("hidden");return}e.classList.remove("hidden"),n.classList.remove("hidden"),e.classList.remove("collapsed"),o.textContent=a;let s=qe(t.selectedCells,t.tableColumns);l.replaceChildren();let i=document.createDocumentFragment();for(let[r,c]of s){let d=Ke(c.values),m=document.createElement("div");m.className="form-field batch-field",m.dataset.colidx=r,m.style.marginBottom="8px";let f=document.createElement("label");f.style.fontSize="11px",f.style.color="var(--text-secondary)";let g=document.createTextNode(c.name+" ");f.appendChild(g);let p=document.createElement("span");p.style.opacity="0.7",p.textContent=c.type||"",f.appendChild(p),m.appendChild(f);let h=document.createElement("div");h.style.display="flex",h.style.gap="4px";let w=document.createElement("input");w.type="text",w.className="batch-input",w.placeholder=d,w.dataset.colidx=r,w.style.flex="1",w.style.minWidth="0",h.appendChild(w);let v=document.createElement("button");v.className="btn-secondary btn-batch-null",v.style.padding="2px 6px",v.title="Set to NULL",v.textContent="NULL",h.appendChild(v);let y=document.createElement("button");y.className="btn-secondary btn-batch-patch",y.style.padding="2px 6px",y.title="JSON Patch",y.textContent="{}",h.appendChild(y),m.appendChild(h),i.appendChild(m)}l.appendChild(i)}async function Zt(){if(t.selectedCells.length===0)return;let e=document.querySelectorAll(".batch-input"),n=new Map;for(let l of e){let a=parseInt(l.dataset.colidx,10);if(n.set(a,l),l.dataset.ispatch==="true")try{JSON.parse(l.value)}catch{let i=t.tableColumns[a];u(`Invalid JSON for patch in ${i?.name??`column ${a}`}`);return}}let o=He(t.selectedCells,n,t.tableColumns);if(o.length===0){u("No values entered for batch update");return}try{u(`Updating ${o.length} cells...`);let l=`Batch update ${o.length} cells`,a=o.map(r=>({rowId:r.rowId,column:r.column,value:r.value,originalValue:r.originalValue,operation:r.operation}));if(await C.updateCellBatch(t.selectedTable,a,l),!o.some(r=>r.operation==="json_patch"))for(let r of o)t.gridData[r.rowIdx][r.colIdx+B()]=r.value;await I(!1);let i=[];for(let r of t.selectedCells){let c=t.gridData[r.rowIdx][r.colIdx+B()];i.push({...r,value:c})}t.selectedCells=i,j(),u("Batch update completed")}catch(l){console.error("Batch update failed:",l),u(`Batch update failed: ${l.message}`)}}function en(e){let n=document.querySelector(`.batch-input[data-colidx="${e}"]`),o=document.querySelector(`.batch-field[data-colidx="${e}"] .btn-batch-patch`);n&&(n.value="",n.placeholder="SET TO NULL",n.dataset.isnull="true",n.dataset.ispatch="false",n.style.fontStyle="italic",o&&(o.style.background="",o.style.color=""))}function tn(e,n){let o=document.querySelector(`.batch-input[data-colidx="${e}"]`);o&&(o.dataset.ispatch==="true"?(o.dataset.ispatch="false",o.placeholder="(mixed values)",n.style.background="",n.style.color=""):(o.dataset.ispatch="true",o.dataset.isnull="false",o.placeholder='JSON Patch (e.g. {"a": 1})',o.style.fontStyle="normal",n.style.background="var(--accent-color)",n.style.color="white"))}function nn(e){let n=document.getElementById(`${e}List`),o=document.querySelector(`.section-title[data-section="${e}"]`);n&&o&&(n.classList.toggle("hidden"),o.classList.toggle("collapsed"))}async function on(e,n){t.selectedTable=e,t.selectedTableType=n,t.currentPageIndex=0,t.sortedColumn=null,t.sortAscending=!0,t.filterQuery="",t.columnFilters={},t.selectedRowIds.clear(),t.selectedCells=[],t.lastSelectedCell=null,t.selectedColumns.clear(),t.pinnedColumns.clear(),t.pinnedRowIds.clear(),t.columnWidths={},t.scrollPosition={top:0,left:0},Y();let o=document.getElementById("tableNameLabel");o&&(o.textContent=e);let l=document.getElementById("filterInput");l&&(l.value=""),await z(),await I(!0,!1),$()}async function ln(){if(t.isDbConnected)try{u("Reloading..."),await C.refreshFile(),await V(),t.selectedTable&&(await z(),await I()),u("Reloaded")}catch(e){console.error("Reload failed:",e),u(`Reload failed: ${e.message}`)}}var Q=new Set,Z=new Set;function Xe(){Q.clear(),t.selectedCells.length>0&&t.selectedCells.forEach(e=>{Q.add(`cell-${e.rowIdx}-${e.colIdx}`)}),Z.clear(),t.selectedRowIds.size>0&&document.querySelectorAll(".data-row.selected").forEach(n=>{n.id&&Z.add(n.id)})}function F(){let e=new Set;for(let o of t.selectedCells)e.add(`cell-${o.rowIdx}-${o.colIdx}`);for(let o of Q)if(!e.has(o)){let l=document.getElementById(o);l&&l.classList.remove("cell-selected")}for(let o of e)if(!Q.has(o)){let l=document.getElementById(o);l&&l.classList.add("cell-selected")}Q=e;let n=new Set;for(let o=0;oo.classList.remove("column-selected")),t.selectedColumns.size>0&&t.selectedColumns.forEach(o=>{let l=CSS.escape(o),a=document.querySelector(`.header-cell[data-column="${l}"]`);a&&a.classList.add("column-selected")})}function se(){t.selectedCells=[],t.selectedRowIds.clear(),t.selectedColumns.clear(),t.lastSelectedCell=null,F(),R(),j()}function an(){let e=document.createElement("div");return e.className="empty-view",e.innerHTML=` + `)}function R(){let e=t.selectedTable&&t.selectedTableType==="table",n=t.selectedRowIds.size>0,o=t.selectedColumns.size>0,l=document.getElementById("btnAddRow"),a=document.getElementById("btnAddColumn"),s=document.getElementById("btnDeleteRows"),i=document.getElementById("btnExport");l&&(l.disabled=!e),a&&(a.disabled=!e),s&&(s.disabled=!e||!n&&!o),i&&(i.disabled=!t.selectedTable)}function Me(){let e=document.getElementById("sidebarPanel"),n=document.getElementById("resizeHandle");if(!e||!n)return;let o=!1;n.addEventListener("mousedown",l=>{o=!0,document.body.style.cursor="col-resize",l.preventDefault()}),document.addEventListener("mousemove",l=>{if(!o)return;let a=Math.max(150,Math.min(400,l.clientX));e.style.width=a+"px"}),document.addEventListener("mouseup",()=>{o&&(o=!1,document.body.style.cursor="")})}function B(){return t.selectedTableType==="table"?1:0}function T(e,n){return t.selectedTableType==="table"?e[0]:t.currentPageIndex*t.rowsPerPage+n}function P(e,n){return e[n+B()]}function Ue(){document.addEventListener("click",e=>{let n=e.target,o=n.closest(".modal-close, .modal-cancel");if(o){let l=o.dataset.modal;l&&O(l)}n.classList.contains("modal-overlay")&&n.classList.add("hidden")}),document.addEventListener("keydown",e=>{if(e.key==="Escape"){let n=document.querySelector(".modal-overlay:not(.hidden)");n&&(n.classList.add("hidden"),e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation())}})}function W(e){let n=document.getElementById(e);if(n){n.classList.remove("hidden");let o=n.querySelector("input, select, textarea, button");o&&o.focus()}}function O(e){let n=document.getElementById(e);n&&n.classList.add("hidden")}function Oe(){document.getElementById("btnAddRow")?.addEventListener("click",zt),document.getElementById("btnDeleteRows")?.addEventListener("click",jt),document.getElementById("btnAddColumn")?.addEventListener("click",Ht),document.getElementById("btnSubmitAddRow")?.addEventListener("click",Vt),document.getElementById("btnSubmitDelete")?.addEventListener("click",ae),document.getElementById("btnSubmitCreateTable")?.addEventListener("click",Kt),document.getElementById("btnAddColumnDef")?.addEventListener("click",()=>je()),document.getElementById("columnDefinitions")?.addEventListener("click",e=>{let n=e.target.closest(".btn-remove-col");if(n){let o=n.dataset.colid;qt(o)}}),document.getElementById("btnSubmitAddColumn")?.addEventListener("click",Gt)}function zt(){if(!t.selectedTable||t.selectedTableType!=="table")return;let e=document.getElementById("addRowForm");e.replaceChildren(),t.tableColumns.forEach(n=>{let o=n.notnull===1&&!n.isPrimaryKey,l=document.createElement("div");l.className="form-field";let a=document.createElement("label");if(a.textContent=n.name,o){let r=document.createElement("span");r.style.color="var(--error-color)",r.textContent="*",a.appendChild(document.createTextNode(" ")),a.appendChild(r)}let s=document.createElement("span");s.style.opacity="0.5",s.textContent=` (${n.type})`,a.appendChild(document.createTextNode(" ")),a.appendChild(s);let i=document.createElement("input");i.type="text",i.dataset.column=n.name,i.dataset.required=o.toString(),n.isPrimaryKey?(i.placeholder="Auto (Primary Key)",i.disabled=!0):o?i.placeholder="Required":i.placeholder="NULL",l.appendChild(a),l.appendChild(i),e.appendChild(l)}),W("addRowModal")}async function Vt(){let e=document.querySelectorAll("#addRowForm input[data-column]:not([disabled])"),n=[];for(let l of e){let a=l.dataset.column,s=l.value.trim();l.dataset.required==="true"&&(s===""||s.toLowerCase()==="null")?(n.push(a),l.style.borderColor="var(--error-color)"):l.style.borderColor=""}if(n.length>0){u(`Required fields missing: ${n.join(", ")}`);return}let o={};for(let l of e){let a=l.dataset.column,s=l.value.trim();s!==""&&(s.toLowerCase()==="null"?o[a]=null:!isNaN(Number(s))&&s!==""?o[a]=Number(s):o[a]=s)}try{u("Inserting row..."),await C.insertRow(t.selectedTable,o),O("addRowModal"),await I(),u("Row inserted - Ctrl+S to save")}catch(l){console.error("Insert failed:",l),u(`Error: ${l.message}`)}}function jt(){if(t.selectedColumns.size>0){let e=Array.from(t.selectedColumns);document.getElementById("deleteConfirmText").textContent=`Are you sure you want to delete ${e.length} column${e.length>1?"s":""} (${e.join(", ")})? This will permanently remove the column${e.length>1?"s":""} and all their data.`}else if(t.selectedRowIds.size>0)document.getElementById("deleteConfirmText").textContent=`Are you sure you want to delete ${t.selectedRowIds.size} row${t.selectedRowIds.size>1?"s":""}?`;else return;W("deleteModal")}async function ae(){t.selectedColumns.size>0?await _t():t.selectedRowIds.size>0&&await Wt()}async function Wt(){if(t.selectedRowIds.size===0)return;let e=Array.from(t.selectedRowIds);try{u("Deleting rows..."),await C.deleteRows(t.selectedTable,e),O("deleteModal"),t.selectedRowIds.clear(),await I(),R(),u(`Deleted ${e.length} row${e.length>1?"s":""} - Ctrl+S to save`)}catch(n){console.error("Delete rows failed:",n),u(`Error: ${n.message}`)}}async function _t(){if(t.selectedColumns.size===0)return;let e=Array.from(t.selectedColumns);try{u("Deleting columns...");let n=await C.deleteColumns(t.selectedTable,e);if(n&&n.cancelled){u("Delete cancelled"),O("deleteModal");return}O("deleteModal"),t.selectedColumns.clear(),t.selectedCells=[],t.lastSelectedCell=null,await V(),await z(),await I(),R(),u(`Deleted ${e.length} column${e.length>1?"s":""} - Ctrl+S to save`)}catch(n){console.error("Delete columns failed:",n),u(`Error: ${n.message}`)}}var ze=0;function Ve(){document.getElementById("newTableName").value="",document.getElementById("columnDefinitions").replaceChildren(),ze=0,je(!0),W("createTableModal")}function je(e=!1){let n=document.getElementById("columnDefinitions"),o=++ze,l=document.createElement("div");l.className="column-def-row",l.id=`colDef_${o}`,Object.assign(l.style,{display:"flex",gap:"8px",marginBottom:"8px",alignItems:"center"});let a=document.createElement("input");a.type="text",a.placeholder="Column name",a.className="col-name",a.style.flex="2",e&&(a.value="id"),l.appendChild(a);let s=document.createElement("select");s.className="col-type",s.style.flex="1",["INTEGER","TEXT","REAL","BLOB","NUMERIC"].forEach(f=>{let p=document.createElement("option");p.value=f,p.textContent=f,e&&f==="INTEGER"&&(p.selected=!0),!e&&f==="TEXT"&&(p.selected=!0),s.appendChild(p)}),l.appendChild(s);let i=document.createElement("label");Object.assign(i.style,{display:"flex",alignItems:"center",gap:"4px",cursor:"pointer"});let r=document.createElement("input");r.type="checkbox",r.className="col-pk",r.style.margin="0",e&&(r.checked=!0),i.appendChild(r),i.appendChild(document.createTextNode(" PK")),l.appendChild(i);let c=document.createElement("label");Object.assign(c.style,{display:"flex",alignItems:"center",gap:"4px",cursor:"pointer"});let d=document.createElement("input");d.type="checkbox",d.className="col-nn",d.style.margin="0",c.appendChild(d),c.appendChild(document.createTextNode(" NN")),l.appendChild(c);let m=document.createElement("button");m.className="icon-button btn-remove-col",m.dataset.colid=o.toString(),m.title="Remove",e&&(m.disabled=!0);let g=document.createElement("span");g.className="codicon codicon-close",m.appendChild(g),l.appendChild(m),n.appendChild(l)}function qt(e){let n=document.getElementById(`colDef_${e}`);n&&n.remove()}async function Kt(){let e=document.getElementById("newTableName").value.trim();if(!e){u("Error: Table name is required");return}if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(e)){u("Error: Invalid table name");return}let n=[],o=document.querySelectorAll(".column-def-row");for(let l of o){let a=l.querySelector(".col-name").value.trim(),s=l.querySelector(".col-type").value,i=l.querySelector(".col-pk").checked,r=l.querySelector(".col-nn").checked;a&&n.push({name:a,type:s,primaryKey:i,notNull:r})}if(n.length===0){u("Error: At least one column is required");return}try{u("Creating table..."),await C.createTable(e,n),O("createTableModal"),await V(),u(`Table "${e}" created - Ctrl+S to save`)}catch(l){console.error("Create table failed:",l),u(`Error: ${l.message}`)}}function Ht(){!t.selectedTable||t.selectedTableType!=="table"||(document.getElementById("newColumnName").value="",document.getElementById("newColumnType").value="TEXT",document.getElementById("newColumnDefault").value="",W("addColumnModal"))}async function Gt(){let e=document.getElementById("newColumnName").value.trim(),n=document.getElementById("newColumnType").value,o=document.getElementById("newColumnDefault").value.trim();if(!e){u("Error: Column name is required");return}if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(e)){u("Error: Invalid column name");return}try{u("Adding column..."),await C.addColumn(t.selectedTable,e,n,o),O("addColumnModal"),await z(),await I(),u(`Column "${e}" added - Ctrl+S to save`)}catch(l){console.error("Add column failed:",l),u(`Error: ${l.message}`)}}function We(){let e=document.getElementById("pragmaSettingsContainer");e&&e.addEventListener("change",n=>{let o=n.target;if(o.matches(".setting-extension")){let l=o.dataset.key,a=o.type==="checkbox"?o.checked:o.value;Xt(l,a)}else if(o.matches(".setting-pragma")){let l=o.dataset.name,a=o.dataset.type,s=o.value;a==="number"?s=Number(s):a==="bool"&&(s=s==="true"?1:0),Yt(l,s)}})}async function _e(){let e=document.getElementById("settingsModal");e&&(e.classList.remove("hidden"),await xe())}async function xe(){let e=document.getElementById("pragmaSettingsContainer");e.textContent="Loading settings...";try{let[n,o]=await Promise.all([C.getPragmas(),C.getExtensionSettings()]);Jt(n,o)}catch(n){console.error("Failed to load settings:",n),e.textContent=`Error loading settings: ${n.message}`,e.style.color="var(--error-color)"}}function Jt(e,n){let o=document.getElementById("pragmaSettingsContainer");if(!o)return;let l=(y,x)=>y.map(k=>{let L=String(k),D=String(x).toUpperCase()===L.toUpperCase(),N=document.createElement("option");return N.value=L,N.selected=D,N.textContent=L,N});o.replaceChildren();let a=y=>{let x=document.createElement("div");x.className="setting-section-title",Object.assign(x.style,{fontWeight:"600",marginBottom:"8px",paddingBottom:"4px",borderBottom:"1px solid var(--border-color)"}),x.textContent=y,o.appendChild(x)},s=(y,x,k)=>{let L=document.createElement("div");L.className="form-field";let b=document.createElement("label");if(x.type==="checkbox"?(Object.assign(b.style,{display:"flex",alignItems:"center",gap:"4px",cursor:"pointer"}),x.style.margin="0",b.appendChild(x),b.appendChild(document.createTextNode(y)),L.appendChild(b)):(b.textContent=y,L.appendChild(b),L.appendChild(x)),k){let D=document.createElement("div");D.className="setting-desc",D.textContent=k,L.appendChild(D)}o.appendChild(L)};if(o.children.length>0){let y=document.createElement("div");y.style.height="16px",o.appendChild(y)}a("Extension Settings");let i=document.createElement("input");i.type="checkbox",i.className="setting-extension",i.dataset.key="autoCommit",i.checked=!!n.autoCommit,s("Auto-Commit Changes",i,"Automatically save changes to disk immediately. If disabled, you must save manually (Ctrl+S).");let r=document.createElement("select");r.className="setting-extension",r.dataset.key="doubleClickBehavior",l(["inline","modal","vscode"],n.cellEditBehavior).forEach(y=>r.appendChild(y)),s("Double Click Behavior",r,"Action when double-clicking a cell");let c=document.createElement("div");c.style.height="16px",o.appendChild(c),a("SQLite Settings (Pragmas)");let d=document.createElement("select");d.className="setting-pragma",d.dataset.name="journal_mode",l(["DELETE","TRUNCATE","PERSIST","MEMORY","WAL","OFF"],e.journal_mode).forEach(y=>d.appendChild(y)),s("Journal Mode",d,"Database journaling mode (WAL is recommended for concurrency)");let m=document.createElement("select");m.className="setting-pragma",m.dataset.name="foreign_keys",m.dataset.type="bool";let g=document.createElement("option");g.value="true",g.textContent="ON";let f=document.createElement("option");f.value="false",f.textContent="OFF",Number(e.foreign_keys)===1?g.selected=!0:f.selected=!0,m.appendChild(g),m.appendChild(f),s("Foreign Keys",m,"Enforce foreign key constraints");let p=document.createElement("select");p.className="setting-pragma",p.dataset.name="synchronous",p.dataset.type="number",[{v:0,t:"OFF (0)"},{v:1,t:"NORMAL (1)"},{v:2,t:"FULL (2)"},{v:3,t:"EXTRA (3)"}].forEach(y=>{let x=document.createElement("option");x.value=y.v,x.textContent=y.t,Number(e.synchronous)===y.v&&(x.selected=!0),p.appendChild(x)}),s("Synchronous",p,"Disk synchronization safety level");let h=document.createElement("select");h.className="setting-pragma",h.dataset.name="locking_mode",l(["NORMAL","EXCLUSIVE"],e.locking_mode).forEach(y=>h.appendChild(y)),s("Locking Mode",h,"");let w=document.createElement("select");w.className="setting-pragma",w.dataset.name="auto_vacuum",w.dataset.type="number",[{v:0,t:"NONE (0)"},{v:1,t:"FULL (1)"},{v:2,t:"INCREMENTAL (2)"}].forEach(y=>{let x=document.createElement("option");x.value=y.v,x.textContent=y.t,Number(e.auto_vacuum)===y.v&&(x.selected=!0),w.appendChild(x)}),s("Auto Vacuum",w,"");let v=document.createElement("input");v.type="number",v.className="setting-pragma",v.dataset.name="cache_size",v.dataset.type="number",v.value=e.cache_size,s("Cache Size",v,"Number of pages (positive) or kilobytes (negative)")}async function Xt(e,n){try{await C.updateExtensionSetting(e,n),u(`Updated ${e}`)}catch(o){console.error(`Failed to set ${e}:`,o),u(`Error: ${o.message}`),await xe()}}async function Yt(e,n){try{u(`Updating ${e}...`),await C.setPragma(e,n),u(`Updated ${e}`)}catch(o){console.error(`Failed to set ${e}:`,o),u(`Error: ${o.message}`),await xe()}}function qe(e,n){let o=new Map;for(let l of e){let a=n&&n[l.colIdx];a&&(o.has(l.colIdx)||o.set(l.colIdx,{name:a.name,type:a.type,values:new Set}),o.get(l.colIdx).values.add(l.value))}return o}function Ke(e){let n=Array.from(e||[]);if(n.length===0)return"";if(n.length>1)return"(mixed values)";let o=n[0];return o===null?"NULL":o instanceof Uint8Array?"[BLOB]":String(o)}function He(e,n,o){let l=[];for(let a of e){let s=n.get(a.colIdx);if(!s)continue;let i=s.dataset||{},r=i.isnull==="true",c=i.ispatch==="true",d=s.value;if(d===""&&!r)continue;let m=o&&o[a.colIdx];if(!m)continue;let g=d,f="set";if(r)g=null;else if(c)f="json_patch";else{let p=(m.type||"").toUpperCase();(p==="INTEGER"||p==="REAL"||p==="NUMERIC")&&!isNaN(Number(d))&&d.trim()!==""&&(g=Number(d))}l.push({rowId:a.rowId,column:m.name,value:g,originalValue:a.value,operation:f,rowIdx:a.rowIdx,colIdx:a.colIdx})}return l}function Je(){let e=document.getElementById("sidebarPanel");if(!e)return;let n=document.getElementById("sidebarFilterInput");n&&n.addEventListener("input",()=>{t.sidebarFilter=n.value,Y()}),e.addEventListener("click",o=>{let l=o.target;if(l.closest("#btnOpenSettings")){_e();return}if(l.closest("#btnOpenCreateTable")){o.stopPropagation(),Ve();return}if(l.closest("#btnReload")){ln();return}if(l.closest("#btnApplyBatchUpdate")){Zt();return}let a=l.closest(".list-item");if(a){let c=a.dataset.name,d=a.dataset.type;if(c&&d){on(c,d);return}}let s=l.closest(".section-title");if(s){if(l.closest(".icon-button")||s.id==="btnOpenSettings")return;let c=s.dataset.section;c&&nn(c)}let i=l.closest(".btn-batch-null");if(i){let c=i.closest(".batch-field");if(c){let d=parseInt(c.dataset.colidx,10);en(d)}return}let r=l.closest(".btn-batch-patch");if(r){let c=r.closest(".batch-field");if(c){let d=parseInt(c.dataset.colidx,10);tn(d,r)}return}})}async function V(){if(t.isDbConnected)try{let e=await C.fetchSchema();t.schemaCache.tables=(e.tables||[]).map(n=>({name:n.identifier})),t.schemaCache.views=(e.views||[]).map(n=>({name:n.identifier})),t.schemaCache.indexes=(e.indexes||[]).map(n=>({name:n.identifier,table:n.parentTable})),Y()}catch(e){console.error("Error loading schema:",e),u("Error loading schema")}}function be(e,n){return n?e.filter(o=>o.name.toLowerCase().includes(n)):e}function we(e,n,o,l){let a=document.getElementById(e);a&&(a.textContent=l?`${n}/${o}`:o)}function Ge(e,n,o,l,a){let s=document.getElementById(e);if(!s)return;if(s.replaceChildren(),n.length===0){let r=document.createElement("li");r.className="list-item",r.style.opacity="0.5",r.textContent=a,s.appendChild(r);return}let i=document.createDocumentFragment();n.forEach(r=>{let c=document.createElement("li");c.className="list-item",t.selectedTable===r.name&&t.selectedTableType===o&&c.classList.add("selected"),c.dataset.name=r.name,o&&(c.dataset.type=o),c.title=r.name;let d=document.createElement("span");d.className=`item-icon codicon ${l}`,c.appendChild(d);let m=document.createElement("span");m.className="item-name",m.textContent=r.name,c.appendChild(m),i.appendChild(c)}),s.appendChild(i)}function Qt(e,n,o){let l=document.getElementById(e);if(!l)return;if(l.replaceChildren(),n.length===0){let s=document.createElement("li");s.className="list-item",s.style.opacity="0.5",s.textContent=o,l.appendChild(s);return}let a=document.createDocumentFragment();n.forEach(s=>{let i=document.createElement("li");i.className="list-item",i.title=`${s.name} on ${s.table}`;let r=document.createElement("span");r.className="item-icon codicon codicon-list-selection",i.appendChild(r);let c=document.createElement("div");c.className="item-content";let d=document.createElement("span");d.className="item-name",d.textContent=s.name,c.appendChild(d);let m=document.createElement("span");m.className="item-detail",m.textContent=s.table,c.appendChild(m),i.appendChild(c),a.appendChild(i)}),l.appendChild(a)}function Y(){let e=t.sidebarFilter.toLowerCase(),n=e.length>0,o=be(t.schemaCache.tables,e),l=be(t.schemaCache.views,e),a=be(t.schemaCache.indexes,e);we("tablesBadge",o.length,t.schemaCache.tables.length,n),we("viewsBadge",l.length,t.schemaCache.views.length,n),we("indexesBadge",a.length,t.schemaCache.indexes.length,n),Ge("tablesList",o,"table","codicon-table",e?"No matching tables":"No tables"),Ge("viewsList",l,"view","codicon-eye",e?"No matching views":"No views"),Qt("indexesList",a,e?"No matching indexes":"No indexes")}function j(){let e=document.getElementById("batchUpdateSectionTitle"),n=document.getElementById("batchUpdateList"),o=document.getElementById("batchUpdateCount"),l=document.getElementById("batchUpdateFields");if(!e||!n||!o||!l)return;let a=t.selectedCells.length;if(a===0){e.classList.add("hidden"),n.classList.add("hidden");return}e.classList.remove("hidden"),n.classList.remove("hidden"),e.classList.remove("collapsed"),o.textContent=a;let s=qe(t.selectedCells,t.tableColumns);l.replaceChildren();let i=document.createDocumentFragment();for(let[r,c]of s){let d=Ke(c.values),m=document.createElement("div");m.className="form-field batch-field",m.dataset.colidx=r,m.style.marginBottom="8px";let g=document.createElement("label");g.style.fontSize="11px",g.style.color="var(--text-secondary)";let f=document.createTextNode(c.name+" ");g.appendChild(f);let p=document.createElement("span");p.style.opacity="0.7",p.textContent=c.type||"",g.appendChild(p),m.appendChild(g);let h=document.createElement("div");h.style.display="flex",h.style.gap="4px";let w=document.createElement("input");w.type="text",w.className="batch-input",w.placeholder=d,w.dataset.colidx=r,w.style.flex="1",w.style.minWidth="0",h.appendChild(w);let v=document.createElement("button");v.className="btn-secondary btn-batch-null",v.style.padding="2px 6px",v.title="Set to NULL",v.textContent="NULL",h.appendChild(v);let y=document.createElement("button");y.className="btn-secondary btn-batch-patch",y.style.padding="2px 6px",y.title="JSON Patch",y.textContent="{}",h.appendChild(y),m.appendChild(h),i.appendChild(m)}l.appendChild(i)}async function Zt(){if(t.selectedCells.length===0)return;let e=document.querySelectorAll(".batch-input"),n=new Map;for(let l of e){let a=parseInt(l.dataset.colidx,10);if(n.set(a,l),l.dataset.ispatch==="true")try{JSON.parse(l.value)}catch{let i=t.tableColumns[a];u(`Invalid JSON for patch in ${i?.name??`column ${a}`}`);return}}let o=He(t.selectedCells,n,t.tableColumns);if(o.length===0){u("No values entered for batch update");return}try{u(`Updating ${o.length} cells...`);let l=`Batch update ${o.length} cells`,a=o.map(r=>({rowId:r.rowId,column:r.column,value:r.value,originalValue:r.originalValue,operation:r.operation}));if(await C.updateCellBatch(t.selectedTable,a,l),!o.some(r=>r.operation==="json_patch"))for(let r of o)t.gridData[r.rowIdx][r.colIdx+B()]=r.value;await I(!1);let i=[];for(let r of t.selectedCells){let c=t.gridData[r.rowIdx][r.colIdx+B()];i.push({...r,value:c})}t.selectedCells=i,j(),u("Batch update completed")}catch(l){console.error("Batch update failed:",l),u(`Batch update failed: ${l.message}`)}}function en(e){let n=document.querySelector(`.batch-input[data-colidx="${e}"]`),o=document.querySelector(`.batch-field[data-colidx="${e}"] .btn-batch-patch`);n&&(n.value="",n.placeholder="SET TO NULL",n.dataset.isnull="true",n.dataset.ispatch="false",n.style.fontStyle="italic",o&&(o.style.background="",o.style.color=""))}function tn(e,n){let o=document.querySelector(`.batch-input[data-colidx="${e}"]`);o&&(o.dataset.ispatch==="true"?(o.dataset.ispatch="false",o.placeholder="(mixed values)",n.style.background="",n.style.color=""):(o.dataset.ispatch="true",o.dataset.isnull="false",o.placeholder='JSON Patch (e.g. {"a": 1})',o.style.fontStyle="normal",n.style.background="var(--accent-color)",n.style.color="white"))}function nn(e){let n=document.getElementById(`${e}List`),o=document.querySelector(`.section-title[data-section="${e}"]`);n&&o&&(n.classList.toggle("hidden"),o.classList.toggle("collapsed"))}async function on(e,n){t.selectedTable=e,t.selectedTableType=n,t.currentPageIndex=0,t.sortedColumn=null,t.sortAscending=!0,t.filterQuery="",t.columnFilters={},t.selectedRowIds.clear(),t.selectedCells=[],t.lastSelectedCell=null,t.selectedColumns.clear(),t.pinnedColumns.clear(),t.pinnedRowIds.clear(),t.columnWidths={},t.scrollPosition={top:0,left:0},Y();let o=document.getElementById("tableNameLabel");o&&(o.textContent=e);let l=document.getElementById("filterInput");l&&(l.value=""),await z(),await I(!0,!1),$()}async function ln(){if(t.isDbConnected)try{u("Reloading..."),await C.refreshFile(),await V(),t.selectedTable&&(await z(),await I()),u("Reloaded")}catch(e){console.error("Reload failed:",e),u(`Reload failed: ${e.message}`)}}var Q=new Set,Z=new Set;function Xe(){Q.clear(),t.selectedCells.length>0&&t.selectedCells.forEach(e=>{Q.add(`cell-${e.rowIdx}-${e.colIdx}`)}),Z.clear(),t.selectedRowIds.size>0&&document.querySelectorAll(".data-row.selected").forEach(n=>{n.id&&Z.add(n.id)})}function F(){let e=new Set;for(let o of t.selectedCells)e.add(`cell-${o.rowIdx}-${o.colIdx}`);for(let o of Q)if(!e.has(o)){let l=document.getElementById(o);l&&l.classList.remove("cell-selected")}for(let o of e)if(!Q.has(o)){let l=document.getElementById(o);l&&l.classList.add("cell-selected")}Q=e;let n=new Set;for(let o=0;oo.classList.remove("column-selected")),t.selectedColumns.size>0&&t.selectedColumns.forEach(o=>{let l=CSS.escape(o),a=document.querySelector(`.header-cell[data-column="${l}"]`);a&&a.classList.add("column-selected")})}function se(){t.selectedCells=[],t.selectedRowIds.clear(),t.selectedColumns.clear(),t.lastSelectedCell=null,F(),R(),j()}function an(){let e=document.createElement("div");return e.className="empty-view",e.innerHTML=` No data This table is empty - `,e}function sn(e,n,o){let l=document.createElement("thead");l.className="grid-header";let a=document.createElement("tr"),s=document.createElement("th");s.className="header-cell row-number-header",Object.assign(s.style,{width:`${e}px`,minWidth:`${e}px`,maxWidth:`${e}px`,position:"sticky",left:"0",top:"0",zIndex:"11",background:"var(--bg-secondary)"}),s.title="Click to select all rows",s.innerHTML='
#
',a.appendChild(s);for(let i of n){let r=t.sortedColumn===i.name,c=t.pinnedColumns.has(i.name),d=t.selectedColumns.has(i.name),m=t.columnWidths[i.name]||120,f=t.columnFilters[i.name]||"",g=document.createElement("th");g.className=`header-cell ${c?"pinned":""} ${d?"column-selected":""}`,Object.assign(g.style,{width:`${m}px`,minWidth:`${m}px`,maxWidth:`${m}px`}),c&&(g.style.position="sticky",g.style.left=`${o.get(i.name)}px`),g.dataset.column=i.name;let p=X(i.name),h=X(f),w=r?`${t.sortAscending?"\u25B2":"\u25BC"}`:"",v=i.isPrimaryKey?'':"",y=c?"pinned":"",x=c?"Unpin column":"Pin column";g.innerHTML=` + `,e}function sn(e,n,o){let l=document.createElement("thead");l.className="grid-header";let a=document.createElement("tr"),s=document.createElement("th");s.className="header-cell row-number-header",Object.assign(s.style,{width:`${e}px`,minWidth:`${e}px`,maxWidth:`${e}px`,position:"sticky",left:"0",top:"0",zIndex:"11",background:"var(--bg-secondary)"}),s.title="Click to select all rows",s.innerHTML='
#
',a.appendChild(s);for(let i of n){let r=t.sortedColumn===i.name,c=t.pinnedColumns.has(i.name),d=t.selectedColumns.has(i.name),m=t.columnWidths[i.name]||120,g=t.columnFilters[i.name]||"",f=document.createElement("th");f.className=`header-cell ${c?"pinned":""} ${d?"column-selected":""}`,Object.assign(f.style,{width:`${m}px`,minWidth:`${m}px`,maxWidth:`${m}px`}),c&&(f.style.position="sticky",f.style.left=`${o.get(i.name)}px`),f.dataset.column=i.name;let p=X(i.name),h=X(g),w=r?`${t.sortAscending?"\u25B2":"\u25BC"}`:"",v=i.isPrimaryKey?'':"",y=c?"pinned":"",x=c?"Unpin column":"Pin column";f.innerHTML=`
${v}${p}${w} @@ -398,9 +398,9 @@
- `,a.appendChild(g)}return l.appendChild(a),l}function rn(e,n,o,l,a,s,i,r){let c=document.createElement("tbody"),d=[];for(let p=0;p({idx:h,rowId:T(p,h)})).filter(p=>t.pinnedRowIds.has(p.rowId)),...t.gridData.map((p,h)=>({idx:h,rowId:T(p,h)})).filter(p=>!t.pinnedRowIds.has(p.rowId))],g=document.createDocumentFragment();for(let{idx:p,rowId:h}of f){let w=t.gridData[p],v=t.selectedRowIds.has(h),y=t.pinnedRowIds.has(h),x=document.createElement("tr");x.id=`row-${p}`,x.className=`data-row ${v?"selected":""} ${y?"pinned":""}`,x.dataset.rowid=h,x.dataset.rowidx=p,y&&(x.style.top=`${m.get(h)}px`);let k=document.createElement("td");k.className="data-cell row-number",Object.assign(k.style,{width:`${l}px`,minWidth:`${l}px`,maxWidth:`${l}px`,position:"sticky",left:"0",zIndex:y?"8":"2"});let L=t.currentPageIndex*t.rowsPerPage+p+1;k.appendChild(document.createTextNode(String(L)));let b=document.createElement("span");b.className=`pin-icon codicon codicon-pin ${y?"pinned":""}`,b.title=y?"Unpin row":"Pin row",k.appendChild(b),x.appendChild(k);for(let D=0;Db&&b.trim()!=="");if(r.innerHTML="",t.gridData.length===0&&!g&&t.tableColumns.length===0){r.appendChild(an());return}let p=new Set;if(t.selectedCells.length>0)for(let b of t.selectedCells)p.add(`${b.rowIdx},${b.colIdx}`);let h=document.createElement("table");if(h.className="data-grid",Object.keys(t.columnWidths).length===0&&t.gridData.length>0)for(let b of t.tableColumns){let D=b.name.length,N=b.isPrimaryKey?86:70,q=D*8+N;t.columnWidths[b.name]=Math.max(80,Math.min(250,q))}let w=[...t.tableColumns.filter(b=>t.pinnedColumns.has(b.name)),...t.tableColumns.filter(b=>!t.pinnedColumns.has(b.name))],v=new Map,y=i-1;for(let b of w)t.pinnedColumns.has(b.name)&&(v.set(b.name,y),y+=t.columnWidths[b.name]||120);let x=new Map;t.tableColumns.forEach((b,D)=>x.set(b.name,D));let k=sn(i,w,v);h.appendChild(k);let L=rn(w,x,v,i,52,26,p,g);h.appendChild(L),r.appendChild(h),r.scrollLeft=m,r.scrollTop=f,Xe()}function Ye(){document.getElementById("pageIndicator").textContent=`${t.currentPageIndex+1} / ${t.totalPageCount}`,document.getElementById("btnFirst").disabled=t.currentPageIndex===0,document.getElementById("btnPrev").disabled=t.currentPageIndex===0,document.getElementById("btnNext").disabled=t.currentPageIndex>=t.totalPageCount-1,document.getElementById("btnLast").disabled=t.currentPageIndex>=t.totalPageCount-1}async function z(){if(t.selectedTable)try{let e=await C.getTableInfo(t.selectedTable);t.tableColumns=e.map(o=>({cid:o.ordinal,name:o.identifier,type:o.declaredType,notnull:o.isRequired,dflt_value:o.defaultExpression,isPrimaryKey:o.primaryKeyPosition>0})).sort((o,l)=>o.cid-l.cid);let n=new Set(t.tableColumns.map(o=>o.name));t.sortedColumn&&!n.has(t.sortedColumn)&&(t.sortedColumn=null,t.sortAscending=!0);for(let o of Object.keys(t.columnFilters))n.has(o)||delete t.columnFilters[o]}catch(e){console.error("Error loading columns:",e),u("Error loading columns")}}async function I(e=!0,n=!0){if(!t.selectedTable)return;let o=document.getElementById("gridContainer");n&&o&&o.querySelector(".data-grid")&&(t.scrollPosition.left=o.scrollLeft,t.scrollPosition.top=o.scrollTop),e&&(t.isLoadingData=!0,(!o||!o.querySelector(".data-grid"))&&$e()),R();try{let l=[];for(let[m,f]of Object.entries(t.columnFilters))f&&f.trim()&&l.push({column:m,value:f});let a={filters:l,globalFilter:t.filterQuery,columns:t.tableColumns.map(m=>m.name)};t.totalRecordCount=await C.fetchTableCount(t.selectedTable,a),t.totalPageCount=Math.max(1,Math.ceil(t.totalRecordCount/t.rowsPerPage)),t.currentPageIndex>=t.totalPageCount&&(t.currentPageIndex=Math.max(0,t.totalPageCount-1));let s=t.selectedTableType==="table",i=t.tableColumns.map(m=>m.name),c={columns:s?["rowid",...i]:i,orderBy:t.sortedColumn,orderDir:t.sortAscending?"ASC":"DESC",limit:t.rowsPerPage,offset:t.currentPageIndex*t.rowsPerPage,filters:l,globalFilter:t.filterQuery},d=await C.fetchTableData(t.selectedTable,c);t.gridData=d.rows||[],!e&&o&&o.querySelector(".data-grid")&&(t.scrollPosition.left=o.scrollLeft,t.scrollPosition.top=o.scrollTop),!e&&t.editingCellInfo||_(t.scrollPosition.top,t.scrollPosition.left),o&&(o.scrollLeft=t.scrollPosition.left,o.scrollTop=t.scrollPosition.top),Ye(),u(`${t.totalRecordCount} records`)}catch(l){console.error("Error loading data:",l),u(`Error: ${l.message}`),le(l.message)}finally{e&&(t.isLoadingData=!1)}}var S={PNG:[137,80,78,71,13,10,26,10],JPEG:[255,216,255],GIF:[71,73,70,56],BMP:[66,77],RIFF:[82,73,70,70],WEBP:[87,69,66,80],PDF:[37,80,68,70,45],ID3:[73,68,51],MP3_SYNC1:[255,251],MP3_SYNC2:[255,243],MP3_SYNC3:[255,242],OGG:[79,103,103,83],WAVE:[87,65,86,69],FLAC:[102,76,97,67],FTYP:[102,116,121,112],WEBM:[26,69,223,163],AVI:[65,86,73,32]},ie=class{constructor(){this.currentObjectUrl=null,this.modal=document.getElementById("blob-inspector-modal"),this.previewContainer=document.getElementById("tab-preview"),this.hexContainer=document.querySelector(".hex-dump"),this.infoContainer=document.getElementById("blob-info"),this.currentData=null,this.currentType=null,this.currentRowId=null,this.currentColName=null,this.currentCellInfo=null,this.isUploading=!1,this.setupEventListeners()}setupEventListeners(){this.modal.querySelectorAll(".modal-close").forEach(l=>{l.addEventListener("click",()=>this.close())}),this.modal.querySelectorAll(".tab-btn").forEach(l=>{l.addEventListener("click",a=>{let s=a.target.dataset.tab;this.switchTab(s)})});let n=document.getElementById("blob-download-btn");n&&n.addEventListener("click",()=>this.download());let o=document.getElementById("blob-replace-btn");o&&o.addEventListener("click",()=>this.handleReplace())}setUploadState(n){this.isUploading=n;let o=document.getElementById("blob-replace-btn"),l=document.getElementById("blob-download-btn");o&&(o.disabled=n,o.textContent=n?"Uploading...":"Replace"),l&&(l.disabled=n)}async handleReplace(){if(!this.isUploading)try{if(((await C.getExtensionSettings())?.fileOperations||"native")==="web")this.showFileInput();else{let l=await C.selectFile();if(l){let a=l.data;if(!(a instanceof Uint8Array)){if(Array.isArray(a))a=new Uint8Array(a);else if(a&&typeof a=="object"){let i=Object.keys(a).filter(r=>!isNaN(parseInt(r,10))).sort((r,c)=>parseInt(r,10)-parseInt(c,10)).map(r=>a[r]);a=new Uint8Array(i)}}let s={name:l.name,arrayBuffer:async()=>a.buffer};await this.uploadFile(s)}}}catch(n){console.error("Replace failed:",n),u(`Replace failed: ${n.message}`)}}showFileInput(){let n=document.createElement("input");n.type="file",n.onchange=async o=>{let l=o.target.files[0];l&&await this.uploadFile(l)},n.click()}async uploadFile(n){if(!(!this.currentRowId||!this.currentColName)&&!this.isUploading){this.setUploadState(!0);try{u(`Reading ${n.name}...`);let o=await n.arrayBuffer(),l=new Uint8Array(o),a=l.length/(1024*1024),s=50;if(a>s)throw new Error(`File too large (${a.toFixed(1)}MB). Maximum size is ${s}MB to prevent freezing.`);a>10?u(`Uploading ${n.name} (${a.toFixed(1)}MB - this may take a moment)...`):u(`Uploading ${n.name}...`);let{rowIdx:i,colIdx:r}=this.currentCellInfo,c=this.currentData;await C.updateCell(t.selectedTable,this.currentRowId,this.currentColName,l,c),t.gridData&&t.gridData[i]&&(t.gridData[i][r+B()]=l),this.inspect(l,this.currentRowId,this.currentColName,i,r),u(`Replaced with ${n.name}`)}catch(o){console.error("Replace failed:",o);let l=o.message||String(o);l.includes("timeout")&&(l="Upload timed out. Try a smaller file or increase the timeout."),u(`Replace failed: ${l}`)}finally{this.setUploadState(!1)}}}close(){this.modal.classList.add("hidden"),this.cleanup()}cleanup(){this.setUploadState(!1),this.currentObjectUrl&&(URL.revokeObjectURL(this.currentObjectUrl),this.currentObjectUrl=null),this.previewContainer.innerHTML="",this.hexContainer.value="",this.infoContainer.textContent="",this.currentData=null}switchTab(n){this.modal.querySelectorAll(".tab-btn").forEach(a=>{a.dataset.tab===n?(a.classList.add("active"),a.style.borderBottom="2px solid var(--accent-color)",a.style.color="var(--text-primary)"):(a.classList.remove("active"),a.style.borderBottom="none",a.style.color="var(--text-secondary)")});let o=document.getElementById("tab-preview"),l=document.getElementById("tab-hex");n==="preview"?(o.style.display="flex",l.style.display="none"):(o.style.display="none",l.style.display="block")}async download(){if(!this.currentData)return;let n=this.currentType?.ext||"bin",o=`blob_${this.currentRowId}.${n}`;try{((await C.getExtensionSettings())?.fileOperations||"native")==="web"?(this.downloadBlob(this.currentData,o),u(`Downloaded ${o}`)):(await C.saveFile(o,this.currentData),u(`Saved ${o}`))}catch(l){console.error("Download failed:",l),u(`Download failed: ${l.message}`)}}downloadBlob(n,o){let l=new Blob([n]),a=URL.createObjectURL(l),s=document.createElement("a");s.href=a,s.download=o,s.click(),URL.revokeObjectURL(a)}inspect(n,o,l,a,s){this.cleanup(),this.currentRowId=o,this.currentColName=l,this.currentCellInfo={rowIdx:a,colIdx:s},this.modal.classList.remove("hidden"),this.switchTab("preview");let i=n instanceof Uint8Array?n:new Uint8Array(n);this.currentData=i;let r=this.detectType(i);this.currentType=r;let c=this.formatSize(i.length);this.infoContainer.textContent=`${l} (Row ${o}) | ${r.mime||"Unknown Type"} | ${c}`,this.renderPreview(i,r),this.renderHex(i)}detectType(n){if(this.checkSignature(n,S.PNG))return{mime:"image/png",type:"image",ext:"png"};if(this.checkSignature(n,S.JPEG))return{mime:"image/jpeg",type:"image",ext:"jpg"};if(this.checkSignature(n,S.GIF))return{mime:"image/gif",type:"image",ext:"gif"};if(this.checkSignature(n,S.BMP))return{mime:"image/bmp",type:"image",ext:"bmp"};if(this.checkSignature(n,S.RIFF)&&this.checkSignature(n.subarray(8),S.WEBP))return{mime:"image/webp",type:"image",ext:"webp"};if(this.checkSignature(n,S.PDF))return{mime:"application/pdf",type:"pdf",ext:"pdf"};if(this.checkSignature(n,S.ID3))return{mime:"audio/mpeg",type:"audio",ext:"mp3"};if(this.checkSignature(n,S.MP3_SYNC1)||this.checkSignature(n,S.MP3_SYNC2)||this.checkSignature(n,S.MP3_SYNC3))return{mime:"audio/mpeg",type:"audio",ext:"mp3"};if(this.checkSignature(n,S.OGG))return{mime:"audio/ogg",type:"audio",ext:"ogg"};if(this.checkSignature(n,S.RIFF)&&this.checkSignature(n.subarray(8),S.WAVE))return{mime:"audio/wav",type:"audio",ext:"wav"};if(this.checkSignature(n,S.FLAC))return{mime:"audio/flac",type:"audio",ext:"flac"};if(this.checkSignature(n.subarray(4),S.FTYP)){let o=String.fromCharCode(...n.subarray(8,12));return o.startsWith("mp4")||o==="isom"||o==="avc1"||o==="M4V "?{mime:"video/mp4",type:"video",ext:"mp4"}:o==="qt "||o.startsWith("M4A")?{mime:"video/quicktime",type:"video",ext:"mov"}:{mime:"video/mp4",type:"video",ext:"mp4"}}if(this.checkSignature(n,S.WEBM))return{mime:"video/webm",type:"video",ext:"webm"};if(this.checkSignature(n,S.RIFF)&&this.checkSignature(n.subarray(8),S.AVI))return{mime:"video/avi",type:"video",ext:"avi"};if(this.isText(n)){try{let o=new TextDecoder().decode(n),l=JSON.parse(o);if(typeof l=="object"&&l!==null)return{mime:"application/json",type:"json",ext:"json"}}catch{}return{mime:"text/plain",type:"text",ext:"txt"}}return{mime:"application/octet-stream",type:"binary",ext:"bin"}}checkSignature(n,o){if(n.lengththis.download()),l.appendChild(a),l.appendChild(s),l.appendChild(i),this.previewContainer.appendChild(l)}else{let l=document.createElement("div");l.className="empty-view";let a=document.createElement("span");a.className="codicon codicon-file-binary",a.style.fontSize="48px",a.style.opacity="0.5";let s=document.createElement("span");s.style.marginTop="12px",s.textContent="Binary Data";let i=document.createElement("span");i.style.fontSize="12px",i.style.opacity="0.7",i.textContent="Use Hex view to inspect",l.appendChild(a),l.appendChild(s),l.appendChild(i),this.previewContainer.appendChild(l)}}renderHex(n){if(!this.hexContainer)return;let o=16*1e3,l="",a=n.subarray(0,o);for(let s=0;s=32&&p<=126?String.fromCharCode(p):".")}else r.push(" "),c.push(" ");let d=r.slice(0,8).join(" "),m=r.slice(8).join(" "),f=c.join("");l+=`${i} ${d} ${m} |${f}| + `,a.appendChild(f)}return l.appendChild(a),l}function rn(e,n,o,l,a,s,i,r){let c=document.createElement("tbody"),d=[];for(let p=0;p({idx:h,rowId:T(p,h)})).filter(p=>t.pinnedRowIds.has(p.rowId)),...t.gridData.map((p,h)=>({idx:h,rowId:T(p,h)})).filter(p=>!t.pinnedRowIds.has(p.rowId))],f=document.createDocumentFragment();for(let{idx:p,rowId:h}of g){let w=t.gridData[p],v=t.selectedRowIds.has(h),y=t.pinnedRowIds.has(h),x=document.createElement("tr");x.id=`row-${p}`,x.className=`data-row ${v?"selected":""} ${y?"pinned":""}`,x.dataset.rowid=h,x.dataset.rowidx=p,y&&(x.style.top=`${m.get(h)}px`);let k=document.createElement("td");k.className="data-cell row-number",Object.assign(k.style,{width:`${l}px`,minWidth:`${l}px`,maxWidth:`${l}px`,position:"sticky",left:"0",zIndex:y?"8":"2"});let L=t.currentPageIndex*t.rowsPerPage+p+1;k.appendChild(document.createTextNode(String(L)));let b=document.createElement("span");b.className=`pin-icon codicon codicon-pin ${y?"pinned":""}`,b.title=y?"Unpin row":"Pin row",k.appendChild(b),x.appendChild(k);for(let D=0;Db&&b.trim()!=="");if(r.innerHTML="",t.gridData.length===0&&!f&&t.tableColumns.length===0){r.appendChild(an());return}let p=new Set;if(t.selectedCells.length>0)for(let b of t.selectedCells)p.add(`${b.rowIdx},${b.colIdx}`);let h=document.createElement("table");if(h.className="data-grid",Object.keys(t.columnWidths).length===0&&t.gridData.length>0)for(let b of t.tableColumns){let D=b.name.length,N=b.isPrimaryKey?86:70,q=D*8+N;t.columnWidths[b.name]=Math.max(80,Math.min(250,q))}let w=[...t.tableColumns.filter(b=>t.pinnedColumns.has(b.name)),...t.tableColumns.filter(b=>!t.pinnedColumns.has(b.name))],v=new Map,y=i-1;for(let b of w)t.pinnedColumns.has(b.name)&&(v.set(b.name,y),y+=t.columnWidths[b.name]||120);let x=new Map;t.tableColumns.forEach((b,D)=>x.set(b.name,D));let k=sn(i,w,v);h.appendChild(k);let L=rn(w,x,v,i,52,26,p,f);h.appendChild(L),r.appendChild(h),r.scrollLeft=m,r.scrollTop=g,Xe()}function Ye(){document.getElementById("pageIndicator").textContent=`${t.currentPageIndex+1} / ${t.totalPageCount}`,document.getElementById("btnFirst").disabled=t.currentPageIndex===0,document.getElementById("btnPrev").disabled=t.currentPageIndex===0,document.getElementById("btnNext").disabled=t.currentPageIndex>=t.totalPageCount-1,document.getElementById("btnLast").disabled=t.currentPageIndex>=t.totalPageCount-1}async function z(){if(t.selectedTable)try{let e=await C.getTableInfo(t.selectedTable);t.tableColumns=e.map(o=>({cid:o.ordinal,name:o.identifier,type:o.declaredType,notnull:o.isRequired,dflt_value:o.defaultExpression,isPrimaryKey:o.primaryKeyPosition>0})).sort((o,l)=>o.cid-l.cid);let n=new Set(t.tableColumns.map(o=>o.name));t.sortedColumn&&!n.has(t.sortedColumn)&&(t.sortedColumn=null,t.sortAscending=!0);for(let o of Object.keys(t.columnFilters))n.has(o)||delete t.columnFilters[o]}catch(e){console.error("Error loading columns:",e),u("Error loading columns")}}async function I(e=!0,n=!0){if(!t.selectedTable)return;let o=document.getElementById("gridContainer"),l=!!(o&&o.querySelector(".data-grid"));n&&l&&(t.scrollPosition.left=o.scrollLeft,t.scrollPosition.top=o.scrollTop),e&&(t.isLoadingData=!0,l||$e()),R();try{let a=[];for(let[g,f]of Object.entries(t.columnFilters))f&&f.trim()&&a.push({column:g,value:f});let s=t.tableColumns.map(g=>g.name),i={filters:a,globalFilter:t.filterQuery,columns:s};t.totalRecordCount=await C.fetchTableCount(t.selectedTable,i),t.totalPageCount=Math.max(1,Math.ceil(t.totalRecordCount/t.rowsPerPage)),t.currentPageIndex>=t.totalPageCount&&(t.currentPageIndex=Math.max(0,t.totalPageCount-1));let d={columns:t.selectedTableType==="table"?["rowid",...s]:s,orderBy:t.sortedColumn,orderDir:t.sortAscending?"ASC":"DESC",limit:t.rowsPerPage,offset:t.currentPageIndex*t.rowsPerPage,filters:a,globalFilter:t.filterQuery},m=await C.fetchTableData(t.selectedTable,d);t.gridData=m.rows||[],!e&&o&&o.querySelector(".data-grid")&&(t.scrollPosition.left=o.scrollLeft,t.scrollPosition.top=o.scrollTop),!e&&t.editingCellInfo||_(t.scrollPosition.top,t.scrollPosition.left),o&&(o.scrollLeft=t.scrollPosition.left,o.scrollTop=t.scrollPosition.top),Ye(),u(`${t.totalRecordCount} records`)}catch(a){console.error("Error loading data:",a),u(`Error: ${a.message}`),le(a.message)}finally{e&&(t.isLoadingData=!1)}}var S={PNG:[137,80,78,71,13,10,26,10],JPEG:[255,216,255],GIF:[71,73,70,56],BMP:[66,77],RIFF:[82,73,70,70],WEBP:[87,69,66,80],PDF:[37,80,68,70,45],ID3:[73,68,51],MP3_SYNC1:[255,251],MP3_SYNC2:[255,243],MP3_SYNC3:[255,242],OGG:[79,103,103,83],WAVE:[87,65,86,69],FLAC:[102,76,97,67],FTYP:[102,116,121,112],WEBM:[26,69,223,163],AVI:[65,86,73,32]},ie=class{constructor(){this.currentObjectUrl=null,this.modal=document.getElementById("blob-inspector-modal"),this.previewContainer=document.getElementById("tab-preview"),this.hexContainer=document.querySelector(".hex-dump"),this.infoContainer=document.getElementById("blob-info"),this.currentData=null,this.currentType=null,this.currentRowId=null,this.currentColName=null,this.currentCellInfo=null,this.isUploading=!1,this.setupEventListeners()}setupEventListeners(){this.modal.querySelectorAll(".modal-close").forEach(l=>{l.addEventListener("click",()=>this.close())}),this.modal.querySelectorAll(".tab-btn").forEach(l=>{l.addEventListener("click",a=>{let s=a.target.dataset.tab;this.switchTab(s)})});let n=document.getElementById("blob-download-btn");n&&n.addEventListener("click",()=>this.download());let o=document.getElementById("blob-replace-btn");o&&o.addEventListener("click",()=>this.handleReplace())}setUploadState(n){this.isUploading=n;let o=document.getElementById("blob-replace-btn"),l=document.getElementById("blob-download-btn");o&&(o.disabled=n,o.textContent=n?"Uploading...":"Replace"),l&&(l.disabled=n)}async handleReplace(){if(!this.isUploading)try{if(((await C.getExtensionSettings())?.fileOperations||"native")==="web")this.showFileInput();else{let l=await C.selectFile();if(l){let a=l.data;if(!(a instanceof Uint8Array)){if(Array.isArray(a))a=new Uint8Array(a);else if(a&&typeof a=="object"){let i=Object.keys(a).filter(r=>!isNaN(parseInt(r,10))).sort((r,c)=>parseInt(r,10)-parseInt(c,10)).map(r=>a[r]);a=new Uint8Array(i)}}let s={name:l.name,arrayBuffer:async()=>a.buffer};await this.uploadFile(s)}}}catch(n){console.error("Replace failed:",n),u(`Replace failed: ${n.message}`)}}showFileInput(){let n=document.createElement("input");n.type="file",n.onchange=async o=>{let l=o.target.files[0];l&&await this.uploadFile(l)},n.click()}async uploadFile(n){if(!(!this.currentRowId||!this.currentColName)&&!this.isUploading){this.setUploadState(!0);try{u(`Reading ${n.name}...`);let o=await n.arrayBuffer(),l=new Uint8Array(o),a=l.length/(1024*1024),s=50;if(a>s)throw new Error(`File too large (${a.toFixed(1)}MB). Maximum size is ${s}MB to prevent freezing.`);a>10?u(`Uploading ${n.name} (${a.toFixed(1)}MB - this may take a moment)...`):u(`Uploading ${n.name}...`);let{rowIdx:i,colIdx:r}=this.currentCellInfo,c=this.currentData;await C.updateCell(t.selectedTable,this.currentRowId,this.currentColName,l,c),t.gridData&&t.gridData[i]&&(t.gridData[i][r+B()]=l),this.inspect(l,this.currentRowId,this.currentColName,i,r),u(`Replaced with ${n.name}`)}catch(o){console.error("Replace failed:",o);let l=o.message||String(o);l.includes("timeout")&&(l="Upload timed out. Try a smaller file or increase the timeout."),u(`Replace failed: ${l}`)}finally{this.setUploadState(!1)}}}close(){this.modal.classList.add("hidden"),this.cleanup()}cleanup(){this.setUploadState(!1),this.currentObjectUrl&&(URL.revokeObjectURL(this.currentObjectUrl),this.currentObjectUrl=null),this.previewContainer.innerHTML="",this.hexContainer.value="",this.infoContainer.textContent="",this.currentData=null}switchTab(n){this.modal.querySelectorAll(".tab-btn").forEach(a=>{a.dataset.tab===n?(a.classList.add("active"),a.style.borderBottom="2px solid var(--accent-color)",a.style.color="var(--text-primary)"):(a.classList.remove("active"),a.style.borderBottom="none",a.style.color="var(--text-secondary)")});let o=document.getElementById("tab-preview"),l=document.getElementById("tab-hex");n==="preview"?(o.style.display="flex",l.style.display="none"):(o.style.display="none",l.style.display="block")}async download(){if(!this.currentData)return;let n=this.currentType?.ext||"bin",o=`blob_${this.currentRowId}.${n}`;try{((await C.getExtensionSettings())?.fileOperations||"native")==="web"?(this.downloadBlob(this.currentData,o),u(`Downloaded ${o}`)):(await C.saveFile(o,this.currentData),u(`Saved ${o}`))}catch(l){console.error("Download failed:",l),u(`Download failed: ${l.message}`)}}downloadBlob(n,o){let l=new Blob([n]),a=URL.createObjectURL(l),s=document.createElement("a");s.href=a,s.download=o,s.click(),URL.revokeObjectURL(a)}inspect(n,o,l,a,s){this.cleanup(),this.currentRowId=o,this.currentColName=l,this.currentCellInfo={rowIdx:a,colIdx:s},this.modal.classList.remove("hidden"),this.switchTab("preview");let i=n instanceof Uint8Array?n:new Uint8Array(n);this.currentData=i;let r=this.detectType(i);this.currentType=r;let c=this.formatSize(i.length);this.infoContainer.textContent=`${l} (Row ${o}) | ${r.mime||"Unknown Type"} | ${c}`,this.renderPreview(i,r),this.renderHex(i)}detectType(n){if(this.checkSignature(n,S.PNG))return{mime:"image/png",type:"image",ext:"png"};if(this.checkSignature(n,S.JPEG))return{mime:"image/jpeg",type:"image",ext:"jpg"};if(this.checkSignature(n,S.GIF))return{mime:"image/gif",type:"image",ext:"gif"};if(this.checkSignature(n,S.BMP))return{mime:"image/bmp",type:"image",ext:"bmp"};if(this.checkSignature(n,S.RIFF)&&this.checkSignature(n.subarray(8),S.WEBP))return{mime:"image/webp",type:"image",ext:"webp"};if(this.checkSignature(n,S.PDF))return{mime:"application/pdf",type:"pdf",ext:"pdf"};if(this.checkSignature(n,S.ID3))return{mime:"audio/mpeg",type:"audio",ext:"mp3"};if(this.checkSignature(n,S.MP3_SYNC1)||this.checkSignature(n,S.MP3_SYNC2)||this.checkSignature(n,S.MP3_SYNC3))return{mime:"audio/mpeg",type:"audio",ext:"mp3"};if(this.checkSignature(n,S.OGG))return{mime:"audio/ogg",type:"audio",ext:"ogg"};if(this.checkSignature(n,S.RIFF)&&this.checkSignature(n.subarray(8),S.WAVE))return{mime:"audio/wav",type:"audio",ext:"wav"};if(this.checkSignature(n,S.FLAC))return{mime:"audio/flac",type:"audio",ext:"flac"};if(this.checkSignature(n.subarray(4),S.FTYP)){let o=String.fromCharCode(...n.subarray(8,12));return o.startsWith("mp4")||o==="isom"||o==="avc1"||o==="M4V "?{mime:"video/mp4",type:"video",ext:"mp4"}:o==="qt "||o.startsWith("M4A")?{mime:"video/quicktime",type:"video",ext:"mov"}:{mime:"video/mp4",type:"video",ext:"mp4"}}if(this.checkSignature(n,S.WEBM))return{mime:"video/webm",type:"video",ext:"webm"};if(this.checkSignature(n,S.RIFF)&&this.checkSignature(n.subarray(8),S.AVI))return{mime:"video/avi",type:"video",ext:"avi"};if(this.isText(n)){try{let o=new TextDecoder().decode(n),l=JSON.parse(o);if(typeof l=="object"&&l!==null)return{mime:"application/json",type:"json",ext:"json"}}catch{}return{mime:"text/plain",type:"text",ext:"txt"}}return{mime:"application/octet-stream",type:"binary",ext:"bin"}}checkSignature(n,o){if(n.lengththis.download()),l.appendChild(a),l.appendChild(s),l.appendChild(i),this.previewContainer.appendChild(l)}else{let l=document.createElement("div");l.className="empty-view";let a=document.createElement("span");a.className="codicon codicon-file-binary",a.style.fontSize="48px",a.style.opacity="0.5";let s=document.createElement("span");s.style.marginTop="12px",s.textContent="Binary Data";let i=document.createElement("span");i.style.fontSize="12px",i.style.opacity="0.7",i.textContent="Use Hex view to inspect",l.appendChild(a),l.appendChild(s),l.appendChild(i),this.previewContainer.appendChild(l)}}renderHex(n){if(!this.hexContainer)return;let o=16*1e3,l="",a=n.subarray(0,o);for(let s=0;s=32&&p<=126?String.fromCharCode(p):".")}else r.push(" "),c.push(" ");let d=r.slice(0,8).join(" "),m=r.slice(8).join(" "),g=c.join("");l+=`${i} ${d} ${m} |${g}| `}n.length>o&&(l+=` -... (${(n.length-o).toLocaleString()} more bytes not shown)`),this.hexContainer.value=l}formatSize(n){if(n===0)return"0 B";let o=1024,l=["B","KB","MB","GB"],a=Math.floor(Math.log(n)/Math.log(o));return parseFloat((n/Math.pow(o,a)).toFixed(2))+" "+l[a]}};var Ee;function Qe(){Ee=new ie,document.getElementById("btnCloseCellPreview")?.addEventListener("click",G),document.getElementById("formatJsonBtn")?.addEventListener("click",cn),document.getElementById("compactJsonBtn")?.addEventListener("click",dn),document.getElementById("wrapTextBtn")?.addEventListener("click",un),document.getElementById("openInVsCodeBtn")?.addEventListener("click",Ie),document.getElementById("btnCancelCellPreview")?.addEventListener("click",G),document.getElementById("cellPreviewSaveBtn")?.addEventListener("click",lt)}function Ze(e,n,o){if(t.selectedTableType!=="table"){u("Views are read-only");return}if(t.editingCellInfo){if(t.editingCellInfo.rowIdx===e&&t.editingCellInfo.colIdx===n)return;ce()}let l=t.tableColumns[n];if(!l)return;let a=document.getElementById(`cell-${e}-${n}`);if(!a)return;let s=t.gridData[e],i=P(s,n);if(i instanceof Uint8Array){H(e,n,o);return}if(typeof i=="string"){let d=i.trim();if(d.startsWith("{")&&d.endsWith("}")||d.startsWith("[")&&d.endsWith("]"))try{JSON.parse(d),H(e,n,o);return}catch{}}t.editingCellInfo={rowIdx:e,colIdx:n,rowId:o,columnName:l.name,originalValue:i};let r=i===null?"":String(i);a.innerHTML="",a.classList.add("editing");let c=document.createElement("textarea");c.className="cell-input",c.value=r,c.spellcheck=!1,a.appendChild(c),c.focus(),t.activeCellInput=c,c.addEventListener("keydown",et),c.addEventListener("blur",tt),c.addEventListener("click",d=>d.stopPropagation()),t.isTransitioningEdit=!0,setTimeout(()=>{t.isTransitioningEdit=!1},100)}function et(e){e.key==="Enter"&&!e.shiftKey?(e.preventDefault(),nt()):e.key==="Escape"&&(e.preventDefault(),ce())}function tt(){setTimeout(()=>{t.editingCellInfo&&nt()},100)}async function nt(){if(t.isSavingCell||!t.editingCellInfo||!t.activeCellInput)return;let{rowIdx:e,colIdx:n,rowId:o,columnName:l,originalValue:a}=t.editingCellInfo,s=t.activeCellInput.value,i=a===null?"":String(a);if(s===i){ce(),t.selectedCells=[],t.lastSelectedCell=null,F();return}let r=t.tableColumns[n],c=r&&r.notnull===1,d;s===""?c?d="":d=null:!isNaN(Number(s))&&s.trim()!==""?d=Number(s):d=s;try{t.isSavingCell=!0,u("Saving..."),await C.updateCell(t.selectedTable,oe(o),l,d,a),t.gridData[e][n+B()]=d,ot(),ve(e,n,d),t.selectedCells=[],t.lastSelectedCell=null,F(),u("Saved")}catch(m){console.error("Save failed:",m);let f=m.message||String(m);u(`Save failed: ${f}`)}finally{t.isSavingCell=!1}}function ce(){if(!t.editingCellInfo)return;let{rowIdx:e,colIdx:n,originalValue:o}=t.editingCellInfo;ot(),ve(e,n,o),se()}function ot(){t.activeCellInput&&(t.activeCellInput.removeEventListener("keydown",et),t.activeCellInput.removeEventListener("blur",tt),t.activeCellInput=null),t.editingCellInfo=null}async function Ie(){if(!t.cellPreviewInfo)return;let{rowIdx:e,colIdx:n,rowId:o,columnName:l,originalValue:a}=t.cellPreviewInfo,s=t.tableColumns[n],i=document.getElementById("vscode-env")?.dataset.webviewId||"default";try{u("Opening in VS Code..."),G(),await C.openCellEditor({table:t.selectedTable,name:""},oe(o),l,{},{value:a,type:{type:s.type},webviewId:i,rowCount:t.gridData.length}),u("Opened in VS Code")}catch(r){console.error("Failed to open in VS Code:",r),u(`Error: ${r.message}`)}}function H(e,n,o){t.editingCellInfo&&ce();let l=t.tableColumns[n];if(!l)return;let a=t.gridData[e];if(!a)return;let s=P(a,n);if(s instanceof Uint8Array){Ee&&Ee.inspect(s,o,l.name,e,n);return}t.cellPreviewInfo={rowIdx:e,colIdx:n,rowId:o,columnName:l.name,originalValue:s};let i=document.getElementById("cellPreviewModal"),r=document.getElementById("cellPreviewColumnName"),c=document.getElementById("cellPreviewTypeBadge"),d=document.getElementById("cellPreviewTextarea"),m=document.getElementById("cellPreviewReadonlyBadge"),f=document.getElementById("cellPreviewSaveBtn"),g=document.getElementById("wrapTextBtn");r.textContent=l.name,c.textContent=l.type||"TEXT";let p="";s==null?p="":s instanceof Uint8Array?p="[BLOB: "+Array.from(s).map(w=>w.toString(16).padStart(2,"0")).join(" ")+"]":p=String(s),d.value=p;let h=t.selectedTableType!=="table";d.readOnly=h,h?(d.classList.add("readonly"),m.style.display="inline",f.style.display="none"):(d.classList.remove("readonly"),m.style.display="none",f.style.display="inline-block"),re(),d.style.whiteSpace=t.cellPreviewWrapEnabled?"pre-wrap":"pre",d.style.overflowX=t.cellPreviewWrapEnabled?"hidden":"auto",g.classList.toggle("active",t.cellPreviewWrapEnabled),i.classList.remove("hidden"),d.focus(),d.oninput=re,d.onkeydown=w=>{w.key==="Escape"?(w.preventDefault(),G()):w.key==="Enter"&&(w.ctrlKey||w.metaKey)&&(w.preventDefault(),lt())}}function re(){let e=document.getElementById("cellPreviewTextarea"),n=document.getElementById("cellPreviewCharCount"),o=e.value.length;n.textContent=`${o.toLocaleString()} character${o!==1?"s":""}`}function G(){document.getElementById("cellPreviewModal").classList.add("hidden"),t.cellPreviewInfo=null}async function lt(){if(!t.cellPreviewInfo)return;if(t.selectedTableType!=="table"){u("Views are read-only");return}let{rowIdx:e,colIdx:n,rowId:o,columnName:l,originalValue:a}=t.cellPreviewInfo,i=document.getElementById("cellPreviewTextarea").value,r=a===null?"":String(a);if(i===r){G(),t.selectedCells=[],t.lastSelectedCell=null,F();return}let c=t.tableColumns[n],d=c&&c.notnull===1,m;i===""?m=d?"":null:!isNaN(Number(i))&&i.trim()!==""?m=Number(i):m=i;try{u("Saving..."),await C.updateCell(t.selectedTable,oe(o),l,m,a),t.gridData[e][n+B()]=m,G(),ve(e,n,m),t.selectedCells=[],t.lastSelectedCell=null,F(),u("Saved")}catch(f){console.error("Save failed:",f),u(`Save failed: ${f.message}`)}}function cn(){let e=document.getElementById("cellPreviewTextarea");try{let n=JSON.parse(e.value);e.value=JSON.stringify(n,null,2),re()}catch{u("Content is not valid JSON")}}function dn(){let e=document.getElementById("cellPreviewTextarea");try{let n=JSON.parse(e.value);e.value=JSON.stringify(n),re()}catch{u("Content is not valid JSON")}}function un(){t.cellPreviewWrapEnabled=!t.cellPreviewWrapEnabled;let e=document.getElementById("cellPreviewTextarea"),n=document.getElementById("wrapTextBtn");e.style.whiteSpace=t.cellPreviewWrapEnabled?"pre-wrap":"pre",e.style.overflowX=t.cellPreviewWrapEnabled?"hidden":"auto",n.classList.toggle("active",t.cellPreviewWrapEnabled)}function ve(e,n,o){let l=document.getElementById(`cell-${e}-${n}`);if(!l)return;l.classList.remove("editing"),o==null?l.classList.add("null-value"):l.classList.remove("null-value");let a=t.tableColumns[n],s=K(o,a?.type,t.dateFormat,a?.name),i=o!=null&&!(o instanceof Uint8Array);l.textContent="";let r=document.createElement("span");if(r.className="cell-text",r.textContent=s,l.appendChild(r),i){let d=document.createElement("span");d.className="expand-icon codicon codicon-link-external",d.title="View full content",l.appendChild(d)}let c=r.scrollWidth>r.clientWidth;l.classList.toggle("has-overflow",c)}function at(){clearTimeout(t.filterTimer),t.filterTimer=setTimeout(()=>{t.filterQuery=document.getElementById("filterInput").value,t.currentPageIndex=0,I(),$()},300)}function st(){t.rowsPerPage=parseInt(document.getElementById("pageSizeSelect").value,10),t.currentPageIndex=0,I(),$()}function it(){let e=document.getElementById("dateFormatSelect");e&&(t.dateFormat=e.value,_(),$())}function ee(e){e>=0&&el.name===n);if(o!==-1){if((e.shiftKey||e.metaKey||e.ctrlKey)&&e.preventDefault(),t.selectedRowIds.clear(),e.shiftKey&&t.lastSelectedColumnIndex!==null){e.metaKey||e.ctrlKey||(t.selectedCells=[],t.selectedColumns.clear());let l=Math.min(t.lastSelectedColumnIndex,o),a=Math.max(t.lastSelectedColumnIndex,o),s=new Array;if(t.selectedCells.length>0)for(let i of t.selectedCells)i.colIdx>=l&&i.colIdx<=a&&(s[i.rowIdx]||(s[i.rowIdx]=new Set),s[i.rowIdx].add(i.colIdx));for(let i=l;i<=a;i++){let r=t.tableColumns[i].name;t.selectedColumns.add(r);for(let c=0;c0&&a===l)t.selectedCells=t.selectedCells.filter(i=>i.colIdx!==o),t.selectedColumns.delete(n);else{let i=new Set;for(let r of t.selectedCells)r.colIdx===o&&i.add(r.rowIdx);for(let r=0;r0&&a===l&&t.selectedColumns.size===1&&t.selectedColumns.has(n))t.selectedCells=[],t.selectedColumns.clear(),t.lastSelectedColumnIndex=null;else{t.selectedCells=[],t.selectedColumns.clear();for(let i=0;ii.name===t.resizingColumn);if(l===-1)return;let a=document.querySelector(`th[data-column="${t.resizingColumn}"]`);a&&(a.style.width=`${o}px`,a.style.minWidth=`${o}px`,a.style.maxWidth=`${o}px`);let s=document.querySelectorAll(`.data-row td:nth-child(${l+2})`);for(let i of s)i.style.width=`${o}px`,i.style.minWidth=`${o}px`,i.style.maxWidth=`${o}px`;t.pinnedColumns.has(t.resizingColumn)}function gt(){if(!t.resizingColumn)return;let e=document.querySelector(".resize-handle.resizing");e&&e.classList.remove("resizing"),t.resizingColumn=null,document.removeEventListener("mousemove",ft),document.removeEventListener("mouseup",gt),document.body.style.userSelect="",document.body.style.cursor="",_()}function ht(e,n,o){if(e.stopPropagation(),(e.shiftKey||e.metaKey||e.ctrlKey)&&e.preventDefault(),t.selectedCells=[],t.lastSelectedCell=null,t.selectedColumns.clear(),e.shiftKey&&t.lastSelectedRowIndex!==null){e.metaKey||e.ctrlKey||t.selectedRowIds.clear();let l=Math.min(t.lastSelectedRowIndex,o),a=Math.max(t.lastSelectedRowIndex,o);for(let s=l;s<=a;s++){let i=T(t.gridData[s],s);t.selectedRowIds.add(i)}}else e.ctrlKey||e.metaKey?(t.selectedRowIds.has(n)?t.selectedRowIds.delete(n):t.selectedRowIds.add(n),t.lastSelectedRowIndex=o):t.selectedRowIds.has(n)&&t.selectedRowIds.size===1?(t.selectedRowIds.delete(n),t.lastSelectedRowIndex=null):(t.selectedRowIds.clear(),t.selectedRowIds.add(n),t.lastSelectedRowIndex=o);F(),R(),j()}function de(e){if(e.stopPropagation(),t.gridData.length===0)return;t.selectedCells=[],t.lastSelectedCell=null,t.selectedColumns.clear();let n=!0;for(let o=0;o=s&&m.rowIdx<=i&&m.colIdx>=r&&m.colIdx<=c&&(d[m.rowIdx]||(d[m.rowIdx]=new Set),d[m.rowIdx].add(m.colIdx));for(let m=s;m<=i;m++){let f=d[m];for(let g=r;g<=c;g++)if(!f||!f.has(g)){let p=T(t.gridData[m],m),h=P(t.gridData[m],g);t.selectedCells.push({rowIdx:m,colIdx:g,rowId:p,value:h})}}}else if(e.metaKey||e.ctrlKey){e.preventDefault(),t.selectedRowIds.clear();let s=t.selectedCells.findIndex(i=>i.rowIdx===n&&i.colIdx===o);s>=0?t.selectedCells.splice(s,1):(t.selectedCells.push({rowIdx:n,colIdx:o,rowId:l,value:a}),t.lastSelectedCell={rowIdx:n,colIdx:o})}else if(e.shiftKey&&t.lastSelectedCell){e.preventDefault(),t.selectedRowIds.clear(),t.selectedCells=[];let s=Math.min(t.lastSelectedCell.rowIdx,n),i=Math.max(t.lastSelectedCell.rowIdx,n),r=Math.min(t.lastSelectedCell.colIdx,o),c=Math.max(t.lastSelectedCell.colIdx,o);for(let d=s;d<=i;d++)for(let m=r;m<=c;m++){let f=T(t.gridData[d],d),g=P(t.gridData[d],m);t.selectedCells.push({rowIdx:d,colIdx:m,rowId:f,value:g})}}else t.selectedRowIds.clear(),t.selectedCells=[{rowIdx:n,colIdx:o,rowId:l,value:a}],t.lastSelectedCell={rowIdx:n,colIdx:o},t.selectedColumns.clear();F(),R(),j()}function Ct(e,n,o,l){if(t.cellEditBehavior==="vscode"){let a=t.tableColumns[o];if(!a)return;let s=t.gridData[n];if(!s)return;let i=P(s,o);t.cellPreviewInfo={rowIdx:n,colIdx:o,rowId:l,columnName:a.name,originalValue:i},Ie()}else t.cellEditBehavior==="modal"?H(n,o,l):Ze(n,o,l)}function xt(){document.getElementById("filterInput")?.addEventListener("keyup",at),document.getElementById("pageSizeSelect")?.addEventListener("change",st),document.getElementById("dateFormatSelect")?.addEventListener("change",it),document.getElementById("btnFirst")?.addEventListener("click",()=>ee(0)),document.getElementById("btnPrev")?.addEventListener("click",()=>ee(t.currentPageIndex-1)),document.getElementById("btnNext")?.addEventListener("click",()=>ee(t.currentPageIndex+1)),document.getElementById("btnLast")?.addEventListener("click",()=>ee(t.totalPageCount-1))}function bt(){let e=document.getElementById("gridContainer");e&&(e.addEventListener("mousedown",mn),e.addEventListener("keydown",pn),e.addEventListener("click",fn),e.addEventListener("dblclick",yn),e.addEventListener("mouseover",Cn),e.addEventListener("scroll",xn,{passive:!0}))}function mn(e){if(e.target.classList.contains("resize-handle")){e.stopPropagation();let n=e.target.closest(".header-cell");n&&n.dataset.column&&pt(e,n.dataset.column)}}function pn(e){if(e.target.classList.contains("column-filter")){let n=e.target.dataset.column;n&&ct(e,n)}}function fn(e){let n=e.target;if(n.closest(".grid-header")){gn(e,n);return}hn(e,n)}function gn(e,n){if(n.closest(".filter-apply-btn")){e.stopPropagation();let l=n.closest(".header-cell");l&&l.dataset.column&&Se(l.dataset.column);return}if(n.closest(".header-bottom")||n.closest(".column-filter")){e.stopPropagation();return}if(n.closest(".select-column-icon")){e.stopPropagation();let l=n.closest(".header-cell");l&&l.dataset.column&&dt(e,l.dataset.column);return}if(n.closest(".pin-icon")){e.stopPropagation();let l=n.closest(".header-cell");l&&l.dataset.column&&ut(e,l.dataset.column);return}if(n.closest(".row-number-header")){de(e);return}let o=n.closest(".header-top");if(o){let l=o.closest(".header-cell");l&&l.dataset.column&&rt(l.dataset.column);return}}function hn(e,n){if(n.closest(".pin-icon")){let l=n.closest(".data-row");if(l){let a=l.dataset.rowid,s=te(a);mt(e,s)}return}if(n.closest(".expand-icon")){let l=n.closest(".data-cell");if(l){let a=parseInt(l.dataset.rowidx,10),s=parseInt(l.dataset.colidx,10),i=te(l.closest(".data-row").dataset.rowid);H(a,s,i)}return}if(n.closest(".row-number")){let l=n.closest(".data-row");if(l){let a=te(l.dataset.rowid),s=parseInt(l.dataset.rowidx,10);ht(e,a,s)}return}let o=n.closest(".data-cell");if(o){let l=parseInt(o.dataset.rowidx,10),a=parseInt(o.dataset.colidx,10),s=o.closest(".data-row"),i=te(s.dataset.rowid);yt(e,l,a,i);return}}function yn(e){let n=e.target.closest(".data-cell");if(n&&!n.classList.contains("row-number")){let o=parseInt(n.dataset.rowidx,10),l=parseInt(n.dataset.colidx,10),a=n.closest(".data-row"),s=te(a.dataset.rowid);Ct(e,o,l,s)}}function Cn(e){let n=e.target.closest(".data-cell");if(n&&!n.classList.contains("checked-overflow")){let o=n.querySelector(".cell-text");if(o){let l=o.scrollWidth>o.clientWidth;n.classList.toggle("has-overflow",l),n.classList.add("checked-overflow")}}}function xn(e){let n=e.currentTarget;t.scrollPosition.left=n.scrollLeft,t.scrollPosition.top=n.scrollTop,$()}function te(e){if(e==null)return e;let n=Number(e);return!isNaN(n)&&e.trim()!==""?n:e}var wt={async refreshContent(e){return t.isDbConnected&&(await V(),!(t.schemaCache.tables.some(o=>o.name===t.selectedTable)||t.schemaCache.views.some(o=>o.name===t.selectedTable))&&t.selectedTable?(t.selectedTable=null,t.selectedTableType=null,document.getElementById("tableNameLabel").textContent="No table selected",document.getElementById("gridContainer").innerHTML=` +... (${(n.length-o).toLocaleString()} more bytes not shown)`),this.hexContainer.value=l}formatSize(n){if(n===0)return"0 B";let o=1024,l=["B","KB","MB","GB"],a=Math.floor(Math.log(n)/Math.log(o));return parseFloat((n/Math.pow(o,a)).toFixed(2))+" "+l[a]}};var Ee;function Qe(){Ee=new ie,document.getElementById("btnCloseCellPreview")?.addEventListener("click",G),document.getElementById("formatJsonBtn")?.addEventListener("click",cn),document.getElementById("compactJsonBtn")?.addEventListener("click",dn),document.getElementById("wrapTextBtn")?.addEventListener("click",un),document.getElementById("openInVsCodeBtn")?.addEventListener("click",Ie),document.getElementById("btnCancelCellPreview")?.addEventListener("click",G),document.getElementById("cellPreviewSaveBtn")?.addEventListener("click",lt)}function Ze(e,n,o){if(t.selectedTableType!=="table"){u("Views are read-only");return}if(t.editingCellInfo){if(t.editingCellInfo.rowIdx===e&&t.editingCellInfo.colIdx===n)return;ce()}let l=t.tableColumns[n];if(!l)return;let a=document.getElementById(`cell-${e}-${n}`);if(!a)return;let s=t.gridData[e],i=P(s,n);if(i instanceof Uint8Array){H(e,n,o);return}if(typeof i=="string"){let d=i.trim();if(d.startsWith("{")&&d.endsWith("}")||d.startsWith("[")&&d.endsWith("]"))try{JSON.parse(d),H(e,n,o);return}catch{}}t.editingCellInfo={rowIdx:e,colIdx:n,rowId:o,columnName:l.name,originalValue:i};let r=i===null?"":String(i);a.innerHTML="",a.classList.add("editing");let c=document.createElement("textarea");c.className="cell-input",c.value=r,c.spellcheck=!1,a.appendChild(c),c.focus(),t.activeCellInput=c,c.addEventListener("keydown",et),c.addEventListener("blur",tt),c.addEventListener("click",d=>d.stopPropagation()),t.isTransitioningEdit=!0,setTimeout(()=>{t.isTransitioningEdit=!1},100)}function et(e){e.key==="Enter"&&!e.shiftKey?(e.preventDefault(),nt()):e.key==="Escape"&&(e.preventDefault(),ce())}function tt(){setTimeout(()=>{t.editingCellInfo&&nt()},100)}async function nt(){if(t.isSavingCell||!t.editingCellInfo||!t.activeCellInput)return;let{rowIdx:e,colIdx:n,rowId:o,columnName:l,originalValue:a}=t.editingCellInfo,s=t.activeCellInput.value,i=a===null?"":String(a);if(s===i){ce(),t.selectedCells=[],t.lastSelectedCell=null,F();return}let r=t.tableColumns[n],c=r&&r.notnull===1,d;s===""?c?d="":d=null:!isNaN(Number(s))&&s.trim()!==""?d=Number(s):d=s;try{t.isSavingCell=!0,u("Saving..."),await C.updateCell(t.selectedTable,oe(o),l,d,a),t.gridData[e][n+B()]=d,ot(),ve(e,n,d),t.selectedCells=[],t.lastSelectedCell=null,F(),u("Saved")}catch(m){console.error("Save failed:",m);let g=m.message||String(m);u(`Save failed: ${g}`)}finally{t.isSavingCell=!1}}function ce(){if(!t.editingCellInfo)return;let{rowIdx:e,colIdx:n,originalValue:o}=t.editingCellInfo;ot(),ve(e,n,o),se()}function ot(){t.activeCellInput&&(t.activeCellInput.removeEventListener("keydown",et),t.activeCellInput.removeEventListener("blur",tt),t.activeCellInput=null),t.editingCellInfo=null}async function Ie(){if(!t.cellPreviewInfo)return;let{rowIdx:e,colIdx:n,rowId:o,columnName:l,originalValue:a}=t.cellPreviewInfo,s=t.tableColumns[n],i=document.getElementById("vscode-env")?.dataset.webviewId||"default";try{u("Opening in VS Code..."),G(),await C.openCellEditor({table:t.selectedTable,name:""},oe(o),l,{},{value:a,type:{type:s.type},webviewId:i,rowCount:t.gridData.length}),u("Opened in VS Code")}catch(r){console.error("Failed to open in VS Code:",r),u(`Error: ${r.message}`)}}function H(e,n,o){t.editingCellInfo&&ce();let l=t.tableColumns[n];if(!l)return;let a=t.gridData[e];if(!a)return;let s=P(a,n);if(s instanceof Uint8Array){Ee&&Ee.inspect(s,o,l.name,e,n);return}t.cellPreviewInfo={rowIdx:e,colIdx:n,rowId:o,columnName:l.name,originalValue:s};let i=document.getElementById("cellPreviewModal"),r=document.getElementById("cellPreviewColumnName"),c=document.getElementById("cellPreviewTypeBadge"),d=document.getElementById("cellPreviewTextarea"),m=document.getElementById("cellPreviewReadonlyBadge"),g=document.getElementById("cellPreviewSaveBtn"),f=document.getElementById("wrapTextBtn");r.textContent=l.name,c.textContent=l.type||"TEXT";let p="";s==null?p="":s instanceof Uint8Array?p="[BLOB: "+Array.from(s).map(w=>w.toString(16).padStart(2,"0")).join(" ")+"]":p=String(s),d.value=p;let h=t.selectedTableType!=="table";d.readOnly=h,h?(d.classList.add("readonly"),m.style.display="inline",g.style.display="none"):(d.classList.remove("readonly"),m.style.display="none",g.style.display="inline-block"),re(),d.style.whiteSpace=t.cellPreviewWrapEnabled?"pre-wrap":"pre",d.style.overflowX=t.cellPreviewWrapEnabled?"hidden":"auto",f.classList.toggle("active",t.cellPreviewWrapEnabled),i.classList.remove("hidden"),d.focus(),d.oninput=re,d.onkeydown=w=>{w.key==="Escape"?(w.preventDefault(),G()):w.key==="Enter"&&(w.ctrlKey||w.metaKey)&&(w.preventDefault(),lt())}}function re(){let e=document.getElementById("cellPreviewTextarea"),n=document.getElementById("cellPreviewCharCount"),o=e.value.length;n.textContent=`${o.toLocaleString()} character${o!==1?"s":""}`}function G(){document.getElementById("cellPreviewModal").classList.add("hidden"),t.cellPreviewInfo=null}async function lt(){if(!t.cellPreviewInfo)return;if(t.selectedTableType!=="table"){u("Views are read-only");return}let{rowIdx:e,colIdx:n,rowId:o,columnName:l,originalValue:a}=t.cellPreviewInfo,i=document.getElementById("cellPreviewTextarea").value,r=a===null?"":String(a);if(i===r){G(),t.selectedCells=[],t.lastSelectedCell=null,F();return}let c=t.tableColumns[n],d=c&&c.notnull===1,m;i===""?m=d?"":null:!isNaN(Number(i))&&i.trim()!==""?m=Number(i):m=i;try{u("Saving..."),await C.updateCell(t.selectedTable,oe(o),l,m,a),t.gridData[e][n+B()]=m,G(),ve(e,n,m),t.selectedCells=[],t.lastSelectedCell=null,F(),u("Saved")}catch(g){console.error("Save failed:",g),u(`Save failed: ${g.message}`)}}function cn(){let e=document.getElementById("cellPreviewTextarea");try{let n=JSON.parse(e.value);e.value=JSON.stringify(n,null,2),re()}catch{u("Content is not valid JSON")}}function dn(){let e=document.getElementById("cellPreviewTextarea");try{let n=JSON.parse(e.value);e.value=JSON.stringify(n),re()}catch{u("Content is not valid JSON")}}function un(){t.cellPreviewWrapEnabled=!t.cellPreviewWrapEnabled;let e=document.getElementById("cellPreviewTextarea"),n=document.getElementById("wrapTextBtn");e.style.whiteSpace=t.cellPreviewWrapEnabled?"pre-wrap":"pre",e.style.overflowX=t.cellPreviewWrapEnabled?"hidden":"auto",n.classList.toggle("active",t.cellPreviewWrapEnabled)}function ve(e,n,o){let l=document.getElementById(`cell-${e}-${n}`);if(!l)return;l.classList.remove("editing"),o==null?l.classList.add("null-value"):l.classList.remove("null-value");let a=t.tableColumns[n],s=K(o,a?.type,t.dateFormat,a?.name),i=o!=null&&!(o instanceof Uint8Array);l.textContent="";let r=document.createElement("span");if(r.className="cell-text",r.textContent=s,l.appendChild(r),i){let d=document.createElement("span");d.className="expand-icon codicon codicon-link-external",d.title="View full content",l.appendChild(d)}let c=r.scrollWidth>r.clientWidth;l.classList.toggle("has-overflow",c)}function at(){clearTimeout(t.filterTimer),t.filterTimer=setTimeout(()=>{t.filterQuery=document.getElementById("filterInput").value,t.currentPageIndex=0,I(),$()},300)}function st(){t.rowsPerPage=parseInt(document.getElementById("pageSizeSelect").value,10),t.currentPageIndex=0,I(),$()}function it(){let e=document.getElementById("dateFormatSelect");e&&(t.dateFormat=e.value,_(),$())}function ee(e){e>=0&&el.name===n);if(o!==-1){if((e.shiftKey||e.metaKey||e.ctrlKey)&&e.preventDefault(),t.selectedRowIds.clear(),e.shiftKey&&t.lastSelectedColumnIndex!==null){e.metaKey||e.ctrlKey||(t.selectedCells=[],t.selectedColumns.clear());let l=Math.min(t.lastSelectedColumnIndex,o),a=Math.max(t.lastSelectedColumnIndex,o),s=new Array;if(t.selectedCells.length>0)for(let i of t.selectedCells)i.colIdx>=l&&i.colIdx<=a&&(s[i.rowIdx]||(s[i.rowIdx]=new Set),s[i.rowIdx].add(i.colIdx));for(let i=l;i<=a;i++){let r=t.tableColumns[i].name;t.selectedColumns.add(r);for(let c=0;c0&&a===l)t.selectedCells=t.selectedCells.filter(i=>i.colIdx!==o),t.selectedColumns.delete(n);else{let i=new Set;for(let r of t.selectedCells)r.colIdx===o&&i.add(r.rowIdx);for(let r=0;r0&&a===l&&t.selectedColumns.size===1&&t.selectedColumns.has(n))t.selectedCells=[],t.selectedColumns.clear(),t.lastSelectedColumnIndex=null;else{t.selectedCells=[],t.selectedColumns.clear();for(let i=0;ii.name===t.resizingColumn);if(l===-1)return;let a=document.querySelector(`th[data-column="${t.resizingColumn}"]`);a&&(a.style.width=`${o}px`,a.style.minWidth=`${o}px`,a.style.maxWidth=`${o}px`);let s=document.querySelectorAll(`.data-row td:nth-child(${l+2})`);for(let i of s)i.style.width=`${o}px`,i.style.minWidth=`${o}px`,i.style.maxWidth=`${o}px`;t.pinnedColumns.has(t.resizingColumn)}function gt(){if(!t.resizingColumn)return;let e=document.querySelector(".resize-handle.resizing");e&&e.classList.remove("resizing"),t.resizingColumn=null,document.removeEventListener("mousemove",ft),document.removeEventListener("mouseup",gt),document.body.style.userSelect="",document.body.style.cursor="",_()}function ht(e,n,o){if(e.stopPropagation(),(e.shiftKey||e.metaKey||e.ctrlKey)&&e.preventDefault(),t.selectedCells=[],t.lastSelectedCell=null,t.selectedColumns.clear(),e.shiftKey&&t.lastSelectedRowIndex!==null){e.metaKey||e.ctrlKey||t.selectedRowIds.clear();let l=Math.min(t.lastSelectedRowIndex,o),a=Math.max(t.lastSelectedRowIndex,o);for(let s=l;s<=a;s++){let i=T(t.gridData[s],s);t.selectedRowIds.add(i)}}else e.ctrlKey||e.metaKey?(t.selectedRowIds.has(n)?t.selectedRowIds.delete(n):t.selectedRowIds.add(n),t.lastSelectedRowIndex=o):t.selectedRowIds.has(n)&&t.selectedRowIds.size===1?(t.selectedRowIds.delete(n),t.lastSelectedRowIndex=null):(t.selectedRowIds.clear(),t.selectedRowIds.add(n),t.lastSelectedRowIndex=o);F(),R(),j()}function de(e){if(e.stopPropagation(),t.gridData.length===0)return;t.selectedCells=[],t.lastSelectedCell=null,t.selectedColumns.clear();let n=!0;for(let o=0;o=s&&m.rowIdx<=i&&m.colIdx>=r&&m.colIdx<=c&&(d[m.rowIdx]||(d[m.rowIdx]=new Set),d[m.rowIdx].add(m.colIdx));for(let m=s;m<=i;m++){let g=d[m];for(let f=r;f<=c;f++)if(!g||!g.has(f)){let p=T(t.gridData[m],m),h=P(t.gridData[m],f);t.selectedCells.push({rowIdx:m,colIdx:f,rowId:p,value:h})}}}else if(e.metaKey||e.ctrlKey){e.preventDefault(),t.selectedRowIds.clear();let s=t.selectedCells.findIndex(i=>i.rowIdx===n&&i.colIdx===o);s>=0?t.selectedCells.splice(s,1):(t.selectedCells.push({rowIdx:n,colIdx:o,rowId:l,value:a}),t.lastSelectedCell={rowIdx:n,colIdx:o})}else if(e.shiftKey&&t.lastSelectedCell){e.preventDefault(),t.selectedRowIds.clear(),t.selectedCells=[];let s=Math.min(t.lastSelectedCell.rowIdx,n),i=Math.max(t.lastSelectedCell.rowIdx,n),r=Math.min(t.lastSelectedCell.colIdx,o),c=Math.max(t.lastSelectedCell.colIdx,o);for(let d=s;d<=i;d++)for(let m=r;m<=c;m++){let g=T(t.gridData[d],d),f=P(t.gridData[d],m);t.selectedCells.push({rowIdx:d,colIdx:m,rowId:g,value:f})}}else t.selectedRowIds.clear(),t.selectedCells=[{rowIdx:n,colIdx:o,rowId:l,value:a}],t.lastSelectedCell={rowIdx:n,colIdx:o},t.selectedColumns.clear();F(),R(),j()}function Ct(e,n,o,l){if(t.cellEditBehavior==="vscode"){let a=t.tableColumns[o];if(!a)return;let s=t.gridData[n];if(!s)return;let i=P(s,o);t.cellPreviewInfo={rowIdx:n,colIdx:o,rowId:l,columnName:a.name,originalValue:i},Ie()}else t.cellEditBehavior==="modal"?H(n,o,l):Ze(n,o,l)}function xt(){document.getElementById("filterInput")?.addEventListener("keyup",at),document.getElementById("pageSizeSelect")?.addEventListener("change",st),document.getElementById("dateFormatSelect")?.addEventListener("change",it),document.getElementById("btnFirst")?.addEventListener("click",()=>ee(0)),document.getElementById("btnPrev")?.addEventListener("click",()=>ee(t.currentPageIndex-1)),document.getElementById("btnNext")?.addEventListener("click",()=>ee(t.currentPageIndex+1)),document.getElementById("btnLast")?.addEventListener("click",()=>ee(t.totalPageCount-1))}function bt(){let e=document.getElementById("gridContainer");e&&(e.addEventListener("mousedown",mn),e.addEventListener("keydown",pn),e.addEventListener("click",fn),e.addEventListener("dblclick",yn),e.addEventListener("mouseover",Cn),e.addEventListener("scroll",xn,{passive:!0}))}function mn(e){if(e.target.classList.contains("resize-handle")){e.stopPropagation();let n=e.target.closest(".header-cell");n&&n.dataset.column&&pt(e,n.dataset.column)}}function pn(e){if(e.target.classList.contains("column-filter")){let n=e.target.dataset.column;n&&ct(e,n)}}function fn(e){let n=e.target;if(n.closest(".grid-header")){gn(e,n);return}hn(e,n)}function gn(e,n){if(n.closest(".filter-apply-btn")){e.stopPropagation();let l=n.closest(".header-cell");l&&l.dataset.column&&Se(l.dataset.column);return}if(n.closest(".header-bottom")||n.closest(".column-filter")){e.stopPropagation();return}if(n.closest(".select-column-icon")){e.stopPropagation();let l=n.closest(".header-cell");l&&l.dataset.column&&dt(e,l.dataset.column);return}if(n.closest(".pin-icon")){e.stopPropagation();let l=n.closest(".header-cell");l&&l.dataset.column&&ut(e,l.dataset.column);return}if(n.closest(".row-number-header")){de(e);return}let o=n.closest(".header-top");if(o){let l=o.closest(".header-cell");l&&l.dataset.column&&rt(l.dataset.column);return}}function hn(e,n){if(n.closest(".pin-icon")){let l=n.closest(".data-row");if(l){let a=l.dataset.rowid,s=te(a);mt(e,s)}return}if(n.closest(".expand-icon")){let l=n.closest(".data-cell");if(l){let a=parseInt(l.dataset.rowidx,10),s=parseInt(l.dataset.colidx,10),i=te(l.closest(".data-row").dataset.rowid);H(a,s,i)}return}if(n.closest(".row-number")){let l=n.closest(".data-row");if(l){let a=te(l.dataset.rowid),s=parseInt(l.dataset.rowidx,10);ht(e,a,s)}return}let o=n.closest(".data-cell");if(o){let l=parseInt(o.dataset.rowidx,10),a=parseInt(o.dataset.colidx,10),s=o.closest(".data-row"),i=te(s.dataset.rowid);yt(e,l,a,i);return}}function yn(e){let n=e.target.closest(".data-cell");if(n&&!n.classList.contains("row-number")){let o=parseInt(n.dataset.rowidx,10),l=parseInt(n.dataset.colidx,10),a=n.closest(".data-row"),s=te(a.dataset.rowid);Ct(e,o,l,s)}}function Cn(e){let n=e.target.closest(".data-cell");if(n&&!n.classList.contains("checked-overflow")){let o=n.querySelector(".cell-text");if(o){let l=o.scrollWidth>o.clientWidth;n.classList.toggle("has-overflow",l),n.classList.add("checked-overflow")}}}function xn(e){let n=e.currentTarget;t.scrollPosition.left=n.scrollLeft,t.scrollPosition.top=n.scrollTop,$()}function te(e){if(e==null)return e;let n=Number(e);return!isNaN(n)&&e.trim()!==""?n:e}var wt={async refreshContent(e){return t.isDbConnected&&(await V(),!(t.schemaCache.tables.some(o=>o.name===t.selectedTable)||t.schemaCache.views.some(o=>o.name===t.selectedTable))&&t.selectedTable?(t.selectedTable=null,t.selectedTableType=null,document.getElementById("tableNameLabel").textContent="No table selected",document.getElementById("gridContainer").innerHTML=`
Select a table diff --git a/website/public/sqlite-viewer/viewer.html b/website/public/sqlite-viewer/viewer.html index 54a7e6af..235321e6 100644 --- a/website/public/sqlite-viewer/viewer.html +++ b/website/public/sqlite-viewer/viewer.html @@ -385,7 +385,7 @@ No data This table is empty - `,e}function Xt(e,t,o){let l=document.createElement("thead");l.className="grid-header";let a=document.createElement("tr"),s=document.createElement("th");s.className="header-cell row-number-header",Object.assign(s.style,{width:`${e}px`,minWidth:`${e}px`,maxWidth:`${e}px`,position:"sticky",left:"0",top:"0",zIndex:"11",background:"var(--bg-secondary)"}),s.title="Click to select all rows",s.innerHTML='
#
',a.appendChild(s);for(let r of t){let i=n.sortedColumn===r.name,c=n.pinnedColumns.has(r.name),d=n.selectedColumns.has(r.name),m=n.columnWidths[r.name]||120,f=n.columnFilters[r.name]||"",g=document.createElement("th");g.className=`header-cell ${c?"pinned":""} ${d?"column-selected":""}`,Object.assign(g.style,{width:`${m}px`,minWidth:`${m}px`,maxWidth:`${m}px`}),c&&(g.style.position="sticky",g.style.left=`${o.get(r.name)}px`),g.dataset.column=r.name;let p=X(r.name),h=X(f),w=i?`${n.sortAscending?"\u25B2":"\u25BC"}`:"",S=r.isPrimaryKey?'':"",y=c?"pinned":"",x=c?"Unpin column":"Pin column";g.innerHTML=` + `,e}function Xt(e,t,o){let l=document.createElement("thead");l.className="grid-header";let a=document.createElement("tr"),s=document.createElement("th");s.className="header-cell row-number-header",Object.assign(s.style,{width:`${e}px`,minWidth:`${e}px`,maxWidth:`${e}px`,position:"sticky",left:"0",top:"0",zIndex:"11",background:"var(--bg-secondary)"}),s.title="Click to select all rows",s.innerHTML='
#
',a.appendChild(s);for(let r of t){let i=n.sortedColumn===r.name,c=n.pinnedColumns.has(r.name),d=n.selectedColumns.has(r.name),m=n.columnWidths[r.name]||120,g=n.columnFilters[r.name]||"",f=document.createElement("th");f.className=`header-cell ${c?"pinned":""} ${d?"column-selected":""}`,Object.assign(f.style,{width:`${m}px`,minWidth:`${m}px`,maxWidth:`${m}px`}),c&&(f.style.position="sticky",f.style.left=`${o.get(r.name)}px`),f.dataset.column=r.name;let p=X(r.name),h=X(g),w=i?`${n.sortAscending?"\u25B2":"\u25BC"}`:"",S=r.isPrimaryKey?'':"",y=c?"pinned":"",x=c?"Unpin column":"Pin column";f.innerHTML=`
${S}${p}${w} @@ -398,9 +398,9 @@
- `,a.appendChild(g)}return l.appendChild(a),l}function Yt(e,t,o,l,a,s,r,i){let c=document.createElement("tbody"),d=[];for(let p=0;p({idx:h,rowId:B(p,h)})).filter(p=>n.pinnedRowIds.has(p.rowId)),...n.gridData.map((p,h)=>({idx:h,rowId:B(p,h)})).filter(p=>!n.pinnedRowIds.has(p.rowId))],g=document.createDocumentFragment();for(let{idx:p,rowId:h}of f){let w=n.gridData[p],S=n.selectedRowIds.has(h),y=n.pinnedRowIds.has(h),x=document.createElement("tr");x.id=`row-${p}`,x.className=`data-row ${S?"selected":""} ${y?"pinned":""}`,x.dataset.rowid=h,x.dataset.rowidx=p,y&&(x.style.top=`${m.get(h)}px`);let A=document.createElement("td");A.className="data-cell row-number",Object.assign(A.style,{width:`${l}px`,minWidth:`${l}px`,maxWidth:`${l}px`,position:"sticky",left:"0",zIndex:y?"8":"2"});let L=n.currentPageIndex*n.rowsPerPage+p+1;A.appendChild(document.createTextNode(String(L)));let b=document.createElement("span");b.className=`pin-icon codicon codicon-pin ${y?"pinned":""}`,b.title=y?"Unpin row":"Pin row",A.appendChild(b),x.appendChild(A);for(let D=0;Db&&b.trim()!=="");if(i.innerHTML="",n.gridData.length===0&&!g&&n.tableColumns.length===0){i.appendChild(Jt());return}let p=new Set;if(n.selectedCells.length>0)for(let b of n.selectedCells)p.add(`${b.rowIdx},${b.colIdx}`);let h=document.createElement("table");if(h.className="data-grid",Object.keys(n.columnWidths).length===0&&n.gridData.length>0)for(let b of n.tableColumns){let D=b.name.length,N=b.isPrimaryKey?86:70,W=D*8+N;n.columnWidths[b.name]=Math.max(80,Math.min(250,W))}let w=[...n.tableColumns.filter(b=>n.pinnedColumns.has(b.name)),...n.tableColumns.filter(b=>!n.pinnedColumns.has(b.name))],S=new Map,y=r-1;for(let b of w)n.pinnedColumns.has(b.name)&&(S.set(b.name,y),y+=n.columnWidths[b.name]||120);let x=new Map;n.tableColumns.forEach((b,D)=>x.set(b.name,D));let A=Xt(r,w,S);h.appendChild(A);let L=Yt(w,x,S,r,52,26,p,g);h.appendChild(L),i.appendChild(h),i.scrollLeft=m,i.scrollTop=f,We()}function Ke(){document.getElementById("pageIndicator").textContent=`${n.currentPageIndex+1} / ${n.totalPageCount}`,document.getElementById("btnFirst").disabled=n.currentPageIndex===0,document.getElementById("btnPrev").disabled=n.currentPageIndex===0,document.getElementById("btnNext").disabled=n.currentPageIndex>=n.totalPageCount-1,document.getElementById("btnLast").disabled=n.currentPageIndex>=n.totalPageCount-1}async function q(){if(n.selectedTable)try{let e=await C.getTableInfo(n.selectedTable);n.tableColumns=e.map(o=>({cid:o.ordinal,name:o.identifier,type:o.declaredType,notnull:o.isRequired,dflt_value:o.defaultExpression,isPrimaryKey:o.primaryKeyPosition>0})).sort((o,l)=>o.cid-l.cid);let t=new Set(n.tableColumns.map(o=>o.name));n.sortedColumn&&!t.has(n.sortedColumn)&&(n.sortedColumn=null,n.sortAscending=!0);for(let o of Object.keys(n.columnFilters))t.has(o)||delete n.columnFilters[o]}catch(e){console.error("Error loading columns:",e),u("Error loading columns")}}async function v(e=!0,t=!0){if(!n.selectedTable)return;let o=document.getElementById("gridContainer");t&&o&&o.querySelector(".data-grid")&&(n.scrollPosition.left=o.scrollLeft,n.scrollPosition.top=o.scrollTop),e&&(n.isLoadingData=!0,(!o||!o.querySelector(".data-grid"))&&Ve()),P();try{let l=[];for(let[m,f]of Object.entries(n.columnFilters))f&&f.trim()&&l.push({column:m,value:f});let a={filters:l,globalFilter:n.filterQuery,columns:n.tableColumns.map(m=>m.name)};n.totalRecordCount=await C.fetchTableCount(n.selectedTable,a),n.totalPageCount=Math.max(1,Math.ceil(n.totalRecordCount/n.rowsPerPage)),n.currentPageIndex>=n.totalPageCount&&(n.currentPageIndex=Math.max(0,n.totalPageCount-1));let s=n.selectedTableType==="table",r=n.tableColumns.map(m=>m.name),c={columns:s?["rowid",...r]:r,orderBy:n.sortedColumn,orderDir:n.sortAscending?"ASC":"DESC",limit:n.rowsPerPage,offset:n.currentPageIndex*n.rowsPerPage,filters:l,globalFilter:n.filterQuery},d=await C.fetchTableData(n.selectedTable,c);n.gridData=d.rows||[],!e&&o&&o.querySelector(".data-grid")&&(n.scrollPosition.left=o.scrollLeft,n.scrollPosition.top=o.scrollTop),!e&&n.editingCellInfo||j(n.scrollPosition.top,n.scrollPosition.left),o&&(o.scrollLeft=n.scrollPosition.left,o.scrollTop=n.scrollPosition.top),Ke(),u(`${n.totalRecordCount} records`)}catch(l){console.error("Error loading data:",l),u(`Error: ${l.message}`),le(l.message)}finally{e&&(n.isLoadingData=!1)}}var T={PNG:[137,80,78,71,13,10,26,10],JPEG:[255,216,255],GIF:[71,73,70,56],BMP:[66,77],RIFF:[82,73,70,70],WEBP:[87,69,66,80],PDF:[37,80,68,70,45],ID3:[73,68,51],MP3_SYNC1:[255,251],MP3_SYNC2:[255,243],MP3_SYNC3:[255,242],OGG:[79,103,103,83],WAVE:[87,65,86,69],FLAC:[102,76,97,67],FTYP:[102,116,121,112],WEBM:[26,69,223,163],AVI:[65,86,73,32]},se=class{constructor(){this.currentObjectUrl=null,this.modal=document.getElementById("blob-inspector-modal"),this.previewContainer=document.getElementById("tab-preview"),this.hexContainer=document.querySelector(".hex-dump"),this.infoContainer=document.getElementById("blob-info"),this.currentData=null,this.currentType=null,this.currentRowId=null,this.currentColName=null,this.currentCellInfo=null,this.isUploading=!1,this.setupEventListeners()}setupEventListeners(){this.modal.querySelectorAll(".modal-close").forEach(l=>{l.addEventListener("click",()=>this.close())}),this.modal.querySelectorAll(".tab-btn").forEach(l=>{l.addEventListener("click",a=>{let s=a.target.dataset.tab;this.switchTab(s)})});let t=document.getElementById("blob-download-btn");t&&t.addEventListener("click",()=>this.download());let o=document.getElementById("blob-replace-btn");o&&o.addEventListener("click",()=>this.handleReplace())}setUploadState(t){this.isUploading=t;let o=document.getElementById("blob-replace-btn"),l=document.getElementById("blob-download-btn");o&&(o.disabled=t,o.textContent=t?"Uploading...":"Replace"),l&&(l.disabled=t)}async handleReplace(){if(!this.isUploading)try{if(((await C.getExtensionSettings())?.fileOperations||"native")==="web")this.showFileInput();else{let l=await C.selectFile();if(l){let a=l.data;if(!(a instanceof Uint8Array)){if(Array.isArray(a))a=new Uint8Array(a);else if(a&&typeof a=="object"){let r=Object.keys(a).filter(i=>!isNaN(parseInt(i,10))).sort((i,c)=>parseInt(i,10)-parseInt(c,10)).map(i=>a[i]);a=new Uint8Array(r)}}let s={name:l.name,arrayBuffer:async()=>a.buffer};await this.uploadFile(s)}}}catch(t){console.error("Replace failed:",t),u(`Replace failed: ${t.message}`)}}showFileInput(){let t=document.createElement("input");t.type="file",t.onchange=async o=>{let l=o.target.files[0];l&&await this.uploadFile(l)},t.click()}async uploadFile(t){if(!(!this.currentRowId||!this.currentColName)&&!this.isUploading){this.setUploadState(!0);try{u(`Reading ${t.name}...`);let o=await t.arrayBuffer(),l=new Uint8Array(o),a=l.length/(1024*1024),s=50;if(a>s)throw new Error(`File too large (${a.toFixed(1)}MB). Maximum size is ${s}MB to prevent freezing.`);a>10?u(`Uploading ${t.name} (${a.toFixed(1)}MB - this may take a moment)...`):u(`Uploading ${t.name}...`);let{rowIdx:r,colIdx:i}=this.currentCellInfo,c=this.currentData;await C.updateCell(n.selectedTable,this.currentRowId,this.currentColName,l,c),n.gridData&&n.gridData[r]&&(n.gridData[r][i+R()]=l),this.inspect(l,this.currentRowId,this.currentColName,r,i),u(`Replaced with ${t.name}`)}catch(o){console.error("Replace failed:",o);let l=o.message||String(o);l.includes("timeout")&&(l="Upload timed out. Try a smaller file or increase the timeout."),u(`Replace failed: ${l}`)}finally{this.setUploadState(!1)}}}close(){this.modal.classList.add("hidden"),this.cleanup()}cleanup(){this.setUploadState(!1),this.currentObjectUrl&&(URL.revokeObjectURL(this.currentObjectUrl),this.currentObjectUrl=null),this.previewContainer.innerHTML="",this.hexContainer.value="",this.infoContainer.textContent="",this.currentData=null}switchTab(t){this.modal.querySelectorAll(".tab-btn").forEach(a=>{a.dataset.tab===t?(a.classList.add("active"),a.style.borderBottom="2px solid var(--accent-color)",a.style.color="var(--text-primary)"):(a.classList.remove("active"),a.style.borderBottom="none",a.style.color="var(--text-secondary)")});let o=document.getElementById("tab-preview"),l=document.getElementById("tab-hex");t==="preview"?(o.style.display="flex",l.style.display="none"):(o.style.display="none",l.style.display="block")}async download(){if(!this.currentData)return;let t=this.currentType?.ext||"bin",o=`blob_${this.currentRowId}.${t}`;try{((await C.getExtensionSettings())?.fileOperations||"native")==="web"?(this.downloadBlob(this.currentData,o),u(`Downloaded ${o}`)):(await C.saveFile(o,this.currentData),u(`Saved ${o}`))}catch(l){console.error("Download failed:",l),u(`Download failed: ${l.message}`)}}downloadBlob(t,o){let l=new Blob([t]),a=URL.createObjectURL(l),s=document.createElement("a");s.href=a,s.download=o,s.click(),URL.revokeObjectURL(a)}inspect(t,o,l,a,s){this.cleanup(),this.currentRowId=o,this.currentColName=l,this.currentCellInfo={rowIdx:a,colIdx:s},this.modal.classList.remove("hidden"),this.switchTab("preview");let r=t instanceof Uint8Array?t:new Uint8Array(t);this.currentData=r;let i=this.detectType(r);this.currentType=i;let c=this.formatSize(r.length);this.infoContainer.textContent=`${l} (Row ${o}) | ${i.mime||"Unknown Type"} | ${c}`,this.renderPreview(r,i),this.renderHex(r)}detectType(t){if(this.checkSignature(t,T.PNG))return{mime:"image/png",type:"image",ext:"png"};if(this.checkSignature(t,T.JPEG))return{mime:"image/jpeg",type:"image",ext:"jpg"};if(this.checkSignature(t,T.GIF))return{mime:"image/gif",type:"image",ext:"gif"};if(this.checkSignature(t,T.BMP))return{mime:"image/bmp",type:"image",ext:"bmp"};if(this.checkSignature(t,T.RIFF)&&this.checkSignature(t.subarray(8),T.WEBP))return{mime:"image/webp",type:"image",ext:"webp"};if(this.checkSignature(t,T.PDF))return{mime:"application/pdf",type:"pdf",ext:"pdf"};if(this.checkSignature(t,T.ID3))return{mime:"audio/mpeg",type:"audio",ext:"mp3"};if(this.checkSignature(t,T.MP3_SYNC1)||this.checkSignature(t,T.MP3_SYNC2)||this.checkSignature(t,T.MP3_SYNC3))return{mime:"audio/mpeg",type:"audio",ext:"mp3"};if(this.checkSignature(t,T.OGG))return{mime:"audio/ogg",type:"audio",ext:"ogg"};if(this.checkSignature(t,T.RIFF)&&this.checkSignature(t.subarray(8),T.WAVE))return{mime:"audio/wav",type:"audio",ext:"wav"};if(this.checkSignature(t,T.FLAC))return{mime:"audio/flac",type:"audio",ext:"flac"};if(this.checkSignature(t.subarray(4),T.FTYP)){let o=String.fromCharCode(...t.subarray(8,12));return o.startsWith("mp4")||o==="isom"||o==="avc1"||o==="M4V "?{mime:"video/mp4",type:"video",ext:"mp4"}:o==="qt "||o.startsWith("M4A")?{mime:"video/quicktime",type:"video",ext:"mov"}:{mime:"video/mp4",type:"video",ext:"mp4"}}if(this.checkSignature(t,T.WEBM))return{mime:"video/webm",type:"video",ext:"webm"};if(this.checkSignature(t,T.RIFF)&&this.checkSignature(t.subarray(8),T.AVI))return{mime:"video/avi",type:"video",ext:"avi"};if(this.isText(t)){try{let o=new TextDecoder().decode(t),l=JSON.parse(o);if(typeof l=="object"&&l!==null)return{mime:"application/json",type:"json",ext:"json"}}catch{}return{mime:"text/plain",type:"text",ext:"txt"}}return{mime:"application/octet-stream",type:"binary",ext:"bin"}}checkSignature(t,o){if(t.lengththis.download()),l.appendChild(a),l.appendChild(s),l.appendChild(r),this.previewContainer.appendChild(l)}else{let l=document.createElement("div");l.className="empty-view";let a=document.createElement("span");a.className="codicon codicon-file-binary",a.style.fontSize="48px",a.style.opacity="0.5";let s=document.createElement("span");s.style.marginTop="12px",s.textContent="Binary Data";let r=document.createElement("span");r.style.fontSize="12px",r.style.opacity="0.7",r.textContent="Use Hex view to inspect",l.appendChild(a),l.appendChild(s),l.appendChild(r),this.previewContainer.appendChild(l)}}renderHex(t){if(!this.hexContainer)return;let o=16*1e3,l="",a=t.subarray(0,o);for(let s=0;s=32&&p<=126?String.fromCharCode(p):".")}else i.push(" "),c.push(" ");let d=i.slice(0,8).join(" "),m=i.slice(8).join(" "),f=c.join("");l+=`${r} ${d} ${m} |${f}| + `,a.appendChild(f)}return l.appendChild(a),l}function Yt(e,t,o,l,a,s,r,i){let c=document.createElement("tbody"),d=[];for(let p=0;p({idx:h,rowId:B(p,h)})).filter(p=>n.pinnedRowIds.has(p.rowId)),...n.gridData.map((p,h)=>({idx:h,rowId:B(p,h)})).filter(p=>!n.pinnedRowIds.has(p.rowId))],f=document.createDocumentFragment();for(let{idx:p,rowId:h}of g){let w=n.gridData[p],S=n.selectedRowIds.has(h),y=n.pinnedRowIds.has(h),x=document.createElement("tr");x.id=`row-${p}`,x.className=`data-row ${S?"selected":""} ${y?"pinned":""}`,x.dataset.rowid=h,x.dataset.rowidx=p,y&&(x.style.top=`${m.get(h)}px`);let A=document.createElement("td");A.className="data-cell row-number",Object.assign(A.style,{width:`${l}px`,minWidth:`${l}px`,maxWidth:`${l}px`,position:"sticky",left:"0",zIndex:y?"8":"2"});let L=n.currentPageIndex*n.rowsPerPage+p+1;A.appendChild(document.createTextNode(String(L)));let b=document.createElement("span");b.className=`pin-icon codicon codicon-pin ${y?"pinned":""}`,b.title=y?"Unpin row":"Pin row",A.appendChild(b),x.appendChild(A);for(let D=0;Db&&b.trim()!=="");if(i.innerHTML="",n.gridData.length===0&&!f&&n.tableColumns.length===0){i.appendChild(Jt());return}let p=new Set;if(n.selectedCells.length>0)for(let b of n.selectedCells)p.add(`${b.rowIdx},${b.colIdx}`);let h=document.createElement("table");if(h.className="data-grid",Object.keys(n.columnWidths).length===0&&n.gridData.length>0)for(let b of n.tableColumns){let D=b.name.length,N=b.isPrimaryKey?86:70,W=D*8+N;n.columnWidths[b.name]=Math.max(80,Math.min(250,W))}let w=[...n.tableColumns.filter(b=>n.pinnedColumns.has(b.name)),...n.tableColumns.filter(b=>!n.pinnedColumns.has(b.name))],S=new Map,y=r-1;for(let b of w)n.pinnedColumns.has(b.name)&&(S.set(b.name,y),y+=n.columnWidths[b.name]||120);let x=new Map;n.tableColumns.forEach((b,D)=>x.set(b.name,D));let A=Xt(r,w,S);h.appendChild(A);let L=Yt(w,x,S,r,52,26,p,f);h.appendChild(L),i.appendChild(h),i.scrollLeft=m,i.scrollTop=g,We()}function Ke(){document.getElementById("pageIndicator").textContent=`${n.currentPageIndex+1} / ${n.totalPageCount}`,document.getElementById("btnFirst").disabled=n.currentPageIndex===0,document.getElementById("btnPrev").disabled=n.currentPageIndex===0,document.getElementById("btnNext").disabled=n.currentPageIndex>=n.totalPageCount-1,document.getElementById("btnLast").disabled=n.currentPageIndex>=n.totalPageCount-1}async function q(){if(n.selectedTable)try{let e=await C.getTableInfo(n.selectedTable);n.tableColumns=e.map(o=>({cid:o.ordinal,name:o.identifier,type:o.declaredType,notnull:o.isRequired,dflt_value:o.defaultExpression,isPrimaryKey:o.primaryKeyPosition>0})).sort((o,l)=>o.cid-l.cid);let t=new Set(n.tableColumns.map(o=>o.name));n.sortedColumn&&!t.has(n.sortedColumn)&&(n.sortedColumn=null,n.sortAscending=!0);for(let o of Object.keys(n.columnFilters))t.has(o)||delete n.columnFilters[o]}catch(e){console.error("Error loading columns:",e),u("Error loading columns")}}async function v(e=!0,t=!0){if(!n.selectedTable)return;let o=document.getElementById("gridContainer"),l=!!(o&&o.querySelector(".data-grid"));t&&l&&(n.scrollPosition.left=o.scrollLeft,n.scrollPosition.top=o.scrollTop),e&&(n.isLoadingData=!0,l||Ve()),P();try{let a=[];for(let[g,f]of Object.entries(n.columnFilters))f&&f.trim()&&a.push({column:g,value:f});let s=n.tableColumns.map(g=>g.name),r={filters:a,globalFilter:n.filterQuery,columns:s};n.totalRecordCount=await C.fetchTableCount(n.selectedTable,r),n.totalPageCount=Math.max(1,Math.ceil(n.totalRecordCount/n.rowsPerPage)),n.currentPageIndex>=n.totalPageCount&&(n.currentPageIndex=Math.max(0,n.totalPageCount-1));let d={columns:n.selectedTableType==="table"?["rowid",...s]:s,orderBy:n.sortedColumn,orderDir:n.sortAscending?"ASC":"DESC",limit:n.rowsPerPage,offset:n.currentPageIndex*n.rowsPerPage,filters:a,globalFilter:n.filterQuery},m=await C.fetchTableData(n.selectedTable,d);n.gridData=m.rows||[],!e&&o&&o.querySelector(".data-grid")&&(n.scrollPosition.left=o.scrollLeft,n.scrollPosition.top=o.scrollTop),!e&&n.editingCellInfo||j(n.scrollPosition.top,n.scrollPosition.left),o&&(o.scrollLeft=n.scrollPosition.left,o.scrollTop=n.scrollPosition.top),Ke(),u(`${n.totalRecordCount} records`)}catch(a){console.error("Error loading data:",a),u(`Error: ${a.message}`),le(a.message)}finally{e&&(n.isLoadingData=!1)}}var T={PNG:[137,80,78,71,13,10,26,10],JPEG:[255,216,255],GIF:[71,73,70,56],BMP:[66,77],RIFF:[82,73,70,70],WEBP:[87,69,66,80],PDF:[37,80,68,70,45],ID3:[73,68,51],MP3_SYNC1:[255,251],MP3_SYNC2:[255,243],MP3_SYNC3:[255,242],OGG:[79,103,103,83],WAVE:[87,65,86,69],FLAC:[102,76,97,67],FTYP:[102,116,121,112],WEBM:[26,69,223,163],AVI:[65,86,73,32]},se=class{constructor(){this.currentObjectUrl=null,this.modal=document.getElementById("blob-inspector-modal"),this.previewContainer=document.getElementById("tab-preview"),this.hexContainer=document.querySelector(".hex-dump"),this.infoContainer=document.getElementById("blob-info"),this.currentData=null,this.currentType=null,this.currentRowId=null,this.currentColName=null,this.currentCellInfo=null,this.isUploading=!1,this.setupEventListeners()}setupEventListeners(){this.modal.querySelectorAll(".modal-close").forEach(l=>{l.addEventListener("click",()=>this.close())}),this.modal.querySelectorAll(".tab-btn").forEach(l=>{l.addEventListener("click",a=>{let s=a.target.dataset.tab;this.switchTab(s)})});let t=document.getElementById("blob-download-btn");t&&t.addEventListener("click",()=>this.download());let o=document.getElementById("blob-replace-btn");o&&o.addEventListener("click",()=>this.handleReplace())}setUploadState(t){this.isUploading=t;let o=document.getElementById("blob-replace-btn"),l=document.getElementById("blob-download-btn");o&&(o.disabled=t,o.textContent=t?"Uploading...":"Replace"),l&&(l.disabled=t)}async handleReplace(){if(!this.isUploading)try{if(((await C.getExtensionSettings())?.fileOperations||"native")==="web")this.showFileInput();else{let l=await C.selectFile();if(l){let a=l.data;if(!(a instanceof Uint8Array)){if(Array.isArray(a))a=new Uint8Array(a);else if(a&&typeof a=="object"){let r=Object.keys(a).filter(i=>!isNaN(parseInt(i,10))).sort((i,c)=>parseInt(i,10)-parseInt(c,10)).map(i=>a[i]);a=new Uint8Array(r)}}let s={name:l.name,arrayBuffer:async()=>a.buffer};await this.uploadFile(s)}}}catch(t){console.error("Replace failed:",t),u(`Replace failed: ${t.message}`)}}showFileInput(){let t=document.createElement("input");t.type="file",t.onchange=async o=>{let l=o.target.files[0];l&&await this.uploadFile(l)},t.click()}async uploadFile(t){if(!(!this.currentRowId||!this.currentColName)&&!this.isUploading){this.setUploadState(!0);try{u(`Reading ${t.name}...`);let o=await t.arrayBuffer(),l=new Uint8Array(o),a=l.length/(1024*1024),s=50;if(a>s)throw new Error(`File too large (${a.toFixed(1)}MB). Maximum size is ${s}MB to prevent freezing.`);a>10?u(`Uploading ${t.name} (${a.toFixed(1)}MB - this may take a moment)...`):u(`Uploading ${t.name}...`);let{rowIdx:r,colIdx:i}=this.currentCellInfo,c=this.currentData;await C.updateCell(n.selectedTable,this.currentRowId,this.currentColName,l,c),n.gridData&&n.gridData[r]&&(n.gridData[r][i+R()]=l),this.inspect(l,this.currentRowId,this.currentColName,r,i),u(`Replaced with ${t.name}`)}catch(o){console.error("Replace failed:",o);let l=o.message||String(o);l.includes("timeout")&&(l="Upload timed out. Try a smaller file or increase the timeout."),u(`Replace failed: ${l}`)}finally{this.setUploadState(!1)}}}close(){this.modal.classList.add("hidden"),this.cleanup()}cleanup(){this.setUploadState(!1),this.currentObjectUrl&&(URL.revokeObjectURL(this.currentObjectUrl),this.currentObjectUrl=null),this.previewContainer.innerHTML="",this.hexContainer.value="",this.infoContainer.textContent="",this.currentData=null}switchTab(t){this.modal.querySelectorAll(".tab-btn").forEach(a=>{a.dataset.tab===t?(a.classList.add("active"),a.style.borderBottom="2px solid var(--accent-color)",a.style.color="var(--text-primary)"):(a.classList.remove("active"),a.style.borderBottom="none",a.style.color="var(--text-secondary)")});let o=document.getElementById("tab-preview"),l=document.getElementById("tab-hex");t==="preview"?(o.style.display="flex",l.style.display="none"):(o.style.display="none",l.style.display="block")}async download(){if(!this.currentData)return;let t=this.currentType?.ext||"bin",o=`blob_${this.currentRowId}.${t}`;try{((await C.getExtensionSettings())?.fileOperations||"native")==="web"?(this.downloadBlob(this.currentData,o),u(`Downloaded ${o}`)):(await C.saveFile(o,this.currentData),u(`Saved ${o}`))}catch(l){console.error("Download failed:",l),u(`Download failed: ${l.message}`)}}downloadBlob(t,o){let l=new Blob([t]),a=URL.createObjectURL(l),s=document.createElement("a");s.href=a,s.download=o,s.click(),URL.revokeObjectURL(a)}inspect(t,o,l,a,s){this.cleanup(),this.currentRowId=o,this.currentColName=l,this.currentCellInfo={rowIdx:a,colIdx:s},this.modal.classList.remove("hidden"),this.switchTab("preview");let r=t instanceof Uint8Array?t:new Uint8Array(t);this.currentData=r;let i=this.detectType(r);this.currentType=i;let c=this.formatSize(r.length);this.infoContainer.textContent=`${l} (Row ${o}) | ${i.mime||"Unknown Type"} | ${c}`,this.renderPreview(r,i),this.renderHex(r)}detectType(t){if(this.checkSignature(t,T.PNG))return{mime:"image/png",type:"image",ext:"png"};if(this.checkSignature(t,T.JPEG))return{mime:"image/jpeg",type:"image",ext:"jpg"};if(this.checkSignature(t,T.GIF))return{mime:"image/gif",type:"image",ext:"gif"};if(this.checkSignature(t,T.BMP))return{mime:"image/bmp",type:"image",ext:"bmp"};if(this.checkSignature(t,T.RIFF)&&this.checkSignature(t.subarray(8),T.WEBP))return{mime:"image/webp",type:"image",ext:"webp"};if(this.checkSignature(t,T.PDF))return{mime:"application/pdf",type:"pdf",ext:"pdf"};if(this.checkSignature(t,T.ID3))return{mime:"audio/mpeg",type:"audio",ext:"mp3"};if(this.checkSignature(t,T.MP3_SYNC1)||this.checkSignature(t,T.MP3_SYNC2)||this.checkSignature(t,T.MP3_SYNC3))return{mime:"audio/mpeg",type:"audio",ext:"mp3"};if(this.checkSignature(t,T.OGG))return{mime:"audio/ogg",type:"audio",ext:"ogg"};if(this.checkSignature(t,T.RIFF)&&this.checkSignature(t.subarray(8),T.WAVE))return{mime:"audio/wav",type:"audio",ext:"wav"};if(this.checkSignature(t,T.FLAC))return{mime:"audio/flac",type:"audio",ext:"flac"};if(this.checkSignature(t.subarray(4),T.FTYP)){let o=String.fromCharCode(...t.subarray(8,12));return o.startsWith("mp4")||o==="isom"||o==="avc1"||o==="M4V "?{mime:"video/mp4",type:"video",ext:"mp4"}:o==="qt "||o.startsWith("M4A")?{mime:"video/quicktime",type:"video",ext:"mov"}:{mime:"video/mp4",type:"video",ext:"mp4"}}if(this.checkSignature(t,T.WEBM))return{mime:"video/webm",type:"video",ext:"webm"};if(this.checkSignature(t,T.RIFF)&&this.checkSignature(t.subarray(8),T.AVI))return{mime:"video/avi",type:"video",ext:"avi"};if(this.isText(t)){try{let o=new TextDecoder().decode(t),l=JSON.parse(o);if(typeof l=="object"&&l!==null)return{mime:"application/json",type:"json",ext:"json"}}catch{}return{mime:"text/plain",type:"text",ext:"txt"}}return{mime:"application/octet-stream",type:"binary",ext:"bin"}}checkSignature(t,o){if(t.lengththis.download()),l.appendChild(a),l.appendChild(s),l.appendChild(r),this.previewContainer.appendChild(l)}else{let l=document.createElement("div");l.className="empty-view";let a=document.createElement("span");a.className="codicon codicon-file-binary",a.style.fontSize="48px",a.style.opacity="0.5";let s=document.createElement("span");s.style.marginTop="12px",s.textContent="Binary Data";let r=document.createElement("span");r.style.fontSize="12px",r.style.opacity="0.7",r.textContent="Use Hex view to inspect",l.appendChild(a),l.appendChild(s),l.appendChild(r),this.previewContainer.appendChild(l)}}renderHex(t){if(!this.hexContainer)return;let o=16*1e3,l="",a=t.subarray(0,o);for(let s=0;s=32&&p<=126?String.fromCharCode(p):".")}else i.push(" "),c.push(" ");let d=i.slice(0,8).join(" "),m=i.slice(8).join(" "),g=c.join("");l+=`${r} ${d} ${m} |${g}| `}t.length>o&&(l+=` -... (${(t.length-o).toLocaleString()} more bytes not shown)`),this.hexContainer.value=l}formatSize(t){if(t===0)return"0 B";let o=1024,l=["B","KB","MB","GB"],a=Math.floor(Math.log(t)/Math.log(o));return parseFloat((t/Math.pow(o,a)).toFixed(2))+" "+l[a]}};var ve;function qe(){ve=new se,document.getElementById("btnCloseCellPreview")?.addEventListener("click",G),document.getElementById("formatJsonBtn")?.addEventListener("click",Zt),document.getElementById("compactJsonBtn")?.addEventListener("click",Qt),document.getElementById("wrapTextBtn")?.addEventListener("click",en),document.getElementById("openInVsCodeBtn")?.addEventListener("click",Te),document.getElementById("btnCancelCellPreview")?.addEventListener("click",G),document.getElementById("cellPreviewSaveBtn")?.addEventListener("click",Ze)}function He(e,t,o){if(n.selectedTableType!=="table"){u("Views are read-only");return}if(n.editingCellInfo){if(n.editingCellInfo.rowIdx===e&&n.editingCellInfo.colIdx===t)return;ie()}let l=n.tableColumns[t];if(!l)return;let a=document.getElementById(`cell-${e}-${t}`);if(!a)return;let s=n.gridData[e],r=k(s,t);if(r instanceof Uint8Array){H(e,t,o);return}if(typeof r=="string"){let d=r.trim();if(d.startsWith("{")&&d.endsWith("}")||d.startsWith("[")&&d.endsWith("]"))try{JSON.parse(d),H(e,t,o);return}catch{}}n.editingCellInfo={rowIdx:e,colIdx:t,rowId:o,columnName:l.name,originalValue:r};let i=r===null?"":String(r);a.innerHTML="",a.classList.add("editing");let c=document.createElement("textarea");c.className="cell-input",c.value=i,c.spellcheck=!1,a.appendChild(c),c.focus(),n.activeCellInput=c,c.addEventListener("keydown",Ge),c.addEventListener("blur",Je),c.addEventListener("click",d=>d.stopPropagation()),n.isTransitioningEdit=!0,setTimeout(()=>{n.isTransitioningEdit=!1},100)}function Ge(e){e.key==="Enter"&&!e.shiftKey?(e.preventDefault(),Xe()):e.key==="Escape"&&(e.preventDefault(),ie())}function Je(){setTimeout(()=>{n.editingCellInfo&&Xe()},100)}async function Xe(){if(n.isSavingCell||!n.editingCellInfo||!n.activeCellInput)return;let{rowIdx:e,colIdx:t,rowId:o,columnName:l,originalValue:a}=n.editingCellInfo,s=n.activeCellInput.value,r=a===null?"":String(a);if(s===r){ie(),n.selectedCells=[],n.lastSelectedCell=null,U();return}let i=n.tableColumns[t],c=i&&i.notnull===1,d;s===""?c?d="":d=null:!isNaN(Number(s))&&s.trim()!==""?d=Number(s):d=s;try{n.isSavingCell=!0,u("Saving..."),await C.updateCell(n.selectedTable,oe(o),l,d,a),n.gridData[e][t+R()]=d,Ye(),Be(e,t,d),n.selectedCells=[],n.lastSelectedCell=null,U(),u("Saved")}catch(m){console.error("Save failed:",m);let f=m.message||String(m);u(`Save failed: ${f}`)}finally{n.isSavingCell=!1}}function ie(){if(!n.editingCellInfo)return;let{rowIdx:e,colIdx:t,originalValue:o}=n.editingCellInfo;Ye(),Be(e,t,o),ae()}function Ye(){n.activeCellInput&&(n.activeCellInput.removeEventListener("keydown",Ge),n.activeCellInput.removeEventListener("blur",Je),n.activeCellInput=null),n.editingCellInfo=null}async function Te(){if(!n.cellPreviewInfo)return;let{rowIdx:e,colIdx:t,rowId:o,columnName:l,originalValue:a}=n.cellPreviewInfo,s=n.tableColumns[t],r=document.getElementById("vscode-env")?.dataset.webviewId||"default";try{u("Opening in VS Code..."),G(),await C.openCellEditor({table:n.selectedTable,name:""},oe(o),l,{},{value:a,type:{type:s.type},webviewId:r,rowCount:n.gridData.length}),u("Opened in VS Code")}catch(i){console.error("Failed to open in VS Code:",i),u(`Error: ${i.message}`)}}function H(e,t,o){n.editingCellInfo&&ie();let l=n.tableColumns[t];if(!l)return;let a=n.gridData[e];if(!a)return;let s=k(a,t);if(s instanceof Uint8Array){ve&&ve.inspect(s,o,l.name,e,t);return}n.cellPreviewInfo={rowIdx:e,colIdx:t,rowId:o,columnName:l.name,originalValue:s};let r=document.getElementById("cellPreviewModal"),i=document.getElementById("cellPreviewColumnName"),c=document.getElementById("cellPreviewTypeBadge"),d=document.getElementById("cellPreviewTextarea"),m=document.getElementById("cellPreviewReadonlyBadge"),f=document.getElementById("cellPreviewSaveBtn"),g=document.getElementById("wrapTextBtn");i.textContent=l.name,c.textContent=l.type||"TEXT";let p="";s==null?p="":s instanceof Uint8Array?p="[BLOB: "+Array.from(s).map(w=>w.toString(16).padStart(2,"0")).join(" ")+"]":p=String(s),d.value=p;let h=n.selectedTableType!=="table";d.readOnly=h,h?(d.classList.add("readonly"),m.style.display="inline",f.style.display="none"):(d.classList.remove("readonly"),m.style.display="none",f.style.display="inline-block"),re(),d.style.whiteSpace=n.cellPreviewWrapEnabled?"pre-wrap":"pre",d.style.overflowX=n.cellPreviewWrapEnabled?"hidden":"auto",g.classList.toggle("active",n.cellPreviewWrapEnabled),r.classList.remove("hidden"),d.focus(),d.oninput=re,d.onkeydown=w=>{w.key==="Escape"?(w.preventDefault(),G()):w.key==="Enter"&&(w.ctrlKey||w.metaKey)&&(w.preventDefault(),Ze())}}function re(){let e=document.getElementById("cellPreviewTextarea"),t=document.getElementById("cellPreviewCharCount"),o=e.value.length;t.textContent=`${o.toLocaleString()} character${o!==1?"s":""}`}function G(){document.getElementById("cellPreviewModal").classList.add("hidden"),n.cellPreviewInfo=null}async function Ze(){if(!n.cellPreviewInfo)return;if(n.selectedTableType!=="table"){u("Views are read-only");return}let{rowIdx:e,colIdx:t,rowId:o,columnName:l,originalValue:a}=n.cellPreviewInfo,r=document.getElementById("cellPreviewTextarea").value,i=a===null?"":String(a);if(r===i){G(),n.selectedCells=[],n.lastSelectedCell=null,U();return}let c=n.tableColumns[t],d=c&&c.notnull===1,m;r===""?m=d?"":null:!isNaN(Number(r))&&r.trim()!==""?m=Number(r):m=r;try{u("Saving..."),await C.updateCell(n.selectedTable,oe(o),l,m,a),n.gridData[e][t+R()]=m,G(),Be(e,t,m),n.selectedCells=[],n.lastSelectedCell=null,U(),u("Saved")}catch(f){console.error("Save failed:",f),u(`Save failed: ${f.message}`)}}function Zt(){let e=document.getElementById("cellPreviewTextarea");try{let t=JSON.parse(e.value);e.value=JSON.stringify(t,null,2),re()}catch{u("Content is not valid JSON")}}function Qt(){let e=document.getElementById("cellPreviewTextarea");try{let t=JSON.parse(e.value);e.value=JSON.stringify(t),re()}catch{u("Content is not valid JSON")}}function en(){n.cellPreviewWrapEnabled=!n.cellPreviewWrapEnabled;let e=document.getElementById("cellPreviewTextarea"),t=document.getElementById("wrapTextBtn");e.style.whiteSpace=n.cellPreviewWrapEnabled?"pre-wrap":"pre",e.style.overflowX=n.cellPreviewWrapEnabled?"hidden":"auto",t.classList.toggle("active",n.cellPreviewWrapEnabled)}function Be(e,t,o){let l=document.getElementById(`cell-${e}-${t}`);if(!l)return;l.classList.remove("editing"),o==null?l.classList.add("null-value"):l.classList.remove("null-value");let a=n.tableColumns[t],s=K(o,a?.type,n.dateFormat,a?.name),r=o!=null&&!(o instanceof Uint8Array);l.textContent="";let i=document.createElement("span");if(i.className="cell-text",i.textContent=s,l.appendChild(i),r){let d=document.createElement("span");d.className="expand-icon codicon codicon-link-external",d.title="View full content",l.appendChild(d)}let c=i.scrollWidth>i.clientWidth;l.classList.toggle("has-overflow",c)}function Qe(){clearTimeout(n.filterTimer),n.filterTimer=setTimeout(()=>{n.filterQuery=document.getElementById("filterInput").value,n.currentPageIndex=0,v(),M()},300)}function et(){n.rowsPerPage=parseInt(document.getElementById("pageSizeSelect").value,10),n.currentPageIndex=0,v(),M()}function tt(){let e=document.getElementById("dateFormatSelect");e&&(n.dateFormat=e.value,j(),M())}function Q(e){e>=0&&el.name===t);if(o!==-1){if((e.shiftKey||e.metaKey||e.ctrlKey)&&e.preventDefault(),n.selectedRowIds.clear(),e.shiftKey&&n.lastSelectedColumnIndex!==null){e.metaKey||e.ctrlKey||(n.selectedCells=[],n.selectedColumns.clear());let l=Math.min(n.lastSelectedColumnIndex,o),a=Math.max(n.lastSelectedColumnIndex,o),s=new Array;if(n.selectedCells.length>0)for(let r of n.selectedCells)r.colIdx>=l&&r.colIdx<=a&&(s[r.rowIdx]||(s[r.rowIdx]=new Set),s[r.rowIdx].add(r.colIdx));for(let r=l;r<=a;r++){let i=n.tableColumns[r].name;n.selectedColumns.add(i);for(let c=0;c0&&a===l)n.selectedCells=n.selectedCells.filter(r=>r.colIdx!==o),n.selectedColumns.delete(t);else{let r=new Set;for(let i of n.selectedCells)i.colIdx===o&&r.add(i.rowIdx);for(let i=0;i0&&a===l&&n.selectedColumns.size===1&&n.selectedColumns.has(t))n.selectedCells=[],n.selectedColumns.clear(),n.lastSelectedColumnIndex=null;else{n.selectedCells=[],n.selectedColumns.clear();for(let r=0;rr.name===n.resizingColumn);if(l===-1)return;let a=document.querySelector(`th[data-column="${n.resizingColumn}"]`);a&&(a.style.width=`${o}px`,a.style.minWidth=`${o}px`,a.style.maxWidth=`${o}px`);let s=document.querySelectorAll(`.data-row td:nth-child(${l+2})`);for(let r of s)r.style.width=`${o}px`,r.style.minWidth=`${o}px`,r.style.maxWidth=`${o}px`;n.pinnedColumns.has(n.resizingColumn)}function ct(){if(!n.resizingColumn)return;let e=document.querySelector(".resize-handle.resizing");e&&e.classList.remove("resizing"),n.resizingColumn=null,document.removeEventListener("mousemove",it),document.removeEventListener("mouseup",ct),document.body.style.userSelect="",document.body.style.cursor="",j()}function dt(e,t,o){if(e.stopPropagation(),(e.shiftKey||e.metaKey||e.ctrlKey)&&e.preventDefault(),n.selectedCells=[],n.lastSelectedCell=null,n.selectedColumns.clear(),e.shiftKey&&n.lastSelectedRowIndex!==null){e.metaKey||e.ctrlKey||n.selectedRowIds.clear();let l=Math.min(n.lastSelectedRowIndex,o),a=Math.max(n.lastSelectedRowIndex,o);for(let s=l;s<=a;s++){let r=B(n.gridData[s],s);n.selectedRowIds.add(r)}}else e.ctrlKey||e.metaKey?(n.selectedRowIds.has(t)?n.selectedRowIds.delete(t):n.selectedRowIds.add(t),n.lastSelectedRowIndex=o):n.selectedRowIds.has(t)&&n.selectedRowIds.size===1?(n.selectedRowIds.delete(t),n.lastSelectedRowIndex=null):(n.selectedRowIds.clear(),n.selectedRowIds.add(t),n.lastSelectedRowIndex=o);U(),P(),z()}function ce(e){if(e.stopPropagation(),n.gridData.length===0)return;n.selectedCells=[],n.lastSelectedCell=null,n.selectedColumns.clear();let t=!0;for(let o=0;o=s&&m.rowIdx<=r&&m.colIdx>=i&&m.colIdx<=c&&(d[m.rowIdx]||(d[m.rowIdx]=new Set),d[m.rowIdx].add(m.colIdx));for(let m=s;m<=r;m++){let f=d[m];for(let g=i;g<=c;g++)if(!f||!f.has(g)){let p=B(n.gridData[m],m),h=k(n.gridData[m],g);n.selectedCells.push({rowIdx:m,colIdx:g,rowId:p,value:h})}}}else if(e.metaKey||e.ctrlKey){e.preventDefault(),n.selectedRowIds.clear();let s=n.selectedCells.findIndex(r=>r.rowIdx===t&&r.colIdx===o);s>=0?n.selectedCells.splice(s,1):(n.selectedCells.push({rowIdx:t,colIdx:o,rowId:l,value:a}),n.lastSelectedCell={rowIdx:t,colIdx:o})}else if(e.shiftKey&&n.lastSelectedCell){e.preventDefault(),n.selectedRowIds.clear(),n.selectedCells=[];let s=Math.min(n.lastSelectedCell.rowIdx,t),r=Math.max(n.lastSelectedCell.rowIdx,t),i=Math.min(n.lastSelectedCell.colIdx,o),c=Math.max(n.lastSelectedCell.colIdx,o);for(let d=s;d<=r;d++)for(let m=i;m<=c;m++){let f=B(n.gridData[d],d),g=k(n.gridData[d],m);n.selectedCells.push({rowIdx:d,colIdx:m,rowId:f,value:g})}}else n.selectedRowIds.clear(),n.selectedCells=[{rowIdx:t,colIdx:o,rowId:l,value:a}],n.lastSelectedCell={rowIdx:t,colIdx:o},n.selectedColumns.clear();U(),P(),z()}function mt(e,t,o,l){if(n.cellEditBehavior==="vscode"){let a=n.tableColumns[o];if(!a)return;let s=n.gridData[t];if(!s)return;let r=k(s,o);n.cellPreviewInfo={rowIdx:t,colIdx:o,rowId:l,columnName:a.name,originalValue:r},Te()}else n.cellEditBehavior==="modal"?H(t,o,l):He(t,o,l)}function pt(){document.getElementById("filterInput")?.addEventListener("keyup",Qe),document.getElementById("pageSizeSelect")?.addEventListener("change",et),document.getElementById("dateFormatSelect")?.addEventListener("change",tt),document.getElementById("btnFirst")?.addEventListener("click",()=>Q(0)),document.getElementById("btnPrev")?.addEventListener("click",()=>Q(n.currentPageIndex-1)),document.getElementById("btnNext")?.addEventListener("click",()=>Q(n.currentPageIndex+1)),document.getElementById("btnLast")?.addEventListener("click",()=>Q(n.totalPageCount-1))}function ft(){let e=document.getElementById("gridContainer");e&&(e.addEventListener("mousedown",tn),e.addEventListener("keydown",nn),e.addEventListener("click",on),e.addEventListener("dblclick",sn),e.addEventListener("mouseover",rn),e.addEventListener("scroll",cn,{passive:!0}))}function tn(e){if(e.target.classList.contains("resize-handle")){e.stopPropagation();let t=e.target.closest(".header-cell");t&&t.dataset.column&&rt(e,t.dataset.column)}}function nn(e){if(e.target.classList.contains("column-filter")){let t=e.target.dataset.column;t&&ot(e,t)}}function on(e){let t=e.target;if(t.closest(".grid-header")){ln(e,t);return}an(e,t)}function ln(e,t){if(t.closest(".filter-apply-btn")){e.stopPropagation();let l=t.closest(".header-cell");l&&l.dataset.column&&Re(l.dataset.column);return}if(t.closest(".header-bottom")||t.closest(".column-filter")){e.stopPropagation();return}if(t.closest(".select-column-icon")){e.stopPropagation();let l=t.closest(".header-cell");l&&l.dataset.column&<(e,l.dataset.column);return}if(t.closest(".pin-icon")){e.stopPropagation();let l=t.closest(".header-cell");l&&l.dataset.column&&at(e,l.dataset.column);return}if(t.closest(".row-number-header")){ce(e);return}let o=t.closest(".header-top");if(o){let l=o.closest(".header-cell");l&&l.dataset.column&&nt(l.dataset.column);return}}function an(e,t){if(t.closest(".pin-icon")){let l=t.closest(".data-row");if(l){let a=l.dataset.rowid,s=ee(a);st(e,s)}return}if(t.closest(".expand-icon")){let l=t.closest(".data-cell");if(l){let a=parseInt(l.dataset.rowidx,10),s=parseInt(l.dataset.colidx,10),r=ee(l.closest(".data-row").dataset.rowid);H(a,s,r)}return}if(t.closest(".row-number")){let l=t.closest(".data-row");if(l){let a=ee(l.dataset.rowid),s=parseInt(l.dataset.rowidx,10);dt(e,a,s)}return}let o=t.closest(".data-cell");if(o){let l=parseInt(o.dataset.rowidx,10),a=parseInt(o.dataset.colidx,10),s=o.closest(".data-row"),r=ee(s.dataset.rowid);ut(e,l,a,r);return}}function sn(e){let t=e.target.closest(".data-cell");if(t&&!t.classList.contains("row-number")){let o=parseInt(t.dataset.rowidx,10),l=parseInt(t.dataset.colidx,10),a=t.closest(".data-row"),s=ee(a.dataset.rowid);mt(e,o,l,s)}}function rn(e){let t=e.target.closest(".data-cell");if(t&&!t.classList.contains("checked-overflow")){let o=t.querySelector(".cell-text");if(o){let l=o.scrollWidth>o.clientWidth;t.classList.toggle("has-overflow",l),t.classList.add("checked-overflow")}}}function cn(e){let t=e.currentTarget;n.scrollPosition.left=t.scrollLeft,n.scrollPosition.top=t.scrollTop,M()}function ee(e){if(e==null)return e;let t=Number(e);return!isNaN(t)&&e.trim()!==""?t:e}function gt(){document.addEventListener("click",e=>{let t=e.target,o=t.closest(".modal-close, .modal-cancel");if(o){let l=o.dataset.modal;l&&O(l)}t.classList.contains("modal-overlay")&&t.classList.add("hidden")}),document.addEventListener("keydown",e=>{if(e.key==="Escape"){let t=document.querySelector(".modal-overlay:not(.hidden)");t&&(t.classList.add("hidden"),e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation())}})}function V(e){let t=document.getElementById(e);if(t){t.classList.remove("hidden");let o=t.querySelector("input, select, textarea, button");o&&o.focus()}}function O(e){let t=document.getElementById(e);t&&t.classList.add("hidden")}function ht(){document.getElementById("btnAddRow")?.addEventListener("click",dn),document.getElementById("btnDeleteRows")?.addEventListener("click",mn),document.getElementById("btnAddColumn")?.addEventListener("click",yn),document.getElementById("btnSubmitAddRow")?.addEventListener("click",un),document.getElementById("btnSubmitDelete")?.addEventListener("click",de),document.getElementById("btnSubmitCreateTable")?.addEventListener("click",hn),document.getElementById("btnAddColumnDef")?.addEventListener("click",()=>xt()),document.getElementById("columnDefinitions")?.addEventListener("click",e=>{let t=e.target.closest(".btn-remove-col");if(t){let o=t.dataset.colid;gn(o)}}),document.getElementById("btnSubmitAddColumn")?.addEventListener("click",Cn)}function dn(){if(!n.selectedTable||n.selectedTableType!=="table")return;let e=document.getElementById("addRowForm");e.replaceChildren(),n.tableColumns.forEach(t=>{let o=t.notnull===1&&!t.isPrimaryKey,l=document.createElement("div");l.className="form-field";let a=document.createElement("label");if(a.textContent=t.name,o){let i=document.createElement("span");i.style.color="var(--error-color)",i.textContent="*",a.appendChild(document.createTextNode(" ")),a.appendChild(i)}let s=document.createElement("span");s.style.opacity="0.5",s.textContent=` (${t.type})`,a.appendChild(document.createTextNode(" ")),a.appendChild(s);let r=document.createElement("input");r.type="text",r.dataset.column=t.name,r.dataset.required=o.toString(),t.isPrimaryKey?(r.placeholder="Auto (Primary Key)",r.disabled=!0):o?r.placeholder="Required":r.placeholder="NULL",l.appendChild(a),l.appendChild(r),e.appendChild(l)}),V("addRowModal")}async function un(){let e=document.querySelectorAll("#addRowForm input[data-column]:not([disabled])"),t=[];for(let l of e){let a=l.dataset.column,s=l.value.trim();l.dataset.required==="true"&&(s===""||s.toLowerCase()==="null")?(t.push(a),l.style.borderColor="var(--error-color)"):l.style.borderColor=""}if(t.length>0){u(`Required fields missing: ${t.join(", ")}`);return}let o={};for(let l of e){let a=l.dataset.column,s=l.value.trim();s!==""&&(s.toLowerCase()==="null"?o[a]=null:!isNaN(Number(s))&&s!==""?o[a]=Number(s):o[a]=s)}try{u("Inserting row..."),await C.insertRow(n.selectedTable,o),O("addRowModal"),await v(),u("Row inserted - Ctrl+S to save")}catch(l){console.error("Insert failed:",l),u(`Error: ${l.message}`)}}function mn(){if(n.selectedColumns.size>0){let e=Array.from(n.selectedColumns);document.getElementById("deleteConfirmText").textContent=`Are you sure you want to delete ${e.length} column${e.length>1?"s":""} (${e.join(", ")})? This will permanently remove the column${e.length>1?"s":""} and all their data.`}else if(n.selectedRowIds.size>0)document.getElementById("deleteConfirmText").textContent=`Are you sure you want to delete ${n.selectedRowIds.size} row${n.selectedRowIds.size>1?"s":""}?`;else return;V("deleteModal")}async function de(){n.selectedColumns.size>0?await fn():n.selectedRowIds.size>0&&await pn()}async function pn(){if(n.selectedRowIds.size===0)return;let e=Array.from(n.selectedRowIds);try{u("Deleting rows..."),await C.deleteRows(n.selectedTable,e),O("deleteModal"),n.selectedRowIds.clear(),await v(),P(),u(`Deleted ${e.length} row${e.length>1?"s":""} - Ctrl+S to save`)}catch(t){console.error("Delete rows failed:",t),u(`Error: ${t.message}`)}}async function fn(){if(n.selectedColumns.size===0)return;let e=Array.from(n.selectedColumns);try{u("Deleting columns...");let t=await C.deleteColumns(n.selectedTable,e);if(t&&t.cancelled){u("Delete cancelled"),O("deleteModal");return}O("deleteModal"),n.selectedColumns.clear(),n.selectedCells=[],n.lastSelectedCell=null,await _(),await q(),await v(),P(),u(`Deleted ${e.length} column${e.length>1?"s":""} - Ctrl+S to save`)}catch(t){console.error("Delete columns failed:",t),u(`Error: ${t.message}`)}}var yt=0;function Ct(){document.getElementById("newTableName").value="",document.getElementById("columnDefinitions").replaceChildren(),yt=0,xt(!0),V("createTableModal")}function xt(e=!1){let t=document.getElementById("columnDefinitions"),o=++yt,l=document.createElement("div");l.className="column-def-row",l.id=`colDef_${o}`,Object.assign(l.style,{display:"flex",gap:"8px",marginBottom:"8px",alignItems:"center"});let a=document.createElement("input");a.type="text",a.placeholder="Column name",a.className="col-name",a.style.flex="2",e&&(a.value="id"),l.appendChild(a);let s=document.createElement("select");s.className="col-type",s.style.flex="1",["INTEGER","TEXT","REAL","BLOB","NUMERIC"].forEach(g=>{let p=document.createElement("option");p.value=g,p.textContent=g,e&&g==="INTEGER"&&(p.selected=!0),!e&&g==="TEXT"&&(p.selected=!0),s.appendChild(p)}),l.appendChild(s);let r=document.createElement("label");Object.assign(r.style,{display:"flex",alignItems:"center",gap:"4px",cursor:"pointer"});let i=document.createElement("input");i.type="checkbox",i.className="col-pk",i.style.margin="0",e&&(i.checked=!0),r.appendChild(i),r.appendChild(document.createTextNode(" PK")),l.appendChild(r);let c=document.createElement("label");Object.assign(c.style,{display:"flex",alignItems:"center",gap:"4px",cursor:"pointer"});let d=document.createElement("input");d.type="checkbox",d.className="col-nn",d.style.margin="0",c.appendChild(d),c.appendChild(document.createTextNode(" NN")),l.appendChild(c);let m=document.createElement("button");m.className="icon-button btn-remove-col",m.dataset.colid=o.toString(),m.title="Remove",e&&(m.disabled=!0);let f=document.createElement("span");f.className="codicon codicon-close",m.appendChild(f),l.appendChild(m),t.appendChild(l)}function gn(e){let t=document.getElementById(`colDef_${e}`);t&&t.remove()}async function hn(){let e=document.getElementById("newTableName").value.trim();if(!e){u("Error: Table name is required");return}if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(e)){u("Error: Invalid table name");return}let t=[],o=document.querySelectorAll(".column-def-row");for(let l of o){let a=l.querySelector(".col-name").value.trim(),s=l.querySelector(".col-type").value,r=l.querySelector(".col-pk").checked,i=l.querySelector(".col-nn").checked;a&&t.push({name:a,type:s,primaryKey:r,notNull:i})}if(t.length===0){u("Error: At least one column is required");return}try{u("Creating table..."),await C.createTable(e,t),O("createTableModal"),await _(),u(`Table "${e}" created - Ctrl+S to save`)}catch(l){console.error("Create table failed:",l),u(`Error: ${l.message}`)}}function yn(){!n.selectedTable||n.selectedTableType!=="table"||(document.getElementById("newColumnName").value="",document.getElementById("newColumnType").value="TEXT",document.getElementById("newColumnDefault").value="",V("addColumnModal"))}async function Cn(){let e=document.getElementById("newColumnName").value.trim(),t=document.getElementById("newColumnType").value,o=document.getElementById("newColumnDefault").value.trim();if(!e){u("Error: Column name is required");return}if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(e)){u("Error: Invalid column name");return}try{u("Adding column..."),await C.addColumn(n.selectedTable,e,t,o),O("addColumnModal"),await q(),await v(),u(`Column "${e}" added - Ctrl+S to save`)}catch(l){console.error("Add column failed:",l),u(`Error: ${l.message}`)}}function bt(){let e=document.getElementById("pragmaSettingsContainer");e&&e.addEventListener("change",t=>{let o=t.target;if(o.matches(".setting-extension")){let l=o.dataset.key,a=o.type==="checkbox"?o.checked:o.value;bn(l,a)}else if(o.matches(".setting-pragma")){let l=o.dataset.name,a=o.dataset.type,s=o.value;a==="number"?s=Number(s):a==="bool"&&(s=s==="true"?1:0),wn(l,s)}})}async function wt(){let e=document.getElementById("settingsModal");e&&(e.classList.remove("hidden"),await Le())}async function Le(){let e=document.getElementById("pragmaSettingsContainer");e.textContent="Loading settings...";try{let[t,o]=await Promise.all([C.getPragmas(),C.getExtensionSettings()]);xn(t,o)}catch(t){console.error("Failed to load settings:",t),e.textContent=`Error loading settings: ${t.message}`,e.style.color="var(--error-color)"}}function xn(e,t){let o=document.getElementById("pragmaSettingsContainer");if(!o)return;let l=(y,x)=>y.map(A=>{let L=String(A),D=String(x).toUpperCase()===L.toUpperCase(),N=document.createElement("option");return N.value=L,N.selected=D,N.textContent=L,N});o.replaceChildren();let a=y=>{let x=document.createElement("div");x.className="setting-section-title",Object.assign(x.style,{fontWeight:"600",marginBottom:"8px",paddingBottom:"4px",borderBottom:"1px solid var(--border-color)"}),x.textContent=y,o.appendChild(x)},s=(y,x,A)=>{let L=document.createElement("div");L.className="form-field";let b=document.createElement("label");if(x.type==="checkbox"?(Object.assign(b.style,{display:"flex",alignItems:"center",gap:"4px",cursor:"pointer"}),x.style.margin="0",b.appendChild(x),b.appendChild(document.createTextNode(y)),L.appendChild(b)):(b.textContent=y,L.appendChild(b),L.appendChild(x)),A){let D=document.createElement("div");D.className="setting-desc",D.textContent=A,L.appendChild(D)}o.appendChild(L)};if(o.children.length>0){let y=document.createElement("div");y.style.height="16px",o.appendChild(y)}a("Extension Settings");let r=document.createElement("input");r.type="checkbox",r.className="setting-extension",r.dataset.key="autoCommit",r.checked=!!t.autoCommit,s("Auto-Commit Changes",r,"Automatically save changes to disk immediately. If disabled, you must save manually (Ctrl+S).");let i=document.createElement("select");i.className="setting-extension",i.dataset.key="doubleClickBehavior",l(["inline","modal","vscode"],t.cellEditBehavior).forEach(y=>i.appendChild(y)),s("Double Click Behavior",i,"Action when double-clicking a cell");let c=document.createElement("div");c.style.height="16px",o.appendChild(c),a("SQLite Settings (Pragmas)");let d=document.createElement("select");d.className="setting-pragma",d.dataset.name="journal_mode",l(["DELETE","TRUNCATE","PERSIST","MEMORY","WAL","OFF"],e.journal_mode).forEach(y=>d.appendChild(y)),s("Journal Mode",d,"Database journaling mode (WAL is recommended for concurrency)");let m=document.createElement("select");m.className="setting-pragma",m.dataset.name="foreign_keys",m.dataset.type="bool";let f=document.createElement("option");f.value="true",f.textContent="ON";let g=document.createElement("option");g.value="false",g.textContent="OFF",Number(e.foreign_keys)===1?f.selected=!0:g.selected=!0,m.appendChild(f),m.appendChild(g),s("Foreign Keys",m,"Enforce foreign key constraints");let p=document.createElement("select");p.className="setting-pragma",p.dataset.name="synchronous",p.dataset.type="number",[{v:0,t:"OFF (0)"},{v:1,t:"NORMAL (1)"},{v:2,t:"FULL (2)"},{v:3,t:"EXTRA (3)"}].forEach(y=>{let x=document.createElement("option");x.value=y.v,x.textContent=y.t,Number(e.synchronous)===y.v&&(x.selected=!0),p.appendChild(x)}),s("Synchronous",p,"Disk synchronization safety level");let h=document.createElement("select");h.className="setting-pragma",h.dataset.name="locking_mode",l(["NORMAL","EXCLUSIVE"],e.locking_mode).forEach(y=>h.appendChild(y)),s("Locking Mode",h,"");let w=document.createElement("select");w.className="setting-pragma",w.dataset.name="auto_vacuum",w.dataset.type="number",[{v:0,t:"NONE (0)"},{v:1,t:"FULL (1)"},{v:2,t:"INCREMENTAL (2)"}].forEach(y=>{let x=document.createElement("option");x.value=y.v,x.textContent=y.t,Number(e.auto_vacuum)===y.v&&(x.selected=!0),w.appendChild(x)}),s("Auto Vacuum",w,"");let S=document.createElement("input");S.type="number",S.className="setting-pragma",S.dataset.name="cache_size",S.dataset.type="number",S.value=e.cache_size,s("Cache Size",S,"Number of pages (positive) or kilobytes (negative)")}async function bn(e,t){try{await C.updateExtensionSetting(e,t),u(`Updated ${e}`)}catch(o){console.error(`Failed to set ${e}:`,o),u(`Error: ${o.message}`),await Le()}}async function wn(e,t){try{u(`Updating ${e}...`),await C.setPragma(e,t),u(`Updated ${e}`)}catch(o){console.error(`Failed to set ${e}:`,o),u(`Error: ${o.message}`),await Le()}}function Et(e,t){let o=new Map;for(let l of e){let a=t&&t[l.colIdx];a&&(o.has(l.colIdx)||o.set(l.colIdx,{name:a.name,type:a.type,values:new Set}),o.get(l.colIdx).values.add(l.value))}return o}function It(e){let t=Array.from(e||[]);if(t.length===0)return"";if(t.length>1)return"(mixed values)";let o=t[0];return o===null?"NULL":o instanceof Uint8Array?"[BLOB]":String(o)}function St(e,t,o){let l=[];for(let a of e){let s=t.get(a.colIdx);if(!s)continue;let r=s.dataset||{},i=r.isnull==="true",c=r.ispatch==="true",d=s.value;if(d===""&&!i)continue;let m=o&&o[a.colIdx];if(!m)continue;let f=d,g="set";if(i)f=null;else if(c)g="json_patch";else{let p=(m.type||"").toUpperCase();(p==="INTEGER"||p==="REAL"||p==="NUMERIC")&&!isNaN(Number(d))&&d.trim()!==""&&(f=Number(d))}l.push({rowId:a.rowId,column:m.name,value:f,originalValue:a.value,operation:g,rowIdx:a.rowIdx,colIdx:a.colIdx})}return l}function Tt(){let e=document.getElementById("sidebarPanel");if(!e)return;let t=document.getElementById("sidebarFilterInput");t&&t.addEventListener("input",()=>{n.sidebarFilter=t.value,De()}),e.addEventListener("click",o=>{let l=o.target;if(l.closest("#btnOpenSettings")){wt();return}if(l.closest("#btnOpenCreateTable")){o.stopPropagation(),Ct();return}if(l.closest("#btnReload")){Rn();return}if(l.closest("#btnApplyBatchUpdate")){In();return}let a=l.closest(".list-item");if(a){let c=a.dataset.name,d=a.dataset.type;if(c&&d){Bn(c,d);return}}let s=l.closest(".section-title");if(s){if(l.closest(".icon-button")||s.id==="btnOpenSettings")return;let c=s.dataset.section;c&&Tn(c)}let r=l.closest(".btn-batch-null");if(r){let c=r.closest(".batch-field");if(c){let d=parseInt(c.dataset.colidx,10);Sn(d)}return}let i=l.closest(".btn-batch-patch");if(i){let c=i.closest(".batch-field");if(c){let d=parseInt(c.dataset.colidx,10);vn(d,i)}return}})}async function _(){if(n.isDbConnected)try{let e=await C.fetchSchema();n.schemaCache.tables=(e.tables||[]).map(t=>({name:t.identifier})),n.schemaCache.views=(e.views||[]).map(t=>({name:t.identifier})),n.schemaCache.indexes=(e.indexes||[]).map(t=>({name:t.identifier,table:t.parentTable})),De()}catch(e){console.error("Error loading schema:",e),u("Error loading schema")}}function Pe(e,t){return t?e.filter(o=>o.name.toLowerCase().includes(t)):e}function ke(e,t,o,l){let a=document.getElementById(e);a&&(a.textContent=l?`${t}/${o}`:o)}function vt(e,t,o,l,a){let s=document.getElementById(e);if(!s)return;if(s.replaceChildren(),t.length===0){let i=document.createElement("li");i.className="list-item",i.style.opacity="0.5",i.textContent=a,s.appendChild(i);return}let r=document.createDocumentFragment();t.forEach(i=>{let c=document.createElement("li");c.className="list-item",n.selectedTable===i.name&&n.selectedTableType===o&&c.classList.add("selected"),c.dataset.name=i.name,o&&(c.dataset.type=o),c.title=i.name;let d=document.createElement("span");d.className=`item-icon codicon ${l}`,c.appendChild(d);let m=document.createElement("span");m.className="item-name",m.textContent=i.name,c.appendChild(m),r.appendChild(c)}),s.appendChild(r)}function En(e,t,o){let l=document.getElementById(e);if(!l)return;if(l.replaceChildren(),t.length===0){let s=document.createElement("li");s.className="list-item",s.style.opacity="0.5",s.textContent=o,l.appendChild(s);return}let a=document.createDocumentFragment();t.forEach(s=>{let r=document.createElement("li");r.className="list-item",r.title=`${s.name} on ${s.table}`;let i=document.createElement("span");i.className="item-icon codicon codicon-list-selection",r.appendChild(i);let c=document.createElement("div");c.className="item-content";let d=document.createElement("span");d.className="item-name",d.textContent=s.name,c.appendChild(d);let m=document.createElement("span");m.className="item-detail",m.textContent=s.table,c.appendChild(m),r.appendChild(c),a.appendChild(r)}),l.appendChild(a)}function De(){let e=n.sidebarFilter.toLowerCase(),t=e.length>0,o=Pe(n.schemaCache.tables,e),l=Pe(n.schemaCache.views,e),a=Pe(n.schemaCache.indexes,e);ke("tablesBadge",o.length,n.schemaCache.tables.length,t),ke("viewsBadge",l.length,n.schemaCache.views.length,t),ke("indexesBadge",a.length,n.schemaCache.indexes.length,t),vt("tablesList",o,"table","codicon-table",e?"No matching tables":"No tables"),vt("viewsList",l,"view","codicon-eye",e?"No matching views":"No views"),En("indexesList",a,e?"No matching indexes":"No indexes")}function z(){let e=document.getElementById("batchUpdateSectionTitle"),t=document.getElementById("batchUpdateList"),o=document.getElementById("batchUpdateCount"),l=document.getElementById("batchUpdateFields");if(!e||!t||!o||!l)return;let a=n.selectedCells.length;if(a===0){e.classList.add("hidden"),t.classList.add("hidden");return}e.classList.remove("hidden"),t.classList.remove("hidden"),e.classList.remove("collapsed"),o.textContent=a;let s=Et(n.selectedCells,n.tableColumns);l.replaceChildren();let r=document.createDocumentFragment();for(let[i,c]of s){let d=It(c.values),m=document.createElement("div");m.className="form-field batch-field",m.dataset.colidx=i,m.style.marginBottom="8px";let f=document.createElement("label");f.style.fontSize="11px",f.style.color="var(--text-secondary)";let g=document.createTextNode(c.name+" ");f.appendChild(g);let p=document.createElement("span");p.style.opacity="0.7",p.textContent=c.type||"",f.appendChild(p),m.appendChild(f);let h=document.createElement("div");h.style.display="flex",h.style.gap="4px";let w=document.createElement("input");w.type="text",w.className="batch-input",w.placeholder=d,w.dataset.colidx=i,w.style.flex="1",w.style.minWidth="0",h.appendChild(w);let S=document.createElement("button");S.className="btn-secondary btn-batch-null",S.style.padding="2px 6px",S.title="Set to NULL",S.textContent="NULL",h.appendChild(S);let y=document.createElement("button");y.className="btn-secondary btn-batch-patch",y.style.padding="2px 6px",y.title="JSON Patch",y.textContent="{}",h.appendChild(y),m.appendChild(h),r.appendChild(m)}l.appendChild(r)}async function In(){if(n.selectedCells.length===0)return;let e=document.querySelectorAll(".batch-input"),t=new Map;for(let l of e){let a=parseInt(l.dataset.colidx,10);if(t.set(a,l),l.dataset.ispatch==="true")try{JSON.parse(l.value)}catch{let r=n.tableColumns[a];u(`Invalid JSON for patch in ${r?.name??`column ${a}`}`);return}}let o=St(n.selectedCells,t,n.tableColumns);if(o.length===0){u("No values entered for batch update");return}try{u(`Updating ${o.length} cells...`);let l=`Batch update ${o.length} cells`,a=o.map(i=>({rowId:i.rowId,column:i.column,value:i.value,originalValue:i.originalValue,operation:i.operation}));if(await C.updateCellBatch(n.selectedTable,a,l),!o.some(i=>i.operation==="json_patch"))for(let i of o)n.gridData[i.rowIdx][i.colIdx+R()]=i.value;await v(!1);let r=[];for(let i of n.selectedCells){let c=n.gridData[i.rowIdx][i.colIdx+R()];r.push({...i,value:c})}n.selectedCells=r,z(),u("Batch update completed")}catch(l){console.error("Batch update failed:",l),u(`Batch update failed: ${l.message}`)}}function Sn(e){let t=document.querySelector(`.batch-input[data-colidx="${e}"]`),o=document.querySelector(`.batch-field[data-colidx="${e}"] .btn-batch-patch`);t&&(t.value="",t.placeholder="SET TO NULL",t.dataset.isnull="true",t.dataset.ispatch="false",t.style.fontStyle="italic",o&&(o.style.background="",o.style.color=""))}function vn(e,t){let o=document.querySelector(`.batch-input[data-colidx="${e}"]`);o&&(o.dataset.ispatch==="true"?(o.dataset.ispatch="false",o.placeholder="(mixed values)",t.style.background="",t.style.color=""):(o.dataset.ispatch="true",o.dataset.isnull="false",o.placeholder='JSON Patch (e.g. {"a": 1})',o.style.fontStyle="normal",t.style.background="var(--accent-color)",t.style.color="white"))}function Tn(e){let t=document.getElementById(`${e}List`),o=document.querySelector(`.section-title[data-section="${e}"]`);t&&o&&(t.classList.toggle("hidden"),o.classList.toggle("collapsed"))}async function Bn(e,t){n.selectedTable=e,n.selectedTableType=t,n.currentPageIndex=0,n.sortedColumn=null,n.sortAscending=!0,n.filterQuery="",n.columnFilters={},n.selectedRowIds.clear(),n.selectedCells=[],n.lastSelectedCell=null,n.selectedColumns.clear(),n.pinnedColumns.clear(),n.pinnedRowIds.clear(),n.columnWidths={},n.scrollPosition={top:0,left:0},De();let o=document.getElementById("tableNameLabel");o&&(o.textContent=e);let l=document.getElementById("filterInput");l&&(l.value=""),await q(),await v(!0,!1),M()}async function Rn(){if(n.isDbConnected)try{u("Reloading..."),await C.refreshFile(),await _(),n.selectedTable&&(await q(),await v()),u("Reloaded")}catch(e){console.error("Reload failed:",e),u(`Reload failed: ${e.message}`)}}function Bt(){document.getElementById("btnExport")?.addEventListener("click",Ln),document.getElementById("btnSubmitExport")?.addEventListener("click",Pn),document.getElementById("exportFormat")?.addEventListener("change",Rt)}function Ln(){if(!n.selectedTable)return;let e=document.getElementById("exportFormat");e&&(e.value="csv");let t=document.getElementById("exportColumns");t&&(t.replaceChildren(),n.tableColumns.forEach(o=>{let l=document.createElement("div"),a=document.createElement("label");Object.assign(a.style,{display:"flex",alignItems:"center",gap:"3px",marginBottom:"4px",fontSize:"13px",cursor:"pointer"});let s=document.createElement("input");s.type="checkbox",s.className="export-col-check",s.value=o.name,s.checked=!0,s.style.margin="0",a.appendChild(s),a.appendChild(document.createTextNode(o.name)),t.appendChild(a)})),Rt(),V("exportModal")}function Rt(){let e=document.getElementById("exportFormat").value,t=document.getElementById("exportOptions");if(t.replaceChildren(),e==="csv"||e==="excel"){let o=document.createElement("label");Object.assign(o.style,{display:"flex",alignItems:"center",gap:"3px",marginBottom:"4px",fontSize:"13px",cursor:"pointer"});let l=document.createElement("input");l.type="checkbox",l.id="exportHeader",l.checked=!0,l.style.margin="0",o.appendChild(l),o.appendChild(document.createTextNode(" Include Headers")),t.appendChild(o)}else if(e==="sql"){let o=document.createElement("label");Object.assign(o.style,{display:"flex",alignItems:"center",gap:"3px",marginBottom:"4px",fontSize:"13px",cursor:"pointer"});let l=document.createElement("input");l.type="checkbox",l.id="exportTableName",l.checked=!0,l.style.margin="0",o.appendChild(l),o.appendChild(document.createTextNode(" Include Table Name")),t.appendChild(o)}}async function Pn(){let e=document.getElementById("exportFormat").value,t=document.querySelectorAll(".export-col-check:checked"),o=Array.from(t).map(a=>a.value);if(o.length===0){u("Error: Select at least one column");return}let l={};if(e==="csv"||e==="excel"?l.header=document.getElementById("exportHeader")?.checked??!0:e==="sql"&&(l.includeTableName=document.getElementById("exportTableName")?.checked??!0),n.selectedTableType==="table"){let a=Array.from(n.selectedRowIds);a.length>0&&(l.rowIds=a)}try{u("Exporting..."),O("exportModal"),await C.exportTable({table:n.selectedTable},o,null,null,{format:e,...l}),u("Export initiated")}catch(a){console.error("Export failed:",a),u(`Export failed: ${a.message}`)}}async function Lt(){if(n.selectedCells.length!==0)try{let e;if(n.selectedCells.length===1){let t=n.selectedCells[0].value;t==null?e="":t instanceof Uint8Array?e="[BLOB]":e=String(t)}else{let t=[...new Set(n.selectedCells.map(s=>s.rowIdx))].sort((s,r)=>s-r),o=[...new Set(n.selectedCells.map(s=>s.colIdx))].sort((s,r)=>s-r),l=new Map;for(let s of n.selectedCells)l.set(`${s.rowIdx},${s.colIdx}`,s.value);let a=[];for(let s of t){let r=[];for(let i of o){let c=`${s},${i}`,d=l.has(c)?l.get(c):"";d==null?d="":d instanceof Uint8Array?d="[BLOB]":(d=String(d),d=d.replace(/\t/g," ").replace(/\n/g," ")),r.push(d)}a.push(r.join(" "))}e=a.join(` +... (${(t.length-o).toLocaleString()} more bytes not shown)`),this.hexContainer.value=l}formatSize(t){if(t===0)return"0 B";let o=1024,l=["B","KB","MB","GB"],a=Math.floor(Math.log(t)/Math.log(o));return parseFloat((t/Math.pow(o,a)).toFixed(2))+" "+l[a]}};var ve;function qe(){ve=new se,document.getElementById("btnCloseCellPreview")?.addEventListener("click",G),document.getElementById("formatJsonBtn")?.addEventListener("click",Zt),document.getElementById("compactJsonBtn")?.addEventListener("click",Qt),document.getElementById("wrapTextBtn")?.addEventListener("click",en),document.getElementById("openInVsCodeBtn")?.addEventListener("click",Te),document.getElementById("btnCancelCellPreview")?.addEventListener("click",G),document.getElementById("cellPreviewSaveBtn")?.addEventListener("click",Ze)}function He(e,t,o){if(n.selectedTableType!=="table"){u("Views are read-only");return}if(n.editingCellInfo){if(n.editingCellInfo.rowIdx===e&&n.editingCellInfo.colIdx===t)return;ie()}let l=n.tableColumns[t];if(!l)return;let a=document.getElementById(`cell-${e}-${t}`);if(!a)return;let s=n.gridData[e],r=k(s,t);if(r instanceof Uint8Array){H(e,t,o);return}if(typeof r=="string"){let d=r.trim();if(d.startsWith("{")&&d.endsWith("}")||d.startsWith("[")&&d.endsWith("]"))try{JSON.parse(d),H(e,t,o);return}catch{}}n.editingCellInfo={rowIdx:e,colIdx:t,rowId:o,columnName:l.name,originalValue:r};let i=r===null?"":String(r);a.innerHTML="",a.classList.add("editing");let c=document.createElement("textarea");c.className="cell-input",c.value=i,c.spellcheck=!1,a.appendChild(c),c.focus(),n.activeCellInput=c,c.addEventListener("keydown",Ge),c.addEventListener("blur",Je),c.addEventListener("click",d=>d.stopPropagation()),n.isTransitioningEdit=!0,setTimeout(()=>{n.isTransitioningEdit=!1},100)}function Ge(e){e.key==="Enter"&&!e.shiftKey?(e.preventDefault(),Xe()):e.key==="Escape"&&(e.preventDefault(),ie())}function Je(){setTimeout(()=>{n.editingCellInfo&&Xe()},100)}async function Xe(){if(n.isSavingCell||!n.editingCellInfo||!n.activeCellInput)return;let{rowIdx:e,colIdx:t,rowId:o,columnName:l,originalValue:a}=n.editingCellInfo,s=n.activeCellInput.value,r=a===null?"":String(a);if(s===r){ie(),n.selectedCells=[],n.lastSelectedCell=null,U();return}let i=n.tableColumns[t],c=i&&i.notnull===1,d;s===""?c?d="":d=null:!isNaN(Number(s))&&s.trim()!==""?d=Number(s):d=s;try{n.isSavingCell=!0,u("Saving..."),await C.updateCell(n.selectedTable,oe(o),l,d,a),n.gridData[e][t+R()]=d,Ye(),Be(e,t,d),n.selectedCells=[],n.lastSelectedCell=null,U(),u("Saved")}catch(m){console.error("Save failed:",m);let g=m.message||String(m);u(`Save failed: ${g}`)}finally{n.isSavingCell=!1}}function ie(){if(!n.editingCellInfo)return;let{rowIdx:e,colIdx:t,originalValue:o}=n.editingCellInfo;Ye(),Be(e,t,o),ae()}function Ye(){n.activeCellInput&&(n.activeCellInput.removeEventListener("keydown",Ge),n.activeCellInput.removeEventListener("blur",Je),n.activeCellInput=null),n.editingCellInfo=null}async function Te(){if(!n.cellPreviewInfo)return;let{rowIdx:e,colIdx:t,rowId:o,columnName:l,originalValue:a}=n.cellPreviewInfo,s=n.tableColumns[t],r=document.getElementById("vscode-env")?.dataset.webviewId||"default";try{u("Opening in VS Code..."),G(),await C.openCellEditor({table:n.selectedTable,name:""},oe(o),l,{},{value:a,type:{type:s.type},webviewId:r,rowCount:n.gridData.length}),u("Opened in VS Code")}catch(i){console.error("Failed to open in VS Code:",i),u(`Error: ${i.message}`)}}function H(e,t,o){n.editingCellInfo&&ie();let l=n.tableColumns[t];if(!l)return;let a=n.gridData[e];if(!a)return;let s=k(a,t);if(s instanceof Uint8Array){ve&&ve.inspect(s,o,l.name,e,t);return}n.cellPreviewInfo={rowIdx:e,colIdx:t,rowId:o,columnName:l.name,originalValue:s};let r=document.getElementById("cellPreviewModal"),i=document.getElementById("cellPreviewColumnName"),c=document.getElementById("cellPreviewTypeBadge"),d=document.getElementById("cellPreviewTextarea"),m=document.getElementById("cellPreviewReadonlyBadge"),g=document.getElementById("cellPreviewSaveBtn"),f=document.getElementById("wrapTextBtn");i.textContent=l.name,c.textContent=l.type||"TEXT";let p="";s==null?p="":s instanceof Uint8Array?p="[BLOB: "+Array.from(s).map(w=>w.toString(16).padStart(2,"0")).join(" ")+"]":p=String(s),d.value=p;let h=n.selectedTableType!=="table";d.readOnly=h,h?(d.classList.add("readonly"),m.style.display="inline",g.style.display="none"):(d.classList.remove("readonly"),m.style.display="none",g.style.display="inline-block"),re(),d.style.whiteSpace=n.cellPreviewWrapEnabled?"pre-wrap":"pre",d.style.overflowX=n.cellPreviewWrapEnabled?"hidden":"auto",f.classList.toggle("active",n.cellPreviewWrapEnabled),r.classList.remove("hidden"),d.focus(),d.oninput=re,d.onkeydown=w=>{w.key==="Escape"?(w.preventDefault(),G()):w.key==="Enter"&&(w.ctrlKey||w.metaKey)&&(w.preventDefault(),Ze())}}function re(){let e=document.getElementById("cellPreviewTextarea"),t=document.getElementById("cellPreviewCharCount"),o=e.value.length;t.textContent=`${o.toLocaleString()} character${o!==1?"s":""}`}function G(){document.getElementById("cellPreviewModal").classList.add("hidden"),n.cellPreviewInfo=null}async function Ze(){if(!n.cellPreviewInfo)return;if(n.selectedTableType!=="table"){u("Views are read-only");return}let{rowIdx:e,colIdx:t,rowId:o,columnName:l,originalValue:a}=n.cellPreviewInfo,r=document.getElementById("cellPreviewTextarea").value,i=a===null?"":String(a);if(r===i){G(),n.selectedCells=[],n.lastSelectedCell=null,U();return}let c=n.tableColumns[t],d=c&&c.notnull===1,m;r===""?m=d?"":null:!isNaN(Number(r))&&r.trim()!==""?m=Number(r):m=r;try{u("Saving..."),await C.updateCell(n.selectedTable,oe(o),l,m,a),n.gridData[e][t+R()]=m,G(),Be(e,t,m),n.selectedCells=[],n.lastSelectedCell=null,U(),u("Saved")}catch(g){console.error("Save failed:",g),u(`Save failed: ${g.message}`)}}function Zt(){let e=document.getElementById("cellPreviewTextarea");try{let t=JSON.parse(e.value);e.value=JSON.stringify(t,null,2),re()}catch{u("Content is not valid JSON")}}function Qt(){let e=document.getElementById("cellPreviewTextarea");try{let t=JSON.parse(e.value);e.value=JSON.stringify(t),re()}catch{u("Content is not valid JSON")}}function en(){n.cellPreviewWrapEnabled=!n.cellPreviewWrapEnabled;let e=document.getElementById("cellPreviewTextarea"),t=document.getElementById("wrapTextBtn");e.style.whiteSpace=n.cellPreviewWrapEnabled?"pre-wrap":"pre",e.style.overflowX=n.cellPreviewWrapEnabled?"hidden":"auto",t.classList.toggle("active",n.cellPreviewWrapEnabled)}function Be(e,t,o){let l=document.getElementById(`cell-${e}-${t}`);if(!l)return;l.classList.remove("editing"),o==null?l.classList.add("null-value"):l.classList.remove("null-value");let a=n.tableColumns[t],s=K(o,a?.type,n.dateFormat,a?.name),r=o!=null&&!(o instanceof Uint8Array);l.textContent="";let i=document.createElement("span");if(i.className="cell-text",i.textContent=s,l.appendChild(i),r){let d=document.createElement("span");d.className="expand-icon codicon codicon-link-external",d.title="View full content",l.appendChild(d)}let c=i.scrollWidth>i.clientWidth;l.classList.toggle("has-overflow",c)}function Qe(){clearTimeout(n.filterTimer),n.filterTimer=setTimeout(()=>{n.filterQuery=document.getElementById("filterInput").value,n.currentPageIndex=0,v(),M()},300)}function et(){n.rowsPerPage=parseInt(document.getElementById("pageSizeSelect").value,10),n.currentPageIndex=0,v(),M()}function tt(){let e=document.getElementById("dateFormatSelect");e&&(n.dateFormat=e.value,j(),M())}function Q(e){e>=0&&el.name===t);if(o!==-1){if((e.shiftKey||e.metaKey||e.ctrlKey)&&e.preventDefault(),n.selectedRowIds.clear(),e.shiftKey&&n.lastSelectedColumnIndex!==null){e.metaKey||e.ctrlKey||(n.selectedCells=[],n.selectedColumns.clear());let l=Math.min(n.lastSelectedColumnIndex,o),a=Math.max(n.lastSelectedColumnIndex,o),s=new Array;if(n.selectedCells.length>0)for(let r of n.selectedCells)r.colIdx>=l&&r.colIdx<=a&&(s[r.rowIdx]||(s[r.rowIdx]=new Set),s[r.rowIdx].add(r.colIdx));for(let r=l;r<=a;r++){let i=n.tableColumns[r].name;n.selectedColumns.add(i);for(let c=0;c0&&a===l)n.selectedCells=n.selectedCells.filter(r=>r.colIdx!==o),n.selectedColumns.delete(t);else{let r=new Set;for(let i of n.selectedCells)i.colIdx===o&&r.add(i.rowIdx);for(let i=0;i0&&a===l&&n.selectedColumns.size===1&&n.selectedColumns.has(t))n.selectedCells=[],n.selectedColumns.clear(),n.lastSelectedColumnIndex=null;else{n.selectedCells=[],n.selectedColumns.clear();for(let r=0;rr.name===n.resizingColumn);if(l===-1)return;let a=document.querySelector(`th[data-column="${n.resizingColumn}"]`);a&&(a.style.width=`${o}px`,a.style.minWidth=`${o}px`,a.style.maxWidth=`${o}px`);let s=document.querySelectorAll(`.data-row td:nth-child(${l+2})`);for(let r of s)r.style.width=`${o}px`,r.style.minWidth=`${o}px`,r.style.maxWidth=`${o}px`;n.pinnedColumns.has(n.resizingColumn)}function ct(){if(!n.resizingColumn)return;let e=document.querySelector(".resize-handle.resizing");e&&e.classList.remove("resizing"),n.resizingColumn=null,document.removeEventListener("mousemove",it),document.removeEventListener("mouseup",ct),document.body.style.userSelect="",document.body.style.cursor="",j()}function dt(e,t,o){if(e.stopPropagation(),(e.shiftKey||e.metaKey||e.ctrlKey)&&e.preventDefault(),n.selectedCells=[],n.lastSelectedCell=null,n.selectedColumns.clear(),e.shiftKey&&n.lastSelectedRowIndex!==null){e.metaKey||e.ctrlKey||n.selectedRowIds.clear();let l=Math.min(n.lastSelectedRowIndex,o),a=Math.max(n.lastSelectedRowIndex,o);for(let s=l;s<=a;s++){let r=B(n.gridData[s],s);n.selectedRowIds.add(r)}}else e.ctrlKey||e.metaKey?(n.selectedRowIds.has(t)?n.selectedRowIds.delete(t):n.selectedRowIds.add(t),n.lastSelectedRowIndex=o):n.selectedRowIds.has(t)&&n.selectedRowIds.size===1?(n.selectedRowIds.delete(t),n.lastSelectedRowIndex=null):(n.selectedRowIds.clear(),n.selectedRowIds.add(t),n.lastSelectedRowIndex=o);U(),P(),z()}function ce(e){if(e.stopPropagation(),n.gridData.length===0)return;n.selectedCells=[],n.lastSelectedCell=null,n.selectedColumns.clear();let t=!0;for(let o=0;o=s&&m.rowIdx<=r&&m.colIdx>=i&&m.colIdx<=c&&(d[m.rowIdx]||(d[m.rowIdx]=new Set),d[m.rowIdx].add(m.colIdx));for(let m=s;m<=r;m++){let g=d[m];for(let f=i;f<=c;f++)if(!g||!g.has(f)){let p=B(n.gridData[m],m),h=k(n.gridData[m],f);n.selectedCells.push({rowIdx:m,colIdx:f,rowId:p,value:h})}}}else if(e.metaKey||e.ctrlKey){e.preventDefault(),n.selectedRowIds.clear();let s=n.selectedCells.findIndex(r=>r.rowIdx===t&&r.colIdx===o);s>=0?n.selectedCells.splice(s,1):(n.selectedCells.push({rowIdx:t,colIdx:o,rowId:l,value:a}),n.lastSelectedCell={rowIdx:t,colIdx:o})}else if(e.shiftKey&&n.lastSelectedCell){e.preventDefault(),n.selectedRowIds.clear(),n.selectedCells=[];let s=Math.min(n.lastSelectedCell.rowIdx,t),r=Math.max(n.lastSelectedCell.rowIdx,t),i=Math.min(n.lastSelectedCell.colIdx,o),c=Math.max(n.lastSelectedCell.colIdx,o);for(let d=s;d<=r;d++)for(let m=i;m<=c;m++){let g=B(n.gridData[d],d),f=k(n.gridData[d],m);n.selectedCells.push({rowIdx:d,colIdx:m,rowId:g,value:f})}}else n.selectedRowIds.clear(),n.selectedCells=[{rowIdx:t,colIdx:o,rowId:l,value:a}],n.lastSelectedCell={rowIdx:t,colIdx:o},n.selectedColumns.clear();U(),P(),z()}function mt(e,t,o,l){if(n.cellEditBehavior==="vscode"){let a=n.tableColumns[o];if(!a)return;let s=n.gridData[t];if(!s)return;let r=k(s,o);n.cellPreviewInfo={rowIdx:t,colIdx:o,rowId:l,columnName:a.name,originalValue:r},Te()}else n.cellEditBehavior==="modal"?H(t,o,l):He(t,o,l)}function pt(){document.getElementById("filterInput")?.addEventListener("keyup",Qe),document.getElementById("pageSizeSelect")?.addEventListener("change",et),document.getElementById("dateFormatSelect")?.addEventListener("change",tt),document.getElementById("btnFirst")?.addEventListener("click",()=>Q(0)),document.getElementById("btnPrev")?.addEventListener("click",()=>Q(n.currentPageIndex-1)),document.getElementById("btnNext")?.addEventListener("click",()=>Q(n.currentPageIndex+1)),document.getElementById("btnLast")?.addEventListener("click",()=>Q(n.totalPageCount-1))}function ft(){let e=document.getElementById("gridContainer");e&&(e.addEventListener("mousedown",tn),e.addEventListener("keydown",nn),e.addEventListener("click",on),e.addEventListener("dblclick",sn),e.addEventListener("mouseover",rn),e.addEventListener("scroll",cn,{passive:!0}))}function tn(e){if(e.target.classList.contains("resize-handle")){e.stopPropagation();let t=e.target.closest(".header-cell");t&&t.dataset.column&&rt(e,t.dataset.column)}}function nn(e){if(e.target.classList.contains("column-filter")){let t=e.target.dataset.column;t&&ot(e,t)}}function on(e){let t=e.target;if(t.closest(".grid-header")){ln(e,t);return}an(e,t)}function ln(e,t){if(t.closest(".filter-apply-btn")){e.stopPropagation();let l=t.closest(".header-cell");l&&l.dataset.column&&Re(l.dataset.column);return}if(t.closest(".header-bottom")||t.closest(".column-filter")){e.stopPropagation();return}if(t.closest(".select-column-icon")){e.stopPropagation();let l=t.closest(".header-cell");l&&l.dataset.column&<(e,l.dataset.column);return}if(t.closest(".pin-icon")){e.stopPropagation();let l=t.closest(".header-cell");l&&l.dataset.column&&at(e,l.dataset.column);return}if(t.closest(".row-number-header")){ce(e);return}let o=t.closest(".header-top");if(o){let l=o.closest(".header-cell");l&&l.dataset.column&&nt(l.dataset.column);return}}function an(e,t){if(t.closest(".pin-icon")){let l=t.closest(".data-row");if(l){let a=l.dataset.rowid,s=ee(a);st(e,s)}return}if(t.closest(".expand-icon")){let l=t.closest(".data-cell");if(l){let a=parseInt(l.dataset.rowidx,10),s=parseInt(l.dataset.colidx,10),r=ee(l.closest(".data-row").dataset.rowid);H(a,s,r)}return}if(t.closest(".row-number")){let l=t.closest(".data-row");if(l){let a=ee(l.dataset.rowid),s=parseInt(l.dataset.rowidx,10);dt(e,a,s)}return}let o=t.closest(".data-cell");if(o){let l=parseInt(o.dataset.rowidx,10),a=parseInt(o.dataset.colidx,10),s=o.closest(".data-row"),r=ee(s.dataset.rowid);ut(e,l,a,r);return}}function sn(e){let t=e.target.closest(".data-cell");if(t&&!t.classList.contains("row-number")){let o=parseInt(t.dataset.rowidx,10),l=parseInt(t.dataset.colidx,10),a=t.closest(".data-row"),s=ee(a.dataset.rowid);mt(e,o,l,s)}}function rn(e){let t=e.target.closest(".data-cell");if(t&&!t.classList.contains("checked-overflow")){let o=t.querySelector(".cell-text");if(o){let l=o.scrollWidth>o.clientWidth;t.classList.toggle("has-overflow",l),t.classList.add("checked-overflow")}}}function cn(e){let t=e.currentTarget;n.scrollPosition.left=t.scrollLeft,n.scrollPosition.top=t.scrollTop,M()}function ee(e){if(e==null)return e;let t=Number(e);return!isNaN(t)&&e.trim()!==""?t:e}function gt(){document.addEventListener("click",e=>{let t=e.target,o=t.closest(".modal-close, .modal-cancel");if(o){let l=o.dataset.modal;l&&O(l)}t.classList.contains("modal-overlay")&&t.classList.add("hidden")}),document.addEventListener("keydown",e=>{if(e.key==="Escape"){let t=document.querySelector(".modal-overlay:not(.hidden)");t&&(t.classList.add("hidden"),e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation())}})}function V(e){let t=document.getElementById(e);if(t){t.classList.remove("hidden");let o=t.querySelector("input, select, textarea, button");o&&o.focus()}}function O(e){let t=document.getElementById(e);t&&t.classList.add("hidden")}function ht(){document.getElementById("btnAddRow")?.addEventListener("click",dn),document.getElementById("btnDeleteRows")?.addEventListener("click",mn),document.getElementById("btnAddColumn")?.addEventListener("click",yn),document.getElementById("btnSubmitAddRow")?.addEventListener("click",un),document.getElementById("btnSubmitDelete")?.addEventListener("click",de),document.getElementById("btnSubmitCreateTable")?.addEventListener("click",hn),document.getElementById("btnAddColumnDef")?.addEventListener("click",()=>xt()),document.getElementById("columnDefinitions")?.addEventListener("click",e=>{let t=e.target.closest(".btn-remove-col");if(t){let o=t.dataset.colid;gn(o)}}),document.getElementById("btnSubmitAddColumn")?.addEventListener("click",Cn)}function dn(){if(!n.selectedTable||n.selectedTableType!=="table")return;let e=document.getElementById("addRowForm");e.replaceChildren(),n.tableColumns.forEach(t=>{let o=t.notnull===1&&!t.isPrimaryKey,l=document.createElement("div");l.className="form-field";let a=document.createElement("label");if(a.textContent=t.name,o){let i=document.createElement("span");i.style.color="var(--error-color)",i.textContent="*",a.appendChild(document.createTextNode(" ")),a.appendChild(i)}let s=document.createElement("span");s.style.opacity="0.5",s.textContent=` (${t.type})`,a.appendChild(document.createTextNode(" ")),a.appendChild(s);let r=document.createElement("input");r.type="text",r.dataset.column=t.name,r.dataset.required=o.toString(),t.isPrimaryKey?(r.placeholder="Auto (Primary Key)",r.disabled=!0):o?r.placeholder="Required":r.placeholder="NULL",l.appendChild(a),l.appendChild(r),e.appendChild(l)}),V("addRowModal")}async function un(){let e=document.querySelectorAll("#addRowForm input[data-column]:not([disabled])"),t=[];for(let l of e){let a=l.dataset.column,s=l.value.trim();l.dataset.required==="true"&&(s===""||s.toLowerCase()==="null")?(t.push(a),l.style.borderColor="var(--error-color)"):l.style.borderColor=""}if(t.length>0){u(`Required fields missing: ${t.join(", ")}`);return}let o={};for(let l of e){let a=l.dataset.column,s=l.value.trim();s!==""&&(s.toLowerCase()==="null"?o[a]=null:!isNaN(Number(s))&&s!==""?o[a]=Number(s):o[a]=s)}try{u("Inserting row..."),await C.insertRow(n.selectedTable,o),O("addRowModal"),await v(),u("Row inserted - Ctrl+S to save")}catch(l){console.error("Insert failed:",l),u(`Error: ${l.message}`)}}function mn(){if(n.selectedColumns.size>0){let e=Array.from(n.selectedColumns);document.getElementById("deleteConfirmText").textContent=`Are you sure you want to delete ${e.length} column${e.length>1?"s":""} (${e.join(", ")})? This will permanently remove the column${e.length>1?"s":""} and all their data.`}else if(n.selectedRowIds.size>0)document.getElementById("deleteConfirmText").textContent=`Are you sure you want to delete ${n.selectedRowIds.size} row${n.selectedRowIds.size>1?"s":""}?`;else return;V("deleteModal")}async function de(){n.selectedColumns.size>0?await fn():n.selectedRowIds.size>0&&await pn()}async function pn(){if(n.selectedRowIds.size===0)return;let e=Array.from(n.selectedRowIds);try{u("Deleting rows..."),await C.deleteRows(n.selectedTable,e),O("deleteModal"),n.selectedRowIds.clear(),await v(),P(),u(`Deleted ${e.length} row${e.length>1?"s":""} - Ctrl+S to save`)}catch(t){console.error("Delete rows failed:",t),u(`Error: ${t.message}`)}}async function fn(){if(n.selectedColumns.size===0)return;let e=Array.from(n.selectedColumns);try{u("Deleting columns...");let t=await C.deleteColumns(n.selectedTable,e);if(t&&t.cancelled){u("Delete cancelled"),O("deleteModal");return}O("deleteModal"),n.selectedColumns.clear(),n.selectedCells=[],n.lastSelectedCell=null,await _(),await q(),await v(),P(),u(`Deleted ${e.length} column${e.length>1?"s":""} - Ctrl+S to save`)}catch(t){console.error("Delete columns failed:",t),u(`Error: ${t.message}`)}}var yt=0;function Ct(){document.getElementById("newTableName").value="",document.getElementById("columnDefinitions").replaceChildren(),yt=0,xt(!0),V("createTableModal")}function xt(e=!1){let t=document.getElementById("columnDefinitions"),o=++yt,l=document.createElement("div");l.className="column-def-row",l.id=`colDef_${o}`,Object.assign(l.style,{display:"flex",gap:"8px",marginBottom:"8px",alignItems:"center"});let a=document.createElement("input");a.type="text",a.placeholder="Column name",a.className="col-name",a.style.flex="2",e&&(a.value="id"),l.appendChild(a);let s=document.createElement("select");s.className="col-type",s.style.flex="1",["INTEGER","TEXT","REAL","BLOB","NUMERIC"].forEach(f=>{let p=document.createElement("option");p.value=f,p.textContent=f,e&&f==="INTEGER"&&(p.selected=!0),!e&&f==="TEXT"&&(p.selected=!0),s.appendChild(p)}),l.appendChild(s);let r=document.createElement("label");Object.assign(r.style,{display:"flex",alignItems:"center",gap:"4px",cursor:"pointer"});let i=document.createElement("input");i.type="checkbox",i.className="col-pk",i.style.margin="0",e&&(i.checked=!0),r.appendChild(i),r.appendChild(document.createTextNode(" PK")),l.appendChild(r);let c=document.createElement("label");Object.assign(c.style,{display:"flex",alignItems:"center",gap:"4px",cursor:"pointer"});let d=document.createElement("input");d.type="checkbox",d.className="col-nn",d.style.margin="0",c.appendChild(d),c.appendChild(document.createTextNode(" NN")),l.appendChild(c);let m=document.createElement("button");m.className="icon-button btn-remove-col",m.dataset.colid=o.toString(),m.title="Remove",e&&(m.disabled=!0);let g=document.createElement("span");g.className="codicon codicon-close",m.appendChild(g),l.appendChild(m),t.appendChild(l)}function gn(e){let t=document.getElementById(`colDef_${e}`);t&&t.remove()}async function hn(){let e=document.getElementById("newTableName").value.trim();if(!e){u("Error: Table name is required");return}if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(e)){u("Error: Invalid table name");return}let t=[],o=document.querySelectorAll(".column-def-row");for(let l of o){let a=l.querySelector(".col-name").value.trim(),s=l.querySelector(".col-type").value,r=l.querySelector(".col-pk").checked,i=l.querySelector(".col-nn").checked;a&&t.push({name:a,type:s,primaryKey:r,notNull:i})}if(t.length===0){u("Error: At least one column is required");return}try{u("Creating table..."),await C.createTable(e,t),O("createTableModal"),await _(),u(`Table "${e}" created - Ctrl+S to save`)}catch(l){console.error("Create table failed:",l),u(`Error: ${l.message}`)}}function yn(){!n.selectedTable||n.selectedTableType!=="table"||(document.getElementById("newColumnName").value="",document.getElementById("newColumnType").value="TEXT",document.getElementById("newColumnDefault").value="",V("addColumnModal"))}async function Cn(){let e=document.getElementById("newColumnName").value.trim(),t=document.getElementById("newColumnType").value,o=document.getElementById("newColumnDefault").value.trim();if(!e){u("Error: Column name is required");return}if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(e)){u("Error: Invalid column name");return}try{u("Adding column..."),await C.addColumn(n.selectedTable,e,t,o),O("addColumnModal"),await q(),await v(),u(`Column "${e}" added - Ctrl+S to save`)}catch(l){console.error("Add column failed:",l),u(`Error: ${l.message}`)}}function bt(){let e=document.getElementById("pragmaSettingsContainer");e&&e.addEventListener("change",t=>{let o=t.target;if(o.matches(".setting-extension")){let l=o.dataset.key,a=o.type==="checkbox"?o.checked:o.value;bn(l,a)}else if(o.matches(".setting-pragma")){let l=o.dataset.name,a=o.dataset.type,s=o.value;a==="number"?s=Number(s):a==="bool"&&(s=s==="true"?1:0),wn(l,s)}})}async function wt(){let e=document.getElementById("settingsModal");e&&(e.classList.remove("hidden"),await Le())}async function Le(){let e=document.getElementById("pragmaSettingsContainer");e.textContent="Loading settings...";try{let[t,o]=await Promise.all([C.getPragmas(),C.getExtensionSettings()]);xn(t,o)}catch(t){console.error("Failed to load settings:",t),e.textContent=`Error loading settings: ${t.message}`,e.style.color="var(--error-color)"}}function xn(e,t){let o=document.getElementById("pragmaSettingsContainer");if(!o)return;let l=(y,x)=>y.map(A=>{let L=String(A),D=String(x).toUpperCase()===L.toUpperCase(),N=document.createElement("option");return N.value=L,N.selected=D,N.textContent=L,N});o.replaceChildren();let a=y=>{let x=document.createElement("div");x.className="setting-section-title",Object.assign(x.style,{fontWeight:"600",marginBottom:"8px",paddingBottom:"4px",borderBottom:"1px solid var(--border-color)"}),x.textContent=y,o.appendChild(x)},s=(y,x,A)=>{let L=document.createElement("div");L.className="form-field";let b=document.createElement("label");if(x.type==="checkbox"?(Object.assign(b.style,{display:"flex",alignItems:"center",gap:"4px",cursor:"pointer"}),x.style.margin="0",b.appendChild(x),b.appendChild(document.createTextNode(y)),L.appendChild(b)):(b.textContent=y,L.appendChild(b),L.appendChild(x)),A){let D=document.createElement("div");D.className="setting-desc",D.textContent=A,L.appendChild(D)}o.appendChild(L)};if(o.children.length>0){let y=document.createElement("div");y.style.height="16px",o.appendChild(y)}a("Extension Settings");let r=document.createElement("input");r.type="checkbox",r.className="setting-extension",r.dataset.key="autoCommit",r.checked=!!t.autoCommit,s("Auto-Commit Changes",r,"Automatically save changes to disk immediately. If disabled, you must save manually (Ctrl+S).");let i=document.createElement("select");i.className="setting-extension",i.dataset.key="doubleClickBehavior",l(["inline","modal","vscode"],t.cellEditBehavior).forEach(y=>i.appendChild(y)),s("Double Click Behavior",i,"Action when double-clicking a cell");let c=document.createElement("div");c.style.height="16px",o.appendChild(c),a("SQLite Settings (Pragmas)");let d=document.createElement("select");d.className="setting-pragma",d.dataset.name="journal_mode",l(["DELETE","TRUNCATE","PERSIST","MEMORY","WAL","OFF"],e.journal_mode).forEach(y=>d.appendChild(y)),s("Journal Mode",d,"Database journaling mode (WAL is recommended for concurrency)");let m=document.createElement("select");m.className="setting-pragma",m.dataset.name="foreign_keys",m.dataset.type="bool";let g=document.createElement("option");g.value="true",g.textContent="ON";let f=document.createElement("option");f.value="false",f.textContent="OFF",Number(e.foreign_keys)===1?g.selected=!0:f.selected=!0,m.appendChild(g),m.appendChild(f),s("Foreign Keys",m,"Enforce foreign key constraints");let p=document.createElement("select");p.className="setting-pragma",p.dataset.name="synchronous",p.dataset.type="number",[{v:0,t:"OFF (0)"},{v:1,t:"NORMAL (1)"},{v:2,t:"FULL (2)"},{v:3,t:"EXTRA (3)"}].forEach(y=>{let x=document.createElement("option");x.value=y.v,x.textContent=y.t,Number(e.synchronous)===y.v&&(x.selected=!0),p.appendChild(x)}),s("Synchronous",p,"Disk synchronization safety level");let h=document.createElement("select");h.className="setting-pragma",h.dataset.name="locking_mode",l(["NORMAL","EXCLUSIVE"],e.locking_mode).forEach(y=>h.appendChild(y)),s("Locking Mode",h,"");let w=document.createElement("select");w.className="setting-pragma",w.dataset.name="auto_vacuum",w.dataset.type="number",[{v:0,t:"NONE (0)"},{v:1,t:"FULL (1)"},{v:2,t:"INCREMENTAL (2)"}].forEach(y=>{let x=document.createElement("option");x.value=y.v,x.textContent=y.t,Number(e.auto_vacuum)===y.v&&(x.selected=!0),w.appendChild(x)}),s("Auto Vacuum",w,"");let S=document.createElement("input");S.type="number",S.className="setting-pragma",S.dataset.name="cache_size",S.dataset.type="number",S.value=e.cache_size,s("Cache Size",S,"Number of pages (positive) or kilobytes (negative)")}async function bn(e,t){try{await C.updateExtensionSetting(e,t),u(`Updated ${e}`)}catch(o){console.error(`Failed to set ${e}:`,o),u(`Error: ${o.message}`),await Le()}}async function wn(e,t){try{u(`Updating ${e}...`),await C.setPragma(e,t),u(`Updated ${e}`)}catch(o){console.error(`Failed to set ${e}:`,o),u(`Error: ${o.message}`),await Le()}}function Et(e,t){let o=new Map;for(let l of e){let a=t&&t[l.colIdx];a&&(o.has(l.colIdx)||o.set(l.colIdx,{name:a.name,type:a.type,values:new Set}),o.get(l.colIdx).values.add(l.value))}return o}function It(e){let t=Array.from(e||[]);if(t.length===0)return"";if(t.length>1)return"(mixed values)";let o=t[0];return o===null?"NULL":o instanceof Uint8Array?"[BLOB]":String(o)}function St(e,t,o){let l=[];for(let a of e){let s=t.get(a.colIdx);if(!s)continue;let r=s.dataset||{},i=r.isnull==="true",c=r.ispatch==="true",d=s.value;if(d===""&&!i)continue;let m=o&&o[a.colIdx];if(!m)continue;let g=d,f="set";if(i)g=null;else if(c)f="json_patch";else{let p=(m.type||"").toUpperCase();(p==="INTEGER"||p==="REAL"||p==="NUMERIC")&&!isNaN(Number(d))&&d.trim()!==""&&(g=Number(d))}l.push({rowId:a.rowId,column:m.name,value:g,originalValue:a.value,operation:f,rowIdx:a.rowIdx,colIdx:a.colIdx})}return l}function Tt(){let e=document.getElementById("sidebarPanel");if(!e)return;let t=document.getElementById("sidebarFilterInput");t&&t.addEventListener("input",()=>{n.sidebarFilter=t.value,De()}),e.addEventListener("click",o=>{let l=o.target;if(l.closest("#btnOpenSettings")){wt();return}if(l.closest("#btnOpenCreateTable")){o.stopPropagation(),Ct();return}if(l.closest("#btnReload")){Rn();return}if(l.closest("#btnApplyBatchUpdate")){In();return}let a=l.closest(".list-item");if(a){let c=a.dataset.name,d=a.dataset.type;if(c&&d){Bn(c,d);return}}let s=l.closest(".section-title");if(s){if(l.closest(".icon-button")||s.id==="btnOpenSettings")return;let c=s.dataset.section;c&&Tn(c)}let r=l.closest(".btn-batch-null");if(r){let c=r.closest(".batch-field");if(c){let d=parseInt(c.dataset.colidx,10);Sn(d)}return}let i=l.closest(".btn-batch-patch");if(i){let c=i.closest(".batch-field");if(c){let d=parseInt(c.dataset.colidx,10);vn(d,i)}return}})}async function _(){if(n.isDbConnected)try{let e=await C.fetchSchema();n.schemaCache.tables=(e.tables||[]).map(t=>({name:t.identifier})),n.schemaCache.views=(e.views||[]).map(t=>({name:t.identifier})),n.schemaCache.indexes=(e.indexes||[]).map(t=>({name:t.identifier,table:t.parentTable})),De()}catch(e){console.error("Error loading schema:",e),u("Error loading schema")}}function Pe(e,t){return t?e.filter(o=>o.name.toLowerCase().includes(t)):e}function ke(e,t,o,l){let a=document.getElementById(e);a&&(a.textContent=l?`${t}/${o}`:o)}function vt(e,t,o,l,a){let s=document.getElementById(e);if(!s)return;if(s.replaceChildren(),t.length===0){let i=document.createElement("li");i.className="list-item",i.style.opacity="0.5",i.textContent=a,s.appendChild(i);return}let r=document.createDocumentFragment();t.forEach(i=>{let c=document.createElement("li");c.className="list-item",n.selectedTable===i.name&&n.selectedTableType===o&&c.classList.add("selected"),c.dataset.name=i.name,o&&(c.dataset.type=o),c.title=i.name;let d=document.createElement("span");d.className=`item-icon codicon ${l}`,c.appendChild(d);let m=document.createElement("span");m.className="item-name",m.textContent=i.name,c.appendChild(m),r.appendChild(c)}),s.appendChild(r)}function En(e,t,o){let l=document.getElementById(e);if(!l)return;if(l.replaceChildren(),t.length===0){let s=document.createElement("li");s.className="list-item",s.style.opacity="0.5",s.textContent=o,l.appendChild(s);return}let a=document.createDocumentFragment();t.forEach(s=>{let r=document.createElement("li");r.className="list-item",r.title=`${s.name} on ${s.table}`;let i=document.createElement("span");i.className="item-icon codicon codicon-list-selection",r.appendChild(i);let c=document.createElement("div");c.className="item-content";let d=document.createElement("span");d.className="item-name",d.textContent=s.name,c.appendChild(d);let m=document.createElement("span");m.className="item-detail",m.textContent=s.table,c.appendChild(m),r.appendChild(c),a.appendChild(r)}),l.appendChild(a)}function De(){let e=n.sidebarFilter.toLowerCase(),t=e.length>0,o=Pe(n.schemaCache.tables,e),l=Pe(n.schemaCache.views,e),a=Pe(n.schemaCache.indexes,e);ke("tablesBadge",o.length,n.schemaCache.tables.length,t),ke("viewsBadge",l.length,n.schemaCache.views.length,t),ke("indexesBadge",a.length,n.schemaCache.indexes.length,t),vt("tablesList",o,"table","codicon-table",e?"No matching tables":"No tables"),vt("viewsList",l,"view","codicon-eye",e?"No matching views":"No views"),En("indexesList",a,e?"No matching indexes":"No indexes")}function z(){let e=document.getElementById("batchUpdateSectionTitle"),t=document.getElementById("batchUpdateList"),o=document.getElementById("batchUpdateCount"),l=document.getElementById("batchUpdateFields");if(!e||!t||!o||!l)return;let a=n.selectedCells.length;if(a===0){e.classList.add("hidden"),t.classList.add("hidden");return}e.classList.remove("hidden"),t.classList.remove("hidden"),e.classList.remove("collapsed"),o.textContent=a;let s=Et(n.selectedCells,n.tableColumns);l.replaceChildren();let r=document.createDocumentFragment();for(let[i,c]of s){let d=It(c.values),m=document.createElement("div");m.className="form-field batch-field",m.dataset.colidx=i,m.style.marginBottom="8px";let g=document.createElement("label");g.style.fontSize="11px",g.style.color="var(--text-secondary)";let f=document.createTextNode(c.name+" ");g.appendChild(f);let p=document.createElement("span");p.style.opacity="0.7",p.textContent=c.type||"",g.appendChild(p),m.appendChild(g);let h=document.createElement("div");h.style.display="flex",h.style.gap="4px";let w=document.createElement("input");w.type="text",w.className="batch-input",w.placeholder=d,w.dataset.colidx=i,w.style.flex="1",w.style.minWidth="0",h.appendChild(w);let S=document.createElement("button");S.className="btn-secondary btn-batch-null",S.style.padding="2px 6px",S.title="Set to NULL",S.textContent="NULL",h.appendChild(S);let y=document.createElement("button");y.className="btn-secondary btn-batch-patch",y.style.padding="2px 6px",y.title="JSON Patch",y.textContent="{}",h.appendChild(y),m.appendChild(h),r.appendChild(m)}l.appendChild(r)}async function In(){if(n.selectedCells.length===0)return;let e=document.querySelectorAll(".batch-input"),t=new Map;for(let l of e){let a=parseInt(l.dataset.colidx,10);if(t.set(a,l),l.dataset.ispatch==="true")try{JSON.parse(l.value)}catch{let r=n.tableColumns[a];u(`Invalid JSON for patch in ${r?.name??`column ${a}`}`);return}}let o=St(n.selectedCells,t,n.tableColumns);if(o.length===0){u("No values entered for batch update");return}try{u(`Updating ${o.length} cells...`);let l=`Batch update ${o.length} cells`,a=o.map(i=>({rowId:i.rowId,column:i.column,value:i.value,originalValue:i.originalValue,operation:i.operation}));if(await C.updateCellBatch(n.selectedTable,a,l),!o.some(i=>i.operation==="json_patch"))for(let i of o)n.gridData[i.rowIdx][i.colIdx+R()]=i.value;await v(!1);let r=[];for(let i of n.selectedCells){let c=n.gridData[i.rowIdx][i.colIdx+R()];r.push({...i,value:c})}n.selectedCells=r,z(),u("Batch update completed")}catch(l){console.error("Batch update failed:",l),u(`Batch update failed: ${l.message}`)}}function Sn(e){let t=document.querySelector(`.batch-input[data-colidx="${e}"]`),o=document.querySelector(`.batch-field[data-colidx="${e}"] .btn-batch-patch`);t&&(t.value="",t.placeholder="SET TO NULL",t.dataset.isnull="true",t.dataset.ispatch="false",t.style.fontStyle="italic",o&&(o.style.background="",o.style.color=""))}function vn(e,t){let o=document.querySelector(`.batch-input[data-colidx="${e}"]`);o&&(o.dataset.ispatch==="true"?(o.dataset.ispatch="false",o.placeholder="(mixed values)",t.style.background="",t.style.color=""):(o.dataset.ispatch="true",o.dataset.isnull="false",o.placeholder='JSON Patch (e.g. {"a": 1})',o.style.fontStyle="normal",t.style.background="var(--accent-color)",t.style.color="white"))}function Tn(e){let t=document.getElementById(`${e}List`),o=document.querySelector(`.section-title[data-section="${e}"]`);t&&o&&(t.classList.toggle("hidden"),o.classList.toggle("collapsed"))}async function Bn(e,t){n.selectedTable=e,n.selectedTableType=t,n.currentPageIndex=0,n.sortedColumn=null,n.sortAscending=!0,n.filterQuery="",n.columnFilters={},n.selectedRowIds.clear(),n.selectedCells=[],n.lastSelectedCell=null,n.selectedColumns.clear(),n.pinnedColumns.clear(),n.pinnedRowIds.clear(),n.columnWidths={},n.scrollPosition={top:0,left:0},De();let o=document.getElementById("tableNameLabel");o&&(o.textContent=e);let l=document.getElementById("filterInput");l&&(l.value=""),await q(),await v(!0,!1),M()}async function Rn(){if(n.isDbConnected)try{u("Reloading..."),await C.refreshFile(),await _(),n.selectedTable&&(await q(),await v()),u("Reloaded")}catch(e){console.error("Reload failed:",e),u(`Reload failed: ${e.message}`)}}function Bt(){document.getElementById("btnExport")?.addEventListener("click",Ln),document.getElementById("btnSubmitExport")?.addEventListener("click",Pn),document.getElementById("exportFormat")?.addEventListener("change",Rt)}function Ln(){if(!n.selectedTable)return;let e=document.getElementById("exportFormat");e&&(e.value="csv");let t=document.getElementById("exportColumns");t&&(t.replaceChildren(),n.tableColumns.forEach(o=>{let l=document.createElement("div"),a=document.createElement("label");Object.assign(a.style,{display:"flex",alignItems:"center",gap:"3px",marginBottom:"4px",fontSize:"13px",cursor:"pointer"});let s=document.createElement("input");s.type="checkbox",s.className="export-col-check",s.value=o.name,s.checked=!0,s.style.margin="0",a.appendChild(s),a.appendChild(document.createTextNode(o.name)),t.appendChild(a)})),Rt(),V("exportModal")}function Rt(){let e=document.getElementById("exportFormat").value,t=document.getElementById("exportOptions");if(t.replaceChildren(),e==="csv"||e==="excel"){let o=document.createElement("label");Object.assign(o.style,{display:"flex",alignItems:"center",gap:"3px",marginBottom:"4px",fontSize:"13px",cursor:"pointer"});let l=document.createElement("input");l.type="checkbox",l.id="exportHeader",l.checked=!0,l.style.margin="0",o.appendChild(l),o.appendChild(document.createTextNode(" Include Headers")),t.appendChild(o)}else if(e==="sql"){let o=document.createElement("label");Object.assign(o.style,{display:"flex",alignItems:"center",gap:"3px",marginBottom:"4px",fontSize:"13px",cursor:"pointer"});let l=document.createElement("input");l.type="checkbox",l.id="exportTableName",l.checked=!0,l.style.margin="0",o.appendChild(l),o.appendChild(document.createTextNode(" Include Table Name")),t.appendChild(o)}}async function Pn(){let e=document.getElementById("exportFormat").value,t=document.querySelectorAll(".export-col-check:checked"),o=Array.from(t).map(a=>a.value);if(o.length===0){u("Error: Select at least one column");return}let l={};if(e==="csv"||e==="excel"?l.header=document.getElementById("exportHeader")?.checked??!0:e==="sql"&&(l.includeTableName=document.getElementById("exportTableName")?.checked??!0),n.selectedTableType==="table"){let a=Array.from(n.selectedRowIds);a.length>0&&(l.rowIds=a)}try{u("Exporting..."),O("exportModal"),await C.exportTable({table:n.selectedTable},o,null,null,{format:e,...l}),u("Export initiated")}catch(a){console.error("Export failed:",a),u(`Export failed: ${a.message}`)}}async function Lt(){if(n.selectedCells.length!==0)try{let e;if(n.selectedCells.length===1){let t=n.selectedCells[0].value;t==null?e="":t instanceof Uint8Array?e="[BLOB]":e=String(t)}else{let t=[...new Set(n.selectedCells.map(s=>s.rowIdx))].sort((s,r)=>s-r),o=[...new Set(n.selectedCells.map(s=>s.colIdx))].sort((s,r)=>s-r),l=new Map;for(let s of n.selectedCells)l.set(`${s.rowIdx},${s.colIdx}`,s.value);let a=[];for(let s of t){let r=[];for(let i of o){let c=`${s},${i}`,d=l.has(c)?l.get(c):"";d==null?d="":d instanceof Uint8Array?d="[BLOB]":(d=String(d),d=d.replace(/\t/g," ").replace(/\n/g," ")),r.push(d)}a.push(r.join(" "))}e=a.join(` `)}await navigator.clipboard.writeText(e),u(`Copied ${n.selectedCells.length} cell${n.selectedCells.length>1?"s":""}`)}catch(e){console.error("Copy failed:",e),u("Copy failed: "+e.message)}}async function Pt(){if(n.selectedRowIds.size!==0)try{let e=[];for(let l=0;lc==null?"":c instanceof Uint8Array?"[BLOB]":String(c));e.push(i.join(" "))}}let o=[n.tableColumns.map(l=>l.name).join(" "),...e].join(` `);await navigator.clipboard.writeText(o),u(`Copied ${e.length} row${e.length>1?"s":""} to clipboard`)}catch(e){console.error("Copy failed:",e),u("Copy failed: "+e.message)}}async function kt(){if(n.selectedCells.length!==0){if(n.selectedTableType!=="table"){u("Views are read-only");return}try{u("Clearing cells...");let e=[];for(let o of n.selectedCells){let l=n.tableColumns[o.colIdx];if(!l)continue;let s=l.notnull===1?"":null;e.push({rowId:o.rowId,column:l.name,value:s,originalValue:o.value,rowIdx:o.rowIdx,colIdx:o.colIdx})}let t=`Clear ${e.length} cell${e.length>1?"s":""}`;await C.updateCellBatch(n.selectedTable,e,t);for(let o of e)n.gridData[o.rowIdx][o.colIdx+R()]=o.value;n.selectedCells=[],n.lastSelectedCell=null,n.selectedColumns.clear(),await v(),P(),u(`${t} - Ctrl+S to save`)}catch(e){console.error("Clear cells failed:",e),u(`Clear failed: ${e.message}`)}}}var ue=50*1024*1024,Ne=!1;function Dt(){let e=document.getElementById("gridContainer");if(!e){console.error("gridContainer not found");return}document.addEventListener("dragover",t=>t.preventDefault()),document.addEventListener("drop",t=>t.preventDefault()),e.addEventListener("dragover",kn),e.addEventListener("dragleave",Dn),e.addEventListener("drop",Nn)}var F=null;function kn(e){e.preventDefault(),e.dataTransfer.dropEffect="copy";let t=e.target.closest(".data-cell");t&&!t.classList.contains("row-number")?(F&&F!==t&&F.classList.remove("drag-over"),t.classList.add("drag-over"),F=t):F&&(F.classList.remove("drag-over"),F=null)}function Dn(e){e.target}async function Nn(e){e.preventDefault(),F&&(F.classList.remove("drag-over"),F=null);let t=e.target.closest(".data-cell");if(!t||t.classList.contains("row-number"))return;if(e.dataTransfer.files.length>0){let l=e.dataTransfer.files[0];await An(t,l.name,l);return}let o=e.dataTransfer.getData("text/uri-list");if(o){let l=o.split(/\r?\n/);if(l.length>0&&l[0]){let a=l[0],s="unknown_file";try{let r=a.split("/");s=decodeURIComponent(r[r.length-1])}catch(r){console.warn("Failed to parse name from URI",r)}await $n(t,s,a);return}}}async function An(e,t,o){if(o.size>ue){let l=(o.size/1048576).toFixed(1),a=(ue/(1024*1024)).toFixed(0);u(`File too large (${l}MB). Maximum is ${a}MB.`);return}try{u(`Reading ${t}...`);let l=await Mn(o),a=new Uint8Array(l);await Nt(e,t,a)}catch(l){console.error("File read failed:",l),u(`File read failed: ${l.message}`)}}async function $n(e,t,o){try{u(`Fetching ${t}...`);let l=await C.readWorkspaceFileUri(o),a;if(l instanceof Uint8Array)a=l;else if(l&&l.type==="Buffer"&&Array.isArray(l.data))a=new Uint8Array(l.data);else if(l&&typeof l=="object"&&Object.keys(l).some(s=>!isNaN(s)))a=new Uint8Array(Object.values(l));else throw console.error("Unknown data format from backend:",l),new Error("Received invalid data format from backend");await Nt(e,t,a)}catch(l){console.error("URI upload failed:",l),u(`Upload failed: ${l.message}`)}}async function Nt(e,t,o){if(Ne){u("Upload already in progress...");return}if(o.byteLength>ue){let c=(o.byteLength/1048576).toFixed(1),d=(ue/(1024*1024)).toFixed(0);u(`File too large (${c}MB). Maximum is ${d}MB.`);return}let l=parseInt(e.dataset.rowidx,10),a=parseInt(e.dataset.colidx,10);if(!n.gridData)return;let s=n.gridData[l];if(!s)return;let r=B(s,l),i=n.tableColumns[a];if(n.selectedTableType!=="table"){u("Cannot upload to a view");return}Ne=!0,n.isLoadingData=!0;try{u(`Uploading ${t} (${Un(o.byteLength)})...`);let c=s[a+R()];await C.updateCell(n.selectedTable,r,i.name,o,c),n.gridData[l][a+R()]=o,Fn(e,o),u(`Uploaded ${t}`)}catch(c){console.error("Upload failed:",c);let d=c.message||String(c);d.includes("timeout")&&(d="Upload timed out. Try a smaller file."),u(`Upload failed: ${d}`)}finally{Ne=!1,n.isLoadingData=!1}}function Mn(e){return new Promise((t,o)=>{let l=new FileReader;l.onload=()=>t(l.result),l.onerror=()=>o(l.error),l.readAsArrayBuffer(e)})}function Un(e){if(e===0)return"0 B";let t=1024,o=["B","KB","MB","GB"],l=Math.floor(Math.log(e)/Math.log(t));return parseFloat((e/Math.pow(t,l)).toFixed(2))+" "+o[l]}function Fn(e,t){let o=K(t);e.textContent="";let l=document.createElement("span");l.className="cell-text",l.textContent=o,e.appendChild(l);let a=document.createElement("span");a.className="expand-icon codicon codicon-link-external",a.title="View full content",e.appendChild(a),e.classList.remove("null-value")}var At={async refreshContent(e){return n.isDbConnected&&(await _(),!(n.schemaCache.tables.some(o=>o.name===n.selectedTable)||n.schemaCache.views.some(o=>o.name===n.selectedTable))&&n.selectedTable?(n.selectedTable=null,n.selectedTableType=null,document.getElementById("tableNameLabel").textContent="No table selected",Se()):n.selectedTable&&await v(!1)),{success:!0}},async updateColorScheme(e){return document.documentElement.style.colorScheme=e,{success:!0}},async updateCellEditBehavior(e){return n.cellEditBehavior=e,{success:!0}}};function On(){window.addEventListener("message",e=>{let t=e.data;if(t&&t.kind==="invoke"){let{correlationId:l,methodName:a,parameters:s}=t,r=At[a];typeof r=="function"?Promise.resolve(r.apply(At,s||[])).then(i=>{je(l,i)}).catch(i=>{Ee(l,i instanceof Error?i.message:String(i))}):Ee(l,`Unknown method: ${a}`);return}if(!t||t.channel!=="rpc")return;let o=t.content;o&&o.kind==="response"&&ze(o)})}On();async function zn(){try{Tt(),ht(),Bt(),gt(),bt(),qe(),pt(),ft(),_e(),Dt();let e=document.getElementById("openInVsCodeBtn");e&&(e.style.display="none"),u("Connecting to database...");let t=await Ie.initialize();n.isDbConnected=!0,await Ie.ping(),await _(),u("Ready"),Se(),document.addEventListener("keydown",async o=>{if(o.key==="Escape"&&!n.editingCellInfo&&!document.querySelector(".modal-overlay:not(.hidden)")&&ae(),(o.metaKey||o.ctrlKey)&&o.key==="c"){if(n.editingCellInfo||document.activeElement.tagName==="INPUT")return;n.selectedCells.length>0?(o.preventDefault(),await Lt()):n.selectedRowIds.size>0&&(o.preventDefault(),await Pt())}if((o.metaKey||o.ctrlKey)&&o.key==="a"){if(n.editingCellInfo||document.activeElement.tagName==="INPUT")return;n.selectedTable&&(o.preventDefault(),ce(o))}if((o.metaKey||o.ctrlKey)&&(o.key==="Delete"||o.key==="Backspace")){if(n.editingCellInfo||document.activeElement.tagName==="INPUT"||document.activeElement.tagName==="TEXTAREA")return;n.selectedTable&&n.selectedTableType==="table"&&(o.preventDefault(),n.selectedColumns.size>0?await de():n.selectedRowIds.size>0?await de():n.selectedCells.length>0&&await kt())}})}catch(e){console.error("Init error:",e),le(e.message)}}zn();})(); From 87f78367f6c3ee51b311c46fd671d4f53b68269d Mon Sep 17 00:00:00 2001 From: zknpr Date: Sun, 21 Jun 2026 21:09:20 +0200 Subject: [PATCH 3/9] =?UTF-8?q?fix:=20address=20grid-flicker=20review=20?= =?UTF-8?q?=E2=80=94=20table-switch=20spinner=20+=20scroll=20capture?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolve the two issues Gemini flagged on the flicker fix: - Switching tables left the previous table's grid on screen with no spinner, because hasRenderedGrid was true for the stale grid. Track the rendered table (state.renderedTable) and only suppress the spinner for a same-table refetch; a table switch now shows the spinner. - Scroll done during a flicker-free (showSpinner=true) refetch was lost. Gate the post-await scroll re-capture on saveScrollPosition instead of !showSpinner so live scrolling is preserved, without clobbering the intentional scroll reset on page change / table switch. Regenerated viewer.html bundles. Co-Authored-By: Claude Opus 4.8 (1M context) --- core/ui/modules/grid-data.js | 37 +++++++++++++++--------- core/ui/modules/state.js | 4 +++ core/ui/viewer.html | 12 ++++---- website/public/sqlite-viewer/viewer.html | 22 +++++++------- 4 files changed, 45 insertions(+), 30 deletions(-) diff --git a/core/ui/modules/grid-data.js b/core/ui/modules/grid-data.js index b852b2a6..eb2894d0 100644 --- a/core/ui/modules/grid-data.js +++ b/core/ui/modules/grid-data.js @@ -42,22 +42,28 @@ export async function loadTableData(showSpinner = true, saveScrollPosition = tru if (!state.selectedTable) return; const container = document.getElementById('gridContainer'); - // Whether a data grid is currently rendered (vs. a spinner/error/empty state). - // Cached once instead of re-querying the DOM at each decision point below. + // Whether a data grid is currently rendered (vs. a spinner/error/empty state), + // AND whether it belongs to the table we're loading. The renderedTable check is + // what separates a same-table refetch (filter/sort/page — keep the grid, no + // flicker) from a table switch, where the previous table's grid is still in the + // DOM and must not be left on screen. Cached once instead of re-querying below. const hasRenderedGrid = !!(container && container.querySelector('.data-grid')); + const isSameTableGrid = hasRenderedGrid && state.renderedTable === state.selectedTable; - // Only capture scroll position if the grid is currently visible (not loading/error state) - // This prevents overwriting the saved position with 0 when reloading data while a spinner is shown. - if (saveScrollPosition && hasRenderedGrid) { + // Only capture scroll position if the current table's grid is visible (not a + // loading/error state, and not a different table's grid mid-switch). This + // prevents overwriting the saved position with 0 while a spinner is shown. + if (saveScrollPosition && isSameTableGrid) { state.scrollPosition.left = container.scrollLeft; state.scrollPosition.top = container.scrollTop; } if (showSpinner) { state.isLoadingData = true; - // Keep the existing grid visible during refetch (prevents flicker); only - // show the spinner on a true first load when nothing is rendered yet. - if (!hasRenderedGrid) { + // Keep the existing grid visible during a same-table refetch (prevents + // flicker); show the spinner on a true first load or a table switch, where + // nothing valid for this table is on screen yet. + if (!isSameTableGrid) { showLoading(); } } @@ -113,13 +119,15 @@ export async function loadTableData(showSpinner = true, saveScrollPosition = tru state.gridData = dataResult.rows || []; - // If not showing spinner (background refresh), capture the current scroll position - // right before rendering. This ensures we use the latest scroll position, - // which covers cases where the user scrolled during fetch or if an edit operation - // updated the view (and restored scroll) while the fetch was pending. + // When preserving scroll, re-capture the latest position right before + // rendering. Covers the user scrolling during the fetch — including a + // flicker-free refetch where the spinner was suppressed and the grid stayed + // interactive — and edit operations that restored scroll while the fetch was + // pending. Gated on saveScrollPosition (not !showSpinner) so callers that + // intentionally reset scroll (page change, table switch) aren't clobbered. // Re-check the DOM here (not the cached flag): this runs after the await, // so the rendered state may differ from when the function started. - if (!showSpinner && container && container.querySelector('.data-grid')) { + if (saveScrollPosition && container && container.querySelector('.data-grid')) { state.scrollPosition.left = container.scrollLeft; state.scrollPosition.top = container.scrollTop; } @@ -131,6 +139,9 @@ export async function loadTableData(showSpinner = true, saveScrollPosition = tru // updateCellDom in edit.js handles the visual update of the modified cell. } else { renderDataGrid(state.scrollPosition.top, state.scrollPosition.left); + // The on-screen grid now reflects this table; remember it so the next + // load can distinguish a same-table refetch from a table switch. + state.renderedTable = state.selectedTable; } if (container) { diff --git a/core/ui/modules/state.js b/core/ui/modules/state.js index 29693ef5..55808a28 100644 --- a/core/ui/modules/state.js +++ b/core/ui/modules/state.js @@ -7,6 +7,10 @@ export const state = { isDbConnected: false, selectedTable: null, selectedTableType: 'table', + // Name of the table whose grid is currently rendered on screen. Lets + // loadTableData tell a same-table refetch (keep the grid, no flicker) apart + // from a table switch (show the spinner instead of the previous table's rows). + renderedTable: null, currentPageIndex: 0, rowsPerPage: 500, totalRecordCount: 0, diff --git a/core/ui/viewer.html b/core/ui/viewer.html index 92c15333..da34bfa6 100644 --- a/core/ui/viewer.html +++ b/core/ui/viewer.html @@ -364,7 +364,7 @@
From b0ae9d1cf704788eb6375a86a4f010d0d9c858d3 Mon Sep 17 00:00:00 2001 From: zknpr Date: Sun, 21 Jun 2026 21:23:56 +0200 Subject: [PATCH 4/9] fix: block grid interaction during refetch (Codex P1) The flicker fix keeps the previous grid visible during a same-table refetch (isLoadingData=true, spinner suppressed). Grid click/dblclick/ keydown handlers didn't check that flag, so a user could select and delete rows from the stale result set before the new data arrived, or queue a concurrent reload. Guard handleClick, handleDoubleClick and handleKeydown on isLoadingData, restoring the pre-flicker-fix "non-interactive while loading" behavior without re-introducing the flicker. Typing in filter inputs still works; scroll/hover/resize remain live. Regenerated viewer.html bundles. Co-Authored-By: Claude Opus 4.8 (1M context) --- core/ui/modules/grid-events.js | 10 ++++++++++ core/ui/viewer.html | 2 +- website/public/sqlite-viewer/viewer.html | 18 +++++++++--------- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/core/ui/modules/grid-events.js b/core/ui/modules/grid-events.js index e1140e50..9ddbabdb 100644 --- a/core/ui/modules/grid-events.js +++ b/core/ui/modules/grid-events.js @@ -52,6 +52,9 @@ function handleMousedown(event) { } function handleKeydown(event) { + // Ignore filter Enter while a load is in flight: acting now would queue a + // concurrent reload and operate against the stale, soon-to-be-replaced grid. + if (state.isLoadingData) return; if (event.target.classList.contains('column-filter')) { const colName = event.target.dataset.column; if (colName) onColumnFilterKeydown(event, colName); @@ -59,6 +62,11 @@ function handleKeydown(event) { } function handleClick(event) { + // Block grid selection/sort/filter/pin clicks while a load is in flight. The + // flicker fix keeps the previous grid visible during a same-table refetch, so + // without this guard a click on the stale row numbers or cells could select + // (and then delete) rows from the old result set before the new data arrives. + if (state.isLoadingData) return; const target = event.target; if (target.closest('.grid-header')) { handleHeaderClick(event, target); @@ -169,6 +177,8 @@ function handleBodyClick(event, target) { } function handleDoubleClick(event) { + // Don't open a cell editor on stale cells while a refetch is in flight. + if (state.isLoadingData) return; const cellEl = event.target.closest('.data-cell'); if (cellEl && !cellEl.classList.contains('row-number')) { const rowIdx = parseInt(cellEl.dataset.rowidx, 10); diff --git a/core/ui/viewer.html b/core/ui/viewer.html index da34bfa6..db2963ea 100644 --- a/core/ui/viewer.html +++ b/core/ui/viewer.html @@ -400,7 +400,7 @@
`,a.appendChild(f)}return l.appendChild(a),l}function rn(e,n,o,l,a,s,i,r){let c=document.createElement("tbody"),d=[];for(let p=0;p({idx:g,rowId:T(p,g)})).filter(p=>t.pinnedRowIds.has(p.rowId)),...t.gridData.map((p,g)=>({idx:g,rowId:T(p,g)})).filter(p=>!t.pinnedRowIds.has(p.rowId))],f=document.createDocumentFragment();for(let{idx:p,rowId:g}of h){let w=t.gridData[p],v=t.selectedRowIds.has(g),y=t.pinnedRowIds.has(g),x=document.createElement("tr");x.id=`row-${p}`,x.className=`data-row ${v?"selected":""} ${y?"pinned":""}`,x.dataset.rowid=g,x.dataset.rowidx=p,y&&(x.style.top=`${m.get(g)}px`);let k=document.createElement("td");k.className="data-cell row-number",Object.assign(k.style,{width:`${l}px`,minWidth:`${l}px`,maxWidth:`${l}px`,position:"sticky",left:"0",zIndex:y?"8":"2"});let L=t.currentPageIndex*t.rowsPerPage+p+1;k.appendChild(document.createTextNode(String(L)));let b=document.createElement("span");b.className=`pin-icon codicon codicon-pin ${y?"pinned":""}`,b.title=y?"Unpin row":"Pin row",k.appendChild(b),x.appendChild(k);for(let D=0;Db&&b.trim()!=="");if(r.innerHTML="",t.gridData.length===0&&!f&&t.tableColumns.length===0){r.appendChild(an());return}let p=new Set;if(t.selectedCells.length>0)for(let b of t.selectedCells)p.add(`${b.rowIdx},${b.colIdx}`);let g=document.createElement("table");if(g.className="data-grid",Object.keys(t.columnWidths).length===0&&t.gridData.length>0)for(let b of t.tableColumns){let D=b.name.length,N=b.isPrimaryKey?86:70,q=D*8+N;t.columnWidths[b.name]=Math.max(80,Math.min(250,q))}let w=[...t.tableColumns.filter(b=>t.pinnedColumns.has(b.name)),...t.tableColumns.filter(b=>!t.pinnedColumns.has(b.name))],v=new Map,y=i-1;for(let b of w)t.pinnedColumns.has(b.name)&&(v.set(b.name,y),y+=t.columnWidths[b.name]||120);let x=new Map;t.tableColumns.forEach((b,D)=>x.set(b.name,D));let k=sn(i,w,v);g.appendChild(k);let L=rn(w,x,v,i,52,26,p,f);g.appendChild(L),r.appendChild(g),r.scrollLeft=m,r.scrollTop=h,Xe()}function Ye(){document.getElementById("pageIndicator").textContent=`${t.currentPageIndex+1} / ${t.totalPageCount}`,document.getElementById("btnFirst").disabled=t.currentPageIndex===0,document.getElementById("btnPrev").disabled=t.currentPageIndex===0,document.getElementById("btnNext").disabled=t.currentPageIndex>=t.totalPageCount-1,document.getElementById("btnLast").disabled=t.currentPageIndex>=t.totalPageCount-1}async function z(){if(t.selectedTable)try{let e=await C.getTableInfo(t.selectedTable);t.tableColumns=e.map(o=>({cid:o.ordinal,name:o.identifier,type:o.declaredType,notnull:o.isRequired,dflt_value:o.defaultExpression,isPrimaryKey:o.primaryKeyPosition>0})).sort((o,l)=>o.cid-l.cid);let n=new Set(t.tableColumns.map(o=>o.name));t.sortedColumn&&!n.has(t.sortedColumn)&&(t.sortedColumn=null,t.sortAscending=!0);for(let o of Object.keys(t.columnFilters))n.has(o)||delete t.columnFilters[o]}catch(e){console.error("Error loading columns:",e),u("Error loading columns")}}async function I(e=!0,n=!0){if(!t.selectedTable)return;let o=document.getElementById("gridContainer"),a=!!(o&&o.querySelector(".data-grid"))&&t.renderedTable===t.selectedTable;n&&a&&(t.scrollPosition.left=o.scrollLeft,t.scrollPosition.top=o.scrollTop),e&&(t.isLoadingData=!0,a||$e()),R();try{let s=[];for(let[f,p]of Object.entries(t.columnFilters))p&&p.trim()&&s.push({column:f,value:p});let i=t.tableColumns.map(f=>f.name),r={filters:s,globalFilter:t.filterQuery,columns:i};t.totalRecordCount=await C.fetchTableCount(t.selectedTable,r),t.totalPageCount=Math.max(1,Math.ceil(t.totalRecordCount/t.rowsPerPage)),t.currentPageIndex>=t.totalPageCount&&(t.currentPageIndex=Math.max(0,t.totalPageCount-1));let m={columns:t.selectedTableType==="table"?["rowid",...i]:i,orderBy:t.sortedColumn,orderDir:t.sortAscending?"ASC":"DESC",limit:t.rowsPerPage,offset:t.currentPageIndex*t.rowsPerPage,filters:s,globalFilter:t.filterQuery},h=await C.fetchTableData(t.selectedTable,m);t.gridData=h.rows||[],n&&o&&o.querySelector(".data-grid")&&(t.scrollPosition.left=o.scrollLeft,t.scrollPosition.top=o.scrollTop),!e&&t.editingCellInfo||(_(t.scrollPosition.top,t.scrollPosition.left),t.renderedTable=t.selectedTable),o&&(o.scrollLeft=t.scrollPosition.left,o.scrollTop=t.scrollPosition.top),Ye(),u(`${t.totalRecordCount} records`)}catch(s){console.error("Error loading data:",s),u(`Error: ${s.message}`),le(s.message)}finally{e&&(t.isLoadingData=!1)}}var S={PNG:[137,80,78,71,13,10,26,10],JPEG:[255,216,255],GIF:[71,73,70,56],BMP:[66,77],RIFF:[82,73,70,70],WEBP:[87,69,66,80],PDF:[37,80,68,70,45],ID3:[73,68,51],MP3_SYNC1:[255,251],MP3_SYNC2:[255,243],MP3_SYNC3:[255,242],OGG:[79,103,103,83],WAVE:[87,65,86,69],FLAC:[102,76,97,67],FTYP:[102,116,121,112],WEBM:[26,69,223,163],AVI:[65,86,73,32]},ie=class{constructor(){this.currentObjectUrl=null,this.modal=document.getElementById("blob-inspector-modal"),this.previewContainer=document.getElementById("tab-preview"),this.hexContainer=document.querySelector(".hex-dump"),this.infoContainer=document.getElementById("blob-info"),this.currentData=null,this.currentType=null,this.currentRowId=null,this.currentColName=null,this.currentCellInfo=null,this.isUploading=!1,this.setupEventListeners()}setupEventListeners(){this.modal.querySelectorAll(".modal-close").forEach(l=>{l.addEventListener("click",()=>this.close())}),this.modal.querySelectorAll(".tab-btn").forEach(l=>{l.addEventListener("click",a=>{let s=a.target.dataset.tab;this.switchTab(s)})});let n=document.getElementById("blob-download-btn");n&&n.addEventListener("click",()=>this.download());let o=document.getElementById("blob-replace-btn");o&&o.addEventListener("click",()=>this.handleReplace())}setUploadState(n){this.isUploading=n;let o=document.getElementById("blob-replace-btn"),l=document.getElementById("blob-download-btn");o&&(o.disabled=n,o.textContent=n?"Uploading...":"Replace"),l&&(l.disabled=n)}async handleReplace(){if(!this.isUploading)try{if(((await C.getExtensionSettings())?.fileOperations||"native")==="web")this.showFileInput();else{let l=await C.selectFile();if(l){let a=l.data;if(!(a instanceof Uint8Array)){if(Array.isArray(a))a=new Uint8Array(a);else if(a&&typeof a=="object"){let i=Object.keys(a).filter(r=>!isNaN(parseInt(r,10))).sort((r,c)=>parseInt(r,10)-parseInt(c,10)).map(r=>a[r]);a=new Uint8Array(i)}}let s={name:l.name,arrayBuffer:async()=>a.buffer};await this.uploadFile(s)}}}catch(n){console.error("Replace failed:",n),u(`Replace failed: ${n.message}`)}}showFileInput(){let n=document.createElement("input");n.type="file",n.onchange=async o=>{let l=o.target.files[0];l&&await this.uploadFile(l)},n.click()}async uploadFile(n){if(!(!this.currentRowId||!this.currentColName)&&!this.isUploading){this.setUploadState(!0);try{u(`Reading ${n.name}...`);let o=await n.arrayBuffer(),l=new Uint8Array(o),a=l.length/(1024*1024),s=50;if(a>s)throw new Error(`File too large (${a.toFixed(1)}MB). Maximum size is ${s}MB to prevent freezing.`);a>10?u(`Uploading ${n.name} (${a.toFixed(1)}MB - this may take a moment)...`):u(`Uploading ${n.name}...`);let{rowIdx:i,colIdx:r}=this.currentCellInfo,c=this.currentData;await C.updateCell(t.selectedTable,this.currentRowId,this.currentColName,l,c),t.gridData&&t.gridData[i]&&(t.gridData[i][r+B()]=l),this.inspect(l,this.currentRowId,this.currentColName,i,r),u(`Replaced with ${n.name}`)}catch(o){console.error("Replace failed:",o);let l=o.message||String(o);l.includes("timeout")&&(l="Upload timed out. Try a smaller file or increase the timeout."),u(`Replace failed: ${l}`)}finally{this.setUploadState(!1)}}}close(){this.modal.classList.add("hidden"),this.cleanup()}cleanup(){this.setUploadState(!1),this.currentObjectUrl&&(URL.revokeObjectURL(this.currentObjectUrl),this.currentObjectUrl=null),this.previewContainer.innerHTML="",this.hexContainer.value="",this.infoContainer.textContent="",this.currentData=null}switchTab(n){this.modal.querySelectorAll(".tab-btn").forEach(a=>{a.dataset.tab===n?(a.classList.add("active"),a.style.borderBottom="2px solid var(--accent-color)",a.style.color="var(--text-primary)"):(a.classList.remove("active"),a.style.borderBottom="none",a.style.color="var(--text-secondary)")});let o=document.getElementById("tab-preview"),l=document.getElementById("tab-hex");n==="preview"?(o.style.display="flex",l.style.display="none"):(o.style.display="none",l.style.display="block")}async download(){if(!this.currentData)return;let n=this.currentType?.ext||"bin",o=`blob_${this.currentRowId}.${n}`;try{((await C.getExtensionSettings())?.fileOperations||"native")==="web"?(this.downloadBlob(this.currentData,o),u(`Downloaded ${o}`)):(await C.saveFile(o,this.currentData),u(`Saved ${o}`))}catch(l){console.error("Download failed:",l),u(`Download failed: ${l.message}`)}}downloadBlob(n,o){let l=new Blob([n]),a=URL.createObjectURL(l),s=document.createElement("a");s.href=a,s.download=o,s.click(),URL.revokeObjectURL(a)}inspect(n,o,l,a,s){this.cleanup(),this.currentRowId=o,this.currentColName=l,this.currentCellInfo={rowIdx:a,colIdx:s},this.modal.classList.remove("hidden"),this.switchTab("preview");let i=n instanceof Uint8Array?n:new Uint8Array(n);this.currentData=i;let r=this.detectType(i);this.currentType=r;let c=this.formatSize(i.length);this.infoContainer.textContent=`${l} (Row ${o}) | ${r.mime||"Unknown Type"} | ${c}`,this.renderPreview(i,r),this.renderHex(i)}detectType(n){if(this.checkSignature(n,S.PNG))return{mime:"image/png",type:"image",ext:"png"};if(this.checkSignature(n,S.JPEG))return{mime:"image/jpeg",type:"image",ext:"jpg"};if(this.checkSignature(n,S.GIF))return{mime:"image/gif",type:"image",ext:"gif"};if(this.checkSignature(n,S.BMP))return{mime:"image/bmp",type:"image",ext:"bmp"};if(this.checkSignature(n,S.RIFF)&&this.checkSignature(n.subarray(8),S.WEBP))return{mime:"image/webp",type:"image",ext:"webp"};if(this.checkSignature(n,S.PDF))return{mime:"application/pdf",type:"pdf",ext:"pdf"};if(this.checkSignature(n,S.ID3))return{mime:"audio/mpeg",type:"audio",ext:"mp3"};if(this.checkSignature(n,S.MP3_SYNC1)||this.checkSignature(n,S.MP3_SYNC2)||this.checkSignature(n,S.MP3_SYNC3))return{mime:"audio/mpeg",type:"audio",ext:"mp3"};if(this.checkSignature(n,S.OGG))return{mime:"audio/ogg",type:"audio",ext:"ogg"};if(this.checkSignature(n,S.RIFF)&&this.checkSignature(n.subarray(8),S.WAVE))return{mime:"audio/wav",type:"audio",ext:"wav"};if(this.checkSignature(n,S.FLAC))return{mime:"audio/flac",type:"audio",ext:"flac"};if(this.checkSignature(n.subarray(4),S.FTYP)){let o=String.fromCharCode(...n.subarray(8,12));return o.startsWith("mp4")||o==="isom"||o==="avc1"||o==="M4V "?{mime:"video/mp4",type:"video",ext:"mp4"}:o==="qt "||o.startsWith("M4A")?{mime:"video/quicktime",type:"video",ext:"mov"}:{mime:"video/mp4",type:"video",ext:"mp4"}}if(this.checkSignature(n,S.WEBM))return{mime:"video/webm",type:"video",ext:"webm"};if(this.checkSignature(n,S.RIFF)&&this.checkSignature(n.subarray(8),S.AVI))return{mime:"video/avi",type:"video",ext:"avi"};if(this.isText(n)){try{let o=new TextDecoder().decode(n),l=JSON.parse(o);if(typeof l=="object"&&l!==null)return{mime:"application/json",type:"json",ext:"json"}}catch{}return{mime:"text/plain",type:"text",ext:"txt"}}return{mime:"application/octet-stream",type:"binary",ext:"bin"}}checkSignature(n,o){if(n.lengththis.download()),l.appendChild(a),l.appendChild(s),l.appendChild(i),this.previewContainer.appendChild(l)}else{let l=document.createElement("div");l.className="empty-view";let a=document.createElement("span");a.className="codicon codicon-file-binary",a.style.fontSize="48px",a.style.opacity="0.5";let s=document.createElement("span");s.style.marginTop="12px",s.textContent="Binary Data";let i=document.createElement("span");i.style.fontSize="12px",i.style.opacity="0.7",i.textContent="Use Hex view to inspect",l.appendChild(a),l.appendChild(s),l.appendChild(i),this.previewContainer.appendChild(l)}}renderHex(n){if(!this.hexContainer)return;let o=16*1e3,l="",a=n.subarray(0,o);for(let s=0;s=32&&p<=126?String.fromCharCode(p):".")}else r.push(" "),c.push(" ");let d=r.slice(0,8).join(" "),m=r.slice(8).join(" "),h=c.join("");l+=`${i} ${d} ${m} |${h}| `}n.length>o&&(l+=` -... (${(n.length-o).toLocaleString()} more bytes not shown)`),this.hexContainer.value=l}formatSize(n){if(n===0)return"0 B";let o=1024,l=["B","KB","MB","GB"],a=Math.floor(Math.log(n)/Math.log(o));return parseFloat((n/Math.pow(o,a)).toFixed(2))+" "+l[a]}};var Ee;function Qe(){Ee=new ie,document.getElementById("btnCloseCellPreview")?.addEventListener("click",G),document.getElementById("formatJsonBtn")?.addEventListener("click",cn),document.getElementById("compactJsonBtn")?.addEventListener("click",dn),document.getElementById("wrapTextBtn")?.addEventListener("click",un),document.getElementById("openInVsCodeBtn")?.addEventListener("click",Ie),document.getElementById("btnCancelCellPreview")?.addEventListener("click",G),document.getElementById("cellPreviewSaveBtn")?.addEventListener("click",lt)}function Ze(e,n,o){if(t.selectedTableType!=="table"){u("Views are read-only");return}if(t.editingCellInfo){if(t.editingCellInfo.rowIdx===e&&t.editingCellInfo.colIdx===n)return;ce()}let l=t.tableColumns[n];if(!l)return;let a=document.getElementById(`cell-${e}-${n}`);if(!a)return;let s=t.gridData[e],i=P(s,n);if(i instanceof Uint8Array){H(e,n,o);return}if(typeof i=="string"){let d=i.trim();if(d.startsWith("{")&&d.endsWith("}")||d.startsWith("[")&&d.endsWith("]"))try{JSON.parse(d),H(e,n,o);return}catch{}}t.editingCellInfo={rowIdx:e,colIdx:n,rowId:o,columnName:l.name,originalValue:i};let r=i===null?"":String(i);a.innerHTML="",a.classList.add("editing");let c=document.createElement("textarea");c.className="cell-input",c.value=r,c.spellcheck=!1,a.appendChild(c),c.focus(),t.activeCellInput=c,c.addEventListener("keydown",et),c.addEventListener("blur",tt),c.addEventListener("click",d=>d.stopPropagation()),t.isTransitioningEdit=!0,setTimeout(()=>{t.isTransitioningEdit=!1},100)}function et(e){e.key==="Enter"&&!e.shiftKey?(e.preventDefault(),nt()):e.key==="Escape"&&(e.preventDefault(),ce())}function tt(){setTimeout(()=>{t.editingCellInfo&&nt()},100)}async function nt(){if(t.isSavingCell||!t.editingCellInfo||!t.activeCellInput)return;let{rowIdx:e,colIdx:n,rowId:o,columnName:l,originalValue:a}=t.editingCellInfo,s=t.activeCellInput.value,i=a===null?"":String(a);if(s===i){ce(),t.selectedCells=[],t.lastSelectedCell=null,F();return}let r=t.tableColumns[n],c=r&&r.notnull===1,d;s===""?c?d="":d=null:!isNaN(Number(s))&&s.trim()!==""?d=Number(s):d=s;try{t.isSavingCell=!0,u("Saving..."),await C.updateCell(t.selectedTable,oe(o),l,d,a),t.gridData[e][n+B()]=d,ot(),ve(e,n,d),t.selectedCells=[],t.lastSelectedCell=null,F(),u("Saved")}catch(m){console.error("Save failed:",m);let h=m.message||String(m);u(`Save failed: ${h}`)}finally{t.isSavingCell=!1}}function ce(){if(!t.editingCellInfo)return;let{rowIdx:e,colIdx:n,originalValue:o}=t.editingCellInfo;ot(),ve(e,n,o),se()}function ot(){t.activeCellInput&&(t.activeCellInput.removeEventListener("keydown",et),t.activeCellInput.removeEventListener("blur",tt),t.activeCellInput=null),t.editingCellInfo=null}async function Ie(){if(!t.cellPreviewInfo)return;let{rowIdx:e,colIdx:n,rowId:o,columnName:l,originalValue:a}=t.cellPreviewInfo,s=t.tableColumns[n],i=document.getElementById("vscode-env")?.dataset.webviewId||"default";try{u("Opening in VS Code..."),G(),await C.openCellEditor({table:t.selectedTable,name:""},oe(o),l,{},{value:a,type:{type:s.type},webviewId:i,rowCount:t.gridData.length}),u("Opened in VS Code")}catch(r){console.error("Failed to open in VS Code:",r),u(`Error: ${r.message}`)}}function H(e,n,o){t.editingCellInfo&&ce();let l=t.tableColumns[n];if(!l)return;let a=t.gridData[e];if(!a)return;let s=P(a,n);if(s instanceof Uint8Array){Ee&&Ee.inspect(s,o,l.name,e,n);return}t.cellPreviewInfo={rowIdx:e,colIdx:n,rowId:o,columnName:l.name,originalValue:s};let i=document.getElementById("cellPreviewModal"),r=document.getElementById("cellPreviewColumnName"),c=document.getElementById("cellPreviewTypeBadge"),d=document.getElementById("cellPreviewTextarea"),m=document.getElementById("cellPreviewReadonlyBadge"),h=document.getElementById("cellPreviewSaveBtn"),f=document.getElementById("wrapTextBtn");r.textContent=l.name,c.textContent=l.type||"TEXT";let p="";s==null?p="":s instanceof Uint8Array?p="[BLOB: "+Array.from(s).map(w=>w.toString(16).padStart(2,"0")).join(" ")+"]":p=String(s),d.value=p;let g=t.selectedTableType!=="table";d.readOnly=g,g?(d.classList.add("readonly"),m.style.display="inline",h.style.display="none"):(d.classList.remove("readonly"),m.style.display="none",h.style.display="inline-block"),re(),d.style.whiteSpace=t.cellPreviewWrapEnabled?"pre-wrap":"pre",d.style.overflowX=t.cellPreviewWrapEnabled?"hidden":"auto",f.classList.toggle("active",t.cellPreviewWrapEnabled),i.classList.remove("hidden"),d.focus(),d.oninput=re,d.onkeydown=w=>{w.key==="Escape"?(w.preventDefault(),G()):w.key==="Enter"&&(w.ctrlKey||w.metaKey)&&(w.preventDefault(),lt())}}function re(){let e=document.getElementById("cellPreviewTextarea"),n=document.getElementById("cellPreviewCharCount"),o=e.value.length;n.textContent=`${o.toLocaleString()} character${o!==1?"s":""}`}function G(){document.getElementById("cellPreviewModal").classList.add("hidden"),t.cellPreviewInfo=null}async function lt(){if(!t.cellPreviewInfo)return;if(t.selectedTableType!=="table"){u("Views are read-only");return}let{rowIdx:e,colIdx:n,rowId:o,columnName:l,originalValue:a}=t.cellPreviewInfo,i=document.getElementById("cellPreviewTextarea").value,r=a===null?"":String(a);if(i===r){G(),t.selectedCells=[],t.lastSelectedCell=null,F();return}let c=t.tableColumns[n],d=c&&c.notnull===1,m;i===""?m=d?"":null:!isNaN(Number(i))&&i.trim()!==""?m=Number(i):m=i;try{u("Saving..."),await C.updateCell(t.selectedTable,oe(o),l,m,a),t.gridData[e][n+B()]=m,G(),ve(e,n,m),t.selectedCells=[],t.lastSelectedCell=null,F(),u("Saved")}catch(h){console.error("Save failed:",h),u(`Save failed: ${h.message}`)}}function cn(){let e=document.getElementById("cellPreviewTextarea");try{let n=JSON.parse(e.value);e.value=JSON.stringify(n,null,2),re()}catch{u("Content is not valid JSON")}}function dn(){let e=document.getElementById("cellPreviewTextarea");try{let n=JSON.parse(e.value);e.value=JSON.stringify(n),re()}catch{u("Content is not valid JSON")}}function un(){t.cellPreviewWrapEnabled=!t.cellPreviewWrapEnabled;let e=document.getElementById("cellPreviewTextarea"),n=document.getElementById("wrapTextBtn");e.style.whiteSpace=t.cellPreviewWrapEnabled?"pre-wrap":"pre",e.style.overflowX=t.cellPreviewWrapEnabled?"hidden":"auto",n.classList.toggle("active",t.cellPreviewWrapEnabled)}function ve(e,n,o){let l=document.getElementById(`cell-${e}-${n}`);if(!l)return;l.classList.remove("editing"),o==null?l.classList.add("null-value"):l.classList.remove("null-value");let a=t.tableColumns[n],s=K(o,a?.type,t.dateFormat,a?.name),i=o!=null&&!(o instanceof Uint8Array);l.textContent="";let r=document.createElement("span");if(r.className="cell-text",r.textContent=s,l.appendChild(r),i){let d=document.createElement("span");d.className="expand-icon codicon codicon-link-external",d.title="View full content",l.appendChild(d)}let c=r.scrollWidth>r.clientWidth;l.classList.toggle("has-overflow",c)}function at(){clearTimeout(t.filterTimer),t.filterTimer=setTimeout(()=>{t.filterQuery=document.getElementById("filterInput").value,t.currentPageIndex=0,I(),$()},300)}function st(){t.rowsPerPage=parseInt(document.getElementById("pageSizeSelect").value,10),t.currentPageIndex=0,I(),$()}function it(){let e=document.getElementById("dateFormatSelect");e&&(t.dateFormat=e.value,_(),$())}function ee(e){e>=0&&el.name===n);if(o!==-1){if((e.shiftKey||e.metaKey||e.ctrlKey)&&e.preventDefault(),t.selectedRowIds.clear(),e.shiftKey&&t.lastSelectedColumnIndex!==null){e.metaKey||e.ctrlKey||(t.selectedCells=[],t.selectedColumns.clear());let l=Math.min(t.lastSelectedColumnIndex,o),a=Math.max(t.lastSelectedColumnIndex,o),s=new Array;if(t.selectedCells.length>0)for(let i of t.selectedCells)i.colIdx>=l&&i.colIdx<=a&&(s[i.rowIdx]||(s[i.rowIdx]=new Set),s[i.rowIdx].add(i.colIdx));for(let i=l;i<=a;i++){let r=t.tableColumns[i].name;t.selectedColumns.add(r);for(let c=0;c0&&a===l)t.selectedCells=t.selectedCells.filter(i=>i.colIdx!==o),t.selectedColumns.delete(n);else{let i=new Set;for(let r of t.selectedCells)r.colIdx===o&&i.add(r.rowIdx);for(let r=0;r0&&a===l&&t.selectedColumns.size===1&&t.selectedColumns.has(n))t.selectedCells=[],t.selectedColumns.clear(),t.lastSelectedColumnIndex=null;else{t.selectedCells=[],t.selectedColumns.clear();for(let i=0;ii.name===t.resizingColumn);if(l===-1)return;let a=document.querySelector(`th[data-column="${t.resizingColumn}"]`);a&&(a.style.width=`${o}px`,a.style.minWidth=`${o}px`,a.style.maxWidth=`${o}px`);let s=document.querySelectorAll(`.data-row td:nth-child(${l+2})`);for(let i of s)i.style.width=`${o}px`,i.style.minWidth=`${o}px`,i.style.maxWidth=`${o}px`;t.pinnedColumns.has(t.resizingColumn)}function gt(){if(!t.resizingColumn)return;let e=document.querySelector(".resize-handle.resizing");e&&e.classList.remove("resizing"),t.resizingColumn=null,document.removeEventListener("mousemove",ft),document.removeEventListener("mouseup",gt),document.body.style.userSelect="",document.body.style.cursor="",_()}function ht(e,n,o){if(e.stopPropagation(),(e.shiftKey||e.metaKey||e.ctrlKey)&&e.preventDefault(),t.selectedCells=[],t.lastSelectedCell=null,t.selectedColumns.clear(),e.shiftKey&&t.lastSelectedRowIndex!==null){e.metaKey||e.ctrlKey||t.selectedRowIds.clear();let l=Math.min(t.lastSelectedRowIndex,o),a=Math.max(t.lastSelectedRowIndex,o);for(let s=l;s<=a;s++){let i=T(t.gridData[s],s);t.selectedRowIds.add(i)}}else e.ctrlKey||e.metaKey?(t.selectedRowIds.has(n)?t.selectedRowIds.delete(n):t.selectedRowIds.add(n),t.lastSelectedRowIndex=o):t.selectedRowIds.has(n)&&t.selectedRowIds.size===1?(t.selectedRowIds.delete(n),t.lastSelectedRowIndex=null):(t.selectedRowIds.clear(),t.selectedRowIds.add(n),t.lastSelectedRowIndex=o);F(),R(),j()}function de(e){if(e.stopPropagation(),t.gridData.length===0)return;t.selectedCells=[],t.lastSelectedCell=null,t.selectedColumns.clear();let n=!0;for(let o=0;o=s&&m.rowIdx<=i&&m.colIdx>=r&&m.colIdx<=c&&(d[m.rowIdx]||(d[m.rowIdx]=new Set),d[m.rowIdx].add(m.colIdx));for(let m=s;m<=i;m++){let h=d[m];for(let f=r;f<=c;f++)if(!h||!h.has(f)){let p=T(t.gridData[m],m),g=P(t.gridData[m],f);t.selectedCells.push({rowIdx:m,colIdx:f,rowId:p,value:g})}}}else if(e.metaKey||e.ctrlKey){e.preventDefault(),t.selectedRowIds.clear();let s=t.selectedCells.findIndex(i=>i.rowIdx===n&&i.colIdx===o);s>=0?t.selectedCells.splice(s,1):(t.selectedCells.push({rowIdx:n,colIdx:o,rowId:l,value:a}),t.lastSelectedCell={rowIdx:n,colIdx:o})}else if(e.shiftKey&&t.lastSelectedCell){e.preventDefault(),t.selectedRowIds.clear(),t.selectedCells=[];let s=Math.min(t.lastSelectedCell.rowIdx,n),i=Math.max(t.lastSelectedCell.rowIdx,n),r=Math.min(t.lastSelectedCell.colIdx,o),c=Math.max(t.lastSelectedCell.colIdx,o);for(let d=s;d<=i;d++)for(let m=r;m<=c;m++){let h=T(t.gridData[d],d),f=P(t.gridData[d],m);t.selectedCells.push({rowIdx:d,colIdx:m,rowId:h,value:f})}}else t.selectedRowIds.clear(),t.selectedCells=[{rowIdx:n,colIdx:o,rowId:l,value:a}],t.lastSelectedCell={rowIdx:n,colIdx:o},t.selectedColumns.clear();F(),R(),j()}function Ct(e,n,o,l){if(t.cellEditBehavior==="vscode"){let a=t.tableColumns[o];if(!a)return;let s=t.gridData[n];if(!s)return;let i=P(s,o);t.cellPreviewInfo={rowIdx:n,colIdx:o,rowId:l,columnName:a.name,originalValue:i},Ie()}else t.cellEditBehavior==="modal"?H(n,o,l):Ze(n,o,l)}function xt(){document.getElementById("filterInput")?.addEventListener("keyup",at),document.getElementById("pageSizeSelect")?.addEventListener("change",st),document.getElementById("dateFormatSelect")?.addEventListener("change",it),document.getElementById("btnFirst")?.addEventListener("click",()=>ee(0)),document.getElementById("btnPrev")?.addEventListener("click",()=>ee(t.currentPageIndex-1)),document.getElementById("btnNext")?.addEventListener("click",()=>ee(t.currentPageIndex+1)),document.getElementById("btnLast")?.addEventListener("click",()=>ee(t.totalPageCount-1))}function bt(){let e=document.getElementById("gridContainer");e&&(e.addEventListener("mousedown",mn),e.addEventListener("keydown",pn),e.addEventListener("click",fn),e.addEventListener("dblclick",yn),e.addEventListener("mouseover",Cn),e.addEventListener("scroll",xn,{passive:!0}))}function mn(e){if(e.target.classList.contains("resize-handle")){e.stopPropagation();let n=e.target.closest(".header-cell");n&&n.dataset.column&&pt(e,n.dataset.column)}}function pn(e){if(e.target.classList.contains("column-filter")){let n=e.target.dataset.column;n&&ct(e,n)}}function fn(e){let n=e.target;if(n.closest(".grid-header")){gn(e,n);return}hn(e,n)}function gn(e,n){if(n.closest(".filter-apply-btn")){e.stopPropagation();let l=n.closest(".header-cell");l&&l.dataset.column&&Se(l.dataset.column);return}if(n.closest(".header-bottom")||n.closest(".column-filter")){e.stopPropagation();return}if(n.closest(".select-column-icon")){e.stopPropagation();let l=n.closest(".header-cell");l&&l.dataset.column&&dt(e,l.dataset.column);return}if(n.closest(".pin-icon")){e.stopPropagation();let l=n.closest(".header-cell");l&&l.dataset.column&&ut(e,l.dataset.column);return}if(n.closest(".row-number-header")){de(e);return}let o=n.closest(".header-top");if(o){let l=o.closest(".header-cell");l&&l.dataset.column&&rt(l.dataset.column);return}}function hn(e,n){if(n.closest(".pin-icon")){let l=n.closest(".data-row");if(l){let a=l.dataset.rowid,s=te(a);mt(e,s)}return}if(n.closest(".expand-icon")){let l=n.closest(".data-cell");if(l){let a=parseInt(l.dataset.rowidx,10),s=parseInt(l.dataset.colidx,10),i=te(l.closest(".data-row").dataset.rowid);H(a,s,i)}return}if(n.closest(".row-number")){let l=n.closest(".data-row");if(l){let a=te(l.dataset.rowid),s=parseInt(l.dataset.rowidx,10);ht(e,a,s)}return}let o=n.closest(".data-cell");if(o){let l=parseInt(o.dataset.rowidx,10),a=parseInt(o.dataset.colidx,10),s=o.closest(".data-row"),i=te(s.dataset.rowid);yt(e,l,a,i);return}}function yn(e){let n=e.target.closest(".data-cell");if(n&&!n.classList.contains("row-number")){let o=parseInt(n.dataset.rowidx,10),l=parseInt(n.dataset.colidx,10),a=n.closest(".data-row"),s=te(a.dataset.rowid);Ct(e,o,l,s)}}function Cn(e){let n=e.target.closest(".data-cell");if(n&&!n.classList.contains("checked-overflow")){let o=n.querySelector(".cell-text");if(o){let l=o.scrollWidth>o.clientWidth;n.classList.toggle("has-overflow",l),n.classList.add("checked-overflow")}}}function xn(e){let n=e.currentTarget;t.scrollPosition.left=n.scrollLeft,t.scrollPosition.top=n.scrollTop,$()}function te(e){if(e==null)return e;let n=Number(e);return!isNaN(n)&&e.trim()!==""?n:e}var wt={async refreshContent(e){return t.isDbConnected&&(await V(),!(t.schemaCache.tables.some(o=>o.name===t.selectedTable)||t.schemaCache.views.some(o=>o.name===t.selectedTable))&&t.selectedTable?(t.selectedTable=null,t.selectedTableType=null,document.getElementById("tableNameLabel").textContent="No table selected",document.getElementById("gridContainer").innerHTML=` +... (${(n.length-o).toLocaleString()} more bytes not shown)`),this.hexContainer.value=l}formatSize(n){if(n===0)return"0 B";let o=1024,l=["B","KB","MB","GB"],a=Math.floor(Math.log(n)/Math.log(o));return parseFloat((n/Math.pow(o,a)).toFixed(2))+" "+l[a]}};var Ee;function Qe(){Ee=new ie,document.getElementById("btnCloseCellPreview")?.addEventListener("click",G),document.getElementById("formatJsonBtn")?.addEventListener("click",cn),document.getElementById("compactJsonBtn")?.addEventListener("click",dn),document.getElementById("wrapTextBtn")?.addEventListener("click",un),document.getElementById("openInVsCodeBtn")?.addEventListener("click",Ie),document.getElementById("btnCancelCellPreview")?.addEventListener("click",G),document.getElementById("cellPreviewSaveBtn")?.addEventListener("click",lt)}function Ze(e,n,o){if(t.selectedTableType!=="table"){u("Views are read-only");return}if(t.editingCellInfo){if(t.editingCellInfo.rowIdx===e&&t.editingCellInfo.colIdx===n)return;ce()}let l=t.tableColumns[n];if(!l)return;let a=document.getElementById(`cell-${e}-${n}`);if(!a)return;let s=t.gridData[e],i=P(s,n);if(i instanceof Uint8Array){H(e,n,o);return}if(typeof i=="string"){let d=i.trim();if(d.startsWith("{")&&d.endsWith("}")||d.startsWith("[")&&d.endsWith("]"))try{JSON.parse(d),H(e,n,o);return}catch{}}t.editingCellInfo={rowIdx:e,colIdx:n,rowId:o,columnName:l.name,originalValue:i};let r=i===null?"":String(i);a.innerHTML="",a.classList.add("editing");let c=document.createElement("textarea");c.className="cell-input",c.value=r,c.spellcheck=!1,a.appendChild(c),c.focus(),t.activeCellInput=c,c.addEventListener("keydown",et),c.addEventListener("blur",tt),c.addEventListener("click",d=>d.stopPropagation()),t.isTransitioningEdit=!0,setTimeout(()=>{t.isTransitioningEdit=!1},100)}function et(e){e.key==="Enter"&&!e.shiftKey?(e.preventDefault(),nt()):e.key==="Escape"&&(e.preventDefault(),ce())}function tt(){setTimeout(()=>{t.editingCellInfo&&nt()},100)}async function nt(){if(t.isSavingCell||!t.editingCellInfo||!t.activeCellInput)return;let{rowIdx:e,colIdx:n,rowId:o,columnName:l,originalValue:a}=t.editingCellInfo,s=t.activeCellInput.value,i=a===null?"":String(a);if(s===i){ce(),t.selectedCells=[],t.lastSelectedCell=null,F();return}let r=t.tableColumns[n],c=r&&r.notnull===1,d;s===""?c?d="":d=null:!isNaN(Number(s))&&s.trim()!==""?d=Number(s):d=s;try{t.isSavingCell=!0,u("Saving..."),await C.updateCell(t.selectedTable,oe(o),l,d,a),t.gridData[e][n+B()]=d,ot(),ve(e,n,d),t.selectedCells=[],t.lastSelectedCell=null,F(),u("Saved")}catch(m){console.error("Save failed:",m);let h=m.message||String(m);u(`Save failed: ${h}`)}finally{t.isSavingCell=!1}}function ce(){if(!t.editingCellInfo)return;let{rowIdx:e,colIdx:n,originalValue:o}=t.editingCellInfo;ot(),ve(e,n,o),se()}function ot(){t.activeCellInput&&(t.activeCellInput.removeEventListener("keydown",et),t.activeCellInput.removeEventListener("blur",tt),t.activeCellInput=null),t.editingCellInfo=null}async function Ie(){if(!t.cellPreviewInfo)return;let{rowIdx:e,colIdx:n,rowId:o,columnName:l,originalValue:a}=t.cellPreviewInfo,s=t.tableColumns[n],i=document.getElementById("vscode-env")?.dataset.webviewId||"default";try{u("Opening in VS Code..."),G(),await C.openCellEditor({table:t.selectedTable,name:""},oe(o),l,{},{value:a,type:{type:s.type},webviewId:i,rowCount:t.gridData.length}),u("Opened in VS Code")}catch(r){console.error("Failed to open in VS Code:",r),u(`Error: ${r.message}`)}}function H(e,n,o){t.editingCellInfo&&ce();let l=t.tableColumns[n];if(!l)return;let a=t.gridData[e];if(!a)return;let s=P(a,n);if(s instanceof Uint8Array){Ee&&Ee.inspect(s,o,l.name,e,n);return}t.cellPreviewInfo={rowIdx:e,colIdx:n,rowId:o,columnName:l.name,originalValue:s};let i=document.getElementById("cellPreviewModal"),r=document.getElementById("cellPreviewColumnName"),c=document.getElementById("cellPreviewTypeBadge"),d=document.getElementById("cellPreviewTextarea"),m=document.getElementById("cellPreviewReadonlyBadge"),h=document.getElementById("cellPreviewSaveBtn"),f=document.getElementById("wrapTextBtn");r.textContent=l.name,c.textContent=l.type||"TEXT";let p="";s==null?p="":s instanceof Uint8Array?p="[BLOB: "+Array.from(s).map(w=>w.toString(16).padStart(2,"0")).join(" ")+"]":p=String(s),d.value=p;let g=t.selectedTableType!=="table";d.readOnly=g,g?(d.classList.add("readonly"),m.style.display="inline",h.style.display="none"):(d.classList.remove("readonly"),m.style.display="none",h.style.display="inline-block"),re(),d.style.whiteSpace=t.cellPreviewWrapEnabled?"pre-wrap":"pre",d.style.overflowX=t.cellPreviewWrapEnabled?"hidden":"auto",f.classList.toggle("active",t.cellPreviewWrapEnabled),i.classList.remove("hidden"),d.focus(),d.oninput=re,d.onkeydown=w=>{w.key==="Escape"?(w.preventDefault(),G()):w.key==="Enter"&&(w.ctrlKey||w.metaKey)&&(w.preventDefault(),lt())}}function re(){let e=document.getElementById("cellPreviewTextarea"),n=document.getElementById("cellPreviewCharCount"),o=e.value.length;n.textContent=`${o.toLocaleString()} character${o!==1?"s":""}`}function G(){document.getElementById("cellPreviewModal").classList.add("hidden"),t.cellPreviewInfo=null}async function lt(){if(!t.cellPreviewInfo)return;if(t.selectedTableType!=="table"){u("Views are read-only");return}let{rowIdx:e,colIdx:n,rowId:o,columnName:l,originalValue:a}=t.cellPreviewInfo,i=document.getElementById("cellPreviewTextarea").value,r=a===null?"":String(a);if(i===r){G(),t.selectedCells=[],t.lastSelectedCell=null,F();return}let c=t.tableColumns[n],d=c&&c.notnull===1,m;i===""?m=d?"":null:!isNaN(Number(i))&&i.trim()!==""?m=Number(i):m=i;try{u("Saving..."),await C.updateCell(t.selectedTable,oe(o),l,m,a),t.gridData[e][n+B()]=m,G(),ve(e,n,m),t.selectedCells=[],t.lastSelectedCell=null,F(),u("Saved")}catch(h){console.error("Save failed:",h),u(`Save failed: ${h.message}`)}}function cn(){let e=document.getElementById("cellPreviewTextarea");try{let n=JSON.parse(e.value);e.value=JSON.stringify(n,null,2),re()}catch{u("Content is not valid JSON")}}function dn(){let e=document.getElementById("cellPreviewTextarea");try{let n=JSON.parse(e.value);e.value=JSON.stringify(n),re()}catch{u("Content is not valid JSON")}}function un(){t.cellPreviewWrapEnabled=!t.cellPreviewWrapEnabled;let e=document.getElementById("cellPreviewTextarea"),n=document.getElementById("wrapTextBtn");e.style.whiteSpace=t.cellPreviewWrapEnabled?"pre-wrap":"pre",e.style.overflowX=t.cellPreviewWrapEnabled?"hidden":"auto",n.classList.toggle("active",t.cellPreviewWrapEnabled)}function ve(e,n,o){let l=document.getElementById(`cell-${e}-${n}`);if(!l)return;l.classList.remove("editing"),o==null?l.classList.add("null-value"):l.classList.remove("null-value");let a=t.tableColumns[n],s=K(o,a?.type,t.dateFormat,a?.name),i=o!=null&&!(o instanceof Uint8Array);l.textContent="";let r=document.createElement("span");if(r.className="cell-text",r.textContent=s,l.appendChild(r),i){let d=document.createElement("span");d.className="expand-icon codicon codicon-link-external",d.title="View full content",l.appendChild(d)}let c=r.scrollWidth>r.clientWidth;l.classList.toggle("has-overflow",c)}function at(){clearTimeout(t.filterTimer),t.filterTimer=setTimeout(()=>{t.filterQuery=document.getElementById("filterInput").value,t.currentPageIndex=0,I(),$()},300)}function st(){t.rowsPerPage=parseInt(document.getElementById("pageSizeSelect").value,10),t.currentPageIndex=0,I(),$()}function it(){let e=document.getElementById("dateFormatSelect");e&&(t.dateFormat=e.value,_(),$())}function ee(e){e>=0&&el.name===n);if(o!==-1){if((e.shiftKey||e.metaKey||e.ctrlKey)&&e.preventDefault(),t.selectedRowIds.clear(),e.shiftKey&&t.lastSelectedColumnIndex!==null){e.metaKey||e.ctrlKey||(t.selectedCells=[],t.selectedColumns.clear());let l=Math.min(t.lastSelectedColumnIndex,o),a=Math.max(t.lastSelectedColumnIndex,o),s=new Array;if(t.selectedCells.length>0)for(let i of t.selectedCells)i.colIdx>=l&&i.colIdx<=a&&(s[i.rowIdx]||(s[i.rowIdx]=new Set),s[i.rowIdx].add(i.colIdx));for(let i=l;i<=a;i++){let r=t.tableColumns[i].name;t.selectedColumns.add(r);for(let c=0;c0&&a===l)t.selectedCells=t.selectedCells.filter(i=>i.colIdx!==o),t.selectedColumns.delete(n);else{let i=new Set;for(let r of t.selectedCells)r.colIdx===o&&i.add(r.rowIdx);for(let r=0;r0&&a===l&&t.selectedColumns.size===1&&t.selectedColumns.has(n))t.selectedCells=[],t.selectedColumns.clear(),t.lastSelectedColumnIndex=null;else{t.selectedCells=[],t.selectedColumns.clear();for(let i=0;ii.name===t.resizingColumn);if(l===-1)return;let a=document.querySelector(`th[data-column="${t.resizingColumn}"]`);a&&(a.style.width=`${o}px`,a.style.minWidth=`${o}px`,a.style.maxWidth=`${o}px`);let s=document.querySelectorAll(`.data-row td:nth-child(${l+2})`);for(let i of s)i.style.width=`${o}px`,i.style.minWidth=`${o}px`,i.style.maxWidth=`${o}px`;t.pinnedColumns.has(t.resizingColumn)}function gt(){if(!t.resizingColumn)return;let e=document.querySelector(".resize-handle.resizing");e&&e.classList.remove("resizing"),t.resizingColumn=null,document.removeEventListener("mousemove",ft),document.removeEventListener("mouseup",gt),document.body.style.userSelect="",document.body.style.cursor="",_()}function ht(e,n,o){if(e.stopPropagation(),(e.shiftKey||e.metaKey||e.ctrlKey)&&e.preventDefault(),t.selectedCells=[],t.lastSelectedCell=null,t.selectedColumns.clear(),e.shiftKey&&t.lastSelectedRowIndex!==null){e.metaKey||e.ctrlKey||t.selectedRowIds.clear();let l=Math.min(t.lastSelectedRowIndex,o),a=Math.max(t.lastSelectedRowIndex,o);for(let s=l;s<=a;s++){let i=T(t.gridData[s],s);t.selectedRowIds.add(i)}}else e.ctrlKey||e.metaKey?(t.selectedRowIds.has(n)?t.selectedRowIds.delete(n):t.selectedRowIds.add(n),t.lastSelectedRowIndex=o):t.selectedRowIds.has(n)&&t.selectedRowIds.size===1?(t.selectedRowIds.delete(n),t.lastSelectedRowIndex=null):(t.selectedRowIds.clear(),t.selectedRowIds.add(n),t.lastSelectedRowIndex=o);F(),R(),j()}function de(e){if(e.stopPropagation(),t.gridData.length===0)return;t.selectedCells=[],t.lastSelectedCell=null,t.selectedColumns.clear();let n=!0;for(let o=0;o=s&&m.rowIdx<=i&&m.colIdx>=r&&m.colIdx<=c&&(d[m.rowIdx]||(d[m.rowIdx]=new Set),d[m.rowIdx].add(m.colIdx));for(let m=s;m<=i;m++){let h=d[m];for(let f=r;f<=c;f++)if(!h||!h.has(f)){let p=T(t.gridData[m],m),g=P(t.gridData[m],f);t.selectedCells.push({rowIdx:m,colIdx:f,rowId:p,value:g})}}}else if(e.metaKey||e.ctrlKey){e.preventDefault(),t.selectedRowIds.clear();let s=t.selectedCells.findIndex(i=>i.rowIdx===n&&i.colIdx===o);s>=0?t.selectedCells.splice(s,1):(t.selectedCells.push({rowIdx:n,colIdx:o,rowId:l,value:a}),t.lastSelectedCell={rowIdx:n,colIdx:o})}else if(e.shiftKey&&t.lastSelectedCell){e.preventDefault(),t.selectedRowIds.clear(),t.selectedCells=[];let s=Math.min(t.lastSelectedCell.rowIdx,n),i=Math.max(t.lastSelectedCell.rowIdx,n),r=Math.min(t.lastSelectedCell.colIdx,o),c=Math.max(t.lastSelectedCell.colIdx,o);for(let d=s;d<=i;d++)for(let m=r;m<=c;m++){let h=T(t.gridData[d],d),f=P(t.gridData[d],m);t.selectedCells.push({rowIdx:d,colIdx:m,rowId:h,value:f})}}else t.selectedRowIds.clear(),t.selectedCells=[{rowIdx:n,colIdx:o,rowId:l,value:a}],t.lastSelectedCell={rowIdx:n,colIdx:o},t.selectedColumns.clear();F(),R(),j()}function Ct(e,n,o,l){if(t.cellEditBehavior==="vscode"){let a=t.tableColumns[o];if(!a)return;let s=t.gridData[n];if(!s)return;let i=P(s,o);t.cellPreviewInfo={rowIdx:n,colIdx:o,rowId:l,columnName:a.name,originalValue:i},Ie()}else t.cellEditBehavior==="modal"?H(n,o,l):Ze(n,o,l)}function xt(){document.getElementById("filterInput")?.addEventListener("keyup",at),document.getElementById("pageSizeSelect")?.addEventListener("change",st),document.getElementById("dateFormatSelect")?.addEventListener("change",it),document.getElementById("btnFirst")?.addEventListener("click",()=>ee(0)),document.getElementById("btnPrev")?.addEventListener("click",()=>ee(t.currentPageIndex-1)),document.getElementById("btnNext")?.addEventListener("click",()=>ee(t.currentPageIndex+1)),document.getElementById("btnLast")?.addEventListener("click",()=>ee(t.totalPageCount-1))}function bt(){let e=document.getElementById("gridContainer");e&&(e.addEventListener("mousedown",mn),e.addEventListener("keydown",pn),e.addEventListener("click",fn),e.addEventListener("dblclick",yn),e.addEventListener("mouseover",Cn),e.addEventListener("scroll",xn,{passive:!0}))}function mn(e){if(e.target.classList.contains("resize-handle")){e.stopPropagation();let n=e.target.closest(".header-cell");n&&n.dataset.column&&pt(e,n.dataset.column)}}function pn(e){if(!t.isLoadingData&&e.target.classList.contains("column-filter")){let n=e.target.dataset.column;n&&ct(e,n)}}function fn(e){if(t.isLoadingData)return;let n=e.target;if(n.closest(".grid-header")){gn(e,n);return}hn(e,n)}function gn(e,n){if(n.closest(".filter-apply-btn")){e.stopPropagation();let l=n.closest(".header-cell");l&&l.dataset.column&&Se(l.dataset.column);return}if(n.closest(".header-bottom")||n.closest(".column-filter")){e.stopPropagation();return}if(n.closest(".select-column-icon")){e.stopPropagation();let l=n.closest(".header-cell");l&&l.dataset.column&&dt(e,l.dataset.column);return}if(n.closest(".pin-icon")){e.stopPropagation();let l=n.closest(".header-cell");l&&l.dataset.column&&ut(e,l.dataset.column);return}if(n.closest(".row-number-header")){de(e);return}let o=n.closest(".header-top");if(o){let l=o.closest(".header-cell");l&&l.dataset.column&&rt(l.dataset.column);return}}function hn(e,n){if(n.closest(".pin-icon")){let l=n.closest(".data-row");if(l){let a=l.dataset.rowid,s=te(a);mt(e,s)}return}if(n.closest(".expand-icon")){let l=n.closest(".data-cell");if(l){let a=parseInt(l.dataset.rowidx,10),s=parseInt(l.dataset.colidx,10),i=te(l.closest(".data-row").dataset.rowid);H(a,s,i)}return}if(n.closest(".row-number")){let l=n.closest(".data-row");if(l){let a=te(l.dataset.rowid),s=parseInt(l.dataset.rowidx,10);ht(e,a,s)}return}let o=n.closest(".data-cell");if(o){let l=parseInt(o.dataset.rowidx,10),a=parseInt(o.dataset.colidx,10),s=o.closest(".data-row"),i=te(s.dataset.rowid);yt(e,l,a,i);return}}function yn(e){if(t.isLoadingData)return;let n=e.target.closest(".data-cell");if(n&&!n.classList.contains("row-number")){let o=parseInt(n.dataset.rowidx,10),l=parseInt(n.dataset.colidx,10),a=n.closest(".data-row"),s=te(a.dataset.rowid);Ct(e,o,l,s)}}function Cn(e){let n=e.target.closest(".data-cell");if(n&&!n.classList.contains("checked-overflow")){let o=n.querySelector(".cell-text");if(o){let l=o.scrollWidth>o.clientWidth;n.classList.toggle("has-overflow",l),n.classList.add("checked-overflow")}}}function xn(e){let n=e.currentTarget;t.scrollPosition.left=n.scrollLeft,t.scrollPosition.top=n.scrollTop,$()}function te(e){if(e==null)return e;let n=Number(e);return!isNaN(n)&&e.trim()!==""?n:e}var wt={async refreshContent(e){return t.isDbConnected&&(await V(),!(t.schemaCache.tables.some(o=>o.name===t.selectedTable)||t.schemaCache.views.some(o=>o.name===t.selectedTable))&&t.selectedTable?(t.selectedTable=null,t.selectedTableType=null,document.getElementById("tableNameLabel").textContent="No table selected",document.getElementById("gridContainer").innerHTML=`
Select a table diff --git a/website/public/sqlite-viewer/viewer.html b/website/public/sqlite-viewer/viewer.html index b85beb12..604a8628 100644 --- a/website/public/sqlite-viewer/viewer.html +++ b/website/public/sqlite-viewer/viewer.html @@ -364,7 +364,7 @@
From 07039bf192f2e6f3ca6e783354b9918902d03ec1 Mon Sep 17 00:00:00 2001 From: zknpr Date: Sun, 21 Jun 2026 21:36:28 +0200 Subject: [PATCH 5/9] fix: guard loadTableData against overlapping loads (Codex P2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Concurrent loadTableData() calls (a slow fetch followed by a filter/ sort/page change or a table switch via toolbar controls the grid guard doesn't cover) could mix state across requests: - A table switch mid-fetch paired the old table's snapshotted columns with the new table name in fetchTableData → SELECT old columns against the new table → error view (P2 #1). - The single isLoadingData boolean was cleared by whichever overlapping load finished first, re-enabling clicks on soon-to-be-replaced rows while a newer load was still pending (P2 #2). Add a monotonic activeLoadToken: snapshot the requested table/type for the whole request, bail after each await if a newer load superseded this one (no state write, render, or stale error), and only let the latest load clear isLoadingData. Regenerated viewer.html bundles. Co-Authored-By: Claude Opus 4.8 (1M context) --- core/ui/modules/grid-data.js | 37 +++++++++++++++++++----- core/ui/viewer.html | 26 ++++++++--------- website/public/sqlite-viewer/viewer.html | 24 +++++++-------- 3 files changed, 55 insertions(+), 32 deletions(-) diff --git a/core/ui/modules/grid-data.js b/core/ui/modules/grid-data.js index eb2894d0..c8ba9fc6 100644 --- a/core/ui/modules/grid-data.js +++ b/core/ui/modules/grid-data.js @@ -38,9 +38,24 @@ export async function loadTableColumns() { } } +// Monotonic token identifying the most recent loadTableData() call. Concurrent +// loads (e.g. a slow fetch followed by a filter/sort/page change or a table +// switch, triggered via toolbar controls the grid guard doesn't cover) compare +// this after each await and bail if a newer load has started — so a superseded +// request never writes state, renders stale rows, shows a stale error, or clears +// the loading flag out from under the in-flight one. +let activeLoadToken = 0; + export async function loadTableData(showSpinner = true, saveScrollPosition = true) { if (!state.selectedTable) return; + const loadToken = ++activeLoadToken; + // Snapshot the target table/type for the whole request so an in-flight load + // can't pair this table's columns with a table the user switched to mid-fetch + // (which would SELECT the old columns against the new table and error out). + const requestedTable = state.selectedTable; + const requestedTableType = state.selectedTableType; + const container = document.getElementById('gridContainer'); // Whether a data grid is currently rendered (vs. a spinner/error/empty state), // AND whether it belongs to the table we're loading. The renderedTable check is @@ -90,7 +105,9 @@ export async function loadTableData(showSpinner = true, saveScrollPosition = tru }; // Get total count - state.totalRecordCount = await backendApi.fetchTableCount(state.selectedTable, countOptions); + const totalRecordCount = await backendApi.fetchTableCount(requestedTable, countOptions); + if (loadToken !== activeLoadToken) return; // a newer load superseded this one + state.totalRecordCount = totalRecordCount; state.totalPageCount = Math.max(1, Math.ceil(state.totalRecordCount / state.rowsPerPage)); if (state.currentPageIndex >= state.totalPageCount) { @@ -98,7 +115,7 @@ export async function loadTableData(showSpinner = true, saveScrollPosition = tru } // Get data - const isTable = state.selectedTableType === 'table'; + const isTable = requestedTableType === 'table'; // For tables, we need to explicitly request the 'rowid' column to handle row identification. // The frontend expects rowid at index 0 for tables (see `getRowId` and `getRowDataOffset`). @@ -115,7 +132,8 @@ export async function loadTableData(showSpinner = true, saveScrollPosition = tru globalFilter: state.filterQuery }; - const dataResult = await backendApi.fetchTableData(state.selectedTable, queryOptions); + const dataResult = await backendApi.fetchTableData(requestedTable, queryOptions); + if (loadToken !== activeLoadToken) return; // superseded while the data fetch was pending state.gridData = dataResult.rows || []; @@ -141,7 +159,7 @@ export async function loadTableData(showSpinner = true, saveScrollPosition = tru renderDataGrid(state.scrollPosition.top, state.scrollPosition.left); // The on-screen grid now reflects this table; remember it so the next // load can distinguish a same-table refetch from a table switch. - state.renderedTable = state.selectedTable; + state.renderedTable = requestedTable; } if (container) { @@ -154,10 +172,15 @@ export async function loadTableData(showSpinner = true, saveScrollPosition = tru } catch (err) { console.error('Error loading data:', err); - updateStatus(`Error: ${err.message}`); - showErrorState(err.message); + // Don't let a superseded load's error replace the current table's view. + if (loadToken === activeLoadToken) { + updateStatus(`Error: ${err.message}`); + showErrorState(err.message); + } } finally { - if (showSpinner) { + // Only the most recent load owns the loading flag; an earlier, superseded + // load must not clear it while the newer request is still in flight. + if (showSpinner && loadToken === activeLoadToken) { state.isLoadingData = false; } } diff --git a/core/ui/viewer.html b/core/ui/viewer.html index db2963ea..c62d2da2 100644 --- a/core/ui/viewer.html +++ b/core/ui/viewer.html @@ -364,51 +364,51 @@ diff --git a/website/public/sqlite-viewer/viewer.html b/website/public/sqlite-viewer/viewer.html index 604a8628..e3bf0e50 100644 --- a/website/public/sqlite-viewer/viewer.html +++ b/website/public/sqlite-viewer/viewer.html @@ -364,45 +364,45 @@ From ae28d251090f8a05ed30b9ce73c5961fa3767caa Mon Sep 17 00:00:00 2001 From: zknpr Date: Sun, 21 Jun 2026 21:54:11 +0200 Subject: [PATCH 6/9] fix: harden loadTableData concurrency + scroll (Codex round 3) Address the follow-up issues Codex raised on the request-token fix: - isLoadingData could get stuck true: a no-spinner background refresh (loadTableData(false)) superseding a spinner-backed load meant neither load cleared the flag (the old one was superseded, the new one skipped the showSpinner-gated clear), leaving the grid permanently non-interactive via the new guards. The current load now clears the flag regardless of showSpinner. - Table-switch window: the sidebar sets state.selectedTable then awaits loadTableColumns() before starting its own load, so the old request still owned the token and could render stale rows under the new selection. Supersession now also checks requestedTable === selectedTable. - Page-change scroll reset (P3): handleScroll wrote scrollPosition while a load was pending, clobbering goToPage's {0,0}. handleScroll now ignores scroll while isLoadingData; same-table refetches still preserve scroll via the post-await re-capture. Unify the checks behind an isSuperseded() predicate. Regenerated bundles. Co-Authored-By: Claude Opus 4.8 (1M context) --- core/ui/modules/grid-data.js | 23 +++++++++++++++++------ core/ui/modules/grid-events.js | 7 +++++++ core/ui/viewer.html | 20 ++++++++++---------- website/public/sqlite-viewer/viewer.html | 20 ++++++++++---------- 4 files changed, 44 insertions(+), 26 deletions(-) diff --git a/core/ui/modules/grid-data.js b/core/ui/modules/grid-data.js index c8ba9fc6..069e8263 100644 --- a/core/ui/modules/grid-data.js +++ b/core/ui/modules/grid-data.js @@ -55,6 +55,13 @@ export async function loadTableData(showSpinner = true, saveScrollPosition = tru // (which would SELECT the old columns against the new table and error out). const requestedTable = state.selectedTable; const requestedTableType = state.selectedTableType; + // This load is superseded if a newer load has started (token bumped) OR the + // user has navigated to a different table. The selection check matters because + // a table switch changes state.selectedTable synchronously but only starts its + // own load (bumping the token) after awaiting loadTableColumns(); during that + // gap the old load still owns the token, so a token-only check would let it + // render the old table's rows under the new selection and clear the flag. + const isSuperseded = () => loadToken !== activeLoadToken || requestedTable !== state.selectedTable; const container = document.getElementById('gridContainer'); // Whether a data grid is currently rendered (vs. a spinner/error/empty state), @@ -106,7 +113,7 @@ export async function loadTableData(showSpinner = true, saveScrollPosition = tru // Get total count const totalRecordCount = await backendApi.fetchTableCount(requestedTable, countOptions); - if (loadToken !== activeLoadToken) return; // a newer load superseded this one + if (isSuperseded()) return; // a newer load started, or the user switched tables state.totalRecordCount = totalRecordCount; state.totalPageCount = Math.max(1, Math.ceil(state.totalRecordCount / state.rowsPerPage)); @@ -133,7 +140,7 @@ export async function loadTableData(showSpinner = true, saveScrollPosition = tru }; const dataResult = await backendApi.fetchTableData(requestedTable, queryOptions); - if (loadToken !== activeLoadToken) return; // superseded while the data fetch was pending + if (isSuperseded()) return; // superseded (newer load or table switch) during the fetch state.gridData = dataResult.rows || []; @@ -173,14 +180,18 @@ export async function loadTableData(showSpinner = true, saveScrollPosition = tru } catch (err) { console.error('Error loading data:', err); // Don't let a superseded load's error replace the current table's view. - if (loadToken === activeLoadToken) { + if (!isSuperseded()) { updateStatus(`Error: ${err.message}`); showErrorState(err.message); } } finally { - // Only the most recent load owns the loading flag; an earlier, superseded - // load must not clear it while the newer request is still in flight. - if (showSpinner && loadToken === activeLoadToken) { + // The current load owns the loading flag: clear it once this load settles, + // regardless of whether THIS load showed a spinner. A no-spinner background + // refresh can supersede a spinner-backed load, and must still release the + // interactivity guard the spinner load set — otherwise isLoadingData (and + // the grid-event handlers keyed on it) would stay stuck on. A superseded + // load leaves the flag for the newer in-flight request to clear. + if (!isSuperseded()) { state.isLoadingData = false; } } diff --git a/core/ui/modules/grid-events.js b/core/ui/modules/grid-events.js index 9ddbabdb..ca93ac3c 100644 --- a/core/ui/modules/grid-events.js +++ b/core/ui/modules/grid-events.js @@ -202,6 +202,13 @@ function handleMouseover(event) { } function handleScroll(event) { + // Ignore scroll while a load is in flight. The flicker fix keeps the grid + // mounted and scrollable during a refetch; without this, scrolling the old + // page during a page change (which reset scrollPosition to {0,0}) would + // overwrite the reset and reopen the new page at a stale offset. Same-table + // filter/sort refetches still preserve scroll via the post-await re-capture + // in loadTableData, which reads the live DOM position directly. + if (state.isLoadingData) return; const container = event.currentTarget; state.scrollPosition.left = container.scrollLeft; state.scrollPosition.top = container.scrollTop; diff --git a/core/ui/viewer.html b/core/ui/viewer.html index c62d2da2..0c9c7f48 100644 --- a/core/ui/viewer.html +++ b/core/ui/viewer.html @@ -364,28 +364,28 @@ diff --git a/website/public/sqlite-viewer/viewer.html b/website/public/sqlite-viewer/viewer.html index e3bf0e50..c1c0945a 100644 --- a/website/public/sqlite-viewer/viewer.html +++ b/website/public/sqlite-viewer/viewer.html @@ -364,45 +364,45 @@ From 121182d041b5415dd83e41caa4dc2a5faf2ac6da Mon Sep 17 00:00:00 2001 From: zknpr Date: Sun, 21 Jun 2026 22:15:26 +0200 Subject: [PATCH 7/9] fix: dedicate a grid-reload guard, decouple from uploads (Codex round 4) The interactivity guard keyed on state.isLoadingData, which is also set by BLOB uploads (dnd.js) and only covered #gridContainer-delegated events. Two consequences: - A no-spinner refresh's finally cleared isLoadingData mid-upload, re-enabling grid handlers during an in-flight upload. - Document-level shortcuts (viewer.js setupGlobalShortcuts) call onSelectAllClick()/submitDelete() directly, bypassing the grid guards, so Ctrl+A then Ctrl+Delete could select/delete stale rows mid-refetch. Introduce a dedicated state.isGridReloading owned solely by loadTableData (set on a spinner-backed load, released by the latest non-superseded load). Revert isLoadingData to its original showSpinner-gated lifecycle so loadTableData never clears the flag an upload set. Point the grid handlers and the global select-all/delete shortcuts at isGridReloading. Regenerated bundles. Co-Authored-By: Claude Opus 4.8 (1M context) --- core/ui/modules/grid-data.js | 21 ++++++++++++++------- core/ui/modules/grid-events.js | 8 ++++---- core/ui/modules/state.js | 6 ++++++ core/ui/viewer.html | 10 +++++----- core/ui/viewer.js | 10 ++++++++-- website/public/sqlite-viewer/viewer.html | 16 ++++++++-------- 6 files changed, 45 insertions(+), 26 deletions(-) diff --git a/core/ui/modules/grid-data.js b/core/ui/modules/grid-data.js index 069e8263..bfe1c46b 100644 --- a/core/ui/modules/grid-data.js +++ b/core/ui/modules/grid-data.js @@ -82,6 +82,10 @@ export async function loadTableData(showSpinner = true, saveScrollPosition = tru if (showSpinner) { state.isLoadingData = true; + // Dedicated guard the grid handlers + global delete/select-all shortcuts + // key on. Separate from isLoadingData (also set by BLOB uploads in dnd.js) + // so the two can't clear each other; released by the latest load below. + state.isGridReloading = true; // Keep the existing grid visible during a same-table refetch (prevents // flicker); show the spinner on a true first load or a table switch, where // nothing valid for this table is on screen yet. @@ -185,14 +189,17 @@ export async function loadTableData(showSpinner = true, saveScrollPosition = tru showErrorState(err.message); } } finally { - // The current load owns the loading flag: clear it once this load settles, - // regardless of whether THIS load showed a spinner. A no-spinner background - // refresh can supersede a spinner-backed load, and must still release the - // interactivity guard the spinner load set — otherwise isLoadingData (and - // the grid-event handlers keyed on it) would stay stuck on. A superseded - // load leaves the flag for the newer in-flight request to clear. - if (!isSuperseded()) { + // isLoadingData keeps its original lifecycle. It is also set by BLOB uploads + // (dnd.js), so a superseded or no-spinner load must NOT clear it — only the + // spinner load that set it does, mirroring the pre-change behavior. + if (showSpinner) { state.isLoadingData = false; } + // isGridReloading is owned solely here: the latest (non-superseded) load + // releases the grid-interaction guard once it settles, regardless of + // showSpinner. A superseded load leaves it set for the newer request to clear. + if (!isSuperseded()) { + state.isGridReloading = false; + } } } diff --git a/core/ui/modules/grid-events.js b/core/ui/modules/grid-events.js index ca93ac3c..d7c0b1aa 100644 --- a/core/ui/modules/grid-events.js +++ b/core/ui/modules/grid-events.js @@ -54,7 +54,7 @@ function handleMousedown(event) { function handleKeydown(event) { // Ignore filter Enter while a load is in flight: acting now would queue a // concurrent reload and operate against the stale, soon-to-be-replaced grid. - if (state.isLoadingData) return; + if (state.isGridReloading) return; if (event.target.classList.contains('column-filter')) { const colName = event.target.dataset.column; if (colName) onColumnFilterKeydown(event, colName); @@ -66,7 +66,7 @@ function handleClick(event) { // flicker fix keeps the previous grid visible during a same-table refetch, so // without this guard a click on the stale row numbers or cells could select // (and then delete) rows from the old result set before the new data arrives. - if (state.isLoadingData) return; + if (state.isGridReloading) return; const target = event.target; if (target.closest('.grid-header')) { handleHeaderClick(event, target); @@ -178,7 +178,7 @@ function handleBodyClick(event, target) { function handleDoubleClick(event) { // Don't open a cell editor on stale cells while a refetch is in flight. - if (state.isLoadingData) return; + if (state.isGridReloading) return; const cellEl = event.target.closest('.data-cell'); if (cellEl && !cellEl.classList.contains('row-number')) { const rowIdx = parseInt(cellEl.dataset.rowidx, 10); @@ -208,7 +208,7 @@ function handleScroll(event) { // overwrite the reset and reopen the new page at a stale offset. Same-table // filter/sort refetches still preserve scroll via the post-await re-capture // in loadTableData, which reads the live DOM position directly. - if (state.isLoadingData) return; + if (state.isGridReloading) return; const container = event.currentTarget; state.scrollPosition.left = container.scrollLeft; state.scrollPosition.top = container.scrollTop; diff --git a/core/ui/modules/state.js b/core/ui/modules/state.js index 55808a28..0aee2037 100644 --- a/core/ui/modules/state.js +++ b/core/ui/modules/state.js @@ -28,6 +28,12 @@ export const state = { activeCellInput: null, isSavingCell: false, isLoadingData: false, + // Dedicated guard for "a grid data reload is in flight", owned solely by + // loadTableData. Kept separate from isLoadingData (which BLOB uploads also set) + // so the grid-interaction guards can't be cleared by an unrelated upload. The + // grid event handlers and the global delete/select-all shortcuts key on this to + // avoid acting on rows that are about to be replaced. + isGridReloading: false, lastDoubleClickTime: 0, isTransitioningEdit: false, transitionLockTimeout: null, diff --git a/core/ui/viewer.html b/core/ui/viewer.html index 0c9c7f48..22d6399b 100644 --- a/core/ui/viewer.html +++ b/core/ui/viewer.html @@ -364,7 +364,7 @@ diff --git a/core/ui/viewer.js b/core/ui/viewer.js index bf4c59da..6a3a56c2 100644 --- a/core/ui/viewer.js +++ b/core/ui/viewer.js @@ -186,7 +186,10 @@ function setupGlobalShortcuts() { // Cmd+A / Ctrl+A if ((event.metaKey || event.ctrlKey) && event.key === 'a') { - if (state.editingCellInfo || document.activeElement.tagName === 'INPUT' || document.activeElement.tagName === 'TEXTAREA') return; + // Bail during a grid reload: selecting "all" would capture row ids from + // the stale, about-to-be-replaced result set. This shortcut bypasses the + // #gridContainer handlers, so it needs its own guard. + if (state.isGridReloading || state.editingCellInfo || document.activeElement.tagName === 'INPUT' || document.activeElement.tagName === 'TEXTAREA') return; if (state.selectedTable) { event.preventDefault(); @@ -196,7 +199,10 @@ function setupGlobalShortcuts() { // Delete / Backspace if ((event.metaKey || event.ctrlKey) && (event.key === 'Delete' || event.key === 'Backspace')) { - if (state.editingCellInfo || document.activeElement.tagName === 'INPUT' || document.activeElement.tagName === 'TEXTAREA') return; + // Bail during a grid reload: deleting now would act on row/column/cell + // selections from the stale result set about to be replaced. Bypasses the + // #gridContainer handlers, so it needs its own guard. + if (state.isGridReloading || state.editingCellInfo || document.activeElement.tagName === 'INPUT' || document.activeElement.tagName === 'TEXTAREA') return; if (state.selectedTable && state.selectedTableType === 'table') { event.preventDefault(); diff --git a/website/public/sqlite-viewer/viewer.html b/website/public/sqlite-viewer/viewer.html index c1c0945a..f734601f 100644 --- a/website/public/sqlite-viewer/viewer.html +++ b/website/public/sqlite-viewer/viewer.html @@ -364,7 +364,7 @@ From e8e651b055794ff911a8c1546208de8736c92013 Mon Sep 17 00:00:00 2001 From: zknpr Date: Sun, 21 Jun 2026 22:24:12 +0200 Subject: [PATCH 8/9] fix: guard web-demo Ctrl+A/Delete during grid reloads (Codex round 5) core/ui/web-viewer.js has its own copy of the global keyboard-shortcut handler (separate from core/ui/viewer.js). Round 4 guarded viewer.js but not this web-demo entry, so in the web bundle Ctrl+A then Ctrl+Delete could still select/delete rows from the stale gridData during a refetch. Apply the same state.isGridReloading guard to the web-demo select-all and delete shortcuts. Regenerated the web bundle. Co-Authored-By: Claude Opus 4.8 (1M context) --- core/ui/web-viewer.js | 8 ++++++-- website/public/sqlite-viewer/viewer.html | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/core/ui/web-viewer.js b/core/ui/web-viewer.js index e131e251..ae1cbafe 100644 --- a/core/ui/web-viewer.js +++ b/core/ui/web-viewer.js @@ -186,7 +186,9 @@ async function initializeApp() { // Cmd+A / Ctrl+A if ((event.metaKey || event.ctrlKey) && event.key === 'a') { - if (state.editingCellInfo || document.activeElement.tagName === 'INPUT') return; + // Bail during a grid reload: "select all" would capture row ids from + // the stale, about-to-be-replaced result set (mirrors core viewer.js). + if (state.isGridReloading || state.editingCellInfo || document.activeElement.tagName === 'INPUT') return; if (state.selectedTable) { event.preventDefault(); @@ -196,7 +198,9 @@ async function initializeApp() { // Delete / Backspace if ((event.metaKey || event.ctrlKey) && (event.key === 'Delete' || event.key === 'Backspace')) { - if (state.editingCellInfo || document.activeElement.tagName === 'INPUT' || document.activeElement.tagName === 'TEXTAREA') return; + // Bail during a grid reload: deleting now would act on selections + // from the stale result set about to be replaced (mirrors viewer.js). + if (state.isGridReloading || state.editingCellInfo || document.activeElement.tagName === 'INPUT' || document.activeElement.tagName === 'TEXTAREA') return; if (state.selectedTable && state.selectedTableType === 'table') { event.preventDefault(); diff --git a/website/public/sqlite-viewer/viewer.html b/website/public/sqlite-viewer/viewer.html index f734601f..154027db 100644 --- a/website/public/sqlite-viewer/viewer.html +++ b/website/public/sqlite-viewer/viewer.html @@ -402,7 +402,7 @@ `}n.length>o&&(l+=` ... (${(n.length-o).toLocaleString()} more bytes not shown)`),this.hexContainer.value=l}formatSize(n){if(n===0)return"0 B";let o=1024,l=["B","KB","MB","GB"],a=Math.floor(Math.log(n)/Math.log(o));return parseFloat((n/Math.pow(o,a)).toFixed(2))+" "+l[a]}};var be;function ze(){be=new le,document.getElementById("btnCloseCellPreview")?.addEventListener("click",H),document.getElementById("formatJsonBtn")?.addEventListener("click",Vt),document.getElementById("compactJsonBtn")?.addEventListener("click",Wt),document.getElementById("wrapTextBtn")?.addEventListener("click",_t),document.getElementById("openInVsCodeBtn")?.addEventListener("click",we),document.getElementById("btnCancelCellPreview")?.addEventListener("click",H),document.getElementById("cellPreviewSaveBtn")?.addEventListener("click",Ke)}function je(e,n,o){if(t.selectedTableType!=="table"){u("Views are read-only");return}if(t.editingCellInfo){if(t.editingCellInfo.rowIdx===e&&t.editingCellInfo.colIdx===n)return;se()}let l=t.tableColumns[n];if(!l)return;let a=document.getElementById(`cell-${e}-${n}`);if(!a)return;let s=t.gridData[e],i=P(s,n);if(i instanceof Uint8Array){K(e,n,o);return}if(typeof i=="string"){let d=i.trim();if(d.startsWith("{")&&d.endsWith("}")||d.startsWith("[")&&d.endsWith("]"))try{JSON.parse(d),K(e,n,o);return}catch{}}t.editingCellInfo={rowIdx:e,colIdx:n,rowId:o,columnName:l.name,originalValue:i};let r=i===null?"":String(i);a.innerHTML="",a.classList.add("editing");let c=document.createElement("textarea");c.className="cell-input",c.value=r,c.spellcheck=!1,a.appendChild(c),c.focus(),t.activeCellInput=c,c.addEventListener("keydown",Ve),c.addEventListener("blur",We),c.addEventListener("click",d=>d.stopPropagation()),t.isTransitioningEdit=!0,setTimeout(()=>{t.isTransitioningEdit=!1},100)}function Ve(e){e.key==="Enter"&&!e.shiftKey?(e.preventDefault(),_e()):e.key==="Escape"&&(e.preventDefault(),se())}function We(){setTimeout(()=>{t.editingCellInfo&&_e()},100)}async function _e(){if(t.isSavingCell||!t.editingCellInfo||!t.activeCellInput)return;let{rowIdx:e,colIdx:n,rowId:o,columnName:l,originalValue:a}=t.editingCellInfo,s=t.activeCellInput.value,i=a===null?"":String(a);if(s===i){se(),t.selectedCells=[],t.lastSelectedCell=null,M();return}let r=t.tableColumns[n],c=r&&r.notnull===1,d;s===""?c?d="":d=null:!isNaN(Number(s))&&s.trim()!==""?d=Number(s):d=s;try{t.isSavingCell=!0,u("Saving..."),await x.updateCell(t.selectedTable,te(o),l,d,a),t.gridData[e][n+B()]=d,qe(),Ee(e,n,d),t.selectedCells=[],t.lastSelectedCell=null,M(),u("Saved")}catch(m){console.error("Save failed:",m);let y=m.message||String(m);u(`Save failed: ${y}`)}finally{t.isSavingCell=!1}}function se(){if(!t.editingCellInfo)return;let{rowIdx:e,colIdx:n,originalValue:o}=t.editingCellInfo;qe(),Ee(e,n,o),oe()}function qe(){t.activeCellInput&&(t.activeCellInput.removeEventListener("keydown",Ve),t.activeCellInput.removeEventListener("blur",We),t.activeCellInput=null),t.editingCellInfo=null}async function we(){if(!t.cellPreviewInfo)return;let{rowIdx:e,colIdx:n,rowId:o,columnName:l,originalValue:a}=t.cellPreviewInfo,s=t.tableColumns[n],i=document.getElementById("vscode-env")?.dataset.webviewId||"default";try{u("Opening in VS Code..."),H(),await x.openCellEditor({table:t.selectedTable,name:""},te(o),l,{},{value:a,type:{type:s.type},webviewId:i,rowCount:t.gridData.length}),u("Opened in VS Code")}catch(r){console.error("Failed to open in VS Code:",r),u(`Error: ${r.message}`)}}function K(e,n,o){t.editingCellInfo&&se();let l=t.tableColumns[n];if(!l)return;let a=t.gridData[e];if(!a)return;let s=P(a,n);if(s instanceof Uint8Array){be&&be.inspect(s,o,l.name,e,n);return}t.cellPreviewInfo={rowIdx:e,colIdx:n,rowId:o,columnName:l.name,originalValue:s};let i=document.getElementById("cellPreviewModal"),r=document.getElementById("cellPreviewColumnName"),c=document.getElementById("cellPreviewTypeBadge"),d=document.getElementById("cellPreviewTextarea"),m=document.getElementById("cellPreviewReadonlyBadge"),y=document.getElementById("cellPreviewSaveBtn"),f=document.getElementById("wrapTextBtn");r.textContent=l.name,c.textContent=l.type||"TEXT";let p="";s==null?p="":s instanceof Uint8Array?p="[BLOB: "+Array.from(s).map(b=>b.toString(16).padStart(2,"0")).join(" ")+"]":p=String(s),d.value=p;let g=t.selectedTableType!=="table";d.readOnly=g,g?(d.classList.add("readonly"),m.style.display="inline",y.style.display="none"):(d.classList.remove("readonly"),m.style.display="none",y.style.display="inline-block"),ae(),d.style.whiteSpace=t.cellPreviewWrapEnabled?"pre-wrap":"pre",d.style.overflowX=t.cellPreviewWrapEnabled?"hidden":"auto",f.classList.toggle("active",t.cellPreviewWrapEnabled),i.classList.remove("hidden"),d.focus(),d.oninput=ae,d.onkeydown=b=>{b.key==="Escape"?(b.preventDefault(),H()):b.key==="Enter"&&(b.ctrlKey||b.metaKey)&&(b.preventDefault(),Ke())}}function ae(){let e=document.getElementById("cellPreviewTextarea"),n=document.getElementById("cellPreviewCharCount"),o=e.value.length;n.textContent=`${o.toLocaleString()} character${o!==1?"s":""}`}function H(){document.getElementById("cellPreviewModal").classList.add("hidden"),t.cellPreviewInfo=null}async function Ke(){if(!t.cellPreviewInfo)return;if(t.selectedTableType!=="table"){u("Views are read-only");return}let{rowIdx:e,colIdx:n,rowId:o,columnName:l,originalValue:a}=t.cellPreviewInfo,i=document.getElementById("cellPreviewTextarea").value,r=a===null?"":String(a);if(i===r){H(),t.selectedCells=[],t.lastSelectedCell=null,M();return}let c=t.tableColumns[n],d=c&&c.notnull===1,m;i===""?m=d?"":null:!isNaN(Number(i))&&i.trim()!==""?m=Number(i):m=i;try{u("Saving..."),await x.updateCell(t.selectedTable,te(o),l,m,a),t.gridData[e][n+B()]=m,H(),Ee(e,n,m),t.selectedCells=[],t.lastSelectedCell=null,M(),u("Saved")}catch(y){console.error("Save failed:",y),u(`Save failed: ${y.message}`)}}function Vt(){let e=document.getElementById("cellPreviewTextarea");try{let n=JSON.parse(e.value);e.value=JSON.stringify(n,null,2),ae()}catch{u("Content is not valid JSON")}}function Wt(){let e=document.getElementById("cellPreviewTextarea");try{let n=JSON.parse(e.value);e.value=JSON.stringify(n),ae()}catch{u("Content is not valid JSON")}}function _t(){t.cellPreviewWrapEnabled=!t.cellPreviewWrapEnabled;let e=document.getElementById("cellPreviewTextarea"),n=document.getElementById("wrapTextBtn");e.style.whiteSpace=t.cellPreviewWrapEnabled?"pre-wrap":"pre",e.style.overflowX=t.cellPreviewWrapEnabled?"hidden":"auto",n.classList.toggle("active",t.cellPreviewWrapEnabled)}function Ee(e,n,o){let l=document.getElementById(`cell-${e}-${n}`);if(!l)return;l.classList.remove("editing"),o==null?l.classList.add("null-value"):l.classList.remove("null-value");let a=t.tableColumns[n],s=_(o,a?.type,t.dateFormat,a?.name),i=o!=null&&!(o instanceof Uint8Array);l.textContent="";let r=document.createElement("span");if(r.className="cell-text",r.textContent=s,l.appendChild(r),i){let d=document.createElement("span");d.className="expand-icon codicon codicon-link-external",d.title="View full content",l.appendChild(d)}let c=r.scrollWidth>r.clientWidth;l.classList.toggle("has-overflow",c)}function He(){clearTimeout(t.filterTimer),t.filterTimer=setTimeout(()=>{t.filterQuery=document.getElementById("filterInput").value,t.currentPageIndex=0,v(),$()},300)}function Ge(){t.rowsPerPage=parseInt(document.getElementById("pageSizeSelect").value,10),t.currentPageIndex=0,v(),$()}function Je(){let e=document.getElementById("dateFormatSelect");e&&(t.dateFormat=e.value,z(),$())}function Z(e){e>=0&&el.name===n);if(o!==-1){if((e.shiftKey||e.metaKey||e.ctrlKey)&&e.preventDefault(),t.selectedRowIds.clear(),e.shiftKey&&t.lastSelectedColumnIndex!==null){e.metaKey||e.ctrlKey||(t.selectedCells=[],t.selectedColumns.clear());let l=Math.min(t.lastSelectedColumnIndex,o),a=Math.max(t.lastSelectedColumnIndex,o),s=new Array;if(t.selectedCells.length>0)for(let i of t.selectedCells)i.colIdx>=l&&i.colIdx<=a&&(s[i.rowIdx]||(s[i.rowIdx]=new Set),s[i.rowIdx].add(i.colIdx));for(let i=l;i<=a;i++){let r=t.tableColumns[i].name;t.selectedColumns.add(r);for(let c=0;c0&&a===l)t.selectedCells=t.selectedCells.filter(i=>i.colIdx!==o),t.selectedColumns.delete(n);else{let i=new Set;for(let r of t.selectedCells)r.colIdx===o&&i.add(r.rowIdx);for(let r=0;r0&&a===l&&t.selectedColumns.size===1&&t.selectedColumns.has(n))t.selectedCells=[],t.selectedColumns.clear(),t.lastSelectedColumnIndex=null;else{t.selectedCells=[],t.selectedColumns.clear();for(let i=0;ii.name===t.resizingColumn);if(l===-1)return;let a=document.querySelector(`th[data-column="${t.resizingColumn}"]`);a&&(a.style.width=`${o}px`,a.style.minWidth=`${o}px`,a.style.maxWidth=`${o}px`);let s=document.querySelectorAll(`.data-row td:nth-child(${l+2})`);for(let i of s)i.style.width=`${o}px`,i.style.minWidth=`${o}px`,i.style.maxWidth=`${o}px`;t.pinnedColumns.has(t.resizingColumn)}function ot(){if(!t.resizingColumn)return;let e=document.querySelector(".resize-handle.resizing");e&&e.classList.remove("resizing"),t.resizingColumn=null,document.removeEventListener("mousemove",nt),document.removeEventListener("mouseup",ot),document.body.style.userSelect="",document.body.style.cursor="",z()}function lt(e,n,o){if(e.stopPropagation(),(e.shiftKey||e.metaKey||e.ctrlKey)&&e.preventDefault(),t.selectedCells=[],t.lastSelectedCell=null,t.selectedColumns.clear(),e.shiftKey&&t.lastSelectedRowIndex!==null){e.metaKey||e.ctrlKey||t.selectedRowIds.clear();let l=Math.min(t.lastSelectedRowIndex,o),a=Math.max(t.lastSelectedRowIndex,o);for(let s=l;s<=a;s++){let i=T(t.gridData[s],s);t.selectedRowIds.add(i)}}else e.ctrlKey||e.metaKey?(t.selectedRowIds.has(n)?t.selectedRowIds.delete(n):t.selectedRowIds.add(n),t.lastSelectedRowIndex=o):t.selectedRowIds.has(n)&&t.selectedRowIds.size===1?(t.selectedRowIds.delete(n),t.lastSelectedRowIndex=null):(t.selectedRowIds.clear(),t.selectedRowIds.add(n),t.lastSelectedRowIndex=o);M(),L(),O()}function ie(e){if(e.stopPropagation(),t.gridData.length===0)return;t.selectedCells=[],t.lastSelectedCell=null,t.selectedColumns.clear();let n=!0;for(let o=0;o=s&&m.rowIdx<=i&&m.colIdx>=r&&m.colIdx<=c&&(d[m.rowIdx]||(d[m.rowIdx]=new Set),d[m.rowIdx].add(m.colIdx));for(let m=s;m<=i;m++){let y=d[m];for(let f=r;f<=c;f++)if(!y||!y.has(f)){let p=T(t.gridData[m],m),g=P(t.gridData[m],f);t.selectedCells.push({rowIdx:m,colIdx:f,rowId:p,value:g})}}}else if(e.metaKey||e.ctrlKey){e.preventDefault(),t.selectedRowIds.clear();let s=t.selectedCells.findIndex(i=>i.rowIdx===n&&i.colIdx===o);s>=0?t.selectedCells.splice(s,1):(t.selectedCells.push({rowIdx:n,colIdx:o,rowId:l,value:a}),t.lastSelectedCell={rowIdx:n,colIdx:o})}else if(e.shiftKey&&t.lastSelectedCell){e.preventDefault(),t.selectedRowIds.clear(),t.selectedCells=[];let s=Math.min(t.lastSelectedCell.rowIdx,n),i=Math.max(t.lastSelectedCell.rowIdx,n),r=Math.min(t.lastSelectedCell.colIdx,o),c=Math.max(t.lastSelectedCell.colIdx,o);for(let d=s;d<=i;d++)for(let m=r;m<=c;m++){let y=T(t.gridData[d],d),f=P(t.gridData[d],m);t.selectedCells.push({rowIdx:d,colIdx:m,rowId:y,value:f})}}else t.selectedRowIds.clear(),t.selectedCells=[{rowIdx:n,colIdx:o,rowId:l,value:a}],t.lastSelectedCell={rowIdx:n,colIdx:o},t.selectedColumns.clear();M(),L(),O()}function st(e,n,o,l){if(t.cellEditBehavior==="vscode"){let a=t.tableColumns[o];if(!a)return;let s=t.gridData[n];if(!s)return;let i=P(s,o);t.cellPreviewInfo={rowIdx:n,colIdx:o,rowId:l,columnName:a.name,originalValue:i},we()}else t.cellEditBehavior==="modal"?K(n,o,l):je(n,o,l)}function it(){document.getElementById("filterInput")?.addEventListener("keyup",He),document.getElementById("pageSizeSelect")?.addEventListener("change",Ge),document.getElementById("dateFormatSelect")?.addEventListener("change",Je),document.getElementById("btnFirst")?.addEventListener("click",()=>Z(0)),document.getElementById("btnPrev")?.addEventListener("click",()=>Z(t.currentPageIndex-1)),document.getElementById("btnNext")?.addEventListener("click",()=>Z(t.currentPageIndex+1)),document.getElementById("btnLast")?.addEventListener("click",()=>Z(t.totalPageCount-1))}function rt(){let e=document.getElementById("gridContainer");e&&(e.addEventListener("mousedown",qt),e.addEventListener("keydown",Kt),e.addEventListener("click",Ht),e.addEventListener("dblclick",Xt),e.addEventListener("mouseover",Yt),e.addEventListener("scroll",Zt,{passive:!0}))}function qt(e){if(e.target.classList.contains("resize-handle")){e.stopPropagation();let n=e.target.closest(".header-cell");n&&n.dataset.column&&tt(e,n.dataset.column)}}function Kt(e){if(!t.isGridReloading&&e.target.classList.contains("column-filter")){let n=e.target.dataset.column;n&&Ye(e,n)}}function Ht(e){if(t.isGridReloading)return;let n=e.target;if(n.closest(".grid-header")){Gt(e,n);return}Jt(e,n)}function Gt(e,n){if(n.closest(".filter-apply-btn")){e.stopPropagation();let l=n.closest(".header-cell");l&&l.dataset.column&&Ie(l.dataset.column);return}if(n.closest(".header-bottom")||n.closest(".column-filter")){e.stopPropagation();return}if(n.closest(".select-column-icon")){e.stopPropagation();let l=n.closest(".header-cell");l&&l.dataset.column&&Ze(e,l.dataset.column);return}if(n.closest(".pin-icon")){e.stopPropagation();let l=n.closest(".header-cell");l&&l.dataset.column&&Qe(e,l.dataset.column);return}if(n.closest(".row-number-header")){ie(e);return}let o=n.closest(".header-top");if(o){let l=o.closest(".header-cell");l&&l.dataset.column&&Xe(l.dataset.column);return}}function Jt(e,n){if(n.closest(".pin-icon")){let l=n.closest(".data-row");if(l){let a=l.dataset.rowid,s=Q(a);et(e,s)}return}if(n.closest(".expand-icon")){let l=n.closest(".data-cell");if(l){let a=parseInt(l.dataset.rowidx,10),s=parseInt(l.dataset.colidx,10),i=Q(l.closest(".data-row").dataset.rowid);K(a,s,i)}return}if(n.closest(".row-number")){let l=n.closest(".data-row");if(l){let a=Q(l.dataset.rowid),s=parseInt(l.dataset.rowidx,10);lt(e,a,s)}return}let o=n.closest(".data-cell");if(o){let l=parseInt(o.dataset.rowidx,10),a=parseInt(o.dataset.colidx,10),s=o.closest(".data-row"),i=Q(s.dataset.rowid);at(e,l,a,i);return}}function Xt(e){if(t.isGridReloading)return;let n=e.target.closest(".data-cell");if(n&&!n.classList.contains("row-number")){let o=parseInt(n.dataset.rowidx,10),l=parseInt(n.dataset.colidx,10),a=n.closest(".data-row"),s=Q(a.dataset.rowid);st(e,o,l,s)}}function Yt(e){let n=e.target.closest(".data-cell");if(n&&!n.classList.contains("checked-overflow")){let o=n.querySelector(".cell-text");if(o){let l=o.scrollWidth>o.clientWidth;n.classList.toggle("has-overflow",l),n.classList.add("checked-overflow")}}}function Zt(e){if(t.isGridReloading)return;let n=e.currentTarget;t.scrollPosition.left=n.scrollLeft,t.scrollPosition.top=n.scrollTop,$()}function Q(e){if(e==null)return e;let n=Number(e);return!isNaN(n)&&e.trim()!==""?n:e}function ct(){document.addEventListener("click",e=>{let n=e.target,o=n.closest(".modal-close, .modal-cancel");if(o){let l=o.dataset.modal;l&&U(l)}n.classList.contains("modal-overlay")&&n.classList.add("hidden")}),document.addEventListener("keydown",e=>{if(e.key==="Escape"){let n=document.querySelector(".modal-overlay:not(.hidden)");n&&(n.classList.add("hidden"),e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation())}})}function j(e){let n=document.getElementById(e);if(n){n.classList.remove("hidden");let o=n.querySelector("input, select, textarea, button");o&&o.focus()}}function U(e){let n=document.getElementById(e);n&&n.classList.add("hidden")}function dt(){document.getElementById("btnAddRow")?.addEventListener("click",Qt),document.getElementById("btnDeleteRows")?.addEventListener("click",tn),document.getElementById("btnAddColumn")?.addEventListener("click",sn),document.getElementById("btnSubmitAddRow")?.addEventListener("click",en),document.getElementById("btnSubmitDelete")?.addEventListener("click",re),document.getElementById("btnSubmitCreateTable")?.addEventListener("click",an),document.getElementById("btnAddColumnDef")?.addEventListener("click",()=>pt()),document.getElementById("columnDefinitions")?.addEventListener("click",e=>{let n=e.target.closest(".btn-remove-col");if(n){let o=n.dataset.colid;ln(o)}}),document.getElementById("btnSubmitAddColumn")?.addEventListener("click",rn)}function Qt(){if(!t.selectedTable||t.selectedTableType!=="table")return;let e=document.getElementById("addRowForm");e.replaceChildren(),t.tableColumns.forEach(n=>{let o=n.notnull===1&&!n.isPrimaryKey,l=document.createElement("div");l.className="form-field";let a=document.createElement("label");if(a.textContent=n.name,o){let r=document.createElement("span");r.style.color="var(--error-color)",r.textContent="*",a.appendChild(document.createTextNode(" ")),a.appendChild(r)}let s=document.createElement("span");s.style.opacity="0.5",s.textContent=` (${n.type})`,a.appendChild(document.createTextNode(" ")),a.appendChild(s);let i=document.createElement("input");i.type="text",i.dataset.column=n.name,i.dataset.required=o.toString(),n.isPrimaryKey?(i.placeholder="Auto (Primary Key)",i.disabled=!0):o?i.placeholder="Required":i.placeholder="NULL",l.appendChild(a),l.appendChild(i),e.appendChild(l)}),j("addRowModal")}async function en(){let e=document.querySelectorAll("#addRowForm input[data-column]:not([disabled])"),n=[];for(let l of e){let a=l.dataset.column,s=l.value.trim();l.dataset.required==="true"&&(s===""||s.toLowerCase()==="null")?(n.push(a),l.style.borderColor="var(--error-color)"):l.style.borderColor=""}if(n.length>0){u(`Required fields missing: ${n.join(", ")}`);return}let o={};for(let l of e){let a=l.dataset.column,s=l.value.trim();s!==""&&(s.toLowerCase()==="null"?o[a]=null:!isNaN(Number(s))&&s!==""?o[a]=Number(s):o[a]=s)}try{u("Inserting row..."),await x.insertRow(t.selectedTable,o),U("addRowModal"),await v(),u("Row inserted - Ctrl+S to save")}catch(l){console.error("Insert failed:",l),u(`Error: ${l.message}`)}}function tn(){if(t.selectedColumns.size>0){let e=Array.from(t.selectedColumns);document.getElementById("deleteConfirmText").textContent=`Are you sure you want to delete ${e.length} column${e.length>1?"s":""} (${e.join(", ")})? This will permanently remove the column${e.length>1?"s":""} and all their data.`}else if(t.selectedRowIds.size>0)document.getElementById("deleteConfirmText").textContent=`Are you sure you want to delete ${t.selectedRowIds.size} row${t.selectedRowIds.size>1?"s":""}?`;else return;j("deleteModal")}async function re(){t.selectedColumns.size>0?await on():t.selectedRowIds.size>0&&await nn()}async function nn(){if(t.selectedRowIds.size===0)return;let e=Array.from(t.selectedRowIds);try{u("Deleting rows..."),await x.deleteRows(t.selectedTable,e),U("deleteModal"),t.selectedRowIds.clear(),await v(),L(),u(`Deleted ${e.length} row${e.length>1?"s":""} - Ctrl+S to save`)}catch(n){console.error("Delete rows failed:",n),u(`Error: ${n.message}`)}}async function on(){if(t.selectedColumns.size===0)return;let e=Array.from(t.selectedColumns);try{u("Deleting columns...");let n=await x.deleteColumns(t.selectedTable,e);if(n&&n.cancelled){u("Delete cancelled"),U("deleteModal");return}U("deleteModal"),t.selectedColumns.clear(),t.selectedCells=[],t.lastSelectedCell=null,await V(),await q(),await v(),L(),u(`Deleted ${e.length} column${e.length>1?"s":""} - Ctrl+S to save`)}catch(n){console.error("Delete columns failed:",n),u(`Error: ${n.message}`)}}var ut=0;function mt(){document.getElementById("newTableName").value="",document.getElementById("columnDefinitions").replaceChildren(),ut=0,pt(!0),j("createTableModal")}function pt(e=!1){let n=document.getElementById("columnDefinitions"),o=++ut,l=document.createElement("div");l.className="column-def-row",l.id=`colDef_${o}`,Object.assign(l.style,{display:"flex",gap:"8px",marginBottom:"8px",alignItems:"center"});let a=document.createElement("input");a.type="text",a.placeholder="Column name",a.className="col-name",a.style.flex="2",e&&(a.value="id"),l.appendChild(a);let s=document.createElement("select");s.className="col-type",s.style.flex="1",["INTEGER","TEXT","REAL","BLOB","NUMERIC"].forEach(f=>{let p=document.createElement("option");p.value=f,p.textContent=f,e&&f==="INTEGER"&&(p.selected=!0),!e&&f==="TEXT"&&(p.selected=!0),s.appendChild(p)}),l.appendChild(s);let i=document.createElement("label");Object.assign(i.style,{display:"flex",alignItems:"center",gap:"4px",cursor:"pointer"});let r=document.createElement("input");r.type="checkbox",r.className="col-pk",r.style.margin="0",e&&(r.checked=!0),i.appendChild(r),i.appendChild(document.createTextNode(" PK")),l.appendChild(i);let c=document.createElement("label");Object.assign(c.style,{display:"flex",alignItems:"center",gap:"4px",cursor:"pointer"});let d=document.createElement("input");d.type="checkbox",d.className="col-nn",d.style.margin="0",c.appendChild(d),c.appendChild(document.createTextNode(" NN")),l.appendChild(c);let m=document.createElement("button");m.className="icon-button btn-remove-col",m.dataset.colid=o.toString(),m.title="Remove",e&&(m.disabled=!0);let y=document.createElement("span");y.className="codicon codicon-close",m.appendChild(y),l.appendChild(m),n.appendChild(l)}function ln(e){let n=document.getElementById(`colDef_${e}`);n&&n.remove()}async function an(){let e=document.getElementById("newTableName").value.trim();if(!e){u("Error: Table name is required");return}if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(e)){u("Error: Invalid table name");return}let n=[],o=document.querySelectorAll(".column-def-row");for(let l of o){let a=l.querySelector(".col-name").value.trim(),s=l.querySelector(".col-type").value,i=l.querySelector(".col-pk").checked,r=l.querySelector(".col-nn").checked;a&&n.push({name:a,type:s,primaryKey:i,notNull:r})}if(n.length===0){u("Error: At least one column is required");return}try{u("Creating table..."),await x.createTable(e,n),U("createTableModal"),await V(),u(`Table "${e}" created - Ctrl+S to save`)}catch(l){console.error("Create table failed:",l),u(`Error: ${l.message}`)}}function sn(){!t.selectedTable||t.selectedTableType!=="table"||(document.getElementById("newColumnName").value="",document.getElementById("newColumnType").value="TEXT",document.getElementById("newColumnDefault").value="",j("addColumnModal"))}async function rn(){let e=document.getElementById("newColumnName").value.trim(),n=document.getElementById("newColumnType").value,o=document.getElementById("newColumnDefault").value.trim();if(!e){u("Error: Column name is required");return}if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(e)){u("Error: Invalid column name");return}try{u("Adding column..."),await x.addColumn(t.selectedTable,e,n,o),U("addColumnModal"),await q(),await v(),u(`Column "${e}" added - Ctrl+S to save`)}catch(l){console.error("Add column failed:",l),u(`Error: ${l.message}`)}}function ft(){let e=document.getElementById("pragmaSettingsContainer");e&&e.addEventListener("change",n=>{let o=n.target;if(o.matches(".setting-extension")){let l=o.dataset.key,a=o.type==="checkbox"?o.checked:o.value;dn(l,a)}else if(o.matches(".setting-pragma")){let l=o.dataset.name,a=o.dataset.type,s=o.value;a==="number"?s=Number(s):a==="bool"&&(s=s==="true"?1:0),un(l,s)}})}async function gt(){let e=document.getElementById("settingsModal");e&&(e.classList.remove("hidden"),await ve())}async function ve(){let e=document.getElementById("pragmaSettingsContainer");e.textContent="Loading settings...";try{let[n,o]=await Promise.all([x.getPragmas(),x.getExtensionSettings()]);cn(n,o)}catch(n){console.error("Failed to load settings:",n),e.textContent=`Error loading settings: ${n.message}`,e.style.color="var(--error-color)"}}function cn(e,n){let o=document.getElementById("pragmaSettingsContainer");if(!o)return;let l=(h,C)=>h.map(k=>{let R=String(k),D=String(C).toUpperCase()===R.toUpperCase(),N=document.createElement("option");return N.value=R,N.selected=D,N.textContent=R,N});o.replaceChildren();let a=h=>{let C=document.createElement("div");C.className="setting-section-title",Object.assign(C.style,{fontWeight:"600",marginBottom:"8px",paddingBottom:"4px",borderBottom:"1px solid var(--border-color)"}),C.textContent=h,o.appendChild(C)},s=(h,C,k)=>{let R=document.createElement("div");R.className="form-field";let w=document.createElement("label");if(C.type==="checkbox"?(Object.assign(w.style,{display:"flex",alignItems:"center",gap:"4px",cursor:"pointer"}),C.style.margin="0",w.appendChild(C),w.appendChild(document.createTextNode(h)),R.appendChild(w)):(w.textContent=h,R.appendChild(w),R.appendChild(C)),k){let D=document.createElement("div");D.className="setting-desc",D.textContent=k,R.appendChild(D)}o.appendChild(R)};if(o.children.length>0){let h=document.createElement("div");h.style.height="16px",o.appendChild(h)}a("Extension Settings");let i=document.createElement("input");i.type="checkbox",i.className="setting-extension",i.dataset.key="autoCommit",i.checked=!!n.autoCommit,s("Auto-Commit Changes",i,"Automatically save changes to disk immediately. If disabled, you must save manually (Ctrl+S).");let r=document.createElement("select");r.className="setting-extension",r.dataset.key="doubleClickBehavior",l(["inline","modal","vscode"],n.cellEditBehavior).forEach(h=>r.appendChild(h)),s("Double Click Behavior",r,"Action when double-clicking a cell");let c=document.createElement("div");c.style.height="16px",o.appendChild(c),a("SQLite Settings (Pragmas)");let d=document.createElement("select");d.className="setting-pragma",d.dataset.name="journal_mode",l(["DELETE","TRUNCATE","PERSIST","MEMORY","WAL","OFF"],e.journal_mode).forEach(h=>d.appendChild(h)),s("Journal Mode",d,"Database journaling mode (WAL is recommended for concurrency)");let m=document.createElement("select");m.className="setting-pragma",m.dataset.name="foreign_keys",m.dataset.type="bool";let y=document.createElement("option");y.value="true",y.textContent="ON";let f=document.createElement("option");f.value="false",f.textContent="OFF",Number(e.foreign_keys)===1?y.selected=!0:f.selected=!0,m.appendChild(y),m.appendChild(f),s("Foreign Keys",m,"Enforce foreign key constraints");let p=document.createElement("select");p.className="setting-pragma",p.dataset.name="synchronous",p.dataset.type="number",[{v:0,t:"OFF (0)"},{v:1,t:"NORMAL (1)"},{v:2,t:"FULL (2)"},{v:3,t:"EXTRA (3)"}].forEach(h=>{let C=document.createElement("option");C.value=h.v,C.textContent=h.t,Number(e.synchronous)===h.v&&(C.selected=!0),p.appendChild(C)}),s("Synchronous",p,"Disk synchronization safety level");let g=document.createElement("select");g.className="setting-pragma",g.dataset.name="locking_mode",l(["NORMAL","EXCLUSIVE"],e.locking_mode).forEach(h=>g.appendChild(h)),s("Locking Mode",g,"");let b=document.createElement("select");b.className="setting-pragma",b.dataset.name="auto_vacuum",b.dataset.type="number",[{v:0,t:"NONE (0)"},{v:1,t:"FULL (1)"},{v:2,t:"INCREMENTAL (2)"}].forEach(h=>{let C=document.createElement("option");C.value=h.v,C.textContent=h.t,Number(e.auto_vacuum)===h.v&&(C.selected=!0),b.appendChild(C)}),s("Auto Vacuum",b,"");let E=document.createElement("input");E.type="number",E.className="setting-pragma",E.dataset.name="cache_size",E.dataset.type="number",E.value=e.cache_size,s("Cache Size",E,"Number of pages (positive) or kilobytes (negative)")}async function dn(e,n){try{await x.updateExtensionSetting(e,n),u(`Updated ${e}`)}catch(o){console.error(`Failed to set ${e}:`,o),u(`Error: ${o.message}`),await ve()}}async function un(e,n){try{u(`Updating ${e}...`),await x.setPragma(e,n),u(`Updated ${e}`)}catch(o){console.error(`Failed to set ${e}:`,o),u(`Error: ${o.message}`),await ve()}}function ht(e,n){let o=new Map;for(let l of e){let a=n&&n[l.colIdx];a&&(o.has(l.colIdx)||o.set(l.colIdx,{name:a.name,type:a.type,values:new Set}),o.get(l.colIdx).values.add(l.value))}return o}function yt(e){let n=Array.from(e||[]);if(n.length===0)return"";if(n.length>1)return"(mixed values)";let o=n[0];return o===null?"NULL":o instanceof Uint8Array?"[BLOB]":String(o)}function Ct(e,n,o){let l=[];for(let a of e){let s=n.get(a.colIdx);if(!s)continue;let i=s.dataset||{},r=i.isnull==="true",c=i.ispatch==="true",d=s.value;if(d===""&&!r)continue;let m=o&&o[a.colIdx];if(!m)continue;let y=d,f="set";if(r)y=null;else if(c)f="json_patch";else{let p=(m.type||"").toUpperCase();(p==="INTEGER"||p==="REAL"||p==="NUMERIC")&&!isNaN(Number(d))&&d.trim()!==""&&(y=Number(d))}l.push({rowId:a.rowId,column:m.name,value:y,originalValue:a.value,operation:f,rowIdx:a.rowIdx,colIdx:a.colIdx})}return l}function bt(){let e=document.getElementById("sidebarPanel");if(!e)return;let n=document.getElementById("sidebarFilterInput");n&&n.addEventListener("input",()=>{t.sidebarFilter=n.value,Be()}),e.addEventListener("click",o=>{let l=o.target;if(l.closest("#btnOpenSettings")){gt();return}if(l.closest("#btnOpenCreateTable")){o.stopPropagation(),mt();return}if(l.closest("#btnReload")){Cn();return}if(l.closest("#btnApplyBatchUpdate")){pn();return}let a=l.closest(".list-item");if(a){let c=a.dataset.name,d=a.dataset.type;if(c&&d){yn(c,d);return}}let s=l.closest(".section-title");if(s){if(l.closest(".icon-button")||s.id==="btnOpenSettings")return;let c=s.dataset.section;c&&hn(c)}let i=l.closest(".btn-batch-null");if(i){let c=i.closest(".batch-field");if(c){let d=parseInt(c.dataset.colidx,10);fn(d)}return}let r=l.closest(".btn-batch-patch");if(r){let c=r.closest(".batch-field");if(c){let d=parseInt(c.dataset.colidx,10);gn(d,r)}return}})}async function V(){if(t.isDbConnected)try{let e=await x.fetchSchema();t.schemaCache.tables=(e.tables||[]).map(n=>({name:n.identifier})),t.schemaCache.views=(e.views||[]).map(n=>({name:n.identifier})),t.schemaCache.indexes=(e.indexes||[]).map(n=>({name:n.identifier,table:n.parentTable})),Be()}catch(e){console.error("Error loading schema:",e),u("Error loading schema")}}function Se(e,n){return n?e.filter(o=>o.name.toLowerCase().includes(n)):e}function Te(e,n,o,l){let a=document.getElementById(e);a&&(a.textContent=l?`${n}/${o}`:o)}function xt(e,n,o,l,a){let s=document.getElementById(e);if(!s)return;if(s.replaceChildren(),n.length===0){let r=document.createElement("li");r.className="list-item",r.style.opacity="0.5",r.textContent=a,s.appendChild(r);return}let i=document.createDocumentFragment();n.forEach(r=>{let c=document.createElement("li");c.className="list-item",t.selectedTable===r.name&&t.selectedTableType===o&&c.classList.add("selected"),c.dataset.name=r.name,o&&(c.dataset.type=o),c.title=r.name;let d=document.createElement("span");d.className=`item-icon codicon ${l}`,c.appendChild(d);let m=document.createElement("span");m.className="item-name",m.textContent=r.name,c.appendChild(m),i.appendChild(c)}),s.appendChild(i)}function mn(e,n,o){let l=document.getElementById(e);if(!l)return;if(l.replaceChildren(),n.length===0){let s=document.createElement("li");s.className="list-item",s.style.opacity="0.5",s.textContent=o,l.appendChild(s);return}let a=document.createDocumentFragment();n.forEach(s=>{let i=document.createElement("li");i.className="list-item",i.title=`${s.name} on ${s.table}`;let r=document.createElement("span");r.className="item-icon codicon codicon-list-selection",i.appendChild(r);let c=document.createElement("div");c.className="item-content";let d=document.createElement("span");d.className="item-name",d.textContent=s.name,c.appendChild(d);let m=document.createElement("span");m.className="item-detail",m.textContent=s.table,c.appendChild(m),i.appendChild(c),a.appendChild(i)}),l.appendChild(a)}function Be(){let e=t.sidebarFilter.toLowerCase(),n=e.length>0,o=Se(t.schemaCache.tables,e),l=Se(t.schemaCache.views,e),a=Se(t.schemaCache.indexes,e);Te("tablesBadge",o.length,t.schemaCache.tables.length,n),Te("viewsBadge",l.length,t.schemaCache.views.length,n),Te("indexesBadge",a.length,t.schemaCache.indexes.length,n),xt("tablesList",o,"table","codicon-table",e?"No matching tables":"No tables"),xt("viewsList",l,"view","codicon-eye",e?"No matching views":"No views"),mn("indexesList",a,e?"No matching indexes":"No indexes")}function O(){let e=document.getElementById("batchUpdateSectionTitle"),n=document.getElementById("batchUpdateList"),o=document.getElementById("batchUpdateCount"),l=document.getElementById("batchUpdateFields");if(!e||!n||!o||!l)return;let a=t.selectedCells.length;if(a===0){e.classList.add("hidden"),n.classList.add("hidden");return}e.classList.remove("hidden"),n.classList.remove("hidden"),e.classList.remove("collapsed"),o.textContent=a;let s=ht(t.selectedCells,t.tableColumns);l.replaceChildren();let i=document.createDocumentFragment();for(let[r,c]of s){let d=yt(c.values),m=document.createElement("div");m.className="form-field batch-field",m.dataset.colidx=r,m.style.marginBottom="8px";let y=document.createElement("label");y.style.fontSize="11px",y.style.color="var(--text-secondary)";let f=document.createTextNode(c.name+" ");y.appendChild(f);let p=document.createElement("span");p.style.opacity="0.7",p.textContent=c.type||"",y.appendChild(p),m.appendChild(y);let g=document.createElement("div");g.style.display="flex",g.style.gap="4px";let b=document.createElement("input");b.type="text",b.className="batch-input",b.placeholder=d,b.dataset.colidx=r,b.style.flex="1",b.style.minWidth="0",g.appendChild(b);let E=document.createElement("button");E.className="btn-secondary btn-batch-null",E.style.padding="2px 6px",E.title="Set to NULL",E.textContent="NULL",g.appendChild(E);let h=document.createElement("button");h.className="btn-secondary btn-batch-patch",h.style.padding="2px 6px",h.title="JSON Patch",h.textContent="{}",g.appendChild(h),m.appendChild(g),i.appendChild(m)}l.appendChild(i)}async function pn(){if(t.selectedCells.length===0)return;let e=document.querySelectorAll(".batch-input"),n=new Map;for(let l of e){let a=parseInt(l.dataset.colidx,10);if(n.set(a,l),l.dataset.ispatch==="true")try{JSON.parse(l.value)}catch{let i=t.tableColumns[a];u(`Invalid JSON for patch in ${i?.name??`column ${a}`}`);return}}let o=Ct(t.selectedCells,n,t.tableColumns);if(o.length===0){u("No values entered for batch update");return}try{u(`Updating ${o.length} cells...`);let l=`Batch update ${o.length} cells`,a=o.map(r=>({rowId:r.rowId,column:r.column,value:r.value,originalValue:r.originalValue,operation:r.operation}));if(await x.updateCellBatch(t.selectedTable,a,l),!o.some(r=>r.operation==="json_patch"))for(let r of o)t.gridData[r.rowIdx][r.colIdx+B()]=r.value;await v(!1);let i=[];for(let r of t.selectedCells){let c=t.gridData[r.rowIdx][r.colIdx+B()];i.push({...r,value:c})}t.selectedCells=i,O(),u("Batch update completed")}catch(l){console.error("Batch update failed:",l),u(`Batch update failed: ${l.message}`)}}function fn(e){let n=document.querySelector(`.batch-input[data-colidx="${e}"]`),o=document.querySelector(`.batch-field[data-colidx="${e}"] .btn-batch-patch`);n&&(n.value="",n.placeholder="SET TO NULL",n.dataset.isnull="true",n.dataset.ispatch="false",n.style.fontStyle="italic",o&&(o.style.background="",o.style.color=""))}function gn(e,n){let o=document.querySelector(`.batch-input[data-colidx="${e}"]`);o&&(o.dataset.ispatch==="true"?(o.dataset.ispatch="false",o.placeholder="(mixed values)",n.style.background="",n.style.color=""):(o.dataset.ispatch="true",o.dataset.isnull="false",o.placeholder='JSON Patch (e.g. {"a": 1})',o.style.fontStyle="normal",n.style.background="var(--accent-color)",n.style.color="white"))}function hn(e){let n=document.getElementById(`${e}List`),o=document.querySelector(`.section-title[data-section="${e}"]`);n&&o&&(n.classList.toggle("hidden"),o.classList.toggle("collapsed"))}async function yn(e,n){t.selectedTable=e,t.selectedTableType=n,t.currentPageIndex=0,t.sortedColumn=null,t.sortAscending=!0,t.filterQuery="",t.columnFilters={},t.selectedRowIds.clear(),t.selectedCells=[],t.lastSelectedCell=null,t.selectedColumns.clear(),t.pinnedColumns.clear(),t.pinnedRowIds.clear(),t.columnWidths={},t.scrollPosition={top:0,left:0},Be();let o=document.getElementById("tableNameLabel");o&&(o.textContent=e);let l=document.getElementById("filterInput");l&&(l.value=""),await q(),await v(!0,!1),$()}async function Cn(){if(t.isDbConnected)try{u("Reloading..."),await x.refreshFile(),await V(),t.selectedTable&&(await q(),await v()),u("Reloaded")}catch(e){console.error("Reload failed:",e),u(`Reload failed: ${e.message}`)}}function wt(){document.getElementById("btnExport")?.addEventListener("click",xn),document.getElementById("btnSubmitExport")?.addEventListener("click",bn),document.getElementById("exportFormat")?.addEventListener("change",Et)}function xn(){if(!t.selectedTable)return;let e=document.getElementById("exportFormat");e&&(e.value="csv");let n=document.getElementById("exportColumns");n&&(n.replaceChildren(),t.tableColumns.forEach(o=>{let l=document.createElement("div"),a=document.createElement("label");Object.assign(a.style,{display:"flex",alignItems:"center",gap:"3px",marginBottom:"4px",fontSize:"13px",cursor:"pointer"});let s=document.createElement("input");s.type="checkbox",s.className="export-col-check",s.value=o.name,s.checked=!0,s.style.margin="0",a.appendChild(s),a.appendChild(document.createTextNode(o.name)),n.appendChild(a)})),Et(),j("exportModal")}function Et(){let e=document.getElementById("exportFormat").value,n=document.getElementById("exportOptions");if(n.replaceChildren(),e==="csv"||e==="excel"){let o=document.createElement("label");Object.assign(o.style,{display:"flex",alignItems:"center",gap:"3px",marginBottom:"4px",fontSize:"13px",cursor:"pointer"});let l=document.createElement("input");l.type="checkbox",l.id="exportHeader",l.checked=!0,l.style.margin="0",o.appendChild(l),o.appendChild(document.createTextNode(" Include Headers")),n.appendChild(o)}else if(e==="sql"){let o=document.createElement("label");Object.assign(o.style,{display:"flex",alignItems:"center",gap:"3px",marginBottom:"4px",fontSize:"13px",cursor:"pointer"});let l=document.createElement("input");l.type="checkbox",l.id="exportTableName",l.checked=!0,l.style.margin="0",o.appendChild(l),o.appendChild(document.createTextNode(" Include Table Name")),n.appendChild(o)}}async function bn(){let e=document.getElementById("exportFormat").value,n=document.querySelectorAll(".export-col-check:checked"),o=Array.from(n).map(a=>a.value);if(o.length===0){u("Error: Select at least one column");return}let l={};if(e==="csv"||e==="excel"?l.header=document.getElementById("exportHeader")?.checked??!0:e==="sql"&&(l.includeTableName=document.getElementById("exportTableName")?.checked??!0),t.selectedTableType==="table"){let a=Array.from(t.selectedRowIds);a.length>0&&(l.rowIds=a)}try{u("Exporting..."),U("exportModal"),await x.exportTable({table:t.selectedTable},o,null,null,{format:e,...l}),u("Export initiated")}catch(a){console.error("Export failed:",a),u(`Export failed: ${a.message}`)}}async function It(){if(t.selectedCells.length!==0)try{let e;if(t.selectedCells.length===1){let n=t.selectedCells[0].value;n==null?e="":n instanceof Uint8Array?e="[BLOB]":e=String(n)}else{let n=[...new Set(t.selectedCells.map(s=>s.rowIdx))].sort((s,i)=>s-i),o=[...new Set(t.selectedCells.map(s=>s.colIdx))].sort((s,i)=>s-i),l=new Map;for(let s of t.selectedCells)l.set(`${s.rowIdx},${s.colIdx}`,s.value);let a=[];for(let s of n){let i=[];for(let r of o){let c=`${s},${r}`,d=l.has(c)?l.get(c):"";d==null?d="":d instanceof Uint8Array?d="[BLOB]":(d=String(d),d=d.replace(/\t/g," ").replace(/\n/g," ")),i.push(d)}a.push(i.join(" "))}e=a.join(` `)}await navigator.clipboard.writeText(e),u(`Copied ${t.selectedCells.length} cell${t.selectedCells.length>1?"s":""}`)}catch(e){console.error("Copy failed:",e),u("Copy failed: "+e.message)}}async function vt(){if(t.selectedRowIds.size!==0)try{let e=[];for(let l=0;lc==null?"":c instanceof Uint8Array?"[BLOB]":String(c));e.push(r.join(" "))}}let o=[t.tableColumns.map(l=>l.name).join(" "),...e].join(` -`);await navigator.clipboard.writeText(o),u(`Copied ${e.length} row${e.length>1?"s":""} to clipboard`)}catch(e){console.error("Copy failed:",e),u("Copy failed: "+e.message)}}async function St(){if(t.selectedCells.length!==0){if(t.selectedTableType!=="table"){u("Views are read-only");return}try{u("Clearing cells...");let e=[];for(let o of t.selectedCells){let l=t.tableColumns[o.colIdx];if(!l)continue;let s=l.notnull===1?"":null;e.push({rowId:o.rowId,column:l.name,value:s,originalValue:o.value,rowIdx:o.rowIdx,colIdx:o.colIdx})}let n=`Clear ${e.length} cell${e.length>1?"s":""}`;await x.updateCellBatch(t.selectedTable,e,n);for(let o of e)t.gridData[o.rowIdx][o.colIdx+B()]=o.value;t.selectedCells=[],t.lastSelectedCell=null,t.selectedColumns.clear(),await v(),L(),u(`${n} - Ctrl+S to save`)}catch(e){console.error("Clear cells failed:",e),u(`Clear failed: ${e.message}`)}}}var ce=50*1024*1024,Re=!1;function Tt(){let e=document.getElementById("gridContainer");if(!e){console.error("gridContainer not found");return}document.addEventListener("dragover",n=>n.preventDefault()),document.addEventListener("drop",n=>n.preventDefault()),e.addEventListener("dragover",wn),e.addEventListener("dragleave",En),e.addEventListener("drop",In)}var F=null;function wn(e){e.preventDefault(),e.dataTransfer.dropEffect="copy";let n=e.target.closest(".data-cell");n&&!n.classList.contains("row-number")?(F&&F!==n&&F.classList.remove("drag-over"),n.classList.add("drag-over"),F=n):F&&(F.classList.remove("drag-over"),F=null)}function En(e){e.target}async function In(e){e.preventDefault(),F&&(F.classList.remove("drag-over"),F=null);let n=e.target.closest(".data-cell");if(!n||n.classList.contains("row-number"))return;if(e.dataTransfer.files.length>0){let l=e.dataTransfer.files[0];await vn(n,l.name,l);return}let o=e.dataTransfer.getData("text/uri-list");if(o){let l=o.split(/\r?\n/);if(l.length>0&&l[0]){let a=l[0],s="unknown_file";try{let i=a.split("/");s=decodeURIComponent(i[i.length-1])}catch(i){console.warn("Failed to parse name from URI",i)}await Sn(n,s,a);return}}}async function vn(e,n,o){if(o.size>ce){let l=(o.size/1048576).toFixed(1),a=(ce/(1024*1024)).toFixed(0);u(`File too large (${l}MB). Maximum is ${a}MB.`);return}try{u(`Reading ${n}...`);let l=await Tn(o),a=new Uint8Array(l);await Bt(e,n,a)}catch(l){console.error("File read failed:",l),u(`File read failed: ${l.message}`)}}async function Sn(e,n,o){try{u(`Fetching ${n}...`);let l=await x.readWorkspaceFileUri(o),a;if(l instanceof Uint8Array)a=l;else if(l&&l.type==="Buffer"&&Array.isArray(l.data))a=new Uint8Array(l.data);else if(l&&typeof l=="object"&&Object.keys(l).some(s=>!isNaN(s)))a=new Uint8Array(Object.values(l));else throw console.error("Unknown data format from backend:",l),new Error("Received invalid data format from backend");await Bt(e,n,a)}catch(l){console.error("URI upload failed:",l),u(`Upload failed: ${l.message}`)}}async function Bt(e,n,o){if(Re){u("Upload already in progress...");return}if(o.byteLength>ce){let c=(o.byteLength/1048576).toFixed(1),d=(ce/(1024*1024)).toFixed(0);u(`File too large (${c}MB). Maximum is ${d}MB.`);return}let l=parseInt(e.dataset.rowidx,10),a=parseInt(e.dataset.colidx,10);if(!t.gridData)return;let s=t.gridData[l];if(!s)return;let i=T(s,l),r=t.tableColumns[a];if(t.selectedTableType!=="table"){u("Cannot upload to a view");return}Re=!0,t.isLoadingData=!0;try{u(`Uploading ${n} (${Bn(o.byteLength)})...`);let c=s[a+B()];await x.updateCell(t.selectedTable,i,r.name,o,c),t.gridData[l][a+B()]=o,Rn(e,o),u(`Uploaded ${n}`)}catch(c){console.error("Upload failed:",c);let d=c.message||String(c);d.includes("timeout")&&(d="Upload timed out. Try a smaller file."),u(`Upload failed: ${d}`)}finally{Re=!1,t.isLoadingData=!1}}function Tn(e){return new Promise((n,o)=>{let l=new FileReader;l.onload=()=>n(l.result),l.onerror=()=>o(l.error),l.readAsArrayBuffer(e)})}function Bn(e){if(e===0)return"0 B";let n=1024,o=["B","KB","MB","GB"],l=Math.floor(Math.log(e)/Math.log(n));return parseFloat((e/Math.pow(n,l)).toFixed(2))+" "+o[l]}function Rn(e,n){let o=_(n);e.textContent="";let l=document.createElement("span");l.className="cell-text",l.textContent=o,e.appendChild(l);let a=document.createElement("span");a.className="expand-icon codicon codicon-link-external",a.title="View full content",e.appendChild(a),e.classList.remove("null-value")}var Rt={async refreshContent(e){return t.isDbConnected&&(await V(),!(t.schemaCache.tables.some(o=>o.name===t.selectedTable)||t.schemaCache.views.some(o=>o.name===t.selectedTable))&&t.selectedTable?(t.selectedTable=null,t.selectedTableType=null,document.getElementById("tableNameLabel").textContent="No table selected",xe()):t.selectedTable&&await v(!1)),{success:!0}},async updateColorScheme(e){return document.documentElement.style.colorScheme=e,{success:!0}},async updateCellEditBehavior(e){return t.cellEditBehavior=e,{success:!0}}};function Ln(){window.addEventListener("message",e=>{let n=e.data;if(n&&n.kind==="invoke"){let{correlationId:l,methodName:a,parameters:s}=n,i=Rt[a];typeof i=="function"?Promise.resolve(i.apply(Rt,s||[])).then(r=>{Ae(l,r)}).catch(r=>{ye(l,r instanceof Error?r.message:String(r))}):ye(l,`Unknown method: ${a}`);return}if(!n||n.channel!=="rpc")return;let o=n.content;o&&o.kind==="response"&&ke(o)})}Ln();async function Pn(){try{bt(),dt(),wt(),ct(),ft(),ze(),it(),rt(),Me(),Tt();let e=document.getElementById("openInVsCodeBtn");e&&(e.style.display="none"),u("Connecting to database...");let n=await x.initialize();t.isDbConnected=!0,await x.ping(),await V(),u("Ready"),xe(),document.addEventListener("keydown",async o=>{if(o.key==="Escape"&&!t.editingCellInfo&&!document.querySelector(".modal-overlay:not(.hidden)")&&oe(),(o.metaKey||o.ctrlKey)&&o.key==="c"){if(t.editingCellInfo||document.activeElement.tagName==="INPUT")return;t.selectedCells.length>0?(o.preventDefault(),await It()):t.selectedRowIds.size>0&&(o.preventDefault(),await vt())}if((o.metaKey||o.ctrlKey)&&o.key==="a"){if(t.editingCellInfo||document.activeElement.tagName==="INPUT")return;t.selectedTable&&(o.preventDefault(),ie(o))}if((o.metaKey||o.ctrlKey)&&(o.key==="Delete"||o.key==="Backspace")){if(t.editingCellInfo||document.activeElement.tagName==="INPUT"||document.activeElement.tagName==="TEXTAREA")return;t.selectedTable&&t.selectedTableType==="table"&&(o.preventDefault(),t.selectedColumns.size>0?await re():t.selectedRowIds.size>0?await re():t.selectedCells.length>0&&await St())}})}catch(e){console.error("Init error:",e),ne(e.message)}}Pn();})(); +`);await navigator.clipboard.writeText(o),u(`Copied ${e.length} row${e.length>1?"s":""} to clipboard`)}catch(e){console.error("Copy failed:",e),u("Copy failed: "+e.message)}}async function St(){if(t.selectedCells.length!==0){if(t.selectedTableType!=="table"){u("Views are read-only");return}try{u("Clearing cells...");let e=[];for(let o of t.selectedCells){let l=t.tableColumns[o.colIdx];if(!l)continue;let s=l.notnull===1?"":null;e.push({rowId:o.rowId,column:l.name,value:s,originalValue:o.value,rowIdx:o.rowIdx,colIdx:o.colIdx})}let n=`Clear ${e.length} cell${e.length>1?"s":""}`;await x.updateCellBatch(t.selectedTable,e,n);for(let o of e)t.gridData[o.rowIdx][o.colIdx+B()]=o.value;t.selectedCells=[],t.lastSelectedCell=null,t.selectedColumns.clear(),await v(),L(),u(`${n} - Ctrl+S to save`)}catch(e){console.error("Clear cells failed:",e),u(`Clear failed: ${e.message}`)}}}var ce=50*1024*1024,Re=!1;function Tt(){let e=document.getElementById("gridContainer");if(!e){console.error("gridContainer not found");return}document.addEventListener("dragover",n=>n.preventDefault()),document.addEventListener("drop",n=>n.preventDefault()),e.addEventListener("dragover",wn),e.addEventListener("dragleave",En),e.addEventListener("drop",In)}var F=null;function wn(e){e.preventDefault(),e.dataTransfer.dropEffect="copy";let n=e.target.closest(".data-cell");n&&!n.classList.contains("row-number")?(F&&F!==n&&F.classList.remove("drag-over"),n.classList.add("drag-over"),F=n):F&&(F.classList.remove("drag-over"),F=null)}function En(e){e.target}async function In(e){e.preventDefault(),F&&(F.classList.remove("drag-over"),F=null);let n=e.target.closest(".data-cell");if(!n||n.classList.contains("row-number"))return;if(e.dataTransfer.files.length>0){let l=e.dataTransfer.files[0];await vn(n,l.name,l);return}let o=e.dataTransfer.getData("text/uri-list");if(o){let l=o.split(/\r?\n/);if(l.length>0&&l[0]){let a=l[0],s="unknown_file";try{let i=a.split("/");s=decodeURIComponent(i[i.length-1])}catch(i){console.warn("Failed to parse name from URI",i)}await Sn(n,s,a);return}}}async function vn(e,n,o){if(o.size>ce){let l=(o.size/1048576).toFixed(1),a=(ce/(1024*1024)).toFixed(0);u(`File too large (${l}MB). Maximum is ${a}MB.`);return}try{u(`Reading ${n}...`);let l=await Tn(o),a=new Uint8Array(l);await Bt(e,n,a)}catch(l){console.error("File read failed:",l),u(`File read failed: ${l.message}`)}}async function Sn(e,n,o){try{u(`Fetching ${n}...`);let l=await x.readWorkspaceFileUri(o),a;if(l instanceof Uint8Array)a=l;else if(l&&l.type==="Buffer"&&Array.isArray(l.data))a=new Uint8Array(l.data);else if(l&&typeof l=="object"&&Object.keys(l).some(s=>!isNaN(s)))a=new Uint8Array(Object.values(l));else throw console.error("Unknown data format from backend:",l),new Error("Received invalid data format from backend");await Bt(e,n,a)}catch(l){console.error("URI upload failed:",l),u(`Upload failed: ${l.message}`)}}async function Bt(e,n,o){if(Re){u("Upload already in progress...");return}if(o.byteLength>ce){let c=(o.byteLength/1048576).toFixed(1),d=(ce/(1024*1024)).toFixed(0);u(`File too large (${c}MB). Maximum is ${d}MB.`);return}let l=parseInt(e.dataset.rowidx,10),a=parseInt(e.dataset.colidx,10);if(!t.gridData)return;let s=t.gridData[l];if(!s)return;let i=T(s,l),r=t.tableColumns[a];if(t.selectedTableType!=="table"){u("Cannot upload to a view");return}Re=!0,t.isLoadingData=!0;try{u(`Uploading ${n} (${Bn(o.byteLength)})...`);let c=s[a+B()];await x.updateCell(t.selectedTable,i,r.name,o,c),t.gridData[l][a+B()]=o,Rn(e,o),u(`Uploaded ${n}`)}catch(c){console.error("Upload failed:",c);let d=c.message||String(c);d.includes("timeout")&&(d="Upload timed out. Try a smaller file."),u(`Upload failed: ${d}`)}finally{Re=!1,t.isLoadingData=!1}}function Tn(e){return new Promise((n,o)=>{let l=new FileReader;l.onload=()=>n(l.result),l.onerror=()=>o(l.error),l.readAsArrayBuffer(e)})}function Bn(e){if(e===0)return"0 B";let n=1024,o=["B","KB","MB","GB"],l=Math.floor(Math.log(e)/Math.log(n));return parseFloat((e/Math.pow(n,l)).toFixed(2))+" "+o[l]}function Rn(e,n){let o=_(n);e.textContent="";let l=document.createElement("span");l.className="cell-text",l.textContent=o,e.appendChild(l);let a=document.createElement("span");a.className="expand-icon codicon codicon-link-external",a.title="View full content",e.appendChild(a),e.classList.remove("null-value")}var Rt={async refreshContent(e){return t.isDbConnected&&(await V(),!(t.schemaCache.tables.some(o=>o.name===t.selectedTable)||t.schemaCache.views.some(o=>o.name===t.selectedTable))&&t.selectedTable?(t.selectedTable=null,t.selectedTableType=null,document.getElementById("tableNameLabel").textContent="No table selected",xe()):t.selectedTable&&await v(!1)),{success:!0}},async updateColorScheme(e){return document.documentElement.style.colorScheme=e,{success:!0}},async updateCellEditBehavior(e){return t.cellEditBehavior=e,{success:!0}}};function Ln(){window.addEventListener("message",e=>{let n=e.data;if(n&&n.kind==="invoke"){let{correlationId:l,methodName:a,parameters:s}=n,i=Rt[a];typeof i=="function"?Promise.resolve(i.apply(Rt,s||[])).then(r=>{Ae(l,r)}).catch(r=>{ye(l,r instanceof Error?r.message:String(r))}):ye(l,`Unknown method: ${a}`);return}if(!n||n.channel!=="rpc")return;let o=n.content;o&&o.kind==="response"&&ke(o)})}Ln();async function Pn(){try{bt(),dt(),wt(),ct(),ft(),ze(),it(),rt(),Me(),Tt();let e=document.getElementById("openInVsCodeBtn");e&&(e.style.display="none"),u("Connecting to database...");let n=await x.initialize();t.isDbConnected=!0,await x.ping(),await V(),u("Ready"),xe(),document.addEventListener("keydown",async o=>{if(o.key==="Escape"&&!t.editingCellInfo&&!document.querySelector(".modal-overlay:not(.hidden)")&&oe(),(o.metaKey||o.ctrlKey)&&o.key==="c"){if(t.editingCellInfo||document.activeElement.tagName==="INPUT")return;t.selectedCells.length>0?(o.preventDefault(),await It()):t.selectedRowIds.size>0&&(o.preventDefault(),await vt())}if((o.metaKey||o.ctrlKey)&&o.key==="a"){if(t.isGridReloading||t.editingCellInfo||document.activeElement.tagName==="INPUT")return;t.selectedTable&&(o.preventDefault(),ie(o))}if((o.metaKey||o.ctrlKey)&&(o.key==="Delete"||o.key==="Backspace")){if(t.isGridReloading||t.editingCellInfo||document.activeElement.tagName==="INPUT"||document.activeElement.tagName==="TEXTAREA")return;t.selectedTable&&t.selectedTableType==="table"&&(o.preventDefault(),t.selectedColumns.size>0?await re():t.selectedRowIds.size>0?await re():t.selectedCells.length>0&&await St())}})}catch(e){console.error("Init error:",e),ne(e.message)}}Pn();})(); From 934acec35971253067069b4b4733a663480896a9 Mon Sep 17 00:00:00 2001 From: zknpr Date: Sun, 21 Jun 2026 22:36:15 +0200 Subject: [PATCH 9/9] fix: block BLOB drag/drop during grid reloads (Codex round 6) dnd.js registers dragover/drop on #gridContainer. The flicker fix keeps stale .data-cell elements mounted during a same-table refetch, so a file dropped on a cell mid-reload uploaded to the old row/column that the incoming result set was about to replace. Guard onDrop and onDragOver on state.isGridReloading (no drop target offered, drops ignored, while a reload is in flight). dnd.js is shared by both the extension (viewer.js) and the web demo (web-viewer.js), so this covers both. Audited the rest of the interaction surface: no paste or contextmenu handlers exist, so click + keyboard + drag/drop is the full set of stale-grid entry points. Regenerated both bundles. Co-Authored-By: Claude Opus 4.8 (1M context) --- core/ui/modules/dnd.js | 17 +++++++++++++++++ core/ui/viewer.html | 10 +++++----- website/public/sqlite-viewer/viewer.html | 10 +++++----- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/core/ui/modules/dnd.js b/core/ui/modules/dnd.js index fb1ca9e0..52b82494 100644 --- a/core/ui/modules/dnd.js +++ b/core/ui/modules/dnd.js @@ -35,6 +35,18 @@ let lastHighlightedCell = null; function onDragOver(e) { e.preventDefault(); + + // Don't offer a drop target while a grid reload is in flight: the cells under + // the cursor are stale and about to be replaced. Leave dropEffect unset so the + // cursor shows "no-drop", and clear any lingering highlight. + if (state.isGridReloading) { + if (lastHighlightedCell) { + lastHighlightedCell.classList.remove('drag-over'); + lastHighlightedCell = null; + } + return; + } + e.dataTransfer.dropEffect = 'copy'; const cell = e.target.closest('.data-cell'); @@ -64,6 +76,11 @@ async function onDrop(e) { lastHighlightedCell = null; } + // Ignore drops while a grid reload is in flight: the targeted cell belongs to + // the stale result set about to be replaced, so the upload would land on the + // wrong row/column once the new data renders. + if (state.isGridReloading) return; + const cell = e.target.closest('.data-cell'); if (!cell || cell.classList.contains('row-number')) { return; diff --git a/core/ui/viewer.html b/core/ui/viewer.html index 22d6399b..55a82b68 100644 --- a/core/ui/viewer.html +++ b/core/ui/viewer.html @@ -364,7 +364,7 @@ diff --git a/website/public/sqlite-viewer/viewer.html b/website/public/sqlite-viewer/viewer.html index 154027db..aa96d822 100644 --- a/website/public/sqlite-viewer/viewer.html +++ b/website/public/sqlite-viewer/viewer.html @@ -364,7 +364,7 @@