diff --git a/app/src/main/java/org/thoughtcrime/securesms/logsubmit/SubmitDebugLogActivity.java b/app/src/main/java/org/thoughtcrime/securesms/logsubmit/SubmitDebugLogActivity.java index b8dcc3e480..87de54ae48 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/logsubmit/SubmitDebugLogActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/logsubmit/SubmitDebugLogActivity.java @@ -61,11 +61,14 @@ public class SubmitDebugLogActivity extends BaseActivity { private MenuItem searchMenuItem; private MenuItem saveMenuItem; - private ImageButton caseSensitiveButton; - private TextView searchPosition; - private ImageButton searchUpButton; - private ImageButton searchDownButton; + private ImageButton filterButton; + private ImageButton caseSensitiveButton; + private TextView searchPosition; + private ImageButton searchUpButton; + private ImageButton searchDownButton; + private boolean isCaseSensitive; + private boolean isFiltered; private boolean isWebViewLoaded; private boolean hasPresentedLines; @@ -101,6 +104,7 @@ public class SubmitDebugLogActivity extends BaseActivity { this.saveMenuItem = menu.findItem(R.id.menu_save); 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.searchPosition = findViewById(R.id.debug_log_search_position); 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)); }); - boolean[] isCaseSensitive = {false}; - caseSensitiveButton.setOnClickListener(v -> { DebugLogsViewer.onToggleCaseSensitive(logWebView); 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)); }); + 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.OnQueryTextListener queryListener = new SearchView.OnQueryTextListener() { @Override @@ -136,8 +157,13 @@ public class SubmitDebugLogActivity extends BaseActivity { @Override public boolean onQueryTextChange(String query) { - DebugLogsViewer.onSearch(logWebView, query); - DebugLogsViewer.getSearchPosition(logWebView, position -> searchPosition.setText(position)); + DebugLogsViewer.onSearchInput(logWebView, query); + if (isFiltered) { + DebugLogsViewer.onFilter(logWebView); + } else { + DebugLogsViewer.onSearch(logWebView); + DebugLogsViewer.getSearchPosition(logWebView, position -> searchPosition.setText(position)); + } return true; } }; @@ -156,6 +182,7 @@ public class SubmitDebugLogActivity extends BaseActivity { searchNav.setVisibility(View.GONE); submitButton.setVisibility(View.VISIBLE); DebugLogsViewer.onSearchClose(logWebView); + DebugLogsViewer.onFilterClose(logWebView); DebugLogsViewer.getSearchPosition(logWebView, position -> searchPosition.setText(position)); searchView.setOnQueryTextListener(null); return true; diff --git a/app/src/main/res/layout/submit_debug_log_activity.xml b/app/src/main/res/layout/submit_debug_log_activity.xml index 2e692fb3e0..1c1157a711 100644 --- a/app/src/main/res/layout/submit_debug_log_activity.xml +++ b/app/src/main/res/layout/submit_debug_log_activity.xml @@ -98,16 +98,33 @@ app:layout_constraintBottom_toBottomOf="parent" tools:visibility="visible"> + + diff --git a/debuglogs-viewer/lib/src/main/assets/debuglogs-viewer.js b/debuglogs-viewer/lib/src/main/assets/debuglogs-viewer.js index 5887192e5b..1eaf9b7f99 100644 --- a/debuglogs-viewer/lib/src/main/assets/debuglogs-viewer.js +++ b/debuglogs-viewer/lib/src/main/assets/debuglogs-viewer.js @@ -52,11 +52,13 @@ editor.session.on("changeScrollLeft", showScrollBar); const Range = ace.require("ace/range").Range; const session = editor.getSession(); +let logLines = ""; // Original logLines 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; +let isFiltered = false; // Clear all search markers and match info function clearMarkers() { @@ -139,10 +141,34 @@ function onSearchClose() { function onToggleCaseSensitive() { isCaseSensitive = !isCaseSensitive; - highlightAllMatches(input); + (isFiltered) ? onFilter() : highlightAllMatches(input); } function onSearchInput(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); +} \ No newline at end of file diff --git a/debuglogs-viewer/lib/src/main/java/org/signal/debuglogsviewer/DebugLogsViewer.kt b/debuglogs-viewer/lib/src/main/java/org/signal/debuglogsviewer/DebugLogsViewer.kt index 388cbe2766..2168cf43a6 100644 --- a/debuglogs-viewer/lib/src/main/java/org/signal/debuglogsviewer/DebugLogsViewer.kt +++ b/debuglogs-viewer/lib/src/main/java/org/signal/debuglogsviewer/DebugLogsViewer.kt @@ -47,7 +47,7 @@ object DebugLogsViewer { fun presentLines(webview: WebView, lines: String) { // Set the debug log lines val escaped = JSONObject.quote(lines) - webview.evaluateJavascript("editor.insert($escaped);", null) + webview.evaluateJavascript("editor.insert($escaped); logLines=$escaped;", null) } @JvmStatic @@ -61,10 +61,25 @@ object DebugLogsViewer { } @JvmStatic - fun onSearch(webview: WebView, query: String) { + fun onSearchInput(webview: WebView, query: String) { 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 fun onSearchUp(webview: WebView) { webview.evaluateJavascript("onSearchUp();", null) @@ -90,10 +105,6 @@ object DebugLogsViewer { webview.evaluateJavascript("onSearchClose();", null) } - @JvmStatic - fun onFilter(webview: WebView) { - } - @JvmStatic fun onEdit(webview: WebView) { readOnly = !readOnly