From 23f2978a64dae614041b9dba2498f2ffccf36e9c Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Sun, 22 Nov 2020 15:39:08 -0600 Subject: [PATCH] Add sync preferences to settings screen --- .../activities/settings/SettingsFragment.java | 38 ++++++--- .../uhabits/activities/sync/SyncActivity.kt | 29 +++++-- .../isoron/uhabits/intents/IntentFactory.kt | 6 +- .../preferences/SharedPreferencesStorage.kt | 2 - .../src/main/res/values/constants.xml | 1 + .../src/main/res/values/strings.xml | 6 +- .../src/main/res/xml/preferences.xml | 27 ++++-- .../uhabits/core/preferences/Preferences.java | 82 +++++-------------- .../core/preferences/PreferencesTest.java | 31 ------- 9 files changed, 101 insertions(+), 121 deletions(-) diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/settings/SettingsFragment.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/settings/SettingsFragment.java index 7f9430b7b..1faca385f 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/settings/SettingsFragment.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/settings/SettingsFragment.java @@ -26,17 +26,15 @@ import android.os.*; import android.provider.*; import android.util.*; -import androidx.annotation.Nullable; -import androidx.preference.ListPreference; -import androidx.preference.Preference; -import androidx.preference.PreferenceCategory; -import androidx.preference.PreferenceFragmentCompat; +import androidx.annotation.*; +import androidx.preference.*; import org.isoron.uhabits.R; import org.isoron.uhabits.*; import org.isoron.uhabits.core.preferences.*; import org.isoron.uhabits.core.ui.*; import org.isoron.uhabits.core.utils.*; +import org.isoron.uhabits.intents.*; import org.isoron.uhabits.notifications.*; import org.isoron.uhabits.widgets.*; @@ -47,7 +45,7 @@ import static android.os.Build.VERSION.*; import static org.isoron.uhabits.activities.habits.list.ListHabitsScreenKt.*; public class SettingsFragment extends PreferenceFragmentCompat - implements SharedPreferences.OnSharedPreferenceChangeListener + implements SharedPreferences.OnSharedPreferenceChangeListener { private static int RINGTONE_REQUEST_CODE = 1; @@ -55,7 +53,7 @@ public class SettingsFragment extends PreferenceFragmentCompat private RingtoneManager ringtoneManager; - @Nullable + @NonNull private Preferences prefs; @Nullable @@ -93,6 +91,7 @@ public class SettingsFragment extends PreferenceFragmentCompat setResultOnPreferenceClick("exportDB", RESULT_EXPORT_DB); setResultOnPreferenceClick("repairDB", RESULT_REPAIR_DB); setResultOnPreferenceClick("bugReport", RESULT_BUG_REPORT); + } @Override @@ -142,24 +141,31 @@ public class SettingsFragment extends PreferenceFragmentCompat sharedPrefs = getPreferenceManager().getSharedPreferences(); sharedPrefs.registerOnSharedPreferenceChangeListener(this); - if (prefs != null && !prefs.isDeveloper()) + if (!prefs.isDeveloper()) { PreferenceCategory devCategory = - (PreferenceCategory) findPreference("devCategory"); + (PreferenceCategory) findPreference("devCategory"); devCategory.removeAll(); devCategory.setVisible(false); } updateWeekdayPreference(); + updateSyncPreferences(); // Temporarily disable this; we now always ask findPreference("reminderSound").setVisible(false); findPreference("pref_snooze_interval").setVisible(false); } + private void updateSyncPreferences() + { + findPreference("pref_sync_base_url").setSummary(prefs.getSyncBaseURL()); + findPreference("pref_sync_key").setSummary(prefs.getSyncKey()); + findPreference("pref_sync_display").setVisible(prefs.isSyncEnabled()); + } + private void updateWeekdayPreference() { - if (prefs == null) return; ListPreference weekdayPref = (ListPreference) findPreference("pref_first_weekday"); int currentFirstWeekday = prefs.getFirstWeekday(); String[] dayNames = DateUtils.getLongWeekdayNames(Calendar.SATURDAY); @@ -179,8 +185,18 @@ public class SettingsFragment extends PreferenceFragmentCompat Log.d("SettingsFragment", "updating widgets"); widgetUpdater.updateWidgets(); } - if (key.equals("pref_first_weekday")) updateWeekdayPreference(); + if (key.equals("pref_sync_enabled")) + { + Context context = getActivity(); + if (prefs.isSyncEnabled()) + { + Intent intent = new IntentFactory().startSyncActivity(context); + context.startActivity(intent); + } + } BackupManager.dataChanged("org.isoron.uhabits"); + updateWeekdayPreference(); + updateSyncPreferences(); } private void setResultOnPreferenceClick(String key, final int result) diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/sync/SyncActivity.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/sync/SyncActivity.kt index a4b9e2fa4..231a2a467 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/sync/SyncActivity.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/sync/SyncActivity.kt @@ -33,6 +33,7 @@ import org.isoron.androidbase.utils.* import org.isoron.androidbase.utils.InterfaceUtils.getFontAwesome import org.isoron.uhabits.* import org.isoron.uhabits.activities.* +import org.isoron.uhabits.core.preferences.* import org.isoron.uhabits.core.tasks.* import org.isoron.uhabits.databinding.* import org.isoron.uhabits.sync.* @@ -40,6 +41,7 @@ import org.isoron.uhabits.sync.* class SyncActivity : BaseActivity() { + private lateinit var preferences: Preferences private lateinit var taskRunner: TaskRunner private lateinit var baseScreen: BaseScreen private lateinit var themeSwitcher: AndroidThemeSwitcher @@ -54,6 +56,7 @@ class SyncActivity : BaseActivity() { themeSwitcher = AndroidThemeSwitcher(this, component.preferences) themeSwitcher.apply() taskRunner = component.taskRunner + preferences = component.preferences binding = ActivitySyncBinding.inflate(layoutInflater) setContentView(binding.root) @@ -74,27 +77,41 @@ class SyncActivity : BaseActivity() { override fun onResume() { super.onResume() + if(preferences.syncKey.isBlank()) { + register() + } else { + displayCurrentKey() + } + } + + private fun displayCurrentKey() { + displayLink("${preferences.syncBaseURL}/sync/${preferences.syncKey}") + displayPassword("6B2W9F5X") + } + + private fun register() { displayLoading() taskRunner.execute(object : Task { private var key = "" private var error = false override fun doInBackground() { runBlocking { - val server = RemoteSyncServer() + val server = RemoteSyncServer(baseURL = preferences.syncBaseURL) try { key = server.register() - } catch(e: ServiceUnavailable) { + } catch (e: ServiceUnavailable) { error = true } } } + override fun onPostExecute() { - if(error) { + if (error) { displayError() - } else { - displayLink("https://loophabits.org/sync/$key") - displayPassword("6B2W9F5X") + return; } + preferences.syncKey = key; + displayCurrentKey() } }) } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/IntentFactory.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/IntentFactory.kt index 2287a56d1..520758705 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/IntentFactory.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/IntentFactory.kt @@ -21,13 +21,13 @@ package org.isoron.uhabits.intents import android.content.* import android.net.* -import org.isoron.androidbase.activities.* import org.isoron.uhabits.* import org.isoron.uhabits.activities.about.* import org.isoron.uhabits.activities.habits.edit.* import org.isoron.uhabits.activities.habits.show.* import org.isoron.uhabits.activities.intro.* import org.isoron.uhabits.activities.settings.* +import org.isoron.uhabits.activities.sync.* import org.isoron.uhabits.core.models.* import javax.inject.* @@ -100,4 +100,8 @@ class IntentFactory intent.putExtra("habitType", habitType) return intent } + + fun startSyncActivity(context: Context): Intent { + return Intent(context, SyncActivity::class.java) + } } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/preferences/SharedPreferencesStorage.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/preferences/SharedPreferencesStorage.kt index 55a9defa7..b92f10385 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/preferences/SharedPreferencesStorage.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/preferences/SharedPreferencesStorage.kt @@ -87,8 +87,6 @@ class SharedPreferencesStorage preferences.setNotificationsSticky(getBoolean(key, false)) "pref_led_notifications" -> preferences.setNotificationsLed(getBoolean(key, false)) - "pref_feature_sync" -> - preferences.isSyncEnabled = getBoolean(key, false) } sharedPreferences.registerOnSharedPreferenceChangeListener(this) } diff --git a/android/uhabits-android/src/main/res/values/constants.xml b/android/uhabits-android/src/main/res/values/constants.xml index c034ad08b..3756855f4 100644 --- a/android/uhabits-android/src/main/res/values/constants.xml +++ b/android/uhabits-android/src/main/res/values/constants.xml @@ -27,6 +27,7 @@ http://translate.loophabits.org/ dev@loophabits.org Bug Report - Loop Habit Tracker + https://sync.loophabits.org @string/interval_15_minutes diff --git a/android/uhabits-android/src/main/res/values/strings.xml b/android/uhabits-android/src/main/res/values/strings.xml index bdd797672..d0f79b0cd 100644 --- a/android/uhabits-android/src/main/res/values/strings.xml +++ b/android/uhabits-android/src/main/res/values/strings.xml @@ -204,10 +204,10 @@ Enable skip days Toggle twice to add a skip instead of a checkmark. Skips keep your score unchanged and don\'t break your streak. Device sync - This feature allows you to synchronize data between multiple devices. When enabled, an encrypted copy of your data will be uploaded to Loop Habit Tracker servers. See privacy policy for more details. - Enable device sync + When enabled, an encrypted copy of your data will be uploaded to our servers. See privacy policy. + Sync data across devices Display sync instructions - Instructions:
1. Install Loop in your second device.
2. Open the link below in your second device.
3. Provide the 8-character password below.
Important: Do not publish this information. It gives anyone access to your entire data.]]>
+ Instructions:
1. Install Loop in your second device.
2. Open the link below in your second device.
3. Provide the 8-character password below.
Important: Do not publish this information. It gives anyone access to your data.]]>
Sync link Sync link (QR code) Password diff --git a/android/uhabits-android/src/main/res/xml/preferences.xml b/android/uhabits-android/src/main/res/xml/preferences.xml index 39524368d..e311649a6 100644 --- a/android/uhabits-android/src/main/res/xml/preferences.xml +++ b/android/uhabits-android/src/main/res/xml/preferences.xml @@ -116,21 +116,24 @@ + app:iconSpaceReserved="false"> + + - @@ -218,6 +221,20 @@ android:title="Enable widget stacks" app:iconSpaceReserved="false" /> + + + + \ No newline at end of file diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/preferences/Preferences.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/preferences/Preferences.java index 857989aea..a2b22fc0e 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/preferences/Preferences.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/preferences/Preferences.java @@ -29,10 +29,6 @@ import java.util.*; public class Preferences { - - public static final String DEFAULT_SYNC_SERVER = - "https://sync.loophabits.org"; - @NonNull private final Storage storage; @@ -130,16 +126,6 @@ public class Preferences else return new Timestamp(unixTime); } - public long getLastSync() - { - return storage.getLong("last_sync", 0); - } - - public void setLastSync(long timestamp) - { - storage.putLong("last_sync", timestamp); - } - public boolean getShowArchived() { return storage.getBoolean("pref_show_archived", false); @@ -170,39 +156,6 @@ public class Preferences storage.putString("pref_snooze_interval", String.valueOf(interval)); } - public String getSyncAddress() - { - return storage.getString("pref_sync_address", DEFAULT_SYNC_SERVER); - } - - public void setSyncAddress(String address) - { - storage.putString("pref_sync_address", address); - for (Listener l : listeners) l.onSyncFeatureChanged(); - } - - public String getSyncClientId() - { - String id = storage.getString("pref_sync_client_id", ""); - if (!id.isEmpty()) return id; - - id = UUID.randomUUID().toString(); - storage.putString("pref_sync_client_id", id); - - return id; - } - - public String getSyncKey() - { - return storage.getString("pref_sync_key", ""); - } - - public void setSyncKey(String key) - { - storage.putString("pref_sync_key", key); - for (Listener l : listeners) l.onSyncFeatureChanged(); - } - public int getTheme() { return storage.getInt("pref_theme", ThemeSwitcher.THEME_AUTOMATIC); @@ -263,17 +216,6 @@ public class Preferences storage.putBoolean("pref_short_toggle", enabled); } - public boolean isSyncEnabled() - { - return storage.getBoolean("pref_feature_sync", false); - } - - public void setSyncEnabled(boolean isEnabled) - { - storage.putBoolean("pref_feature_sync", isEnabled); - for (Listener l : listeners) l.onSyncFeatureChanged(); - } - public boolean isWidgetStackEnabled() { return storage.getBoolean("pref_feature_widget_stack", false); @@ -367,6 +309,26 @@ public class Preferences storage.putBoolean("pref_skip_enabled", value); } + public String getSyncBaseURL() + { + return storage.getString("pref_sync_base_url", ""); + } + + public String getSyncKey() + { + return storage.getString("pref_sync_key", ""); + } + + public void setSyncKey(String key) + { + storage.putString("pref_sync_key", key); + } + + public boolean isSyncEnabled() + { + return storage.getBoolean("pref_sync_enabled", false); + } + /** * @return An integer representing the first day of the week. Sunday @@ -390,10 +352,6 @@ public class Preferences default void onNotificationsChanged() { } - - default void onSyncFeatureChanged() - { - } } public interface Storage diff --git a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/preferences/PreferencesTest.java b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/preferences/PreferencesTest.java index 409a9fa9e..a58abd868 100644 --- a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/preferences/PreferencesTest.java +++ b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/preferences/PreferencesTest.java @@ -109,37 +109,6 @@ public class PreferencesTest extends BaseUnitTest assertThat(prefs.getLastHintTimestamp(), equalTo(Timestamp.ZERO.plus(100))); } - @Test - public void testSync() throws Exception - { - assertThat(prefs.getLastSync(), equalTo(0L)); - prefs.setLastSync(100); - assertThat(prefs.getLastSync(), equalTo(100L)); - - assertThat(prefs.getSyncAddress(), - equalTo(Preferences.DEFAULT_SYNC_SERVER)); - prefs.setSyncAddress("example"); - assertThat(prefs.getSyncAddress(), equalTo("example")); - verify(listener).onSyncFeatureChanged(); - reset(listener); - - assertThat(prefs.getSyncKey(), equalTo("")); - prefs.setSyncKey("123"); - assertThat(prefs.getSyncKey(), equalTo("123")); - verify(listener).onSyncFeatureChanged(); - reset(listener); - - assertFalse(prefs.isSyncEnabled()); - prefs.setSyncEnabled(true); - assertTrue(prefs.isSyncEnabled()); - verify(listener).onSyncFeatureChanged(); - reset(listener); - - String id = prefs.getSyncClientId(); - assertFalse(id.isEmpty()); - assertThat(prefs.getSyncClientId(), equalTo(id)); - } - @Test public void testTheme() throws Exception {