mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-06 09:08:52 -06:00
Implement SyncActivity (with static data)
This commit is contained in:
@@ -127,8 +127,7 @@ open class BaseScreen(@JvmField protected var activity: BaseActivity) {
|
|||||||
*
|
*
|
||||||
* @param stringId the string resource id for this message.
|
* @param stringId the string resource id for this message.
|
||||||
*/
|
*/
|
||||||
fun showMessage(@StringRes stringId: Int?) {
|
fun showMessage(@StringRes stringId: Int?, rootView: View?) {
|
||||||
val rootView = this.rootView
|
|
||||||
var snackbar = this.snackbar
|
var snackbar = this.snackbar
|
||||||
if (stringId == null || rootView == null) return
|
if (stringId == null || rootView == null) return
|
||||||
if (snackbar == null) {
|
if (snackbar == null) {
|
||||||
@@ -142,6 +141,10 @@ open class BaseScreen(@JvmField protected var activity: BaseActivity) {
|
|||||||
snackbar.show()
|
snackbar.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun showMessage(@StringRes stringId: Int?) {
|
||||||
|
showMessage(stringId, this.rootView)
|
||||||
|
}
|
||||||
|
|
||||||
fun showSendEmailScreen(@StringRes toId: Int, @StringRes subjectId: Int, content: String?) {
|
fun showSendEmailScreen(@StringRes toId: Int, @StringRes subjectId: Int, content: String?) {
|
||||||
val to = activity.getString(toId)
|
val to = activity.getString(toId)
|
||||||
val subject = activity.getString(subjectId)
|
val subject = activity.getString(subjectId)
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ dependencies {
|
|||||||
implementation "com.google.code.findbugs:jsr305:3.0.2"
|
implementation "com.google.code.findbugs:jsr305:3.0.2"
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$KOTLIN_VERSION"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$KOTLIN_VERSION"
|
||||||
implementation "androidx.constraintlayout:constraintlayout:2.0.0-beta4"
|
implementation "androidx.constraintlayout:constraintlayout:2.0.0-beta4"
|
||||||
|
implementation 'com.google.zxing:core:3.4.1'
|
||||||
|
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||||
compileOnly "javax.annotation:jsr250-api:1.0"
|
compileOnly "javax.annotation:jsr250-api:1.0"
|
||||||
|
|||||||
@@ -41,6 +41,14 @@
|
|||||||
android:value=".activities.habits.list.ListHabitsActivity" />
|
android:value=".activities.habits.list.ListHabitsActivity" />
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".activities.sync.SyncActivity"
|
||||||
|
android:exported="true">
|
||||||
|
<meta-data
|
||||||
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
|
android:value=".activities.settings.SettingsActivity" />
|
||||||
|
</activity>
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="com.google.android.backup.api_key"
|
android:name="com.google.android.backup.api_key"
|
||||||
android:value="AEdPqrEAAAAI6aeWncbnMNo8E5GWeZ44dlc5cQ7tCROwFhOtiw" />
|
android:value="AEdPqrEAAAAI6aeWncbnMNo8E5GWeZ44dlc5cQ7tCROwFhOtiw" />
|
||||||
|
|||||||
@@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016-2020 Á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.sync
|
||||||
|
|
||||||
|
import android.content.*
|
||||||
|
import android.content.ClipboardManager
|
||||||
|
import android.graphics.*
|
||||||
|
import android.os.*
|
||||||
|
import android.text.*
|
||||||
|
import com.google.zxing.*
|
||||||
|
import com.google.zxing.qrcode.*
|
||||||
|
import org.isoron.androidbase.activities.*
|
||||||
|
import org.isoron.androidbase.utils.*
|
||||||
|
import org.isoron.uhabits.*
|
||||||
|
import org.isoron.uhabits.activities.*
|
||||||
|
import org.isoron.uhabits.databinding.*
|
||||||
|
|
||||||
|
|
||||||
|
class SyncActivity : BaseActivity() {
|
||||||
|
|
||||||
|
private lateinit var baseScreen: BaseScreen
|
||||||
|
private lateinit var themeSwitcher: AndroidThemeSwitcher
|
||||||
|
private lateinit var binding: ActivitySyncBinding
|
||||||
|
|
||||||
|
override fun onCreate(state: Bundle?) {
|
||||||
|
super.onCreate(state)
|
||||||
|
|
||||||
|
baseScreen = BaseScreen(this)
|
||||||
|
|
||||||
|
val component = (application as HabitsApplication).component
|
||||||
|
themeSwitcher = AndroidThemeSwitcher(this, component.preferences)
|
||||||
|
themeSwitcher.apply()
|
||||||
|
|
||||||
|
binding = ActivitySyncBinding.inflate(layoutInflater)
|
||||||
|
setContentView(binding.root)
|
||||||
|
|
||||||
|
setSupportActionBar(binding.toolbar)
|
||||||
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
|
supportActionBar?.setDisplayShowHomeEnabled(true)
|
||||||
|
supportActionBar?.elevation = 10.0f
|
||||||
|
|
||||||
|
binding.instructions.setText(Html.fromHtml(resources.getString(R.string.sync_instructions)))
|
||||||
|
|
||||||
|
displayLink("https://loophabits.org/sync/KA9GvblSWrcLk9iwJrplHvWiWdE6opAokdf2qqRl6n6ECX8IUhvcksqlfkQACoMM")
|
||||||
|
displayPassword("6B2W9F5X")
|
||||||
|
|
||||||
|
binding.syncLink.setOnClickListener {
|
||||||
|
copyToClipboard()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun copyToClipboard() {
|
||||||
|
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||||
|
clipboard.setPrimaryClip(ClipData.newPlainText("Loop Sync Link", binding.syncLink.text))
|
||||||
|
baseScreen.showMessage(R.string.copied_to_the_clipboard, binding.root)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun displayPassword(pin: String) {
|
||||||
|
binding.password.text = pin
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun displayLink(link: String) {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.qrCode.setImageBitmap(bitmap)
|
||||||
|
}
|
||||||
|
}
|
||||||
113
android/uhabits-android/src/main/res/layout/activity_sync.xml
Normal file
113
android/uhabits-android/src/main/res/layout/activity_sync.xml
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="?attr/highContrastReverseTextColor"
|
||||||
|
android:fitsSystemWindows="true"
|
||||||
|
android:orientation="vertical"
|
||||||
|
tools:context=".activities.habits.edit.EditHabitActivity">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.Toolbar
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?attr/colorPrimary"
|
||||||
|
android:elevation="2dp"
|
||||||
|
android:gravity="end"
|
||||||
|
android:minHeight="?attr/actionBarSize"
|
||||||
|
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
|
||||||
|
app:title="@string/device_sync"
|
||||||
|
app:titleTextColor="@color/white">
|
||||||
|
|
||||||
|
</androidx.appcompat.widget.Toolbar>
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingLeft="4dp"
|
||||||
|
android:paddingTop="8dp"
|
||||||
|
android:paddingRight="4dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:lineSpacingExtra="4sp"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:paddingBottom="16dp"
|
||||||
|
android:textSize="@dimen/regularTextSize"
|
||||||
|
android:id="@+id/instructions"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- Sync Link -->
|
||||||
|
<FrameLayout style="@style/FormOuterBox">
|
||||||
|
|
||||||
|
<LinearLayout style="@style/FormInnerBox">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/FormLabel"
|
||||||
|
android:text="@string/sync_link" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/syncLink"
|
||||||
|
style="@style/FormInput"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:text=""
|
||||||
|
android:background="@drawable/ripple"
|
||||||
|
android:textSize="@dimen/smallTextSize"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
/>
|
||||||
|
</LinearLayout>
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<!-- Sync Link -->
|
||||||
|
<FrameLayout style="@style/FormOuterBox">
|
||||||
|
|
||||||
|
<LinearLayout style="@style/FormInnerBox">
|
||||||
|
<TextView
|
||||||
|
style="@style/FormLabel"
|
||||||
|
android:text="@string/sync_link_qr" />
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="200dp"
|
||||||
|
android:layout_height="200dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:id="@+id/qrCode" />
|
||||||
|
</LinearLayout>
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<FrameLayout style="@style/FormOuterBox">
|
||||||
|
|
||||||
|
<LinearLayout style="@style/FormInnerBox">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/FormLabel"
|
||||||
|
android:text="@string/password" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/password"
|
||||||
|
style="@style/FormInput"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:letterSpacing=".5"
|
||||||
|
android:textSize="24sp"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:text="" />
|
||||||
|
</LinearLayout>
|
||||||
|
</FrameLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
@@ -203,4 +203,13 @@
|
|||||||
<string name="decrement">Decrement</string>
|
<string name="decrement">Decrement</string>
|
||||||
<string name="pref_skip_title">Enable skip days</string>
|
<string name="pref_skip_title">Enable skip days</string>
|
||||||
<string name="pref_skip_description">Toggle twice to add a skip instead of a checkmark. Skips keep your score unchanged and don\'t break your streak.</string>
|
<string name="pref_skip_description">Toggle twice to add a skip instead of a checkmark. Skips keep your score unchanged and don\'t break your streak.</string>
|
||||||
|
<string name="device_sync">Device sync</string>
|
||||||
|
<string name="pref_sync_summary">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.</string>
|
||||||
|
<string name="pref_sync_title">Enable device sync</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 entire 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>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -110,6 +110,27 @@
|
|||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
<PreferenceCategory
|
||||||
|
android:key="deviceSync"
|
||||||
|
android:title="@string/device_sync" >
|
||||||
|
|
||||||
|
<CheckBoxPreference
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:key="pref_enable_device_sync"
|
||||||
|
android:summary="@string/pref_sync_summary"
|
||||||
|
android:title="@string/pref_sync_title"
|
||||||
|
app:iconSpaceReserved="false" />
|
||||||
|
|
||||||
|
<Preference
|
||||||
|
android:key="viewSync"
|
||||||
|
android:title="@string/display_sync_code"
|
||||||
|
app:iconSpaceReserved="false"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
android:key="databaseCategory"
|
android:key="databaseCategory"
|
||||||
android:title="@string/database">
|
android:title="@string/database">
|
||||||
|
|||||||
Reference in New Issue
Block a user