refactor import/export to create DaggerAppCompatActivityWithResult
This commit is contained in:
parent
3f18f94c79
commit
65a39d91be
45 changed files with 491 additions and 499 deletions
|
@ -5,11 +5,13 @@ import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
class Config @Inject constructor(): ConfigInterface{
|
class Config @Inject constructor() : ConfigInterface {
|
||||||
|
|
||||||
override val SUPPORTEDNSVERSION = 1002 // 0.10.00
|
override val SUPPORTEDNSVERSION = 1002 // 0.10.00
|
||||||
override val APS = BuildConfig.FLAVOR == "full"
|
override val APS = BuildConfig.FLAVOR == "full"
|
||||||
override val NSCLIENT = BuildConfig.FLAVOR == "nsclient" || BuildConfig.FLAVOR == "nsclient2"
|
override val NSCLIENT = BuildConfig.FLAVOR == "nsclient" || BuildConfig.FLAVOR == "nsclient2"
|
||||||
override val PUMPCONTROL = BuildConfig.FLAVOR == "pumpcontrol"
|
override val PUMPCONTROL = BuildConfig.FLAVOR == "pumpcontrol"
|
||||||
override val PUMPDRIVERS = BuildConfig.FLAVOR == "full" || BuildConfig.FLAVOR == "pumpcontrol"
|
override val PUMPDRIVERS = BuildConfig.FLAVOR == "full" || BuildConfig.FLAVOR == "pumpcontrol"
|
||||||
|
override val FLAVOR = BuildConfig.FLAVOR
|
||||||
|
override val VERSION_NAME = BuildConfig.VERSION_NAME
|
||||||
}
|
}
|
|
@ -47,8 +47,6 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||||
import info.nightscout.androidaps.plugins.constraints.signatureVerifier.SignatureVerifierPlugin
|
import info.nightscout.androidaps.plugins.constraints.signatureVerifier.SignatureVerifierPlugin
|
||||||
import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtils
|
import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtils
|
||||||
import info.nightscout.androidaps.plugins.general.maintenance.ImportExportPrefs
|
|
||||||
import info.nightscout.androidaps.plugins.general.maintenance.PrefsFileContract
|
|
||||||
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus
|
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus
|
||||||
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin
|
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin
|
||||||
import info.nightscout.androidaps.setupwizard.SetupWizardActivity
|
import info.nightscout.androidaps.setupwizard.SetupWizardActivity
|
||||||
|
@ -92,18 +90,11 @@ class MainActivity : NoSplashAppCompatActivity() {
|
||||||
@Inject lateinit var constraintChecker: ConstraintChecker
|
@Inject lateinit var constraintChecker: ConstraintChecker
|
||||||
@Inject lateinit var signatureVerifierPlugin: SignatureVerifierPlugin
|
@Inject lateinit var signatureVerifierPlugin: SignatureVerifierPlugin
|
||||||
@Inject lateinit var config: Config
|
@Inject lateinit var config: Config
|
||||||
@Inject lateinit var importExportPrefs: ImportExportPrefs
|
|
||||||
|
|
||||||
private lateinit var actionBarDrawerToggle: ActionBarDrawerToggle
|
private lateinit var actionBarDrawerToggle: ActionBarDrawerToggle
|
||||||
private var pluginPreferencesMenuItem: MenuItem? = null
|
private var pluginPreferencesMenuItem: MenuItem? = null
|
||||||
private var menu: Menu? = null
|
private var menu: Menu? = null
|
||||||
|
|
||||||
val callForPrefFile = registerForActivityResult(PrefsFileContract()) {
|
|
||||||
it?.let {
|
|
||||||
importExportPrefs.importSharedPreferences(this, it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
Iconify.with(FontAwesomeModule())
|
Iconify.with(FontAwesomeModule())
|
||||||
|
@ -203,10 +194,9 @@ class MainActivity : NoSplashAppCompatActivity() {
|
||||||
if (p.isEnabled() && p.hasFragment() && !p.isFragmentVisible() && !p.pluginDescription.neverVisible) {
|
if (p.isEnabled() && p.hasFragment() && !p.isFragmentVisible() && !p.pluginDescription.neverVisible) {
|
||||||
val menuItem = menu.add(p.name)
|
val menuItem = menu.add(p.name)
|
||||||
menuItem.isCheckable = true
|
menuItem.isCheckable = true
|
||||||
if(p.menuIcon != -1) {
|
if (p.menuIcon != -1) {
|
||||||
menuItem.setIcon(p.menuIcon)
|
menuItem.setIcon(p.menuIcon)
|
||||||
} else
|
} else {
|
||||||
{
|
|
||||||
menuItem.setIcon(R.drawable.ic_settings)
|
menuItem.setIcon(R.drawable.ic_settings)
|
||||||
}
|
}
|
||||||
menuItem.setOnMenuItemClickListener {
|
menuItem.setOnMenuItemClickListener {
|
||||||
|
@ -283,7 +273,7 @@ class MainActivity : NoSplashAppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||||
this.menu = menu
|
this.menu = menu
|
||||||
menuInflater.inflate(R.menu.menu_main, menu)
|
menuInflater.inflate(R.menu.menu_main, menu)
|
||||||
pluginPreferencesMenuItem = menu.findItem(R.id.nav_plugin_preferences)
|
pluginPreferencesMenuItem = menu.findItem(R.id.nav_plugin_preferences)
|
||||||
setPluginPreferenceMenuName()
|
setPluginPreferenceMenuName()
|
||||||
|
|
|
@ -5,29 +5,20 @@ import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import dagger.android.support.DaggerAppCompatActivity
|
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
import info.nightscout.androidaps.interfaces.PluginBase
|
import info.nightscout.androidaps.interfaces.PluginBase
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.PluginStore
|
import info.nightscout.androidaps.plugins.configBuilder.PluginStore
|
||||||
import info.nightscout.androidaps.plugins.general.maintenance.ImportExportPrefs
|
|
||||||
import info.nightscout.androidaps.plugins.general.maintenance.PrefsFileContract
|
|
||||||
import info.nightscout.androidaps.utils.locale.LocaleHelper
|
import info.nightscout.androidaps.utils.locale.LocaleHelper
|
||||||
import info.nightscout.androidaps.utils.protection.ProtectionCheck
|
import info.nightscout.androidaps.utils.protection.ProtectionCheck
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class SingleFragmentActivity : DaggerAppCompatActivity() {
|
class SingleFragmentActivity : DaggerAppCompatActivityWithResult() {
|
||||||
|
|
||||||
@Inject lateinit var pluginStore: PluginStore
|
@Inject lateinit var pluginStore: PluginStore
|
||||||
@Inject lateinit var protectionCheck: ProtectionCheck
|
@Inject lateinit var protectionCheck: ProtectionCheck
|
||||||
@Inject lateinit var importExportPrefs: ImportExportPrefs
|
|
||||||
|
|
||||||
private var plugin: PluginBase? = null
|
private var plugin: PluginBase? = null
|
||||||
|
|
||||||
val callForPrefFile = registerForActivityResult(PrefsFileContract()) {
|
|
||||||
it?.let {
|
|
||||||
importExportPrefs.importSharedPreferences(this, it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override fun onCreate(savedInstanceState: Bundle?) {
|
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_single_fragment)
|
setContentView(R.layout.activity_single_fragment)
|
||||||
|
|
|
@ -6,7 +6,6 @@ import info.nightscout.androidaps.MainActivity
|
||||||
import info.nightscout.androidaps.activities.*
|
import info.nightscout.androidaps.activities.*
|
||||||
import info.nightscout.androidaps.historyBrowser.HistoryBrowseActivity
|
import info.nightscout.androidaps.historyBrowser.HistoryBrowseActivity
|
||||||
import info.nightscout.androidaps.plugins.general.maintenance.activities.LogSettingActivity
|
import info.nightscout.androidaps.plugins.general.maintenance.activities.LogSettingActivity
|
||||||
import info.nightscout.androidaps.plugins.general.maintenance.activities.PrefImportListActivity
|
|
||||||
import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansLoginActivity
|
import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansLoginActivity
|
||||||
import info.nightscout.androidaps.plugins.general.overview.activities.QuickWizardListActivity
|
import info.nightscout.androidaps.plugins.general.overview.activities.QuickWizardListActivity
|
||||||
import info.nightscout.androidaps.plugins.general.smsCommunicator.activities.SmsCommunicatorOtpActivity
|
import info.nightscout.androidaps.plugins.general.smsCommunicator.activities.SmsCommunicatorOtpActivity
|
||||||
|
@ -40,7 +39,6 @@ abstract class ActivitiesModule {
|
||||||
@ContributesAndroidInjector abstract fun contributesStatsActivity(): StatsActivity
|
@ContributesAndroidInjector abstract fun contributesStatsActivity(): StatsActivity
|
||||||
@ContributesAndroidInjector abstract fun contributesSurveyActivity(): SurveyActivity
|
@ContributesAndroidInjector abstract fun contributesSurveyActivity(): SurveyActivity
|
||||||
@ContributesAndroidInjector abstract fun contributesDefaultProfileActivity(): ProfileHelperActivity
|
@ContributesAndroidInjector abstract fun contributesDefaultProfileActivity(): ProfileHelperActivity
|
||||||
@ContributesAndroidInjector abstract fun contributesPrefImportListActivity(): PrefImportListActivity
|
|
||||||
@ContributesAndroidInjector abstract fun contributesOpenHumansLoginActivity(): OpenHumansLoginActivity
|
@ContributesAndroidInjector abstract fun contributesOpenHumansLoginActivity(): OpenHumansLoginActivity
|
||||||
|
|
||||||
}
|
}
|
|
@ -12,6 +12,7 @@ import info.nightscout.androidaps.db.DatabaseHelperProvider
|
||||||
import info.nightscout.androidaps.interfaces.*
|
import info.nightscout.androidaps.interfaces.*
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.PluginStore
|
import info.nightscout.androidaps.plugins.configBuilder.PluginStore
|
||||||
|
import info.nightscout.androidaps.plugins.general.maintenance.ImportExportPrefs
|
||||||
import info.nightscout.androidaps.plugins.general.nsclient.UploadQueue
|
import info.nightscout.androidaps.plugins.general.nsclient.UploadQueue
|
||||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
||||||
import info.nightscout.androidaps.queue.CommandQueue
|
import info.nightscout.androidaps.queue.CommandQueue
|
||||||
|
@ -58,5 +59,6 @@ open class AppModule {
|
||||||
@Binds fun bindDatabaseHelperInterface(databaseHelperProvider: DatabaseHelperProvider): DatabaseHelperInterface
|
@Binds fun bindDatabaseHelperInterface(databaseHelperProvider: DatabaseHelperProvider): DatabaseHelperInterface
|
||||||
@Binds fun bindUploadQueueInterface(uploadQueue: UploadQueue): UploadQueueInterface
|
@Binds fun bindUploadQueueInterface(uploadQueue: UploadQueue): UploadQueueInterface
|
||||||
@Binds fun bindNotificationHolderInterface(notificationHolder: NotificationHolder): NotificationHolderInterface
|
@Binds fun bindNotificationHolderInterface(notificationHolder: NotificationHolder): NotificationHolderInterface
|
||||||
|
@Binds fun bindImportExportPrefsInterface(importExportPrefs: ImportExportPrefs): ImportExportPrefsInterface
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ package info.nightscout.androidaps.dependencyInjection
|
||||||
|
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.android.ContributesAndroidInjector
|
import dagger.android.ContributesAndroidInjector
|
||||||
import info.nightscout.androidaps.plugins.general.maintenance.ImportExportPrefs
|
|
||||||
import info.nightscout.androidaps.plugins.general.maintenance.PrefFileListProvider
|
import info.nightscout.androidaps.plugins.general.maintenance.PrefFileListProvider
|
||||||
import info.nightscout.androidaps.plugins.general.maintenance.formats.ClassicPrefsFormat
|
import info.nightscout.androidaps.plugins.general.maintenance.formats.ClassicPrefsFormat
|
||||||
import info.nightscout.androidaps.plugins.general.maintenance.formats.EncryptedPrefsFormat
|
import info.nightscout.androidaps.plugins.general.maintenance.formats.EncryptedPrefsFormat
|
||||||
|
@ -13,7 +12,6 @@ import info.nightscout.androidaps.utils.CryptoUtil
|
||||||
abstract class PreferencesModule {
|
abstract class PreferencesModule {
|
||||||
|
|
||||||
@ContributesAndroidInjector abstract fun cryptoUtilInjector(): CryptoUtil
|
@ContributesAndroidInjector abstract fun cryptoUtilInjector(): CryptoUtil
|
||||||
@ContributesAndroidInjector abstract fun importExportPrefsInjector(): ImportExportPrefs
|
|
||||||
@ContributesAndroidInjector abstract fun encryptedPrefsFormatInjector(): EncryptedPrefsFormat
|
@ContributesAndroidInjector abstract fun encryptedPrefsFormatInjector(): EncryptedPrefsFormat
|
||||||
@ContributesAndroidInjector abstract fun classicPrefsFormatInjector(): ClassicPrefsFormat
|
@ContributesAndroidInjector abstract fun classicPrefsFormatInjector(): ClassicPrefsFormat
|
||||||
@ContributesAndroidInjector abstract fun prefImportListProviderInjector(): PrefFileListProvider
|
@ContributesAndroidInjector abstract fun prefImportListProviderInjector(): PrefFileListProvider
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package info.nightscout.androidaps.plugins.constraints.objectives.objectives;
|
package info.nightscout.androidaps.plugins.constraints.objectives.objectives;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.text.util.Linkify;
|
import android.text.util.Linkify;
|
||||||
|
@ -185,9 +184,9 @@ public abstract class Objective {
|
||||||
int days = (int) Math.floor((double) duration / T.days(1).msecs());
|
int days = (int) Math.floor((double) duration / T.days(1).msecs());
|
||||||
int hours = (int) Math.floor((double) duration / T.hours(1).msecs());
|
int hours = (int) Math.floor((double) duration / T.hours(1).msecs());
|
||||||
int minutes = (int) Math.floor((double) duration / T.mins(1).msecs());
|
int minutes = (int) Math.floor((double) duration / T.mins(1).msecs());
|
||||||
if (days > 0) return resourceHelper.gq(R.plurals.objective_days, days, days);
|
if (days > 0) return resourceHelper.gq(R.plurals.days, days, days);
|
||||||
else if (hours > 0) return resourceHelper.gq(R.plurals.objective_hours, hours, hours);
|
else if (hours > 0) return resourceHelper.gq(R.plurals.hours, hours, hours);
|
||||||
else return resourceHelper.gq(R.plurals.objective_minutes, minutes, minutes);
|
else return resourceHelper.gq(R.plurals.minutes, minutes, minutes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,16 +12,15 @@ import androidx.core.content.ContextCompat
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import info.nightscout.androidaps.BuildConfig
|
import info.nightscout.androidaps.BuildConfig
|
||||||
import info.nightscout.androidaps.MainActivity
|
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.activities.DaggerAppCompatActivityWithResult
|
||||||
import info.nightscout.androidaps.activities.PreferencesActivity
|
import info.nightscout.androidaps.activities.PreferencesActivity
|
||||||
import info.nightscout.androidaps.activities.SingleFragmentActivity
|
|
||||||
import info.nightscout.androidaps.events.EventAppExit
|
import info.nightscout.androidaps.events.EventAppExit
|
||||||
|
import info.nightscout.androidaps.interfaces.ImportExportPrefsInterface
|
||||||
import info.nightscout.androidaps.logging.AAPSLogger
|
import info.nightscout.androidaps.logging.AAPSLogger
|
||||||
import info.nightscout.androidaps.logging.LTag
|
import info.nightscout.androidaps.logging.LTag
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||||
import info.nightscout.androidaps.plugins.general.maintenance.formats.*
|
import info.nightscout.androidaps.plugins.general.maintenance.formats.*
|
||||||
import info.nightscout.androidaps.setupwizard.SetupWizardActivity
|
|
||||||
import info.nightscout.androidaps.utils.AndroidPermission
|
import info.nightscout.androidaps.utils.AndroidPermission
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
import info.nightscout.androidaps.utils.ToastUtils
|
import info.nightscout.androidaps.utils.ToastUtils
|
||||||
|
@ -40,6 +39,7 @@ import java.io.IOException
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by mike on 03.07.2016.
|
* Created by mike on 03.07.2016.
|
||||||
|
@ -57,19 +57,17 @@ class ImportExportPrefs @Inject constructor(
|
||||||
private val classicPrefsFormat: ClassicPrefsFormat,
|
private val classicPrefsFormat: ClassicPrefsFormat,
|
||||||
private val encryptedPrefsFormat: EncryptedPrefsFormat,
|
private val encryptedPrefsFormat: EncryptedPrefsFormat,
|
||||||
private val prefFileList: PrefFileListProvider
|
private val prefFileList: PrefFileListProvider
|
||||||
) {
|
) : ImportExportPrefsInterface {
|
||||||
|
|
||||||
val TAG = LTag.CORE
|
override fun prefsFileExists(): Boolean {
|
||||||
|
|
||||||
fun prefsFileExists(): Boolean {
|
|
||||||
return prefFileList.listPreferenceFiles().size > 0
|
return prefFileList.listPreferenceFiles().size > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
fun exportSharedPreferences(f: Fragment) {
|
override fun exportSharedPreferences(f: Fragment) {
|
||||||
f.activity?.let { exportSharedPreferences(it) }
|
f.activity?.let { exportSharedPreferences(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun verifyStoragePermissions(fragment: Fragment, onGranted: Runnable) {
|
override fun verifyStoragePermissions(fragment: Fragment, onGranted: Runnable) {
|
||||||
fragment.context?.let { ctx ->
|
fragment.context?.let { ctx ->
|
||||||
val permission = ContextCompat.checkSelfPermission(ctx,
|
val permission = ContextCompat.checkSelfPermission(ctx,
|
||||||
Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||||
|
@ -119,8 +117,7 @@ class ImportExportPrefs @Inject constructor(
|
||||||
|
|
||||||
// name we detect from OS
|
// name we detect from OS
|
||||||
val systemName = n1 ?: n2 ?: n3 ?: n4 ?: n5 ?: n6 ?: defaultPatientName
|
val systemName = n1 ?: n2 ?: n3 ?: n4 ?: n5 ?: n6 ?: defaultPatientName
|
||||||
val name = if (patientName.isNotEmpty() && patientName != defaultPatientName) patientName else systemName
|
return if (patientName.isNotEmpty() && patientName != defaultPatientName) patientName else systemName
|
||||||
return name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun prefsEncryptionIsDisabled() =
|
private fun prefsEncryptionIsDisabled() =
|
||||||
|
@ -134,6 +131,7 @@ class ImportExportPrefs @Inject constructor(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("SameParameterValue")
|
||||||
private fun askForEncryptionPass(activity: FragmentActivity, @StringRes canceledMsg: Int, @StringRes passwordName: Int, @StringRes passwordExplanation: Int?,
|
private fun askForEncryptionPass(activity: FragmentActivity, @StringRes canceledMsg: Int, @StringRes passwordName: Int, @StringRes passwordExplanation: Int?,
|
||||||
@StringRes passwordWarning: Int?, then: ((password: String) -> Unit)) {
|
@StringRes passwordWarning: Int?, then: ((password: String) -> Unit)) {
|
||||||
passwordCheck.queryAnyPassword(activity, passwordName, R.string.key_master_password, passwordExplanation, passwordWarning, { password ->
|
passwordCheck.queryAnyPassword(activity, passwordName, R.string.key_master_password, passwordExplanation, passwordWarning, { password ->
|
||||||
|
@ -143,6 +141,7 @@ class ImportExportPrefs @Inject constructor(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("SameParameterValue")
|
||||||
private fun askForMasterPassIfNeeded(activity: FragmentActivity, @StringRes canceledMsg: Int, then: ((password: String) -> Unit)) {
|
private fun askForMasterPassIfNeeded(activity: FragmentActivity, @StringRes canceledMsg: Int, then: ((password: String) -> Unit)) {
|
||||||
if (prefsEncryptionIsDisabled()) {
|
if (prefsEncryptionIsDisabled()) {
|
||||||
then("")
|
then("")
|
||||||
|
@ -239,49 +238,45 @@ class ImportExportPrefs @Inject constructor(
|
||||||
ToastUtils.okToast(activity, resourceHelper.gs(R.string.exported))
|
ToastUtils.okToast(activity, resourceHelper.gs(R.string.exported))
|
||||||
} catch (e: FileNotFoundException) {
|
} catch (e: FileNotFoundException) {
|
||||||
ToastUtils.errorToast(activity, resourceHelper.gs(R.string.filenotfound) + " " + newFile)
|
ToastUtils.errorToast(activity, resourceHelper.gs(R.string.filenotfound) + " " + newFile)
|
||||||
log.error(TAG, "Unhandled exception", e)
|
log.error(LTag.CORE, "Unhandled exception", e)
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
ToastUtils.errorToast(activity, e.message)
|
ToastUtils.errorToast(activity, e.message)
|
||||||
log.error(TAG, "Unhandled exception", e)
|
log.error(LTag.CORE, "Unhandled exception", e)
|
||||||
} catch (e: PrefFileNotFoundError) {
|
} catch (e: PrefFileNotFoundError) {
|
||||||
ToastUtils.Long.errorToast(activity, resourceHelper.gs(R.string.preferences_export_canceled)
|
ToastUtils.Long.errorToast(activity, resourceHelper.gs(R.string.preferences_export_canceled)
|
||||||
+ "\n\n" + resourceHelper.gs(R.string.filenotfound)
|
+ "\n\n" + resourceHelper.gs(R.string.filenotfound)
|
||||||
+ ": " + e.message
|
+ ": " + e.message
|
||||||
+ "\n\n" + resourceHelper.gs(R.string.needstoragepermission))
|
+ "\n\n" + resourceHelper.gs(R.string.needstoragepermission))
|
||||||
log.error(TAG, "File system exception", e)
|
log.error(LTag.CORE, "File system exception", e)
|
||||||
} catch (e: PrefIOError) {
|
} catch (e: PrefIOError) {
|
||||||
ToastUtils.Long.errorToast(activity, resourceHelper.gs(R.string.preferences_export_canceled)
|
ToastUtils.Long.errorToast(activity, resourceHelper.gs(R.string.preferences_export_canceled)
|
||||||
+ "\n\n" + resourceHelper.gs(R.string.needstoragepermission)
|
+ "\n\n" + resourceHelper.gs(R.string.needstoragepermission)
|
||||||
+ ": " + e.message)
|
+ ": " + e.message)
|
||||||
log.error(TAG, "File system exception", e)
|
log.error(LTag.CORE, "File system exception", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun importSharedPreferences(fragment: Fragment) {
|
override fun importSharedPreferences(fragment: Fragment) {
|
||||||
fragment.activity?.let { fragmentAct ->
|
fragment.activity?.let { fragmentAct ->
|
||||||
importSharedPreferences(fragmentAct)
|
importSharedPreferences(fragmentAct)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun importSharedPreferences(activity: FragmentActivity) {
|
override fun importSharedPreferences(activity: FragmentActivity) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (activity is SingleFragmentActivity)
|
if (activity is DaggerAppCompatActivityWithResult)
|
||||||
activity.callForPrefFile.launch(null)
|
|
||||||
if (activity is MainActivity)
|
|
||||||
activity.callForPrefFile.launch(null)
|
|
||||||
if (activity is SetupWizardActivity)
|
|
||||||
activity.callForPrefFile.launch(null)
|
activity.callForPrefFile.launch(null)
|
||||||
} catch (e: IllegalArgumentException) {
|
} catch (e: IllegalArgumentException) {
|
||||||
// this exception happens on some early implementations of ActivityResult contracts
|
// this exception happens on some early implementations of ActivityResult contracts
|
||||||
// when registered and called for the second time
|
// when registered and called for the second time
|
||||||
ToastUtils.errorToast(activity, resourceHelper.gs(R.string.goto_main_try_again))
|
ToastUtils.errorToast(activity, resourceHelper.gs(R.string.goto_main_try_again))
|
||||||
log.error(TAG, "Internal android framework exception", e)
|
log.error(LTag.CORE, "Internal android framework exception", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun importSharedPreferences(activity: FragmentActivity, importFile: PrefsFile) {
|
override fun importSharedPreferences(activity: FragmentActivity, importFile: PrefsFile) {
|
||||||
|
|
||||||
askToConfirmImport(activity, importFile) { password ->
|
askToConfirmImport(activity, importFile) { password ->
|
||||||
|
|
||||||
|
@ -301,7 +296,7 @@ class ImportExportPrefs @Inject constructor(
|
||||||
promptForDecryptionPasswordIfNeeded(activity, prefsAttempted, importOkAttempted, format, importFile) { prefs, importOk ->
|
promptForDecryptionPasswordIfNeeded(activity, prefsAttempted, importOkAttempted, format, importFile) { prefs, importOk ->
|
||||||
|
|
||||||
// if at end we allow to import preferences
|
// if at end we allow to import preferences
|
||||||
val importPossible = (importOk || buildHelper.isEngineeringMode()) && (prefs.values.size > 0)
|
val importPossible = (importOk || buildHelper.isEngineeringMode()) && (prefs.values.isNotEmpty())
|
||||||
|
|
||||||
PrefImportSummaryDialog.showSummary(activity, importOk, importPossible, prefs, {
|
PrefImportSummaryDialog.showSummary(activity, importOk, importPossible, prefs, {
|
||||||
if (importPossible) {
|
if (importPossible) {
|
||||||
|
@ -325,9 +320,9 @@ class ImportExportPrefs @Inject constructor(
|
||||||
|
|
||||||
} catch (e: PrefFileNotFoundError) {
|
} catch (e: PrefFileNotFoundError) {
|
||||||
ToastUtils.errorToast(activity, resourceHelper.gs(R.string.filenotfound) + " " + importFile)
|
ToastUtils.errorToast(activity, resourceHelper.gs(R.string.filenotfound) + " " + importFile)
|
||||||
log.error(TAG, "Unhandled exception", e)
|
log.error(LTag.CORE, "Unhandled exception", e)
|
||||||
} catch (e: PrefIOError) {
|
} catch (e: PrefIOError) {
|
||||||
log.error(TAG, "Unhandled exception", e)
|
log.error(LTag.CORE, "Unhandled exception", e)
|
||||||
ToastUtils.errorToast(activity, e.message)
|
ToastUtils.errorToast(activity, e.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -346,13 +341,13 @@ class ImportExportPrefs @Inject constructor(
|
||||||
private fun restartAppAfterImport(context: Context) {
|
private fun restartAppAfterImport(context: Context) {
|
||||||
sp.putBoolean(R.string.key_setupwizard_processed, true)
|
sp.putBoolean(R.string.key_setupwizard_processed, true)
|
||||||
show(context, resourceHelper.gs(R.string.setting_imported), resourceHelper.gs(R.string.restartingapp), Runnable {
|
show(context, resourceHelper.gs(R.string.setting_imported), resourceHelper.gs(R.string.restartingapp), Runnable {
|
||||||
log.debug(TAG, "Exiting")
|
log.debug(LTag.CORE, "Exiting")
|
||||||
rxBus.send(EventAppExit())
|
rxBus.send(EventAppExit())
|
||||||
if (context is AppCompatActivity) {
|
if (context is AppCompatActivity) {
|
||||||
context.finish()
|
context.finish()
|
||||||
}
|
}
|
||||||
System.runFinalization()
|
System.runFinalization()
|
||||||
System.exit(0)
|
exitProcess(0)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -8,6 +8,7 @@ import android.view.ViewGroup
|
||||||
import dagger.android.support.DaggerFragment
|
import dagger.android.support.DaggerFragment
|
||||||
import info.nightscout.androidaps.MainApp
|
import info.nightscout.androidaps.MainApp
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.interfaces.ImportExportPrefsInterface
|
||||||
import info.nightscout.androidaps.plugins.general.food.FoodPlugin
|
import info.nightscout.androidaps.plugins.general.food.FoodPlugin
|
||||||
import info.nightscout.androidaps.plugins.general.maintenance.activities.LogSettingActivity
|
import info.nightscout.androidaps.plugins.general.maintenance.activities.LogSettingActivity
|
||||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
||||||
|
@ -23,7 +24,7 @@ class MaintenanceFragment : DaggerFragment() {
|
||||||
@Inject lateinit var resourceHelper: ResourceHelper
|
@Inject lateinit var resourceHelper: ResourceHelper
|
||||||
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin
|
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin
|
||||||
@Inject lateinit var foodPlugin: FoodPlugin
|
@Inject lateinit var foodPlugin: FoodPlugin
|
||||||
@Inject lateinit var importExportPrefs: ImportExportPrefs
|
@Inject lateinit var importExportPrefs: ImportExportPrefsInterface
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
return inflater.inflate(R.layout.maintenance_fragment, container, false)
|
return inflater.inflate(R.layout.maintenance_fragment, container, false)
|
||||||
|
|
|
@ -11,6 +11,7 @@ import info.nightscout.androidaps.dialogs.ProfileSwitchDialog
|
||||||
import info.nightscout.androidaps.events.EventPumpStatusChanged
|
import info.nightscout.androidaps.events.EventPumpStatusChanged
|
||||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider
|
import info.nightscout.androidaps.interfaces.ActivePluginProvider
|
||||||
import info.nightscout.androidaps.interfaces.CommandQueueProvider
|
import info.nightscout.androidaps.interfaces.CommandQueueProvider
|
||||||
|
import info.nightscout.androidaps.interfaces.ImportExportPrefsInterface
|
||||||
import info.nightscout.androidaps.interfaces.PluginType
|
import info.nightscout.androidaps.interfaces.PluginType
|
||||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||||
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
|
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
|
||||||
|
@ -18,7 +19,6 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
||||||
import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesFragment
|
import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesFragment
|
||||||
import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin
|
import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin
|
||||||
import info.nightscout.androidaps.plugins.general.maintenance.ImportExportPrefs
|
|
||||||
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin
|
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin
|
||||||
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientStatus
|
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientStatus
|
||||||
import info.nightscout.androidaps.plugins.general.nsclient.services.NSClientService
|
import info.nightscout.androidaps.plugins.general.nsclient.services.NSClientService
|
||||||
|
@ -55,7 +55,7 @@ class SWDefinition @Inject constructor(
|
||||||
private val loopPlugin: LoopPlugin,
|
private val loopPlugin: LoopPlugin,
|
||||||
private val nsClientPlugin: NSClientPlugin,
|
private val nsClientPlugin: NSClientPlugin,
|
||||||
private val nsProfilePlugin: NSProfilePlugin,
|
private val nsProfilePlugin: NSProfilePlugin,
|
||||||
private val importExportPrefs: ImportExportPrefs,
|
private val importExportPrefs: ImportExportPrefsInterface,
|
||||||
private val androidPermission: AndroidPermission,
|
private val androidPermission: AndroidPermission,
|
||||||
private val cryptoUtil: CryptoUtil,
|
private val cryptoUtil: CryptoUtil,
|
||||||
private val config: Config
|
private val config: Config
|
||||||
|
|
|
@ -14,8 +14,6 @@ import info.nightscout.androidaps.events.EventProfileNeedsUpdate
|
||||||
import info.nightscout.androidaps.events.EventProfileStoreChanged
|
import info.nightscout.androidaps.events.EventProfileStoreChanged
|
||||||
import info.nightscout.androidaps.events.EventPumpStatusChanged
|
import info.nightscout.androidaps.events.EventPumpStatusChanged
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||||
import info.nightscout.androidaps.plugins.general.maintenance.ImportExportPrefs
|
|
||||||
import info.nightscout.androidaps.plugins.general.maintenance.PrefsFileContract
|
|
||||||
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientStatus
|
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientStatus
|
||||||
import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin
|
import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin
|
||||||
import info.nightscout.androidaps.plugins.pump.common.events.EventRileyLinkDeviceStatusChange
|
import info.nightscout.androidaps.plugins.pump.common.events.EventRileyLinkDeviceStatusChange
|
||||||
|
@ -44,7 +42,6 @@ class SetupWizardActivity : NoSplashAppCompatActivity() {
|
||||||
@Inject lateinit var resourceHelper: ResourceHelper
|
@Inject lateinit var resourceHelper: ResourceHelper
|
||||||
@Inject lateinit var sp: SP
|
@Inject lateinit var sp: SP
|
||||||
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
||||||
@Inject lateinit var importExportPrefs: ImportExportPrefs
|
|
||||||
|
|
||||||
private val disposable = CompositeDisposable()
|
private val disposable = CompositeDisposable()
|
||||||
private lateinit var screens: List<SWScreen>
|
private lateinit var screens: List<SWScreen>
|
||||||
|
@ -52,12 +49,6 @@ class SetupWizardActivity : NoSplashAppCompatActivity() {
|
||||||
|
|
||||||
private val intentMessage = "WIZZARDPAGE"
|
private val intentMessage = "WIZZARDPAGE"
|
||||||
|
|
||||||
val callForPrefFile = registerForActivityResult(PrefsFileContract()) {
|
|
||||||
it?.let {
|
|
||||||
importExportPrefs.importSharedPreferences(this, it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
update(applicationContext)
|
update(applicationContext)
|
||||||
|
@ -213,7 +204,7 @@ class SetupWizardActivity : NoSplashAppCompatActivity() {
|
||||||
if (permissions.isNotEmpty()) {
|
if (permissions.isNotEmpty()) {
|
||||||
if (ActivityCompat.checkSelfPermission(this, permissions[0]) == PackageManager.PERMISSION_GRANTED) {
|
if (ActivityCompat.checkSelfPermission(this, permissions[0]) == PackageManager.PERMISSION_GRANTED) {
|
||||||
when (requestCode) {
|
when (requestCode) {
|
||||||
AndroidPermission.CASE_STORAGE -> //show dialog after permission is granted
|
AndroidPermission.CASE_STORAGE -> //show dialog after permission is granted
|
||||||
show(this, resourceHelper.gs(R.string.permission), resourceHelper.gs(R.string.alert_dialog_storage_permission_text))
|
show(this, resourceHelper.gs(R.string.permission), resourceHelper.gs(R.string.alert_dialog_storage_permission_text))
|
||||||
|
|
||||||
AndroidPermission.CASE_LOCATION, AndroidPermission.CASE_SMS, AndroidPermission.CASE_BATTERY -> {
|
AndroidPermission.CASE_LOCATION, AndroidPermission.CASE_SMS, AndroidPermission.CASE_BATTERY -> {
|
||||||
|
|
|
@ -64,10 +64,6 @@
|
||||||
|
|
||||||
<color name="splashBackground">#2E2E2E</color>
|
<color name="splashBackground">#2E2E2E</color>
|
||||||
|
|
||||||
<color name="metadataOk">#77dd77</color>
|
|
||||||
<color name="metadataTextWarning">#FF8C00</color>
|
|
||||||
<color name="metadataTextError">#FF5555</color>
|
|
||||||
|
|
||||||
<color name="importListFileName">#FFFFFF</color>
|
<color name="importListFileName">#FFFFFF</color>
|
||||||
<color name="importListAdditionalInfo">#BBBBBB</color>
|
<color name="importListAdditionalInfo">#BBBBBB</color>
|
||||||
|
|
||||||
|
|
|
@ -66,16 +66,4 @@
|
||||||
<string name="failedretrievetime">Failed retrieve time</string>
|
<string name="failedretrievetime">Failed retrieve time</string>
|
||||||
<string name="requirementnotmet">Objective requirements not met</string>
|
<string name="requirementnotmet">Objective requirements not met</string>
|
||||||
|
|
||||||
<plurals name="objective_days">
|
|
||||||
<item quantity="one">%1$d day</item>
|
|
||||||
<item quantity="other">%1$d days</item>
|
|
||||||
</plurals>
|
|
||||||
<plurals name="objective_hours">
|
|
||||||
<item quantity="one">%1$d hour</item>
|
|
||||||
<item quantity="other">%1$d hours</item>
|
|
||||||
</plurals>
|
|
||||||
<plurals name="objective_minutes">
|
|
||||||
<item quantity="one">%1$d minute</item>
|
|
||||||
<item quantity="other">%1$d minutes</item>
|
|
||||||
</plurals>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -204,8 +204,6 @@
|
||||||
<string name="different_password_used">This file was exported and encrypted with different master password. Provide old master password to decrypt file.</string>
|
<string name="different_password_used">This file was exported and encrypted with different master password. Provide old master password to decrypt file.</string>
|
||||||
<string name="master_password_will_be_replaced">As a result of successful import current master password WILL BE REPLACED with that old master password!</string>
|
<string name="master_password_will_be_replaced">As a result of successful import current master password WILL BE REPLACED with that old master password!</string>
|
||||||
|
|
||||||
<string name="preferences_import_list_title">Select file to import</string>
|
|
||||||
|
|
||||||
<string name="check_preferences_before_import">Please check preferences before importing:</string>
|
<string name="check_preferences_before_import">Please check preferences before importing:</string>
|
||||||
<string name="check_preferences_cannot_import">Preferences cannot be imported!</string>
|
<string name="check_preferences_cannot_import">Preferences cannot be imported!</string>
|
||||||
<string name="check_preferences_dangerous_import">Preferences should not be imported!</string>
|
<string name="check_preferences_dangerous_import">Preferences should not be imported!</string>
|
||||||
|
@ -214,45 +212,6 @@
|
||||||
<string name="check_preferences_import_btn">Import</string>
|
<string name="check_preferences_import_btn">Import</string>
|
||||||
<string name="check_preferences_import_anyway_btn">Import anyway (DANGEROUS!)</string>
|
<string name="check_preferences_import_anyway_btn">Import anyway (DANGEROUS!)</string>
|
||||||
|
|
||||||
<string name="metadata_warning_different_flavour">Preferences were created with different variant of AAPS (%1$s) while you have: %2$s.\n\nSome settings may be missing or invalid - after importing please check and update your preferences.</string>
|
|
||||||
<string name="metadata_warning_different_device">Preferences were created on a different device. It is OK if you are importing from older/different phone, but make sure imported preferences are correct!</string>
|
|
||||||
<string name="metadata_warning_outdated_format">You are using the outdated legacy format from old versions of AAPS, which is not secure! Only use it as a last resort, if you do not have an export in current, JSON format.</string>
|
|
||||||
<string name="metadata_warning_old_export">Imported preferences are already %1$s days old! Maybe you have more up-to-date preferences or you choose the wrong file? Remember to export preferences regularly!</string>
|
|
||||||
<string name="metadata_warning_date_format">Invalid date-time format!</string>
|
|
||||||
<string name="metadata_warning_different_version">Preferences from different minor version of application. It is OK if you are importing after upgrade, but check after import if preferences are still correct!</string>
|
|
||||||
<string name="metadata_urgent_different_version">Preferences from different major version of application. Major versions differ significantly and may have incompatible preferences! Make sure after import that preferences are still correct!</string>
|
|
||||||
|
|
||||||
<string name="metadata_label_format">File format</string>
|
|
||||||
<string name="metadata_label_created_at">Created at</string>
|
|
||||||
<string name="metadata_label_aaps_version">AAPS Version</string>
|
|
||||||
<string name="metadata_label_aaps_flavour">Build Variant</string>
|
|
||||||
<string name="metadata_label_device_name">Exporting device patient name</string>
|
|
||||||
<string name="metadata_label_device_model">Exporting device model</string>
|
|
||||||
<string name="metadata_label_encryption">File encryption</string>
|
|
||||||
|
|
||||||
<string name="metadata_format_old">Old export format</string>
|
|
||||||
<string name="metadata_format_new">New encrypted format</string>
|
|
||||||
<string name="metadata_format_debug">New debug format (unencrypted)</string>
|
|
||||||
<string name="metadata_format_other">Unknown export format</string>
|
|
||||||
|
|
||||||
<string name="prefdecrypt_settings_tampered">Settings file tampered</string>
|
|
||||||
<string name="prefdecrypt_settings_secure">Settings file is secure</string>
|
|
||||||
<string name="prefdecrypt_settings_unencrypted">Using not secure, unencrypted settings format</string>
|
|
||||||
<string name="prefdecrypt_wrong_json">JSON format error, missing required field (format, content, metadata or security)</string>
|
|
||||||
<string name="prefdecrypt_wrong_password">Decryption error, the given password cannot decrypt the file</string>
|
|
||||||
|
|
||||||
<string name="prefdecrypt_issue_missing_file_hash">File checksum (hash) missing, cannot verify the authenticity of settings!</string>
|
|
||||||
<string name="prefdecrypt_issue_modified">File was modified after export!</string>
|
|
||||||
<string name="prefdecrypt_issue_parsing">Decryption error, parsing preferences failed!</string>
|
|
||||||
<string name="prefdecrypt_issue_wrong_pass">Decryption error, the provided password is invalid or settings file was modified! It may happen that the imported file was exported with a different Master password.</string>
|
|
||||||
<string name="prefdecrypt_issue_wrong_format">Missing encryption configuration, settings format is invalid!</string>
|
|
||||||
<string name="prefdecrypt_issue_wrong_algorithm">Unsupported or not specified encryption algorithm!</string>
|
|
||||||
|
|
||||||
<string name="exported_ago" comment="at placeholder we add pluralized number of hours/minutes">exported %1$s ago</string>
|
|
||||||
<string name="exported_at" comment="at placeholder we add export date">exported at %1$s</string>
|
|
||||||
<string name="exported_less_than_hour_ago">exported less than hour ago</string>
|
|
||||||
<string name="in_directory" comment="placeholder is for exported file path">in directory: %1$s</string>
|
|
||||||
|
|
||||||
<string name="end_user_license_agreement">End User License Agreement</string>
|
<string name="end_user_license_agreement">End User License Agreement</string>
|
||||||
<string name="end_user_license_agreement_text">MUST NOT BE USED TO MAKE MEDICAL DECISIONS. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</string>
|
<string name="end_user_license_agreement_text">MUST NOT BE USED TO MAKE MEDICAL DECISIONS. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</string>
|
||||||
<string name="end_user_license_agreement_i_understand">I UNDERSTAND AND AGREE</string>
|
<string name="end_user_license_agreement_i_understand">I UNDERSTAND AND AGREE</string>
|
||||||
|
@ -977,7 +936,6 @@
|
||||||
<string name="nav_logsettings">Log settings</string>
|
<string name="nav_logsettings">Log settings</string>
|
||||||
<string name="resettodefaults">Reset to defaults</string>
|
<string name="resettodefaults">Reset to defaults</string>
|
||||||
<string name="nsmalfunction">NSClient malfunction. Consider NS and NSClient restart.</string>
|
<string name="nsmalfunction">NSClient malfunction. Consider NS and NSClient restart.</string>
|
||||||
<string name="versionavailable">Version %1$s available</string>
|
|
||||||
<string name="time_offset">Time offset</string>
|
<string name="time_offset">Time offset</string>
|
||||||
<string name="key_aps_mode" translatable="false">aps_mode</string>
|
<string name="key_aps_mode" translatable="false">aps_mode</string>
|
||||||
<string name="setupwizard_preferred_aps_mode">Preferred APS mode</string>
|
<string name="setupwizard_preferred_aps_mode">Preferred APS mode</string>
|
||||||
|
@ -1158,12 +1116,6 @@
|
||||||
<string name="copy_short">COPY</string>
|
<string name="copy_short">COPY</string>
|
||||||
<string name="addnew">Add new</string>
|
<string name="addnew">Add new</string>
|
||||||
<string name="versionChecker">Version Checker</string>
|
<string name="versionChecker">Version Checker</string>
|
||||||
<string name="key_last_time_this_version_detected" translatable="false">last_time_this_version_detected</string>
|
|
||||||
<string name="key_last_versionchecker_warning" translatable="false">last_versionchecker_waring</string>
|
|
||||||
<string name="key_last_versionchecker_plugin_warning" translatable="false">last_versionchecker_plugin_waring</string>
|
|
||||||
<string name="key_last_revoked_certs_check" translatable="false">last_revoked_certs_check</string>
|
|
||||||
<string name="signature_verifier">Signature verifier</string>
|
|
||||||
<string name="running_invalid_version">We have detected that you are running an invalid version. Loop disabled!</string>
|
|
||||||
|
|
||||||
<string name="old_version">old version</string>
|
<string name="old_version">old version</string>
|
||||||
<string name="very_old_version">very old version</string>
|
<string name="very_old_version">very old version</string>
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package info.nightscout.androidaps.activities
|
||||||
|
|
||||||
|
import dagger.android.support.DaggerAppCompatActivity
|
||||||
|
import info.nightscout.androidaps.interfaces.ImportExportPrefsInterface
|
||||||
|
import info.nightscout.androidaps.plugins.general.maintenance.PrefsFileContract
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
open class DaggerAppCompatActivityWithResult : DaggerAppCompatActivity() {
|
||||||
|
|
||||||
|
@Inject lateinit var importExportPrefs: ImportExportPrefsInterface
|
||||||
|
|
||||||
|
val callForPrefFile = registerForActivityResult(PrefsFileContract()) {
|
||||||
|
it?.let {
|
||||||
|
importExportPrefs.importSharedPreferences(this, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,12 +2,10 @@ package info.nightscout.androidaps.activities
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import dagger.android.support.DaggerAppCompatActivity
|
|
||||||
import info.nightscout.androidaps.core.R
|
import info.nightscout.androidaps.core.R
|
||||||
import info.nightscout.androidaps.utils.locale.LocaleHelper
|
import info.nightscout.androidaps.utils.locale.LocaleHelper
|
||||||
|
|
||||||
//@Suppress("registered")
|
open class NoSplashAppCompatActivity : DaggerAppCompatActivityWithResult() {
|
||||||
open class NoSplashAppCompatActivity : DaggerAppCompatActivity() {
|
|
||||||
|
|
||||||
public override fun onCreate(savedInstanceState: Bundle?) {
|
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
|
@ -9,11 +9,13 @@ import info.nightscout.androidaps.dialogs.BolusProgressDialog
|
||||||
import info.nightscout.androidaps.dialogs.ErrorDialog
|
import info.nightscout.androidaps.dialogs.ErrorDialog
|
||||||
import info.nightscout.androidaps.dialogs.NtpProgressDialog
|
import info.nightscout.androidaps.dialogs.NtpProgressDialog
|
||||||
import info.nightscout.androidaps.dialogs.ProfileViewerDialog
|
import info.nightscout.androidaps.dialogs.ProfileViewerDialog
|
||||||
|
import info.nightscout.androidaps.plugins.general.maintenance.activities.PrefImportListActivity
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
abstract class CoreFragmentsModule {
|
abstract class CoreFragmentsModule {
|
||||||
|
|
||||||
|
@ContributesAndroidInjector abstract fun contributesPrefImportListActivity(): PrefImportListActivity
|
||||||
@ContributesAndroidInjector abstract fun contributesTDDStatsActivity(): TDDStatsActivity
|
@ContributesAndroidInjector abstract fun contributesTDDStatsActivity(): TDDStatsActivity
|
||||||
@ContributesAndroidInjector abstract fun contributeBolusProgressHelperActivity(): BolusProgressHelperActivity
|
@ContributesAndroidInjector abstract fun contributeBolusProgressHelperActivity(): BolusProgressHelperActivity
|
||||||
@ContributesAndroidInjector abstract fun contributeErrorHelperActivity(): ErrorHelperActivity
|
@ContributesAndroidInjector abstract fun contributeErrorHelperActivity(): ErrorHelperActivity
|
||||||
|
|
|
@ -6,4 +6,6 @@ interface ConfigInterface {
|
||||||
val NSCLIENT: Boolean
|
val NSCLIENT: Boolean
|
||||||
val PUMPCONTROL: Boolean
|
val PUMPCONTROL: Boolean
|
||||||
val PUMPDRIVERS: Boolean
|
val PUMPDRIVERS: Boolean
|
||||||
|
val FLAVOR: String
|
||||||
|
val VERSION_NAME: String
|
||||||
}
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package info.nightscout.androidaps.interfaces
|
||||||
|
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
import info.nightscout.androidaps.plugins.general.maintenance.PrefsFile
|
||||||
|
|
||||||
|
interface ImportExportPrefsInterface {
|
||||||
|
|
||||||
|
fun importSharedPreferences(activity: FragmentActivity, importFile: PrefsFile)
|
||||||
|
fun importSharedPreferences(activity: FragmentActivity)
|
||||||
|
fun importSharedPreferences(fragment: Fragment)
|
||||||
|
fun prefsFileExists(): Boolean
|
||||||
|
fun verifyStoragePermissions(fragment: Fragment, onGranted: Runnable)
|
||||||
|
fun exportSharedPreferences(f: Fragment)
|
||||||
|
}
|
|
@ -2,9 +2,8 @@ package info.nightscout.androidaps.plugins.constraints.versionChecker
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.ConnectivityManager
|
import android.net.ConnectivityManager
|
||||||
import info.nightscout.androidaps.BuildConfig
|
import info.nightscout.androidaps.core.R
|
||||||
import info.nightscout.androidaps.MainApp
|
import info.nightscout.androidaps.interfaces.ConfigInterface
|
||||||
import info.nightscout.androidaps.R
|
|
||||||
import info.nightscout.androidaps.logging.AAPSLogger
|
import info.nightscout.androidaps.logging.AAPSLogger
|
||||||
import info.nightscout.androidaps.logging.LTag
|
import info.nightscout.androidaps.logging.LTag
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||||
|
@ -24,6 +23,7 @@ class VersionCheckerUtils @Inject constructor(
|
||||||
val sp: SP,
|
val sp: SP,
|
||||||
val resourceHelper: ResourceHelper,
|
val resourceHelper: ResourceHelper,
|
||||||
val rxBus: RxBusWrapper,
|
val rxBus: RxBusWrapper,
|
||||||
|
private val config: ConfigInterface,
|
||||||
val context: Context
|
val context: Context
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ class VersionCheckerUtils @Inject constructor(
|
||||||
Thread {
|
Thread {
|
||||||
try {
|
try {
|
||||||
val version: String? = findVersion(URL("https://raw.githubusercontent.com/nightscout/AndroidAPS/master/app/build.gradle").readText())
|
val version: String? = findVersion(URL("https://raw.githubusercontent.com/nightscout/AndroidAPS/master/app/build.gradle").readText())
|
||||||
compareWithCurrentVersion(version, BuildConfig.VERSION_NAME)
|
compareWithCurrentVersion(version, config.VERSION_NAME)
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
aapsLogger.error(LTag.CORE, "Github master version check error: $e")
|
aapsLogger.error(LTag.CORE, "Github master version check error: $e")
|
||||||
}
|
}
|
||||||
|
@ -130,6 +130,7 @@ class VersionCheckerUtils @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private val CHECK_EVERY = TimeUnit.DAYS.toMillis(1)
|
private val CHECK_EVERY = TimeUnit.DAYS.toMillis(1)
|
||||||
private val WARN_EVERY = TimeUnit.DAYS.toMillis(1)
|
private val WARN_EVERY = TimeUnit.DAYS.toMillis(1)
|
||||||
}
|
}
|
||||||
|
@ -148,7 +149,7 @@ fun findVersion(file: String?): String? {
|
||||||
fun String.versionStrip() = this.mapNotNull {
|
fun String.versionStrip() = this.mapNotNull {
|
||||||
when (it) {
|
when (it) {
|
||||||
in '0'..'9' -> it
|
in '0'..'9' -> it
|
||||||
'.' -> it
|
'.' -> it
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}.joinToString(separator = "")
|
}.joinToString(separator = "")
|
|
@ -1,220 +1,178 @@
|
||||||
package info.nightscout.androidaps.plugins.general.maintenance
|
package info.nightscout.androidaps.plugins.general.maintenance
|
||||||
|
|
||||||
import android.content.Context
|
import android.os.Build
|
||||||
import android.content.Intent
|
import android.os.Environment
|
||||||
import android.os.Build
|
import info.nightscout.androidaps.core.R
|
||||||
import android.os.Environment
|
import info.nightscout.androidaps.interfaces.ConfigInterface
|
||||||
import android.os.Parcelable
|
import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtils
|
||||||
import androidx.activity.result.contract.ActivityResultContract
|
import info.nightscout.androidaps.plugins.general.maintenance.formats.*
|
||||||
import androidx.fragment.app.FragmentActivity
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.BuildConfig
|
import info.nightscout.androidaps.utils.storage.Storage
|
||||||
import info.nightscout.androidaps.R
|
import org.joda.time.DateTime
|
||||||
import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtils
|
import org.joda.time.Days
|
||||||
import info.nightscout.androidaps.plugins.general.maintenance.activities.PrefImportListActivity
|
import org.joda.time.Hours
|
||||||
import info.nightscout.androidaps.plugins.general.maintenance.formats.*
|
import org.joda.time.LocalDateTime
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import org.joda.time.format.DateTimeFormat
|
||||||
import info.nightscout.androidaps.utils.storage.Storage
|
import java.io.File
|
||||||
import kotlinx.android.parcel.Parcelize
|
import javax.inject.Inject
|
||||||
import kotlinx.android.parcel.RawValue
|
import javax.inject.Singleton
|
||||||
import org.joda.time.DateTime
|
import kotlin.math.abs
|
||||||
import org.joda.time.Days
|
|
||||||
import org.joda.time.Hours
|
fun getCurrentDeviceModelString() =
|
||||||
import org.joda.time.LocalDateTime
|
Build.MANUFACTURER + " " + Build.MODEL + " (" + Build.DEVICE + ")"
|
||||||
import org.joda.time.format.DateTimeFormat
|
|
||||||
import java.io.File
|
@Singleton
|
||||||
import javax.inject.Inject
|
class PrefFileListProvider @Inject constructor(
|
||||||
import javax.inject.Singleton
|
private val resourceHelper: ResourceHelper,
|
||||||
|
private val config: ConfigInterface,
|
||||||
enum class PrefsImportDir {
|
private val classicPrefsFormat: ClassicPrefsFormat,
|
||||||
ROOT_DIR,
|
private val encryptedPrefsFormat: EncryptedPrefsFormat,
|
||||||
AAPS_DIR
|
private val storage: Storage,
|
||||||
}
|
private val versionCheckerUtils: VersionCheckerUtils
|
||||||
|
) {
|
||||||
@Parcelize
|
|
||||||
data class PrefsFile(
|
companion object {
|
||||||
val name: String,
|
|
||||||
val file: File,
|
private val path = File(Environment.getExternalStorageDirectory().toString())
|
||||||
val baseDir: File,
|
private val aapsPath = File(path, "AAPS" + File.separator + "preferences")
|
||||||
val dirKind: PrefsImportDir,
|
private const val IMPORT_AGE_NOT_YET_OLD_DAYS = 60
|
||||||
val handler: PrefsFormatsHandler,
|
}
|
||||||
|
|
||||||
// metadata here is used only for list display
|
/**
|
||||||
val metadata: @RawValue Map<PrefsMetadataKey, PrefMetadata>
|
* This function tries to list possible preference files from main SDCard root dir and AAPS/preferences dir
|
||||||
) : Parcelable
|
* and tries to do quick assessment for preferences format plausibility.
|
||||||
|
* It does NOT load full metadata or is 100% accurate - it tries to do QUICK detection, based on:
|
||||||
class PrefsFileContract : ActivityResultContract<Void, PrefsFile>() {
|
* - file name and extension
|
||||||
|
* - predicted file contents
|
||||||
companion object {
|
*/
|
||||||
|
fun listPreferenceFiles(loadMetadata: Boolean = false): MutableList<PrefsFile> {
|
||||||
const val OUTPUT_PARAM = "prefs_file"
|
val prefFiles = mutableListOf<PrefsFile>()
|
||||||
}
|
|
||||||
|
// searching rood dir for legacy files
|
||||||
override fun parseResult(resultCode: Int, intent: Intent?): PrefsFile? {
|
path.walk().maxDepth(1).filter { it.isFile && (it.name.endsWith(".json") || it.name.contains("Preferences")) }.forEach {
|
||||||
return when (resultCode) {
|
val contents = storage.getFileContents(it)
|
||||||
FragmentActivity.RESULT_OK -> intent?.getParcelableExtra(OUTPUT_PARAM)
|
val detectedNew = encryptedPrefsFormat.isPreferencesFile(it, contents)
|
||||||
else -> null
|
val detectedOld = !detectedNew && classicPrefsFormat.isPreferencesFile(it, contents)
|
||||||
}
|
if (detectedNew || detectedOld) {
|
||||||
}
|
val formatHandler = if (detectedNew) PrefsFormatsHandler.ENCRYPTED else PrefsFormatsHandler.CLASSIC
|
||||||
|
prefFiles.add(PrefsFile(it.name, it, path, PrefsImportDir.ROOT_DIR, formatHandler, metadataFor(loadMetadata, formatHandler, contents)))
|
||||||
override fun createIntent(context: Context, input: Void?): Intent {
|
}
|
||||||
return Intent(context, PrefImportListActivity::class.java)
|
}
|
||||||
}
|
|
||||||
}
|
// searching dedicated dir, only for new JSON format
|
||||||
|
aapsPath.walk().filter { it.isFile && it.name.endsWith(".json") }.forEach {
|
||||||
fun getCurrentDeviceModelString() =
|
val contents = storage.getFileContents(it)
|
||||||
Build.MANUFACTURER + " " + Build.MODEL + " (" + Build.DEVICE + ")"
|
if (encryptedPrefsFormat.isPreferencesFile(it, contents)) {
|
||||||
|
prefFiles.add(PrefsFile(it.name, it, aapsPath, PrefsImportDir.AAPS_DIR, PrefsFormatsHandler.ENCRYPTED, metadataFor(loadMetadata, PrefsFormatsHandler.ENCRYPTED, contents)))
|
||||||
@Singleton
|
}
|
||||||
class PrefFileListProvider @Inject constructor(
|
}
|
||||||
private val resourceHelper: ResourceHelper,
|
|
||||||
private val classicPrefsFormat: ClassicPrefsFormat,
|
// we sort only if we have metadata to be used for that
|
||||||
private val encryptedPrefsFormat: EncryptedPrefsFormat,
|
if (loadMetadata) {
|
||||||
private val storage: Storage,
|
prefFiles.sortWith(
|
||||||
private val versionCheckerUtils: VersionCheckerUtils
|
compareByDescending<PrefsFile> { it.handler }
|
||||||
) {
|
.thenBy { it.metadata[PrefsMetadataKey.AAPS_FLAVOUR]?.status }
|
||||||
|
.thenByDescending { it.metadata[PrefsMetadataKey.CREATED_AT]?.value }
|
||||||
companion object {
|
)
|
||||||
|
}
|
||||||
private val path = File(Environment.getExternalStorageDirectory().toString())
|
|
||||||
private val aapsPath = File(path, "AAPS" + File.separator + "preferences")
|
return prefFiles
|
||||||
private const val IMPORT_AGE_NOT_YET_OLD_DAYS = 60
|
}
|
||||||
}
|
|
||||||
|
private fun metadataFor(loadMetadata: Boolean, formatHandler: PrefsFormatsHandler, contents: String): PrefMetadataMap {
|
||||||
/**
|
if (!loadMetadata) {
|
||||||
* This function tries to list possible preference files from main SDCard root dir and AAPS/preferences dir
|
return mapOf()
|
||||||
* and tries to do quick assessment for preferences format plausibility.
|
}
|
||||||
* It does NOT load full metadata or is 100% accurate - it tries to do QUICK detection, based on:
|
return checkMetadata(when (formatHandler) {
|
||||||
* - file name and extension
|
PrefsFormatsHandler.CLASSIC -> classicPrefsFormat.loadMetadata(contents)
|
||||||
* - predicted file contents
|
PrefsFormatsHandler.ENCRYPTED -> encryptedPrefsFormat.loadMetadata(contents)
|
||||||
*/
|
})
|
||||||
fun listPreferenceFiles(loadMetadata: Boolean = false): MutableList<PrefsFile> {
|
}
|
||||||
val prefFiles = mutableListOf<PrefsFile>()
|
|
||||||
|
fun legacyFile(): File {
|
||||||
// searching rood dir for legacy files
|
return File(path, resourceHelper.gs(R.string.app_name) + "Preferences")
|
||||||
path.walk().maxDepth(1).filter { it.isFile && (it.name.endsWith(".json") || it.name.contains("Preferences")) }.forEach {
|
}
|
||||||
val contents = storage.getFileContents(it)
|
|
||||||
val detectedNew = encryptedPrefsFormat.isPreferencesFile(it, contents)
|
fun ensureExportDirExists() {
|
||||||
val detectedOld = !detectedNew && classicPrefsFormat.isPreferencesFile(it, contents)
|
if (!aapsPath.exists()) {
|
||||||
if (detectedNew || detectedOld) {
|
aapsPath.mkdirs()
|
||||||
val formatHandler = if (detectedNew) PrefsFormatsHandler.ENCRYPTED else PrefsFormatsHandler.CLASSIC
|
}
|
||||||
prefFiles.add(PrefsFile(it.name, it, path, PrefsImportDir.ROOT_DIR, formatHandler, metadataFor(loadMetadata, formatHandler, contents)))
|
}
|
||||||
}
|
|
||||||
}
|
fun newExportFile(): File {
|
||||||
|
val timeLocal = LocalDateTime.now().toString(DateTimeFormat.forPattern("yyyy-MM-dd'_'HHmmss"))
|
||||||
// searching dedicated dir, only for new JSON format
|
return File(aapsPath, timeLocal + "_" + config.FLAVOR + ".json")
|
||||||
aapsPath.walk().filter { it.isFile && it.name.endsWith(".json") }.forEach {
|
}
|
||||||
val contents = storage.getFileContents(it)
|
|
||||||
if (encryptedPrefsFormat.isPreferencesFile(it, contents)) {
|
// check metadata for known issues, change their status and add info with explanations
|
||||||
prefFiles.add(PrefsFile(it.name, it, aapsPath, PrefsImportDir.AAPS_DIR, PrefsFormatsHandler.ENCRYPTED, metadataFor(loadMetadata, PrefsFormatsHandler.ENCRYPTED, contents)))
|
fun checkMetadata(metadata: Map<PrefsMetadataKey, PrefMetadata>): Map<PrefsMetadataKey, PrefMetadata> {
|
||||||
}
|
val meta = metadata.toMutableMap()
|
||||||
}
|
|
||||||
|
meta[PrefsMetadataKey.AAPS_FLAVOUR]?.let { flavour ->
|
||||||
// we sort only if we have metadata to be used for that
|
val flavourOfPrefs = flavour.value
|
||||||
if (loadMetadata) {
|
if (flavour.value != config.FLAVOR) {
|
||||||
prefFiles.sortWith(
|
flavour.status = PrefsStatus.WARN
|
||||||
compareByDescending<PrefsFile> { it.handler }
|
flavour.info = resourceHelper.gs(R.string.metadata_warning_different_flavour, flavourOfPrefs, config.FLAVOR)
|
||||||
.thenBy { it.metadata[PrefsMetadataKey.AAPS_FLAVOUR]?.status }
|
}
|
||||||
.thenByDescending { it.metadata[PrefsMetadataKey.CREATED_AT]?.value }
|
}
|
||||||
)
|
|
||||||
}
|
meta[PrefsMetadataKey.DEVICE_MODEL]?.let { model ->
|
||||||
|
if (model.value != getCurrentDeviceModelString()) {
|
||||||
return prefFiles
|
model.status = PrefsStatus.WARN
|
||||||
}
|
model.info = resourceHelper.gs(R.string.metadata_warning_different_device)
|
||||||
|
}
|
||||||
private fun metadataFor(loadMetadata: Boolean, formatHandler: PrefsFormatsHandler, contents: String): PrefMetadataMap {
|
}
|
||||||
if (!loadMetadata) {
|
|
||||||
return mapOf()
|
meta[PrefsMetadataKey.CREATED_AT]?.let { createdAt ->
|
||||||
}
|
try {
|
||||||
return checkMetadata(when (formatHandler) {
|
val date1 = DateTime.parse(createdAt.value)
|
||||||
PrefsFormatsHandler.CLASSIC -> classicPrefsFormat.loadMetadata(contents)
|
val date2 = DateTime.now()
|
||||||
PrefsFormatsHandler.ENCRYPTED -> encryptedPrefsFormat.loadMetadata(contents)
|
|
||||||
})
|
val daysOld = Days.daysBetween(date1.toLocalDate(), date2.toLocalDate()).days
|
||||||
}
|
|
||||||
|
if (daysOld > IMPORT_AGE_NOT_YET_OLD_DAYS) {
|
||||||
fun legacyFile(): File {
|
createdAt.status = PrefsStatus.WARN
|
||||||
return File(path, resourceHelper.gs(R.string.app_name) + "Preferences")
|
createdAt.info = resourceHelper.gs(R.string.metadata_warning_old_export, daysOld.toString())
|
||||||
}
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
fun ensureExportDirExists() {
|
createdAt.status = PrefsStatus.WARN
|
||||||
if (!aapsPath.exists()) {
|
createdAt.info = resourceHelper.gs(R.string.metadata_warning_date_format)
|
||||||
aapsPath.mkdirs()
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
meta[PrefsMetadataKey.AAPS_VERSION]?.let { version ->
|
||||||
fun newExportFile(): File {
|
val currentAppVer = versionCheckerUtils.versionDigits(config.VERSION_NAME)
|
||||||
val timeLocal = LocalDateTime.now().toString(DateTimeFormat.forPattern("yyyy-MM-dd'_'HHmmss"))
|
val metadataVer = versionCheckerUtils.versionDigits(version.value)
|
||||||
return File(aapsPath, timeLocal + "_" + BuildConfig.FLAVOR + ".json")
|
|
||||||
}
|
if ((currentAppVer.size >= 2) && (metadataVer.size >= 2) && (abs(currentAppVer[1] - metadataVer[1]) > 1)) {
|
||||||
|
version.status = PrefsStatus.WARN
|
||||||
// check metadata for known issues, change their status and add info with explanations
|
version.info = resourceHelper.gs(R.string.metadata_warning_different_version)
|
||||||
fun checkMetadata(metadata: Map<PrefsMetadataKey, PrefMetadata>): Map<PrefsMetadataKey, PrefMetadata> {
|
}
|
||||||
val meta = metadata.toMutableMap()
|
|
||||||
|
if ((currentAppVer.isNotEmpty()) && (metadataVer.isNotEmpty()) && (currentAppVer[0] != metadataVer[0])) {
|
||||||
meta[PrefsMetadataKey.AAPS_FLAVOUR]?.let { flavour ->
|
version.status = PrefsStatus.WARN
|
||||||
val flavourOfPrefs = flavour.value
|
version.info = resourceHelper.gs(R.string.metadata_urgent_different_version)
|
||||||
if (flavour.value != BuildConfig.FLAVOR) {
|
}
|
||||||
flavour.status = PrefsStatus.WARN
|
}
|
||||||
flavour.info = resourceHelper.gs(R.string.metadata_warning_different_flavour, flavourOfPrefs, BuildConfig.FLAVOR)
|
|
||||||
}
|
return meta
|
||||||
}
|
}
|
||||||
|
|
||||||
meta[PrefsMetadataKey.DEVICE_MODEL]?.let { model ->
|
fun formatExportedAgo(utcTime: String): String {
|
||||||
if (model.value != getCurrentDeviceModelString()) {
|
val refTime = DateTime.now()
|
||||||
model.status = PrefsStatus.WARN
|
val itTime = DateTime.parse(utcTime)
|
||||||
model.info = resourceHelper.gs(R.string.metadata_warning_different_device)
|
val days = Days.daysBetween(itTime, refTime).days
|
||||||
}
|
val hours = Hours.hoursBetween(itTime, refTime).hours
|
||||||
}
|
|
||||||
|
return if (hours == 0) {
|
||||||
meta[PrefsMetadataKey.CREATED_AT]?.let { createdAt ->
|
resourceHelper.gs(R.string.exported_less_than_hour_ago)
|
||||||
try {
|
} else if ((hours < 24) && (hours > 0)) {
|
||||||
val date1 = DateTime.parse(createdAt.value)
|
resourceHelper.gs(R.string.exported_ago, resourceHelper.gq(R.plurals.hours, hours, hours))
|
||||||
val date2 = DateTime.now()
|
} else if ((days < IMPORT_AGE_NOT_YET_OLD_DAYS) && (days > 0)) {
|
||||||
|
resourceHelper.gs(R.string.exported_ago, resourceHelper.gq(R.plurals.days, days, days))
|
||||||
val daysOld = Days.daysBetween(date1.toLocalDate(), date2.toLocalDate()).days
|
} else {
|
||||||
|
resourceHelper.gs(R.string.exported_at, utcTime.substring(0, 10))
|
||||||
if (daysOld > IMPORT_AGE_NOT_YET_OLD_DAYS) {
|
}
|
||||||
createdAt.status = PrefsStatus.WARN
|
}
|
||||||
createdAt.info = resourceHelper.gs(R.string.metadata_warning_old_export, daysOld.toString())
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
createdAt.status = PrefsStatus.WARN
|
|
||||||
createdAt.info = resourceHelper.gs(R.string.metadata_warning_date_format)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
meta[PrefsMetadataKey.AAPS_VERSION]?.let { version ->
|
|
||||||
val currentAppVer = versionCheckerUtils.versionDigits(BuildConfig.VERSION_NAME)
|
|
||||||
val metadataVer = versionCheckerUtils.versionDigits(version.value)
|
|
||||||
|
|
||||||
if ((currentAppVer.size >= 2) && (metadataVer.size >= 2) && (Math.abs(currentAppVer[1] - metadataVer[1]) > 1)) {
|
|
||||||
version.status = PrefsStatus.WARN
|
|
||||||
version.info = resourceHelper.gs(R.string.metadata_warning_different_version)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((currentAppVer.isNotEmpty()) && (metadataVer.isNotEmpty()) && (currentAppVer[0] != metadataVer[0])) {
|
|
||||||
version.status = PrefsStatus.WARN
|
|
||||||
version.info = resourceHelper.gs(R.string.metadata_urgent_different_version)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return meta
|
|
||||||
}
|
|
||||||
|
|
||||||
fun formatExportedAgo(utcTime: String): String {
|
|
||||||
val refTime = DateTime.now()
|
|
||||||
val itTime = DateTime.parse(utcTime)
|
|
||||||
val days = Days.daysBetween(itTime, refTime).days
|
|
||||||
val hours = Hours.hoursBetween(itTime, refTime).hours
|
|
||||||
|
|
||||||
return if (hours == 0) {
|
|
||||||
resourceHelper.gs(R.string.exported_less_than_hour_ago)
|
|
||||||
} else if ((hours < 24) && (hours > 0)) {
|
|
||||||
resourceHelper.gs(R.string.exported_ago, resourceHelper.gq(R.plurals.objective_hours, hours, hours))
|
|
||||||
} else if ((days < IMPORT_AGE_NOT_YET_OLD_DAYS) && (days > 0)) {
|
|
||||||
resourceHelper.gs(R.string.exported_ago, resourceHelper.gq(R.plurals.objective_days, days, days))
|
|
||||||
} else {
|
|
||||||
resourceHelper.gs(R.string.exported_at, utcTime.substring(0, 10))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.maintenance
|
||||||
|
|
||||||
|
import android.os.Parcelable
|
||||||
|
import info.nightscout.androidaps.plugins.general.maintenance.formats.PrefMetadata
|
||||||
|
import info.nightscout.androidaps.plugins.general.maintenance.formats.PrefsMetadataKey
|
||||||
|
import kotlinx.android.parcel.Parcelize
|
||||||
|
import kotlinx.android.parcel.RawValue
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
|
data class PrefsFile(
|
||||||
|
val name: String,
|
||||||
|
val file: File,
|
||||||
|
val baseDir: File,
|
||||||
|
val dirKind: PrefsImportDir,
|
||||||
|
val handler: PrefsFormatsHandler,
|
||||||
|
|
||||||
|
// metadata here is used only for list display
|
||||||
|
val metadata: @RawValue Map<PrefsMetadataKey, PrefMetadata>
|
||||||
|
) : Parcelable
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.maintenance
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import androidx.activity.result.contract.ActivityResultContract
|
||||||
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
import info.nightscout.androidaps.plugins.general.maintenance.activities.PrefImportListActivity
|
||||||
|
|
||||||
|
class PrefsFileContract : ActivityResultContract<Void, PrefsFile>() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
const val OUTPUT_PARAM = "prefs_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun parseResult(resultCode: Int, intent: Intent?): PrefsFile? {
|
||||||
|
return when (resultCode) {
|
||||||
|
FragmentActivity.RESULT_OK -> intent?.getParcelableExtra(OUTPUT_PARAM)
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createIntent(context: Context, input: Void?): Intent {
|
||||||
|
return Intent(context, PrefImportListActivity::class.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.maintenance
|
||||||
|
|
||||||
|
enum class PrefsFormatsHandler {
|
||||||
|
CLASSIC,
|
||||||
|
ENCRYPTED
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.maintenance
|
||||||
|
|
||||||
|
enum class PrefsImportDir {
|
||||||
|
ROOT_DIR,
|
||||||
|
AAPS_DIR
|
||||||
|
}
|
|
@ -12,11 +12,11 @@ import androidx.fragment.app.FragmentActivity
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import dagger.android.support.DaggerAppCompatActivity
|
import dagger.android.support.DaggerAppCompatActivity
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.core.R
|
||||||
import info.nightscout.androidaps.plugins.general.maintenance.PrefFileListProvider
|
import info.nightscout.androidaps.plugins.general.maintenance.PrefFileListProvider
|
||||||
import info.nightscout.androidaps.plugins.general.maintenance.PrefsFile
|
import info.nightscout.androidaps.plugins.general.maintenance.PrefsFile
|
||||||
import info.nightscout.androidaps.plugins.general.maintenance.PrefsFileContract
|
import info.nightscout.androidaps.plugins.general.maintenance.PrefsFileContract
|
||||||
import info.nightscout.androidaps.plugins.general.maintenance.formats.PrefsFormatsHandler
|
import info.nightscout.androidaps.plugins.general.maintenance.PrefsFormatsHandler
|
||||||
import info.nightscout.androidaps.plugins.general.maintenance.formats.PrefsMetadataKey
|
import info.nightscout.androidaps.plugins.general.maintenance.formats.PrefsMetadataKey
|
||||||
import info.nightscout.androidaps.plugins.general.maintenance.formats.PrefsStatus
|
import info.nightscout.androidaps.plugins.general.maintenance.formats.PrefsStatus
|
||||||
import info.nightscout.androidaps.utils.locale.LocaleHelper
|
import info.nightscout.androidaps.utils.locale.LocaleHelper
|
||||||
|
@ -46,6 +46,7 @@ class PrefImportListActivity : DaggerAppCompatActivity() {
|
||||||
inner class RecyclerViewAdapter internal constructor(private var prefFileList: List<PrefsFile>) : RecyclerView.Adapter<RecyclerViewAdapter.PrefFileViewHolder>() {
|
inner class RecyclerViewAdapter internal constructor(private var prefFileList: List<PrefsFile>) : RecyclerView.Adapter<RecyclerViewAdapter.PrefFileViewHolder>() {
|
||||||
|
|
||||||
inner class PrefFileViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
inner class PrefFileViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||||
|
|
||||||
var fileName: TextView = itemView.findViewById(R.id.filelist_name)
|
var fileName: TextView = itemView.findViewById(R.id.filelist_name)
|
||||||
var fileDir: TextView = itemView.findViewById(R.id.filelist_dir)
|
var fileDir: TextView = itemView.findViewById(R.id.filelist_dir)
|
||||||
var metaDateTime: TextView = itemView.findViewById(R.id.meta_date_time)
|
var metaDateTime: TextView = itemView.findViewById(R.id.meta_date_time)
|
|
@ -1,7 +1,7 @@
|
||||||
package info.nightscout.androidaps.plugins.general.maintenance.formats
|
package info.nightscout.androidaps.plugins.general.maintenance.formats
|
||||||
|
|
||||||
import info.nightscout.androidaps.Constants
|
import info.nightscout.androidaps.Constants
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.core.R
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.storage.Storage
|
import info.nightscout.androidaps.utils.storage.Storage
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
@ -17,6 +17,7 @@ class ClassicPrefsFormat @Inject constructor(
|
||||||
) : PrefsFormat {
|
) : PrefsFormat {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
val FORMAT_KEY = "aaps_old"
|
val FORMAT_KEY = "aaps_old"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package info.nightscout.androidaps.plugins.general.maintenance.formats
|
package info.nightscout.androidaps.plugins.general.maintenance.formats
|
||||||
|
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.core.R
|
||||||
import info.nightscout.androidaps.utils.CryptoUtil
|
import info.nightscout.androidaps.utils.CryptoUtil
|
||||||
import info.nightscout.androidaps.utils.extensions.hexStringToByteArray
|
import info.nightscout.androidaps.utils.extensions.hexStringToByteArray
|
||||||
import info.nightscout.androidaps.utils.extensions.toHex
|
import info.nightscout.androidaps.utils.extensions.toHex
|
||||||
|
@ -23,6 +23,7 @@ class EncryptedPrefsFormat @Inject constructor(
|
||||||
) : PrefsFormat {
|
) : PrefsFormat {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
val FORMAT_KEY_ENC = "aaps_encrypted"
|
val FORMAT_KEY_ENC = "aaps_encrypted"
|
||||||
val FORMAT_KEY_NOENC = "aaps_structured"
|
val FORMAT_KEY_NOENC = "aaps_structured"
|
||||||
|
|
|
@ -4,7 +4,7 @@ import android.content.Context
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.core.R
|
||||||
import kotlinx.android.parcel.Parcelize
|
import kotlinx.android.parcel.Parcelize
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
|
@ -74,11 +74,6 @@ enum class PrefsStatus(@DrawableRes val icon: Int) {
|
||||||
DISABLED(R.drawable.ic_meta_error)
|
DISABLED(R.drawable.ic_meta_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class PrefsFormatsHandler {
|
|
||||||
CLASSIC,
|
|
||||||
ENCRYPTED
|
|
||||||
}
|
|
||||||
|
|
||||||
class PrefFileNotFoundError(message: String) : Exception(message)
|
class PrefFileNotFoundError(message: String) : Exception(message)
|
||||||
class PrefIOError(message: String) : Exception(message)
|
class PrefIOError(message: String) : Exception(message)
|
||||||
class PrefFormatError(message: String) : Exception(message)
|
class PrefFormatError(message: String) : Exception(message)
|
|
@ -1,17 +1,17 @@
|
||||||
package info.nightscout.androidaps.utils.storage
|
package info.nightscout.androidaps.utils.storage
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
class FileStorage : Storage {
|
class FileStorage : Storage {
|
||||||
|
|
||||||
override fun getFileContents(file: File): String {
|
override fun getFileContents(file: File): String {
|
||||||
return file.readText()
|
return file.readText()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun putFileContents(file: File, contents: String) {
|
override fun putFileContents(file: File, contents: String) {
|
||||||
file.writeText(contents)
|
file.writeText(contents)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
package info.nightscout.androidaps.utils.storage
|
package info.nightscout.androidaps.utils.storage
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
// This may seems unnecessary abstraction - but it will simplify testing
|
// This may seems unnecessary abstraction - but it will simplify testing
|
||||||
interface Storage {
|
interface Storage {
|
||||||
|
|
||||||
fun getFileContents(file: File) : String
|
fun getFileContents(file: File): String
|
||||||
fun putFileContents(file: File, contents: String)
|
fun putFileContents(file: File, contents: String)
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="24dp"
|
android:width="24dp"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="24"
|
||||||
android:viewportHeight="24">
|
android:viewportHeight="24">
|
||||||
<path
|
<path
|
||||||
android:fillColor="#000"
|
android:fillColor="#000"
|
||||||
android:pathData="M15,13H16.5V15.82L18.94,17.23L18.19,18.53L15,16.69V13M19,8H5V19H9.67C9.24,18.09 9,17.07 9,16A7,7 0 0,1 16,9C17.07,9 18.09,9.24 19,9.67V8M5,21C3.89,21 3,20.1 3,19V5C3,3.89 3.89,3 5,3H6V1H8V3H16V1H18V3H19A2,2 0 0,1 21,5V11.1C22.24,12.36 23,14.09 23,16A7,7 0 0,1 16,23C14.09,23 12.36,22.24 11.1,21H5M16,11.15A4.85,4.85 0 0,0 11.15,16C11.15,18.68 13.32,20.85 16,20.85A4.85,4.85 0 0,0 20.85,16C20.85,13.32 18.68,11.15 16,11.15Z" />
|
android:pathData="M15,13H16.5V15.82L18.94,17.23L18.19,18.53L15,16.69V13M19,8H5V19H9.67C9.24,18.09 9,17.07 9,16A7,7 0 0,1 16,9C17.07,9 18.09,9.24 19,9.67V8M5,21C3.89,21 3,20.1 3,19V5C3,3.89 3.89,3 5,3H6V1H8V3H16V1H18V3H19A2,2 0 0,1 21,5V11.1C22.24,12.36 23,14.09 23,16A7,7 0 0,1 16,23C14.09,23 12.36,22.24 11.1,21H5M16,11.15A4.85,4.85 0 0,0 11.15,16C11.15,18.68 13.32,20.85 16,20.85A4.85,4.85 0 0,0 20.85,16C20.85,13.32 18.68,11.15 16,11.15Z" />
|
||||||
</vector>
|
</vector>
|
|
@ -1,9 +1,9 @@
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="24dp"
|
android:width="24dp"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="24"
|
||||||
android:viewportHeight="24">
|
android:viewportHeight="24">
|
||||||
<path
|
<path
|
||||||
android:fillColor="#000"
|
android:fillColor="#000"
|
||||||
android:pathData="M21,11C21,16.55 17.16,21.74 12,23C6.84,21.74 3,16.55 3,11V5L12,1L21,5V11M12,21C15.75,20 19,15.54 19,11.22V6.3L12,3.18L5,6.3V11.22C5,15.54 8.25,20 12,21M14.8,11V9.5C14.8,8.1 13.4,7 12,7C10.6,7 9.2,8.1 9.2,9.5V11C8.6,11 8,11.6 8,12.2V15.7C8,16.4 8.6,17 9.2,17H14.7C15.4,17 16,16.4 16,15.8V12.3C16,11.6 15.4,11 14.8,11M13.5,11H10.5V9.5C10.5,8.7 11.2,8.2 12,8.2C12.8,8.2 13.5,8.7 13.5,9.5V11Z" />
|
android:pathData="M21,11C21,16.55 17.16,21.74 12,23C6.84,21.74 3,16.55 3,11V5L12,1L21,5V11M12,21C15.75,20 19,15.54 19,11.22V6.3L12,3.18L5,6.3V11.22C5,15.54 8.25,20 12,21M14.8,11V9.5C14.8,8.1 13.4,7 12,7C10.6,7 9.2,8.1 9.2,9.5V11C8.6,11 8,11.6 8,12.2V15.7C8,16.4 8.6,17 9.2,17H14.7C15.4,17 16,16.4 16,15.8V12.3C16,11.6 15.4,11 14.8,11M13.5,11H10.5V9.5C10.5,8.7 11.2,8.2 12,8.2C12.8,8.2 13.5,8.7 13.5,9.5V11Z" />
|
||||||
</vector>
|
</vector>
|
|
@ -1,10 +1,10 @@
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="24dp"
|
android:width="24dp"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:tint="@color/metadataTextError"
|
android:tint="@color/metadataTextError"
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="24"
|
||||||
android:viewportHeight="24">
|
android:viewportHeight="24">
|
||||||
<path
|
<path
|
||||||
android:fillColor="#000"
|
android:fillColor="#000"
|
||||||
android:pathData="M8.27,3L3,8.27V15.73L8.27,21H15.73L21,15.73V8.27L15.73,3M8.41,7L12,10.59L15.59,7L17,8.41L13.41,12L17,15.59L15.59,17L12,13.41L8.41,17L7,15.59L10.59,12L7,8.41" />
|
android:pathData="M8.27,3L3,8.27V15.73L8.27,21H15.73L21,15.73V8.27L15.73,3M8.41,7L12,10.59L15.59,7L17,8.41L13.41,12L17,15.59L15.59,17L12,13.41L8.41,17L7,15.59L10.59,12L7,8.41" />
|
||||||
</vector>
|
</vector>
|
|
@ -1,9 +1,9 @@
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="24dp"
|
android:width="24dp"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="24"
|
||||||
android:viewportHeight="24">
|
android:viewportHeight="24">
|
||||||
<path
|
<path
|
||||||
android:fillColor="#000"
|
android:fillColor="#000"
|
||||||
android:pathData="M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12C22,10.84 21.79,9.69 21.39,8.61L19.79,10.21C19.93,10.8 20,11.4 20,12A8,8 0 0,1 12,20A8,8 0 0,1 4,12A8,8 0 0,1 12,4C12.6,4 13.2,4.07 13.79,4.21L15.4,2.6C14.31,2.21 13.16,2 12,2M19,2L15,6V7.5L12.45,10.05C12.3,10 12.15,10 12,10A2,2 0 0,0 10,12A2,2 0 0,0 12,14A2,2 0 0,0 14,12C14,11.85 14,11.7 13.95,11.55L16.5,9H18L22,5H19V2M12,6A6,6 0 0,0 6,12A6,6 0 0,0 12,18A6,6 0 0,0 18,12H16A4,4 0 0,1 12,16A4,4 0 0,1 8,12A4,4 0 0,1 12,8V6Z" />
|
android:pathData="M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12C22,10.84 21.79,9.69 21.39,8.61L19.79,10.21C19.93,10.8 20,11.4 20,12A8,8 0 0,1 12,20A8,8 0 0,1 4,12A8,8 0 0,1 12,4C12.6,4 13.2,4.07 13.79,4.21L15.4,2.6C14.31,2.21 13.16,2 12,2M19,2L15,6V7.5L12.45,10.05C12.3,10 12.15,10 12,10A2,2 0 0,0 10,12A2,2 0 0,0 12,14A2,2 0 0,0 14,12C14,11.85 14,11.7 13.95,11.55L16.5,9H18L22,5H19V2M12,6A6,6 0 0,0 6,12A6,6 0 0,0 12,18A6,6 0 0,0 18,12H16A4,4 0 0,1 12,16A4,4 0 0,1 8,12A4,4 0 0,1 12,8V6Z" />
|
||||||
</vector>
|
</vector>
|
|
@ -1,9 +1,9 @@
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="24dp"
|
android:width="24dp"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="24"
|
||||||
android:viewportHeight="24">
|
android:viewportHeight="24">
|
||||||
<path
|
<path
|
||||||
android:fillColor="#000"
|
android:fillColor="#000"
|
||||||
android:pathData="M6 2C4.89 2 4 2.9 4 4V20C4 21.11 4.89 22 6 22H12V20H6V4H13V9H18V12H20V8L14 2M18 14C17.87 14 17.76 14.09 17.74 14.21L17.55 15.53C17.25 15.66 16.96 15.82 16.7 16L15.46 15.5C15.35 15.5 15.22 15.5 15.15 15.63L14.15 17.36C14.09 17.47 14.11 17.6 14.21 17.68L15.27 18.5C15.25 18.67 15.24 18.83 15.24 19C15.24 19.17 15.25 19.33 15.27 19.5L14.21 20.32C14.12 20.4 14.09 20.53 14.15 20.64L15.15 22.37C15.21 22.5 15.34 22.5 15.46 22.5L16.7 22C16.96 22.18 17.24 22.35 17.55 22.47L17.74 23.79C17.76 23.91 17.86 24 18 24H20C20.11 24 20.22 23.91 20.24 23.79L20.43 22.47C20.73 22.34 21 22.18 21.27 22L22.5 22.5C22.63 22.5 22.76 22.5 22.83 22.37L23.83 20.64C23.89 20.53 23.86 20.4 23.77 20.32L22.7 19.5C22.72 19.33 22.74 19.17 22.74 19C22.74 18.83 22.73 18.67 22.7 18.5L23.76 17.68C23.85 17.6 23.88 17.47 23.82 17.36L22.82 15.63C22.76 15.5 22.63 15.5 22.5 15.5L21.27 16C21 15.82 20.73 15.65 20.42 15.53L20.23 14.21C20.22 14.09 20.11 14 20 14M19 17.5C19.83 17.5 20.5 18.17 20.5 19C20.5 19.83 19.83 20.5 19 20.5C18.16 20.5 17.5 19.83 17.5 19C17.5 18.17 18.17 17.5 19 17.5Z" />
|
android:pathData="M6 2C4.89 2 4 2.9 4 4V20C4 21.11 4.89 22 6 22H12V20H6V4H13V9H18V12H20V8L14 2M18 14C17.87 14 17.76 14.09 17.74 14.21L17.55 15.53C17.25 15.66 16.96 15.82 16.7 16L15.46 15.5C15.35 15.5 15.22 15.5 15.15 15.63L14.15 17.36C14.09 17.47 14.11 17.6 14.21 17.68L15.27 18.5C15.25 18.67 15.24 18.83 15.24 19C15.24 19.17 15.25 19.33 15.27 19.5L14.21 20.32C14.12 20.4 14.09 20.53 14.15 20.64L15.15 22.37C15.21 22.5 15.34 22.5 15.46 22.5L16.7 22C16.96 22.18 17.24 22.35 17.55 22.47L17.74 23.79C17.76 23.91 17.86 24 18 24H20C20.11 24 20.22 23.91 20.24 23.79L20.43 22.47C20.73 22.34 21 22.18 21.27 22L22.5 22.5C22.63 22.5 22.76 22.5 22.83 22.37L23.83 20.64C23.89 20.53 23.86 20.4 23.77 20.32L22.7 19.5C22.72 19.33 22.74 19.17 22.74 19C22.74 18.83 22.73 18.67 22.7 18.5L23.76 17.68C23.85 17.6 23.88 17.47 23.82 17.36L22.82 15.63C22.76 15.5 22.63 15.5 22.5 15.5L21.27 16C21 15.82 20.73 15.65 20.42 15.53L20.23 14.21C20.22 14.09 20.11 14 20 14M19 17.5C19.83 17.5 20.5 18.17 20.5 19C20.5 19.83 19.83 20.5 19 20.5C18.16 20.5 17.5 19.83 17.5 19C17.5 18.17 18.17 17.5 19 17.5Z" />
|
||||||
</vector>
|
</vector>
|
|
@ -1,9 +1,9 @@
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="24dp"
|
android:width="24dp"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="24"
|
||||||
android:viewportHeight="24">
|
android:viewportHeight="24">
|
||||||
<path
|
<path
|
||||||
android:fillColor="#000"
|
android:fillColor="#000"
|
||||||
android:pathData="M13 7H11V9H13V7M13 11H11V17H13V11M17 1H7C5.9 1 5 1.9 5 3V21C5 22.1 5.9 23 7 23H17C18.1 23 19 22.1 19 21V3C19 1.9 18.1 1 17 1M17 19H7V5H17V19Z" />
|
android:pathData="M13 7H11V9H13V7M13 11H11V17H13V11M17 1H7C5.9 1 5 1.9 5 3V21C5 22.1 5.9 23 7 23H17C18.1 23 19 22.1 19 21V3C19 1.9 18.1 1 17 1M17 19H7V5H17V19Z" />
|
||||||
</vector>
|
</vector>
|
|
@ -1,9 +1,9 @@
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="24dp"
|
android:width="24dp"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="24"
|
||||||
android:viewportHeight="24">
|
android:viewportHeight="24">
|
||||||
<path
|
<path
|
||||||
android:fillColor="#000"
|
android:fillColor="#000"
|
||||||
android:pathData="M22,3H2C0.91,3.04 0.04,3.91 0,5V19C0.04,20.09 0.91,20.96 2,21H22C23.09,20.96 23.96,20.09 24,19V5C23.96,3.91 23.09,3.04 22,3M22,19H2V5H22V19M14,17V15.75C14,14.09 10.66,13.25 9,13.25C7.34,13.25 4,14.09 4,15.75V17H14M9,7A2.5,2.5 0 0,0 6.5,9.5A2.5,2.5 0 0,0 9,12A2.5,2.5 0 0,0 11.5,9.5A2.5,2.5 0 0,0 9,7M14,7V8H20V7H14M14,9V10H20V9H14M14,11V12H18V11H14" />
|
android:pathData="M22,3H2C0.91,3.04 0.04,3.91 0,5V19C0.04,20.09 0.91,20.96 2,21H22C23.09,20.96 23.96,20.09 24,19V5C23.96,3.91 23.09,3.04 22,3M22,19H2V5H22V19M14,17V15.75C14,14.09 10.66,13.25 9,13.25C7.34,13.25 4,14.09 4,15.75V17H14M9,7A2.5,2.5 0 0,0 6.5,9.5A2.5,2.5 0 0,0 9,12A2.5,2.5 0 0,0 11.5,9.5A2.5,2.5 0 0,0 9,7M14,7V8H20V7H14M14,9V10H20V9H14M14,11V12H18V11H14" />
|
||||||
</vector>
|
</vector>
|
|
@ -1,9 +1,9 @@
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="24dp"
|
android:width="24dp"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="24"
|
||||||
android:viewportHeight="24">
|
android:viewportHeight="24">
|
||||||
<path
|
<path
|
||||||
android:fillColor="#000"
|
android:fillColor="#000"
|
||||||
android:pathData="M2,10.96C1.5,10.68 1.35,10.07 1.63,9.59L3.13,7C3.24,6.8 3.41,6.66 3.6,6.58L11.43,2.18C11.59,2.06 11.79,2 12,2C12.21,2 12.41,2.06 12.57,2.18L20.47,6.62C20.66,6.72 20.82,6.88 20.91,7.08L22.36,9.6C22.64,10.08 22.47,10.69 22,10.96L21,11.54V16.5C21,16.88 20.79,17.21 20.47,17.38L12.57,21.82C12.41,21.94 12.21,22 12,22C11.79,22 11.59,21.94 11.43,21.82L3.53,17.38C3.21,17.21 3,16.88 3,16.5V10.96C2.7,11.13 2.32,11.14 2,10.96M12,4.15V4.15L12,10.85V10.85L17.96,7.5L12,4.15M5,15.91L11,19.29V12.58L5,9.21V15.91M19,15.91V12.69L14,15.59C13.67,15.77 13.3,15.76 13,15.6V19.29L19,15.91M13.85,13.36L20.13,9.73L19.55,8.72L13.27,12.35L13.85,13.36Z" />
|
android:pathData="M2,10.96C1.5,10.68 1.35,10.07 1.63,9.59L3.13,7C3.24,6.8 3.41,6.66 3.6,6.58L11.43,2.18C11.59,2.06 11.79,2 12,2C12.21,2 12.41,2.06 12.57,2.18L20.47,6.62C20.66,6.72 20.82,6.88 20.91,7.08L22.36,9.6C22.64,10.08 22.47,10.69 22,10.96L21,11.54V16.5C21,16.88 20.79,17.21 20.47,17.38L12.57,21.82C12.41,21.94 12.21,22 12,22C11.79,22 11.59,21.94 11.43,21.82L3.53,17.38C3.21,17.21 3,16.88 3,16.5V10.96C2.7,11.13 2.32,11.14 2,10.96M12,4.15V4.15L12,10.85V10.85L17.96,7.5L12,4.15M5,15.91L11,19.29V12.58L5,9.21V15.91M19,15.91V12.69L14,15.59C13.67,15.77 13.3,15.76 13,15.6V19.29L19,15.91M13.85,13.36L20.13,9.73L19.55,8.72L13.27,12.35L13.85,13.36Z" />
|
||||||
</vector>
|
</vector>
|
|
@ -1,10 +1,10 @@
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="24dp"
|
android:width="24dp"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:tint="@color/metadataTextWarning"
|
android:tint="@color/metadataTextWarning"
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="24"
|
||||||
android:viewportHeight="24">
|
android:viewportHeight="24">
|
||||||
<path
|
<path
|
||||||
android:fillColor="#000"
|
android:fillColor="#000"
|
||||||
android:pathData="M13,14H11V10H13M13,18H11V16H13M1,21H23L12,2L1,21Z" />
|
android:pathData="M13,14H11V10H13M13,18H11V16H13M1,21H23L12,2L1,21Z" />
|
||||||
</vector>
|
</vector>
|
|
@ -77,5 +77,10 @@
|
||||||
<color name="white_alpha_80">#CCFFFFFF</color>
|
<color name="white_alpha_80">#CCFFFFFF</color>
|
||||||
<color name="white_alpha_90">#E6FFFFFF</color>
|
<color name="white_alpha_90">#E6FFFFFF</color>
|
||||||
|
|
||||||
|
<!-- Maintenance -->
|
||||||
|
<color name="metadataOk">#77dd77</color>
|
||||||
|
<color name="metadataTextWarning">#FF8C00</color>
|
||||||
|
<color name="metadataTextError">#FF5555</color>
|
||||||
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -266,29 +266,62 @@
|
||||||
<string name="history_group_glucose">Glucose</string>
|
<string name="history_group_glucose">Glucose</string>
|
||||||
<string name="mute5min">Mute for 5 minutes</string>
|
<string name="mute5min">Mute for 5 minutes</string>
|
||||||
|
|
||||||
<!-- <string name="medtronic_pump_status_never_contacted">Never contacted</string>-->
|
<!-- Maintenance -->
|
||||||
<!-- <string name="medtronic_pump_status_waking_up">Waking up</string>-->
|
<string name="metadata_label_format">File format</string>
|
||||||
<!-- <string name="medtronic_pump_status_error_comm">Error with communication</string>-->
|
<string name="metadata_label_created_at">Created at</string>
|
||||||
<!-- <string name="medtronic_pump_status_timeout_comm">Timeout on communication</string>-->
|
<string name="metadata_label_aaps_version">AAPS Version</string>
|
||||||
<!-- <string name="medtronic_pump_status_pump_unreachable">Pump unreachable</string>-->
|
<string name="metadata_label_aaps_flavour">Build Variant</string>
|
||||||
<!-- <string name="medtronic_pump_status_invalid_config">Invalid configuration</string>-->
|
<string name="metadata_label_device_name">Exporting device patient name</string>
|
||||||
<!-- <string name="medtronic_pump_status_active">Active</string>-->
|
<string name="metadata_label_device_model">Exporting device model</string>
|
||||||
<!-- <string name="medtronic_pump_status_sleeping">Sleeping</string>-->
|
<string name="metadata_label_encryption">File encryption</string>
|
||||||
|
<string name="metadata_format_old">Old export format</string>
|
||||||
|
<string name="metadata_format_new">New encrypted format</string>
|
||||||
|
<string name="metadata_format_debug">New debug format (unencrypted)</string>
|
||||||
|
<string name="metadata_format_other">Unknown export format</string>
|
||||||
|
<string name="exported_ago" comment="at placeholder we add pluralized number of hours/minutes">exported %1$s ago</string>
|
||||||
|
<string name="exported_at" comment="at placeholder we add export date">exported at %1$s</string>
|
||||||
|
<string name="exported_less_than_hour_ago">exported less than hour ago</string>
|
||||||
|
<string name="in_directory" comment="placeholder is for exported file path">in directory: %1$s</string>
|
||||||
|
<string name="preferences_import_list_title">Select file to import</string>
|
||||||
|
<string name="metadata_warning_different_flavour">Preferences were created with different variant of AAPS (%1$s) while you have: %2$s.\n\nSome settings may be missing or invalid - after importing please check and update your preferences.</string>
|
||||||
|
<string name="metadata_warning_different_device">Preferences were created on a different device. It is OK if you are importing from older/different phone, but make sure imported preferences are correct!</string>
|
||||||
|
<string name="metadata_warning_outdated_format">You are using the outdated legacy format from old versions of AAPS, which is not secure! Only use it as a last resort, if you do not have an export in current, JSON format.</string>
|
||||||
|
<string name="metadata_warning_old_export">Imported preferences are already %1$s days old! Maybe you have more up-to-date preferences or you choose the wrong file? Remember to export preferences regularly!</string>
|
||||||
|
<string name="metadata_warning_date_format">Invalid date-time format!</string>
|
||||||
|
<string name="metadata_warning_different_version">Preferences from different minor version of application. It is OK if you are importing after upgrade, but check after import if preferences are still correct!</string>
|
||||||
|
<string name="metadata_urgent_different_version">Preferences from different major version of application. Major versions differ significantly and may have incompatible preferences! Make sure after import that preferences are still correct!</string>
|
||||||
|
<string name="prefdecrypt_settings_tampered">Settings file tampered</string>
|
||||||
|
<string name="prefdecrypt_settings_secure">Settings file is secure</string>
|
||||||
|
<string name="prefdecrypt_settings_unencrypted">Using not secure, unencrypted settings format</string>
|
||||||
|
<string name="prefdecrypt_wrong_json">JSON format error, missing required field (format, content, metadata or security)</string>
|
||||||
|
<string name="prefdecrypt_wrong_password">Decryption error, the given password cannot decrypt the file</string>
|
||||||
|
<string name="prefdecrypt_issue_missing_file_hash">File checksum (hash) missing, cannot verify the authenticity of settings!</string>
|
||||||
|
<string name="prefdecrypt_issue_modified">File was modified after export!</string>
|
||||||
|
<string name="prefdecrypt_issue_parsing">Decryption error, parsing preferences failed!</string>
|
||||||
|
<string name="prefdecrypt_issue_wrong_pass">Decryption error, the provided password is invalid or settings file was modified! It may happen that the imported file was exported with a different Master password.</string>
|
||||||
|
<string name="prefdecrypt_issue_wrong_format">Missing encryption configuration, settings format is invalid!</string>
|
||||||
|
<string name="prefdecrypt_issue_wrong_algorithm">Unsupported or not specified encryption algorithm!</string>
|
||||||
|
|
||||||
<!-- <string name="danar_history_alarm">Alarms</string>-->
|
<!-- VersionChecker -->
|
||||||
<!-- <string name="danar_history_glucose">Glucose</string>-->
|
<string name="key_last_time_this_version_detected" translatable="false">last_time_this_version_detected</string>
|
||||||
|
<string name="key_last_versionchecker_warning" translatable="false">last_versionchecker_waring</string>
|
||||||
|
<string name="key_last_versionchecker_plugin_warning" translatable="false">last_versionchecker_plugin_waring</string>
|
||||||
<!-- All(R.string.medtronic_history_group_all), //-->
|
<string name="key_last_revoked_certs_check" translatable="false">last_revoked_certs_check</string>
|
||||||
<!-- Bolus(R.string.danar_history_bolus), //-->
|
<string name="signature_verifier">Signature verifier</string>
|
||||||
<!-- Basal(R.string.medtronic_history_group_basal), //-->
|
<string name="running_invalid_version">We have detected that you are running an invalid version. Loop disabled!</string>
|
||||||
<!-- Prime(R.string.danar_history_prime), //-->
|
<string name="versionavailable">Version %1$s available</string>
|
||||||
<!-- Configuration(R.string.medtronic_history_group_configuration), //-->
|
|
||||||
<!-- Alarm(R.string.danar_history_alarm), //-->
|
|
||||||
<!-- Glucose(R.string.danar_history_glucose), //-->
|
|
||||||
<!-- Notification(R.string.medtronic_history_group_notification), //-->
|
|
||||||
<!-- Statistic(R.string.medtronic_history_group_statistic),-->
|
|
||||||
<!-- Unknown(R.string.medtronic_history_group_unknown), //-->
|
|
||||||
|
|
||||||
|
<plurals name="days">
|
||||||
|
<item quantity="one">%1$d day</item>
|
||||||
|
<item quantity="other">%1$d days</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="hours">
|
||||||
|
<item quantity="one">%1$d hour</item>
|
||||||
|
<item quantity="other">%1$d hours</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="minutes">
|
||||||
|
<item quantity="one">%1$d minute</item>
|
||||||
|
<item quantity="other">%1$d minutes</item>
|
||||||
|
</plurals>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
Loading…
Reference in a new issue