Skip to content

Commit ae5224a

Browse files
ozgesolidkeyclaude
andcommitted
Convert bottom panels to push-up layout, improve scroll, and clean up toolbar
- Change notes, search results, and search configs panels from absolute overlay to flex layout so editor shrinks and horizontal scrollbar stays visible - Improve horizontal scroll: remove speed factor for trackpad, add 3x multiplier for mouse wheel, add Shift+scroll for horizontal scrolling - Scope JSON format warning to only .json/.jsonl/.ndjson files - Remove toolbar settings and sidebar toggle buttons (already in activity bar) - Move settings modal + Datadog config loading to activity bar settings button Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent dab3995 commit ae5224a

3 files changed

Lines changed: 50 additions & 186 deletions

File tree

src/renderer/index.html

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,7 @@
7777
<div class="toolbar-right">
7878
<button id="btn-notes-toggle" class="toolbar-btn small" title="Toggle Notes (Ctrl+Shift+N)">&#128221;</button>
7979
<button id="btn-terminal-toggle" class="toolbar-btn small" title="Toggle Terminal (Ctrl+`)">&#9000;</button>
80-
<button id="btn-settings" class="toolbar-btn small" title="Settings">&#9881;</button>
8180
<button id="btn-help" class="toolbar-btn small" title="Keyboard shortcuts & help (F1)">&#9432;</button>
82-
<button id="btn-toggle-sidebar" class="toolbar-btn small" title="Toggle sidebar">&#9776;</button>
8381
</div>
8482
</div>
8583

src/renderer/renderer.ts

