]> gitweb.stoutner.com Git - PrivacyCell.git/commitdiff
Add a logcat activity. https://redmine.stoutner.com/issues/768
authorSoren Stoutner <soren@stoutner.com>
Tue, 12 Oct 2021 23:46:31 +0000 (16:46 -0700)
committerSoren Stoutner <soren@stoutner.com>
Tue, 12 Oct 2021 23:46:31 +0000 (16:46 -0700)
44 files changed:
app/build.gradle
app/src/main/AndroidManifest.xml
app/src/main/assets/en/licenses.html
app/src/main/assets/es/licenses.html
app/src/main/assets/fr/licenses.html
app/src/main/assets/images/bug_report_rounded.svg
app/src/main/assets/images/call_to_action_rounded.svg
app/src/main/assets/images/chrome_reader_mode_rounded.svg
app/src/main/assets/images/close_rounded.svg [new file with mode: 0644]
app/src/main/assets/images/content_copy_outlined.svg [new file with mode: 0644]
app/src/main/assets/images/fact_check_outlined.svg
app/src/main/assets/images/format_list_bulleted_rounded.svg
app/src/main/assets/images/forum_rounded.svg
app/src/main/assets/images/groups_filled.svg
app/src/main/assets/images/list_alt_rounded.svg [new file with mode: 0644]
app/src/main/assets/images/map_rounded.svg
app/src/main/assets/images/not_secure.svg
app/src/main/assets/images/payments_rounded.svg
app/src/main/assets/images/phone_android_outlined.svg
app/src/main/assets/images/policy_filled.svg
app/src/main/assets/images/privacy_cell.svg
app/src/main/assets/images/save_outlined.svg [new file with mode: 0644]
app/src/main/assets/images/settings_rounded.svg
app/src/main/assets/images/text_snippet_outlined.svg
app/src/main/assets/it/licenses.html
app/src/main/assets/ru/licenses.html
app/src/main/java/com/stoutner/privacycell/activities/LogcatActivity.kt [new file with mode: 0644]
app/src/main/java/com/stoutner/privacycell/activities/PrivacyCellActivity.kt
app/src/main/res/drawable/clear.xml [new file with mode: 0644]
app/src/main/res/drawable/copy.xml [new file with mode: 0644]
app/src/main/res/drawable/logcat.xml [new file with mode: 0644]
app/src/main/res/drawable/save.xml [new file with mode: 0644]
app/src/main/res/layout/logcat_bottom_appbar.xml [new file with mode: 0644]
app/src/main/res/layout/logcat_top_appbar.xml [new file with mode: 0644]
app/src/main/res/menu/logcat_options_menu.xml [new file with mode: 0644]
app/src/main/res/menu/navigation_menu_bottom_appbar.xml
app/src/main/res/menu/navigation_menu_top_appbar.xml
app/src/main/res/values-es/strings.xml
app/src/main/res/values-fr/strings.xml
app/src/main/res/values-it/strings.xml
app/src/main/res/values-night/colors.xml
app/src/main/res/values-ru/strings.xml
app/src/main/res/values/colors.xml
app/src/main/res/values/strings.xml

