Skip to content

Commit 3645697

Browse files
committed
fix: prevent right border overwrite in ActiveQueriesPane
- Remove unnecessary width reserve that was causing visible gap - Use full available width from getContentArea (already accounts for borders) - Replace clearLine() with str_repeat() to clear only content area - Add strict width checking and padding to ensure exact width output - Fix width calculation to use actual padded column widths
1 parent b82b52e commit 3645697

File tree

1 file changed

+104
-14
lines changed

1 file changed

+104
-14
lines changed

src/cli/ui/panes/ActiveQueriesPane.php

Lines changed: 104 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -75,18 +75,47 @@ public static function render(PdoDb $db, Layout $layout, int $paneIndex, bool $a
7575
}
7676

7777
$visibleHeight = $content['height'] - 1; // -1 for header
78-
$colWidth = (int)floor($content['width'] / 4);
78+
// Use full available width - getContentArea already accounts for borders
79+
$availableWidth = $content['width'];
80+
$colWidth = (int)floor($availableWidth / 4);
7981

8082
// Header
8183
if (Terminal::supportsColors()) {
8284
Terminal::bold();
8385
}
8486
Terminal::moveTo($content['row'], $content['col']);
85-
$headerText = str_pad('ID', $colWidth) . str_pad('Time', $colWidth) . str_pad('DB', $colWidth) . 'Query';
86-
// Truncate if too long
87-
if (mb_strlen($headerText, 'UTF-8') > $content['width']) {
88-
$headerText = mb_substr($headerText, 0, $content['width'], 'UTF-8');
87+
// Clear only the content area, not the entire line (to preserve right border)
88+
echo str_repeat(' ', $availableWidth);
89+
Terminal::moveTo($content['row'], $content['col']);
90+
91+
// Build header with UTF-8 aware padding
92+
$headerId = 'ID';
93+
$headerTime = 'Time';
94+
$headerDb = 'DB';
95+
$headerQuery = 'Query';
96+
97+
$idLen = mb_strlen($headerId, 'UTF-8');
98+
$timeLen = mb_strlen($headerTime, 'UTF-8');
99+
$dbLen = mb_strlen($headerDb, 'UTF-8');
100+
101+
$headerIdPadded = $headerId . str_repeat(' ', max(0, $colWidth - $idLen));
102+
$headerTimePadded = $headerTime . str_repeat(' ', max(0, $colWidth - $timeLen));
103+
$headerDbPadded = $headerDb . str_repeat(' ', max(0, $colWidth - $dbLen));
104+
105+
// Calculate available width for Query header
106+
$usedWidth = ($colWidth * 3);
107+
$queryHeaderWidth = max(1, $availableWidth - $usedWidth);
108+
$headerQueryTruncated = mb_strlen($headerQuery, 'UTF-8') > $queryHeaderWidth
109+
? mb_substr($headerQuery, 0, $queryHeaderWidth, 'UTF-8')
110+
: $headerQuery;
111+
112+
$headerText = $headerIdPadded . $headerTimePadded . $headerDbPadded . $headerQueryTruncated;
113+
114+
// Final safety check
115+
if (mb_strlen($headerText, 'UTF-8') > $availableWidth) {
116+
$headerText = mb_substr($headerText, 0, $availableWidth, 'UTF-8');
89117
}
118+
90119
echo $headerText;
91120
Terminal::reset();
92121

@@ -114,7 +143,9 @@ public static function render(PdoDb $db, Layout $layout, int $paneIndex, bool $a
114143
}
115144

116145
Terminal::moveTo($displayRow, $content['col']);
117-
Terminal::clearLine(); // Clear line before rendering to avoid artifacts
146+
// Clear only the content area, not the entire line (to preserve right border)
147+
echo str_repeat(' ', $availableWidth);
148+
Terminal::moveTo($displayRow, $content['col']);
118149

119150
$isSelected = $active && $selectedIndex === $i;
120151
if ($isSelected && Terminal::supportsColors()) {
@@ -125,7 +156,6 @@ public static function render(PdoDb $db, Layout $layout, int $paneIndex, bool $a
125156
$id = self::truncate((string)($query['id'] ?? $query['pid'] ?? $query['session_id'] ?? ''), $colWidth);
126157
$time = self::truncate((string)($query['time'] ?? $query['duration'] ?? ''), $colWidth);
127158
$dbName = self::truncate((string)($query['db'] ?? $query['database'] ?? $query['datname'] ?? ''), $colWidth);
128-
$queryText = self::truncate((string)($query['query'] ?? ''), $content['width'] - ($colWidth * 3));
129159

130160
// Highlight slow queries (> 5 seconds) if not selected
131161
if (!$isSelected) {
@@ -137,12 +167,68 @@ public static function render(PdoDb $db, Layout $layout, int $paneIndex, bool $a
137167
}
138168

139169
$marker = $isSelected ? '> ' : ' ';
140-
$rowText = $marker . str_pad($id, $colWidth - 2) . str_pad($time, $colWidth) . str_pad($dbName, $colWidth) . $queryText;
141-
// Truncate if too long
142-
if (mb_strlen($rowText, 'UTF-8') > $content['width']) {
143-
$rowText = mb_substr($rowText, 0, $content['width'], 'UTF-8');
170+
171+
// Build row text with proper padding (using UTF-8 aware length)
172+
$idPadded = $id;
173+
$timePadded = $time;
174+
$dbNamePadded = $dbName;
175+
176+
// Pad using UTF-8 aware method
177+
$idLen = mb_strlen($id, 'UTF-8');
178+
if ($idLen < $colWidth) {
179+
$idPadded = $id . str_repeat(' ', $colWidth - $idLen);
180+
}
181+
182+
$timeLen = mb_strlen($time, 'UTF-8');
183+
if ($timeLen < $colWidth) {
184+
$timePadded = $time . str_repeat(' ', $colWidth - $timeLen);
185+
}
186+
187+
$dbNameLen = mb_strlen($dbName, 'UTF-8');
188+
if ($dbNameLen < $colWidth) {
189+
$dbNamePadded = $dbName . str_repeat(' ', $colWidth - $dbNameLen);
190+
}
191+
192+
// Calculate actual used width after padding
193+
$markerWidth = mb_strlen($marker, 'UTF-8');
194+
$idPaddedWidth = mb_strlen($idPadded, 'UTF-8');
195+
$timePaddedWidth = mb_strlen($timePadded, 'UTF-8');
196+
$dbNamePaddedWidth = mb_strlen($dbNamePadded, 'UTF-8');
197+
$usedWidth = $markerWidth + $idPaddedWidth + $timePaddedWidth + $dbNamePaddedWidth;
198+
199+
// Calculate available width for query text
200+
$queryTextWidth = max(1, $availableWidth - $usedWidth);
201+
$queryText = self::truncate((string)($query['query'] ?? ''), $queryTextWidth);
202+
203+
$rowText = $marker . $idPadded . $timePadded . $dbNamePadded . $queryText;
204+
205+
// Final safety check - ensure total width doesn't exceed available width
206+
$totalWidth = mb_strlen($rowText, 'UTF-8');
207+
if ($totalWidth > $availableWidth) {
208+
// Truncate queryText further if needed
209+
$queryTextWidth = max(0, $queryTextWidth - ($totalWidth - $availableWidth));
210+
$queryText = self::truncate((string)($query['query'] ?? ''), $queryTextWidth);
211+
$rowText = $marker . $idPadded . $timePadded . $dbNamePadded . $queryText;
212+
// Final truncation as last resort
213+
if (mb_strlen($rowText, 'UTF-8') > $availableWidth) {
214+
$rowText = mb_substr($rowText, 0, $availableWidth, 'UTF-8');
215+
}
144216
}
217+
218+
// Ensure we don't output more than available width (strict check)
219+
$finalWidth = mb_strlen($rowText, 'UTF-8');
220+
if ($finalWidth > $availableWidth) {
221+
// Truncate to exact available width
222+
$rowText = mb_substr($rowText, 0, $availableWidth, 'UTF-8');
223+
}
224+
225+
// Output text and pad to exact width to ensure we don't overwrite anything
145226
echo $rowText;
227+
$actualWidth = mb_strlen($rowText, 'UTF-8');
228+
if ($actualWidth < $availableWidth) {
229+
// Pad with spaces to fill exactly availableWidth (prevents any overflow)
230+
echo str_repeat(' ', $availableWidth - $actualWidth);
231+
}
146232
Terminal::reset();
147233

148234
$lastDisplayRow = $displayRow; // Update last displayed row
@@ -160,7 +246,8 @@ public static function render(PdoDb $db, Layout $layout, int $paneIndex, bool $a
160246

161247
for ($row = $lastDisplayRow + 1; $row < $maxRow; $row++) {
162248
Terminal::moveTo($row, $content['col']);
163-
Terminal::clearLine();
249+
// Clear only the content area, not the entire line (to preserve right border)
250+
echo str_repeat(' ', $availableWidth);
164251
}
165252

166253
// Show scroll indicator
@@ -175,7 +262,9 @@ public static function render(PdoDb $db, Layout $layout, int $paneIndex, bool $a
175262

176263
if ($scrollOffset > 0 || $endIdx < count($queries)) {
177264
Terminal::moveTo($scrollIndicatorRow, $content['col']);
178-
Terminal::clearLine(); // Clear before rendering indicator
265+
// Clear only the content area, not the entire line (to preserve right border)
266+
echo str_repeat(' ', $availableWidth);
267+
Terminal::moveTo($scrollIndicatorRow, $content['col']);
179268
if (Terminal::supportsColors()) {
180269
Terminal::color(Terminal::COLOR_YELLOW);
181270
}
@@ -194,7 +283,8 @@ public static function render(PdoDb $db, Layout $layout, int $paneIndex, bool $a
194283
} else {
195284
// Clear scroll indicator row if no scrolling needed
196285
Terminal::moveTo($scrollIndicatorRow, $content['col']);
197-
Terminal::clearLine();
286+
// Clear only the content area, not the entire line (to preserve right border)
287+
echo str_repeat(' ', $availableWidth);
198288
}
199289
}
200290

0 commit comments

Comments
 (0)