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
{