Add filter functionality to debug log screen.

This commit is contained in:
lisa-signal
2025-08-05 15:05:18 -04:00
committed by Cody Henthorne
parent f8b18b6ea9
commit 57454a2661
4 changed files with 100 additions and 19 deletions

View File

@@ -61,11 +61,14 @@ public class SubmitDebugLogActivity extends BaseActivity {
private MenuItem searchMenuItem; private MenuItem searchMenuItem;
private MenuItem saveMenuItem; private MenuItem saveMenuItem;
private ImageButton filterButton;
private ImageButton caseSensitiveButton; private ImageButton caseSensitiveButton;
private TextView searchPosition; private TextView searchPosition;
private ImageButton searchUpButton; private ImageButton searchUpButton;
private ImageButton searchDownButton; private ImageButton searchDownButton;
private boolean isCaseSensitive;
private boolean isFiltered;
private boolean isWebViewLoaded; private boolean isWebViewLoaded;
private boolean hasPresentedLines; private boolean hasPresentedLines;
@@ -101,6 +104,7 @@ public class SubmitDebugLogActivity extends BaseActivity {
this.saveMenuItem = menu.findItem(R.id.menu_save); this.saveMenuItem = menu.findItem(R.id.menu_save);
this.searchNav = findViewById(R.id.debug_log_search_nav); this.searchNav = findViewById(R.id.debug_log_search_nav);
this.filterButton = findViewById(R.id.debug_log_filter);
this.caseSensitiveButton = findViewById(R.id.case_sensitive_button); this.caseSensitiveButton = findViewById(R.id.case_sensitive_button);
this.searchPosition = findViewById(R.id.debug_log_search_position); this.searchPosition = findViewById(R.id.debug_log_search_position);
this.searchUpButton = findViewById(R.id.debug_log_search_up); this.searchUpButton = findViewById(R.id.debug_log_search_up);
@@ -116,17 +120,34 @@ public class SubmitDebugLogActivity extends BaseActivity {
DebugLogsViewer.getSearchPosition(logWebView, position -> searchPosition.setText(position)); DebugLogsViewer.getSearchPosition(logWebView, position -> searchPosition.setText(position));
}); });
boolean[] isCaseSensitive = {false};
caseSensitiveButton.setOnClickListener(v -> { caseSensitiveButton.setOnClickListener(v -> {
DebugLogsViewer.onToggleCaseSensitive(logWebView); DebugLogsViewer.onToggleCaseSensitive(logWebView);
DebugLogsViewer.getSearchPosition(logWebView, position -> searchPosition.setText(position)); DebugLogsViewer.getSearchPosition(logWebView, position -> searchPosition.setText(position));
isCaseSensitive[0] = !isCaseSensitive[0]; isCaseSensitive = !isCaseSensitive;
int backgroundColor = isCaseSensitive[0] ? R.drawable.circle_tint_darker : R.drawable.circle_touch_highlight_background; int backgroundColor = isCaseSensitive ? R.drawable.circle_tint_darker : R.drawable.circle_touch_highlight_background;
caseSensitiveButton.setBackground(getResources().getDrawable(backgroundColor)); caseSensitiveButton.setBackground(getResources().getDrawable(backgroundColor));
}); });
filterButton.setOnClickListener(v -> {
isFiltered = !isFiltered;
if (isFiltered) {
DebugLogsViewer.onFilter(logWebView);
searchPosition.setVisibility(View.GONE);
searchUpButton.setVisibility(View.GONE);
searchDownButton.setVisibility(View.GONE);
filterButton.setBackground(getResources().getDrawable(R.drawable.circle_tint_darker));
} else {
DebugLogsViewer.onFilterClose(logWebView);
searchPosition.setVisibility(View.VISIBLE);
searchUpButton.setVisibility(View.VISIBLE);
searchDownButton.setVisibility(View.VISIBLE);
DebugLogsViewer.getSearchPosition(logWebView, position -> searchPosition.setText(position));
DebugLogsViewer.scrollToTop(logWebView);
filterButton.setBackground(getResources().getDrawable(R.drawable.circle_touch_highlight_background));
}
});
SearchView searchView = (SearchView) searchMenuItem.getActionView(); SearchView searchView = (SearchView) searchMenuItem.getActionView();
SearchView.OnQueryTextListener queryListener = new SearchView.OnQueryTextListener() { SearchView.OnQueryTextListener queryListener = new SearchView.OnQueryTextListener() {
@Override @Override
@@ -136,8 +157,13 @@ public class SubmitDebugLogActivity extends BaseActivity {
@Override @Override
public boolean onQueryTextChange(String query) { public boolean onQueryTextChange(String query) {
DebugLogsViewer.onSearch(logWebView, query); DebugLogsViewer.onSearchInput(logWebView, query);
if (isFiltered) {
DebugLogsViewer.onFilter(logWebView);
} else {
DebugLogsViewer.onSearch(logWebView);
DebugLogsViewer.getSearchPosition(logWebView, position -> searchPosition.setText(position)); DebugLogsViewer.getSearchPosition(logWebView, position -> searchPosition.setText(position));
}
return true; return true;
} }
}; };
@@ -156,6 +182,7 @@ public class SubmitDebugLogActivity extends BaseActivity {
searchNav.setVisibility(View.GONE); searchNav.setVisibility(View.GONE);
submitButton.setVisibility(View.VISIBLE); submitButton.setVisibility(View.VISIBLE);
DebugLogsViewer.onSearchClose(logWebView); DebugLogsViewer.onSearchClose(logWebView);
DebugLogsViewer.onFilterClose(logWebView);
DebugLogsViewer.getSearchPosition(logWebView, position -> searchPosition.setText(position)); DebugLogsViewer.getSearchPosition(logWebView, position -> searchPosition.setText(position));
searchView.setOnQueryTextListener(null); searchView.setOnQueryTextListener(null);
return true; return true;

View File

@@ -98,16 +98,33 @@
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
tools:visibility="visible"> tools:visibility="visible">
<ImageButton
android:id="@+id/debug_log_filter"
android:layout_width="40dp"
android:layout_height="40dp"
android:background="@drawable/circle_touch_highlight_background"
android:layout_marginTop="8dp"
android:layout_marginStart="8dp"
android:layout_marginBottom="8dp"
android:padding="8dp"
android:src="@drawable/symbol_filter_24"
app:tint="@color/signal_colorOnSurface"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
<ImageButton <ImageButton
android:id="@+id/case_sensitive_button" android:id="@+id/case_sensitive_button"
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="40dp" android:layout_height="40dp"
android:background="@drawable/circle_touch_highlight_background" android:background="@drawable/circle_touch_highlight_background"
android:layout_marginStart="16dp" android:layout_marginTop="8dp"
android:layout_marginStart="8dp"
android:layout_marginBottom="8dp"
android:padding="8dp" android:padding="8dp"
android:src="@drawable/symbol_match_case_24" android:src="@drawable/symbol_match_case_24"
app:tint="@color/signal_colorOnSurface" app:tint="@color/signal_colorOnSurface"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toEndOf="@+id/debug_log_filter"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" /> app:layout_constraintBottom_toBottomOf="parent" />

View File

@@ -52,11 +52,13 @@ editor.session.on("changeScrollLeft", showScrollBar);
const Range = ace.require("ace/range").Range; const Range = ace.require("ace/range").Range;
const session = editor.getSession(); const session = editor.getSession();
let logLines = ""; // Original logLines
let input = ""; // Search query input let input = ""; // Search query input
let markers = []; // IDs of highlighted search markers let markers = []; // IDs of highlighted search markers
let matchRanges = []; // Ranges of all search matches let matchRanges = []; // Ranges of all search matches
let matchCount = 0; // Total number of matches let matchCount = 0; // Total number of matches
let isCaseSensitive = false; let isCaseSensitive = false;
let isFiltered = false;
// Clear all search markers and match info // Clear all search markers and match info
function clearMarkers() { function clearMarkers() {
@@ -139,10 +141,34 @@ function onSearchClose() {
function onToggleCaseSensitive() { function onToggleCaseSensitive() {
isCaseSensitive = !isCaseSensitive; isCaseSensitive = !isCaseSensitive;
highlightAllMatches(input); (isFiltered) ? onFilter() : highlightAllMatches(input);
} }
function onSearchInput(value) { function onSearchInput(value) {
input = value; input = value;
}
function onSearch() {
highlightAllMatches(input);
}
function onFilter() {
isFiltered = true;
editor.getSelection().clearSelection();
clearMarkers();
const filtered = logLines
.split("\n")
.filter((line) => {
const newLine = isCaseSensitive ? line : line.toLowerCase();
return newLine.includes(isCaseSensitive ? input : input.toLowerCase());
})
.join("\n");
editor.setValue(filtered, -1);
}
function onFilterClose() {
isFiltered = false;
editor.setValue(logLines, -1);
highlightAllMatches(input); highlightAllMatches(input);
} }

View File

@@ -47,7 +47,7 @@ object DebugLogsViewer {
fun presentLines(webview: WebView, lines: String) { fun presentLines(webview: WebView, lines: String) {
// Set the debug log lines // Set the debug log lines
val escaped = JSONObject.quote(lines) val escaped = JSONObject.quote(lines)
webview.evaluateJavascript("editor.insert($escaped);", null) webview.evaluateJavascript("editor.insert($escaped); logLines=$escaped;", null)
} }
@JvmStatic @JvmStatic
@@ -61,10 +61,25 @@ object DebugLogsViewer {
} }
@JvmStatic @JvmStatic
fun onSearch(webview: WebView, query: String) { fun onSearchInput(webview: WebView, query: String) {
webview.evaluateJavascript("onSearchInput('$query')", null) webview.evaluateJavascript("onSearchInput('$query')", null)
} }
@JvmStatic
fun onSearch(webview: WebView) {
webview.evaluateJavascript("onSearch()", null)
}
@JvmStatic
fun onFilter(webview: WebView) {
webview.evaluateJavascript("onFilter()", null)
}
@JvmStatic
fun onFilterClose(webview: WebView) {
webview.evaluateJavascript("onFilterClose()", null)
}
@JvmStatic @JvmStatic
fun onSearchUp(webview: WebView) { fun onSearchUp(webview: WebView) {
webview.evaluateJavascript("onSearchUp();", null) webview.evaluateJavascript("onSearchUp();", null)
@@ -90,10 +105,6 @@ object DebugLogsViewer {
webview.evaluateJavascript("onSearchClose();", null) webview.evaluateJavascript("onSearchClose();", null)
} }
@JvmStatic
fun onFilter(webview: WebView) {
}
@JvmStatic @JvmStatic
fun onEdit(webview: WebView) { fun onEdit(webview: WebView) {
readOnly = !readOnly readOnly = !readOnly