Implement intent filter; hide password for now

pull/699/head
Alinson S. Xavier 5 years ago
parent 23f2978a64
commit 0859cec853

@ -68,9 +68,16 @@
android:targetActivity=".activities.habits.list.ListHabitsActivity">
<intent-filter android:label="@string/main_activity_title">
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https"
android:host="loophabits.org"
android:pathPrefix="/sync" />
</intent-filter>
</activity-alias>
<activity

@ -34,8 +34,11 @@ abstract class HabitsActivity : BaseActivity() {
appComponent = (applicationContext as HabitsApplication).component
val habit = getHabitFromIntent(appComponent.habitList)
?: appComponent.modelFactory.buildHabit()
var habit = appComponent.modelFactory.buildHabit()
if(intent.action != "android.intent.action.VIEW") {
val intentHabit = getHabitFromIntent(appComponent.habitList)
if (intentHabit != null) habit = intentHabit
}
component = DaggerHabitsActivityComponent
.builder()

@ -0,0 +1,58 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
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) -> {});
}
}

@ -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<ListHabitsBehavior>,
@ -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() {
@ -177,6 +184,7 @@ class ListHabitsScreen
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
})
}
@ -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) {

@ -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());

@ -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) {
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
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)
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)
}
}
}
override fun onPostExecute() {
binding.progress.visibility = View.GONE
binding.qrCode.visibility = View.VISIBLE
binding.qrCode.setImageBitmap(bitmap)
}
})
}
}

@ -123,7 +123,9 @@
</FrameLayout>
<!-- Password -->
<FrameLayout style="@style/FormOuterBox">
<FrameLayout
style="@style/FormOuterBox"
android:visibility="gone">
<LinearLayout style="@style/FormInnerBox">

@ -206,10 +206,12 @@
<string name="device_sync">Device sync</string>
<string name="pref_sync_summary">When enabled, an encrypted copy of your data will be uploaded to our servers. See privacy policy.</string>
<string name="pref_sync_title">Sync data across devices</string>
<string name="display_sync_code">Display sync instructions</string>
<string name="sync_instructions"><![CDATA[<b>Instructions:</b><br/>1. Install Loop in your second device.<br/>2. Open the link below in your second device.<br/>3. Provide the 8-character password below.<br/><b>Important:</b> Do not publish this information. It gives anyone access to your data.]]></string>
<string name="display_sync_code">Show device sync instructions</string>
<string name="sync_instructions"><![CDATA[<b>Instructions:</b><br/>1. Install Loop in your second device.<br/>2. Open the link below in your second device.<br/><b>Important:</b> Do not not make this information public. It gives anyone access to your data.]]></string>
<string name="sync_link">Sync link</string>
<string name="sync_link_qr">Sync link (QR code)</string>
<string name="password">Password</string>
<string name="copied_to_the_clipboard">Copied to the clipboard</string>
<string name="sync_confirm"><![CDATA[Are you trying to enable device sync?\n\nThis feature allows you to sync your data across multiple devices. When enabled, an encrypted copy of your data will be uploaded to our servers.]]></string>
<string name="sync_enabled">Device sync enabled</string>
</resources>

@ -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

@ -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);
}
}

Loading…
Cancel
Save