// MarkLite — Tabs Module (function () { 'use strict'; var ML = window.MarkLite; // ===== Tab State ===== ML.tabs = []; ML.activeTabId = null; var tabIdCounter = 0; ML.mruTabStack = []; ML.createTab = function (filePath, content) { var id = ++tabIdCounter; return { id: id, filePath: filePath || null, content: content || '', isModified: false, scrollTop: 0, scrollLeft: 0, selectionStart: 0, selectionEnd: 0, previewScrollTop: 0 }; }; ML.getActiveTab = function () { return ML.tabs.find(function (t) { return t.id === ML.activeTabId; }) || null; }; ML.getTabIndex = function (tabId) { return ML.tabs.findIndex(function (t) { return t.id === tabId; }); }; ML.saveCurrentTabState = function () { var tab = ML.getActiveTab(); if (!tab) return; tab.content = ML.editor.value; tab.scrollTop = ML.editor.scrollTop; tab.scrollLeft = ML.editor.scrollLeft; tab.selectionStart = ML.editor.selectionStart; tab.selectionEnd = ML.editor.selectionEnd; tab.previewScrollTop = ML.previewPanel.scrollTop; }; ML.loadTabState = function (tab) { ML.editor.focus(); ML.editor.select(); var inserted = document.execCommand('insertText', false, tab.content); if (!inserted) ML.editor.value = tab.content; ML.lineCountCache = 0; ML.updateLineNumbers(); ML.renderMarkdown(tab.content); ML.updateFileSize(); ML.cachePreviewPositions(); requestAnimationFrame(function () { ML.editor.scrollTop = tab.scrollTop; ML.editor.scrollLeft = tab.scrollLeft; ML.lineNumbers.scrollTop = tab.scrollTop; ML.editor.setSelectionRange(tab.selectionStart, tab.selectionEnd); ML.previewPanel.scrollTop = tab.previewScrollTop; ML.updateCursorPosition(); }); ML.setModified(tab.isModified); if (typeof window.electronAPI !== 'undefined') window.electronAPI.tabSwitched(tab.filePath); }; ML.setModified = function (modified) { var tab = ML.getActiveTab(); if (tab) { tab.isModified = modified; var tabEl = ML.tabList.querySelector('.tab-item[data-tab-id="' + tab.id + '"]'); if (tabEl) tabEl.classList.toggle('modified', modified); } ML.updateTitle(); }; ML.createNewTab = function (filePath, content) { if (filePath) { var existing = ML.tabs.find(function (t) { return t.filePath === filePath; }); if (existing) { ML.switchToTab(existing.id); return existing; } } var tab = ML.createTab(filePath, content); ML.tabs.push(tab); ML.switchToTab(tab.id); return tab; }; ML.switchToTab = function (tabId) { if (tabId === ML.activeTabId) return; ML.saveCurrentTabState(); if (ML.activeTabId) { ML.mruTabStack = ML.mruTabStack.filter(function (id) { return id !== ML.activeTabId; }); ML.mruTabStack.unshift(ML.activeTabId); } ML.activeTabId = tabId; var tab = ML.getActiveTab(); if (!tab) return; ML.loadTabState(tab); ML.renderTabBar(); ML.updateTitle(); ML.updateSidebarHighlight(); ML.welcomeScreen.classList.add('hidden'); }; ML.closeTab = function (tabId) { var index = ML.getTabIndex(tabId); if (index === -1) return; var tab = ML.tabs[index]; if (tab.isModified) { var name = tab.filePath ? ML.getFileName(tab.filePath) : '未命名'; if (!confirm('"' + name + '" 尚未保存,确定要关闭吗?')) return; } ML.tabs.splice(index, 1); ML.mruTabStack = ML.mruTabStack.filter(function (id) { return id !== tabId; }); if (tabId === ML.activeTabId) { if (ML.tabs.length === 0) { ML.activeTabId = null; ML.editor.value = ''; ML.preview.innerHTML = ''; ML.lineNumbers.innerHTML = ''; ML.lineCountCache = 0; ML.statusSize.textContent = ''; ML.statusSizeDivider.classList.remove('visible'); ML.welcomeScreen.classList.remove('hidden'); document.title = 'MarkLite'; ML.statusText.textContent = '就绪'; if (typeof window.electronAPI !== 'undefined') window.electronAPI.tabSwitched(null); } else { var newIndex = Math.min(index, ML.tabs.length - 1); ML.activeTabId = ML.tabs[newIndex].id; ML.loadTabState(ML.tabs[newIndex]); } } ML.renderTabBar(); ML.updateTitle(); ML.updateSidebarHighlight(); }; ML.renderTabBar = function () { ML.tabList.innerHTML = ''; ML.tabs.forEach(function (tab) { var el = document.createElement('div'); el.className = 'tab-item' + (tab.id === ML.activeTabId ? ' active' : '') + (tab.isModified ? ' modified' : ''); el.dataset.tabId = tab.id; var name = document.createElement('span'); name.className = 'tab-name'; name.textContent = tab.filePath ? ML.getFileName(tab.filePath) : '未命名'; el.appendChild(name); var close = document.createElement('button'); close.className = 'tab-close'; close.innerHTML = ''; close.addEventListener('click', function (e) { e.stopPropagation(); ML.closeTab(tab.id); }); el.appendChild(close); el.addEventListener('click', function () { ML.switchToTab(tab.id); }); ML.tabList.appendChild(el); }); }; ML.updateTitle = function () { var tab = ML.getActiveTab(); if (tab) { var name = tab.filePath ? ML.getFileName(tab.filePath) : '未命名'; var mod = tab.isModified ? ' *' : ''; document.title = 'MarkLite - ' + name + mod; ML.statusText.textContent = name; } else { document.title = 'MarkLite'; ML.statusText.textContent = '就绪'; } }; })();