Add search functionality to debug log screen.

This commit is contained in:
lisa-signal
2025-08-01 12:47:49 -04:00
committed by Cody Henthorne
parent 962375e422
commit 5e0aa830bf
8 changed files with 313 additions and 35 deletions

View File

@@ -9,6 +9,7 @@
<meta charset="UTF-8">
<style>
#container { position: absolute; top: 0; bottom: 0; left: 0; right: 0; height: 100%; width: 100%; }
.searchMatches { position: absolute; background-color: rgba(182, 190, 250, 0.4); }
/* Scrollbar Setup */
.ace_scrollbar::-webkit-scrollbar { width: 0; height: 0; }

View File

@@ -47,3 +47,102 @@ function showScrollBar() {
editor.session.on("changeScrollTop", showScrollBar);
editor.session.on("changeScrollLeft", showScrollBar);
// Generate highlight markers for all search matches
const Range = ace.require("ace/range").Range;
const session = editor.getSession();
let input = ""; // Search query input
let markers = []; // IDs of highlighted search markers
let matchRanges = []; // Ranges of all search matches
let matchCount = 0; // Total number of matches
let isCaseSensitive = false;
// Clear all search markers and match info
function clearMarkers() {
markers.forEach((id) => session.removeMarker(id));
markers = [];
matchRanges = [];
matchCount = 0;
}
// Highlight all instances of the search term
function highlightAllMatches(term) {
clearMarkers();
if (!term) {
return;
}
const searchTerm = isCaseSensitive ? term : term.toLowerCase();
session
.getDocument()
.getAllLines()
.forEach((line, row) => {
let start = 0;
const caseLine = isCaseSensitive ? line : line.toLowerCase();
while (true) {
const index = caseLine.indexOf(searchTerm, start);
if (index === -1) {
break;
}
const range = new Range(row, index, row, index + term.length);
markers.push(session.addMarker(range, "searchMatches", "text", false));
matchRanges.push(range);
start = index + term.length;
}
});
matchCount = markers.length;
}
// Return index of current match
function getCurrentMatchIndex() {
const current = editor.getSelection().getRange();
return matchRanges.findIndex(
(r) =>
r.start.row === current.start.row &&
r.start.column === current.start.column &&
r.end.row === current.end.row &&
r.end.column === current.end.column,
);
}
function getSearchPosition() {
if (input == "") {
return "";
}
return matchCount == 0 ? "No match" : `${getCurrentMatchIndex() + 1} of ${matchCount}`;
}
function onSearchUp() {
editor.find(input, {
backwards: true,
wrap: true,
skipCurrent: true,
caseSensitive: isCaseSensitive,
});
}
function onSearchDown() {
editor.find(input, {
backwards: false,
wrap: true,
skipCurrent: true,
caseSensitive: isCaseSensitive,
});
}
function onSearchClose() {
editor.getSelection().clearSelection();
input = "";
clearMarkers();
}
function onToggleCaseSensitive() {
isCaseSensitive = !isCaseSensitive;
highlightAllMatches(input);
}
function onSearchInput(value) {
input = value;
highlightAllMatches(input);
}

View File

@@ -9,10 +9,12 @@ import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.res.Configuration
import android.webkit.ValueCallback
import android.webkit.WebView
import android.webkit.WebViewClient
import kotlinx.coroutines.Runnable
import org.json.JSONObject
import java.util.function.Consumer
var readOnly = true
@@ -59,13 +61,37 @@ object DebugLogsViewer {
}
@JvmStatic
fun onFind(webview: WebView) {
webview.evaluateJavascript("document.getElementById('searchBar').style.display = 'block';", null)
fun onSearch(webview: WebView, query: String) {
webview.evaluateJavascript("onSearchInput('$query')", null)
}
@JvmStatic
fun onSearchUp(webview: WebView) {
webview.evaluateJavascript("onSearchUp();", null)
}
@JvmStatic
fun onSearchDown(webview: WebView) {
webview.evaluateJavascript("onSearchDown();", null)
}
@JvmStatic
fun getSearchPosition(webView: WebView, callback: Consumer<String?>) {
webView.evaluateJavascript("getSearchPosition();", ValueCallback { value: String? -> callback.accept(value?.trim('"') ?: "") })
}
@JvmStatic
fun onToggleCaseSensitive(webview: WebView) {
webview.evaluateJavascript("onToggleCaseSensitive();", null)
}
@JvmStatic
fun onSearchClose(webview: WebView) {
webview.evaluateJavascript("onSearchClose();", null)
}
@JvmStatic
fun onFilter(webview: WebView) {
webview.evaluateJavascript("document.getElementById('filterLevel').style.display = 'block';", null)
}
@JvmStatic