aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/ui/src/main/res
diff options
context:
space:
mode:
authorHarsh Shandilya <me@msfjarvis.dev>2020-03-09 19:06:11 +0530
committerHarsh Shandilya <me@msfjarvis.dev>2020-03-09 19:24:27 +0530
commit7d48bef70a56d4370856eedab619b1f83ac3d0d0 (patch)
tree76fd859578e499cd3a8fd2f402652530ea36a72d /ui/src/main/res
parentEnable nonnull generation for tunnel module (diff)
downloadwireguard-android-7d48bef70a56d4370856eedab619b1f83ac3d0d0.tar.xz
wireguard-android-7d48bef70a56d4370856eedab619b1f83ac3d0d0.zip
Rename app module to ui
Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
Diffstat (limited to 'ui/src/main/res')
-rw-r--r--ui/src/main/res/drawable/ic_action_add_white.xml9
-rw-r--r--ui/src/main/res/drawable/ic_action_delete.xml9
-rw-r--r--ui/src/main/res/drawable/ic_action_edit.xml9
-rw-r--r--ui/src/main/res/drawable/ic_action_edit_white.xml9
-rw-r--r--ui/src/main/res/drawable/ic_action_open_white.xml9
-rw-r--r--ui/src/main/res/drawable/ic_action_save.xml10
-rw-r--r--ui/src/main/res/drawable/ic_action_scan_qr_code_white.xml9
-rw-r--r--ui/src/main/res/drawable/ic_action_select_all.xml10
-rw-r--r--ui/src/main/res/drawable/ic_launcher_foreground.xml35
-rw-r--r--ui/src/main/res/drawable/ic_settings.xml9
-rw-r--r--ui/src/main/res/drawable/ic_tile.xml24
-rw-r--r--ui/src/main/res/drawable/list_item_background.xml12
-rw-r--r--ui/src/main/res/layout-sw600dp/main_activity.xml31
-rw-r--r--ui/src/main/res/layout/add_tunnels_bottom_sheet.xml73
-rw-r--r--ui/src/main/res/layout/app_list_dialog_fragment.xml47
-rw-r--r--ui/src/main/res/layout/app_list_item.xml61
-rw-r--r--ui/src/main/res/layout/config_naming_dialog_fragment.xml33
-rw-r--r--ui/src/main/res/layout/main_activity.xml16
-rw-r--r--ui/src/main/res/layout/tunnel_detail_fragment.xml139
-rw-r--r--ui/src/main/res/layout/tunnel_detail_peer.xml112
-rw-r--r--ui/src/main/res/layout/tunnel_editor_fragment.xml254
-rw-r--r--ui/src/main/res/layout/tunnel_editor_peer.xml161
-rw-r--r--ui/src/main/res/layout/tunnel_list_fragment.xml78
-rw-r--r--ui/src/main/res/layout/tunnel_list_item.xml62
-rw-r--r--ui/src/main/res/menu/config_editor.xml10
-rw-r--r--ui/src/main/res/menu/main_activity.xml11
-rw-r--r--ui/src/main/res/menu/tunnel_detail.xml10
-rw-r--r--ui/src/main/res/menu/tunnel_list_action_mode.xml16
-rw-r--r--ui/src/main/res/mipmap-anydpi-v26/ic_launcher.xml5
-rw-r--r--ui/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml5
-rw-r--r--ui/src/main/res/mipmap-hdpi/ic_launcher.pngbin0 -> 6688 bytes
-rw-r--r--ui/src/main/res/mipmap-hdpi/ic_launcher_round.pngbin0 -> 7525 bytes
-rw-r--r--ui/src/main/res/mipmap-mdpi/ic_launcher.pngbin0 -> 3594 bytes
-rw-r--r--ui/src/main/res/mipmap-mdpi/ic_launcher_round.pngbin0 -> 4050 bytes
-rw-r--r--ui/src/main/res/mipmap-xhdpi/ic_launcher.pngbin0 -> 8904 bytes
-rw-r--r--ui/src/main/res/mipmap-xhdpi/ic_launcher_round.pngbin0 -> 10484 bytes
-rw-r--r--ui/src/main/res/mipmap-xxhdpi/ic_launcher.pngbin0 -> 16217 bytes
-rw-r--r--ui/src/main/res/mipmap-xxhdpi/ic_launcher_round.pngbin0 -> 19531 bytes
-rw-r--r--ui/src/main/res/mipmap-xxxhdpi/ic_launcher.pngbin0 -> 22885 bytes
-rw-r--r--ui/src/main/res/mipmap-xxxhdpi/ic_launcher_round.pngbin0 -> 27146 bytes
-rw-r--r--ui/src/main/res/values-hi/strings.xml179
-rw-r--r--ui/src/main/res/values-it/strings.xml179
-rw-r--r--ui/src/main/res/values-ja/strings.xml173
-rw-r--r--ui/src/main/res/values-night/bools.xml5
-rw-r--r--ui/src/main/res/values-night/colors.xml17
-rw-r--r--ui/src/main/res/values-ru/strings.xml179
-rw-r--r--ui/src/main/res/values-v27/styles.xml28
-rw-r--r--ui/src/main/res/values-zh-rCN/strings.xml173
-rw-r--r--ui/src/main/res/values/attrs.xml11
-rw-r--r--ui/src/main/res/values/bools.xml5
-rw-r--r--ui/src/main/res/values/colors.xml21
-rw-r--r--ui/src/main/res/values/dimens.xml9
-rw-r--r--ui/src/main/res/values/ic_launcher_background.xml4
-rw-r--r--ui/src/main/res/values/ids.xml4
-rw-r--r--ui/src/main/res/values/strings.xml179
-rw-r--r--ui/src/main/res/values/styles.xml56
-rw-r--r--ui/src/main/res/xml/preferences.xml19
57 files changed, 2519 insertions, 0 deletions
diff --git a/ui/src/main/res/drawable/ic_action_add_white.xml b/ui/src/main/res/drawable/ic_action_add_white.xml
new file mode 100644
index 0000000..cbb4c4e
--- /dev/null
+++ b/ui/src/main/res/drawable/ic_action_add_white.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
+ <path
+ android:fillColor="?attr/colorOnSecondary"
+ android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" />
+</vector>
diff --git a/ui/src/main/res/drawable/ic_action_delete.xml b/ui/src/main/res/drawable/ic_action_delete.xml
new file mode 100644
index 0000000..d4ebd61
--- /dev/null
+++ b/ui/src/main/res/drawable/ic_action_delete.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24">
+ <path
+ android:fillColor="?attr/colorOnPrimary"
+ android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z" />
+</vector>
diff --git a/ui/src/main/res/drawable/ic_action_edit.xml b/ui/src/main/res/drawable/ic_action_edit.xml
new file mode 100644
index 0000000..fc42d2e
--- /dev/null
+++ b/ui/src/main/res/drawable/ic_action_edit.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24">
+ <path
+ android:fillColor="?attr/colorOnPrimary"
+ android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z" />
+</vector>
diff --git a/ui/src/main/res/drawable/ic_action_edit_white.xml b/ui/src/main/res/drawable/ic_action_edit_white.xml
new file mode 100644
index 0000000..fa95f54
--- /dev/null
+++ b/ui/src/main/res/drawable/ic_action_edit_white.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24">
+ <path
+ android:fillColor="?attr/colorOnSecondary"
+ android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z" />
+</vector>
diff --git a/ui/src/main/res/drawable/ic_action_open_white.xml b/ui/src/main/res/drawable/ic_action_open_white.xml
new file mode 100644
index 0000000..01b2815
--- /dev/null
+++ b/ui/src/main/res/drawable/ic_action_open_white.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24">
+ <path
+ android:fillColor="?attr/colorOnSecondary"
+ android:pathData="M6,2c-1.1,0 -1.99,0.9 -1.99,2L4,20c0,1.1 0.89,2 1.99,2L18,22c1.1,0 2,-0.9 2,-2L20,8l-6,-6L6,2zM13,9L13,3.5L18.5,9L13,9z" />
+</vector>
diff --git a/ui/src/main/res/drawable/ic_action_save.xml b/ui/src/main/res/drawable/ic_action_save.xml
new file mode 100644
index 0000000..528bd99
--- /dev/null
+++ b/ui/src/main/res/drawable/ic_action_save.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24">
+ <path
+ android:fillColor="?attr/colorOnPrimary"
+ 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,-4zM12,19c-1.66,0 -3,-1.34 -3,-3s1.34,-3 3,-3 3,1.34 3,3 -1.34,3 -3,3zM15,9L5,9L5,5h10v4z" />
+</vector>
diff --git a/ui/src/main/res/drawable/ic_action_scan_qr_code_white.xml b/ui/src/main/res/drawable/ic_action_scan_qr_code_white.xml
new file mode 100644
index 0000000..2383d03
--- /dev/null
+++ b/ui/src/main/res/drawable/ic_action_scan_qr_code_white.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24">
+ <path
+ android:fillColor="?attr/colorOnSecondary"
+ android:pathData="M4,4H10V10H4V4M20,4V10H14V4H20M14,15H16V13H14V11H16V13H18V11H20V13H18V15H20V18H18V20H16V18H13V20H11V16H14V15M16,15V18H18V15H16M4,20V14H10V20H4M6,6V8H8V6H6M16,6V8H18V6H16M6,16V18H8V16H6M4,11H6V13H4V11M9,11H13V15H11V13H9V11M11,6H13V10H11V6M2,2V6H0V2A2,2 0 0,1 2,0H6V2H2M22,0A2,2 0 0,1 24,2V6H22V2H18V0H22M2,18V22H6V24H2A2,2 0 0,1 0,22V18H2M22,22V18H24V22A2,2 0 0,1 22,24H18V22H22Z" />
+</vector> \ No newline at end of file
diff --git a/ui/src/main/res/drawable/ic_action_select_all.xml b/ui/src/main/res/drawable/ic_action_select_all.xml
new file mode 100644
index 0000000..2883742
--- /dev/null
+++ b/ui/src/main/res/drawable/ic_action_select_all.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24">
+ <path
+ android:fillColor="?attr/colorOnPrimary"
+ android:pathData="M3 5L5 5 5 3C3.9 3 3 3.9 3 5Zm0 8l2 0 0 -2 -2 0 0 2zm4 8l2 0 0 -2 -2 0 0 2zM3 9L5 9 5 7 3 7 3 9Zm10 -6l-2 0 0 2 2 0 0 -2zm6 0l0 2 2 0C21 3.9 20.1 3 19 3ZM5 21L5 19 3 19c0 1.1 0.9 2 2 2zm-2 -4l2 0 0 -2 -2 0 0 2zM9 3L7 3 7 5 9 5 9 3Zm2 18l2 0 0 -2 -2 0 0 2zm8 -8l2 0 0 -2 -2 0 0 2zm0 8c1.1 0 2 -0.9 2 -2l-2 0 0 2zm0 -12l2 0 0 -2 -2 0 0 2zm0 8l2 0 0 -2 -2 0 0 2zm-4 4l2 0 0 -2 -2 0 0 2zm0 -16l2 0 0 -2 -2 0 0 2zM7 17L17 17 17 7 7 7 7 17Zm2 -8l6 0 0 6 -6 0 0 -6z" />
+</vector>
diff --git a/ui/src/main/res/drawable/ic_launcher_foreground.xml b/ui/src/main/res/drawable/ic_launcher_foreground.xml
new file mode 100644
index 0000000..f9713f3
--- /dev/null
+++ b/ui/src/main/res/drawable/ic_launcher_foreground.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="108dp"
+ android:height="108dp"
+ android:viewportHeight="2160"
+ android:viewportWidth="2160">
+ <group
+ android:scaleX="1"
+ android:scaleY="-1"
+ android:translateX="630"
+ android:translateY="1750">
+ <group>
+ <clip-path android:pathData="M0 1347.452l773.449 0L773.449 0 0 0Z" />
+ <group
+ android:translateX="349.0264"
+ android:translateY="572.616">
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M0 0c-12.169 -6.44 -21.541 -11.184 -30.71 -16.292 -37.523 -20.902 -69.603 -48.262 -95.162 -82.767 -8.264 -11.156 -13.945 -12.055 -26.528 -4.36 -163.692 100.101 -174.212 351.318 4.549 460.681 139.045 85.064 316.68 33.074 383.242 -94.85 12.614 -24.244 14.218 -61.567 6.228 -87 -27.582 -87.807 -92.71 -137.049 -182.1 -157.968 26.353 22.561 47.329 48.145 54.006 83.494 6.725 35.606 -0.388 67.807 -21.041 97.072 -31.371 44.451 -92.029 62.74 -142.721 43.492 -55.035 -20.896 -85.181 -71.123 -79.747 -132.863C-124.935 51.288 -81.419 14.12 0 0" />
+ </group>
+ <group android:translateY="285.9856">
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M0 0C13.148 88.712 117.033 170.407 204.881 161.087 177.673 124.291 165.104 82.664 162.071 41.145 132.88 35.769 105.368 32.152 78.66 25.373 52.364 18.698 26.882 8.816 0 0" />
+ </group>
+ <group
+ android:translateX="580.2814"
+ android:translateY="1243.915">
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M0 0C4.917 3.762 9.98 6.922 16.085 1.891 19.557 -0.97 22.93 -3.933 27.136 -7.523 21.915 -10.28 17.676 -12.599 13.355 -14.779 7.307 -17.83 2.785 -15.792 -0.877 -10.972 -3.847 -7.062 -4.384 -3.354 0 0m71.552 -730.934c-7.403 6.401 -12.094 6.399 -20.775 0.845 -29.454 -18.844 -59.602 -36.696 -90.239 -53.556 -17.562 -9.664 -36.584 -16.675 -58.61 -26.516 7.564 -1.952 11.203 -2.865 14.829 -3.83 82.337 -21.913 126.326 -94.196 106.841 -175.157 -17.329 -71.999 -90.422 -118.033 -161.255 -105.889 -59.053 10.125 -110.601 59.161 -119.21 117.917 -9.382 64.032 22.508 125.618 79.246 151.417 31.472 14.31 63.79 26.766 95.186 41.229 35.697 16.445 74.29 29.435 105.458 52.322 77.355 56.801 125.124 135.006 143.747 229.401 11.155 56.543 10.401 112.837 -15.467 166.524 -19.851 41.202 -52.429 71.133 -87.429 98.447 -36.018 28.108 -74.148 53.518 -110.002 81.821 -9.702 7.659 -16.252 20.865 -20.742 32.84 -1.903 5.075 4.287 18.838 8.426 19.581 21.985 3.946 44.45 5.978 66.818 6.823 25.82 0.974 51.713 0.148 77.571 -0.192 5.606 -0.073 13.217 0.653 16.439 -2.514 13.394 -13.167 23.897 -4.697 33.194 3.965 7.823 7.29 13.399 16.992 19.62 25.168 -3.775 0.555 -11.519 2.505 -19.304 2.689 -26.003 0.616 -52.035 0.221 -78.021 1.176 -4.63 0.17 -9.09 4.935 -13.629 7.579 4.776 1.898 9.537 5.399 14.33 5.444 44.849 0.421 89.703 0.25 134.594 0.25 0.052 23.336 -31.136 55.291 -58.846 63.95 -0.207 -3.158 -0.4 -6.097 -0.606 -9.233C106.184 0.913 79.16 1.426 54.61 14.481 48.141 17.921 43.912 25.57 38.647 31.279 32.019 38.467 26.58 47.709 18.5 52.399 1.934 62.014 -16.148 68.982 -33.431 77.4c-61.418 29.914 -126.278 28.862 -195.946 22.484 41.644 -9.693 79.255 -18.447 116.865 -27.202 -0.428 -2.286 -0.856 -4.573 -1.284 -6.86 -50.308 -6.74 -97.898 11.71 -147.101 18.545 17.831 -10.443 35.897 -20.152 54.561 -28.527 18.965 -8.51 38.52 -15.705 58.076 -23.58 -24.845 -21.229 -49.776 -25.887 -81.008 -18.751 -17.072 3.901 -35.132 5.972 -52.564 5.121 -18.006 -0.88 -36.141 -5.311 -52.491 -16.238 17.507 -8.875 33.643 -16.24 48.864 -25.165 6.277 -3.681 13.473 -9.93 15.223 -16.377 4.191 -15.44 5.402 -31.689 7.817 -47.623 -28.667 -3.247 -79.074 -32.4 -89.261 -51.373 44.059 -8.478 92.031 1.777 134.06 -26.617 -13.844 -10.477 -46.085 -23.507 -57.911 -32.457 14.621 -3.831 48.498 -1.955 61.751 -1.057 11.157 0.756 16.306 1.029 20.881 -2.735l129.701 -101.541c13.638 -10.994 68.719 -63.131 83.098 -95.903 12.241 -27.902 13.739 -51.638 13.736 -57.431 -0.01 -15.541 -1.917 -39.876 -12.605 -67.022 -4.488 -11.399 -17.658 -36.65 -44.826 -66.083 -42.107 -45.617 -96.27 -70.274 -155.501 -82.487 -137.722 -28.395 -252.153 -175.469 -219.85 -337.61 37.714 -189.296 246.646 -291.784 417.386 -201.739 110.359 58.201 168.871 171.751 153.193 295.356 -9.471 74.672 -43.252 135.578 -99.881 184.538" />
+ </group>
+ </group>
+ </group>
+</vector> \ No newline at end of file
diff --git a/ui/src/main/res/drawable/ic_settings.xml b/ui/src/main/res/drawable/ic_settings.xml
new file mode 100644
index 0000000..aabfce2
--- /dev/null
+++ b/ui/src/main/res/drawable/ic_settings.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24">
+ <path
+ android:fillColor="?android:attr/colorForeground"
+ android:pathData="M12,8c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM12,16c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z" />
+</vector>
diff --git a/ui/src/main/res/drawable/ic_tile.xml b/ui/src/main/res/drawable/ic_tile.xml
new file mode 100644
index 0000000..eaf784c
--- /dev/null
+++ b/ui/src/main/res/drawable/ic_tile.xml
@@ -0,0 +1,24 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="400dp"
+ android:height="400dp"
+ android:viewportHeight="400.0"
+ android:viewportWidth="400.0">
+ <path
+ android:fillAlpha="1"
+ android:fillColor="#ffffff"
+ android:pathData="m197.7,0c-6.2,0.1 -12.5,0.5 -19,1.1 12.4,2.9 23.5,5.5 34.7,8.1 -0.1,0.7 -0.3,1.4 -0.4,2 -14.9,2 -29.1,-3.5 -43.7,-5.5 5.3,3.1 10.7,6 16.2,8.5 5.6,2.5 11.4,4.7 17.2,7 -7.4,6.3 -14.8,7.7 -24,5.6 -5.1,-1.2 -10.4,-1.8 -15.6,-1.5 -5.3,0.3 -10.7,1.6 -15.6,4.8 5.2,2.6 10,4.8 14.5,7.5 1.9,1.1 4,2.9 4.5,4.9 1.2,4.6 1.6,9.4 2.3,14.1 -8.5,1 -23.5,9.6 -26.5,15.3 13.1,2.5 27.3,-0.5 39.8,7.9 -4.1,3.1 -13.7,7 -17.2,9.6 4.3,1.1 14.4,0.6 18.3,0.3 3.3,-0.2 4.8,-0.3 6.2,0.8l38.5,30.1c4,3.3 20.4,18.7 24.7,28.5 3.6,8.3 4.1,15.3 4.1,17.1 -0,4.6 -0.6,11.8 -3.7,19.9 -1.3,3.4 -5.2,10.9 -13.3,19.6 -12.5,13.5 -28.6,20.9 -46.2,24.5 -40.9,8.4 -74.9,52.1 -65.3,100.2 11.2,56.2 73.2,86.6 123.9,59.9 32.8,-17.3 50.1,-51 45.5,-87.7 -2.8,-22.2 -12.8,-40.2 -29.7,-54.8 -2.2,-1.9 -3.6,-1.9 -6.2,-0.3 -8.7,5.6 -17.7,10.9 -26.8,15.9 -5.2,2.9 -10.9,5 -17.4,7.9 2.2,0.6 3.3,0.9 4.4,1.1 24.4,6.5 37.5,28 31.7,52 -5.1,21.4 -26.8,35 -47.9,31.4 -17.5,-3 -32.8,-17.6 -35.4,-35 -2.8,-19 6.7,-37.3 23.5,-44.9 9.3,-4.2 18.9,-7.9 28.3,-12.2 10.6,-4.9 22.1,-8.7 31.3,-15.5 23,-16.9 37.1,-40.1 42.7,-68.1 3.3,-16.8 3.1,-33.5 -4.6,-49.4 -5.9,-12.2 -15.6,-21.1 -26,-29.2 -10.7,-8.3 -22,-15.9 -32.7,-24.3 -2.9,-2.3 -4.8,-6.2 -6.2,-9.7 -0.6,-1.5 1.3,-5.6 2.5,-5.8 6.5,-1.2 13.2,-1.8 19.8,-2 7.7,-0.3 15.4,-0 23,0.1 1.7,0 3.9,-0.2 4.9,0.7 4,3.9 7.1,1.4 9.9,-1.2 2.3,-2.2 4,-5 5.8,-7.5 -1.1,-0.2 -3.4,-0.7 -5.7,-0.8 -7.7,-0.2 -15.4,-0.1 -23.2,-0.3 -1.4,-0.1 -2.7,-1.5 -4,-2.2 1.4,-0.6 2.8,-1.6 4.3,-1.6 13.3,-0.1 26.6,-0.1 40,-0.1 0,-6.9 -9.2,-16.4 -17.5,-19 -0.1,0.9 -0.1,1.8 -0.2,2.7 -8.2,0.2 -16.2,0 -23.5,-3.8 -1.9,-1 -3.2,-3.3 -4.7,-5 -2,-2.1 -3.6,-4.9 -6,-6.3 -4.9,-2.9 -10.3,-4.9 -15.4,-7.4C224.3,1.7 211.3,-0.1 197.7,0ZM249.6,29.4c0.6,-0 1.2,0.2 1.9,0.8 1,0.8 2,1.7 3.3,2.8 -1.5,0.8 -2.8,1.5 -4.1,2.2 -1.8,0.9 -3.1,0.3 -4.2,-1.1 -0.9,-1.2 -1,-2.3 0.3,-3.3 0.9,-0.7 1.8,-1.3 2.9,-1.3z"
+ android:strokeColor="#00000000"
+ android:strokeWidth="1.33333325" />
+ <path
+ android:fillAlpha="1"
+ android:fillColor="#ffffff"
+ android:pathData="m97.9,307.6c-7.8,2 -15.4,4.9 -23.4,7.5 3.9,-26.3 34.7,-50.6 60.8,-47.8 -8.1,10.9 -11.8,23.3 -12.7,35.6 -8.7,1.6 -16.8,2.7 -24.8,4.7"
+ android:strokeColor="#00000000"
+ android:strokeWidth="1.33333325" />
+ <path
+ android:fillAlpha="1"
+ android:fillColor="#ffffff"
+ android:pathData="m134.3,124c41.3,-25.3 94,-9.8 113.8,28.2 3.7,7.2 4.2,18.3 1.8,25.8 -8.2,26.1 -27.5,40.7 -54.1,46.9 7.8,-6.7 14.1,-14.3 16,-24.8 2,-10.6 -0.1,-20.1 -6.2,-28.8 -9.3,-13.2 -27.3,-18.6 -42.4,-12.9 -16.3,6.2 -25.3,21.1 -23.7,39.4 1.5,17 14.4,28.1 38.6,32.2 -3.6,1.9 -6.4,3.3 -9.1,4.8 -11.1,6.2 -20.7,14.3 -28.2,24.6 -2.5,3.3 -4.1,3.6 -7.9,1.3 -48.6,-29.7 -51.7,-104.3 1.4,-136.8"
+ android:strokeColor="#00000000"
+ android:strokeWidth="1.33333325" />
+</vector>
diff --git a/ui/src/main/res/drawable/list_item_background.xml b/ui/src/main/res/drawable/list_item_background.xml
new file mode 100644
index 0000000..f967f70
--- /dev/null
+++ b/ui/src/main/res/drawable/list_item_background.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+ <item>
+ <selector>
+ <item app:state_multiselected="true" android:state_activated="true">
+ <color android:color="?attr/colorMultiselectActiveBackground" />
+ </item>
+ </selector>
+ </item>
+ <item android:drawable="?attr/selectableItemBackground" />
+</layer-list>
diff --git a/ui/src/main/res/layout-sw600dp/main_activity.xml b/ui/src/main/res/layout-sw600dp/main_activity.xml
new file mode 100644
index 0000000..5104df9
--- /dev/null
+++ b/ui/src/main/res/layout-sw600dp/main_activity.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context=".activity.MainActivity">
+ <LinearLayout
+ android:id="@+id/master_detail_wrapper"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:baselineAligned="false"
+ android:divider="?attr/dividerHorizontal"
+ android:orientation="horizontal"
+ android:showDividers="middle">
+
+ <androidx.fragment.app.FragmentContainerView
+ android:id="@+id/list_fragment"
+ android:name="com.wireguard.android.fragment.TunnelListFragment"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="2"
+ android:tag="LIST" />
+
+ <androidx.fragment.app.FragmentContainerView
+ android:id="@+id/detail_container"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="3" />
+ </LinearLayout>
+
+</androidx.coordinatorlayout.widget.CoordinatorLayout>
diff --git a/ui/src/main/res/layout/add_tunnels_bottom_sheet.xml b/ui/src/main/res/layout/add_tunnels_bottom_sheet.xml
new file mode 100644
index 0000000..62f168b
--- /dev/null
+++ b/ui/src/main/res/layout/add_tunnels_bottom_sheet.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/root"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="@dimen/bottom_sheet_top_padding">
+
+ <com.google.android.material.button.MaterialButton
+ android:id="@+id/create_empty"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/bottom_sheet_item_height"
+ android:layout_marginLeft="@dimen/normal_margin"
+ android:layout_marginRight="@dimen/normal_margin"
+ android:layout_marginStart="@dimen/normal_margin"
+ android:layout_marginEnd="@dimen/normal_margin"
+ android:text="@string/create_empty"
+ android:textAlignment="viewStart"
+ android:textColor="?attr/colorOnSurface"
+ app:icon="@drawable/ic_action_edit"
+ app:iconPadding="@dimen/bottom_sheet_icon_padding"
+ app:iconTint="?attr/colorSecondary"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintBottom_toTopOf="@+id/create_from_file"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:rippleColor="?attr/colorSecondary"
+ style="@style/Widget.MaterialComponents.Button.TextButton.Icon"/>
+
+ <com.google.android.material.button.MaterialButton
+ android:id="@+id/create_from_file"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/bottom_sheet_item_height"
+ android:layout_marginLeft="@dimen/normal_margin"
+ android:layout_marginRight="@dimen/normal_margin"
+ android:layout_marginStart="@dimen/normal_margin"
+ android:layout_marginEnd="@dimen/normal_margin"
+ android:text="@string/create_from_file"
+ android:textAlignment="viewStart"
+ android:textColor="?attr/colorOnSurface"
+ app:icon="@drawable/ic_action_open_white"
+ app:iconPadding="@dimen/bottom_sheet_icon_padding"
+ app:iconTint="?attr/colorSecondary"
+ app:layout_constraintTop_toBottomOf="@+id/create_empty"
+ app:layout_constraintBottom_toTopOf="@+id/create_from_qrcode"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:rippleColor="?attr/colorSecondary"
+ style="@style/Widget.MaterialComponents.Button.TextButton.Icon"/>
+
+ <com.google.android.material.button.MaterialButton
+ android:id="@+id/create_from_qrcode"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/bottom_sheet_item_height"
+ android:layout_marginLeft="@dimen/normal_margin"
+ android:layout_marginRight="@dimen/normal_margin"
+ android:layout_marginStart="@dimen/normal_margin"
+ android:layout_marginEnd="@dimen/normal_margin"
+ android:text="@string/create_from_qr_code"
+ android:textAlignment="viewStart"
+ android:textColor="?attr/colorOnSurface"
+ app:icon="@drawable/ic_action_scan_qr_code_white"
+ app:iconPadding="@dimen/bottom_sheet_icon_padding"
+ app:iconTint="?attr/colorSecondary"
+ app:layout_constraintTop_toBottomOf="@+id/create_from_file"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:rippleColor="?attr/colorSecondary"
+ style="@style/Widget.MaterialComponents.Button.TextButton.Icon"/>
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/ui/src/main/res/layout/app_list_dialog_fragment.xml b/ui/src/main/res/layout/app_list_dialog_fragment.xml
new file mode 100644
index 0000000..c91161e
--- /dev/null
+++ b/ui/src/main/res/layout/app_list_dialog_fragment.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools">
+
+ <data>
+
+ <import type="android.view.View" />
+
+ <import type="com.wireguard.android.model.ApplicationData" />
+
+ <variable
+ name="fragment"
+ type="com.wireguard.android.fragment.AppListDialogFragment" />
+
+ <variable
+ name="appData"
+ type="com.wireguard.android.util.ObservableKeyedList&lt;String, ApplicationData&gt;" />
+ </data>
+
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:minHeight="200dp">
+
+ <ProgressBar
+ android:id="@+id/progress_bar"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:indeterminate="true"
+ android:visibility="@{appData.isEmpty() ? View.VISIBLE : View.GONE}"
+ tools:visibility="gone" />
+
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/app_list"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ app:items="@{appData}"
+ app:layout="@{@layout/app_list_item}"
+ tools:itemCount="10"
+ tools:listitem="@layout/app_list_item" />
+
+ </FrameLayout>
+
+
+</layout>
diff --git a/ui/src/main/res/layout/app_list_item.xml b/ui/src/main/res/layout/app_list_item.xml
new file mode 100644
index 0000000..1e81751
--- /dev/null
+++ b/ui/src/main/res/layout/app_list_item.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools">
+
+ <data>
+
+ <import type="com.wireguard.android.model.ApplicationData" />
+
+ <variable
+ name="collection"
+ type="com.wireguard.android.util.ObservableKeyedList&lt;String, com.wireguard.android.model.ApplicationData&gt;" />
+
+ <variable
+ name="key"
+ type="String" />
+
+ <variable
+ name="item"
+ type="com.wireguard.android.model.ApplicationData" />
+ </data>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="@drawable/list_item_background"
+ android:gravity="center_vertical"
+ android:onClick="@{(view) -> item.setExcludedFromTunnel(!item.excludedFromTunnel)}"
+ android:orientation="horizontal"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp">
+
+ <ImageView
+ android:id="@+id/app_icon"
+ android:layout_width="32dp"
+ android:layout_height="32dp"
+ android:layout_marginStart="16dp"
+ android:src="@{item.icon}"
+ tools:src="@tools:sample/avatars" />
+
+ <TextView
+ android:id="@+id/app_name"
+ style="?android:attr/textAppearanceMedium"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:ellipsize="end"
+ android:maxLines="1"
+ android:layout_marginStart="16dp"
+ android:layout_marginEnd="16dp"
+ android:text="@{key}"
+ tools:text="@tools:sample/full_names" />
+
+ <CheckBox
+ android:id="@+id/excluded_checkbox"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:checked="@={item.excludedFromTunnel}"
+ tools:checked="true" />
+
+ </LinearLayout>
+</layout>
diff --git a/ui/src/main/res/layout/config_naming_dialog_fragment.xml b/ui/src/main/res/layout/config_naming_dialog_fragment.xml
new file mode 100644
index 0000000..a701780
--- /dev/null
+++ b/ui/src/main/res/layout/config_naming_dialog_fragment.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+
+ <data>
+
+ <import type="com.wireguard.android.widget.NameInputFilter" />
+ </data>
+
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:padding="16dp">
+
+ <com.google.android.material.textfield.TextInputLayout
+ android:id="@+id/tunnel_name_text_layout"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <EditText
+ android:id="@+id/tunnel_name_text"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:hint="@string/tunnel_name"
+ android:inputType="textNoSuggestions|textVisiblePassword"
+ app:filter="@{NameInputFilter.newInstance()}" />
+
+ </com.google.android.material.textfield.TextInputLayout>
+
+ </FrameLayout>
+
+
+</layout>
diff --git a/ui/src/main/res/layout/main_activity.xml b/ui/src/main/res/layout/main_activity.xml
new file mode 100644
index 0000000..cf892e4
--- /dev/null
+++ b/ui/src/main/res/layout/main_activity.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/master_detail_wrapper"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context=".activity.MainActivity"
+ android:fitsSystemWindows="true">
+
+ <androidx.fragment.app.FragmentContainerView
+ android:id="@+id/detail_container"
+ android:name="com.wireguard.android.fragment.TunnelListFragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:tag="LIST"/>
+</androidx.coordinatorlayout.widget.CoordinatorLayout>
diff --git a/ui/src/main/res/layout/tunnel_detail_fragment.xml b/ui/src/main/res/layout/tunnel_detail_fragment.xml
new file mode 100644
index 0000000..463f8b8
--- /dev/null
+++ b/ui/src/main/res/layout/tunnel_detail_fragment.xml
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools">
+
+ <data>
+
+ <import type="com.wireguard.android.backend.Tunnel.State" />
+
+ <import type="com.wireguard.android.util.ClipboardUtils" />
+
+ <variable
+ name="fragment"
+ type="com.wireguard.android.fragment.TunnelDetailFragment" />
+
+ <variable
+ name="tunnel"
+ type="com.wireguard.android.model.ObservableTunnel" />
+
+ <variable
+ name="config"
+ type="com.wireguard.config.Config" />
+ </data>
+
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="?attr/colorBackground">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <androidx.cardview.widget.CardView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="4dp"
+ android:layout_marginEnd="8dp"
+ android:layout_marginStart="8dp"
+ android:layout_marginTop="8dp"
+ android:background="?attr/colorBackground"
+ app:cardCornerRadius="4dp"
+ app:cardElevation="2dp"
+ app:contentPadding="8dp">
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:id="@+id/interface_title"
+ style="?android:attr/textAppearanceMedium"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentStart="true"
+ android:layout_alignParentTop="true"
+ android:text="@string/interface_title" />
+
+ <com.wireguard.android.widget.ToggleSwitch
+ android:id="@+id/tunnel_switch"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignBaseline="@+id/interface_title"
+ android:layout_alignParentEnd="true"
+ app:checked="@{tunnel.state == State.UP}"
+ app:onBeforeCheckedChanged="@{fragment::setTunnelState}" />
+
+ <TextView
+ android:id="@+id/interface_name_label"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/interface_title"
+ android:layout_marginTop="8dp"
+ android:labelFor="@+id/interface_name_text"
+ android:text="@string/name" />
+
+ <TextView
+ android:id="@+id/interface_name_text"
+ style="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/interface_name_label"
+ android:text="@{tunnel.name}" />
+
+ <TextView
+ android:id="@+id/public_key_label"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/interface_name_text"
+ android:layout_marginTop="8dp"
+ android:labelFor="@+id/public_key_text"
+ android:text="@string/public_key" />
+
+ <TextView
+ android:id="@+id/public_key_text"
+ style="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/public_key_label"
+ android:contentDescription="@string/public_key_description"
+ android:ellipsize="end"
+ android:maxLines="1"
+ android:onClick="@{ClipboardUtils::copyTextView}"
+ android:text="@{config.interface.keyPair.publicKey.toBase64}" />
+
+ <TextView
+ android:id="@+id/addresses_label"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/public_key_text"
+ android:layout_marginTop="8dp"
+ android:labelFor="@+id/addresses_text"
+ android:text="@string/addresses" />
+
+ <TextView
+ android:id="@+id/addresses_text"
+ style="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/addresses_label"
+ android:contentDescription="@string/addresses"
+ android:text="@{config.interface.addresses}" />
+ </RelativeLayout>
+ </androidx.cardview.widget.CardView>
+
+ <LinearLayout
+ android:id="@+id/peers_layout"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="4dp"
+ android:divider="@null"
+ android:orientation="vertical"
+ app:items="@{config.peers}"
+ app:layout="@{@layout/tunnel_detail_peer}"
+ tools:ignore="UselessLeaf" />
+ </LinearLayout>
+ </ScrollView>
+</layout>
diff --git a/ui/src/main/res/layout/tunnel_detail_peer.xml b/ui/src/main/res/layout/tunnel_detail_peer.xml
new file mode 100644
index 0000000..181a4a2
--- /dev/null
+++ b/ui/src/main/res/layout/tunnel_detail_peer.xml
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+
+ <data>
+
+ <import type="com.wireguard.android.util.ClipboardUtils" />
+
+ <variable
+ name="item"
+ type="com.wireguard.config.Peer" />
+ </data>
+
+ <androidx.cardview.widget.CardView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="4dp"
+ android:layout_marginEnd="8dp"
+ android:layout_marginStart="8dp"
+ android:layout_marginTop="4dp"
+ android:background="?attr/colorBackground"
+ app:cardCornerRadius="4dp"
+ app:cardElevation="2dp"
+ app:contentPadding="8dp">
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:id="@+id/peer_title"
+ style="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:text="@string/peer" />
+
+ <TextView
+ android:id="@+id/public_key_label"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/peer_title"
+ android:layout_marginTop="8dp"
+ android:labelFor="@+id/public_key_text"
+ android:text="@string/public_key" />
+
+ <TextView
+ android:id="@+id/public_key_text"
+ style="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/public_key_label"
+ android:contentDescription="@string/public_key_description"
+ android:ellipsize="end"
+ android:maxLines="1"
+ android:onClick="@{ClipboardUtils::copyTextView}"
+ android:text="@{item.publicKey.toBase64}" />
+
+ <TextView
+ android:id="@+id/allowed_ips_label"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/public_key_text"
+ android:layout_marginTop="8dp"
+ android:labelFor="@+id/allowed_ips_text"
+ android:text="@string/allowed_ips" />
+
+ <TextView
+ android:id="@+id/allowed_ips_text"
+ style="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/allowed_ips_label"
+ android:text="@{item.allowedIps}" />
+
+ <TextView
+ android:id="@+id/endpoint_label"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/allowed_ips_text"
+ android:layout_marginTop="8dp"
+ android:labelFor="@+id/endpoint_text"
+ android:text="@string/endpoint" />
+
+ <TextView
+ android:id="@+id/endpoint_text"
+ style="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/endpoint_label"
+ android:text="@{item.endpoint}" />
+
+ <TextView
+ android:id="@+id/transfer_label"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/endpoint_text"
+ android:layout_marginTop="8dp"
+ android:labelFor="@+id/transfer_text"
+ android:text="@string/transfer"
+ android:visibility="gone" />
+
+ <TextView
+ android:id="@+id/transfer_text"
+ style="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/transfer_label"
+ android:visibility="gone" />
+ </RelativeLayout>
+ </androidx.cardview.widget.CardView>
+</layout>
diff --git a/ui/src/main/res/layout/tunnel_editor_fragment.xml b/ui/src/main/res/layout/tunnel_editor_fragment.xml
new file mode 100644
index 0000000..887b3bb
--- /dev/null
+++ b/ui/src/main/res/layout/tunnel_editor_fragment.xml
@@ -0,0 +1,254 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools">
+
+ <data>
+
+ <import type="com.wireguard.android.util.ClipboardUtils" />
+
+ <import type="com.wireguard.android.widget.KeyInputFilter" />
+
+ <import type="com.wireguard.android.widget.NameInputFilter" />
+
+ <variable
+ name="fragment"
+ type="com.wireguard.android.fragment.TunnelEditorFragment" />
+
+ <variable
+ name="config"
+ type="com.wireguard.android.viewmodel.ConfigProxy" />
+
+ <variable
+ name="name"
+ type="String" />
+ </data>
+
+ <androidx.coordinatorlayout.widget.CoordinatorLayout
+ android:id="@+id/main_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="?attr/colorBackground">
+
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <androidx.cardview.widget.CardView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="4dp"
+ android:layout_marginEnd="8dp"
+ android:layout_marginStart="8dp"
+ android:layout_marginTop="8dp"
+ android:background="?attr/colorBackground"
+ app:cardCornerRadius="4dp"
+ app:cardElevation="2dp"
+ app:contentPadding="8dp">
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:id="@+id/interface_title"
+ style="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:text="@string/interface_title" />
+
+ <TextView
+ android:id="@+id/interface_name_label"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/interface_title"
+ android:layout_marginTop="8dp"
+ android:labelFor="@+id/interface_name_text"
+ android:text="@string/name" />
+
+ <EditText
+ android:id="@+id/interface_name_text"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/interface_name_label"
+ android:inputType="textNoSuggestions|textVisiblePassword"
+ android:text="@={name}"
+ app:filter="@{NameInputFilter.newInstance()}" />
+
+ <TextView
+ android:id="@+id/private_key_label"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/interface_name_text"
+ android:labelFor="@+id/private_key_text"
+ android:text="@string/private_key" />
+
+ <EditText
+ android:id="@+id/private_key_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentStart="true"
+ android:layout_below="@+id/private_key_label"
+ android:layout_toStartOf="@+id/generate_private_key_button"
+ android:contentDescription="@string/public_key_description"
+ android:inputType="textNoSuggestions|textVisiblePassword"
+ android:text="@={config.interface.privateKey}"
+ app:filter="@{KeyInputFilter.newInstance()}" />
+
+ <Button
+ android:id="@+id/generate_private_key_button"
+ style="@style/Widget.AppCompat.Button.Borderless.Colored"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignBottom="@id/private_key_text"
+ android:layout_alignParentEnd="true"
+ android:layout_below="@+id/private_key_label"
+ android:onClick="@{() -> config.interface.generateKeyPair()}"
+ android:text="@string/generate" />
+
+ <TextView
+ android:id="@+id/public_key_label"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/private_key_text"
+ android:labelFor="@+id/public_key_text"
+ android:text="@string/public_key" />
+
+ <TextView
+ android:id="@+id/public_key_text"
+ style="?attr/editTextStyle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/public_key_label"
+ android:contentDescription="@string/public_key_description"
+ android:ellipsize="end"
+ android:focusable="false"
+ android:hint="@string/hint_generated"
+ android:maxLines="1"
+ android:onClick="@{ClipboardUtils::copyTextView}"
+ android:text="@{config.interface.publicKey}" />
+
+ <TextView
+ android:id="@+id/addresses_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentStart="true"
+ android:layout_below="@+id/public_key_text"
+ android:layout_toStartOf="@+id/listen_port_label"
+ android:labelFor="@+id/addresses_text"
+ android:text="@string/addresses" />
+
+ <EditText
+ android:id="@+id/addresses_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentStart="true"
+ android:layout_below="@+id/addresses_label"
+ android:layout_toStartOf="@+id/listen_port_text"
+ android:inputType="textNoSuggestions|textVisiblePassword"
+ android:text="@={config.interface.addresses}" />
+
+ <TextView
+ android:id="@+id/listen_port_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignBaseline="@+id/addresses_label"
+ android:layout_alignParentEnd="true"
+ android:layout_alignStart="@+id/generate_private_key_button"
+ android:labelFor="@+id/listen_port_text"
+ android:text="@string/listen_port" />
+
+ <EditText
+ android:id="@+id/listen_port_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignBaseline="@+id/addresses_text"
+ android:layout_alignParentEnd="true"
+ android:layout_alignStart="@+id/generate_private_key_button"
+ android:hint="@string/hint_random"
+ android:inputType="number"
+ android:text="@={config.interface.listenPort}"
+ android:textAlignment="center" />
+
+ <TextView
+ android:id="@+id/dns_servers_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentStart="true"
+ android:layout_below="@+id/addresses_text"
+ android:layout_toStartOf="@+id/mtu_label"
+ android:labelFor="@+id/dns_servers_text"
+ android:text="@string/dns_servers" />
+
+ <EditText
+ android:id="@+id/dns_servers_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentStart="true"
+ android:layout_below="@+id/dns_servers_label"
+ android:layout_toStartOf="@+id/mtu_text"
+ android:inputType="textNoSuggestions|textVisiblePassword"
+ android:text="@={config.interface.dnsServers}" />
+
+ <TextView
+ android:id="@+id/mtu_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignBaseline="@+id/dns_servers_label"
+ android:layout_alignParentEnd="true"
+ android:layout_alignStart="@+id/generate_private_key_button"
+ android:labelFor="@+id/mtu_text"
+ android:text="@string/mtu" />
+
+ <EditText
+ android:id="@+id/mtu_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignBaseline="@+id/dns_servers_text"
+ android:layout_alignParentEnd="true"
+ android:layout_alignStart="@+id/generate_private_key_button"
+ android:hint="@string/hint_automatic"
+ android:inputType="number"
+ android:text="@={config.interface.mtu}"
+ android:textAlignment="center" />
+
+ <Button
+ android:id="@+id/set_excluded_applications"
+ style="@style/Widget.AppCompat.Button.Borderless.Colored"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/dns_servers_text"
+ android:layout_marginLeft="-8dp"
+ android:onClick="@{fragment::onRequestSetExcludedApplications}"
+ android:text="@{@plurals/set_excluded_applications(config.interface.excludedApplications.size, config.interface.excludedApplications.size)}" />
+ </RelativeLayout>
+ </androidx.cardview.widget.CardView>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:divider="@null"
+ android:orientation="vertical"
+ app:items="@{config.peers}"
+ app:layout="@{@layout/tunnel_editor_peer}"
+ tools:ignore="UselessLeaf" />
+
+ <Button
+ style="@style/Widget.AppCompat.Button.Colored"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="4dp"
+ android:layout_marginEnd="4dp"
+ android:layout_marginStart="4dp"
+ android:onClick="@{() -> config.addPeer()}"
+ android:text="@string/add_peer" />
+ </LinearLayout>
+ </ScrollView>
+ </androidx.coordinatorlayout.widget.CoordinatorLayout>
+</layout>
diff --git a/ui/src/main/res/layout/tunnel_editor_peer.xml b/ui/src/main/res/layout/tunnel_editor_peer.xml
new file mode 100644
index 0000000..cf5d628
--- /dev/null
+++ b/ui/src/main/res/layout/tunnel_editor_peer.xml
@@ -0,0 +1,161 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+
+ <data>
+
+ <import type="android.view.View" />
+
+ <import type="com.wireguard.android.widget.KeyInputFilter" />
+
+ <variable
+ name="collection"
+ type="androidx.databinding.ObservableList&lt;com.wireguard.android.viewmodel.PeerProxy&gt;" />
+
+ <variable
+ name="item"
+ type="com.wireguard.android.viewmodel.PeerProxy" />
+ </data>
+
+ <androidx.cardview.widget.CardView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="4dp"
+ android:layout_marginEnd="8dp"
+ android:layout_marginStart="8dp"
+ android:layout_marginTop="4dp"
+ android:background="?attr/colorBackground"
+ app:cardCornerRadius="4dp"
+ app:cardElevation="2dp"
+ app:contentPadding="8dp">
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:id="@+id/peer_title"
+ style="?android:attr/textAppearanceMedium"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentStart="true"
+ android:layout_alignParentTop="true"
+ android:layout_marginBottom="8dp"
+ android:layout_toStartOf="@+id/peer_action_delete"
+ android:text="@string/peer" />
+
+ <ImageButton
+ android:id="@+id/peer_action_delete"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentTop="true"
+ android:background="@null"
+ android:contentDescription="@string/delete"
+ android:onClick="@{() -> item.unbind()}"
+ android:src="@drawable/ic_action_delete" />
+
+ <TextView
+ android:id="@+id/public_key_label"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/peer_title"
+ android:labelFor="@+id/public_key_text"
+ android:text="@string/public_key" />
+
+ <EditText
+ android:id="@+id/public_key_text"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/public_key_label"
+ android:inputType="textNoSuggestions|textVisiblePassword"
+ android:text="@={item.publicKey}"
+ app:filter="@{KeyInputFilter.newInstance()}" />
+
+ <TextView
+ android:id="@+id/pre_shared_key_label"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/public_key_text"
+ android:labelFor="@+id/pre_shared_key_text"
+ android:text="@string/pre_shared_key" />
+
+ <EditText
+ android:id="@+id/pre_shared_key_text"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/pre_shared_key_label"
+ android:hint="@string/hint_optional"
+ android:inputType="textNoSuggestions|textVisiblePassword"
+ android:text="@={item.preSharedKey}" />
+
+ <TextView
+ android:id="@+id/allowed_ips_label"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/pre_shared_key_text"
+ android:layout_toStartOf="@+id/exclude_private_ips"
+ android:labelFor="@+id/allowed_ips_text"
+ android:text="@string/allowed_ips" />
+
+ <CheckBox
+ android:id="@+id/exclude_private_ips"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignBaseline="@+id/allowed_ips_label"
+ android:layout_alignParentEnd="true"
+ android:checked="@={item.excludingPrivateIps}"
+ android:text="@string/exclude_private_ips"
+ android:visibility="@{item.ableToExcludePrivateIps ? View.VISIBLE : View.GONE}" />
+
+ <EditText
+ android:id="@+id/allowed_ips_text"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/allowed_ips_label"
+ android:inputType="textNoSuggestions|textVisiblePassword"
+ android:text="@={item.allowedIps}" />
+
+ <TextView
+ android:id="@+id/endpoint_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentStart="true"
+ android:layout_below="@+id/allowed_ips_text"
+ android:layout_toStartOf="@+id/persistent_keepalive_label"
+ android:labelFor="@+id/endpoint_text"
+ android:text="@string/endpoint" />
+
+ <EditText
+ android:id="@+id/endpoint_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentStart="true"
+ android:layout_below="@+id/endpoint_label"
+ android:layout_toStartOf="@+id/persistent_keepalive_text"
+ android:inputType="textNoSuggestions|textVisiblePassword"
+ android:text="@={item.endpoint}" />
+
+ <TextView
+ android:id="@+id/persistent_keepalive_label"
+ android:layout_width="96dp"
+ android:layout_height="wrap_content"
+ android:layout_alignBaseline="@+id/endpoint_label"
+ android:layout_alignParentEnd="true"
+ android:labelFor="@+id/persistent_keepalive_text"
+ android:text="@string/persistent_keepalive" />
+
+ <EditText
+ android:id="@+id/persistent_keepalive_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignBaseline="@+id/endpoint_text"
+ android:layout_alignParentEnd="true"
+ android:layout_alignStart="@+id/persistent_keepalive_label"
+ android:hint="@string/hint_optional"
+ android:inputType="number"
+ android:text="@={item.persistentKeepalive}"
+ android:textAlignment="center" />
+ </RelativeLayout>
+ </androidx.cardview.widget.CardView>
+</layout>
diff --git a/ui/src/main/res/layout/tunnel_list_fragment.xml b/ui/src/main/res/layout/tunnel_list_fragment.xml
new file mode 100644
index 0000000..c8144db
--- /dev/null
+++ b/ui/src/main/res/layout/tunnel_list_fragment.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools">
+
+ <data>
+
+ <import type="com.wireguard.android.model.ObservableTunnel" />
+
+ <variable
+ name="fragment"
+ type="com.wireguard.android.fragment.TunnelListFragment" />
+
+ <variable
+ name="rowConfigurationHandler"
+ type="com.wireguard.android.databinding.ObservableKeyedRecyclerViewAdapter.RowConfigurationHandler" />
+
+ <variable
+ name="tunnels"
+ type="com.wireguard.android.util.ObservableKeyedList&lt;String, ObservableTunnel&gt;" />
+ </data>
+
+ <androidx.coordinatorlayout.widget.CoordinatorLayout
+ android:id="@+id/main_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="?attr/colorBackground"
+ android:clipChildren="false">
+
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/tunnel_list"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:choiceMode="multipleChoiceModal"
+ android:clipToPadding="false"
+ android:paddingBottom="@{@dimen/design_fab_size_normal * 1.1f}"
+ android:visibility="@{tunnels.size() > 0 ? android.view.View.VISIBLE : android.view.View.GONE}"
+ app:configurationHandler="@{rowConfigurationHandler}"
+ app:items="@{tunnels}"
+ app:layout="@{@layout/tunnel_list_item}"
+ tools:listitem="@layout/tunnel_list_item"
+ tools:itemCount="12" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:orientation="vertical"
+ android:visibility="@{tunnels.size() == 0 ? android.view.View.VISIBLE : android.view.View.GONE}"
+ tools:visibility="gone">
+
+ <androidx.appcompat.widget.AppCompatImageView
+ android:id="@+id/logo_placeholder"
+ android:layout_width="140dp"
+ android:layout_height="140dp"
+ android:layout_gravity="center"
+ android:layout_marginBottom="20dp"
+ android:alpha="0.3333333"
+ android:src="@mipmap/ic_launcher" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:text="@string/tunnel_list_placeholder"
+ android:textSize="20sp" />
+ </LinearLayout>
+ <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
+ style="@style/Widget.MaterialComponents.ExtendedFloatingActionButton.Icon"
+ android:id="@+id/create_fab"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom|end"
+ android:layout_margin="@dimen/fab_margin"
+ app:icon="@drawable/ic_action_add_white" />
+
+ </androidx.coordinatorlayout.widget.CoordinatorLayout>
+</layout>
diff --git a/ui/src/main/res/layout/tunnel_list_item.xml b/ui/src/main/res/layout/tunnel_list_item.xml
new file mode 100644
index 0000000..04c0f51
--- /dev/null
+++ b/ui/src/main/res/layout/tunnel_list_item.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools">
+
+ <data>
+
+ <import type="com.wireguard.android.model.ObservableTunnel" />
+
+ <import type="com.wireguard.android.backend.Tunnel.State" />
+
+ <variable
+ name="collection"
+ type="com.wireguard.android.util.ObservableKeyedList&lt;String, ObservableTunnel&gt;" />
+
+ <variable
+ name="key"
+ type="String" />
+
+ <variable
+ name="item"
+ type="com.wireguard.android.model.ObservableTunnel" />
+
+ <variable
+ name="fragment"
+ type="com.wireguard.android.fragment.TunnelListFragment" />
+ </data>
+
+ <com.wireguard.android.widget.MultiselectableRelativeLayout
+ android:id="@+id/tunnel_list_item"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="@drawable/list_item_background"
+ android:descendantFocusability="beforeDescendants"
+ android:focusable="true"
+ android:nextFocusRight="@+id/tunnel_switch"
+ android:padding="16dp">
+
+ <TextView
+ android:id="@+id/tunnel_name"
+ style="?android:attr/textAppearanceMedium"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentStart="true"
+ android:layout_alignParentTop="true"
+ android:ellipsize="end"
+ android:maxLines="1"
+ android:text="@{key}"
+ tools:text="@sample/interface_names.json/names/names/name" />
+
+ <com.wireguard.android.widget.ToggleSwitch
+ android:id="@+id/tunnel_switch"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignBaseline="@+id/tunnel_name"
+ android:layout_alignParentEnd="true"
+ android:nextFocusLeft="@+id/tunnel_list_item"
+ app:checked="@{item.state == State.UP}"
+ app:onBeforeCheckedChanged="@{fragment::setTunnelState}"
+ tools:checked="@sample/interface_names.json/names/checked/checked" />
+ </com.wireguard.android.widget.MultiselectableRelativeLayout>
+</layout>
diff --git a/ui/src/main/res/menu/config_editor.xml b/ui/src/main/res/menu/config_editor.xml
new file mode 100644
index 0000000..dd0137d
--- /dev/null
+++ b/ui/src/main/res/menu/config_editor.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+ <item
+ android:id="@+id/menu_action_save"
+ android:alphabeticShortcut="s"
+ android:icon="@drawable/ic_action_save"
+ android:title="@string/save"
+ app:showAsAction="always" />
+</menu>
diff --git a/ui/src/main/res/menu/main_activity.xml b/ui/src/main/res/menu/main_activity.xml
new file mode 100644
index 0000000..68bce52
--- /dev/null
+++ b/ui/src/main/res/menu/main_activity.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+ <item
+ android:id="@+id/menu_settings"
+ android:alphabeticShortcut="s"
+ android:icon="@drawable/ic_settings"
+ android:orderInCategory="1000"
+ android:title="@string/settings"
+ app:showAsAction="always" />
+</menu>
diff --git a/ui/src/main/res/menu/tunnel_detail.xml b/ui/src/main/res/menu/tunnel_detail.xml
new file mode 100644
index 0000000..2834a66
--- /dev/null
+++ b/ui/src/main/res/menu/tunnel_detail.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+ <item
+ android:id="@+id/menu_action_edit"
+ android:alphabeticShortcut="e"
+ android:icon="@drawable/ic_action_edit"
+ android:title="@string/edit"
+ app:showAsAction="always" />
+</menu>
diff --git a/ui/src/main/res/menu/tunnel_list_action_mode.xml b/ui/src/main/res/menu/tunnel_list_action_mode.xml
new file mode 100644
index 0000000..22f6194
--- /dev/null
+++ b/ui/src/main/res/menu/tunnel_list_action_mode.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+ <item
+ android:id="@+id/menu_action_select_all"
+ android:alphabeticShortcut="s"
+ android:icon="@drawable/ic_action_select_all"
+ android:title="@string/select_all"
+ app:showAsAction="always" />
+ <item
+ android:id="@+id/menu_action_delete"
+ android:alphabeticShortcut="d"
+ android:icon="@drawable/ic_action_delete"
+ android:title="@string/delete"
+ app:showAsAction="always" />
+</menu>
diff --git a/ui/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/ui/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..a8a8fa5
--- /dev/null
+++ b/ui/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@color/ic_launcher_background" />
+ <foreground android:drawable="@drawable/ic_launcher_foreground" />
+</adaptive-icon>
diff --git a/ui/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/ui/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..a8a8fa5
--- /dev/null
+++ b/ui/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@color/ic_launcher_background" />
+ <foreground android:drawable="@drawable/ic_launcher_foreground" />
+</adaptive-icon>
diff --git a/ui/src/main/res/mipmap-hdpi/ic_launcher.png b/ui/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..8a5b8d6
--- /dev/null
+++ b/ui/src/main/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/ui/src/main/res/mipmap-hdpi/ic_launcher_round.png b/ui/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..5611194
--- /dev/null
+++ b/ui/src/main/res/mipmap-hdpi/ic_launcher_round.png
Binary files differ
diff --git a/ui/src/main/res/mipmap-mdpi/ic_launcher.png b/ui/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..aa5ac82
--- /dev/null
+++ b/ui/src/main/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/ui/src/main/res/mipmap-mdpi/ic_launcher_round.png b/ui/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..ebad319
--- /dev/null
+++ b/ui/src/main/res/mipmap-mdpi/ic_launcher_round.png
Binary files differ
diff --git a/ui/src/main/res/mipmap-xhdpi/ic_launcher.png b/ui/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..ef183c3
--- /dev/null
+++ b/ui/src/main/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/ui/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/ui/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..79f3fa9
--- /dev/null
+++ b/ui/src/main/res/mipmap-xhdpi/ic_launcher_round.png
Binary files differ
diff --git a/ui/src/main/res/mipmap-xxhdpi/ic_launcher.png b/ui/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..95e7241
--- /dev/null
+++ b/ui/src/main/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/ui/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/ui/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..d1731b3
--- /dev/null
+++ b/ui/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
Binary files differ
diff --git a/ui/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/ui/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..d3ec336
--- /dev/null
+++ b/ui/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/ui/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/ui/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..c0ae03b
--- /dev/null
+++ b/ui/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
Binary files differ
diff --git a/ui/src/main/res/values-hi/strings.xml b/ui/src/main/res/values-hi/strings.xml
new file mode 100644
index 0000000..a9f0186
--- /dev/null
+++ b/ui/src/main/res/values-hi/strings.xml
@@ -0,0 +1,179 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <plurals name="delete_error">
+ <item quantity="one">%d टनल हटाने में असमर्थ: %s</item>
+ <item quantity="other">%d टनलस को हटाने में असमर्थ: %s</item>
+ </plurals>
+ <plurals name="delete_success">
+ <item quantity="one">%d टनल को सफलतापूर्वक हटा दिया गया</item>
+ <item quantity="other">%d टनलस को सफलतापूर्वक हटा दिया गया</item>
+ </plurals>
+ <plurals name="delete_title">
+ <item quantity="one">%d टनल चयनित</item>
+ <item quantity="other">%d टनलस का चयन किया गया</item>
+ </plurals>
+ <plurals name="import_partial_success">
+ <item quantity="one">आयातित %d %d टनल</item>
+ <item quantity="other">आयातित %d %d टनलस</item>
+ </plurals>
+ <plurals name="import_total_success">
+ <item quantity="one">आयातित %d टनल</item>
+ <item quantity="other">आयातित %d टनलस</item>
+ </plurals>
+ <plurals name="set_excluded_applications">
+ <item quantity="one">%d बहिष्कृत अनुप्रयोग</item>
+ <item quantity="other">%d बहिष्कृत अनुप्रयोग</item>
+ </plurals>
+ <string name="add_peer">पीयर जोड़ें</string>
+ <string name="addresses">एड्रेससैस</string>
+ <string name="allowed_ips">अनुमत आईपी</string>
+ <string name="app_name">WireGuard</string>
+ <string name="bad_config_context">%1$s\'s %2$s</string>
+ <string name="bad_config_context_top_level">%s</string>
+ <string name="bad_config_error">%1$s in %2$s</string>
+ <string name="bad_config_explanation_pka">: सकारात्मक होना चाहिए और 65535 से अधिक नहीं होना चाहिए</string>
+ <string name="bad_config_explanation_positive_number">: सकारात्मक होना चाहिए</string>
+ <string name="bad_config_explanation_udp_port">: एक वैध यूडीपी पोर्ट नंबर होना चाहिए</string>
+ <string name="bad_config_reason_invalid_key">अमान्य चाबी</string>
+ <string name="bad_config_reason_invalid_number">अमान्य संख्या</string>
+ <string name="bad_config_reason_invalid_value">अमान्य मूल्य</string>
+ <string name="bad_config_reason_missing_attribute">गुम विशेषता</string>
+ <string name="bad_config_reason_missing_section">छूटा हुआ भाग</string>
+ <string name="bad_config_reason_missing_value">अनुपस्थित मान</string>
+ <string name="bad_config_reason_syntax_error">वक्य रचना त्रुटि</string>
+ <string name="bad_config_reason_unknown_attribute">अज्ञात एट्रिब्यूट</string>
+ <string name="bad_config_reason_unknown_section">अज्ञात एट्रिब्यूट </string>
+ <string name="bad_config_reason_value_out_of_range">मूल्य सीमा से बाहर</string>
+ <string name="bad_extension_error">फ़ाइल .conf या .zip होनी चाहिए</string>
+ <string name="cancel">रद्द</string>
+ <string name="config_delete_error">कॉन्फ़िगरेशन फ़ाइल %s को नहीं हटा सकता</string>
+ <string name="config_exists_error">“%s” के लिए कॉन्फ़िगरेशन पहले से मौजूद है</string>
+ <string name="config_file_exists_error">कॉन्फ़िगरेशन फ़ाइल “%s” पहले से मौजूद है</string>
+ <string name="config_not_found_error">कॉन्फ़िगरेशन फ़ाइल “%s” नहीं मिली</string>
+ <string name="config_rename_error">कॉन्फ़िगरेशन फ़ाइल “%s” का नाम नहीं बदल सकता</string>
+ <string name="config_save_error">“%1$s” के लिए कॉन्फ़िगरेशन को नहीं बचा सकता: %2$s</string>
+ <string name="config_save_success">“%s” के लिए सफलतापूर्वक सहेजा गया कॉन्फ़िगरेशन</string>
+ <string name="create_activity_title">वायरगार्ड टनल बनाएं</string>
+ <string name="create_bin_dir_error">स्थानीय बाइनरी निर्देशिका नहीं बना सकते</string>
+ <string name="create_empty">स्क्रैच से बनाएँ</string>
+ <string name="create_from_file">फ़ाइल या संग्रह से बनाएँ</string>
+ <string name="create_from_qr_code">क्यूआर कोड से बनाएं</string>
+ <string name="create_output_dir_error">आउटपुट निर्देशिका नहीं बना सकता</string>
+ <string name="create_downloads_file_error">डाउनलोड निर्देशिका में फ़ाइल नहीं बना सकते</string>
+ <string name="create_temp_dir_error">स्थानीय अस्थायी निर्देशिका नहीं बना सकते</string>
+ <string name="create_tunnel">टनल बनाए</string>
+ <string name="dark_theme_summary_off">अभी प्रकाश (दिन) थीम का उपयोग कर रहे हैं</string>
+ <string name="dark_theme_summary_on">अभी डार्क (रात) थीम का उपयोग कर रहे हैं</string>
+ <string name="dark_theme_title">डार्क थीम का इस्तेमाल करें</string>
+ <string name="delete">हटाएं</string>
+ <string name="toggle_all">सबको स्विच करो</string>
+ <string name="dns_servers">DNS सर्वर</string>
+ <string name="edit">संपादित करें</string>
+ <string name="endpoint">अंतिम</string>
+ <string name="error_down">टनल को लाने में त्रुटि: %s</string>
+ <string name="error_fetching_apps">ऐप्स सूची लाने में त्रुटि: %s</string>
+ <string name="error_root">कृपया रूट एक्सेस प्राप्त करें और पुनः प्रयास करें</string>
+ <string name="error_up">टनल को लाने में त्रुटि: %s</string>
+ <string name="exclude_private_ips">निजी आईपी को छोड़ दें</string>
+ <string name="excluded_applications">निकाले गए ऐप्स</string>
+ <string name="generate">उत्पन्न</string>
+ <string name="generic_error">अज्ञात “%s” त्रुटि</string>
+ <string name="hint_automatic">(ऑटो)</string>
+ <string name="hint_generated">(उत्पन्न)</string>
+ <string name="hint_optional">(ऐच्छिक)</string>
+ <string name="hint_random">(क्रमरहित)</string>
+ <string name="illegal_filename_error">अवैध फ़ाइल नाम “%s”</string>
+ <string name="import_error">टनल को आयात करने में असमर्थ: %s</string>
+ <string name="import_from_qr_code">क्यूआर कोड से टनल को आयात करें</string>
+ <string name="import_success">आयातित “%s”</string>
+ <string name="interface_title">इंटरफेस</string>
+ <string name="key_length_explanation_base64">: वायरगार्ड बेस 64 कीज़ में 44 अक्षर (32 बाइट्स) होने चाहिए</string>
+ <string name="key_length_explanation_binary">: वायरगार्ड कीज 32 बाइट होनी चाहिए</string>
+ <string name="key_length_explanation_hex">: वायरगार्ड हेक्स कीज़ 64 अक्षरों की होनी चाहिए (32 बाइट्स)</string>
+ <string name="listen_port">पोर्ट सुनो</string>
+ <string name="log_export_error">लॉग निर्यात करने में असमर्थ: %s</string>
+ <string name="log_export_success">“%s” में सहेजा गया</string>
+ <string name="log_export_summary">लॉग फ़ाइल को डाउनलोड फ़ोल्डर में सहेजा जाएगा</string>
+ <string name="log_export_title">लॉग फ़ाइल निर्यात करें</string>
+ <string name="logcat_error">लॉगकैट चलाने में असमर्थ: </string>
+ <string name="module_version_error">कर्नेल मॉड्यूल संस्करण निर्धारित करने में असमर्थ</string>
+ <string name="module_installer_not_found">आपके डिवाइस के लिए कोई मॉड्यूल उपलब्ध नहीं हैं</string>
+ <string name="module_installer_initial">प्रयोगात्मक कर्नेल मॉड्यूल प्रदर्शन में सुधार कर सकता है</string>
+ <string name="module_installer_success">सफलता। ऐप 5 सेकंड में रीस्टार्ट होगा</string>
+ <string name="module_installer_title">कर्नेल मॉड्यूल डाउनलोड और इंस्टॉल करें</string>
+ <string name="module_installer_working">डाउनलोड कर रहा है और स्थापित कर रहा है…</string>
+ <string name="module_installer_error">कुछ गलत हो गया। कृपया पुन: प्रयास करें</string>
+ <string name="mtu">MTU</string>
+ <string name="name">नाम</string>
+ <string name="no_config_error">बिना किसी कॉन्फ़िगरेशन के एक टनल को लाने की कोशिश करना</string>
+ <string name="no_configs_error">कोई कॉन्फ़िगरेशन नहीं मिला</string>
+ <string name="no_tunnels_error">कोई टनल मौजूद नहीं है</string>
+ <string name="parse_error_generic">पाठ</string>
+ <string name="parse_error_inet_address">आईपी पता</string>
+ <string name="parse_error_inet_endpoint">समाप्त</string>
+ <string name="parse_error_inet_network">आईपी नेटवर्क</string>
+ <string name="parse_error_integer">संख्या</string>
+ <string name="parse_error_reason">%1$s “%2$s” को पार्स नहीं कर सकता</string>
+ <string name="peer">पीयर</string>
+ <string name="permission_description">किसी एप्लिकेशन को वायरगार्ड सुरंगों को नियंत्रित करने की अनुमति देता है। इस अनुमति वाले ऐप्स, इंटरनेट ट्रैफ़िक को संभावित रूप से गलत तरीके से वायरगार्ड सुरंगों को सक्षम और अक्षम कर सकते हैं।</string>
+ <string name="permission_label">वायरगार्ड सुरंगों को नियंत्रित करें</string>
+ <string name="persistent_keepalive">लगातार जिंदा रहो</string>
+ <string name="pre_shared_key">प्री-शेयर्ड कीस</string>
+ <string name="private_key">निजी कीस</string>
+ <string name="public_key">सार्वजनिक कीस</string>
+ <string name="public_key_description">सार्वजनिक कीस</string>
+ <string name="qr_code_hint">टिप: `qrencode -t ansiutf8 &lt; tunnel.conf` के साथ उत्पन्न करो</string>
+ <string name="restore_on_boot_summary">बूट पर पहले से सक्षम टनल को ऊपर लाएं</string>
+ <string name="restore_on_boot_title">बूट पर पुनर्स्थापित करें</string>
+ <string name="save">सहेजें</string>
+ <string name="select_all">सभी का चयन करे</string>
+ <string name="set_exclusions">बहिष्करण सेट करें</string>
+ <string name="settings">सेटिंग्स</string>
+ <string name="shell_exit_status_read_error">शेल बाहर निकलने की स्थिति नहीं पढ़ सकता</string>
+ <string name="shell_marker_count_error">शेल ने 4 मार्करों की अपेक्षा की, %d प्राप्त किया</string>
+ <string name="shell_start_error">शेल शुरू करने में विफल: %d</string>
+ <string name="toggle_error">वायरगार्ड टनल टॉगल करने में त्रुटि: %s</string>
+ <string name="tools_installer_already">wg और wg-quick पहले से इंस्टॉल हैं</string>
+ <string name="tools_installer_failure">कमांड-लाइन टूल स्थापित करने में असमर्थ (कोई रूट नहीं)</string>
+ <string name="tools_installer_initial">स्क्रिप्टिंग के लिए वैकल्पिक उपकरण स्थापित करें</string>
+ <string name="tools_installer_initial_magisk">Magisk मॉड्यूल के रूप में स्क्रिप्टिंग के लिए वैकल्पिक उपकरण स्थापित करें</string>
+ <string name="tools_installer_initial_system">सिस्टम विभाजन में स्क्रिप्टिंग के लिए वैकल्पिक उपकरण स्थापित करें</string>
+ <string name="tools_installer_success_magisk">wg और wg-quick को मैजिक मॉड्यूल के रूप में स्थापित किया गया है (रिबूट आवश्यक)</string>
+ <string name="tools_installer_success_system">wg और wg-quick सिस्टम विभाजन में स्थापित है</string>
+ <string name="tools_installer_title">कमांड लाइन उपकरण स्थापित करें</string>
+ <string name="tools_installer_working">Wg और wg-quick इंस्टॉल करना</string>
+ <string name="tools_unavailable_error">आवश्यक उपकरण अनुपलब्ध हैं</string>
+ <string name="transfer">स्थानांतरण</string>
+ <string name="transfer_rx_tx">rx: %1$s, tx: %2$s</string>
+ <string name="transfer_bytes">%d B</string>
+ <string name="transfer_kibibytes">%.2f KiB</string>
+ <string name="transfer_mibibytes">%.2f MiB</string>
+ <string name="transfer_gibibytes">%.2f GiB</string>
+ <string name="transfer_tibibytes">%.2f TiB</string>
+ <string name="tun_create_error">ट्यून डिवाइस बनाने में असमर्थ</string>
+ <string name="tunnel_config_error">टनल को कॉन्फ़िगर करने में असमर्थ (wg-quick लौटा %d)</string>
+ <string name="tunnel_create_error">टनल बनाने में असमर्थ: %s</string>
+ <string name="tunnel_create_success">सफलतापूर्वक बनाया गया टनल “%s”</string>
+ <string name="tunnel_error_already_exists">टनल “%s” पहले से मौजूद है</string>
+ <string name="tunnel_error_invalid_name">गलत नाम</string>
+ <string name="tunnel_list_placeholder">नीले बटन का उपयोग करके एक टनल को जोड़ें</string>
+ <string name="tunnel_name">टनल का नाम</string>
+ <string name="tunnel_on_error">टनल चालू करने में असमर्थ (wgTurnOn लौटा %d)</string>
+ <string name="tunnel_rename_error">टनल का नाम बदलने में असमर्थ: %s</string>
+ <string name="tunnel_rename_success">टनल का नाम बदलकर “%s” करने के लिए</string>
+ <string name="type_name_go_userspace">userspace पे जाए </string>
+ <string name="type_name_kernel_module">कर्नेल मॉड्यूल</string>
+ <string name="unknown_error">अज्ञात त्रुटि</string>
+ <string name="version_summary">%1$s बैकएंड v%2$s</string>
+ <string name="version_summary_checking">%s बैकएंड संस्करण की जाँच कर रहा है</string>
+ <string name="version_summary_unknown">अज्ञात %s संस्करण</string>
+ <string name="version_title">WireGuard for Android v%s</string>
+ <string name="vpn_not_authorized_error">वीपीएन सेवा उपयोगकर्ता द्वारा अधिकृत नहीं है</string>
+ <string name="vpn_start_error">Android VPN सेवा प्रारंभ करने में असमर्थ</string>
+ <string name="zip_export_error">टनल का निर्यात करने में असमर्थ: %s</string>
+ <string name="zip_export_success">“%s” पर सहेजा गया</string>
+ <string name="zip_export_summary">ज़िप फ़ाइल को डाउनलोड फ़ोल्डर में सहेजा जाएगा</string>
+ <string name="zip_export_title">जिप फाइल के लिए टनल को एक्सपोर्ट करें</string>
+ <string name="key_length_error">चाबी की लम्बाई गलत </string>
+ <string name="key_contents_error">चाबी में खराब वर्ण</string>
+</resources>
diff --git a/ui/src/main/res/values-it/strings.xml b/ui/src/main/res/values-it/strings.xml
new file mode 100644
index 0000000..b76c39c
--- /dev/null
+++ b/ui/src/main/res/values-it/strings.xml
@@ -0,0 +1,179 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <plurals name="delete_error">
+ <item quantity="one">Impossibile eliminare %d tunnel: %s</item>
+ <item quantity="other">Impossibile eliminare %d tunnel: %s</item>
+ </plurals>
+ <plurals name="delete_success">
+ <item quantity="one">%d tunnel eliminato correttamente</item>
+ <item quantity="other">%d tunnel eliminati correttamente</item>
+ </plurals>
+ <plurals name="delete_title">
+ <item quantity="one">%d tunnel selezionato</item>
+ <item quantity="other">%d tunnel selezionati</item>
+ </plurals>
+ <plurals name="import_partial_success">
+ <item quantity="one">Importato %d di %d tunnel</item>
+ <item quantity="other">Importati %d di %d tunnel</item>
+ </plurals>
+ <plurals name="import_total_success">
+ <item quantity="one">Importato %d tunnel</item>
+ <item quantity="other">Importati %d tunnel</item>
+ </plurals>
+ <plurals name="set_excluded_applications">
+ <item quantity="one">%d applicazione esclusa</item>
+ <item quantity="other">%d applicazioni escluse</item>
+ </plurals>
+ <string name="add_peer">Aggiungi peer</string>
+ <string name="addresses">Indirizzi</string>
+ <string name="allowed_ips">IP consentiti</string>
+ <string name="app_name">WireGuard</string>
+ <string name="bad_config_context">%2$s di %1$s</string>
+ <string name="bad_config_context_top_level">%s</string>
+ <string name="bad_config_error">%1$s in %2$s</string>
+ <string name="bad_config_explanation_pka">: deve essere positivo e non maggiore di 65535</string>
+ <string name="bad_config_explanation_positive_number">: deve essere positivo</string>
+ <string name="bad_config_explanation_udp_port">: deve essere un numero di porta UDP valido</string>
+ <string name="bad_config_reason_invalid_key">Chiave non valida</string>
+ <string name="bad_config_reason_invalid_number">Numero non valido</string>
+ <string name="bad_config_reason_invalid_value">Valore non valido</string>
+ <string name="bad_config_reason_missing_attribute">Attributo mancante</string>
+ <string name="bad_config_reason_missing_section">Sezione mancante</string>
+ <string name="bad_config_reason_missing_value">Valore mancante</string>
+ <string name="bad_config_reason_syntax_error">Errore di sintassi</string>
+ <string name="bad_config_reason_unknown_attribute">Attributo sconosciuto</string>
+ <string name="bad_config_reason_unknown_section">Sezione sconosciuta</string>
+ <string name="bad_config_reason_value_out_of_range">Valore fuori scala</string>
+ <string name="bad_extension_error">Il file deve essere .conf o .zip</string>
+ <string name="cancel">Annulla</string>
+ <string name="config_delete_error">Impossibile eliminare il file di configurazione %s</string>
+ <string name="config_exists_error">La configurazione per “%s” esiste già</string>
+ <string name="config_file_exists_error">Il file di configurazione “%s” esiste già</string>
+ <string name="config_not_found_error">File di configurazione “%s” non trovato</string>
+ <string name="config_rename_error">Impossibile rinominare il file di configurazione “%s”</string>
+ <string name="config_save_error">Impossibile salvare la configurazione per “%1$s”: %2$s</string>
+ <string name="config_save_success">Configurazione per “%s” salvata correttamente</string>
+ <string name="create_activity_title">Crea un tunnel WireGuard</string>
+ <string name="create_bin_dir_error">Impossibile creare cartella locale binari</string>
+ <string name="create_empty">Crea da zero</string>
+ <string name="create_from_file">Crea da un file o archivio</string>
+ <string name="create_from_qr_code">Crea da un codice QR</string>
+ <string name="create_output_dir_error">Impossibile creare la cartella di output</string>
+ <string name="create_downloads_file_error">Impossibile creare il file nella cartella di download</string>
+ <string name="create_temp_dir_error">Impossibile creare la cartella locale temporanea</string>
+ <string name="create_tunnel">Crea tunnel</string>
+ <string name="dark_theme_summary_off">Stai usando il tema chiaro (giorno)</string>
+ <string name="dark_theme_summary_on">Stai usando il tema scuro (notte)</string>
+ <string name="dark_theme_title">Usa tema scuro</string>
+ <string name="delete">Elimina</string>
+ <string name="toggle_all">Inverti tutto</string>
+ <string name="dns_servers">Server DNS</string>
+ <string name="edit">Modifica</string>
+ <string name="endpoint">Endpoint</string>
+ <string name="error_down">Errore di disattivazione del tunnel: %s</string>
+ <string name="error_fetching_apps">Errore di recupero della lista app: %s</string>
+ <string name="error_root">Si prega di ottenere l\'accesso root e riprovare</string>
+ <string name="error_up">Errore di attivazione del tunnel: %s</string>
+ <string name="exclude_private_ips">Escludi IP privati</string>
+ <string name="excluded_applications">Applicazioni escluse</string>
+ <string name="generate">Genera</string>
+ <string name="generic_error">Errore “%s” sconosciuto</string>
+ <string name="hint_automatic">(auto)</string>
+ <string name="hint_generated">(generato)</string>
+ <string name="hint_optional">(facoltativo)</string>
+ <string name="hint_random">(casuale)</string>
+ <string name="illegal_filename_error">Nome file “%s” non valido</string>
+ <string name="import_error">Impossibile importare il tunnel: %s</string>
+ <string name="import_from_qr_code">Importa tunnel da codice QR</string>
+ <string name="import_success">Importato “%s”</string>
+ <string name="interface_title">Interfaccia</string>
+ <string name="key_length_explanation_base64">: le chiavi base64 di WireGuard devono essere di 44 caratteri (32 byte)</string>
+ <string name="key_length_explanation_binary">: le chiavi di WireGuard devono essere di 32 byte</string>
+ <string name="key_length_explanation_hex">: le chiavi hex di WireGuard devono essere di 64 caratteri (32 byte)</string>
+ <string name="listen_port">Porta in ascolto</string>
+ <string name="log_export_error">Impossibile esportare il registro: %s</string>
+ <string name="log_export_success">Salvato in “%s”</string>
+ <string name="log_export_summary">Il file del registro verrà salvato nella cartella di download</string>
+ <string name="log_export_title">Esporta file registro</string>
+ <string name="logcat_error">Impossibile eseguire logcat: </string>
+ <string name="module_version_error">Impossibile determinare la versione modulo del kernel</string>
+ <string name="module_installer_not_found">Nessun modulo disponibile per il tuo dispositivo</string>
+ <string name="module_installer_initial">Il modulo del kernel sperimentale può migliorare le prestazioni</string>
+ <string name="module_installer_success">Fatto. L\'applicazione si riavvierà in 5 secondi</string>
+ <string name="module_installer_title">Scarica e installa il modulo del kernel</string>
+ <string name="module_installer_working">Scaricamento e installazione…</string>
+ <string name="module_installer_error">Qualcosa è andato storto. Riprova</string>
+ <string name="mtu">MTU</string>
+ <string name="name">Nome</string>
+ <string name="no_config_error">Tentativo di attivare un tunnel senza configurazione</string>
+ <string name="no_configs_error">Nessuna configurazione trovata</string>
+ <string name="no_tunnels_error">Non esistono tunnel</string>
+ <string name="parse_error_generic">stringa</string>
+ <string name="parse_error_inet_address">indirizzo IP</string>
+ <string name="parse_error_inet_endpoint">endpoint</string>
+ <string name="parse_error_inet_network">rete IP</string>
+ <string name="parse_error_integer">numero</string>
+ <string name="parse_error_reason">Impossibile analizzare %1$s “%2$s”</string>
+ <string name="peer">Peer</string>
+ <string name="permission_description">Permette ad un\'app di controllare i tunnel WireGuard. Le app con questa autorizzazione possono attivare e disattivare i tunnel WireGuard a piacimento, potenzialmente deviando il traffico internet.</string>
+ <string name="permission_label">controlla tunnel WireGuard</string>
+ <string name="persistent_keepalive">Tieni sempre attivo</string>
+ <string name="pre_shared_key">Chiave condivisa (PSK)</string>
+ <string name="private_key">Chiave privata</string>
+ <string name="public_key">Chiave pubblica</string>
+ <string name="public_key_description">La chiave pubblica</string>
+ <string name="qr_code_hint">Suggerimento: genera con `qrencode -t ansiutf8 &lt; tunnel.conf`.</string>
+ <string name="restore_on_boot_summary">Attiva tunnel attivati in precedenza all\'avvio</string>
+ <string name="restore_on_boot_title">Ripristina all\'avvio</string>
+ <string name="save">Salva</string>
+ <string name="select_all">Seleziona tutto</string>
+ <string name="set_exclusions">Imposta esclusioni</string>
+ <string name="settings">Impostazioni</string>
+ <string name="shell_exit_status_read_error">La shell non riesce a leggere l\'exit status</string>
+ <string name="shell_marker_count_error">La shell si aspettava 4 marker, ne ha ricevuti %d</string>
+ <string name="shell_start_error">Avvio della shell fallito: %d</string>
+ <string name="toggle_error">Errore di commutazione tunnel WireGuard: %s</string>
+ <string name="tools_installer_already">wg e wg-quick sono già installati</string>
+ <string name="tools_installer_failure">Impossibile installare strumenti di riga di comando (non root?)</string>
+ <string name="tools_installer_initial">Installa strumenti facoltativi per script</string>
+ <string name="tools_installer_initial_magisk">Installa strumenti facoltativi per script come moduli Magisk</string>
+ <string name="tools_installer_initial_system">Installa strumenti facoltativi per script nella partizione di sistema</string>
+ <string name="tools_installer_success_magisk">wg e wg-quick installati come moduli Magisk (riavvio necessario)</string>
+ <string name="tools_installer_success_system">wg e wg-quick installati nella partizione di sistema</string>
+ <string name="tools_installer_title">Installa strumenti di riga di comando</string>
+ <string name="tools_installer_working">Installazione di wg e wg-quick</string>
+ <string name="tools_unavailable_error">Strumenti necessari non disponibili</string>
+ <string name="transfer">Trasferisci</string>
+ <string name="transfer_rx_tx">rx: %1$s, tx: %2$s</string>
+ <string name="transfer_bytes">%d B</string>
+ <string name="transfer_kibibytes">%.2f KiB</string>
+ <string name="transfer_mibibytes">%.2f MiB</string>
+ <string name="transfer_gibibytes">%.2f GiB</string>
+ <string name="transfer_tibibytes">%.2f TiB</string>
+ <string name="tun_create_error">Impossibile creare il dispositivo tun</string>
+ <string name="tunnel_config_error">Impossibile configurare il tunnel (wg-quick ha risposto %d)</string>
+ <string name="tunnel_create_error">Impossibile creare il tunnel: %s</string>
+ <string name="tunnel_create_success">Tunnel “%s” creato correttamente</string>
+ <string name="tunnel_error_already_exists">Il tunnel “%s” esiste già</string>
+ <string name="tunnel_error_invalid_name">Nome non valido</string>
+ <string name="tunnel_list_placeholder">Aggiungi un tunnel usando il pulsante blu</string>
+ <string name="tunnel_name">Nome tunnel</string>
+ <string name="tunnel_on_error">Impossibile attivare il tunnel (wgTurnOn ha risposto %d)</string>
+ <string name="tunnel_rename_error">Impossibile rinominare il tunnel: %s</string>
+ <string name="tunnel_rename_success">Tunnel rinominato correttamente in “%s”</string>
+ <string name="type_name_go_userspace">Spazio utente Go</string>
+ <string name="type_name_kernel_module">Modulo kernel</string>
+ <string name="unknown_error">Errore sconosciuto</string>
+ <string name="version_summary">%1$s backend v%2$s</string>
+ <string name="version_summary_checking">Controllo versione backend %s</string>
+ <string name="version_summary_unknown">Versione %s sconosciuta</string>
+ <string name="version_title">WireGuard per Android v%s</string>
+ <string name="vpn_not_authorized_error">Servizio VPN non autorizzato dall\'utente</string>
+ <string name="vpn_start_error">Impossibile avviare il servizio VPN di Android</string>
+ <string name="zip_export_error">Impossibile esportare i tunnel: %s</string>
+ <string name="zip_export_success">Salvato in “%s”</string>
+ <string name="zip_export_summary">Il file zip verrà salvato nella cartella di download</string>
+ <string name="zip_export_title">Esporta i tunnel in un file zip</string>
+ <string name="key_length_error">Lunghezza chiave non valida</string>
+ <string name="key_contents_error">Caratteri errati nella chiave</string>
+</resources>
diff --git a/ui/src/main/res/values-ja/strings.xml b/ui/src/main/res/values-ja/strings.xml
new file mode 100644
index 0000000..22d1b72
--- /dev/null
+++ b/ui/src/main/res/values-ja/strings.xml
@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <plurals name="delete_error">
+ <item quantity="other">%d トンネルを削除できません: %s</item>
+ </plurals>
+ <plurals name="delete_success">
+ <item quantity="other">%d トンネルを削除しました</item>
+ </plurals>
+ <plurals name="delete_title">
+ <item quantity="other">%d トンネルを選択</item>
+ </plurals>
+ <plurals name="import_partial_success">
+ <item quantity="other">%d 個(全 %d 個)のトンネル設定をインポート</item>
+ </plurals>
+ <plurals name="import_total_success">
+ <item quantity="other">%d 個のトンネル設定をインポート済</item>
+ </plurals>
+ <plurals name="set_excluded_applications">
+ <item quantity="other">除外アプリ %d 個</item>
+ </plurals>
+ <string name="add_peer">ピアを追加する</string>
+ <string name="addresses">Addresses</string>
+ <string name="allowed_ips">Allowed IPs</string>
+ <string name="app_name">WireGuard</string>
+ <string name="bad_config_context">%1$s\'s %2$s</string>
+ <string name="bad_config_context_top_level">%s</string>
+ <string name="bad_config_error">%1$s in %2$s</string>
+ <string name="bad_config_explanation_pka">: 65535未満の正の整数を指定してください</string>
+ <string name="bad_config_explanation_positive_number">: 正の整数を指定</string>
+ <string name="bad_config_explanation_udp_port">: 有効な UDP ポート番号を指定してください</string>
+ <string name="bad_config_reason_invalid_key">無効な鍵</string>
+ <string name="bad_config_reason_invalid_number">無効な数字</string>
+ <string name="bad_config_reason_invalid_value">無効な値</string>
+ <string name="bad_config_reason_missing_attribute">属性が不足しています</string>
+ <string name="bad_config_reason_missing_section">セクションが不足しています</string>
+ <string name="bad_config_reason_missing_value">値が不足しています</string>
+ <string name="bad_config_reason_syntax_error">構文エラー</string>
+ <string name="bad_config_reason_unknown_attribute">未知の属性</string>
+ <string name="bad_config_reason_unknown_section">未知のセクション</string>
+ <string name="bad_config_reason_value_out_of_range">範囲外の値</string>
+ <string name="bad_extension_error">ファイルの拡張子は .conf か .zip です</string>
+ <string name="cancel">キャンセル</string>
+ <string name="config_delete_error">%s の定義を削除できません</string>
+ <string name="config_exists_error">"%s" の定義はすでに存在します</string>
+ <string name="config_file_exists_error">設定ファイル "%s" はすでに存在します</string>
+ <string name="config_not_found_error">設定ファイル "%s" が見つかりません</string>
+ <string name="config_rename_error">設定ファイル "%s" の名前を変更できません</string>
+ <string name="config_save_error">“%1$s” の設定を保存できません: %2$s</string>
+ <string name="config_save_success">"%s" の設定を保存しました</string>
+ <string name="create_activity_title">WireGuard トンネルの作成</string>
+ <string name="create_bin_dir_error">ローカルバイナリディレクトリを作成できません</string>
+ <string name="create_empty">空の状態から作成</string>
+ <string name="create_from_file">ファイル、アーカイブから作成</string>
+ <string name="create_from_qr_code">QRコードから作成</string>
+ <string name="create_output_dir_error">出力ディレクトリを作成できません</string>
+ <string name="create_downloads_file_error">ダウンロードディレクトリにファイルを作成できません</string>
+ <string name="create_temp_dir_error">ローカルに一時ディレクトリを作成できません</string>
+ <string name="create_tunnel">トンネルを作成</string>
+ <string name="dark_theme_summary_off">ライト(日中)テーマを使用中</string>
+ <string name="dark_theme_summary_on">ダーク(夜間)テーマを使用中</string>
+ <string name="dark_theme_title">ダークテーマを使用する</string>
+ <string name="delete">削除</string>
+ <string name="toggle_all">すべての状態を切り替え</string>
+ <string name="dns_servers">DNS サーバ</string>
+ <string name="edit">編集</string>
+ <string name="endpoint">エンドポイント</string>
+ <string name="error_down">トンネル停止時エラー: %s</string>
+ <string name="error_fetching_apps">アプリ一覧取得エラー: %s</string>
+ <string name="error_root">root 権限を取得して再試行してください</string>
+ <string name="error_up">トンネル起動時エラー: %s</string>
+ <string name="exclude_private_ips">プライベート IP アドレスの除外</string>
+ <string name="excluded_applications">除外されたアプリケーション</string>
+ <string name="generate">生成</string>
+ <string name="generic_error">未知のエラー “%s”</string>
+ <string name="hint_automatic">(自動)</string>
+ <string name="hint_generated">(生成済み)</string>
+ <string name="hint_optional">(任意)</string>
+ <string name="hint_random">(ランダム)</string>
+ <string name="illegal_filename_error">不正なファイル名 “%s”</string>
+ <string name="import_error">トンネル設定をインポートできません: %s</string>
+ <string name="import_from_qr_code">QR コードからトンネル設定をインポートできません</string>
+ <string name="import_success">インポートしました “%s”</string>
+ <string name="interface_title">インターフェース</string>
+ <string name="key_length_explanation_base64">: WireGuard base64 鍵は44文字(32バイト)でなければなりません</string>
+ <string name="key_length_explanation_binary">: WireGuard 鍵は32バイトでなければなりません</string>
+ <string name="key_length_explanation_hex">: WireGuard hex 鍵は64文字(32バイト)でなければなりません</string>
+ <string name="listen_port">Listen ポート</string>
+ <string name="log_export_error">ログをエクスポートできません: %s</string>
+ <string name="log_export_success">“%s” に保存しました</string>
+ <string name="log_export_summary">ログはダウンロードフォルダに保存されます</string>
+ <string name="log_export_title">ログのエクスポート</string>
+ <string name="logcat_error">logcat を実行できません: </string>
+ <string name="module_version_error">カーネルモジュールバージョンを特定できません</string>
+ <string name="module_installer_not_found">このデバイス用のモジュールは利用できません</string>
+ <string name="module_installer_initial">実験的カーネルモジュールはパフォーマンスが向上する場合があります</string>
+ <string name="module_installer_success">成功. アプリは5秒後以内に再起動します</string>
+ <string name="module_installer_title">カーネルモジュールをダウンロードしてインストールする</string>
+ <string name="module_installer_working">ダウンロードしてインストールしています…</string>
+ <string name="module_installer_error">失敗しました. 再度実行してみてください</string>
+ <string name="mtu">MTU</string>
+ <string name="name">名前</string>
+ <string name="no_config_error">未設定のままトンネルを起動しようとしています</string>
+ <string name="no_configs_error">設定が見つかりません</string>
+ <string name="no_tunnels_error">トンネルが存在しません</string>
+ <string name="parse_error_generic">文字</string>
+ <string name="parse_error_inet_address">IP アドレス</string>
+ <string name="parse_error_inet_endpoint">エンドポイント</string>
+ <string name="parse_error_inet_network">IP ネットワーク</string>
+ <string name="parse_error_integer">数値</string>
+ <string name="parse_error_reason">%1$s の内容を解読できません “%2$s”</string>
+ <string name="peer">ピア</string>
+ <string name="permission_description">アプリに WireGuard トンネルの制御を許可します。この権限を持つアプリはトンネルの起動停止ができるようになりますが、インターネットトラフィックが意図しない方向に向かう可能性があります。</string>
+ <string name="permission_label">control WireGuard tunnels</string>
+ <string name="persistent_keepalive">持続的キープアライブ</string>
+ <string name="pre_shared_key">事前共有鍵</string>
+ <string name="private_key">秘密鍵</string>
+ <string name="public_key">公開鍵</string>
+ <string name="public_key_description">公開鍵</string>
+ <string name="qr_code_hint">Tip: `qrencode -t ansiutf8 &lt; tunnel.conf` で生成できます</string>
+ <string name="restore_on_boot_summary">起動時に前回有効だったトンネルを起動する</string>
+ <string name="restore_on_boot_title">起動時に復元</string>
+ <string name="save">保存</string>
+ <string name="select_all">すべて選択</string>
+ <string name="set_exclusions">例外を設定</string>
+ <string name="settings">設定</string>
+ <string name="shell_exit_status_read_error">シェルは終了ステータスを取得できません</string>
+ <string name="shell_marker_count_error">シェルは 4 マーカーを期待していますが、 %d を受け取りました</string>
+ <string name="shell_start_error">シェル実行に失敗しました: %d</string>
+ <string name="toggle_error">WireGuard トンネルのトグル時にエラー: %s</string>
+ <string name="tools_installer_already">wg および wg-quick はインストール済みです</string>
+ <string name="tools_installer_failure">コマンドラインツールをインストールできません(rootではない?)</string>
+ <string name="tools_installer_initial">スクリプティングのためのオプションツールのインストール</string>
+ <string name="tools_installer_initial_magisk">スクリプティングのためのオプションツールを Magisk モジュールとしてインストール</string>
+ <string name="tools_installer_initial_system">スクリプティングのためのオプションツールをシステムパーティションにインストール</string>
+ <string name="tools_installer_success_magisk">wg および wg-quick を Magisk モジュールとしてインストール(再起動必須)</string>
+ <string name="tools_installer_success_system">wg および wg-quick をシステムパーティションにインストール</string>
+ <string name="tools_installer_title">コマンドラインツールのインストール</string>
+ <string name="tools_installer_working">wg および wg-quick のインストール</string>
+ <string name="tools_unavailable_error">リクエストされたツールは利用できません</string>
+ <string name="transfer">転送</string>
+ <string name="transfer_rx_tx">受信: %1$s, 送信: %2$s</string>
+ <string name="transfer_bytes">%d B</string>
+ <string name="transfer_kibibytes">%.2f KiB</string>
+ <string name="transfer_mibibytes">%.2f MiB</string>
+ <string name="transfer_gibibytes">%.2f GiB</string>
+ <string name="transfer_tibibytes">%.2f TiB</string>
+ <string name="tun_create_error">tun デバイスを作成できません</string>
+ <string name="tunnel_config_error">トンネルを設定できません (wg-quick が %d を返却)</string>
+ <string name="tunnel_create_error">トンネルを作成できません: %s</string>
+ <string name="tunnel_create_success">トンネル "%s" を作成しました</string>
+ <string name="tunnel_error_already_exists">トンネル “%s” は存在します</string>
+ <string name="tunnel_error_invalid_name">不正な名前</string>
+ <string name="tunnel_list_placeholder">青ボタンでトンネルを追加</string>
+ <string name="tunnel_name">トンネル名</string>
+ <string name="tunnel_on_error">トンネルを有効にできません (wgTurnOn が %d を返却)</string>
+ <string name="tunnel_rename_error">トンネル名を変更できません: %s</string>
+ <string name="tunnel_rename_success">トンネル名を “%s” に変更しました</string>
+ <string name="type_name_go_userspace">Go ユーザースペース</string>
+ <string name="type_name_kernel_module">カーネルモジュール</string>
+ <string name="unknown_error">未知のエラー</string>
+ <string name="version_summary">%1$s backend v%2$s</string>
+ <string name="version_summary_checking">%s バックエンドのバージョンを確認中</string>
+ <string name="version_summary_unknown">未知の %s バージョン</string>
+ <string name="version_title">WireGuard for Android v%s</string>
+ <string name="vpn_not_authorized_error">VPN サービスはユーザに認証されていません</string>
+ <string name="vpn_start_error">Android VPN サービスを開始できません</string>
+ <string name="zip_export_error">トンネル設定をエクスポートできません: %s</string>
+ <string name="zip_export_success">“%s” に保存</string>
+ <string name="zip_export_summary">Zip ファイルはダウンロードフォルダに保存されます</string>
+ <string name="zip_export_title">トンネル設定を zip ファイルにエクスポート</string>
+ <string name="key_length_error">鍵の長さが不正</string>
+ <string name="key_contents_error">鍵に不正な文字があります</string>
+</resources>
diff --git a/ui/src/main/res/values-night/bools.xml b/ui/src/main/res/values-night/bools.xml
new file mode 100644
index 0000000..b02fcc0
--- /dev/null
+++ b/ui/src/main/res/values-night/bools.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <bool name="light_status_bar">false</bool>
+ <bool name="light_navigation_bar">false</bool>
+</resources>
diff --git a/ui/src/main/res/values-night/colors.xml b/ui/src/main/res/values-night/colors.xml
new file mode 100644
index 0000000..314142d
--- /dev/null
+++ b/ui/src/main/res/values-night/colors.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Base palette -->
+ <color name="primary_color">#ff212121</color>
+ <color name="primary_light_color">#ff484848</color>
+ <color name="primary_dark_color">#ff000000</color>
+ <color name="secondary_color">#ff4285f4</color>
+ <color name="secondary_light_color">#ff80b4ff</color>
+ <color name="secondary_dark_color">#ff0059c1</color>
+ <color name="primary_text_color">#ffffffff</color>
+ <color name="secondary_text_color">#ffffffff</color>
+
+ <!-- Theme variables -->
+ <color name="list_multiselect_background">#1aeeeeee</color>
+ <color name="status_bar_color">#21242424</color>
+ <color name="navigation_bar_color">#aa242424</color>
+</resources>
diff --git a/ui/src/main/res/values-ru/strings.xml b/ui/src/main/res/values-ru/strings.xml
new file mode 100644
index 0000000..c8f1b8a
--- /dev/null
+++ b/ui/src/main/res/values-ru/strings.xml
@@ -0,0 +1,179 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <plurals name="delete_error">
+ <item quantity="one">Не удалось удалить %d туннель: %s</item>
+ <item quantity="other">Не удалось удалить %d туннелей: %s</item>
+ </plurals>
+ <plurals name="delete_success">
+ <item quantity="one">Успешно удален %d туннель</item>
+ <item quantity="other">Успешно удалено %d туннелей</item>
+ </plurals>
+ <plurals name="delete_title">
+ <item quantity="one">%d туннель выбран</item>
+ <item quantity="other">%d туннелей выбрано</item>
+ </plurals>
+ <plurals name="import_partial_success">
+ <item quantity="one">Импортирован %d из %d туннелей</item>
+ <item quantity="other">Импортировано %d из %d туннелей</item>
+ </plurals>
+ <plurals name="import_total_success">
+ <item quantity="one">Импортированный %d туннель</item>
+ <item quantity="other">Импортировано %d туннелей</item>
+ </plurals>
+ <plurals name="set_excluded_applications">
+ <item quantity="one">%d Исключенное приложение</item>
+ <item quantity="other">%d Исключенных приложений</item>
+ </plurals>
+ <string name="add_peer">Добавить пира</string>
+ <string name="addresses">IP-адреса</string>
+ <string name="allowed_ips">Разрешенные IP-адреса</string>
+ <string name="app_name">WireGuard</string>
+ <string name="bad_config_context">%1$s из %2$s</string>
+ <string name="bad_config_context_top_level">%s</string>
+ <string name="bad_config_error">%1$s в %2$s</string>
+ <string name="bad_config_explanation_pka">: Должен быть положительный и не больше 65535</string>
+ <string name="bad_config_explanation_positive_number">: Должен быть положительный</string>
+ <string name="bad_config_explanation_udp_port">: Должен быть действительный номер порта UDP</string>
+ <string name="bad_config_reason_invalid_key">Неправильный ключ</string>
+ <string name="bad_config_reason_invalid_number">Неправильный номер</string>
+ <string name="bad_config_reason_invalid_value">Неправильное значение</string>
+ <string name="bad_config_reason_missing_attribute">Несуществующий атрибут</string>
+ <string name="bad_config_reason_missing_section">Несуществующий раздел</string>
+ <string name="bad_config_reason_missing_value">Несуществющее значение</string>
+ <string name="bad_config_reason_syntax_error">Синтаксическая ошибка</string>
+ <string name="bad_config_reason_unknown_attribute">Неизвестный атрибут</string>
+ <string name="bad_config_reason_unknown_section">Неизвестный раздел</string>
+ <string name="bad_config_reason_value_out_of_range">Значение вне диапазона</string>
+ <string name="bad_extension_error">Файл должен быть .conf или .zip</string>
+ <string name="cancel">Отмена</string>
+ <string name="config_delete_error">Не удалось удалить файл конфигурации %s</string>
+ <string name="config_exists_error">Конфигурация для “%s” уже существует</string>
+ <string name="config_file_exists_error">Файл конфигурации “%s” уже существует</string>
+ <string name="config_not_found_error">Файл конфигурации “%s” не найден</string>
+ <string name="config_rename_error">Не удалось переименовать файл конфигурации “%s”</string>
+ <string name="config_save_error">Не удается сохранить конфигурацию для “%1$s”: %2$s</string>
+ <string name="config_save_success">Конфигурация для “%s” успешно сохранена</string>
+ <string name="create_activity_title">Создать WireGuard туннель</string>
+ <string name="create_bin_dir_error">Не удалось создать локальный двоичный каталог</string>
+ <string name="create_empty">Создать вручную</string>
+ <string name="create_from_file">Создать из файла или архива</string>
+ <string name="create_from_qr_code">Создать из QR-кода</string>
+ <string name="create_output_dir_error">Не удалось создать выходной каталог</string>
+ <string name="create_downloads_file_error">Не удалось создать файл в каталоге загрузок</string>
+ <string name="create_temp_dir_error">Не удалось создать временный локальный каталог</string>
+ <string name="create_tunnel">Создать туннель</string>
+ <string name="dark_theme_summary_off">В данный момент используется светлая (дневная) тема</string>
+ <string name="dark_theme_summary_on">В данный момент используется темная (ночная) тема</string>
+ <string name="dark_theme_title">Использовать темную тему</string>
+ <string name="delete">Удалить</string>
+ <string name="toggle_all">Инвертировать все</string>
+ <string name="dns_servers">DNS-серверы</string>
+ <string name="edit">Редактировать</string>
+ <string name="endpoint">Конечная точка</string>
+ <string name="error_down">Ошибка при выходе из туннеля: %s</string>
+ <string name="error_fetching_apps">Ошибка при получении списка приложений: %s</string>
+ <string name="error_root">Пожалуйста, получите root-доступ и попробуйте снова</string>
+ <string name="error_up">Ошибка при запуске туннеля: %s</string>
+ <string name="exclude_private_ips">Исключить частные IP-адреса</string>
+ <string name="excluded_applications">Исключенные приложения</string>
+ <string name="generate">Создать</string>
+ <string name="generic_error">Неизвестная “%s” ошибка</string>
+ <string name="hint_automatic">(авто)</string>
+ <string name="hint_generated">(авто)</string>
+ <string name="hint_optional">(авто)</string>
+ <string name="hint_random">(авто)</string>
+ <string name="illegal_filename_error">Неверное имя файла “%s”</string>
+ <string name="import_error">Не удалось импортировать туннель: %s</string>
+ <string name="import_from_qr_code">Импортировать туннель из QR-кода</string>
+ <string name="import_success">Импортировано “%s”</string>
+ <string name="interface_title">Интерфейс</string>
+ <string name="key_length_explanation_base64">: Ключи WireGuard base64 должны содержать 44 символа (32 байта)</string>
+ <string name="key_length_explanation_binary">: Ключи WireGuard должны быть 32 байта</string>
+ <string name="key_length_explanation_hex">: HEX ключи WireGuard должны содержать 64 символа (32 байта)</string>
+ <string name="listen_port">Порт</string>
+ <string name="log_export_error">Не удалось экспортировать логи: %s</string>
+ <string name="log_export_success">Сохранено в “%s”</string>
+ <string name="log_export_summary">Файл логов будет сохранен в папке загрузок</string>
+ <string name="log_export_title">Экспорт логов в файл</string>
+ <string name="logcat_error">Не удалось запустить logcat: </string>
+ <string name="module_version_error">Не удалось определить версию модуля ядра</string>
+ <string name="module_installer_not_found">Для вашего устройства нет доступных модулей</string>
+ <string name="module_installer_initial">Экспериментальный модуль ядра может улучшить производительность</string>
+ <string name="module_installer_success">Успех. Приложение перезапустится через 5 секунд</string>
+ <string name="module_installer_title">Скачать и установить модуль ядра</string>
+ <string name="module_installer_working">Скачивание и установка…</string>
+ <string name="module_installer_error">Что-то пошло не так. Пожалуйста, попробуйте еще раз</string>
+ <string name="mtu">MTU</string>
+ <string name="name">Имя</string>
+ <string name="no_config_error">Попытка поднять туннель без конфигурации</string>
+ <string name="no_configs_error">Конфигурации не найдены</string>
+ <string name="no_tunnels_error">Туннелей не существует</string>
+ <string name="parse_error_generic">строка</string>
+ <string name="parse_error_inet_address">IP-адрес</string>
+ <string name="parse_error_inet_endpoint">конечная точка</string>
+ <string name="parse_error_inet_network">IP-сеть</string>
+ <string name="parse_error_integer">число</string>
+ <string name="parse_error_reason">Не могу разобрать %1$s “%2$s”</string>
+ <string name="peer">Пир</string>
+ <string name="permission_description">Приложение сможет управлять туннелями WireGuard. Приложения с таким разрешением могут по желанию включать и отключать туннели WireGuard, что может привести к неправильному перенаправлению интернет-трафика.</string>
+ <string name="permission_label">управлять туннелями WireGuard</string>
+ <string name="persistent_keepalive">Постоянное соединение</string>
+ <string name="pre_shared_key">Общий ключ</string>
+ <string name="private_key">Приватный ключ</string>
+ <string name="public_key">Публичный ключ</string>
+ <string name="public_key_description">Публичный ключ</string>
+ <string name="qr_code_hint">Совет: генерировать с `qrencode -t ansiutf8 &lt; tunnel.conf`.</string>
+ <string name="restore_on_boot_summary">Поднимать ранее выбранные туннели при загрузке</string>
+ <string name="restore_on_boot_title">Восстанавливать при загрузке</string>
+ <string name="save">Сохранить</string>
+ <string name="select_all">Выбрать все</string>
+ <string name="set_exclusions">ОК</string>
+ <string name="settings">Настройки</string>
+ <string name="shell_exit_status_read_error">Shell не может прочитать статус выхода</string>
+ <string name="shell_marker_count_error">Shell ожидает 4 маркера, получено %d</string>
+ <string name="shell_start_error">Не удалось запустить Shell: %d</string>
+ <string name="toggle_error">Ошибка переключения туннеля WireGuard: %s</string>
+ <string name="tools_installer_already">wg и wg-quick уже установлены</string>
+ <string name="tools_installer_failure">Не удалось установить инструменты командной строки (нет root?)</string>
+ <string name="tools_installer_initial">Установите дополнительные инструменты для сценариев</string>
+ <string name="tools_installer_initial_magisk">Установите дополнительные инструменты для сценариев в качестве модуля Magisk</string>
+ <string name="tools_installer_initial_system">Установите дополнительные инструменты для сценариев в системный раздел</string>
+ <string name="tools_installer_success_magisk">wg и wg-quick установлены как модуль Magisk (требуется перезагрузка)</string>
+ <string name="tools_installer_success_system">wg и wg-quick установлены в системный раздел</string>
+ <string name="tools_installer_title">Установить инструменты командной строки</string>
+ <string name="tools_installer_working">Установка wg и wg-quick</string>
+ <string name="tools_unavailable_error">Необходимые инструменты недоступны</string>
+ <string name="transfer">Статистика</string>
+ <string name="transfer_rx_tx">Принято: %1$s, Отдано: %2$s</string>
+ <string name="transfer_bytes">%d Б</string>
+ <string name="transfer_kibibytes">%.2f Кб</string>
+ <string name="transfer_mibibytes">%.2f Мб</string>
+ <string name="transfer_gibibytes">%.2f Гб</string>
+ <string name="transfer_tibibytes">%.2f Тб</string>
+ <string name="tun_create_error">Не удалось создать устройство tun</string>
+ <string name="tunnel_config_error">Не удалось настроить туннель (wg-quick вернул %d)</string>
+ <string name="tunnel_create_error">Не удалось создать туннель: %s</string>
+ <string name="tunnel_create_success">Успешно созданный туннель “%s”</string>
+ <string name="tunnel_error_already_exists">Туннель “%s” уже существует</string>
+ <string name="tunnel_error_invalid_name">Неправильное имя</string>
+ <string name="tunnel_list_placeholder">Добавьте туннель с помощью синей кнопки</string>
+ <string name="tunnel_name">Название туннеля</string>
+ <string name="tunnel_on_error">Не удалось включить туннель (wgTurnOn вернул %d)</string>
+ <string name="tunnel_rename_error">Не удалось переименовать туннель: %s</string>
+ <string name="tunnel_rename_success">Туннель успешно переименован в “%s”</string>
+ <string name="type_name_go_userspace">Пользовательское пространство</string>
+ <string name="type_name_kernel_module">Модуль ядра</string>
+ <string name="unknown_error">Неизвестная ошибка</string>
+ <string name="version_summary">%1$s v%2$s</string>
+ <string name="version_summary_checking">Проверка версии %s</string>
+ <string name="version_summary_unknown">Неизвестная версия %s</string>
+ <string name="version_title">WireGuard для Android v%s</string>
+ <string name="vpn_not_authorized_error">VPN-сервис не авторизован пользователем</string>
+ <string name="vpn_start_error">Не удалось запустить службу Android VPN</string>
+ <string name="zip_export_error">Не удалось экспортировать туннели: %s</string>
+ <string name="zip_export_success">Сохранено в “%s”</string>
+ <string name="zip_export_summary">Zip-архив будет сохранен в папке загрузок</string>
+ <string name="zip_export_title">Экспорт туннелей в zip-архив</string>
+ <string name="key_length_error">Неверная длина ключа</string>
+ <string name="key_contents_error">Плохие символы в ключе</string>
+</resources>
diff --git a/ui/src/main/res/values-v27/styles.xml b/ui/src/main/res/values-v27/styles.xml
new file mode 100644
index 0000000..2f4b710
--- /dev/null
+++ b/ui/src/main/res/values-v27/styles.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <style name="AppTheme" parent="Theme.MaterialComponents.DayNight">
+ <item name="colorPrimary">@color/primary_color</item>
+ <item name="colorOnPrimary">@color/color_control_normal</item>
+ <item name="colorPrimaryDark">@color/primary_color</item>
+ <item name="colorPrimaryVariant">@color/primary_light_color</item>
+ <item name="colorSecondary">@color/secondary_color</item>
+ <item name="colorOnSecondary">@color/secondary_text_color</item>
+ <item name="colorSurface">@color/primary_color</item>
+ <item name="colorOnSurface">@color/color_control_normal</item>
+ <item name="colorBackground">@color/primary_color</item>
+ <item name="colorControlNormal">@color/color_control_normal</item>
+ <item name="colorMultiselectActiveBackground">@color/list_multiselect_background</item>
+ <item name="elevationOverlayColor">@color/primary_light_color</item>
+ <item name="elevationOverlayEnabled">true</item>
+ <item name="android:colorBackground">@color/primary_color</item>
+ <item name="android:navigationBarColor">@color/navigation_bar_color</item>
+ <item name="android:statusBarColor">@color/status_bar_color</item>
+ <item name="android:windowLightNavigationBar">@bool/light_navigation_bar</item>
+ <item name="android:windowLightStatusBar">@bool/light_status_bar</item>
+ <item name="android:windowBackground">@color/primary_color</item>
+ <item name="alertDialogTheme">@style/AppTheme.Dialog</item>
+ <item name="materialAlertDialogTheme">@style/AppTheme.Dialog</item>
+ <item name="actionBarPopupTheme">@style/ThemeOverlay.MaterialComponents.ActionBar</item>
+ </style>
+</resources>
diff --git a/ui/src/main/res/values-zh-rCN/strings.xml b/ui/src/main/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000..8f7ab98
--- /dev/null
+++ b/ui/src/main/res/values-zh-rCN/strings.xml
@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <plurals name="delete_error">
+ <item quantity="other">无法删除 %d 项:%s</item>
+ </plurals>
+ <plurals name="delete_success">
+ <item quantity="other">删除了 %d 项</item>
+ </plurals>
+ <plurals name="delete_title">
+ <item quantity="other">已选择 %d 项</item>
+ </plurals>
+ <plurals name="import_partial_success">
+ <item quantity="other">导入了 %d 项,读取到 %d 项</item>
+ </plurals>
+ <plurals name="import_total_success">
+ <item quantity="other">导入了 %d 项</item>
+ </plurals>
+ <plurals name="set_excluded_applications">
+ <item quantity="other">%d 个排除应用</item>
+ </plurals>
+ <string name="add_peer">添加节点</string>
+ <string name="addresses">局域网 IP 地址</string>
+ <string name="allowed_ips">允许的 IP 地址(段)</string>
+ <string name="app_name">WireGuard</string>
+ <string name="bad_config_context">%1$s 的 %2$s 字段</string>
+ <string name="bad_config_context_top_level">%s</string>
+ <string name="bad_config_error">在 %2$s发生了%1$s的问题</string>
+ <string name="bad_config_explanation_pka">:必须为正整数且不超过 65535</string>
+ <string name="bad_config_explanation_positive_number">:必须为正整数</string>
+ <string name="bad_config_explanation_udp_port">:必须为有效的 UDP 端口号</string>
+ <string name="bad_config_reason_invalid_key">密钥无效</string>
+ <string name="bad_config_reason_invalid_number">数字无效</string>
+ <string name="bad_config_reason_invalid_value">数值无效</string>
+ <string name="bad_config_reason_missing_attribute">属性缺失</string>
+ <string name="bad_config_reason_missing_section">节缺失</string>
+ <string name="bad_config_reason_missing_value">数值缺失</string>
+ <string name="bad_config_reason_syntax_error">语法错误</string>
+ <string name="bad_config_reason_unknown_attribute">属性未知</string>
+ <string name="bad_config_reason_unknown_section">节未知</string>
+ <string name="bad_config_reason_value_out_of_range">数值超出范围</string>
+ <string name="bad_extension_error">扩展名必须为 .conf 或 .zip</string>
+ <string name="cancel">取消</string>
+ <string name="config_delete_error">无法删除配置 “%s”</string>
+ <string name="config_exists_error">“%s” 的配置已存在</string>
+ <string name="config_file_exists_error">配置 “%s” 已存在</string>
+ <string name="config_not_found_error">找不到配置 “%s”</string>
+ <string name="config_rename_error">无法重命名配置 “%s”</string>
+ <string name="config_save_error">无法保存 “%1$s” 的配置:%2$s</string>
+ <string name="config_save_success">已保存 “%s” 的配置</string>
+ <string name="create_activity_title">创建 WireGuard 隧道</string>
+ <string name="create_bin_dir_error">无法创建本地二进制文件目录</string>
+ <string name="create_empty">手动配置</string>
+ <string name="create_from_file">导入配置或压缩包</string>
+ <string name="create_from_qr_code">扫描二维码</string>
+ <string name="create_output_dir_error">无法创建输出目录</string>
+ <string name="create_downloads_file_error">无法在下载目录中创建文件</string>
+ <string name="create_temp_dir_error">无法创建本地临时目录</string>
+ <string name="create_tunnel">创建隧道</string>
+ <string name="dark_theme_summary_off">正在使用亮色(白昼)主题</string>
+ <string name="dark_theme_summary_on">正在使用暗色(黑夜)主题</string>
+ <string name="dark_theme_title">使用暗色主题</string>
+ <string name="delete">删除</string>
+ <string name="toggle_all">反选</string>
+ <string name="dns_servers">DNS 服务器</string>
+ <string name="edit">编辑</string>
+ <string name="endpoint">对端地址</string>
+ <string name="error_down">断开连接时出错:%s</string>
+ <string name="error_fetching_apps">获取应用列表时出错:%s</string>
+ <string name="error_root">请获取 root 权限并重试</string>
+ <string name="error_up">建立连接时出错:%s</string>
+ <string name="exclude_private_ips">排除局域网 IP</string>
+ <string name="excluded_applications">排除的应用</string>
+ <string name="generate">生成密钥</string>
+ <string name="generic_error">未知的 “%s” 错误</string>
+ <string name="hint_automatic">(自动)</string>
+ <string name="hint_generated">(生成)</string>
+ <string name="hint_optional">(可选)</string>
+ <string name="hint_random">(随机)</string>
+ <string name="illegal_filename_error">文件名 “%s” 不合法</string>
+ <string name="import_error">无法导入隧道:%s</string>
+ <string name="import_from_qr_code">从二维码导入隧道</string>
+ <string name="import_success">导入了 “%s”</string>
+ <string name="interface_title">接口 / Interface</string>
+ <string name="key_length_explanation_base64">:WireGuard 的 Base64 密钥长度必须为 44 个字符(32 字节)</string>
+ <string name="key_length_explanation_binary">:WireGuard 密钥大小必须为 32 字节</string>
+ <string name="key_length_explanation_hex">:WireGuard 的十六进制密钥长度必须为 64 个字符(32 字节)</string>
+ <string name="listen_port">监听端口</string>
+ <string name="log_export_error">无法导出日志:%s</string>
+ <string name="log_export_success">已保存至 “%s”</string>
+ <string name="log_export_summary">日志文件将保存至下载文件夹</string>
+ <string name="log_export_title">导出日志文件</string>
+ <string name="logcat_error">无法运行 logcat:</string>
+ <string name="module_version_error">无法确定内核模块版本</string>
+ <string name="module_installer_not_found">没有可用于此设备的模块</string>
+ <string name="module_installer_initial">此实验性的内核模块可以提升性能</string>
+ <string name="module_installer_success">安装成功,应用将在 5 秒后重启</string>
+ <string name="module_installer_title">下载并安装内核模块</string>
+ <string name="module_installer_working">正在下载安装...</string>
+ <string name="module_installer_error">发生错误,请重试</string>
+ <string name="mtu">MTU</string>
+ <string name="name">名称</string>
+ <string name="no_config_error">尝试在无配置情况下建立连接</string>
+ <string name="no_configs_error">未找到配置</string>
+ <string name="no_tunnels_error">无隧道</string>
+ <string name="parse_error_generic">字符串</string>
+ <string name="parse_error_inet_address"> IP 地址</string>
+ <string name="parse_error_inet_endpoint">对端地址</string>
+ <string name="parse_error_inet_network"> IP 网络</string>
+ <string name="parse_error_integer">数字</string>
+ <string name="parse_error_reason">无法解析%1$s “%2$s” </string>
+ <string name="peer">节点 / Peer</string>
+ <string name="permission_description">允许一个应用对 WireGuard 隧道进行控制(开启 / 关闭隧道),但可能会误传一些流量</string>
+ <string name="permission_label">控制 WireGuard 隧道</string>
+ <string name="persistent_keepalive">连接保活间隔</string>
+ <string name="pre_shared_key">预共享密钥</string>
+ <string name="private_key">私钥</string>
+ <string name="public_key">公钥</string>
+ <string name="public_key_description">公钥</string>
+ <string name="qr_code_hint">提示:使用命令 `qrencode -t ansiutf8 &lt; tunnel.conf` 生成二维码</string>
+ <string name="restore_on_boot_summary">设备启动时自动开启上一次使用的隧道</string>
+ <string name="restore_on_boot_title">开机自启</string>
+ <string name="save">保存</string>
+ <string name="select_all">全选</string>
+ <string name="set_exclusions">确定</string>
+ <string name="settings">设置</string>
+ <string name="shell_exit_status_read_error">Shell 无法读取退出状态</string>
+ <string name="shell_marker_count_error">Shell 应获取 4 个标记,获取到 %d 个</string>
+ <string name="shell_start_error">Shell 启动失败:%d</string>
+ <string name="toggle_error">切换隧道状态时出错:%s</string>
+ <string name="tools_installer_already">wg 与 wg-quick 已安装</string>
+ <string name="tools_installer_failure">无法安装命令行工具(尚未获取 root 权限?)</string>
+ <string name="tools_installer_initial">安装脚本工具(可选)</string>
+ <string name="tools_installer_initial_magisk">安装脚本工具为 Magisk 模块(可选)</string>
+ <string name="tools_installer_initial_system">安装脚本工具至系统分区(可选)</string>
+ <string name="tools_installer_success_magisk">wg 与 wg-quick 已安装为 Magisk 模块(重启后生效)</string>
+ <string name="tools_installer_success_system">wg 与 wg-quick 已安装至系统分区</string>
+ <string name="tools_installer_title">安装命令行工具</string>
+ <string name="tools_installer_working">正在安装 wg 与 wg-quick...</string>
+ <string name="tools_unavailable_error">所需工具不可用</string>
+ <string name="transfer">流量</string>
+ <string name="transfer_rx_tx">接收:%1$s,发送:%2$s</string>
+ <string name="transfer_bytes">%d B</string>
+ <string name="transfer_kibibytes">%.2f KiB</string>
+ <string name="transfer_mibibytes">%.2f MiB</string>
+ <string name="transfer_gibibytes">%.2f GiB</string>
+ <string name="transfer_tibibytes">%.2f TiB</string>
+ <string name="tun_create_error">无法创建 tun 设备</string>
+ <string name="tunnel_config_error">无法配置隧道(wg-quick returned %d)</string>
+ <string name="tunnel_create_error">无法创建隧道:%s</string>
+ <string name="tunnel_create_success">成功创建隧道 “%s”</string>
+ <string name="tunnel_error_already_exists">名称 “%s” 已存在</string>
+ <string name="tunnel_error_invalid_name">名称无效</string>
+ <string name="tunnel_list_placeholder">点击下方按钮添加隧道</string>
+ <string name="tunnel_name">隧道名称</string>
+ <string name="tunnel_on_error">无法开启隧道(wgTurnOn returned %d)</string>
+ <string name="tunnel_rename_error">无法重命名隧道:%s</string>
+ <string name="tunnel_rename_success">隧道已重命名为 “%s”</string>
+ <string name="type_name_go_userspace">Go userspace</string>
+ <string name="type_name_kernel_module">Kernel module</string>
+ <string name="unknown_error">未知错误</string>
+ <string name="version_summary">%1$s backend v%2$s</string>
+ <string name="version_summary_checking">正在检查 %s backend 版本</string>
+ <string name="version_summary_unknown">未知的 %s 版本</string>
+ <string name="version_title">WireGuard for Android v%s</string>
+ <string name="vpn_not_authorized_error">用户未授权 VPN 服务</string>
+ <string name="vpn_start_error">无法启动 Android VPN 服务</string>
+ <string name="zip_export_error">无法导出隧道配置:%s</string>
+ <string name="zip_export_success">已保存至 “%s”</string>
+ <string name="zip_export_summary">zip 压缩包将保存至下载文件夹</string>
+ <string name="zip_export_title">导出隧道配置为 zip 压缩包</string>
+ <string name="key_length_error">密钥长度错误</string>
+ <string name="key_contents_error">密钥中含有错误字符</string>
+</resources>
diff --git a/ui/src/main/res/values/attrs.xml b/ui/src/main/res/values/attrs.xml
new file mode 100644
index 0000000..68a8db0
--- /dev/null
+++ b/ui/src/main/res/values/attrs.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <declare-styleable name="Multiselected">
+ <attr name="state_multiselected" format="boolean" />
+ <attr name="colorMultiselectActiveBackground" format="reference|color"/>
+ </declare-styleable>
+
+ <declare-styleable name="custom_color">
+ <attr name="colorBackground" format="reference|color"/>
+ </declare-styleable>
+</resources>
diff --git a/ui/src/main/res/values/bools.xml b/ui/src/main/res/values/bools.xml
new file mode 100644
index 0000000..288f85a
--- /dev/null
+++ b/ui/src/main/res/values/bools.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <bool name="light_status_bar">true</bool>
+ <bool name="light_navigation_bar">true</bool>
+</resources>
diff --git a/ui/src/main/res/values/colors.xml b/ui/src/main/res/values/colors.xml
new file mode 100644
index 0000000..06bcd14
--- /dev/null
+++ b/ui/src/main/res/values/colors.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:tools="http://schemas.android.com/tools">
+ <!-- Base palette -->
+ <color name="primary_color">#ffffffff</color>
+ <color name="primary_light_color">#ffffffff</color>
+ <color name="primary_dark_color">#ffcccccc</color>
+ <color name="secondary_color">#ff1a73e8</color>
+ <color name="secondary_light_color">#ff1a73e8</color>
+ <color name="secondary_dark_color">#ff1a73e8</color>
+ <color name="primary_text_color">#ff000000</color>
+ <color name="secondary_text_color">#ffffffff</color>
+
+ <!-- Theme variables -->
+ <color name="color_control_normal">@color/primary_text_color</color>
+ <color name="status_bar_color">@color/primary_color</color>
+ <color name="navigation_bar_color">#aaffffff</color>
+ <color name="list_multiselect_background">#ffeeeeee</color>
+ <color name="mtrl_textinput_default_box_stroke_color" tools:override="true">@color/secondary_color</color>
+ <color name="white">#ffffffff</color>
+
+</resources>
diff --git a/ui/src/main/res/values/dimens.xml b/ui/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..c6abf8e
--- /dev/null
+++ b/ui/src/main/res/values/dimens.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <dimen name="fab_margin">16dp</dimen>
+ <dimen name="extra_margin">12dp</dimen>
+ <dimen name="bottom_sheet_item_height">56dp</dimen>
+ <dimen name="normal_margin">8dp</dimen>
+ <dimen name="bottom_sheet_top_padding">8dp</dimen>
+ <dimen name="bottom_sheet_icon_padding">16dp</dimen>
+</resources>
diff --git a/ui/src/main/res/values/ic_launcher_background.xml b/ui/src/main/res/values/ic_launcher_background.xml
new file mode 100644
index 0000000..f8bad52
--- /dev/null
+++ b/ui/src/main/res/values/ic_launcher_background.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <color name="ic_launcher_background">#871719</color>
+</resources> \ No newline at end of file
diff --git a/ui/src/main/res/values/ids.xml b/ui/src/main/res/values/ids.xml
new file mode 100644
index 0000000..7f34f80
--- /dev/null
+++ b/ui/src/main/res/values/ids.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <item name="item_change_listener" type="id" />
+</resources>
diff --git a/ui/src/main/res/values/strings.xml b/ui/src/main/res/values/strings.xml
new file mode 100644
index 0000000..45964ee
--- /dev/null
+++ b/ui/src/main/res/values/strings.xml
@@ -0,0 +1,179 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <plurals name="delete_error">
+ <item quantity="one">Unable to delete %d tunnel: %s</item>
+ <item quantity="other">Unable to delete %d tunnels: %s</item>
+ </plurals>
+ <plurals name="delete_success">
+ <item quantity="one">Successfully deleted %d tunnel</item>
+ <item quantity="other">Successfully deleted %d tunnels</item>
+ </plurals>
+ <plurals name="delete_title">
+ <item quantity="one">%d tunnel selected</item>
+ <item quantity="other">%d tunnels selected</item>
+ </plurals>
+ <plurals name="import_partial_success">
+ <item quantity="one">Imported %d of %d tunnels</item>
+ <item quantity="other">Imported %d of %d tunnels</item>
+ </plurals>
+ <plurals name="import_total_success">
+ <item quantity="one">Imported %d tunnel</item>
+ <item quantity="other">Imported %d tunnels</item>
+ </plurals>
+ <plurals name="set_excluded_applications">
+ <item quantity="one">%d Excluded Application</item>
+ <item quantity="other">%d Excluded Applications</item>
+ </plurals>
+ <string name="add_peer">Add peer</string>
+ <string name="addresses">Addresses</string>
+ <string name="allowed_ips">Allowed IPs</string>
+ <string name="app_name">WireGuard</string>
+ <string name="bad_config_context">%1$s\'s %2$s</string>
+ <string name="bad_config_context_top_level">%s</string>
+ <string name="bad_config_error">%1$s in %2$s</string>
+ <string name="bad_config_explanation_pka">: Must be positive and no more than 65535</string>
+ <string name="bad_config_explanation_positive_number">: Must be positive</string>
+ <string name="bad_config_explanation_udp_port">: Must be a valid UDP port number</string>
+ <string name="bad_config_reason_invalid_key">Invalid key</string>
+ <string name="bad_config_reason_invalid_number">Invalid number</string>
+ <string name="bad_config_reason_invalid_value">Invalid value</string>
+ <string name="bad_config_reason_missing_attribute">Missing attribute</string>
+ <string name="bad_config_reason_missing_section">Missing section</string>
+ <string name="bad_config_reason_missing_value">Missing value</string>
+ <string name="bad_config_reason_syntax_error">Syntax error</string>
+ <string name="bad_config_reason_unknown_attribute">Unknown attribute</string>
+ <string name="bad_config_reason_unknown_section">Unknown section</string>
+ <string name="bad_config_reason_value_out_of_range">Value out of range</string>
+ <string name="bad_extension_error">File must be .conf or .zip</string>
+ <string name="cancel">Cancel</string>
+ <string name="config_delete_error">Cannot delete configuration file %s</string>
+ <string name="config_exists_error">Configuration for “%s” already exists</string>
+ <string name="config_file_exists_error">Configuration file “%s” already exists</string>
+ <string name="config_not_found_error">Configuration file “%s” not found</string>
+ <string name="config_rename_error">Cannot rename configuration file “%s”</string>
+ <string name="config_save_error">Cannot save configuration for “%1$s”: %2$s</string>
+ <string name="config_save_success">Successfully saved configuration for “%s”</string>
+ <string name="create_activity_title">Create WireGuard Tunnel</string>
+ <string name="create_bin_dir_error">Cannot create local binary directory</string>
+ <string name="create_empty">Create from scratch</string>
+ <string name="create_from_file">Create from file or archive</string>
+ <string name="create_from_qr_code">Create from QR code</string>
+ <string name="create_output_dir_error">Cannot create output directory</string>
+ <string name="create_downloads_file_error">Cannot create file in downloads directory</string>
+ <string name="create_temp_dir_error">Cannot create local temporary directory</string>
+ <string name="create_tunnel">Create Tunnel</string>
+ <string name="dark_theme_summary_off">Currently using light (day) theme</string>
+ <string name="dark_theme_summary_on">Currently using dark (night) theme</string>
+ <string name="dark_theme_title">Use dark theme</string>
+ <string name="delete">Delete</string>
+ <string name="toggle_all">Toggle All</string>
+ <string name="dns_servers">DNS servers</string>
+ <string name="edit">Edit</string>
+ <string name="endpoint">Endpoint</string>
+ <string name="error_down">Error bringing down tunnel: %s</string>
+ <string name="error_fetching_apps">Error fetching apps list: %s</string>
+ <string name="error_root">Please obtain root access and try again</string>
+ <string name="error_up">Error bringing up tunnel: %s</string>
+ <string name="exclude_private_ips">Exclude private IPs</string>
+ <string name="excluded_applications">Excluded Applications</string>
+ <string name="generate">Generate</string>
+ <string name="generic_error">Unknown “%s” error</string>
+ <string name="hint_automatic">(auto)</string>
+ <string name="hint_generated">(generated)</string>
+ <string name="hint_optional">(optional)</string>
+ <string name="hint_random">(random)</string>
+ <string name="illegal_filename_error">Illegal file name “%s”</string>
+ <string name="import_error">Unable to import tunnel: %s</string>
+ <string name="import_from_qr_code">Import Tunnel from QR Code</string>
+ <string name="import_success">Imported “%s”</string>
+ <string name="interface_title">Interface</string>
+ <string name="key_length_explanation_base64">: WireGuard base64 keys must be 44 characters (32 bytes)</string>
+ <string name="key_length_explanation_binary">: WireGuard keys must be 32 bytes</string>
+ <string name="key_length_explanation_hex">: WireGuard hex keys must be 64 characters (32 bytes)</string>
+ <string name="listen_port">Listen port</string>
+ <string name="log_export_error">Unable to export log: %s</string>
+ <string name="log_export_success">Saved to “%s”</string>
+ <string name="log_export_summary">Log file will be saved to downloads folder</string>
+ <string name="log_export_title">Export log file</string>
+ <string name="logcat_error">Unable to run logcat: </string>
+ <string name="module_version_error">Unable to determine kernel module version</string>
+ <string name="module_installer_not_found">No modules are available for your device</string>
+ <string name="module_installer_initial">The experimental kernel module can improve performance</string>
+ <string name="module_installer_success">Success. The application will restart in 5 seconds</string>
+ <string name="module_installer_title">Download and install kernel module</string>
+ <string name="module_installer_working">Downloading and installing…</string>
+ <string name="module_installer_error">Something went wrong. Please try again</string>
+ <string name="mtu">MTU</string>
+ <string name="name">Name</string>
+ <string name="no_config_error">Trying to bring up a tunnel with no config</string>
+ <string name="no_configs_error">No configurations found</string>
+ <string name="no_tunnels_error">No tunnels exist</string>
+ <string name="parse_error_generic">string</string>
+ <string name="parse_error_inet_address">IP address</string>
+ <string name="parse_error_inet_endpoint">endpoint</string>
+ <string name="parse_error_inet_network">IP network</string>
+ <string name="parse_error_integer">number</string>
+ <string name="parse_error_reason">Cannot parse %1$s “%2$s”</string>
+ <string name="peer">Peer</string>
+ <string name="permission_description">Allows an app to control WireGuard tunnels. Apps with this permission may enable and disable WireGuard tunnels at will, potentially misdirecting Internet traffic.</string>
+ <string name="permission_label">control WireGuard tunnels</string>
+ <string name="persistent_keepalive">Persistent keepalive</string>
+ <string name="pre_shared_key">Pre-shared key</string>
+ <string name="private_key">Private key</string>
+ <string name="public_key">Public key</string>
+ <string name="public_key_description">Public key</string>
+ <string name="qr_code_hint">Tip: generate with `qrencode -t ansiutf8 &lt; tunnel.conf`.</string>
+ <string name="restore_on_boot_summary">Bring up previously-enabled tunnels on boot</string>
+ <string name="restore_on_boot_title">Restore on boot</string>
+ <string name="save">Save</string>
+ <string name="select_all">Select all</string>
+ <string name="set_exclusions">Set Exclusions</string>
+ <string name="settings">Settings</string>
+ <string name="shell_exit_status_read_error">Shell cannot read exit status</string>
+ <string name="shell_marker_count_error">Shell expected 4 markers, received %d</string>
+ <string name="shell_start_error">Shell failed to start: %d</string>
+ <string name="toggle_error">Error toggling WireGuard tunnel: %s</string>
+ <string name="tools_installer_already">wg and wg-quick are already installed</string>
+ <string name="tools_installer_failure">Unable to install command-line tools (no root?)</string>
+ <string name="tools_installer_initial">Install optional tools for scripting</string>
+ <string name="tools_installer_initial_magisk">Install optional tools for scripting as Magisk module</string>
+ <string name="tools_installer_initial_system">Install optional tools for scripting into the system partition</string>
+ <string name="tools_installer_success_magisk">wg and wg-quick installed as a Magisk module (reboot required)</string>
+ <string name="tools_installer_success_system">wg and wg-quick installed into the system partition</string>
+ <string name="tools_installer_title">Install command line tools</string>
+ <string name="tools_installer_working">Installing wg and wg-quick</string>
+ <string name="tools_unavailable_error">Required tools unavailable</string>
+ <string name="transfer">Transfer</string>
+ <string name="transfer_rx_tx">rx: %1$s, tx: %2$s</string>
+ <string name="transfer_bytes">%d B</string>
+ <string name="transfer_kibibytes">%.2f KiB</string>
+ <string name="transfer_mibibytes">%.2f MiB</string>
+ <string name="transfer_gibibytes">%.2f GiB</string>
+ <string name="transfer_tibibytes">%.2f TiB</string>
+ <string name="tun_create_error">Unable to create tun device</string>
+ <string name="tunnel_config_error">Unable to configure tunnel (wg-quick returned %d)</string>
+ <string name="tunnel_create_error">Unable to create tunnel: %s</string>
+ <string name="tunnel_create_success">Successfully created tunnel “%s”</string>
+ <string name="tunnel_error_already_exists">Tunnel “%s” already exists</string>
+ <string name="tunnel_error_invalid_name">Invalid name</string>
+ <string name="tunnel_list_placeholder">Add a tunnel using the blue button</string>
+ <string name="tunnel_name">Tunnel Name</string>
+ <string name="tunnel_on_error">Unable to turn tunnel on (wgTurnOn returned %d)</string>
+ <string name="tunnel_rename_error">Unable to rename tunnel: %s</string>
+ <string name="tunnel_rename_success">Successfully renamed tunnel to “%s”</string>
+ <string name="type_name_go_userspace">Go userspace</string>
+ <string name="type_name_kernel_module">Kernel module</string>
+ <string name="unknown_error">Unknown error</string>
+ <string name="version_summary">%1$s backend v%2$s</string>
+ <string name="version_summary_checking">Checking %s backend version</string>
+ <string name="version_summary_unknown">Unknown %s version</string>
+ <string name="version_title">WireGuard for Android v%s</string>
+ <string name="vpn_not_authorized_error">VPN service not authorized by user</string>
+ <string name="vpn_start_error">Unable to start Android VPN service</string>
+ <string name="zip_export_error">Unable to export tunnels: %s</string>
+ <string name="zip_export_success">Saved to “%s”</string>
+ <string name="zip_export_summary">Zip file will be saved to downloads folder</string>
+ <string name="zip_export_title">Export tunnels to zip file</string>
+ <string name="key_length_error">Incorrect key length</string>
+ <string name="key_contents_error">Bad characters in key</string>
+</resources>
diff --git a/ui/src/main/res/values/styles.xml b/ui/src/main/res/values/styles.xml
new file mode 100644
index 0000000..f5af8bc
--- /dev/null
+++ b/ui/src/main/res/values/styles.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <style name="AppTheme" parent="Theme.MaterialComponents.DayNight">
+ <item name="colorPrimary">@color/primary_color</item>
+ <item name="colorOnPrimary">@color/color_control_normal</item>
+ <item name="colorPrimaryDark">@color/primary_color</item>
+ <item name="colorPrimaryVariant">@color/primary_light_color</item>
+ <item name="colorSecondary">@color/secondary_color</item>
+ <item name="colorOnSecondary">@color/secondary_text_color</item>
+ <item name="colorSurface">@color/primary_color</item>
+ <item name="colorOnSurface">@color/color_control_normal</item>
+ <item name="colorBackground">@color/primary_color</item>
+ <item name="colorMultiselectActiveBackground">@color/list_multiselect_background</item>
+ <item name="colorControlNormal">@color/color_control_normal</item>
+ <item name="elevationOverlayColor">@color/primary_light_color</item>
+ <item name="elevationOverlayEnabled">true</item>
+ <item name="android:statusBarColor">@color/status_bar_color</item>
+ <item name="android:windowBackground">@color/primary_color</item>
+ <item name="alertDialogTheme">@style/AppTheme.Dialog</item>
+ <item name="materialAlertDialogTheme">@style/AppTheme.Dialog</item>
+ <item name="actionBarPopupTheme">@style/ThemeOverlay.MaterialComponents.ActionBar</item>
+ </style>
+
+ <style name="AppTheme.Dialog" parent="Theme.MaterialComponents.DayNight.Dialog.Alert">
+ <item name="colorPrimary">@color/secondary_color</item>
+ <item name="colorSecondary">@color/secondary_color</item>
+ <item name="android:windowBackground">?attr/colorBackground</item>
+ </style>
+
+ <style name="BottomSheetDialogTheme" parent="ThemeOverlay.MaterialComponents.BottomSheetDialog">
+ <item name="android:windowIsFloating">false</item>
+ <item name="android:navigationBarColor">?attr/colorBackground</item>
+ <item name="android:statusBarColor">@android:color/transparent</item>
+ <item name="android:windowTranslucentNavigation">false</item>
+ <item name="android:windowIsTranslucent">false</item>
+ <item name="android:backgroundDimEnabled">true</item>
+ <item name="android:backgroundDimAmount">0.5</item>
+ <item name="android:windowTranslucentStatus">false</item>
+ <item name="android:colorBackground">@android:color/transparent</item>
+ </style>
+
+ <style name="NoBackgroundTheme" parent="AppTheme">
+ <item name="android:windowIsTranslucent">true</item>
+ <item name="android:windowContentOverlay">@null</item>
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:windowActionBar">false</item>
+ <item name="android:windowBackground">@android:color/transparent</item>
+ <item name="android:background">@android:color/transparent</item>
+ <item name="colorPrimaryDark">@android:color/transparent</item>
+ <item name="android:backgroundDimEnabled">true</item>
+ <item name="android:windowEnterAnimation">@android:anim/fade_in</item>
+ <item name="android:windowExitAnimation">@android:anim/fade_out</item>
+ </style>
+
+</resources>
diff --git a/ui/src/main/res/xml/preferences.xml b/ui/src/main/res/xml/preferences.xml
new file mode 100644
index 0000000..9c09ae8
--- /dev/null
+++ b/ui/src/main/res/xml/preferences.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+ <com.wireguard.android.preference.VersionPreference android:icon="@mipmap/ic_launcher" />
+ <CheckBoxPreference
+ android:defaultValue="false"
+ android:key="restore_on_boot"
+ android:summary="@string/restore_on_boot_summary"
+ android:title="@string/restore_on_boot_title" />
+ <com.wireguard.android.preference.ModuleDownloaderPreference android:key="module_downloader" />
+ <com.wireguard.android.preference.ToolsInstallerPreference android:key="tools_installer" />
+ <com.wireguard.android.preference.ZipExporterPreference />
+ <com.wireguard.android.preference.LogExporterPreference />
+ <CheckBoxPreference
+ android:defaultValue="false"
+ android:key="dark_theme"
+ android:summaryOff="@string/dark_theme_summary_off"
+ android:summaryOn="@string/dark_theme_summary_on"
+ android:title="@string/dark_theme_title" />
+</androidx.preference.PreferenceScreen>