window.robotnet = window.robotnet || {}; robotnet.console = { init: function (dotNetRef) { // Initialization if needed }, addMessage: function (level, message, autoScroll) { const container = document.getElementById('console-content'); if (!container) return; const messageDiv = document.createElement('div'); messageDiv.className = `console-message console-message-${level.toLowerCase()}`; const timestamp = new Date().toLocaleTimeString(); const levelSpan = document.createElement('span'); levelSpan.className = 'console-level'; levelSpan.textContent = level; const timeSpan = document.createElement('span'); timeSpan.className = 'console-time'; timeSpan.textContent = timestamp; const messageSpan = document.createElement('span'); messageSpan.className = 'console-text'; messageSpan.textContent = message; messageDiv.appendChild(levelSpan); messageDiv.appendChild(timeSpan); messageDiv.appendChild(messageSpan); container.appendChild(messageDiv); if (autoScroll) { container.scrollTop = container.scrollHeight; } }, clear: function () { const container = document.getElementById('console-content'); if (!container) return; // Xóa tất cả messages bằng cách set innerHTML rỗng container.innerHTML = ''; }, toggleCollapse: function () { const container = document.getElementById('console-content'); const consolePanel = document.getElementById('console-panel'); const consoleHeader = document.querySelector('.console-header'); const verticalResizer = document.querySelector('.vertical-resizer'); const toggleButton = document.querySelector('.console-container .btn-toggle'); const iconSpan = toggleButton?.querySelector('span'); if (!container || !consolePanel || !toggleButton || !iconSpan) return; // Check trạng thái hiện tại trước khi toggle const wasCollapsed = container.classList.contains('collapsed'); // Toggle collapsed class trên cả console-content và console-panel container.classList.toggle('collapsed'); consolePanel.classList.toggle('collapsed'); // Tính toán và set height cho console-panel sau khi toggle if (!wasCollapsed) { // Đang collapse - set height về chỉ còn header if (consoleHeader) { const headerHeight = consoleHeader.offsetHeight; consolePanel.style.height = headerHeight + 'px'; } else { consolePanel.style.height = '40px'; // Fallback height } // Ẩn vertical resizer khi collapsed if (verticalResizer) { verticalResizer.style.display = 'none'; } // Update icon iconSpan.className = 'mdi mdi-chevron-up'; toggleButton.title = 'Expand Console'; } else { // Đang expand - restore về height mặc định consolePanel.style.height = '200px'; // Hiện vertical resizer khi expanded if (verticalResizer) { verticalResizer.style.display = ''; } // Update icon iconSpan.className = 'mdi mdi-chevron-down'; toggleButton.title = 'Collapse Console'; } } }; robotnet.monaco = { CSharpLanguageRegisterSignatureHelpProvider: (dotnetRef, getSignatureHelpMethod) => { return monaco.languages.registerSignatureHelpProvider("csharp", { signatureHelpTriggerCharacters: ['('], provideSignatureHelp: async (model, position, token, context) => { let signature = await dotnetRef.invokeMethodAsync(getSignatureHelpMethod, model.uri.toString(), position.lineNumber, position.column); if (!signature) { return undefined; } return { value: signature.value, dispose: () => { }, } } }); }, } robotnet.blazor = { getResourcePath: function (logicalName) { // In .NET 10, try to get resource path from Blazor runtime // Strategy 1: Try to access via window.Blazor or Blazor._internal if (window.Blazor && window.Blazor._internal) { try { // Try to get resource mapping from Blazor internal APIs var resources = window.Blazor._internal.resources; if (resources && resources.assembly) { var assemblyName = logicalName.replace('.wasm', ''); if (resources.assembly[assemblyName]) { return '/_framework/' + resources.assembly[assemblyName]; } } } catch (e) { // Fallback to direct path } } // Strategy 2: Try direct path (NET 10+) // In .NET 10, resources might be directly accessible return '/_framework/' + logicalName; } } window.fileExplorer = { init: function (element) { // Initialize file explorer interactions // Currently no initialization needed as we use MudMenu for context menus // This function is kept for future use if needed }, updateFileBadges: function (fileId, showWarning, showError, showModified, warningCount, errorCount, fileName) { if (!fileId) return; // Update name const nameElement = document.querySelector(`[data-file-id="${fileId}"][data-name="name"]`); if (nameElement) { nameElement.textContent = fileName; } // Update warning badge const warningBadge = document.querySelector(`[data-file-id="${fileId}"][data-badge="warning"]`); if (warningBadge) { warningBadge.textContent = warningCount; warningBadge.setAttribute('data-count', warningCount); warningBadge.setAttribute('title', `${warningCount} warning(s)`); if (showWarning) { warningBadge.classList.remove('hidden'); } else { warningBadge.classList.add('hidden'); } } // Update error badge const errorBadge = document.querySelector(`[data-file-id="${fileId}"][data-badge="error"]`); if (errorBadge) { errorBadge.textContent = errorCount; errorBadge.setAttribute('data-count', errorCount); errorBadge.setAttribute('title', `${errorCount} error(s)`); if (showError) { errorBadge.classList.remove('hidden'); } else { errorBadge.classList.add('hidden'); } } // Update modified badge const modifiedBadge = document.querySelector(`[data-file-id="${fileId}"][data-badge="modified"]`); if (modifiedBadge) { if (showModified) { modifiedBadge.classList.remove('hidden'); } else { modifiedBadge.classList.add('hidden'); } } }, CheckRadioById: function (id) { const radio = document.getElementById(id); if (radio) { radio.checked = true; // Trigger change event to ensure CSS :has(:checked) selector works radio.dispatchEvent(new Event('change', { bubbles: true })); } }, UncheckRadioByName: function (name) { const radios = document.querySelectorAll(`input[type="radio"][name="${name}"]`); radios.forEach(radio => radio.checked = false); }, updateFolderBadges: function (folderPath, showWarning, showError, showModified, warningCount, errorCount, folderName) { if (!folderPath) return; // Update name const nameElement = document.querySelector(`[data-folder-path="${folderPath}"][data-name="name"]`); if (nameElement) { nameElement.textContent = folderName; } // Update warning badge const warningBadge = document.querySelector(`[data-folder-path="${folderPath}"][data-badge="warning"]`); if (warningBadge) { warningBadge.textContent = warningCount; warningBadge.setAttribute('data-count', warningCount); warningBadge.setAttribute('title', `${warningCount} warning(s)`); if (showWarning) { warningBadge.classList.remove('hidden'); } else { warningBadge.classList.add('hidden'); } } // Update error badge const errorBadge = document.querySelector(`[data-folder-path="${folderPath}"][data-badge="error"]`); if (errorBadge) { errorBadge.textContent = errorCount; errorBadge.setAttribute('data-count', errorCount); errorBadge.setAttribute('title', `${errorCount} error(s)`); if (showError) { errorBadge.classList.remove('hidden'); } else { errorBadge.classList.add('hidden'); } } // Update modified badge const modifiedBadge = document.querySelector(`[data-folder-path="${folderPath}"][data-badge="modified"]`); if (modifiedBadge) { if (showModified) { modifiedBadge.classList.remove('hidden'); } else { modifiedBadge.classList.add('hidden'); } } } };