index 58c39593b1ef5206dff9cdf0650ebeaca044536e..5c2d71733554d03dcf5e40f88854badf45609cb8 100644 (file)
@@ -52,6 +52,7 @@ dependencies {
     implementation 'androidx.appcompat:appcompat:1.3.1'
     implementation 'androidx.core:core-ktx:1.6.0'
     implementation 'androidx.preference:preference-ktx:1.1.1'
+    implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
     implementation 'androidx.webkit:webkit:1.4.0'
     implementation 'androidx.work:work-runtime-ktx:2.6.0'
 
index 4400b2cac5c197a51eeda5354d1b95a84ede72bc..2196ce8678ca80f597832c44d66b9e244b7117ad 100644 (file)
             </intent-filter>
         </activity>
 
-        <!-- Settings Activity.  The `parentActivityName` is used when restarting Privacy Cell.-->
+        <!-- Settings Activity.  The `parentActivityName` is used when restarting Privacy Cell and when navigating back. -->
         <activity
             android:name=".activities.SettingsActivity"
             android:label="@string/settings"
             android:screenOrientation="fullUser"
             android:parentActivityName=".activities.PrivacyCellActivity" />
 
+        <!-- Logcat Activity. The `parentActivityName` is used when navigating back. -->
+        <activity
+            android:name=".activities.LogcatActivity"
+            android:label="@string/logcat"
+            android:parentActivityName=".activities.PrivacyCellActivity"
+            android:screenOrientation="fullUser" />
+
         <!-- Realtime Monitoring Service. -->
         <service android:name=".services.RealtimeMonitoringService" />
 
index a370ba5540bcdef1735b0d656cb9114d23724f50..c6914ce0fe0a99c78fce0e7d2efb21d90c15f76f 100644 (file)
         <p><svg class="icon"><use href="../images/bug_report_rounded.svg#icon"/></svg> bug_report_rounded.</p>
         <p><svg class="icon"><use href="../images/call_to_action_rounded.svg#icon"/></svg> call_to_action_rounded.</p>
         <p><svg class="icon"><use href="../images/chrome_reader_mode_rounded.svg#icon"/></svg> chrome_reader_mode_rounded.</p>
+        <p><svg class="icon"><use href="../images/close_rounded.svg#icon"/></svg> close_rounded.</p>
+        <p><svg class="icon"><use href="../images/content_copy_outlined.svg#icon"/></svg> content_copy_outlined.</p>
         <p><svg class="icon"><use href="../images/fact_check_outlined.svg#icon"/></svg> fact_checked_outlined.</p>
         <p><svg class="icon"><use href="../images/format_list_bulleted_rounded.svg#icon"/></svg> format_list_bulleted_rounded.</p>
         <p><svg class="icon"><use href="../images/forum_rounded.svg#icon"/></svg> forum_rounded.</p>
         <p><svg class="icon"><use href="../images/groups_filled.svg#icon"/></svg> groups_filled.</p>
+        <p><svg class="icon"><use href="../images/list_alt_rounded.svg#icon"/></svg> list_alt_rounded.</p>
         <p><svg class="icon"><use href="../images/map_rounded.svg#icon"/></svg> map_rounded.</p>
         <p><svg class="icon"><use href="../images/payments_rounded.svg#icon"/></svg> payments_rounded.</p>
         <p><svg class="icon"><use href="../images/phone_android_outlined.svg#icon"/></svg> phone_android_outlined.</p>
         <p><svg class="icon"><use href="../images/policy_filled.svg#icon"/></svg> policy_filled.</p>
+        <p><svg class="icon"><use href="../images/save_outlined.svg#icon"/></svg> save_outlined.</p>
         <p><svg class="icon"><use href="../images/settings_rounded.svg#icon"/></svg> settings_rounded.</p>
         <p><svg class="icon"><use href="../images/text_snippet_outlined.svg#icon"/></svg> text_snippet_outlined.</p>
 
index 8eb61d5fbd12d867dcbce6310a66dbe986681a56..cae1254ad6421323b8e93d0c5d5db598145c54be 100644 (file)
         <p><svg class="icon"><use href="../images/bug_report_rounded.svg#icon"/></svg> bug_report_rounded.</p>
         <p><svg class="icon"><use href="../images/call_to_action_rounded.svg#icon"/></svg> call_to_action_rounded.</p>
         <p><svg class="icon"><use href="../images/chrome_reader_mode_rounded.svg#icon"/></svg> chrome_reader_mode_rounded.</p>
+        <p><svg class="icon"><use href="../images/close_rounded.svg#icon"/></svg> close_rounded.</p>
+        <p><svg class="icon"><use href="../images/content_copy_outlined.svg#icon"/></svg> content_copy_outlined.</p>
         <p><svg class="icon"><use href="../images/fact_check_outlined.svg#icon"/></svg> fact_checked_outlined.</p>
         <p><svg class="icon"><use href="../images/format_list_bulleted_rounded.svg#icon"/></svg> format_list_bulleted_rounded.</p>
         <p><svg class="icon"><use href="../images/forum_rounded.svg#icon"/></svg> forum_rounded.</p>
         <p><svg class="icon"><use href="../images/groups_filled.svg#icon"/></svg> groups_filled.</p>
+        <p><svg class="icon"><use href="../images/list_alt_rounded.svg#icon"/></svg> list_alt_rounded.</p>
         <p><svg class="icon"><use href="../images/map_rounded.svg#icon"/></svg> map_rounded.</p>
         <p><svg class="icon"><use href="../images/payments_rounded.svg#icon"/></svg> payments_rounded.</p>
         <p><svg class="icon"><use href="../images/phone_android_outlined.svg#icon"/></svg> phone_android_outlined.</p>
         <p><svg class="icon"><use href="../images/policy_filled.svg#icon"/></svg> policy_filled.</p>
+        <p><svg class="icon"><use href="../images/save_outlined.svg#icon"/></svg> save_outlined.</p>
         <p><svg class="icon"><use href="../images/settings_rounded.svg#icon"/></svg> settings_rounded.</p>
         <p><svg class="icon"><use href="../images/text_snippet_outlined.svg#icon"/></svg> text_snippet_outlined.</p>
 
index cb7f10c5ed68f0831adfd970b2580fc28a503453..7855e7830973db10404b3fe49602884cf2c1fde9 100644 (file)
         <p><svg class="icon"><use href="../images/bug_report_rounded.svg#icon"/></svg> bug_report_rounded.</p>
         <p><svg class="icon"><use href="../images/call_to_action_rounded.svg#icon"/></svg> call_to_action_rounded.</p>
         <p><svg class="icon"><use href="../images/chrome_reader_mode_rounded.svg#icon"/></svg> chrome_reader_mode_rounded.</p>
+        <p><svg class="icon"><use href="../images/close_rounded.svg#icon"/></svg> close_rounded.</p>
+        <p><svg class="icon"><use href="../images/content_copy_outlined.svg#icon"/></svg> content_copy_outlined.</p>
         <p><svg class="icon"><use href="../images/fact_check_outlined.svg#icon"/></svg> fact_checked_outlined.</p>
         <p><svg class="icon"><use href="../images/format_list_bulleted_rounded.svg#icon"/></svg> format_list_bulleted_rounded.</p>
         <p><svg class="icon"><use href="../images/forum_rounded.svg#icon"/></svg> forum_rounded.</p>
         <p><svg class="icon"><use href="../images/groups_filled.svg#icon"/></svg> groups_filled.</p>
+        <p><svg class="icon"><use href="../images/list_alt_rounded.svg#icon"/></svg> list_alt_rounded.</p>
         <p><svg class="icon"><use href="../images/map_rounded.svg#icon"/></svg> map_rounded.</p>
         <p><svg class="icon"><use href="../images/payments_rounded.svg#icon"/></svg> payments_rounded.</p>
         <p><svg class="icon"><use href="../images/phone_android_outlined.svg#icon"/></svg> phone_android_outlined.</p>
         <p><svg class="icon"><use href="../images/policy_filled.svg#icon"/></svg> policy_filled.</p>
+        <p><svg class="icon"><use href="../images/save_outlined.svg#icon"/></svg> save_outlined.</p>
         <p><svg class="icon"><use href="../images/settings_rounded.svg#icon"/></svg> settings_rounded.</p>
         <p><svg class="icon"><use href="../images/text_snippet_outlined.svg#icon"/></svg> text_snippet_outlined.</p>
 
index fbac78cf2e2fc87ff282d3ee422d6b88134ff063..3ec48b02f6819f52a98e2aa057b0f8dc1b09c953 100644 (file)
   along with Privacy Cell.  If not, see <http://www.gnu.org/licenses/>. -->
 
 <svg
-  xmlns="http://www.w3.org/2000/svg"
-  viewBox="0 0 24 24"
-  id="icon" >
+    xmlns="http://www.w3.org/2000/svg"
+    viewBox="0 0 24 24"
+    id="icon" >
 
-  <path
-    d="M19 8h-1.81c-.45-.78-1.07-1.45-1.82-1.96l.93-.93c.39-.39.39-1.02 0-1.41-.39-.39-1.02-.39-1.41 0l-1.47 1.47C12.96 5.06 12.49 5 12 5s-.96.06-1.41.17L9.11 3.7c-.39-.39-1.02-.39-1.41 0-.39.39-.39 1.02 0 1.41l.92.93C7.88 6.55 7.26 7.22 6.81 8H5c-.55 0-1 .45-1 1s.45 1 1 1h1.09c-.05.33-.09.66-.09 1v1H5c-.55 0-1 .45-1 1s.45 1 1 1h1v1c0 .34.04.67.09 1H5c-.55 0-1 .45-1 1s.45 1 1 1h1.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H19c.55 0 1-.45 1-1s-.45-1-1-1h-1.09c.05-.33.09-.66.09-1v-1h1c.55 0 1-.45 1-1s-.45-1-1-1h-1v-1c0-.34-.04-.67-.09-1H19c.55 0 1-.45 1-1s-.45-1-1-1zm-6 8h-2c-.55 0-1-.45-1-1s.45-1 1-1h2c.55 0 1 .45 1 1s-.45 1-1 1zm0-4h-2c-.55 0-1-.45-1-1s.45-1 1-1h2c.55 0 1 .45 1 1s-.45 1-1 1z" />
+    <path
+        d="M19 8h-1.81c-.45-.78-1.07-1.45-1.82-1.96l.93-.93c.39-.39.39-1.02 0-1.41-.39-.39-1.02-.39-1.41 0l-1.47 1.47C12.96 5.06 12.49 5 12 5s-.96.06-1.41.17L9.11 3.7c-.39-.39-1.02-.39-1.41 0-.39.39-.39 1.02 0 1.41l.92.93C7.88 6.55 7.26 7.22 6.81 8H5c-.55 0-1 .45-1 1s.45 1 1 1h1.09c-.05.33-.09.66-.09 1v1H5c-.55 0-1 .45-1 1s.45 1 1 1h1v1c0 .34.04.67.09 1H5c-.55 0-1 .45-1 1s.45 1 1 1h1.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H19c.55 0 1-.45 1-1s-.45-1-1-1h-1.09c.05-.33.09-.66.09-1v-1h1c.55 0 1-.45 1-1s-.45-1-1-1h-1v-1c0-.34-.04-.67-.09-1H19c.55 0 1-.45 1-1s-.45-1-1-1zm-6 8h-2c-.55 0-1-.45-1-1s.45-1 1-1h2c.55 0 1 .45 1 1s-.45 1-1 1zm0-4h-2c-.55 0-1-.45-1-1s.45-1 1-1h2c.55 0 1 .45 1 1s-.45 1-1 1z" />
 </svg>
\ No newline at end of file
index e81a073f982be50f64c473bbfa2796d37178e878..9921a52ada1a02a508e1fb0e4f17d0c229105d23 100644 (file)
   along with Privacy Cell.  If not, see <http://www.gnu.org/licenses/>. -->
 
 <svg
-  xmlns="http://www.w3.org/2000/svg"
-  viewBox="0 0 24 24"
-  id="icon" >
+    xmlns="http://www.w3.org/2000/svg"
+    viewBox="0 0 24 24"
+    id="icon" >
 
-  <path
-    d="M21 3H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H4c-.55 0-1-.45-1-1v-1c0-.55.45-1 1-1h16c.55 0 1 .45 1 1v1c0 .55-.45 1-1 1z" />
+    <path
+        d="M21 3H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H4c-.55 0-1-.45-1-1v-1c0-.55.45-1 1-1h16c.55 0 1 .45 1 1v1c0 .55-.45 1-1 1z" />
 </svg>
\ No newline at end of file
index 5d924420f2e26bf786dd6cf0c87aee03632fdc53..855df2cd28b82375d45e1f8de51d3513e5e97f39 100644 (file)
   along with Privacy Cell.  If not, see <http://www.gnu.org/licenses/>. -->
 
 <svg
-  xmlns="http://www.w3.org/2000/svg"
-  viewBox="0 0 24 24"
-  id="icon" >
+    xmlns="http://www.w3.org/2000/svg"
+    viewBox="0 0 24 24"
+    id="icon" >
 
-  <path
-    d="M21 4H3c-1.1 0-2 .9-2 2v13c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 14c0 .55-.45 1-1 1h-8V6h8c.55 0 1 .45 1 1v11zm-1.75-8.5h-5.5c-.41 0-.75.34-.75.75s.34.75.75.75h5.5c.41 0 .75-.34.75-.75s-.34-.75-.75-.75zm0 2.5h-5.5c-.41 0-.75.34-.75.75s.34.75.75.75h5.5c.41 0 .75-.34.75-.75s-.34-.75-.75-.75zm0 2.5h-5.5c-.41 0-.75.34-.75.75s.34.75.75.75h5.5c.41 0 .75-.34.75-.75s-.34-.75-.75-.75z" />
+    <path
+        d="M21 4H3c-1.1 0-2 .9-2 2v13c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 14c0 .55-.45 1-1 1h-8V6h8c.55 0 1 .45 1 1v11zm-1.75-8.5h-5.5c-.41 0-.75.34-.75.75s.34.75.75.75h5.5c.41 0 .75-.34.75-.75s-.34-.75-.75-.75zm0 2.5h-5.5c-.41 0-.75.34-.75.75s.34.75.75.75h5.5c.41 0 .75-.34.75-.75s-.34-.75-.75-.75zm0 2.5h-5.5c-.41 0-.75.34-.75.75s.34.75.75.75h5.5c.41 0 .75-.34.75-.75s-.34-.75-.75-.75z" />
 </svg>
\ No newline at end of file
diff --git a/app/src/main/assets/images/close_rounded.svg b/app/src/main/assets/images/close_rounded.svg
new file mode 100644 (file)
index 0000000..f895cea
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+
+<!--
+  This file is a modified version of `content_copy_outlined`, which is part of the Android Material icon set and is released under the Apache License 2.0.
+
+  Changes copyright © 2021 Soren Stoutner <soren@stoutner.com>.  The resulting file is released under the GPLv3+ license.
+
+  This file is part of Privacy Cell <https://www.stoutner.com/privacy-cell>.
+
+  Privacy Cell is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  Privacy Cell is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with Privacy Cell.  If not, see <http://www.gnu.org/licenses/>. -->
+
+<svg
+    xmlns="http://www.w3.org/2000/svg"
+    viewBox="0 0 24 24"
+    id="icon" >
+
+    <path
+        d="M18.3 5.71c-.39-.39-1.02-.39-1.41 0L12 10.59 7.11 5.7c-.39-.39-1.02-.39-1.41 0-.39.39-.39 1.02 0 1.41L10.59 12 5.7 16.89c-.39.39-.39 1.02 0 1.41.39.39 1.02.39 1.41 0L12 13.41l4.89 4.89c.39.39 1.02.39 1.41 0 .39-.39.39-1.02 0-1.41L13.41 12l4.89-4.89c.38-.38.38-1.02 0-1.4z" />
+</svg>
diff --git a/app/src/main/assets/images/content_copy_outlined.svg b/app/src/main/assets/images/content_copy_outlined.svg
new file mode 100644 (file)
index 0000000..3c33f2d
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+
+<!--
+  This file is a modified version of `content_copy_outlined`, which is part of the Android Material icon set and is released under the Apache License 2.0.
+
+  Changes copyright © 2021 Soren Stoutner <soren@stoutner.com>.  The resulting file is released under the GPLv3+ license.
+
+  This file is part of Privacy Cell <https://www.stoutner.com/privacy-cell>.
+
+  Privacy Cell is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  Privacy Cell is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with Privacy Cell.  If not, see <http://www.gnu.org/licenses/>. -->
+
+<svg
+    xmlns="http://www.w3.org/2000/svg"
+    viewBox="0 0 24 24"
+    id="icon" >
+
+    <path
+        d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z" />
+</svg>
index 91cb8af3ffe636a42ecce8361a2a01742c3e28e0..2bcbcd6a4d4c4e29a9c0cbe3f09da3ed94342391 100644 (file)
   along with Privacy Cell.  If not, see <http://www.gnu.org/licenses/>. -->
 
 <svg
-  xmlns="http://www.w3.org/2000/svg"
-  viewBox="0 0 20 20"
-  id="icon" >
-
-  <path
-    d="M16,4H4C3.45,4,3,4.45,3,5v10c0,0.55,0.45,1,1,1h12c0.55,0,1-0.45,1-1V5 C17,4.45,16.55,4,16,4z M16,15H4V5h12V15z" />
-
-  <rect
-    height="1"
-    width="4"
-    x="5"
-    y="7" />
-
-  <rect
-    height="1"
-    width="4"
-    x="5"
-    y="9.5" />
-
-  <rect
-    height="1"
-    width="4"
-    x="5"
-    y="12" />
-
-  <polygon
-    points="11.97,11.77 14.8,8.94 14.1,8.23 11.97,10.35 11.27,9.65 10.56,10.35" />
+    xmlns="http://www.w3.org/2000/svg"
+    viewBox="0 0 20 20"
+    id="icon" >
+
+    <path
+        d="M16,4H4C3.45,4,3,4.45,3,5v10c0,0.55,0.45,1,1,1h12c0.55,0,1-0.45,1-1V5 C17,4.45,16.55,4,16,4z M16,15H4V5h12V15z" />
+
+    <rect
+        height="1"
+        width="4"
+        x="5"
+        y="7" />
+
+    <rect
+        height="1"
+        width="4"
+        x="5"
+        y="9.5" />
+
+    <rect
+        height="1"
+        width="4"
+        x="5"
+        y="12" />
+
+    <polygon
+        points="11.97,11.77 14.8,8.94 14.1,8.23 11.97,10.35 11.27,9.65 10.56,10.35" />
 </svg>
\ No newline at end of file
index b1f2851d0026a2f0ae655d58c6d15410ddba2373..4ea9b140b36ab594ac4c548292c165eff7cb8df7 100644 (file)
   along with Privacy Cell.  If not, see <http://www.gnu.org/licenses/>. -->
 
 <svg
-  xmlns="http://www.w3.org/2000/svg"
-  viewBox="0 0 24 24"
-  id="icon" >
+    xmlns="http://www.w3.org/2000/svg"
+    viewBox="0 0 24 24"
+    id="icon" >
 
-  <path
-    d="M4 10.5c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5zm0-6c-.83 0-1.5.67-1.5 1.5S3.17 7.5 4 7.5 5.5 6.83 5.5 6 4.83 4.5 4 4.5zm0 12c-.83 0-1.5.68-1.5 1.5s.68 1.5 1.5 1.5 1.5-.68 1.5-1.5-.67-1.5-1.5-1.5zM8 19h12c.55 0 1-.45 1-1s-.45-1-1-1H8c-.55 0-1 .45-1 1s.45 1 1 1zm0-6h12c.55 0 1-.45 1-1s-.45-1-1-1H8c-.55 0-1 .45-1 1s.45 1 1 1zM7 6c0 .55.45 1 1 1h12c.55 0 1-.45 1-1s-.45-1-1-1H8c-.55 0-1 .45-1 1z" />
+    <path
+        d="M4 10.5c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5zm0-6c-.83 0-1.5.67-1.5 1.5S3.17 7.5 4 7.5 5.5 6.83 5.5 6 4.83 4.5 4 4.5zm0 12c-.83 0-1.5.68-1.5 1.5s.68 1.5 1.5 1.5 1.5-.68 1.5-1.5-.67-1.5-1.5-1.5zM8 19h12c.55 0 1-.45 1-1s-.45-1-1-1H8c-.55 0-1 .45-1 1s.45 1 1 1zm0-6h12c.55 0 1-.45 1-1s-.45-1-1-1H8c-.55 0-1 .45-1 1s.45 1 1 1zM7 6c0 .55.45 1 1 1h12c.55 0 1-.45 1-1s-.45-1-1-1H8c-.55 0-1 .45-1 1z" />
 </svg>
\ No newline at end of file
index 50edc80cd5b77c7cdb3f186f6458a046aa964f87..0179ccf952921d4fa2f561d0607732546bd60520 100644 (file)
   along with Privacy Cell.  If not, see <http://www.gnu.org/licenses/>. -->
 
 <svg
-  xmlns="http://www.w3.org/2000/svg"
-  viewBox="0 0 24 24"
-  id="icon" >
+    xmlns="http://www.w3.org/2000/svg"
+    viewBox="0 0 24 24"
+    id="icon" >
 
-  <path
-    d="M20 6h-1v8c0 .55-.45 1-1 1H6v1c0 1.1.9 2 2 2h10l4 4V8c0-1.1-.9-2-2-2zm-3 5V4c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v13l4-4h9c1.1 0 2-.9 2-2z" />
+    <path
+        d="M20 6h-1v8c0 .55-.45 1-1 1H6v1c0 1.1.9 2 2 2h10l4 4V8c0-1.1-.9-2-2-2zm-3 5V4c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v13l4-4h9c1.1 0 2-.9 2-2z" />
 </svg>
\ No newline at end of file
index d2aee47c3fa17b99d46a0eafa8eacdbe68300319..72b0f803722990dda676f3f48019bb43c9072063 100644 (file)
   along with Privacy Cell.  If not, see <http://www.gnu.org/licenses/>. -->
 
 <svg
-  xmlns="http://www.w3.org/2000/svg"
-  viewBox="0 0 24 24"
-  id="icon" >
+    xmlns="http://www.w3.org/2000/svg"
+    viewBox="0 0 24 24"
+    id="icon" >
 
-  <path
-    d="M12,12.75c1.63,0,3.07,0.39,4.24,0.9c1.08,0.48,1.76,1.56,1.76,2.73L18,18H6l0-1.61c0-1.18,0.68-2.26,1.76-2.73 C8.93,13.14,10.37,12.75,12,12.75z M4,13c1.1,0,2-0.9,2-2c0-1.1-0.9-2-2-2s-2,0.9-2,2C2,12.1,2.9,13,4,13z M5.13,14.1 C4.76,14.04,4.39,14,4,14c-0.99,0-1.93,0.21-2.78,0.58C0.48,14.9,0,15.62,0,16.43V18l4.5,0v-1.61C4.5,15.56,4.73,14.78,5.13,14.1z M20,13c1.1,0,2-0.9,2-2c0-1.1-0.9-2-2-2s-2,0.9-2,2C18,12.1,18.9,13,20,13z M24,16.43c0-0.81-0.48-1.53-1.22-1.85 C21.93,14.21,20.99,14,20,14c-0.39,0-0.76,0.04-1.13,0.1c0.4,0.68,0.63,1.46,0.63,2.29V18l4.5,0V16.43z M12,6c1.66,0,3,1.34,3,3 c0,1.66-1.34,3-3,3s-3-1.34-3-3C9,7.34,10.34,6,12,6z" />
+    <path
+        d="M12,12.75c1.63,0,3.07,0.39,4.24,0.9c1.08,0.48,1.76,1.56,1.76,2.73L18,18H6l0-1.61c0-1.18,0.68-2.26,1.76-2.73 C8.93,13.14,10.37,12.75,12,12.75z M4,13c1.1,0,2-0.9,2-2c0-1.1-0.9-2-2-2s-2,0.9-2,2C2,12.1,2.9,13,4,13z M5.13,14.1 C4.76,14.04,4.39,14,4,14c-0.99,0-1.93,0.21-2.78,0.58C0.48,14.9,0,15.62,0,16.43V18l4.5,0v-1.61C4.5,15.56,4.73,14.78,5.13,14.1z M20,13c1.1,0,2-0.9,2-2c0-1.1-0.9-2-2-2s-2,0.9-2,2C18,12.1,18.9,13,20,13z M24,16.43c0-0.81-0.48-1.53-1.22-1.85 C21.93,14.21,20.99,14,20,14c-0.39,0-0.76,0.04-1.13,0.1c0.4,0.68,0.63,1.46,0.63,2.29V18l4.5,0V16.43z M12,6c1.66,0,3,1.34,3,3 c0,1.66-1.34,3-3,3s-3-1.34-3-3C9,7.34,10.34,6,12,6z" />
 </svg>
\ No newline at end of file
diff --git a/app/src/main/assets/images/list_alt_rounded.svg b/app/src/main/assets/images/list_alt_rounded.svg
new file mode 100644 (file)
index 0000000..c07743c
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+
+<!--
+  This file is a modified version of `list_alt_rounded`, which is part of the Android Material icon set and is released under the Apache License 2.0.
+
+  Changes copyright © 2021 Soren Stoutner <soren@stoutner.com>.  The resulting file is released under the GPLv3+ license.
+
+  This file is part of Privacy Cell <https://www.stoutner.com/privacy-cell>.
+
+  Privacy Cell is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  Privacy Cell is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with Privacy Cell.  If not, see <http://www.gnu.org/licenses/>. -->
+
+<svg
+    xmlns="http://www.w3.org/2000/svg"
+    viewBox="0 0 24 24"
+    id="icon" >
+
+    <path
+        d="M12 9h4c.55 0 1-.45 1-1s-.45-1-1-1h-4c-.55 0-1 .45-1 1s.45 1 1 1zm0 4h4c.55 0 1-.45 1-1s-.45-1-1-1h-4c-.55 0-1 .45-1 1s.45 1 1 1zm0 4h4c.55 0 1-.45 1-1s-.45-1-1-1h-4c-.55 0-1 .45-1 1s.45 1 1 1zM7 7h2v2H7zm0 4h2v2H7zm0 4h2v2H7zM20 3H4c-.55 0-1 .45-1 1v16c0 .55.45 1 1 1h16c.55 0 1-.45 1-1V4c0-.55-.45-1-1-1zm-1 16H5V5h14v14z" />
+</svg>
index 201f4c5d56da8c5792fe6461d89911e90e09f566..84bafe2ebcbe17713e6a4f1f78210c21bc491820 100644 (file)
   along with Privacy Cell.  If not, see <http://www.gnu.org/licenses/>. -->
 
 <svg
-  xmlns="http://www.w3.org/2000/svg"
-  viewBox="0 0 24 24"
-  id="icon" >
+    xmlns="http://www.w3.org/2000/svg"
+    viewBox="0 0 24 24"
+    id="icon" >
 
-  <path
-    d="M14.65 4.98l-5-1.75c-.42-.15-.88-.15-1.3-.01L4.36 4.56C3.55 4.84 3 5.6 3 6.46v11.85c0 1.41 1.41 2.37 2.72 1.86l2.93-1.14c.22-.09.47-.09.69-.01l5 1.75c.42.15.88.15 1.3.01l3.99-1.34c.81-.27 1.36-1.04 1.36-1.9V5.69c0-1.41-1.41-2.37-2.72-1.86l-2.93 1.14c-.22.08-.46.09-.69.01zM15 18.89l-6-2.11V5.11l6 2.11v11.67z" />
+    <path
+        d="M14.65 4.98l-5-1.75c-.42-.15-.88-.15-1.3-.01L4.36 4.56C3.55 4.84 3 5.6 3 6.46v11.85c0 1.41 1.41 2.37 2.72 1.86l2.93-1.14c.22-.09.47-.09.69-.01l5 1.75c.42.15.88.15 1.3.01l3.99-1.34c.81-.27 1.36-1.04 1.36-1.9V5.69c0-1.41-1.41-2.37-2.72-1.86l-2.93 1.14c-.22.08-.46.09-.69.01zM15 18.89l-6-2.11V5.11l6 2.11v11.67z" />
 </svg>
\ No newline at end of file
index b97f53224b445f7aa7e82d493dc915002c236198..adfa508b73e70137c678711472b92782138c90be 100644 (file)
   along with Privacy Cell.  If not, see <http://www.gnu.org/licenses/>. -->
 
 <svg
-  xmlns="http://www.w3.org/2000/svg"
-  viewBox="0 0 256 256" >
-
-  <!-- Inner shield. -->
-  <g transform="translate(0,160)" >
-    <path
-       style="fill:#b71c1c"
-       d="m 128,-147.2 -94.254546,41.89091 0,62.836368 c 0,58.123635 40.215273,112.477091 94.254546,125.672721 54.03928,-13.19563 94.25454,-67.549086 94.25454,-125.672721 l 0,-62.836368 z" />
-  </g>
-
-  <!-- Shield. -->
-  <g transform="translate(0,160)" >
-    <path
-      style="fill:#d32f2f"
-      d="m 128,-160 -104.727273,46.54546 0,69.818182 C 23.272727,20.945459 67.956363,81.338188 128,95.999999 188.04364,81.338188 232.72727,20.945459 232.72727,-43.636358 l 0,-69.818182 L 128,-160 Z m 0,127.883641 81.45454,0 C 203.28728,15.825464 171.28727,58.530919 128,71.912739 l 0,-103.912735 -81.454545,0 0,-66.327272 L 128,-134.51636 l 0,102.400001 z" />
-  </g>
-
-  <!-- Do not proceed. -->
-  <g transform="matrix(8.107179,0,0,8.107179,30.713852,31.529816)" >
-    <path
-      style="fill:#ffffff"
-      d="M 12,2 C 6.48,2 2,6.48 2,12 2,17.52 6.48,22 12,22 17.52,22 22,17.52 22,12 22,6.48 17.52,2 12,2 Z m 0,18 C 7.58,20 4,16.42 4,12 4,10.15 4.63,8.45 5.69,7.1 L 16.9,18.31 C 15.55,19.37 13.85,20 12,20 Z M 18.31,16.9 7.1,5.69 C 8.45,4.63 10.15,4 12,4 c 4.42,0 8,3.58 8,8 0,1.85 -0.63,3.55 -1.69,4.9 z" />
-  </g>
+    xmlns="http://www.w3.org/2000/svg"
+    viewBox="0 0 256 256" >
+
+    <!-- Inner shield. -->
+    <g transform="translate(0,160)" >
+        <path
+            style="fill:#b71c1c"
+            d="m 128,-147.2 -94.254546,41.89091 0,62.836368 c 0,58.123635 40.215273,112.477091 94.254546,125.672721 54.03928,-13.19563 94.25454,-67.549086 94.25454,-125.672721 l 0,-62.836368 z" />
+    </g>
+
+    <!-- Shield. -->
+    <g transform="translate(0,160)" >
+        <path
+            style="fill:#d32f2f"
+            d="m 128,-160 -104.727273,46.54546 0,69.818182 C 23.272727,20.945459 67.956363,81.338188 128,95.999999 188.04364,81.338188 232.72727,20.945459 232.72727,-43.636358 l 0,-69.818182 L 128,-160 Z m 0,127.883641 81.45454,0 C 203.28728,15.825464 171.28727,58.530919 128,71.912739 l 0,-103.912735 -81.454545,0 0,-66.327272 L 128,-134.51636 l 0,102.400001 z" />
+    </g>
+
+    <!-- Do not proceed. -->
+    <g transform="matrix(8.107179,0,0,8.107179,30.713852,31.529816)" >
+        <path
+            style="fill:#ffffff"
+            d="M 12,2 C 6.48,2 2,6.48 2,12 2,17.52 6.48,22 12,22 17.52,22 22,17.52 22,12 22,6.48 17.52,2 12,2 Z m 0,18 C 7.58,20 4,16.42 4,12 4,10.15 4.63,8.45 5.69,7.1 L 16.9,18.31 C 15.55,19.37 13.85,20 12,20 Z M 18.31,16.9 7.1,5.69 C 8.45,4.63 10.15,4 12,4 c 4.42,0 8,3.58 8,8 0,1.85 -0.63,3.55 -1.69,4.9 z" />
+    </g>
 </svg>
\ No newline at end of file
index d25280775f62714ec2ea9ecd5d8533e61b0c8fdd..8a9b2b67011999fb23379516b5ebc1f956020723 100644 (file)
   along with Privacy Cell.  If not, see <http://www.gnu.org/licenses/>. -->
 
 <svg
-  xmlns="http://www.w3.org/2000/svg"
-  viewBox="0 0 24 24"
-  id="icon" >
+    xmlns="http://www.w3.org/2000/svg"
+    viewBox="0 0 24 24"
+    id="icon" >
 
-  <path
-    d="M23,8v10c0,1.1-0.9,2-2,2H5c-0.55,0-1-0.45-1-1c0-0.55,0.45-1,1-1h16V8c0-0.55,0.45-1,1-1S23,7.45,23,8z M4,16 c-1.66,0-3-1.34-3-3V7c0-1.66,1.34-3,3-3h12c1.66,0,3,1.34,3,3v7c0,1.1-0.9,2-2,2H4z M7,10c0,1.66,1.34,3,3,3s3-1.34,3-3 s-1.34-3-3-3S7,8.34,7,10z" />
+    <path
+        d="M23,8v10c0,1.1-0.9,2-2,2H5c-0.55,0-1-0.45-1-1c0-0.55,0.45-1,1-1h16V8c0-0.55,0.45-1,1-1S23,7.45,23,8z M4,16 c-1.66,0-3-1.34-3-3V7c0-1.66,1.34-3,3-3h12c1.66,0,3,1.34,3,3v7c0,1.1-0.9,2-2,2H4z M7,10c0,1.66,1.34,3,3,3s3-1.34,3-3 s-1.34-3-3-3S7,8.34,7,10z" />
 </svg>
\ No newline at end of file
index 1b95ff971cb2a6d89b48c26d5ed81176dfc24588..cdf565f086545b091adf2d483abb1604c31d6c5e 100644 (file)
   along with Privacy Cell.  If not, see <http://www.gnu.org/licenses/>. -->
 
 <svg
-  xmlns="http://www.w3.org/2000/svg"
-  viewBox="0 0 24 24"
-  id="icon" >
+    xmlns="http://www.w3.org/2000/svg"
+    viewBox="0 0 24 24"
+    id="icon" >
 
-  <path
-     d="M16 1H8C6.34 1 5 2.34 5 4v16c0 1.66 1.34 3 3 3h8c1.66 0 3-1.34 3-3V4c0-1.66-1.34-3-3-3zm1 17H7V4h10v14zm-3 3h-4v-1h4v1z" />
+    <path
+        d="M16 1H8C6.34 1 5 2.34 5 4v16c0 1.66 1.34 3 3 3h8c1.66 0 3-1.34 3-3V4c0-1.66-1.34-3-3-3zm1 17H7V4h10v14zm-3 3h-4v-1h4v1z" />
 </svg>
\ No newline at end of file
index abae45e79bc69cd8371527b9351c8379a7ba6dea..84820fe9f863ccc6bc1eceb5fece08b3d459e662 100644 (file)
   along with Privacy Cell.  If not, see <http://www.gnu.org/licenses/>. -->
 
 <svg
-  xmlns="http://www.w3.org/2000/svg"
-  viewBox="0 0 20 20"
-  id="icon" >
+    xmlns="http://www.w3.org/2000/svg"
+    viewBox="0 0 20 20"
+    id="icon" >
 
-  <path
-    d="M10,13c-1.66,0-3-1.34-3-3s1.34-3,3-3s3,1.34,3,3c0,0.65-0.21,1.24-0.56,1.73l2.1,2.1C15.46,12.52,16,10.94,16,9.31V5 l-6-2L4,5v4.31c0,3.55,2.56,6.88,6,7.69c1.53-0.36,2.89-1.22,3.92-2.37l-2.19-2.19C11.24,12.79,10.65,13,10,13z" />
+    <path
+        d="M10,13c-1.66,0-3-1.34-3-3s1.34-3,3-3s3,1.34,3,3c0,0.65-0.21,1.24-0.56,1.73l2.1,2.1C15.46,12.52,16,10.94,16,9.31V5 l-6-2L4,5v4.31c0,3.55,2.56,6.88,6,7.69c1.53-0.36,2.89-1.22,3.92-2.37l-2.19-2.19C11.24,12.79,10.65,13,10,13z" />
 
-  <circle
-    cx="10"
-    cy="10"
-    r="2" />
+    <circle
+        cx="10"
+        cy="10"
+        r="2" />
 </svg>
\ No newline at end of file
index 41192322aa1151f980669a1a49c0bd6b2905a3ae..24ed58a6d0dc7cab74becf5bec669a8e0930cf45 100644 (file)
   along with Privacy Cell.  If not, see <http://www.gnu.org/licenses/>. -->
 
 <svg
-  xmlns="http://www.w3.org/2000/svg"
-  viewBox="0 0 256 256" >
-
-  <!-- Inner shield. -->
-  <g transform="translate(0,160)" >
-    <path
-      style="fill:#0d4781"
-      d="m 128,-147.2 -94.254546,41.89091 v 62.836368 c 0,58.123635 40.215273,112.477091 94.254546,125.672721 54.03928,-13.19563 94.25454,-67.549086 94.25454,-125.672721 v -62.836368 z" />
-  </g>
-
-  <!-- Shield. -->
-  <g transform="translate(0,160)" >
-    <path
-      style="fill:#1976d2"
-      d="m 128,-160 -104.727273,46.54546 v 69.818182 C 23.272727,20.945459 67.956363,81.338188 128,95.999999 188.04364,81.338188 232.72727,20.945459 232.72727,-43.636358 v -69.818182 z m 0,127.883641 h 81.45454 C 203.28728,15.825464 171.28727,58.530919 128,71.912739 V -31.999996 H 46.545455 V -98.327268 L 128,-134.51636 Z" />
-  </g>
-
-  <!-- 5G. -->
-  <g>
-    <g transform="matrix(16.218486,0,0,16.218486,-34.349857,-36.895951)" >
-
-      <!-- 5. -->
-      <path
-        style="fill:#ffffff"
-        d="M 8.5,8 H 6 v 1.5 h 2 c 0.55,0 1,0.45 1,1 V 12 c 0,0.55 -0.45,1 -1,1 H 5.5 C 5.22,13 5,12.78 5,12.5 v 0 C 5,12.22 5.22,12 5.5,12 H 8 V 10.5 H 5.5 C 5.22,10.5 5,10.28 5,10 V 7.5 C 5,7.22 5.22,7 5.5,7 h 3 C 8.78,7 9,7.22 9,7.5 v 0 C 9,7.78 8.78,8 8.5,8 Z" />
-
-      <!-- G. -->
-      <path
-        style="fill:#ffffff"
-        d="M 12.5,10.5 H 14 V 12 H 11 V 8 h 3.5 C 14.78,8 15,7.78 15,7.5 v 0 C 15,7.22 14.78,7 14.5,7 H 11 c -0.55,0 -1,0.45 -1,1 v 4 c 0,0.55 0.45,1 1,1 h 3 c 0.55,0 1,-0.45 1,-1 V 10 C 15,9.72 14.78,9.5 14.5,9.5 h -2 C 12.22,9.5 12,9.72 12,10 v 0 c 0,0.28 0.22,0.5 0.5,0.5 z" />
+    xmlns="http://www.w3.org/2000/svg"
+    viewBox="0 0 256 256" >
+
+    <!-- Inner shield. -->
+    <g transform="translate(0,160)" >
+        <path
+            style="fill:#0d4781"
+            d="m 128,-147.2 -94.254546,41.89091 v 62.836368 c 0,58.123635 40.215273,112.477091 94.254546,125.672721 54.03928,-13.19563 94.25454,-67.549086 94.25454,-125.672721 v -62.836368 z" />
+    </g>
+
+    <!-- Shield. -->
+    <g transform="translate(0,160)" >
+        <path
+            style="fill:#1976d2"
+            d="m 128,-160 -104.727273,46.54546 v 69.818182 C 23.272727,20.945459 67.956363,81.338188 128,95.999999 188.04364,81.338188 232.72727,20.945459 232.72727,-43.636358 v -69.818182 z m 0,127.883641 h 81.45454 C 203.28728,15.825464 171.28727,58.530919 128,71.912739 V -31.999996 H 46.545455 V -98.327268 L 128,-134.51636 Z" />
+    </g>
+
+    <!-- 5G. -->
+    <g>
+        <g transform="matrix(16.218486,0,0,16.218486,-34.349857,-36.895951)" >
+
+            <!-- 5. -->
+            <path
+                style="fill:#ffffff"
+                d="M 8.5,8 H 6 v 1.5 h 2 c 0.55,0 1,0.45 1,1 V 12 c 0,0.55 -0.45,1 -1,1 H 5.5 C 5.22,13 5,12.78 5,12.5 v 0 C 5,12.22 5.22,12 5.5,12 H 8 V 10.5 H 5.5 C 5.22,10.5 5,10.28 5,10 V 7.5 C 5,7.22 5.22,7 5.5,7 h 3 C 8.78,7 9,7.22 9,7.5 v 0 C 9,7.78 8.78,8 8.5,8 Z" />
+
+            <!-- G. -->
+            <path
+                style="fill:#ffffff"
+                d="M 12.5,10.5 H 14 V 12 H 11 V 8 h 3.5 C 14.78,8 15,7.78 15,7.5 v 0 C 15,7.22 14.78,7 14.5,7 H 11 c -0.55,0 -1,0.45 -1,1 v 4 c 0,0.55 0.45,1 1,1 h 3 c 0.55,0 1,-0.45 1,-1 V 10 C 15,9.72 14.78,9.5 14.5,9.5 h -2 C 12.22,9.5 12,9.72 12,10 v 0 c 0,0.28 0.22,0.5 0.5,0.5 z" />
+        </g>
     </g>
-  </g>
 </svg>
\ No newline at end of file
diff --git a/app/src/main/assets/images/save_outlined.svg b/app/src/main/assets/images/save_outlined.svg
new file mode 100644 (file)
index 0000000..d5ab83d
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+
+<!--
+  This file is a modified version of `save_outlined`, which is part of the Android Material icon set and is released under the Apache License 2.0.
+
+  Changes copyright © 2021 Soren Stoutner <soren@stoutner.com>.  The resulting file is released under the GPLv3+ license.
+
+  This file is part of Privacy Cell <https://www.stoutner.com/privacy-cell>.
+
+  Privacy Cell is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  Privacy Cell is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with Privacy Cell.  If not, see <http://www.gnu.org/licenses/>. -->
+
+<svg
+    xmlns="http://www.w3.org/2000/svg"
+    viewBox="0 0 24 24"
+    id="icon" >
+
+    <path
+        d="M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm2 16H5V5h11.17L19 7.83V19zm-7-7c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3zM6 6h9v4H6z" />
+</svg>
index 85b72e6ade9079d7add7dc3103938ed5537e1c07..e68c928cb7d69798773f18b2346dd262392f8c96 100644 (file)
   along with Privacy Cell.  If not, see <http://www.gnu.org/licenses/>. -->
 
 <svg
-  xmlns="http://www.w3.org/2000/svg"
-  viewBox="0 0 24 24"
-  id="icon" >
+    xmlns="http://www.w3.org/2000/svg"
+    viewBox="0 0 24 24"
+    id="icon" >
 
-  <path
-    d="M19.5,12c0-0.23-0.01-0.45-0.03-0.68l1.86-1.41c0.4-0.3,0.51-0.86,0.26-1.3l-1.87-3.23c-0.25-0.44-0.79-0.62-1.25-0.42 l-2.15,0.91c-0.37-0.26-0.76-0.49-1.17-0.68l-0.29-2.31C14.8,2.38,14.37,2,13.87,2h-3.73C9.63,2,9.2,2.38,9.14,2.88L8.85,5.19 c-0.41,0.19-0.8,0.42-1.17,0.68L5.53,4.96c-0.46-0.2-1-0.02-1.25,0.42L2.41,8.62c-0.25,0.44-0.14,0.99,0.26,1.3l1.86,1.41 C4.51,11.55,4.5,11.77,4.5,12s0.01,0.45,0.03,0.68l-1.86,1.41c-0.4,0.3-0.51,0.86-0.26,1.3l1.87,3.23c0.25,0.44,0.79,0.62,1.25,0.42 l2.15-0.91c0.37,0.26,0.76,0.49,1.17,0.68l0.29,2.31C9.2,21.62,9.63,22,10.13,22h3.73c0.5,0,0.93-0.38,0.99-0.88l0.29-2.31 c0.41-0.19,0.8-0.42,1.17-0.68l2.15,0.91c0.46,0.2,1,0.02,1.25-0.42l1.87-3.23c0.25-0.44,0.14-0.99-0.26-1.3l-1.86-1.41 C19.49,12.45,19.5,12.23,19.5,12z M12.04,15.5c-1.93,0-3.5-1.57-3.5-3.5s1.57-3.5,3.5-3.5s3.5,1.57,3.5,3.5S13.97,15.5,12.04,15.5z" />
+    <path
+        d="M19.5,12c0-0.23-0.01-0.45-0.03-0.68l1.86-1.41c0.4-0.3,0.51-0.86,0.26-1.3l-1.87-3.23c-0.25-0.44-0.79-0.62-1.25-0.42 l-2.15,0.91c-0.37-0.26-0.76-0.49-1.17-0.68l-0.29-2.31C14.8,2.38,14.37,2,13.87,2h-3.73C9.63,2,9.2,2.38,9.14,2.88L8.85,5.19 c-0.41,0.19-0.8,0.42-1.17,0.68L5.53,4.96c-0.46-0.2-1-0.02-1.25,0.42L2.41,8.62c-0.25,0.44-0.14,0.99,0.26,1.3l1.86,1.41 C4.51,11.55,4.5,11.77,4.5,12s0.01,0.45,0.03,0.68l-1.86,1.41c-0.4,0.3-0.51,0.86-0.26,1.3l1.87,3.23c0.25,0.44,0.79,0.62,1.25,0.42 l2.15-0.91c0.37,0.26,0.76,0.49,1.17,0.68l0.29,2.31C9.2,21.62,9.63,22,10.13,22h3.73c0.5,0,0.93-0.38,0.99-0.88l0.29-2.31 c0.41-0.19,0.8-0.42,1.17-0.68l2.15,0.91c0.46,0.2,1,0.02,1.25-0.42l1.87-3.23c0.25-0.44,0.14-0.99-0.26-1.3l-1.86-1.41 C19.49,12.45,19.5,12.23,19.5,12z M12.04,15.5c-1.93,0-3.5-1.57-3.5-3.5s1.57-3.5,3.5-3.5s3.5,1.57,3.5,3.5S13.97,15.5,12.04,15.5z" />
 </svg>
\ No newline at end of file
index ca49d3e10de9e2a3a2501c463f8c4b9ea6d7cf75..121240c46e2b4edf38e1df9b4714b60c473de105 100644 (file)
   along with Privacy Cell.  If not, see <http://www.gnu.org/licenses/>. -->
 
 <svg
-  xmlns="http://www.w3.org/2000/svg"
-  viewBox="0 0 24 24"
-  id="icon" >
+    xmlns="http://www.w3.org/2000/svg"
+    viewBox="0 0 24 24"
+    id="icon" >
 
-  <path
-    d="M14.17,5L19,9.83V19H5V5L14.17,5L14.17,5 M14.17,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V9.83 c0-0.53-0.21-1.04-0.59-1.41l-4.83-4.83C15.21,3.21,14.7,3,14.17,3L14.17,3z M7,15h10v2H7V15z M7,11h10v2H7V11z M7,7h7v2H7V7z" />
+    <path
+        d="M14.17,5L19,9.83V19H5V5L14.17,5L14.17,5 M14.17,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V9.83 c0-0.53-0.21-1.04-0.59-1.41l-4.83-4.83C15.21,3.21,14.7,3,14.17,3L14.17,3z M7,15h10v2H7V15z M7,11h10v2H7V11z M7,7h7v2H7V7z" />
 </svg>
index 3a00ff08122bdff69d17d7367ab03fb7616015d5..a16c917a9fd294ad035d59947c8c59b60c7e7f2b 100644 (file)
         <p><svg class="icon"><use href="../images/bug_report_rounded.svg#icon"/></svg> bug_report_rounded.</p>
         <p><svg class="icon"><use href="../images/call_to_action_rounded.svg#icon"/></svg> call_to_action_rounded.</p>
         <p><svg class="icon"><use href="../images/chrome_reader_mode_rounded.svg#icon"/></svg> chrome_reader_mode_rounded.</p>
+        <p><svg class="icon"><use href="../images/close_rounded.svg#icon"/></svg> close_rounded.</p>
+        <p><svg class="icon"><use href="../images/content_copy_outlined.svg#icon"/></svg> content_copy_outlined.</p>
         <p><svg class="icon"><use href="../images/fact_check_outlined.svg#icon"/></svg> fact_checked_outlined.</p>
         <p><svg class="icon"><use href="../images/format_list_bulleted_rounded.svg#icon"/></svg> format_list_bulleted_rounded.</p>
         <p><svg class="icon"><use href="../images/forum_rounded.svg#icon"/></svg> forum_rounded.</p>
         <p><svg class="icon"><use href="../images/groups_filled.svg#icon"/></svg> groups_filled.</p>
+        <p><svg class="icon"><use href="../images/list_alt_rounded.svg#icon"/></svg> list_alt_rounded.</p>
         <p><svg class="icon"><use href="../images/map_rounded.svg#icon"/></svg> map_rounded.</p>
         <p><svg class="icon"><use href="../images/payments_rounded.svg#icon"/></svg> payments_rounded.</p>
         <p><svg class="icon"><use href="../images/phone_android_outlined.svg#icon"/></svg> phone_android_outlined.</p>
         <p><svg class="icon"><use href="../images/policy_filled.svg#icon"/></svg> policy_filled.</p>
+        <p><svg class="icon"><use href="../images/save_outlined.svg#icon"/></svg> save_outlined.</p>
         <p><svg class="icon"><use href="../images/settings_rounded.svg#icon"/></svg> settings_rounded.</p>
         <p><svg class="icon"><use href="../images/text_snippet_outlined.svg#icon"/></svg> text_snippet_outlined.</p>
 
index a370ba5540bcdef1735b0d656cb9114d23724f50..c6914ce0fe0a99c78fce0e7d2efb21d90c15f76f 100644 (file)
         <p><svg class="icon"><use href="../images/bug_report_rounded.svg#icon"/></svg> bug_report_rounded.</p>
         <p><svg class="icon"><use href="../images/call_to_action_rounded.svg#icon"/></svg> call_to_action_rounded.</p>
         <p><svg class="icon"><use href="../images/chrome_reader_mode_rounded.svg#icon"/></svg> chrome_reader_mode_rounded.</p>
+        <p><svg class="icon"><use href="../images/close_rounded.svg#icon"/></svg> close_rounded.</p>
+        <p><svg class="icon"><use href="../images/content_copy_outlined.svg#icon"/></svg> content_copy_outlined.</p>
         <p><svg class="icon"><use href="../images/fact_check_outlined.svg#icon"/></svg> fact_checked_outlined.</p>
         <p><svg class="icon"><use href="../images/format_list_bulleted_rounded.svg#icon"/></svg> format_list_bulleted_rounded.</p>
         <p><svg class="icon"><use href="../images/forum_rounded.svg#icon"/></svg> forum_rounded.</p>
         <p><svg class="icon"><use href="../images/groups_filled.svg#icon"/></svg> groups_filled.</p>
+        <p><svg class="icon"><use href="../images/list_alt_rounded.svg#icon"/></svg> list_alt_rounded.</p>
         <p><svg class="icon"><use href="../images/map_rounded.svg#icon"/></svg> map_rounded.</p>
         <p><svg class="icon"><use href="../images/payments_rounded.svg#icon"/></svg> payments_rounded.</p>
         <p><svg class="icon"><use href="../images/phone_android_outlined.svg#icon"/></svg> phone_android_outlined.</p>
         <p><svg class="icon"><use href="../images/policy_filled.svg#icon"/></svg> policy_filled.</p>
+        <p><svg class="icon"><use href="../images/save_outlined.svg#icon"/></svg> save_outlined.</p>
         <p><svg class="icon"><use href="../images/settings_rounded.svg#icon"/></svg> settings_rounded.</p>
         <p><svg class="icon"><use href="../images/text_snippet_outlined.svg#icon"/></svg> text_snippet_outlined.</p>
 
diff --git a/app/src/main/java/com/stoutner/privacycell/activities/LogcatActivity.kt b/app/src/main/java/com/stoutner/privacycell/activities/LogcatActivity.kt
new file mode 100644 (file)
index 0000000..122ccc5
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ * Copyright © 2021 Soren Stoutner <soren@stoutner.com>.
+ *
+ * This file is part of Privacy Cell <https://www.stoutner.com/privacy-cell>.
+ *
+ * Privacy Cell is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Privacy Cell is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Privacy Cell.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.stoutner.privacycell.activities
+
+import android.content.ClipData
+import android.content.ClipboardManager
+import android.net.Uri
+import android.os.Bundle
+import android.provider.OpenableColumns
+import android.util.TypedValue
+import android.view.Menu
+import android.view.MenuItem
+import android.widget.ScrollView
+import android.widget.TextView
+
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.appcompat.app.AppCompatActivity
+import androidx.appcompat.widget.Toolbar
+import androidx.preference.PreferenceManager
+import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
+
+import com.google.android.material.snackbar.Snackbar
+
+import com.stoutner.privacycell.R
+
+import java.io.BufferedReader
+import java.io.IOException
+import java.io.InputStreamReader
+import java.lang.Exception
+import java.nio.charset.StandardCharsets
+
+// Define the class constants.
+private const val SCROLLVIEW_POSITION = "scrollview_position"
+
+class LogcatActivity : AppCompatActivity() {
+    // Define the class variables.
+    private var scrollViewYPositionInt = 0
+
+    // Define the class views.
+    private lateinit var swipeRefreshLayout: SwipeRefreshLayout
+    private lateinit var logcatScrollView: ScrollView
+    private lateinit var logcatTextView: TextView
+
+    // Define the save logcat activity result launcher.
+    private val saveLogcatActivityResultLauncher = registerForActivityResult(ActivityResultContracts.CreateDocument()) { fileNameUri: Uri? ->
+        // Only save the file if the URI is not null, which happens if the user exited the file picker by pressing back.
+        if (fileNameUri != null) {
+            try {
+                // Get the logcat as a string.
+                val logcatString = logcatTextView.text.toString()
+
+                // Open an output stream.
+                val outputStream = contentResolver.openOutputStream(fileNameUri)!!
+
+                // Write the logcat string to the output stream.
+                outputStream.write(logcatString.toByteArray(StandardCharsets.UTF_8))
+
+                // Close the output stream.
+                outputStream.close()
+
+                // Get a cursor from the content resolver.
+                val contentResolverCursor = contentResolver.query(fileNameUri, null, null, null)!!
+
+                // Move to the first row.
+                contentResolverCursor.moveToFirst()
+
+                // Get the file name from the cursor.
+                val fileNameString = contentResolverCursor.getString(contentResolverCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME))
+
+                // Close the cursor.
+                contentResolverCursor.close()
+
+                // Display a snackbar with the saved logcat information.
+                Snackbar.make(logcatTextView, getString(R.string.logcat_saved, fileNameString), Snackbar.LENGTH_SHORT).show()
+            } catch (exception: Exception) {
+                // Display a snackbar with the error message.
+                Snackbar.make(logcatTextView, getString(R.string.error_saving_logcat, exception.toString()), Snackbar.LENGTH_INDEFINITE).show()
+            }
+        }
+    }
+
+    public override fun onCreate(savedInstanceState: Bundle?) {
+        // Run the default commands.
+        super.onCreate(savedInstanceState)
+
+        // Get a handle for the shared preferences.
+        val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
+
+        // Get the bottom app bar preference.
+        val bottomAppBar = sharedPreferences.getBoolean(getString(R.string.bottom_app_bar_key), false)
+
+        // Set the content view.
+        if (bottomAppBar) {
+            setContentView(R.layout.logcat_bottom_appbar)
+        } else {
+            setContentView(R.layout.logcat_top_appbar)
+        }
+
+        // Get handles for the views.
+        val toolbar = findViewById<Toolbar>(R.id.toolbar)
+        swipeRefreshLayout = findViewById(R.id.swiperefreshlayout)
+        logcatScrollView = findViewById(R.id.scrollview)
+        logcatTextView = findViewById(R.id.logcat_textview)
+
+        // Set the toolbar as the action bar.
+        setSupportActionBar(toolbar)
+
+        // Get a handle for the action bar.
+        val actionBar = supportActionBar!!
+
+        // Display the back arrow in the action bar.
+        actionBar.setDisplayHomeAsUpEnabled(true)
+
+        // Implement swipe to refresh.
+        swipeRefreshLayout.setOnRefreshListener {
+            // Get the current logcat.
+            getLogcat()
+        }
+
+        // Set the swipe refresh color scheme according to the theme.
+        swipeRefreshLayout.setColorSchemeResources(R.color.blue_text)
+
+        // Initialize a color background typed value.
+        val colorBackgroundTypedValue = TypedValue()
+
+        // Get the color background from the theme.
+        theme.resolveAttribute(android.R.attr.colorBackground, colorBackgroundTypedValue, true)
+
+        // Get the color background int from the typed value.
+        val colorBackgroundInt = colorBackgroundTypedValue.data
+
+        // Set the swipe refresh background color.
+        swipeRefreshLayout.setProgressBackgroundColorSchemeColor(colorBackgroundInt)
+
+        // Check to see if the activity has been restarted.
+        if (savedInstanceState != null) {
+            // Get the saved scrollview position.
+            scrollViewYPositionInt = savedInstanceState.getInt(SCROLLVIEW_POSITION)
+        }
+
+        // Get the logcat.
+        getLogcat()
+    }
+
+    override fun onCreateOptionsMenu(menu: Menu): Boolean {
+        // Inflate the menu.  This adds items to the action bar.
+        menuInflater.inflate(R.menu.logcat_options_menu, menu)
+
+        // Display the menu.
+        return true
+    }
+
+    override fun onOptionsItemSelected(menuItem: MenuItem): Boolean {
+        // Run the commands that correlate to the selected menu item.
+        return when (menuItem.itemId) {
+            R.id.copy -> {  // Copy was selected.
+                // Get a handle for the clipboard manager.
+                val clipboardManager = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
+
+                // Save the logcat in a clip data.
+                val logcatClipData = ClipData.newPlainText(getString(R.string.logcat), logcatTextView.text)
+
+                // Place the clip data on the clipboard.
+                clipboardManager.setPrimaryClip(logcatClipData)
+
+                // Display a snackbar.
+                Snackbar.make(logcatTextView, R.string.logcat_copied, Snackbar.LENGTH_SHORT).show()
+
+                // Consume the event.
+                true
+            }
+
+            R.id.save -> {  // Save was selected.
+                // Open the file picker.
+                saveLogcatActivityResultLauncher.launch(getString(R.string.privacy_cell_logcat_txt))
+
+                // Consume the event.
+                true
+            }
+
+            R.id.clear -> {  // Clear was selected.
+                try {
+                    // Clear the logcat.  `-c` clears the logcat.  `-b all` clears all the buffers (instead of just crash, main, and system).
+                    val process = Runtime.getRuntime().exec("logcat -b all -c")
+
+                    // Wait for the process to finish.
+                    process.waitFor()
+
+                    // Reset the scroll view Y position int.
+                    scrollViewYPositionInt = 0
+
+                    // Reload the logcat.
+                    getLogcat()
+                } catch (exception: Exception) {
+                    // Do nothing.
+                }
+
+                // Consume the event.
+                true
+            }
+
+            else -> {  // The home button was pushed.
+                // Do not consume the event.  The system will process the home command.
+                super.onOptionsItemSelected(menuItem)
+            }
+        }
+    }
+
+    public override fun onSaveInstanceState(savedInstanceState: Bundle) {
+        // Run the default commands.
+        super.onSaveInstanceState(savedInstanceState)
+
+        // Get the scrollview Y position.
+        val scrollViewYPositionInt = logcatScrollView.scrollY
+
+        // Store the scrollview Y position in the bundle.
+        savedInstanceState.putInt(SCROLLVIEW_POSITION, scrollViewYPositionInt)
+    }
+
+    private fun getLogcat() {
+        try {
+            // Get the logcat.  `-b all` gets all the buffers (instead of just crash, main, and system).  `-v long` produces more complete information.  `-d` dumps the logcat and exits.
+            val getLogcatProcess = Runtime.getRuntime().exec("logcat -b all -v long -d")
+
+            // Wrap the logcat in a buffered reader.
+            val logcatBufferedReader = BufferedReader(InputStreamReader(getLogcatProcess.inputStream))
+
+            // Display the logcat.
+            logcatTextView.text = logcatBufferedReader.readText()
+
+            // Close the buffered reader.
+            logcatBufferedReader.close()
+        } catch (exception: IOException) {
+            // Do nothing.
+        }
+
+        // Update the scroll position after the text is populated.
+        logcatTextView.post {
+            // Set the scroll position.
+            logcatScrollView.scrollY = scrollViewYPositionInt
+        }
+
+        // Stop the swipe to refresh animation if it is displayed.
+        swipeRefreshLayout.isRefreshing = false
+    }
+}
\ No newline at end of file
index 091586fdf9386896a8161013ddd2825551ab1650..618ef569cd052a79ca5cb67ff85cf119675a60d5 100644 (file)
@@ -205,6 +205,14 @@ class PrivacyCellActivity : AppCompatActivity(), NavigationView.OnNavigationItem
                 startActivity(settingsIntent)
             }
 
