From 0859cec853af183f199abf3693c8378acdaa7855 Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Sun, 22 Nov 2020 17:00:37 -0600 Subject: [PATCH] Implement intent filter; hide password for now --- .../src/main/AndroidManifest.xml | 9 ++- .../uhabits/activities/HabitsActivity.kt | 7 ++- .../common/dialogs/ConfirmSyncKeyDialog.java | 58 +++++++++++++++++++ .../habits/list/ListHabitsScreen.kt | 42 +++++++++----- .../activities/settings/SettingsFragment.java | 5 +- .../uhabits/activities/sync/SyncActivity.kt | 46 +++++++++------ .../src/main/res/layout/activity_sync.xml | 4 +- .../src/main/res/values/strings.xml | 6 +- .../uhabits/core/preferences/Preferences.java | 5 ++ .../habits/list/ListHabitsBehavior.java | 15 ++++- 10 files changed, 155 insertions(+), 42 deletions(-) create mode 100644 android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/ConfirmSyncKeyDialog.java diff --git a/android/uhabits-android/src/main/AndroidManifest.xml b/android/uhabits-android/src/main/AndroidManifest.xml index f043a92fb..a054ce37d 100644 --- a/android/uhabits-android/src/main/AndroidManifest.xml +++ b/android/uhabits-android/src/main/AndroidManifest.xml @@ -68,9 +68,16 @@ android:targetActivity=".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.common.dialogs; + +import android.content.*; + +import androidx.annotation.*; +import androidx.appcompat.app.*; + +import com.google.auto.factory.*; + +import org.isoron.androidbase.activities.*; +import org.isoron.uhabits.core.ui.callbacks.*; +import org.isoron.uhabits.R; + +import butterknife.*; + +@AutoFactory(allowSubclasses = true) +public class ConfirmSyncKeyDialog extends AlertDialog +{ + @BindString(R.string.sync_confirm) + protected String question; + + @BindString(R.string.yes) + protected String yes; + + @BindString(R.string.no) + protected String no; + + protected ConfirmSyncKeyDialog(@Provided @ActivityContext Context context, + @NonNull OnConfirmedCallback callback) + { + super(context); + ButterKnife.bind(this); + + setTitle(R.string.device_sync); + setMessage(question); + setButton(BUTTON_POSITIVE, yes, (dialog, which) -> callback.onConfirmed()); + setButton(BUTTON_NEGATIVE, no, (dialog, which) -> {}); + } +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt index e4c3752a1..4d2d32602 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt @@ -21,6 +21,7 @@ package org.isoron.uhabits.activities.habits.list import android.app.* import android.content.* +import android.util.* import androidx.annotation.* import dagger.* import org.isoron.androidbase.activities.* @@ -31,7 +32,6 @@ import org.isoron.uhabits.activities.habits.edit.* import org.isoron.uhabits.activities.habits.list.views.* import org.isoron.uhabits.core.commands.* import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.core.preferences.* import org.isoron.uhabits.core.tasks.* import org.isoron.uhabits.core.ui.* import org.isoron.uhabits.core.ui.callbacks.* @@ -42,13 +42,13 @@ import org.isoron.uhabits.tasks.* import java.io.* import javax.inject.* -const val RESULT_IMPORT_DATA = 1 -const val RESULT_EXPORT_CSV = 2 -const val RESULT_EXPORT_DB = 3 -const val RESULT_BUG_REPORT = 4 -const val RESULT_REPAIR_DB = 5 -const val REQUEST_OPEN_DOCUMENT = 6 -const val REQUEST_SETTINGS = 7 +const val RESULT_IMPORT_DATA = 101 +const val RESULT_EXPORT_CSV = 102 +const val RESULT_EXPORT_DB = 103 +const val RESULT_BUG_REPORT = 104 +const val RESULT_REPAIR_DB = 105 +const val REQUEST_OPEN_DOCUMENT = 106 +const val REQUEST_SETTINGS = 107 @ActivityScope class ListHabitsScreen @@ -63,6 +63,7 @@ class ListHabitsScreen private val exportDBFactory: ExportDBTaskFactory, private val importTaskFactory: ImportDataTaskFactory, private val confirmDeleteDialogFactory: ConfirmDeleteDialogFactory, + private val confirmSyncKeyDialogFactory: ConfirmSyncKeyDialogFactory, private val colorPickerFactory: ColorPickerDialogFactory, private val numberPickerFactory: NumberPickerFactory, private val behavior: Lazy, @@ -82,6 +83,12 @@ class ListHabitsScreen setMenu(menu.get()) setSelectionMenu(selectionMenu.get()) commandRunner.addListener(this) + if(activity.intent.action == "android.intent.action.VIEW") { + val uri = activity.intent.data!!.toString() + val key = uri.replace(Regex("^.*sync/"), "") + Log.i("ListHabitsScreen", key) + behavior.get().onSyncKeyOffer(key) + } } fun onDettached() { @@ -171,13 +178,14 @@ class ListHabitsScreen override fun showMessage(m: ListHabitsBehavior.Message) { showMessage(when (m) { - COULD_NOT_EXPORT -> R.string.could_not_export - IMPORT_SUCCESSFUL -> R.string.habits_imported - IMPORT_FAILED -> R.string.could_not_import - DATABASE_REPAIRED -> R.string.database_repaired - COULD_NOT_GENERATE_BUG_REPORT -> R.string.bug_report_failed - FILE_NOT_RECOGNIZED -> R.string.file_not_recognized - }) + COULD_NOT_EXPORT -> R.string.could_not_export + IMPORT_SUCCESSFUL -> R.string.habits_imported + IMPORT_FAILED -> R.string.could_not_import + DATABASE_REPAIRED -> R.string.database_repaired + COULD_NOT_GENERATE_BUG_REPORT -> R.string.bug_report_failed + FILE_NOT_RECOGNIZED -> R.string.file_not_recognized + SYNC_ENABLED -> R.string.sync_enabled + }) } override fun showSendBugReportToDeveloperScreen(log: String) { @@ -204,6 +212,10 @@ class ListHabitsScreen numberPickerFactory.create(value, unit, callback).show() } + override fun showConfirmInstallSyncKey(callback: OnConfirmedCallback) { + activity.showDialog(confirmSyncKeyDialogFactory.create(callback)) + } + @StringRes private fun getExecuteString(command: Command): Int? { when (command) { 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 1faca385f..64153beda 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 @@ -145,7 +145,6 @@ public class SettingsFragment extends PreferenceFragmentCompat { PreferenceCategory devCategory = (PreferenceCategory) findPreference("devCategory"); - devCategory.removeAll(); devCategory.setVisible(false); } @@ -159,6 +158,10 @@ public class SettingsFragment extends PreferenceFragmentCompat private void updateSyncPreferences() { + if(prefs.getSyncKey().isEmpty()) { + prefs.setSyncEnabled(false); + ((CheckBoxPreference) findPreference("pref_sync_enabled")).setChecked(false); + } findPreference("pref_sync_base_url").setSummary(prefs.getSyncBaseURL()); findPreference("pref_sync_key").setSummary(prefs.getSyncKey()); findPreference("pref_sync_display").setVisible(prefs.isSyncEnabled()); 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 231a2a467..7d04793be 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 @@ -44,17 +44,16 @@ class SyncActivity : BaseActivity() { private lateinit var preferences: Preferences private lateinit var taskRunner: TaskRunner private lateinit var baseScreen: BaseScreen - private lateinit var themeSwitcher: AndroidThemeSwitcher private lateinit var binding: ActivitySyncBinding + private var styledResources = StyledResources(this) + override fun onCreate(state: Bundle?) { super.onCreate(state) baseScreen = BaseScreen(this) val component = (application as HabitsApplication).component - themeSwitcher = AndroidThemeSwitcher(this, component.preferences) - themeSwitcher.apply() taskRunner = component.taskRunner preferences = component.preferences @@ -85,7 +84,7 @@ class SyncActivity : BaseActivity() { } private fun displayCurrentKey() { - displayLink("${preferences.syncBaseURL}/sync/${preferences.syncKey}") + displayLink("https://loophabits.org/sync/${preferences.syncKey}") displayPassword("6B2W9F5X") } @@ -139,27 +138,36 @@ class SyncActivity : BaseActivity() { } private fun displayLink(link: String) { - binding.qrCode.visibility = View.VISIBLE - binding.progress.visibility = View.GONE + binding.qrCode.visibility = View.GONE + binding.progress.visibility = View.VISIBLE binding.errorPanel.visibility = View.GONE binding.syncLink.text = link displayQR(link) } private fun displayQR(msg: String) { - val writer = QRCodeWriter() - val matrix = writer.encode(msg, BarcodeFormat.QR_CODE, 1024, 1024) - val height = matrix.height - val width = matrix.width - val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565) - val bgColor = StyledResources(this).getColor(R.attr.highContrastReverseTextColor) - val fgColor = StyledResources(this).getColor(R.attr.highContrastTextColor) - for (x in 0 until width) { - for (y in 0 until height) { - val color = if (matrix.get(x, y)) fgColor else bgColor - bitmap.setPixel(x, y, color) + taskRunner.execute(object : Task { + lateinit var bitmap: Bitmap + override fun doInBackground() { + val writer = QRCodeWriter() + val matrix = writer.encode(msg, BarcodeFormat.QR_CODE, 1024, 1024) + val height = matrix.height + val width = matrix.width + bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565) + val bgColor = styledResources.getColor(R.attr.highContrastReverseTextColor) + val fgColor = styledResources.getColor(R.attr.highContrastTextColor) + for (x in 0 until width) { + for (y in 0 until height) { + val color = if (matrix.get(x, y)) fgColor else bgColor + bitmap.setPixel(x, y, color) + } + } } - } - binding.qrCode.setImageBitmap(bitmap) + override fun onPostExecute() { + binding.progress.visibility = View.GONE + binding.qrCode.visibility = View.VISIBLE + binding.qrCode.setImageBitmap(bitmap) + } + }) } } \ No newline at end of file diff --git a/android/uhabits-android/src/main/res/layout/activity_sync.xml b/android/uhabits-android/src/main/res/layout/activity_sync.xml index 660d31bbd..67416d582 100644 --- a/android/uhabits-android/src/main/res/layout/activity_sync.xml +++ b/android/uhabits-android/src/main/res/layout/activity_sync.xml @@ -123,7 +123,9 @@ - + diff --git a/android/uhabits-android/src/main/res/values/strings.xml b/android/uhabits-android/src/main/res/values/strings.xml index d0f79b0cd..31afe7709 100644 --- a/android/uhabits-android/src/main/res/values/strings.xml +++ b/android/uhabits-android/src/main/res/values/strings.xml @@ -206,10 +206,12 @@ 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 data.]]>
+ Show device sync instructions + Instructions:
1. Install Loop in your second device.
2. Open the link below in your second device.
Important: Do not not make this information public. It gives anyone access to your data.]]>
Sync link Sync link (QR code) Password Copied to the clipboard + + Device sync enabled \ 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 a2b22fc0e..af1a37bba 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 @@ -329,6 +329,11 @@ public class Preferences return storage.getBoolean("pref_sync_enabled", false); } + public void setSyncEnabled(boolean enabled) + { + storage.putBoolean("pref_sync_enabled", enabled); + } + /** * @return An integer representing the first day of the week. Sunday diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehavior.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehavior.java index 870ad65f3..6f6c3c5a2 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehavior.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehavior.java @@ -25,7 +25,9 @@ import org.isoron.uhabits.core.commands.*; import org.isoron.uhabits.core.models.*; import org.isoron.uhabits.core.preferences.*; import org.isoron.uhabits.core.tasks.*; +import org.isoron.uhabits.core.ui.callbacks.*; import org.isoron.uhabits.core.utils.*; +import org.jetbrains.annotations.*; import java.io.*; import java.util.*; @@ -156,10 +158,19 @@ public class ListHabitsBehavior habit.getId()); } + public void onSyncKeyOffer(@NotNull String key) + { + screen.showConfirmInstallSyncKey(() -> { + prefs.setSyncKey(key); + prefs.setSyncEnabled(true); + screen.showMessage(Message.SYNC_ENABLED); + }); + } + public enum Message { COULD_NOT_EXPORT, IMPORT_SUCCESSFUL, IMPORT_FAILED, DATABASE_REPAIRED, - COULD_NOT_GENERATE_BUG_REPORT, FILE_NOT_RECOGNIZED + COULD_NOT_GENERATE_BUG_REPORT, FILE_NOT_RECOGNIZED, SYNC_ENABLED } public interface BugReporter @@ -196,5 +207,7 @@ public class ListHabitsBehavior void showSendBugReportToDeveloperScreen(String log); void showSendFileScreen(@NonNull String filename); + + void showConfirmInstallSyncKey(@NonNull OnConfirmedCallback callback); } }