@@ -56,7 +56,7 @@ class ConsoleUI extends Logger {
5656 term.writer().flush()
5757 // Clear screen
5858 clearScreen()
59-
59+
6060 // Show a brief startup banner with the Fukuii mini logo
6161 showStartupBanner()
6262 }
@@ -71,10 +71,10 @@ class ConsoleUI extends Logger {
7171 }
7272
7373 /** Display startup banner briefly before main UI takes over. */
74- private def showStartupBanner (): Unit = {
74+ private def showStartupBanner (): Unit =
7575 terminal.foreach { term =>
7676 val width = term.getWidth
77-
77+
7878 // Compact Fukuii branding
7979 val banner = Seq (
8080 " " ,
@@ -91,7 +91,7 @@ class ConsoleUI extends Logger {
9191 )
9292
9393 val greenStyle = AttributedStyle .DEFAULT .foreground(AttributedStyle .GREEN ).bold()
94-
94+
9595 term.writer().print(" \u001b [H" ) // Move to top
9696 banner.foreach { line =>
9797 val centered = " " * ((width - line.length) / 2 ) + line
@@ -100,16 +100,14 @@ class ConsoleUI extends Logger {
100100 term.writer().println(styledLine.toAnsi())
101101 }
102102 term.writer().flush()
103-
103+
104104 // Brief pause to show banner
105105 Thread .sleep(BANNER_DISPLAY_DURATION_MS )
106106 }
107- }
108107
109108 /** Disable the console UI. */
110- def disable (): Unit = {
109+ def disable (): Unit =
111110 enabled = false
112- }
113111
114112 /** Check if the console UI is enabled. */
115113 def isEnabled : Boolean = enabled
@@ -127,19 +125,16 @@ class ConsoleUI extends Logger {
127125 }
128126
129127 /** Update the network name. */
130- def updateNetwork (name : String ): Unit = {
128+ def updateNetwork (name : String ): Unit =
131129 networkName = name
132- }
133130
134131 /** Update the sync status. */
135- def updateSyncStatus (status : String ): Unit = {
132+ def updateSyncStatus (status : String ): Unit =
136133 syncStatus = status
137- }
138134
139135 /** Update the connection status. */
140- def updateConnectionStatus (status : String ): Unit = {
136+ def updateConnectionStatus (status : String ): Unit =
141137 connectionStatus = status
142- }
143138
144139 /** Render the console UI. */
145140 def render (): Unit = {
@@ -192,15 +187,15 @@ class ConsoleUI extends Logger {
192187 lines += createInfoLine(" Current Block" , formatNumber(currentBlock), width)
193188 lines += createInfoLine(" Best Block" , formatNumber(bestBlock), width)
194189 lines += createInfoLine(" Sync Status" , syncStatus, width)
195-
190+
196191 if (bestBlock > 0 && currentBlock > 0 && currentBlock < bestBlock) {
197192 val progress = (currentBlock.toDouble / bestBlock.toDouble) * 100.0
198193 val remaining = bestBlock - currentBlock
199-
194+
200195 // Create progress bar
201196 lines += createProgressBar(" Sync Progress" , progress, width)
202197 lines += createInfoLine(" Blocks Remaining" , formatNumber(remaining), width)
203-
198+
204199 // Estimate sync time
205200 val uptime = Duration .between(startTime, Instant .now()).getSeconds
206201 if (uptime > 10 && currentBlock > 0 ) {
@@ -214,7 +209,7 @@ class ConsoleUI extends Logger {
214209 } else if (currentBlock >= bestBlock && bestBlock > 0 ) {
215210 lines += createInfoLine(" Status" , " ✓ SYNCHRONIZED" , width)
216211 }
217-
212+
218213 lines += createSeparator(width)
219214
220215 // Runtime section
@@ -227,9 +222,8 @@ class ConsoleUI extends Logger {
227222 lines += createFooter(width)
228223
229224 // Fill remaining space
230- while (lines.length < height - 1 ) {
225+ while (lines.length < height - 1 )
231226 lines += new AttributedString (" " * width)
232- }
233227
234228 lines.toSeq
235229 }
@@ -259,10 +253,10 @@ class ConsoleUI extends Logger {
259253 private def createInfoLine (label : String , value : String , width : Int ): AttributedString = {
260254 val labelStyle = AttributedStyle .DEFAULT .foreground(AttributedStyle .CYAN )
261255 val valueStyle = AttributedStyle .DEFAULT .foreground(AttributedStyle .WHITE ).bold()
262-
256+
263257 val labelPart = new AttributedString (s " $label: " , labelStyle)
264258 val valuePart = new AttributedString (value, valueStyle)
265-
259+
266260 val combinedLength = labelPart.columnLength() + valuePart.columnLength()
267261 val padding = " " * (width - combinedLength)
268262 new AttributedString (labelPart.toAnsi() + valuePart.toAnsi() + padding)
@@ -274,16 +268,18 @@ class ConsoleUI extends Logger {
274268 val barWidth = Math .min(40 , width - 30 ) // Max 40 chars for bar
275269 val filled = ((percentage / 100.0 ) * barWidth).toInt
276270 val empty = barWidth - filled
277-
271+
278272 val labelPart = new AttributedString (s " $label: " , labelStyle)
279273 val barStyle = AttributedStyle .DEFAULT .foreground(AttributedStyle .GREEN ).bold()
280274 val emptyStyle = AttributedStyle .DEFAULT .foreground(AttributedStyle .WHITE )
281-
275+
282276 val filledBar = new AttributedString (" █" * filled, barStyle)
283277 val emptyBar = new AttributedString (" ░" * empty, emptyStyle)
284- val percentText = new AttributedString (f " $percentage%.2f%% " , AttributedStyle .DEFAULT .foreground(AttributedStyle .WHITE ).bold())
285-
286- val combinedLength = labelPart.columnLength() + filledBar.columnLength() + emptyBar.columnLength() + percentText.columnLength()
278+ val percentText =
279+ new AttributedString (f " $percentage%.2f%% " , AttributedStyle .DEFAULT .foreground(AttributedStyle .WHITE ).bold())
280+
281+ val combinedLength =
282+ labelPart.columnLength() + filledBar.columnLength() + emptyBar.columnLength() + percentText.columnLength()
287283 val padding = " " * (width - combinedLength)
288284 new AttributedString (labelPart.toAnsi() + filledBar.toAnsi() + emptyBar.toAnsi() + percentText.toAnsi() + padding)
289285 }
@@ -292,19 +288,19 @@ class ConsoleUI extends Logger {
292288 private def createStatusLine (label : String , status : String , width : Int ): AttributedString = {
293289 val labelStyle = AttributedStyle .DEFAULT .foreground(AttributedStyle .CYAN )
294290 val statusStyle = status.toLowerCase match {
295- case s if s.contains(" connected" ) || s.contains(" running" ) =>
291+ case s if s.contains(" connected" ) || s.contains(" running" ) =>
296292 AttributedStyle .DEFAULT .foreground(AttributedStyle .GREEN ).bold()
297- case s if s.contains(" starting" ) || s.contains(" initializing" ) =>
293+ case s if s.contains(" starting" ) || s.contains(" initializing" ) =>
298294 AttributedStyle .DEFAULT .foreground(AttributedStyle .YELLOW ).bold()
299- case s if s.contains(" error" ) || s.contains(" failed" ) =>
295+ case s if s.contains(" error" ) || s.contains(" failed" ) =>
300296 AttributedStyle .DEFAULT .foreground(AttributedStyle .RED ).bold()
301- case _ =>
297+ case _ =>
302298 AttributedStyle .DEFAULT .foreground(AttributedStyle .WHITE ).bold()
303299 }
304-
300+
305301 val labelPart = new AttributedString (s " $label: " , labelStyle)
306302 val statusPart = new AttributedString (s " ● $status" , statusStyle)
307-
303+
308304 val combinedLength = labelPart.columnLength() + statusPart.columnLength()
309305 val padding = " " * (width - combinedLength)
310306 new AttributedString (labelPart.toAnsi() + statusPart.toAnsi() + padding)
@@ -320,26 +316,25 @@ class ConsoleUI extends Logger {
320316 } else {
321317 AttributedStyle .DEFAULT .foreground(AttributedStyle .GREEN ).bold()
322318 }
323-
319+
324320 val labelPart = new AttributedString (s " Peers: " , labelStyle)
325321 val peerText = s " $count / $max"
326322 val peerPart = new AttributedString (peerText, peerStyle)
327-
323+
328324 // Add visual indicator
329325 val indicator = if (count > 0 ) " ◆" * Math .min(count, 10 ) else " "
330326 val indicatorPart = new AttributedString (indicator, peerStyle)
331-
327+
332328 val combinedLength = labelPart.columnLength() + peerPart.columnLength() + indicatorPart.columnLength()
333329 val padding = " " * (width - combinedLength)
334330 new AttributedString (labelPart.toAnsi() + peerPart.toAnsi() + indicatorPart.toAnsi() + padding)
335331 }
336332
337- private def createSeparator (width : Int ): AttributedString = {
333+ private def createSeparator (width : Int ): AttributedString =
338334 new AttributedString (
339335 " ─" * width,
340336 AttributedStyle .DEFAULT .foreground(AttributedStyle .GREEN )
341337 )
342- }
343338
344339 private def createFooter (width : Int ): AttributedString = {
345340 val footer = " Commands: [Q]uit | [R]efresh | [D]isable UI "
@@ -370,17 +365,16 @@ class ConsoleUI extends Logger {
370365 )
371366
372367 val greenStyle = AttributedStyle .DEFAULT .foreground(AttributedStyle .GREEN ).bold()
373-
368+
374369 logo.foreach { line =>
375370 val centered = " " * ((width - line.length) / 2 ) + line
376371 val padded = centered + " " * (width - centered.length)
377372 lines += new AttributedString (padded, greenStyle)
378373 }
379374 }
380375
381- private def formatNumber (n : Long ): String = {
376+ private def formatNumber (n : Long ): String =
382377 " %,d" .format(n)
383- }
384378
385379 private def formatDuration (seconds : Long ): String = {
386380 val days = seconds / 86400
@@ -394,28 +388,27 @@ class ConsoleUI extends Logger {
394388 else s " ${secs}s "
395389 }
396390
397- private def clearScreen (): Unit = {
391+ private def clearScreen (): Unit =
398392 terminal.foreach { term =>
399393 // Clear entire screen
400394 term.writer().print(" \u001b [2J" )
401395 // Move cursor to home position
402396 term.writer().print(" \u001b [H" )
403397 term.writer().flush()
404398 }
405- }
406399
407400 /** Check for keyboard input (non-blocking). */
408401 def checkInput (): Option [Char ] = {
409402 if (! enabled || terminal.isEmpty) return None
410403
411404 terminal.flatMap { term =>
412- try {
405+ try
413406 if (term.reader().peek(0 ) > 0 ) {
414407 Some (term.reader().read().toChar.toLower)
415408 } else {
416409 None
417410 }
418- } catch {
411+ catch {
419412 case _ : Exception => None
420413 }
421414 }
@@ -472,15 +465,14 @@ object ConsoleUI {
472465 private var instance : Option [ConsoleUI ] = None
473466
474467 /** Get or create the singleton instance. */
475- def getInstance (): ConsoleUI = {
468+ def getInstance (): ConsoleUI =
476469 instance match {
477470 case Some (ui) => ui
478471 case None =>
479472 val ui = new ConsoleUI ()
480473 instance = Some (ui)
481474 ui
482475 }
483- }
484476
485477 /** Reset the singleton instance (useful for testing). */
486478 def reset (): Unit = {
0 commit comments