1import { Controller } from "@hotwired/stimulus" 2 3const STORAGE_OPEN = "bartok-bubble-open" 4const STORAGE_UNREAD = "bartok-bubble-unread" 5 6export default class extends Controller { 7 static targets = ["panel", "unread"] 8 static values = { open: false, unread: false } 9 10 connect() { 11 this.openValue = localStorage.getItem(STORAGE_OPEN) === "true" 12 this.unreadValue = localStorage.getItem(STORAGE_UNREAD) === "true" 13 this.element.addEventListener("turbo:before-stream-render", this.#onStreamReceived) 14 } 15 16 disconnect() { 17 this.element.removeEventListener("turbo:before-stream-render", this.#onStreamReceived) 18 } 19 20 toggle() { 21 this.openValue = !this.openValue 22 if (this.openValue) { 23 this.unreadValue = false 24 this.#scrollToBottom() 25 } 26 } 27 28 close() { 29 this.openValue = false 30 } 31 32 openValueChanged() { 33 localStorage.setItem(STORAGE_OPEN, this.openValue) 34 this.element.dataset.open = this.openValue 35 } 36 37 unreadValueChanged() { 38 localStorage.setItem(STORAGE_UNREAD, this.unreadValue) 39 this.element.dataset.unread = this.unreadValue 40 } 41 42 #onStreamReceived = (event) => { 43 if (this.openValue) return 44 const action = event.detail?.newStream?.getAttribute("action") 45 if (action === "append" || action === "replace") this.unreadValue = true 46 } 47 48 #scrollToBottom() { 49 requestAnimationFrame(() => { 50 const messages = this.panelTarget.querySelector("#bartok_messages") 51 if (messages) messages.scrollTop = messages.scrollHeight 52 }) 53 } 54}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.