Lines changed: 47 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,6 @@ const elements = {
656656
btnNextResult: document.getElementById('btn-next-result') as HTMLButtonElement,
657657
btnFilter: document.getElementById('btn-filter') as HTMLButtonElement,
658658
btnAnalyze: document.getElementById('btn-analyze') as HTMLButtonElement,
659-
btnToggleSidebar: document.getElementById('btn-toggle-sidebar') as HTMLButtonElement,
660659
searchInput: document.getElementById('search-input') as HTMLInputElement,
661660
searchRegex: document.getElementById('search-regex') as HTMLInputElement,
662661
searchWildcard: document.getElementById('search-wildcard') as HTMLInputElement,
@@ -768,7 +767,6 @@ const elements = {
768767
helpModal: document.getElementById('help-modal') as HTMLDivElement,
769768
btnCloseHelp: document.getElementById('btn-close-help') as HTMLButtonElement,
770769
// Settings
771-
btnSettings: document.getElementById('btn-settings') as HTMLButtonElement,
772770
settingsModal: document.getElementById('settings-modal') as HTMLDivElement,
773771
scrollSpeedSlider: document.getElementById('scroll-speed') as HTMLInputElement,
774772
scrollSpeedValue: document.getElementById('scroll-speed-value') as HTMLSpanElement,
@@ -1868,20 +1866,26 @@ function createLogViewer(): void {
18681866
let deltaX = e.deltaX;
18691867

18701868
if (e.deltaMode === 0) {
1871-
// Pixel-based scrolling (trackpad) - apply user's scroll speed setting
1869+
// Pixel-based scrolling (trackpad) - apply user's scroll speed setting for vertical only
18721870
const speedFactor = userSettings.scrollSpeed / 100;
18731871
deltaY = deltaY * speedFactor;
1874-
deltaX = deltaX * speedFactor;
1872+
// Horizontal scroll uses raw pixel values for natural trackpad feel
18751873
} else if (e.deltaMode === 1) {
18761874
// Line-based scrolling (mouse wheel) - convert to pixels
18771875
deltaY = deltaY * getLineHeight();
1878-
deltaX = deltaX * getLineHeight();
1876+
deltaX = deltaX * getLineHeight() * 3; // 3x multiplier for faster horizontal nav
18791877
} else if (e.deltaMode === 2) {
18801878
// Page-based scrolling - convert to pixels
18811879
deltaY = deltaY * logViewerElement!.clientHeight;
18821880
deltaX = deltaX * logViewerElement!.clientWidth;
18831881
}
18841882

1883+
// Shift+Scroll: convert vertical scroll to horizontal for easy line navigation
1884+
if (e.shiftKey && deltaY !== 0 && deltaX === 0) {
1885+
deltaX = deltaY;
1886+
deltaY = 0;
1887+
}
1888+
18851889
// Apply normalized vertical scroll
18861890
const newScrollTop = logViewerElement!.scrollTop + deltaY;
18871891
const maxScrollY = logViewerElement!.scrollHeight - logViewerElement!.clientHeight;
@@ -4246,22 +4250,9 @@ function showNotesDrawer(): void {
42464250
if (state.searchConfigsPanelVisible) {
42474251
closeSearchConfigsPanel();
42484252
}
4249-
const overlay = elements.notesOverlay;
4250-
overlay.classList.remove('hidden');
4251-
// Force reflow so the transition triggers from initial state
4252-
void overlay.offsetHeight;
4253-
overlay.classList.add('visible');
4253+
elements.notesOverlay.classList.remove('hidden');
42544254
elements.btnNotesToggle.classList.add('active');
4255-
4256-
// Focus textarea after slide animation completes
4257-
const drawer = overlay.querySelector('.notes-drawer') as HTMLElement;
4258-
if (drawer) {
4259-
const onShown = () => {
4260-
drawer.removeEventListener('transitionend', onShown);
4261-
elements.notesTextarea.focus();
4262-
};
4263-
drawer.addEventListener('transitionend', onShown);
4264-
}
4255+
elements.notesTextarea.focus();
42654256

42664257
// Load notes content
42674258
window.api.loadNotes().then((result) => {
@@ -4274,20 +4265,8 @@ function showNotesDrawer(): void {
42744265
}
42754266

42764267
function hideNotesDrawer(): void {
4277-
const overlay = elements.notesOverlay;
4278-
overlay.classList.remove('visible');
4268+
elements.notesOverlay.classList.add('hidden');
42794269
elements.btnNotesToggle.classList.remove('active');
4280-
// Fallback if transitionend doesn't fire (e.g., display:none, no transition)
4281-
const fallback = setTimeout(() => hide(), 350);
4282-
const hide = () => {
4283-
clearTimeout(fallback);
4284-
overlay.removeEventListener('transitionend', onEnd);
4285-
if (!overlay.classList.contains('visible')) {
4286-
overlay.classList.add('hidden');
4287-
}
4288-
};
4289-
const onEnd = () => hide();
4290-
overlay.addEventListener('transitionend', onEnd);
42914270
}
42924271

42934272
function toggleNotesDrawer(): void {
@@ -4372,25 +4351,11 @@ function showSearchResultsPanel(): void {
43724351
closeSearchConfigsPanel();
43734352
}
43744353
state.searchResultsPanelVisible = true;
4375-
const overlay = elements.searchResultsOverlay;
4376-
overlay.classList.remove('hidden');
4377-
void overlay.offsetHeight;
4378-
overlay.classList.add('visible');
4354+
elements.searchResultsOverlay.classList.remove('hidden');
43794355
}
43804356

43814357
function hideSearchResultsPanel(): void {
4382-
const overlay = elements.searchResultsOverlay;
4383-
overlay.classList.remove('visible');
4384-
const fallback = setTimeout(() => hide(), 350);
4385-
const hide = () => {
4386-
clearTimeout(fallback);
4387-
overlay.removeEventListener('transitionend', onEnd);
4388-
if (!overlay.classList.contains('visible')) {
4389-
overlay.classList.add('hidden');
4390-
}
4391-
};
4392-
const onEnd = () => hide();
4393-
overlay.addEventListener('transitionend', onEnd);
4358+
elements.searchResultsOverlay.classList.add('hidden');
43944359
}
43954360

43964361
function toggleSearchResultsPanel(): void {
@@ -4537,27 +4502,13 @@ function showSearchConfigsPanel(): void {
45374502
if (state.notesVisible) closeNotesDrawer();
45384503
if (state.searchResultsPanelVisible) closeSearchResultsPanel();
45394504
state.searchConfigsPanelVisible = true;
4540-
const overlay = elements.searchConfigsOverlay;
4541-
overlay.classList.remove('hidden');
4542-
void overlay.offsetHeight;
4543-
overlay.classList.add('visible');
4505+
elements.searchConfigsOverlay.classList.remove('hidden');
45444506
elements.btnSearchConfigs.classList.add('active');
45454507
}
45464508

45474509
function hideSearchConfigsPanel(): void {
4548-
const overlay = elements.searchConfigsOverlay;
4549-
overlay.classList.remove('visible');
4510+
elements.searchConfigsOverlay.classList.add('hidden');
45504511
elements.btnSearchConfigs.classList.remove('active');
4551-
const fallback = setTimeout(() => hide(), 350);
4552-
const hide = () => {
4553-
clearTimeout(fallback);
4554-
overlay.removeEventListener('transitionend', onEnd);
4555-
if (!overlay.classList.contains('visible')) {
4556-
overlay.classList.add('hidden');
4557-
}
4558-
};
4559-
const onEnd = () => hide();
4560-
overlay.addEventListener('transitionend', onEnd);
45614512
}
45624513

45634514
function toggleSearchConfigsPanel(): void {
@@ -5087,8 +5038,10 @@ async function loadFile(filePath: string, createNewTab: boolean = true): Promise
50875038
elements.btnColumns.disabled = false;
50885039
state.columnConfig = null; // Reset column config for new file
50895040

5090-
// Show warning for files with long lines
5091-
if (result.hasLongLines) {
5041+
// Show warning for files with long lines (only for JSON-like files where reformatting helps)
5042+
const lowerPath = filePath.toLowerCase();
5043+
const isJsonLike = lowerPath.endsWith('.json') || lowerPath.endsWith('.jsonl') || lowerPath.endsWith('.ndjson');
5044+
if (result.hasLongLines && isJsonLike) {
50925045
elements.longLinesWarning.classList.remove('hidden');
50935046
} else {
50945047
elements.longLinesWarning.classList.add('hidden');
@@ -7927,8 +7880,33 @@ function setupActivityBar(): void {
79277880
elements.btnPinPanel.addEventListener('click', togglePinPanel);
79287881

79297882
// Settings button in activity bar
7930-
document.getElementById('btn-activity-settings')?.addEventListener('click', () => {
7931-
document.getElementById('settings-modal')?.classList.remove('hidden');
7883+
document.getElementById('btn-activity-settings')?.addEventListener('click', async () => {
7884+
// Load current settings into UI
7885+
elements.scrollSpeedSlider.value = userSettings.scrollSpeed.toString();
7886+
elements.scrollSpeedValue.textContent = `${userSettings.scrollSpeed}%`;
7887+
elements.defaultFontSizeSlider.value = userSettings.defaultFontSize.toString();
7888+
elements.defaultFontSizeValue.textContent = `${userSettings.defaultFontSize}px`;
7889+
elements.defaultGapThresholdSlider.value = userSettings.defaultGapThreshold.toString();
7890+
elements.defaultGapThresholdValue.textContent = `${userSettings.defaultGapThreshold}s`;
7891+
elements.autoAnalyzeCheckbox.checked = userSettings.autoAnalyze;
7892+
elements.themeSelect.value = userSettings.theme;
7893+
populateSidebarSectionToggles();
7894+
// Load Datadog config
7895+
const result = await window.api.datadogLoadConfig();
7896+
if (result.success && result.config) {
7897+
elements.ddSiteSelect.value = result.config.site || 'US1';
7898+
elements.ddApiKey.value = result.config.hasApiKey ? '••••••••' : '';
7899+
elements.ddAppKey.value = result.config.hasAppKey ? '••••••••' : '';
7900+
elements.ddConfigStatus.textContent = 'Configured';
7901+
elements.ddConfigStatus.style.color = 'var(--debug-color)';
7902+
} else {
7903+
elements.ddSiteSelect.value = 'US1';
7904+
elements.ddApiKey.value = '';
7905+
elements.ddAppKey.value = '';
7906+
elements.ddConfigStatus.textContent = 'Not configured';
7907+
elements.ddConfigStatus.style.color = 'var(--text-muted)';
7908+
}
7909+
elements.settingsModal.classList.remove('hidden');
79327910
});
79337911

79347912
// History panel controls
@@ -8500,11 +8478,6 @@ function init(): void {
85008478
// Notes drawer events
85018479
elements.btnNotesToggle.addEventListener('click', toggleNotesDrawer);
85028480
elements.btnNotesClose.addEventListener('click', closeNotesDrawer);
8503-
elements.notesOverlay.addEventListener('click', (e) => {
8504-
if (e.target === elements.notesOverlay) {
8505-
closeNotesDrawer();
8506-
}
8507-
});
85088481
elements.notesTextarea.addEventListener('input', saveNotesDebounced);
85098482
setupNotesDrawerResize();
85108483

@@ -8782,24 +8755,6 @@ function init(): void {
87828755
}
87838756
});
87848757

8785-
// Datadog settings - load config when settings open
8786-
const origSettingsClick = elements.btnSettings.onclick;
8787-
elements.btnSettings.addEventListener('click', async () => {
8788-
const result = await window.api.datadogLoadConfig();
8789-
if (result.success && result.config) {
8790-
elements.ddSiteSelect.value = result.config.site || 'US1';
8791-
elements.ddApiKey.value = result.config.hasApiKey ? '••••••••' : '';
8792-
elements.ddAppKey.value = result.config.hasAppKey ? '••••••••' : '';
8793-
elements.ddConfigStatus.textContent = 'Configured';
8794-
elements.ddConfigStatus.style.color = 'var(--debug-color)';
8795-
} else {
8796-
elements.ddSiteSelect.value = 'US1';
8797-
elements.ddApiKey.value = '';
8798-
elements.ddAppKey.value = '';
8799-
elements.ddConfigStatus.textContent = 'Not configured';
8800-
elements.ddConfigStatus.style.color = 'var(--text-muted)';
8801-
}
8802-
});
88038758

88048759
elements.btnDdSaveConfig.addEventListener('click', async () => {
88058760
const apiKey = elements.ddApiKey.value.trim();
@@ -8840,9 +8795,6 @@ function init(): void {
88408795
});
88418796
elements.splitValue.addEventListener('input', updateSplitPreview);
88428797

8843-
// Sidebar
8844-
elements.btnToggleSidebar.addEventListener('click', togglePanelVisibility);
8845-
88468798
// Highlights
88478799
elements.btnAddHighlight.addEventListener('click', showHighlightModal);
88488800
elements.btnSaveHighlight.addEventListener('click', saveHighlight);
@@ -8868,20 +8820,6 @@ function init(): void {
88688820
elements.helpModal.classList.add('hidden');
88698821
});
88708822

8871-
// Settings modal
8872-
elements.btnSettings.addEventListener('click', () => {
8873-
// Load current settings into UI
8874-
elements.scrollSpeedSlider.value = userSettings.scrollSpeed.toString();
8875-
elements.scrollSpeedValue.textContent = `${userSettings.scrollSpeed}%`;
8876-
elements.defaultFontSizeSlider.value = userSettings.defaultFontSize.toString();
8877-
elements.defaultFontSizeValue.textContent = `${userSettings.defaultFontSize}px`;
8878-
elements.defaultGapThresholdSlider.value = userSettings.defaultGapThreshold.toString();
8879-
elements.defaultGapThresholdValue.textContent = `${userSettings.defaultGapThreshold}s`;
8880-
elements.autoAnalyzeCheckbox.checked = userSettings.autoAnalyze;
8881-
elements.themeSelect.value = userSettings.theme;
8882-
populateSidebarSectionToggles();
8883-
elements.settingsModal.classList.remove('hidden');
8884-
});
88858823

88868824
elements.scrollSpeedSlider.addEventListener('input', () => {
88878825
const value = parseInt(elements.scrollSpeedSlider.value, 10);

0 commit comments

Comments
 (0)