mirror of
				https://github.com/SimpleMobileTools/Simple-Notes.git
				synced 2025-06-05 17:00:23 +02:00 
			
		
		
		
	Merge branch 'master' into feature/641-open-note-ui
This commit is contained in:
		| @@ -66,7 +66,7 @@ android { | ||||
| } | ||||
|  | ||||
| dependencies { | ||||
|     implementation 'com.github.esensar:Simple-Commons:2a2c17151e' | ||||
|     implementation 'com.github.SimpleMobileTools:Simple-Commons:91763fe00f' | ||||
|     implementation 'androidx.constraintlayout:constraintlayout:2.1.4' | ||||
|     implementation 'androidx.documentfile:documentfile:1.0.1' | ||||
|  | ||||
|   | ||||
| @@ -6,6 +6,10 @@ | ||||
|     <uses-permission | ||||
|         android:name="android.permission.WRITE_EXTERNAL_STORAGE" | ||||
|         android:maxSdkVersion="28" /> | ||||
|     <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> | ||||
|     <uses-permission android:name="android.permission.WAKE_LOCK" /> | ||||
|     <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" /> | ||||
|     <uses-permission android:name="android.permission.USE_EXACT_ALARM" /> | ||||
|  | ||||
|     <uses-feature | ||||
|         android:name="android.hardware.faketouch" | ||||
| @@ -107,6 +111,22 @@ | ||||
|                 android:resource="@xml/widget_info" /> | ||||
|         </receiver> | ||||
|  | ||||
|         <receiver | ||||
|             android:name=".receivers.BootCompletedReceiver" | ||||
|             android:exported="true"> | ||||
|  | ||||
|             <intent-filter> | ||||
|                 <action android:name="android.intent.action.BOOT_COMPLETED" /> | ||||
|                 <action android:name="android.intent.action.QUICKBOOT_POWERON" /> | ||||
|                 <action android:name="com.htc.intent.action.QUICKBOOT_POWERON" /> | ||||
|                 <action android:name="android.intent.action.MY_PACKAGE_REPLACED" /> | ||||
|             </intent-filter> | ||||
|         </receiver> | ||||
|  | ||||
|         <receiver | ||||
|             android:name=".receivers.AutomaticBackupReceiver" | ||||
|             android:exported="false" /> | ||||
|  | ||||
|         <activity-alias | ||||
|             android:name=".activities.SplashActivity.Red" | ||||
|             android:enabled="false" | ||||
|   | ||||
| @@ -13,10 +13,8 @@ import com.simplemobiletools.commons.helpers.* | ||||
| import com.simplemobiletools.commons.models.RadioItem | ||||
| import com.simplemobiletools.notes.pro.R | ||||
| import com.simplemobiletools.notes.pro.dialogs.ExportNotesDialog | ||||
| import com.simplemobiletools.notes.pro.extensions.config | ||||
| import com.simplemobiletools.notes.pro.extensions.requestUnlockNotes | ||||
| import com.simplemobiletools.notes.pro.extensions.updateWidgets | ||||
| import com.simplemobiletools.notes.pro.extensions.widgetsDB | ||||
| import com.simplemobiletools.notes.pro.dialogs.ManageAutoBackupsDialog | ||||
| import com.simplemobiletools.notes.pro.extensions.* | ||||
| import com.simplemobiletools.notes.pro.helpers.* | ||||
| import com.simplemobiletools.notes.pro.models.Note | ||||
| import com.simplemobiletools.notes.pro.models.Widget | ||||
| @@ -62,6 +60,8 @@ class SettingsActivity : SimpleActivity() { | ||||
|         setupCustomizeWidgetColors() | ||||
|         setupNotesExport() | ||||
|         setupNotesImport() | ||||
|         setupEnableAutomaticBackups() | ||||
|         setupManageAutomaticBackups() | ||||
|         updateTextColors(settings_nested_scrollview) | ||||
|  | ||||
|         arrayOf( | ||||
| @@ -71,6 +71,7 @@ class SettingsActivity : SimpleActivity() { | ||||
|             settings_startup_label, | ||||
|             settings_saving_label, | ||||
|             settings_migrating_label, | ||||
|             settings_backups_label, | ||||
|         ).forEach { | ||||
|             it.setTextColor(getProperPrimaryColor()) | ||||
|         } | ||||
| @@ -355,4 +356,43 @@ class SettingsActivity : SimpleActivity() { | ||||
|             showErrorToast(e) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private fun setupEnableAutomaticBackups() { | ||||
|         settings_backups_label.beVisibleIf(isRPlus()) | ||||
|         settings_enable_automatic_backups_holder.beVisibleIf(isRPlus()) | ||||
|         settings_enable_automatic_backups.isChecked = config.autoBackup | ||||
|         settings_enable_automatic_backups_holder.setOnClickListener { | ||||
|             val wasBackupDisabled = !config.autoBackup | ||||
|             if (wasBackupDisabled) { | ||||
|                 ManageAutoBackupsDialog( | ||||
|                     activity = this, | ||||
|                     onSuccess = { | ||||
|                         enableOrDisableAutomaticBackups(true) | ||||
|                         scheduleNextAutomaticBackup() | ||||
|                     } | ||||
|                 ) | ||||
|             } else { | ||||
|                 cancelScheduledAutomaticBackup() | ||||
|                 enableOrDisableAutomaticBackups(false) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private fun setupManageAutomaticBackups() { | ||||
|         settings_manage_automatic_backups_holder.beVisibleIf(isRPlus() && config.autoBackup) | ||||
|         settings_manage_automatic_backups_holder.setOnClickListener { | ||||
|             ManageAutoBackupsDialog( | ||||
|                 activity = this, | ||||
|                 onSuccess = { | ||||
|                     scheduleNextAutomaticBackup() | ||||
|                 } | ||||
|             ) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private fun enableOrDisableAutomaticBackups(enable: Boolean) { | ||||
|         config.autoBackup = enable | ||||
|         settings_enable_automatic_backups.isChecked = enable | ||||
|         settings_manage_automatic_backups_holder.beVisibleIf(enable) | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,18 @@ | ||||
| package com.simplemobiletools.notes.pro.dialogs | ||||
|  | ||||
| import com.simplemobiletools.commons.activities.BaseSimpleActivity | ||||
| import com.simplemobiletools.commons.extensions.getAlertDialogBuilder | ||||
| import com.simplemobiletools.commons.extensions.setupDialogStuff | ||||
| import com.simplemobiletools.notes.pro.R | ||||
|  | ||||
| class DateTimePatternInfoDialog(activity: BaseSimpleActivity) { | ||||
|  | ||||
|     init { | ||||
|         val view = activity.layoutInflater.inflate(R.layout.datetime_pattern_info_layout, null) | ||||
|         activity.getAlertDialogBuilder() | ||||
|             .setPositiveButton(R.string.ok) { _, _ -> { } } | ||||
|             .apply { | ||||
|                 activity.setupDialogStuff(view, this) | ||||
|             } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,99 @@ | ||||
| package com.simplemobiletools.notes.pro.dialogs | ||||
|  | ||||
| import android.view.ViewGroup | ||||
| import androidx.appcompat.app.AlertDialog | ||||
| import com.simplemobiletools.commons.dialogs.FilePickerDialog | ||||
| import com.simplemobiletools.commons.extensions.* | ||||
| import com.simplemobiletools.commons.helpers.ensureBackgroundThread | ||||
| import com.simplemobiletools.notes.pro.R | ||||
| import com.simplemobiletools.notes.pro.activities.SimpleActivity | ||||
| import com.simplemobiletools.notes.pro.extensions.config | ||||
| import kotlinx.android.synthetic.main.dialog_manage_automatic_backups.view.backup_notes_filename | ||||
| import kotlinx.android.synthetic.main.dialog_manage_automatic_backups.view.backup_notes_filename_hint | ||||
| import kotlinx.android.synthetic.main.dialog_manage_automatic_backups.view.backup_notes_folder | ||||
| import java.io.File | ||||
|  | ||||
| class ManageAutoBackupsDialog(private val activity: SimpleActivity, onSuccess: () -> Unit) { | ||||
|     private val view = (activity.layoutInflater.inflate(R.layout.dialog_manage_automatic_backups, null) as ViewGroup) | ||||
|     private val config = activity.config | ||||
|     private var backupFolder = config.autoBackupFolder | ||||
|  | ||||
|     init { | ||||
|         view.apply { | ||||
|             backup_notes_folder.setText(activity.humanizePath(backupFolder)) | ||||
|             val filename = config.autoBackupFilename.ifEmpty { | ||||
|                 "${activity.getString(R.string.notes)}_%Y%M%D_%h%m%s" | ||||
|             } | ||||
|  | ||||
|             backup_notes_filename.setText(filename) | ||||
|             backup_notes_filename_hint.setEndIconOnClickListener { | ||||
|                 DateTimePatternInfoDialog(activity) | ||||
|             } | ||||
|  | ||||
|             backup_notes_filename_hint.setEndIconOnLongClickListener { | ||||
|                 DateTimePatternInfoDialog(activity) | ||||
|                 true | ||||
|             } | ||||
|  | ||||
|             backup_notes_folder.setOnClickListener { | ||||
|                 selectBackupFolder() | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         activity.getAlertDialogBuilder() | ||||
|             .setPositiveButton(R.string.ok, null) | ||||
|             .setNegativeButton(R.string.cancel, null) | ||||
|             .apply { | ||||
|                 activity.setupDialogStuff(view, this, R.string.manage_automatic_backups) { dialog -> | ||||
|                     dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener { | ||||
|                         val filename = view.backup_notes_filename.value | ||||
|                         when { | ||||
|                             filename.isEmpty() -> activity.toast(R.string.empty_name) | ||||
|                             filename.isAValidFilename() -> { | ||||
|                                 val file = File(backupFolder, "$filename.json") | ||||
|                                 if (file.exists() && !file.canWrite()) { | ||||
|                                     activity.toast(R.string.name_taken) | ||||
|                                     return@setOnClickListener | ||||
|                                 } | ||||
|  | ||||
|                                 ensureBackgroundThread { | ||||
|                                     config.apply { | ||||
|                                         autoBackupFolder = backupFolder | ||||
|                                         autoBackupFilename = filename | ||||
|                                     } | ||||
|  | ||||
|                                     activity.runOnUiThread { | ||||
|                                         onSuccess() | ||||
|                                     } | ||||
|  | ||||
|                                     dialog.dismiss() | ||||
|                                 } | ||||
|                             } | ||||
|  | ||||
|                             else -> activity.toast(R.string.invalid_name) | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|     } | ||||
|  | ||||
|     private fun selectBackupFolder() { | ||||
|         activity.hideKeyboard(view.backup_notes_filename) | ||||
|         FilePickerDialog(activity, backupFolder, false, showFAB = true) { path -> | ||||
|             activity.handleSAFDialog(path) { grantedSAF -> | ||||
|                 if (!grantedSAF) { | ||||
|                     return@handleSAFDialog | ||||
|                 } | ||||
|  | ||||
|                 activity.handleSAFDialogSdk30(path) { grantedSAF30 -> | ||||
|                     if (!grantedSAF30) { | ||||
|                         return@handleSAFDialogSdk30 | ||||
|                     } | ||||
|  | ||||
|                     backupFolder = path | ||||
|                     view.backup_notes_folder.setText(activity.humanizePath(path)) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,18 +1,28 @@ | ||||
| package com.simplemobiletools.notes.pro.extensions | ||||
|  | ||||
| import android.app.AlarmManager | ||||
| import android.app.PendingIntent | ||||
| import android.appwidget.AppWidgetManager | ||||
| import android.content.ComponentName | ||||
| import android.content.Context | ||||
| import android.content.Intent | ||||
| import androidx.core.app.AlarmManagerCompat | ||||
| import com.simplemobiletools.commons.activities.BaseSimpleActivity | ||||
| import com.simplemobiletools.commons.extensions.* | ||||
| import com.simplemobiletools.commons.helpers.ExportResult | ||||
| import com.simplemobiletools.commons.helpers.ensureBackgroundThread | ||||
| import com.simplemobiletools.commons.helpers.isRPlus | ||||
| import com.simplemobiletools.notes.pro.R | ||||
| import com.simplemobiletools.notes.pro.databases.NotesDatabase | ||||
| import com.simplemobiletools.notes.pro.dialogs.UnlockNotesDialog | ||||
| import com.simplemobiletools.notes.pro.helpers.Config | ||||
| import com.simplemobiletools.notes.pro.helpers.MyWidgetProvider | ||||
| import com.simplemobiletools.notes.pro.helpers.* | ||||
| import com.simplemobiletools.notes.pro.interfaces.NotesDao | ||||
| import com.simplemobiletools.notes.pro.interfaces.WidgetsDao | ||||
| import com.simplemobiletools.notes.pro.models.Note | ||||
| import com.simplemobiletools.notes.pro.receivers.AutomaticBackupReceiver | ||||
| import org.joda.time.DateTime | ||||
| import java.io.File | ||||
| import java.io.FileOutputStream | ||||
|  | ||||
| val Context.config: Config get() = Config.newInstance(applicationContext) | ||||
|  | ||||
| @@ -43,3 +53,111 @@ fun BaseSimpleActivity.requestUnlockNotes(notes: List<Note>, callback: (unlocked | ||||
|         callback(emptyList()) | ||||
|     } | ||||
| } | ||||
|  | ||||
| fun Context.getAutomaticBackupIntent(): PendingIntent { | ||||
|     val intent = Intent(this, AutomaticBackupReceiver::class.java) | ||||
|     return PendingIntent.getBroadcast(this, AUTOMATIC_BACKUP_REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) | ||||
| } | ||||
|  | ||||
| fun Context.scheduleNextAutomaticBackup() { | ||||
|     if (config.autoBackup) { | ||||
|         val backupAtMillis = getNextAutoBackupTime().millis | ||||
|         val pendingIntent = getAutomaticBackupIntent() | ||||
|         val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager | ||||
|         try { | ||||
|             AlarmManagerCompat.setExactAndAllowWhileIdle(alarmManager, AlarmManager.RTC_WAKEUP, backupAtMillis, pendingIntent) | ||||
|         } catch (e: Exception) { | ||||
|             showErrorToast(e) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| fun Context.cancelScheduledAutomaticBackup() { | ||||
|     val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager | ||||
|     alarmManager.cancel(getAutomaticBackupIntent()) | ||||
| } | ||||
|  | ||||
| fun Context.checkAndBackupNotesOnBoot() { | ||||
|     if (config.autoBackup) { | ||||
|         val previousRealBackupTime = config.lastAutoBackupTime | ||||
|         val previousScheduledBackupTime = getPreviousAutoBackupTime().millis | ||||
|         val missedPreviousBackup = previousRealBackupTime < previousScheduledBackupTime | ||||
|         if (missedPreviousBackup) { | ||||
|             // device was probably off at the scheduled time so backup now | ||||
|             backupNotes() | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| fun Context.backupNotes() { | ||||
|     require(isRPlus()) | ||||
|     ensureBackgroundThread { | ||||
|         val config = config | ||||
|         NotesHelper(this).getNotes { notesToBackup -> | ||||
|             if (notesToBackup.isEmpty()) { | ||||
|                 toast(R.string.no_entries_for_exporting) | ||||
|                 config.lastAutoBackupTime = DateTime.now().millis | ||||
|                 scheduleNextAutomaticBackup() | ||||
|                 return@getNotes | ||||
|             } | ||||
|  | ||||
|  | ||||
|             val now = DateTime.now() | ||||
|             val year = now.year.toString() | ||||
|             val month = now.monthOfYear.ensureTwoDigits() | ||||
|             val day = now.dayOfMonth.ensureTwoDigits() | ||||
|             val hours = now.hourOfDay.ensureTwoDigits() | ||||
|             val minutes = now.minuteOfHour.ensureTwoDigits() | ||||
|             val seconds = now.secondOfMinute.ensureTwoDigits() | ||||
|  | ||||
|             val filename = config.autoBackupFilename | ||||
|                 .replace("%Y", year, false) | ||||
|                 .replace("%M", month, false) | ||||
|                 .replace("%D", day, false) | ||||
|                 .replace("%h", hours, false) | ||||
|                 .replace("%m", minutes, false) | ||||
|                 .replace("%s", seconds, false) | ||||
|  | ||||
|             val outputFolder = File(config.autoBackupFolder).apply { | ||||
|                 mkdirs() | ||||
|             } | ||||
|  | ||||
|             var exportFile = File(outputFolder, "$filename.json") | ||||
|             var exportFilePath = exportFile.absolutePath | ||||
|             val outputStream = try { | ||||
|                 if (hasProperStoredFirstParentUri(exportFilePath)) { | ||||
|                     val exportFileUri = createDocumentUriUsingFirstParentTreeUri(exportFilePath) | ||||
|                     if (!getDoesFilePathExist(exportFilePath)) { | ||||
|                         createSAFFileSdk30(exportFilePath) | ||||
|                     } | ||||
|                     applicationContext.contentResolver.openOutputStream(exportFileUri, "wt") ?: FileOutputStream(exportFile) | ||||
|                 } else { | ||||
|                     var num = 0 | ||||
|                     while (getDoesFilePathExist(exportFilePath) && !exportFile.canWrite()) { | ||||
|                         num++ | ||||
|                         exportFile = File(outputFolder, "${filename}_${num}.json") | ||||
|                         exportFilePath = exportFile.absolutePath | ||||
|                     } | ||||
|                     FileOutputStream(exportFile) | ||||
|                 } | ||||
|             } catch (e: Exception) { | ||||
|                 showErrorToast(e) | ||||
|                 scheduleNextAutomaticBackup() | ||||
|                 return@getNotes | ||||
|             } | ||||
|  | ||||
|             val exportResult = try { | ||||
|                 NotesHelper(this).exportNotes(notesToBackup, outputStream) | ||||
|             } catch (e: Exception) { | ||||
|                 showErrorToast(e) | ||||
|             } | ||||
|  | ||||
|             if (exportResult == ExportResult.EXPORT_FAIL) { | ||||
|                 toast(R.string.exporting_failed) | ||||
|             } | ||||
|  | ||||
|             config.lastAutoBackupTime = DateTime.now().millis | ||||
|             scheduleNextAutomaticBackup() | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| package com.simplemobiletools.notes.pro.helpers | ||||
|  | ||||
| import android.graphics.Color | ||||
| import org.joda.time.DateTime | ||||
|  | ||||
| const val NOTE_ID = "note_id" | ||||
| const val OPEN_NOTE_ID = "open_note_id" | ||||
| @@ -39,6 +40,26 @@ const val FONT_SIZE_PERCENTAGE = "font_size_percentage" | ||||
| const val EXPORT_MIME_TYPE = "text/plain" | ||||
| const val ADD_NEW_CHECKLIST_ITEMS_TOP = "add_new_checklist_items_top" | ||||
|  | ||||
| // auto backups | ||||
| const val AUTOMATIC_BACKUP_REQUEST_CODE = 10001 | ||||
| const val AUTO_BACKUP_INTERVAL_IN_DAYS = 1 | ||||
|  | ||||
| // 6 am is the hardcoded automatic backup time, intervals shorter than 1 day are not yet supported. | ||||
| fun getNextAutoBackupTime(): DateTime { | ||||
|     val now = DateTime.now() | ||||
|     val sixHour = now.withHourOfDay(6) | ||||
|     return if (now.millis < sixHour.millis) { | ||||
|         sixHour | ||||
|     } else { | ||||
|         sixHour.plusDays(AUTO_BACKUP_INTERVAL_IN_DAYS) | ||||
|     } | ||||
| } | ||||
|  | ||||
| fun getPreviousAutoBackupTime(): DateTime { | ||||
|     val nextBackupTime = getNextAutoBackupTime() | ||||
|     return nextBackupTime.minusDays(AUTO_BACKUP_INTERVAL_IN_DAYS) | ||||
| } | ||||
|  | ||||
| // gravity | ||||
| const val GRAVITY_START = 0 | ||||
| const val GRAVITY_CENTER = 1 | ||||
|   | ||||
| @@ -4,6 +4,7 @@ import android.content.Context | ||||
| import android.os.Handler | ||||
| import android.os.Looper | ||||
| import com.simplemobiletools.commons.activities.BaseSimpleActivity | ||||
| import com.simplemobiletools.commons.helpers.ExportResult | ||||
| import com.simplemobiletools.commons.helpers.PROTECTION_NONE | ||||
| import com.simplemobiletools.commons.helpers.ensureBackgroundThread | ||||
| import com.simplemobiletools.notes.pro.R | ||||
| @@ -11,7 +12,10 @@ import com.simplemobiletools.notes.pro.extensions.config | ||||
| import com.simplemobiletools.notes.pro.extensions.notesDB | ||||
| import com.simplemobiletools.notes.pro.models.Note | ||||
| import com.simplemobiletools.notes.pro.models.NoteType | ||||
| import kotlinx.serialization.encodeToString | ||||
| import kotlinx.serialization.json.Json | ||||
| import java.io.File | ||||
| import java.io.OutputStream | ||||
|  | ||||
| class NotesHelper(val context: Context) { | ||||
|     fun getNotes(callback: (notes: List<Note>) -> Unit) { | ||||
| @@ -124,6 +128,18 @@ class NotesHelper(val context: Context) { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fun exportNotes(notesToBackup: List<Note>, outputStream: OutputStream): ExportResult { | ||||
|         return try { | ||||
|             val jsonString = Json.encodeToString(notesToBackup) | ||||
|             outputStream.use { | ||||
|                 it.write(jsonString.toByteArray()) | ||||
|             } | ||||
|             ExportResult.EXPORT_OK | ||||
|         } catch (_: Error) { | ||||
|             ExportResult.EXPORT_FAIL | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     enum class ImportResult { | ||||
|         IMPORT_FAIL, IMPORT_OK, IMPORT_PARTIAL, IMPORT_NOTHING_NEW | ||||
|     } | ||||
|   | ||||
| @@ -0,0 +1,17 @@ | ||||
| package com.simplemobiletools.notes.pro.receivers | ||||
|  | ||||
| import android.content.BroadcastReceiver | ||||
| import android.content.Context | ||||
| import android.content.Intent | ||||
| import android.os.PowerManager | ||||
| import com.simplemobiletools.notes.pro.extensions.backupNotes | ||||
|  | ||||
| class AutomaticBackupReceiver : BroadcastReceiver() { | ||||
|  | ||||
|     override fun onReceive(context: Context, intent: Intent) { | ||||
|         val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager | ||||
|         val wakelock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "simplenotes:automaticbackupreceiver") | ||||
|         wakelock.acquire(3000) | ||||
|         context.backupNotes() | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,18 @@ | ||||
| package com.simplemobiletools.notes.pro.receivers | ||||
|  | ||||
| import android.content.BroadcastReceiver | ||||
| import android.content.Context | ||||
| import android.content.Intent | ||||
| import com.simplemobiletools.commons.helpers.ensureBackgroundThread | ||||
| import com.simplemobiletools.notes.pro.extensions.checkAndBackupNotesOnBoot | ||||
|  | ||||
| class BootCompletedReceiver : BroadcastReceiver() { | ||||
|  | ||||
|     override fun onReceive(context: Context, intent: Intent) { | ||||
|         ensureBackgroundThread { | ||||
|             context.apply { | ||||
|                 checkAndBackupNotesOnBoot() | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -386,6 +386,47 @@ | ||||
|                 android:text="@string/import_notes" /> | ||||
|             </RelativeLayout> | ||||
|  | ||||
|             <include | ||||
|                 android:id="@+id/settings_migrating_divider" | ||||
|                 layout="@layout/divider" /> | ||||
|  | ||||
|             <TextView | ||||
|                 android:id="@+id/settings_backups_label" | ||||
|                 style="@style/SettingsSectionLabelStyle" | ||||
|                 android:layout_width="match_parent" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:text="@string/backups" /> | ||||
|  | ||||
|             <RelativeLayout | ||||
|                 android:id="@+id/settings_enable_automatic_backups_holder" | ||||
|                 style="@style/SettingsHolderCheckboxStyle" | ||||
|                 android:layout_width="match_parent" | ||||
|                 android:layout_height="wrap_content"> | ||||
|  | ||||
|                 <com.simplemobiletools.commons.views.MyAppCompatCheckbox | ||||
|                     android:id="@+id/settings_enable_automatic_backups" | ||||
|                     style="@style/SettingsCheckboxStyle" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:text="@string/enable_automatic_backups" /> | ||||
|  | ||||
|             </RelativeLayout> | ||||
|  | ||||
|             <RelativeLayout | ||||
|                 android:id="@+id/settings_manage_automatic_backups_holder" | ||||
|                 style="@style/SettingsHolderTextViewOneLinerStyle" | ||||
|                 android:layout_width="match_parent" | ||||
|                 android:layout_height="wrap_content"> | ||||
|  | ||||
|                 <com.simplemobiletools.commons.views.MyTextView | ||||
|                     android:id="@+id/settings_manage_automatic_backups" | ||||
|                     style="@style/SettingsTextLabelStyle" | ||||
|                     android:layout_width="wrap_content" | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:text="@string/manage_automatic_backups" /> | ||||
|  | ||||
|             </RelativeLayout> | ||||
|  | ||||
|         </LinearLayout> | ||||
|     </androidx.core.widget.NestedScrollView> | ||||
| </androidx.coordinatorlayout.widget.CoordinatorLayout> | ||||
|   | ||||
							
								
								
									
										9
									
								
								app/src/main/res/layout/datetime_pattern_info_layout.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								app/src/main/res/layout/datetime_pattern_info_layout.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <com.simplemobiletools.commons.views.MyTextView xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:id="@+id/date_time_pattern_info" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="match_parent" | ||||
|     android:paddingHorizontal="@dimen/big_margin" | ||||
|     android:paddingTop="@dimen/big_margin" | ||||
|     android:text="@string/date_time_pattern_info" | ||||
|     android:textIsSelectable="true" /> | ||||
							
								
								
									
										54
									
								
								app/src/main/res/layout/dialog_manage_automatic_backups.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								app/src/main/res/layout/dialog_manage_automatic_backups.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
|     android:id="@+id/backup_notes_scrollview" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="wrap_content"> | ||||
|  | ||||
|     <LinearLayout | ||||
|         android:id="@+id/backup_notes_holder" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:orientation="vertical" | ||||
|         android:paddingTop="@dimen/activity_margin"> | ||||
|  | ||||
|         <com.simplemobiletools.commons.views.MyTextInputLayout | ||||
|             android:id="@+id/backup_notes_folder_hint" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_marginStart="@dimen/activity_margin" | ||||
|             android:layout_marginEnd="@dimen/activity_margin" | ||||
|             android:layout_marginBottom="@dimen/activity_margin" | ||||
|             android:hint="@string/folder"> | ||||
|  | ||||
|             <com.google.android.material.textfield.TextInputEditText | ||||
|                 android:id="@+id/backup_notes_folder" | ||||
|                 style="@style/UnclickableEditText" | ||||
|                 android:layout_width="match_parent" | ||||
|                 android:layout_height="wrap_content" /> | ||||
|  | ||||
|         </com.simplemobiletools.commons.views.MyTextInputLayout> | ||||
|  | ||||
|         <com.simplemobiletools.commons.views.MyTextInputLayout | ||||
|             android:id="@+id/backup_notes_filename_hint" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_marginStart="@dimen/activity_margin" | ||||
|             android:layout_marginEnd="@dimen/activity_margin" | ||||
|             android:hint="@string/filename_without_json" | ||||
|             app:endIconDrawable="@drawable/ic_info_vector" | ||||
|             app:endIconMode="custom"> | ||||
|  | ||||
|             <com.google.android.material.textfield.TextInputEditText | ||||
|                 android:id="@+id/backup_notes_filename" | ||||
|                 android:layout_width="match_parent" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:inputType="textCapWords" | ||||
|                 android:singleLine="true" | ||||
|                 android:textCursorDrawable="@null" | ||||
|                 android:textSize="@dimen/bigger_text_size" /> | ||||
|  | ||||
|         </com.simplemobiletools.commons.views.MyTextInputLayout> | ||||
|  | ||||
|     </LinearLayout> | ||||
| </ScrollView> | ||||
| @@ -56,7 +56,7 @@ | ||||
|     <string name="alignment">Joondumine</string> | ||||
|     <string name="left">Vasakule</string> | ||||
|     <string name="center">Keskele</string> | ||||
|     <string name="right">Õigus</string> | ||||
|     <string name="right">Paremale</string> | ||||
|     <string name="widget_note">Märge on kasutusel rakenduse vidinas</string> | ||||
|     <string name="show_note_picker">Rakenduse käivitamisel näita märkmete valijat</string> | ||||
|     <string name="autosave_notes">Salvesta märkmed automaatselt</string> | ||||
| @@ -71,7 +71,7 @@ | ||||
|     <string name="add_new_checklist_items">Lisa tööde loendisse uued kirjed</string> | ||||
|     <string name="checklist_is_empty">Tööde loend on tühi</string> | ||||
|     <string name="remove_done_items">Kustuta tehtuks märgitud kirjed</string> | ||||
|     <string name="add_to_the_top">Add to the top</string> | ||||
|     <string name="add_to_the_top">Lisa ülaossa</string> | ||||
|     <!-- Import / Export --> | ||||
|     <string name="import_folder">Impordi kaust</string> | ||||
|     <string name="export_notes">Ekspordi märkmed</string> | ||||
|   | ||||
| @@ -1 +1 @@ | ||||
| Lihtne märkmete Pro | ||||
| Lihtne märkmik Pro | ||||
|   | ||||
		Reference in New Issue
	
	Block a user