diff --git a/uhabits-android/src/main/AndroidManifest.xml b/uhabits-android/src/main/AndroidManifest.xml
index 3b0851207..6e52cd176 100644
--- a/uhabits-android/src/main/AndroidManifest.xml
+++ b/uhabits-android/src/main/AndroidManifest.xml
@@ -79,6 +79,14 @@
android:value=".activities.habits.list.ListHabitsActivity" />
+
+
+
+
+ *
+ * This file is part of Loop Habit Tracker.
+ *
+ * Loop Habit Tracker is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or (at your
+ * option) any later version.
+ *
+ * Loop Habit Tracker is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see .
+ */
+
+package org.isoron.uhabits.activities.sync
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.widget.EditText
+import androidx.appcompat.app.AlertDialog
+import androidx.appcompat.app.AppCompatActivity
+import org.isoron.uhabits.HabitsApplication
+import org.isoron.uhabits.R
+import org.isoron.uhabits.activities.AndroidThemeSwitcher
+import org.isoron.uhabits.core.models.PaletteColor
+import org.isoron.uhabits.databinding.SyncActivityBinding
+import org.isoron.uhabits.utils.setupToolbar
+
+class SyncActivity : AppCompatActivity() {
+
+ private lateinit var binding: SyncActivityBinding
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ val component = (application as HabitsApplication).component
+ val themeSwitcher = AndroidThemeSwitcher(this, component.preferences)
+ themeSwitcher.apply()
+
+ binding = SyncActivityBinding.inflate(LayoutInflater.from(this))
+ binding.root.setupToolbar(
+ toolbar = binding.toolbar,
+ title = resources.getString(R.string.device_sync),
+ color = PaletteColor(11),
+ theme = themeSwitcher.currentTheme,
+ )
+ binding.generateButton.setOnClickListener { onGenerateCode() }
+ binding.enterButton.setOnClickListener {
+ val et = EditText(this)
+ AlertDialog.Builder(this)
+ .setTitle(R.string.sync_code)
+ .setView(et)
+ .setPositiveButton(R.string.save) { _, _ ->
+ onEnterCode(et.text.toString())
+ }
+ .show()
+ }
+ binding.disableButton.setOnClickListener {
+ AlertDialog.Builder(this)
+ .setTitle(R.string.disable_sync)
+ .setMessage(R.string.disable_sync_description)
+ .setPositiveButton(R.string.disable) { _, _ ->
+ onDisableSync()
+ }
+ .setNegativeButton(R.string.keep_enabled) { dialog, _ ->
+ dialog.dismiss()
+ }
+ .show()
+ }
+
+ setContentView(binding.root)
+ }
+
+ private fun onGenerateCode() {
+ showCodeScreen()
+ }
+
+ private fun onEnterCode(code: String) {
+ showCodeScreen()
+ }
+
+ private fun onDisableSync() {
+ showIntroScreen()
+ }
+
+ private fun showCodeScreen() {
+ binding.introGroup.visibility = View.GONE
+ binding.codeGroup.visibility = View.VISIBLE
+ }
+
+ private fun showIntroScreen() {
+ binding.introGroup.visibility = View.VISIBLE
+ binding.codeGroup.visibility = View.GONE
+ }
+}
diff --git a/uhabits-android/src/main/res/drawable/ic_sync_dark.xml b/uhabits-android/src/main/res/drawable/ic_sync_dark.xml
new file mode 100644
index 000000000..833e710c8
--- /dev/null
+++ b/uhabits-android/src/main/res/drawable/ic_sync_dark.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uhabits-android/src/main/res/drawable/ic_sync_light.xml b/uhabits-android/src/main/res/drawable/ic_sync_light.xml
new file mode 100644
index 000000000..fbe538b0a
--- /dev/null
+++ b/uhabits-android/src/main/res/drawable/ic_sync_light.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uhabits-android/src/main/res/layout/sync_activity.xml b/uhabits-android/src/main/res/layout/sync_activity.xml
new file mode 100644
index 000000000..31e53dd93
--- /dev/null
+++ b/uhabits-android/src/main/res/layout/sync_activity.xml
@@ -0,0 +1,162 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uhabits-android/src/main/res/values/attrs.xml b/uhabits-android/src/main/res/values/attrs.xml
index b00eaf69b..98db6f2fd 100644
--- a/uhabits-android/src/main/res/values/attrs.xml
+++ b/uhabits-android/src/main/res/values/attrs.xml
@@ -43,6 +43,7 @@
+
diff --git a/uhabits-android/src/main/res/values/strings.xml b/uhabits-android/src/main/res/values/strings.xml
index 75d7d88a7..e9088b636 100644
--- a/uhabits-android/src/main/res/values/strings.xml
+++ b/uhabits-android/src/main/res/values/strings.xml
@@ -232,4 +232,18 @@
No app was found to support this action
Extend day a few hours past midnight
Wait until 3:00 AM to show a new day. Useful if you typically go to sleep after midnight. Requires app restart.
+ Device sync
+ Configure device sync
+ Synchronize data across multiple devices. When enabled, an end-to-end encrypted copy of your data will be uploaded to Loop Habit Tracker servers.
+ Device sync allows you to keep your data synchronized across multiple devices. To get started, generate a new sync code below, install Loop Habit Tracker in another device, then type the generated code there.
+ When sync is enabled, an end-to-end encrypted copy of your data will be uploaded to Loop Habit Tracker servers. See privacy policy for more details.
+ Generate new code
+ Enter existing code
+ Device sync is enabled. To get started, install Loop in another device, then type the following code there.
+ Sync code
+ Disable sync
+ Are you sure you want to disable sync on this device? This will not delete any data from any of your devices, but the current device will no longer be kept in sync with the others. If you disable sync from all devices, your data will be deleted from our servers in 30 days.
+ Disable
+ Keep enabled
+ Last sync
diff --git a/uhabits-android/src/main/res/values/styles.xml b/uhabits-android/src/main/res/values/styles.xml
index 147d05d24..6752ed646 100644
--- a/uhabits-android/src/main/res/values/styles.xml
+++ b/uhabits-android/src/main/res/values/styles.xml
@@ -45,6 +45,7 @@
- @drawable/ic_action_unarchive_dark
- @drawable/ic_arrow_up_light
- @drawable/ic_arrow_down_light
+ - @drawable/ic_sync_light
- @color/white
- @color/grey_300
- @color/grey_350
@@ -89,6 +90,7 @@
- @drawable/ic_action_unarchive_dark
- @drawable/ic_arrow_up_dark
- @drawable/ic_arrow_down_dark
+ - @drawable/ic_sync_dark
- @color/grey_900
- @color/grey_800
- @color/grey_750
diff --git a/uhabits-android/src/main/res/xml/preferences.xml b/uhabits-android/src/main/res/xml/preferences.xml
index 89ab445f9..b7dafafc7 100644
--- a/uhabits-android/src/main/res/xml/preferences.xml
+++ b/uhabits-android/src/main/res/xml/preferences.xml
@@ -114,6 +114,24 @@
+
+
+
+
+
+
+
+
+