Console.coffee 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. class Console extends Class
  2. constructor: (@sidebar) ->
  3. @tag = null
  4. @opened = false
  5. @filter = null
  6. @tab_types = [
  7. {title: "All", filter: ""},
  8. {title: "Info", filter: "INFO"},
  9. {title: "Warning", filter: "WARNING"},
  10. {title: "Error", filter: "ERROR"}
  11. ]
  12. @read_size = 32 * 1024
  13. @tab_active = ""
  14. #@filter = @sidebar.wrapper.site_info.address_short
  15. handleMessageWebsocket_original = @sidebar.wrapper.handleMessageWebsocket
  16. @sidebar.wrapper.handleMessageWebsocket = (message) =>
  17. if message.cmd == "logLineAdd" and message.params.stream_id == @stream_id
  18. @addLines(message.params.lines)
  19. else
  20. handleMessageWebsocket_original(message)
  21. $(window).on "hashchange", =>
  22. if window.top.location.hash.startsWith("#ZeroNet:Console")
  23. @open()
  24. if window.top.location.hash.startsWith("#ZeroNet:Console")
  25. setTimeout (=> @open()), 10
  26. createHtmltag: ->
  27. if not @container
  28. @container = $("""
  29. <div class="console-container">
  30. <div class="console">
  31. <div class="console-top">
  32. <div class="console-tabs"></div>
  33. <div class="console-text">Loading...</div>
  34. </div>
  35. <div class="console-middle">
  36. <div class="mynode"></div>
  37. <div class="peers">
  38. <div class="peer"><div class="line"></div><a href="#" class="icon">\u25BD</div></div>
  39. </div>
  40. </div>
  41. </div>
  42. </div>
  43. """)
  44. @text = @container.find(".console-text")
  45. @text_elem = @text[0]
  46. @tabs = @container.find(".console-tabs")
  47. @text.on "mousewheel", (e) => # Stop animation on manual scrolling
  48. if e.originalEvent.deltaY < 0
  49. @text.stop()
  50. RateLimit 300, @checkTextIsBottom
  51. @text.is_bottom = true
  52. @container.appendTo(document.body)
  53. @tag = @container.find(".console")
  54. for tab_type in @tab_types
  55. tab = $("<a></a>", {href: "#", "data-filter": tab_type.filter, "data-title": tab_type.title}).text(tab_type.title)
  56. if tab_type.filter == @tab_active
  57. tab.addClass("active")
  58. tab.on("click", @handleTabClick)
  59. if window.top.location.hash.endsWith(tab_type.title)
  60. @log "Triggering click on", tab
  61. tab.trigger("click")
  62. @tabs.append(tab)
  63. @container.on "mousedown touchend touchcancel", (e) =>
  64. if e.target != e.currentTarget
  65. return true
  66. @log "closing"
  67. if $(document.body).hasClass("body-console")
  68. @close()
  69. return true
  70. @loadConsoleText()
  71. checkTextIsBottom: =>
  72. @text.is_bottom = Math.round(@text_elem.scrollTop + @text_elem.clientHeight) >= @text_elem.scrollHeight - 15
  73. toColor: (text, saturation=60, lightness=70) ->
  74. hash = 0
  75. for i in [0..text.length-1]
  76. hash += text.charCodeAt(i)*i
  77. hash = hash % 1777
  78. return "hsl(" + (hash % 360) + ",#{saturation}%,#{lightness}%)";
  79. formatLine: (line) =>
  80. match = line.match(/(\[.*?\])[ ]+(.*?)[ ]+(.*?)[ ]+(.*)/)
  81. if not match
  82. return line.replace(/\</g, "&lt;").replace(/\>/g, "&gt;")
  83. [line, added, level, module, text] = line.match(/(\[.*?\])[ ]+(.*?)[ ]+(.*?)[ ]+(.*)/)
  84. added = "<span style='color: #dfd0fa'>#{added}</span>"
  85. level = "<span style='color: #{@toColor(level, 100)};'>#{level}</span>"
  86. module = "<span style='color: #{@toColor(module, 60)}; font-weight: bold;'>#{module}</span>"
  87. text = text.replace(/(Site:[A-Za-z0-9\.]+)/g, "<span style='color: #AAAAFF'>$1</span>")
  88. text = text.replace(/\</g, "&lt;").replace(/\>/g, "&gt;")
  89. #text = text.replace(/( [0-9\.]+(|s|ms))/g, "<span style='color: #FFF;'>$1</span>")
  90. return "#{added} #{level} #{module} #{text}"
  91. addLines: (lines, animate=true) =>
  92. html_lines = []
  93. @logStart "formatting"
  94. for line in lines
  95. html_lines.push @formatLine(line)
  96. @logEnd "formatting"
  97. @logStart "adding"
  98. @text.append(html_lines.join("<br>") + "<br>")
  99. @logEnd "adding"
  100. if @text.is_bottom and animate
  101. @text.stop().animate({scrollTop: @text_elem.scrollHeight - @text_elem.clientHeight + 1}, 600, 'easeInOutCubic')
  102. loadConsoleText: =>
  103. @sidebar.wrapper.ws.cmd "consoleLogRead", {filter: @filter, read_size: @read_size}, (res) =>
  104. @text.html("")
  105. pos_diff = res["pos_end"] - res["pos_start"]
  106. size_read = Math.round(pos_diff/1024)
  107. size_total = Math.round(res['pos_end']/1024)
  108. @text.append("<br><br>")
  109. @text.append("Displaying #{res.lines.length} of #{res.num_found} lines found in the last #{size_read}kB of the log file. (#{size_total}kB total)<br>")
  110. @addLines res.lines, false
  111. @text_elem.scrollTop = @text_elem.scrollHeight
  112. if @stream_id
  113. @sidebar.wrapper.ws.cmd "consoleLogStreamRemove", {stream_id: @stream_id}
  114. @sidebar.wrapper.ws.cmd "consoleLogStream", {filter: @filter}, (res) =>
  115. @stream_id = res.stream_id
  116. close: =>
  117. window.top.location.hash = ""
  118. @sidebar.move_lock = "y"
  119. @sidebar.startDrag()
  120. @sidebar.stopDrag()
  121. open: =>
  122. @sidebar.startDrag()
  123. @sidebar.moved("y")
  124. @sidebar.fixbutton_targety = @sidebar.page_height - @sidebar.fixbutton_inity - 50
  125. @sidebar.stopDrag()
  126. onOpened: =>
  127. @sidebar.onClosed()
  128. @log "onOpened"
  129. onClosed: =>
  130. $(document.body).removeClass("body-console")
  131. if @stream_id
  132. @sidebar.wrapper.ws.cmd "consoleLogStreamRemove", {stream_id: @stream_id}
  133. cleanup: =>
  134. if @container
  135. @container.remove()
  136. @container = null
  137. stopDragY: =>
  138. # Animate sidebar and iframe
  139. if @sidebar.fixbutton_targety == @sidebar.fixbutton_inity
  140. # Closed
  141. targety = 0
  142. @opened = false
  143. else
  144. # Opened
  145. targety = @sidebar.fixbutton_targety - @sidebar.fixbutton_inity
  146. @onOpened()
  147. @opened = true
  148. # Revent sidebar transitions
  149. if @tag
  150. @tag.css("transition", "0.5s ease-out")
  151. @tag.css("transform", "translateY(#{targety}px)").one transitionEnd, =>
  152. @tag.css("transition", "")
  153. if not @opened
  154. @cleanup()
  155. # Revert body transformations
  156. @log "stopDragY", "opened:", @opened, targety
  157. if not @opened
  158. @onClosed()
  159. changeFilter: (filter) =>
  160. @filter = filter
  161. if @filter == ""
  162. @read_size = 32 * 1024
  163. else
  164. @read_size = 5 * 1024 * 1024
  165. @loadConsoleText()
  166. handleTabClick: (e) =>
  167. elem = $(e.currentTarget)
  168. @tab_active = elem.data("filter")
  169. $("a", @tabs).removeClass("active")
  170. elem.addClass("active")
  171. @changeFilter(@tab_active)
  172. window.top.location.hash = "#ZeroNet:Console:" + elem.data("title")
  173. return false
  174. window.Console = Console