+            R.id.logcat -> {  // Logcat.
+                // Create an intent to load the Logcat activity.
+                val logcatIntent = Intent(this, LogcatActivity::class.java)
+
+                // Make it so.
+                startActivity(logcatIntent)
+            }
+
             R.id.permissions -> {  // Permissions.
                 // Instantiate the permissions dialog fragment.
                 val permissionsDialogFragment = WebViewDialog().type(WebViewDialog.PERMISSIONS)
diff --git a/app/src/main/res/drawable/clear.xml b/app/src/main/res/drawable/clear.xml
new file mode 100644 (file)
index 0000000..35870ea
--- /dev/null
@@ -0,0 +1,13 @@
+<!-- This file comes from the Android Material icon set, where it is called `close_rounded`.  It is released under the Apache License 2.0. -->
+
+<vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="24dp"
+    android:width="24dp"
+    android:viewportHeight="24"
+    android:viewportWidth="24" >
+
+    <path
+        android:fillColor="@color/logcat_icons"
+        android:pathData="M18.3,5.71c-0.39,-0.39 -1.02,-0.39 -1.41,0L12,10.59 7.11,5.7c-0.39,-0.39 -1.02,-0.39 -1.41,0 -0.39,0.39 -0.39,1.02 0,1.41L10.59,12 5.7,16.89c-0.39,0.39 -0.39,1.02 0,1.41 0.39,0.39 1.02,0.39 1.41,0L12,13.41l4.89,4.89c0.39,0.39 1.02,0.39 1.41,0 0.39,-0.39 0.39,-1.02 0,-1.41L13.41,12l4.89,-4.89c0.38,-0.38 0.38,-1.02 0,-1.4z" />
+</vector>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/copy.xml b/app/src/main/res/drawable/copy.xml
new file mode 100644 (file)
index 0000000..f51eb87
--- /dev/null
@@ -0,0 +1,14 @@
+<!-- This file comes from the Android Material icon set, where it is called `content_copy_outlined`.  It is released under the Apache License 2.0. -->
+
+<vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="24dp"
+    android:width="24dp"
+    android:viewportHeight="24"
+    android:viewportWidth="24"
+    android:autoMirrored="true" >
+
+    <path
+        android:fillColor="@color/logcat_icons"
+        android:pathData="M16,1L4,1c-1.1,0 -2,0.9 -2,2v14h2L4,3h12L16,1zM19,5L8,5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h11c1.1,0 2,-0.9 2,-2L21,7c0,-1.1 -0.9,-2 -2,-2zM19,21L8,21L8,7h11v14z" />
+</vector>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/logcat.xml b/app/src/main/res/drawable/logcat.xml
new file mode 100644 (file)
index 0000000..1024d6a
--- /dev/null
@@ -0,0 +1,14 @@
+<!-- This file comes from the Android Material icon set, where it is called `chrome_reader_mode_rounded`.  It is released under the Apache License 2.0. -->
+
+<vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="24dp"
+    android:width="24dp"
+    android:viewportHeight="24"
+    android:viewportWidth="24"
+    android:autoMirrored="true" >
+
+    <path
+        android:fillColor="@color/icon_enabled"
+        android:pathData="M12,9h4c0.55,0 1,-0.45 1,-1s-0.45,-1 -1,-1h-4c-0.55,0 -1,0.45 -1,1s0.45,1 1,1zM12,13h4c0.55,0 1,-0.45 1,-1s-0.45,-1 -1,-1h-4c-0.55,0 -1,0.45 -1,1s0.45,1 1,1zM12,17h4c0.55,0 1,-0.45 1,-1s-0.45,-1 -1,-1h-4c-0.55,0 -1,0.45 -1,1s0.45,1 1,1zM7,7h2v2L7,9zM7,11h2v2L7,13zM7,15h2v2L7,17zM20,3L4,3c-0.55,0 -1,0.45 -1,1v16c0,0.55 0.45,1 1,1h16c0.55,0 1,-0.45 1,-1L21,4c0,-0.55 -0.45,-1 -1,-1zM19,19L5,19L5,5h14v14z" />
+</vector>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/save.xml b/app/src/main/res/drawable/save.xml
new file mode 100644 (file)
index 0000000..1705dc1
--- /dev/null
@@ -0,0 +1,13 @@
+<!-- This file comes from the Android Material icon set, where it is called `save_outlined`.  It is released under the Apache License 2.0. -->
+
+<vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="24dp"
+    android:width="24dp"
+    android:viewportHeight="24"
+    android:viewportWidth="24" >
+
+    <path
+        android:fillColor="@color/logcat_icons"
+        android:pathData="M17,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,7l-4,-4zM19,19L5,19L5,5h11.17L19,7.83L19,19zM12,12c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3zM6,6h9v4L6,10z" />
+</vector>
\ No newline at end of file
diff --git a/app/src/main/res/layout/logcat_bottom_appbar.xml b/app/src/main/res/layout/logcat_bottom_appbar.xml
new file mode 100644 (file)
index 0000000..49d9adb
--- /dev/null
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  Copyright © 2021 Soren Stoutner <soren@stoutner.com>.
+
+  This file is part of Privacy Cell <https://www.stoutner.com/privacy-cell>.
+
+  Privacy Cell is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  Privacy Cell is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with Privacy Cell.  If not, see <http://www.gnu.org/licenses/>. -->
+
+<androidx.coordinatorlayout.widget.CoordinatorLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_height="match_parent"
+    android:layout_width="match_parent" >
+
+    <!-- The linear layout with `orientation="vertical"` keeps the content above the app bar layout.  `app:layout_dodgeInsetEdges="bottom"` as a child of a coordinator layout moves the view above snackbars. -->
+    <LinearLayout
+        android:layout_height="match_parent"
+        android:layout_width="match_parent"
+        android:orientation="vertical"
+        app:layout_dodgeInsetEdges="bottom" >
+
+        <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
+            android:id="@+id/swiperefreshlayout"
+            android:layout_height="0dp"
+            android:layout_width="match_parent"
+            android:layout_weight="1" >
+
+            <ScrollView
+                android:id="@+id/scrollview"
+                android:layout_height="wrap_content"
+                android:layout_width="match_parent" >
+
+                <TextView
+                    android:id="@+id/logcat_textview"
+                    android:layout_height="wrap_content"
+                    android:layout_width="match_parent"
+                    android:layout_margin="10dp"
+                    android:textIsSelectable="true" />
+            </ScrollView>
+        </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
+
+        <!-- The app bar theme must be specified here because the activity uses a `NoActionBar` theme. -->
+        <com.google.android.material.appbar.AppBarLayout
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:background="?android:attr/colorBackground"
+            android:theme="@style/ThemeOverlay.AppCompat.DayNight.ActionBar" >
+
+            <androidx.appcompat.widget.Toolbar
+                android:id="@+id/toolbar"
+                android:layout_height="wrap_content"
+                android:layout_width="match_parent" />
+        </com.google.android.material.appbar.AppBarLayout>
+    </LinearLayout>
+</androidx.coordinatorlayout.widget.CoordinatorLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/logcat_top_appbar.xml b/app/src/main/res/layout/logcat_top_appbar.xml
new file mode 100644 (file)
index 0000000..3e3a53a
--- /dev/null
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  Copyright © 2021 Soren Stoutner <soren@stoutner.com>.
+
+  This file is part of Privacy Cell <https://www.stoutner.com/privacy-cell>.
+
+  Privacy Cell is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  Privacy Cell is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with Privacy Cell.  If not, see <http://www.gnu.org/licenses/>. -->
+
+<androidx.coordinatorlayout.widget.CoordinatorLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_height="match_parent"
+    android:layout_width="match_parent" >
+
+    <!-- The linear layout with `orientation="vertical"` moves the content below the app bar layout. -->
+    <LinearLayout
+        android:layout_height="match_parent"
+        android:layout_width="match_parent"
+        android:orientation="vertical" >
+
+        <!-- The app bar theme must be specified here because the activity uses a `NoActionBar` theme. -->
+        <com.google.android.material.appbar.AppBarLayout
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:background="?android:attr/colorBackground"
+            android:theme="@style/ThemeOverlay.AppCompat.DayNight.ActionBar" >
+
+            <androidx.appcompat.widget.Toolbar
+                android:id="@+id/toolbar"
+                android:layout_height="wrap_content"
+                android:layout_width="match_parent" />
+        </com.google.android.material.appbar.AppBarLayout>
+
+        <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
+            android:id="@+id/swiperefreshlayout"
+            android:layout_height="match_parent"
+            android:layout_width="match_parent" >
+
+            <ScrollView
+                android:id="@+id/scrollview"
+                android:layout_height="wrap_content"
+                android:layout_width="match_parent" >
+
+                <TextView
+                    android:id="@+id/logcat_textview"
+                    android:layout_height="wrap_content"
+                    android:layout_width="match_parent"
+                    android:layout_margin="10dp"
+                    android:textIsSelectable="true" />
+            </ScrollView>
+        </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
+    </LinearLayout>
+</androidx.coordinatorlayout.widget.CoordinatorLayout>
\ No newline at end of file
diff --git a/app/src/main/res/menu/logcat_options_menu.xml b/app/src/main/res/menu/logcat_options_menu.xml
new file mode 100644 (file)
index 0000000..f81aa28
--- /dev/null
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  Copyright © 2021 Soren Stoutner <soren@stoutner.com>.
+
+  This file is part of Privacy Cell <https://www.stoutner.com/privacy-cell>.
+
+  Privacy Cell is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  Privacy Cell is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with Privacy Cell.  If not, see <http://www.gnu.org/licenses/>. -->
+
+<menu
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto" >
+
+    <item
+        android:id="@+id/copy"
+        android:title="@string/copy"
+        android:orderInCategory="10"
+        android:icon="@drawable/copy"
+        app:showAsAction="always" />
+
+    <item
+        android:id="@+id/save"
+        android:title="@string/save"
+        android:orderInCategory="20"
+        android:icon="@drawable/save"
+        app:showAsAction="ifRoom" />
+
+    <item
+        android:id="@+id/clear"
+        android:title="@string/clear"
+        android:orderInCategory="30"
+        android:icon="@drawable/clear"
+        app:showAsAction="ifRoom" />
+</menu>
\ No newline at end of file
index cdbf1d880673e4f043583da6c63a796d89009594..7173dd62d379f534241434fd3ecbf2c157f3a51b 100644 (file)
 
     <!-- If a group has an id, a line is drawn above it in the navigation view. -->
     <group android:id="@+id/settings_group" >
+        <item
+            android:id="@+id/logcat"
+            android:title="@string/logcat"
+            android:icon="@drawable/logcat"
+            android:orderInCategory="110" />
+
         <item
             android:id="@+id/settings"
             android:title="@string/settings"
             android:icon="@drawable/settings"
-            android:orderInCategory="110" />
+            android:orderInCategory="120" />
     </group>
 </menu>
\ No newline at end of file
index 7b18f981e40e269550e2c413e442842d52239f31..2504912f99237e0848edee08c23a71c604f06a17 100644 (file)
         android:icon="@drawable/settings"
         android:orderInCategory="10" />
 
+    <item
+        android:id="@+id/logcat"
+        android:title="@string/logcat"
+        android:icon="@drawable/logcat"
+        android:orderInCategory="20" />
+
     <!-- If a group has an id, a line is drawn above it in the navigation view. -->
     <group android:id="@+id/dialogs" >
         <item
             android:id="@+id/permissions"
             android:title="@string/permissions"
             android:icon="@drawable/permissions"
-            android:orderInCategory="20" />
+            android:orderInCategory="30" />
 
         <item
             android:id="@+id/privacy_policy"
             android:title="@string/privacy_policy"
             android:icon="@drawable/privacy_policy"
-            android:orderInCategory="30" />
+            android:orderInCategory="40" />
 
         <item
             android:id="@+id/changelog"
             android:title="@string/changelog"
             android:icon="@drawable/changelog"
-            android:orderInCategory="40" />
+            android:orderInCategory="50" />
 
         <item
             android:id="@+id/licenses"
             android:title="@string/licenses"
             android:icon="@drawable/licenses"
-            android:orderInCategory="50" />
+            android:orderInCategory="60" />
 
         <item
             android:id="@+id/contributors"
             android:title="@string/contributors"
             android:icon="@drawable/contributors"
-            android:orderInCategory="60" />
+            android:orderInCategory="70" />
     </group>
 
     <!-- If a group has an id, a line is drawn above it in the navigation view. -->
             android:id="@+id/news"
             android:title="@string/news"
             android:icon="@drawable/news"
-            android:orderInCategory="70" />
+            android:orderInCategory="80" />
 
         <item
             android:id="@+id/roadmap"
             android:title="@string/roadmap"
             android:icon="@drawable/roadmap"
-            android:orderInCategory="80" />
+            android:orderInCategory="90" />
 
         <item
             android:id="@+id/bug_tracker"
             android:title="@string/bug_tracker"
             android:icon="@drawable/bug_tracker"
-            android:orderInCategory="90" />
+            android:orderInCategory="100" />
 
         <item
             android:id="@+id/forum"
             android:title="@string/forum"
             android:icon="@drawable/forum"
-            android:orderInCategory="100" />
+            android:orderInCategory="110" />
     </group>
 
     <!-- If a group has an id, a line is drawn above it in the navigation view. -->
@@ -91,6 +97,6 @@
             android:id="@+id/donations"
             android:title="@string/donations"
             android:icon="@drawable/donations"
-            android:orderInCategory="110" />
+            android:orderInCategory="120" />
     </group>
 </menu>
\ No newline at end of file
index 99cbee612229a309564e419cc264853844ccff69..51db8961518f0529f3ff0621d3d73feca0152282 100644 (file)
     <string name="forum">Foro</string>
     <string name="donations">Donaciones</string>
 
-    <!-- Settings. -->
-    <string name="monitoring">Monitorización</string>
-    <string name="realtime_monitoring">Monitorización en tiempo real</string>
-    <string name="realtime_monitoring_summary">Coloca un icono en la barra de estado que monitoriza la red celular.</string>
-    <string name="secure_network_notification">Notificación de red segura</string>
-    <string name="insecure_network_notification">Notificación de red insegura</string>
-    <string name="interface_title">Interfaz</string>
-    <string name="bottom_app_bar">Barra inferior de app</string>
-    <string name="bottom_app_bar_summary">Mueve la barra de aplicaciones a la parte inferior de la pantalla.  Al cambiar esta configuración se reiniciará Privacy Cell.</string>
-
     <!-- Network types. -->
     <string name="unknown">Desconocido</string>
     <string name="gprs">GPRS – 2.5G/3G</string>
     <string name="stingrays">Stingrays</string>
     <string name="close">Cerrar</string>
 
+    <!-- Settings. -->
+    <string name="monitoring">Monitorización</string>
+    <string name="realtime_monitoring">Monitorización en tiempo real</string>
+    <string name="realtime_monitoring_summary">Coloca un icono en la barra de estado que monitoriza la red celular.</string>
+    <string name="secure_network_notification">Notificación de red segura</string>
+    <string name="insecure_network_notification">Notificación de red insegura</string>
+    <string name="interface_title">Interfaz</string>
+    <string name="bottom_app_bar">Barra inferior de app</string>
+    <string name="bottom_app_bar_summary">Mueve la barra de aplicaciones a la parte inferior de la pantalla.  Al cambiar esta configuración se reiniciará Privacy Cell.</string>
+
     <!-- Notifications. -->
     <string name="secure">Seguro</string>
     <string name="insecure">Inseguro</string>
index b3d3a56d94a5f22db8825fdcbd76f87bde3b58b9..ebf3c6b1de877357c19952057f4bf2c8fa6e24d1 100644 (file)
     <string name="forum">Forum</string>
     <string name="donations">Dons</string>
 
-    <!-- Settings. -->
-    <string name="monitoring">Supervision</string>
-    <string name="realtime_monitoring">Supervision en temps-réel</string>
-    <string name="realtime_monitoring_summary">Placez une icône dans la barre d\'état qui surveille le réseau cellulaire.</string>
-    <string name="secure_network_notification">Notification de réseau sécurisé</string>
-    <string name="insecure_network_notification">Notification de réseau non sécurisé</string>
-    <string name="interface_title">Interface</string>
-    <string name="bottom_app_bar">Barre d\'apps inférieure</string>
-    <string name="bottom_app_bar_summary">Déplacer la barre d\'apps en bas de l\'écran. La modification de ce paramètre entraîne le redémarrage de Privacy Cell.</string>
-
     <!-- Network types. -->
     <string name="unknown">Inconnu</string>
     <string name="gprs">GPRS – 2.5G/3G</string>
     <string name="stingrays">IMSI-catcher</string>
     <string name="close">Fermer</string>
 
+    <!-- Settings. -->
+    <string name="monitoring">Supervision</string>
+    <string name="realtime_monitoring">Supervision en temps-réel</string>
+    <string name="realtime_monitoring_summary">Placez une icône dans la barre d\'état qui surveille le réseau cellulaire.</string>
+    <string name="secure_network_notification">Notification de réseau sécurisé</string>
+    <string name="insecure_network_notification">Notification de réseau non sécurisé</string>
+    <string name="interface_title">Interface</string>
+    <string name="bottom_app_bar">Barre d\'apps inférieure</string>
+    <string name="bottom_app_bar_summary">Déplacer la barre d\'apps en bas de l\'écran. La modification de ce paramètre entraîne le redémarrage de Privacy Cell.</string>
+
     <!-- Notifications. -->
     <string name="secure">Sécurisé</string>
     <string name="insecure">Non-sécurisé</string>
index 26c589edbc61a293df3eef3091a3eea7fd366ee5..d3bf2130a17f7d20a7c65ef154f5c450849ce5e2 100644 (file)
     <string name="forum">Forum</string>
     <string name="donations">Donazioni</string>
 
-    <!-- Settings. -->
-    <string name="monitoring">Monitoraggio</string>
-    <string name="realtime_monitoring">Monitoraggio in tempo reale</string>
-    <string name="realtime_monitoring_summary">Aggiunge un\'icona nella barra di stato che monitora la rete cellulare.</string>
-    <string name="secure_network_notification">Notifica di rete sicura</string>
-    <string name="insecure_network_notification">Notifica di rete insicura</string>
-    <string name="interface_title">Interfaccia</string>
-    <string name="bottom_app_bar">Barra dell\'app in basso</string>
-    <string name="bottom_app_bar_summary">Sposta la barra dell\'app nella parte inferiore dello schermo.  La modifica di questa impostazione provoca il riavvio di Privacy Cell.</string>
-
     <!-- Network types. -->
     <string name="unknown">Sconosciuta</string>
     <string name="gprs">GPRS – 2.5G/3G</string>
     <string name="stingrays">Stingray</string>
     <string name="close">Chiudi</string>
 
+    <!-- Settings. -->
+    <string name="monitoring">Monitoraggio</string>
+    <string name="realtime_monitoring">Monitoraggio in tempo reale</string>
+    <string name="realtime_monitoring_summary">Aggiunge un\'icona nella barra di stato che monitora la rete cellulare.</string>
+    <string name="secure_network_notification">Notifica di rete sicura</string>
+    <string name="insecure_network_notification">Notifica di rete insicura</string>
+    <string name="interface_title">Interfaccia</string>
+    <string name="bottom_app_bar">Barra dell\'app in basso</string>
+    <string name="bottom_app_bar_summary">Sposta la barra dell\'app nella parte inferiore dello schermo.  La modifica di questa impostazione provoca il riavvio di Privacy Cell.</string>
+
     <!-- Notifications. -->
     <string name="secure">Sicura</string>
     <string name="insecure">Insicura</string>
index 4566de8aafcb59572c820b568a9460b7d384bcd9..fed68ea3d57e720e6e193719a6ef67b47e3638ce 100644 (file)
     <color name="blue_text">@color/violet_500</color>
     <color name="icon_enabled">@color/violet_500</color>
     <color name="icon_disabled">@color/gray_500</color>
+    <color name="logcat_icons">@color/white</color>
     <color name="red_text">@color/salmon</color>
 
     <!-- Raw colors. -->
     <color name="black">#FF000000</color>
+
     <color name="blue_500">#FF2196F3</color>
     <color name="blue_700">#FF1976D2</color>
     <color name="blue_900">#FF0D47A1</color>
+
     <color name="gray_500">#FF9E9E9E</color>
     <color name="gray_600">#FF757575</color>
+    <color name="gray_925">#FF202020</color>
+
     <color name="red_600">#FFE53935</color>
     <color name="red_700">#FFD32F2F</color>
+
     <color name="salmon">#FFFC684E</color>
+
     <color name="soft_red">#FFC73625</color>
+
     <color name="violet_500">#FF8AB4F8</color>
+
     <color name="white">#FFFFFFFF</color>
 </resources>
\ No newline at end of file
index 3069875324a15fd3cf9cfa6bf59e3669d7a1e09d..62089e1590b33f1fb5f0dbfb8418eaa7e5eb5364 100644 (file)
     <string name="forum">Форум</string>
     <string name="donations">Пожертвования</string>
 
-    <!-- Settings. -->
-    <string name="monitoring">Мониторинг</string>
-    <string name="realtime_monitoring">Мониторинг в реальном времени</string>
-    <string name="realtime_monitoring_summary">Поместить в строку состояния значок для отслеживания сотовой сети.</string>
-    <string name="secure_network_notification">Уведомление о безопасной сети</string>
-    <string name="insecure_network_notification">Уведомление о небезопасной сети</string>
-    <string name="interface_title">Интерфейс</string>
-    <string name="bottom_app_bar">Панель приложения внизу</string>
-    <string name="bottom_app_bar_summary">Переместить панель приложения в нижнюю часть экрана. Изменение этой настройки приведет к перезапуску Privacy Cell.</string>
-
     <!-- Network types. -->
     <string name="unknown">Неизвестно</string>
     <string name="gprs">GPRS – 2.5G/3G</string>
     <string name="stingrays">Stingrays</string>
     <string name="close">Закрыть</string>
 
+    <!-- Settings. -->
+    <string name="monitoring">Мониторинг</string>
+    <string name="realtime_monitoring">Мониторинг в реальном времени</string>
+    <string name="realtime_monitoring_summary">Поместить в строку состояния значок для отслеживания сотовой сети.</string>
+    <string name="secure_network_notification">Уведомление о безопасной сети</string>
+    <string name="insecure_network_notification">Уведомление о небезопасной сети</string>
+    <string name="interface_title">Интерфейс</string>
+    <string name="bottom_app_bar">Панель приложения внизу</string>
+    <string name="bottom_app_bar_summary">Переместить панель приложения в нижнюю часть экрана. Изменение этой настройки приведет к перезапуску Privacy Cell.</string>
+
     <!-- Notifications. -->
     <string name="secure">Безопасна</string>
     <string name="insecure">Небезопасна</string>
index f49cbd0a0cf3b84512e12cfd31e6384e2157f721..584c22da5681e7a2ac38a1bb3b0a94b193b2b6cc 100644 (file)
     <color name="blue_text">@color/blue_700</color>
     <color name="icon_enabled">@color/blue_700</color>
     <color name="icon_disabled">@color/gray_600</color>
+    <color name="logcat_icons">@color/gray_925</color>
     <color name="red_text">@color/red_700</color>
 
     <!-- Raw colors. -->
     <color name="black">#FF000000</color>
+
     <color name="blue_500">#FF2196F3</color>
     <color name="blue_700">#FF1976D2</color>
     <color name="blue_900">#FF0D47A1</color>
+
     <color name="gray_500">#FF9E9E9E</color>
     <color name="gray_600">#FF757575</color>
+    <color name="gray_925">#FF202020</color>
+
     <color name="red_600">#FFE53935</color>
     <color name="red_700">#FFD32F2F</color>
+
     <color name="salmon">#FFFC684E</color>
+
     <color name="soft_red">#FFC73625</color>
+
     <color name="violet_500">#FF8AB4F8</color>
+
     <color name="white">#FFFFFFFF</color>
 </resources>
\ No newline at end of file
index d4b5d61e7324accc57b318ad963dea23b7a68f09..551e449957678b78c3664a801d59574b8a4a07de 100644 (file)
     <string name="roadmap">Roadmap</string>
     <string name="bug_tracker">Bug Tracker</string>
     <string name="forum">Forum</string>
+    <string name="logcat">Logcat</string>
     <string name="donations">Donations</string>
 
-    <!-- Settings. -->
-    <string name="monitoring">Monitoring</string>
-    <string name="realtime_monitoring">Realtime monitoring</string>
-    <string name="realtime_monitoring_summary">Place an icon in the status bar that monitors the cell network.</string>
-    <string name="secure_network_notification">Secure network notification</string>
-    <string name="insecure_network_notification">Insecure network notification</string>
-    <string name="interface_title">Interface</string>
-    <string name="bottom_app_bar">Bottom app bar</string>
-    <string name="bottom_app_bar_summary">Move the app bar to the bottom of the screen.  Changing this setting will restart Privacy Cell.</string>
-
     <!-- Network types. -->
     <string name="unknown">Unknown</string>
     <string name="gprs">GPRS – 2.5G/3G</string>
     <string name="stingrays">Stingrays</string>
     <string name="close">Close</string>
 
+    <!-- Settings. -->
+    <string name="monitoring">Monitoring</string>
+    <string name="realtime_monitoring">Realtime monitoring</string>
+    <string name="realtime_monitoring_summary">Place an icon in the status bar that monitors the cell network.</string>
+    <string name="secure_network_notification">Secure network notification</string>
+    <string name="insecure_network_notification">Insecure network notification</string>
+    <string name="interface_title">Interface</string>
+    <string name="bottom_app_bar">Bottom app bar</string>
+    <string name="bottom_app_bar_summary">Move the app bar to the bottom of the screen.  Changing this setting will restart Privacy Cell.</string>
+
+    <!-- Logcat.
+        Android removes double spaces, but extra spaces can be manually specified with the Unicode `\u0020` formatting.
+        The `%1$s` code inserts variables into the displayed text and should be preserved in translation.-->
+    <string name="copy">Copy</string>
+    <string name="save">Save</string>
+    <string name="clear">Clear</string>
+    <string name="logcat_copied">Logcat copied.</string>
+    <string name="privacy_cell_logcat_txt">Privacy Cell Logcat.txt</string>
+    <string name="logcat_saved">%1$s saved.</string>
+    <string name="error_saving_logcat">Error saving logcat: \u0020 %1$s</string>
+
     <!-- Notifications. -->
     <string name="secure">Secure</string>
     <string name="insecure">Insecure</string>