Compare commits

...

9 commits
main ... v7.2.1

Author SHA1 Message Date
PhilKes
e243ed5155 Bump version v7.2.1 2025-03-18 20:51:26 +01:00
Phil
200694d2e2
Merge pull request #465 from PhilKes/translation/update
Update zh-rCN/strings.xml
2025-03-18 18:00:19 +01:00
PhilKes
9ba90e88c4 Update zh-rCN/strings.xml 2025-03-18 17:59:55 +01:00
Phil
3b72ae619e
Merge pull request #464 from PhilKes/fix/export-backup-database
Fix databaseFile path when creating backup
2025-03-18 17:57:48 +01:00
PhilKes
9fe6fb9e5a Fix databaseFile path when creating backup 2025-03-18 13:41:27 +01:00
PhilKes
ebab977d38 Add rate app in About settings 2025-03-16 18:11:32 +01:00
Phil
250a901fce
Merge pull request #458 from PhilKes/feat/auto-save-idle
Add auto-save after user idle time
2025-03-16 18:05:28 +01:00
PhilKes
9d7b3ab6c5 Add auto-save after user idle time 2025-03-16 18:01:13 +01:00
Phil
eda1d8db3e
Add Google Play badge to README.md 2025-03-12 18:17:29 +01:00
22 changed files with 208 additions and 50 deletions

View file

@ -4,9 +4,9 @@
<b>NotallyX | Minimalistic note taking app</b>
<p>
<center>
<a href='https://play.google.com/store/apps/details?id=com.philkes.notallyx&pcampaignid=pcampaignidMKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1'><img alt='Get it on Google Play' src='https://play.google.com/intl/en_us/badges/static/images/badges/en_badge_web_generic.png' height='80'/></a>
<a href="https://f-droid.org/en/packages/com.philkes.notallyx"><img alt='IzzyOnDroid' height='80' src='https://fdroid.gitlab.io/artwork/badge/get-it-on.png' /></a>
<a href="https://apt.izzysoft.de/fdroid/index/apk/com.philkes.notallyx"><img alt='F-Droid' height='80' src='https://gitlab.com/IzzyOnDroid/repo/-/raw/master/assets/IzzyOnDroid.png' /></a>
<a href="https://github.com/PhilKes/NotallyX/issues/120"><img alt="JoinTesters" height="80" src="fastlane/join-testers.png" /></a>
</center>
</p>
</h2>

View file

@ -31,6 +31,50 @@ data class BaseNote(
const val COLOR_DEFAULT = "DEFAULT"
const val COLOR_NEW = "NEW"
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as BaseNote
if (id != other.id) return false
if (type != other.type) return false
if (folder != other.folder) return false
if (color != other.color) return false
if (title != other.title) return false
if (pinned != other.pinned) return false
if (timestamp != other.timestamp) return false
if (labels != other.labels) return false
if (body != other.body) return false
if (spans != other.spans) return false
if (items != other.items) return false
if (images != other.images) return false
if (files != other.files) return false
if (audios != other.audios) return false
if (reminders != other.reminders) return false
return true
}
override fun hashCode(): Int {
var result = id.hashCode()
result = 31 * result + type.hashCode()
result = 31 * result + folder.hashCode()
result = 31 * result + color.hashCode()
result = 31 * result + title.hashCode()
result = 31 * result + pinned.hashCode()
result = 31 * result + timestamp.hashCode()
result = 31 * result + labels.hashCode()
result = 31 * result + body.hashCode()
result = 31 * result + spans.hashCode()
result = 31 * result + items.hashCode()
result = 31 * result + images.hashCode()
result = 31 * result + files.hashCode()
result = 31 * result + audios.hashCode()
result = 31 * result + reminders.hashCode()
return result
}
}
fun BaseNote.deepCopy(): BaseNote {

View file

@ -434,6 +434,29 @@ fun PreferenceSeekbarBinding.setup(
}
}
fun PreferenceSeekbarBinding.setupAutoSaveIdleTime(
preference: IntPreference,
context: Context,
value: Int = preference.value,
onChange: (newValue: Int) -> Unit,
) {
Slider.apply {
setLabelFormatter { sliderValue ->
if (sliderValue == -1f) {
context.getString(R.string.disabled)
} else "${sliderValue.toInt()}s"
}
addOnChangeListener { _, value, _ ->
if (value == -1f) {
setAlpha(0.6f) // Reduce opacity to make it look disabled
} else {
setAlpha(1f) // Restore normal appearance
}
}
}
setup(preference, context, value, onChange)
}
fun PreferenceBinding.setupStartView(
preference: StringPreference,
value: String,

View file

@ -616,6 +616,12 @@ class SettingsFragment : Fragment() {
}
}
}
binding.AutoSaveAfterIdle.setupAutoSaveIdleTime(
autoSaveAfterIdleTime,
requireContext(),
) { newValue ->
model.savePreference(autoSaveAfterIdleTime, newValue)
}
ClearData.setOnClickListener {
MaterialAlertDialogBuilder(requireContext())
.setMessage(R.string.clear_data_message)
@ -689,8 +695,10 @@ class SettingsFragment : Fragment() {
.setCancelButton()
.show()
}
Rate.setOnClickListener {
openLink("https://play.google.com/store/apps/details?id=com.philkes.notallyx")
}
SourceCode.setOnClickListener { openLink("https://github.com/PhilKes/NotallyX") }
// TODO: add ColorPickerView
Libraries.setOnClickListener {
val libraries =
arrayOf(

View file

@ -8,8 +8,11 @@ import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.provider.Settings
import android.text.Editable
import android.util.Log
import android.util.TypedValue
import android.view.MenuItem
import android.view.View
@ -114,12 +117,25 @@ abstract class EditActivity(private val type: Type) :
protected var colorInt: Int = -1
protected var inputMethodManager: InputMethodManager? = null
private val autoSaveHandler = Handler(Looper.getMainLooper())
private val autoSaveRunnable = Runnable {
lifecycleScope.launch(Dispatchers.Main) {
updateModel()
if (notallyModel.isModified()) {
Log.d(TAG, "Auto-saving note...")
saveNote(checkAutoSave = false)
}
}
}
override fun finish() {
lifecycleScope.launch(Dispatchers.Main) {
if (notallyModel.isEmpty()) {
notallyModel.deleteBaseNote(checkAutoSave = false)
} else if (notallyModel.isModified()) {
saveNote()
} else {
notallyModel.checkBackupOnSave()
}
super.finish()
}
@ -137,9 +153,9 @@ abstract class EditActivity(private val type: Type) :
}
}
open suspend fun saveNote() {
open suspend fun saveNote(checkAutoSave: Boolean = true) {
updateModel()
notallyModel.saveNote()
notallyModel.saveNote(checkAutoSave)
WidgetProvider.sendBroadcast(application, longArrayOf(notallyModel.id))
}
@ -193,6 +209,19 @@ abstract class EditActivity(private val type: Type) :
}
}
override fun onDestroy() {
autoSaveHandler.removeCallbacks(autoSaveRunnable)
super.onDestroy()
}
protected fun resetIdleTimer() {
autoSaveHandler.removeCallbacks(autoSaveRunnable)
val idleTime = preferences.autoSaveAfterIdleTime.value
if (idleTime > -1) {
autoSaveHandler.postDelayed(autoSaveRunnable, idleTime.toLong() * 1000)
}
}
private fun setupActivityResultLaunchers() {
recordAudioActivityResultLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
@ -243,6 +272,7 @@ abstract class EditActivity(private val type: Type) :
paddingTop = true,
colorInt,
)
resetIdleTimer()
}
}
}
@ -317,6 +347,7 @@ abstract class EditActivity(private val type: Type) :
ChangeHistory().apply {
canUndo.observe(this@EditActivity) { canUndo -> undo?.isEnabled = canUndo }
canRedo.observe(this@EditActivity) { canRedo -> redo?.isEnabled = canRedo }
stackPointer.observe(this@EditActivity) { _ -> resetIdleTimer() }
}
}
@ -645,6 +676,7 @@ abstract class EditActivity(private val type: Type) :
}
notallyModel.color = selectedColor
setColor()
resetIdleTimer()
},
) { colorToDelete, newColor ->
baseModel.changeColor(colorToDelete, newColor)
@ -652,6 +684,7 @@ abstract class EditActivity(private val type: Type) :
notallyModel.color = newColor
setColor()
}
resetIdleTimer()
}
}
}

View file

@ -40,7 +40,7 @@ import com.philkes.notallyx.presentation.widget.WidgetProvider
import com.philkes.notallyx.utils.Cache
import com.philkes.notallyx.utils.Event
import com.philkes.notallyx.utils.FileError
import com.philkes.notallyx.utils.backup.checkAutoSave
import com.philkes.notallyx.utils.backup.checkBackupOnSave
import com.philkes.notallyx.utils.backup.importAudio
import com.philkes.notallyx.utils.backup.importFile
import com.philkes.notallyx.utils.cancelNoteReminders
@ -268,7 +268,7 @@ class NotallyModel(private val app: Application) : AndroidViewModel(app) {
withContext(Dispatchers.IO) { app.deleteAttachments(attachments) }
}
if (checkAutoSave) {
app.checkAutoSave(preferences, forceFullBackup = true)
app.checkBackupOnSave(preferences, forceFullBackup = true)
}
}
@ -277,19 +277,26 @@ class NotallyModel(private val app: Application) : AndroidViewModel(app) {
this.items.addAll(items)
}
suspend fun saveNote(): Long {
suspend fun saveNote(checkBackupOnSave: Boolean = true): Long {
return withContext(Dispatchers.IO) {
val note = getBaseNote()
val id = baseNoteDao.insert(note)
app.checkAutoSave(
preferences,
note = note,
forceFullBackup = originalNote?.attachmentsDifferFrom(note) == true,
)
if (checkBackupOnSave) {
checkBackupOnSave(note)
}
originalNote = note.deepCopy()
return@withContext id
}
}
suspend fun checkBackupOnSave(note: BaseNote = getBaseNote()) {
app.checkBackupOnSave(
preferences,
note = note,
forceFullBackup = originalNote?.attachmentsDifferFrom(note) == true,
)
}
fun isEmpty(): Boolean {
return title.isEmpty() &&
body.isEmpty() &&

View file

@ -111,6 +111,16 @@ class NotallyXPreferences private constructor(private val context: Context) {
)
}
val autoSaveAfterIdleTime =
IntPreference(
"autoSaveAfterIdleTime",
preferences,
5,
-1,
20,
R.string.auto_save_after_idle_time,
)
val biometricLock =
createEnumPreference(
preferences,
@ -219,6 +229,7 @@ class NotallyXPreferences private constructor(private val context: Context) {
periodicBackups,
backupPassword,
backupOnSave,
autoSaveAfterIdleTime,
)
.forEach { it.refresh() }
}

View file

@ -81,6 +81,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import net.lingala.zip4j.ZipFile
import net.lingala.zip4j.exception.ZipException
import net.lingala.zip4j.model.ZipParameters
import net.lingala.zip4j.model.enums.CompressionLevel
import net.lingala.zip4j.model.enums.EncryptionMethod
@ -164,6 +165,9 @@ fun ContextWrapper.autoBackupOnSave(backupPath: String, password: String, savedN
backupPath,
"Auto backup on note save (${savedNote?.let { "id: '${savedNote.id}, title: '${savedNote.title}'" }}) failed, because auto-backup path '$backupPath' is invalid",
) ?: return
fun log(msg: String? = null, throwable: Throwable? = null) {
logToFile(TAG, folder, NOTALLYX_BACKUP_LOGS_FILE, msg = msg, throwable = throwable)
}
try {
var backupFile = folder.findFile(ON_SAVE_BACKUP_FILE)
if (savedNote == null || backupFile == null || !backupFile.exists()) {
@ -193,16 +197,21 @@ fun ContextWrapper.autoBackupOnSave(backupPath: String, password: String, savedN
NotallyDatabase.getCurrentDatabaseFile(this@autoBackupOnSave),
)
}
exportToZip(backupFile.uri, files, password)
try {
exportToZip(backupFile.uri, files, password)
} catch (e: ZipException) {
log(
msg =
"Re-creating full backup since existing auto backup ZIP is corrupt: ${e.message}"
)
backupFile.delete()
autoBackupOnSave(backupPath, password, savedNote)
}
}
} catch (e: Exception) {
logToFile(
TAG,
folder,
NOTALLYX_BACKUP_LOGS_FILE,
msg =
"Auto backup on note save (${savedNote?.let { "id: '${savedNote.id}, title: '${savedNote.title}'" }}) failed",
throwable = e,
log(
"Auto backup on note save (${savedNote?.let { "id: '${savedNote.id}, title: '${savedNote.title}'" }}) failed",
e,
)
tryPostErrorNotification(e)
}
@ -224,7 +233,7 @@ private fun ContextWrapper.requireBackupFolder(path: String, msg: String): Docum
}
}
suspend fun ContextWrapper.checkAutoSave(
suspend fun ContextWrapper.checkBackupOnSave(
preferences: NotallyXPreferences,
note: BaseNote? = null,
forceFullBackup: Boolean = false,
@ -400,6 +409,7 @@ fun ContextWrapper.copyDatabase(): Pair<NotallyDatabase, File> {
val database = NotallyDatabase.getDatabase(this, observePreferences = false).value
database.checkpoint()
val preferences = NotallyXPreferences.getInstance(this)
val databaseFile = NotallyDatabase.getCurrentDatabaseFile(this)
return if (
preferences.biometricLock.value == BiometricLock.ENABLED &&
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
@ -407,16 +417,11 @@ fun ContextWrapper.copyDatabase(): Pair<NotallyDatabase, File> {
val cipher = getInitializedCipherForDecryption(iv = preferences.iv.value!!)
val passphrase = cipher.doFinal(preferences.databaseEncryptionKey.value)
val decryptedFile = File(cacheDir, DATABASE_NAME)
decryptDatabase(
this,
passphrase,
decryptedFile,
NotallyDatabase.getExternalDatabaseFile(this),
)
decryptDatabase(this, passphrase, decryptedFile, databaseFile)
Pair(database, decryptedFile)
} else {
val dbFile = File(cacheDir, DATABASE_NAME)
NotallyDatabase.getCurrentDatabaseFile(this).copyTo(dbFile, overwrite = true)
databaseFile.copyTo(dbFile, overwrite = true)
Pair(database, dbFile)
}
}

View file

@ -6,7 +6,7 @@ import kotlin.IllegalStateException
class ChangeHistory {
private val changeStack = ArrayList<Change>()
private var stackPointer = NotNullLiveData(-1)
var stackPointer = NotNullLiveData(-1)
internal val canUndo = NotNullLiveData(false)
internal val canRedo = NotNullLiveData(false)

View file

@ -30,6 +30,16 @@
android:id="@+id/TextSize"
layout="@layout/preference" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?android:attr/listDivider" />
<TextView
style="@style/PreferenceHeader"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/behaviour" />
<include
android:id="@+id/NotesSortOrder"
@ -39,11 +49,14 @@
android:id="@+id/CheckedListItemSorting"
layout="@layout/preference" />
<include
android:id="@+id/StartView"
layout="@layout/preference" />
<include
android:id="@+id/AutoSaveAfterIdle"
layout="@layout/preference_seekbar" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
@ -222,18 +235,11 @@
android:text="@string/send_feedback" />
<TextView
android:id="@+id/SourceCode"
style="@style/Preference"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/source_code" />
<TextView
android:id="@+id/Libraries"
style="@style/Preference"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/libraries" />
android:id="@+id/Rate"
style="@style/Preference"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/rate" />
<TextView
android:id="@+id/Donate"
@ -242,6 +248,20 @@
android:layout_height="wrap_content"
android:text="@string/donate" />
<TextView
android:id="@+id/SourceCode"
style="@style/Preference"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/source_code" />
<TextView
android:id="@+id/Libraries"
style="@style/Preference"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/libraries" />
<TextView
android:id="@+id/VersionText"
android:layout_width="match_parent"

View file

@ -23,7 +23,7 @@
<string name="auto_backup_error_message">Během automatického zálohování došlo k chybě:\n\'%1$s\'\nProsím, zkontrolujte nastavení nebo nahlaste chybu</string>
<string name="auto_backup_failed">Automatické zálohování NotallyX selhalo</string>
<string name="auto_backup_last">Poslední záloha</string>
<string name="auto_backup_on_save">Automaticky zálohovat při uložení poznámky</string>
<string name="auto_backup_on_save">Automaticky zálohovat při ukončení poznámky</string>
<string name="auto_backup_on_save_hint">Pokud tuto možnost povolíte, záloha („NotallyX_AutoBackup.zip“) bude automaticky vytvořena ve zvoleném „Adresáři záloh“ pokaždé, když bude poznámka uložena. Mějte na paměti, že to může ovlivnit výkon</string>
<string name="auto_backup_period">Frekvence automatického zálohování</string>
<string name="auto_backups_folder">Adresář pro zálohy</string>

View file

@ -22,8 +22,8 @@
<string name="auto_backup_error_message">Beim autom. Backup ist ein Fehler aufgetreten:\n\'%1$s\'\nÜberprüfe deine Einstellungen oder melde einen Bug</string>
<string name="auto_backup_failed">NotallyX Auto Backup fehlgeschlagen</string>
<string name="auto_backup_last">Letztes Backup</string>
<string name="auto_backup_on_save">Autom. Backup beim Notiz-Speichern</string>
<string name="auto_backup_on_save_hint">Ist dies aktiviert, wird jedesmal wenn eine Notiz gespeichert wird autom. ein Backup (\"NotallyX_AutoBackup.zip\") im \"Backups Ordner\" erstellt.\nDies kann die App-Performance beeinträchtigen</string>
<string name="auto_backup_on_save">Autom. Backup beim Notiz Verlassen</string>
<string name="auto_backup_on_save_hint">Ist dies aktiviert, wird jedesmal wenn eine Notiz verlassen wird autom. ein Backup (\"NotallyX_AutoBackup.zip\") im \"Backups Ordner\" erstellt.\nDies kann die App-Performance beeinträchtigen</string>
<string name="auto_backup_period">Intervall für autom. Backups</string>
<string name="auto_backups_folder">Backups Ordner</string>
<string name="auto_backups_folder_hint">Ordner in dem alle autom. Backups erstellt werden</string>

View file

@ -22,7 +22,7 @@
<string name="auto_backup_error_message">Ha ocurrido un error durante una copia automática:\n\'%1$s\nComprueba tus ajustes o informa de un error</string>
<string name="auto_backup_failed">Falló la copia de seguridad automática de Notallyx</string>
<string name="auto_backup_last">Última copia de seguridad</string>
<string name="auto_backup_on_save">Copia de seguridad automática al guardar una nota</string>
<string name="auto_backup_on_save">Copia de seguridad automática al salir una nota</string>
<string name="auto_backup_on_save_hint">Al habilitar esta opción, se crea automáticamente una copia de seguridad (\"NotallyX_AutoBackup.zip\") en la \"Directorio de copias de seguridad\" configurada cada vez que se guarda una nota.\nTenga en cuenta que esto puede afectar el rendimiento.</string>
<string name="auto_backup_period">Periodo de copia automática</string>
<string name="auto_backups_folder">Directorio de copias de seguridad</string>

View file

@ -22,7 +22,7 @@
<string name="auto_backup_error_message">Une erreur est survenue lors de la sauvegarde automatique:\n\'%1$s\'\nVeuillez vérifier vos paramètres ou signaler un bug</string>
<string name="auto_backup_failed">La sauvegarde automatique de NotallyX a échoué </string>
<string name="auto_backup_last">Dernière sauvegarde</string>
<string name="auto_backup_on_save">Sauvegarde automatique après chaque édition</string>
<string name="auto_backup_on_save">Sauvegarde automatique après avoir quitté la note</string>
<string name="auto_backup_on_save_hint">En activant cette option, une sauvegarde (\"NotallyX_AutoBackup.zip\") est automatiquement créée dans le \"Dossier des sauvegardes\" configuré, à chaque fois qu\'une note est enregistrée.\nAttention, cela pourrait affecter les performances.</string>
<string name="auto_backups_folder">Dossier des sauvegardes</string>
<string name="auto_backups_folder_hint">Dossier dans lequel toutes les sauvegardes automatiques seront stockées.</string>

View file

@ -22,7 +22,7 @@
<string name="auto_backup_error_message">Si é verificato un errore durante il backup automatico:\n\'%1$s\'\nPer favore controlla le tue impostazioni o segnala un bug</string>
<string name="auto_backup_failed">Backup automatico di NotallyX non riuscito</string>
<string name="auto_backup_last">Ultimo backup</string>
<string name="auto_backup_on_save">Backup automatico al salvataggio della nota</string>
<string name="auto_backup_on_save">Backup automatico dopo l\'uscita dalla nota</string>
<string name="auto_backup_on_save_hint">Abilitando questa opzione, un backup (NotallyX_AutoBackup.zip) verrà creato automaticamente nella \"Cartella di Backup\" configurata ogni volta che una nota viene salvata.\nTieni presente che questa operazione potrebbe influire sulle prestazioni</string>
<string name="auto_backup_period">Frequenza dei backup automatici</string>
<string name="auto_backups_folder">Cartella backup</string>

View file

@ -22,7 +22,7 @@
<string name="auto_backup_error_message">Wystąpił błąd podczas tworzenia automatycznej kopii zapasowej:\n„%1$s”\nSprawdź ustawienia lub zgłoś błąd</string>
<string name="auto_backup_failed">Automatyczna kopia zapasowa NotallyX nie powiodła się</string>
<string name="auto_backup_last">Ostatnia kopia zapasowa</string>
<string name="auto_backup_on_save">Kopia zapasowa po zapisaniu notatki</string>
<string name="auto_backup_on_save">Kopia zapasowa po wyjściu z notatki</string>
<string name="auto_backup_on_save_hint">Po włączeniu tej opcji kopia zapasowa („NotallyX_AutoBackup.zip”) jest automatycznie tworzona w skonfigurowanym „Folderze kopii zapasowych” za każdym razem, gdy zapisywana jest notatka.\nPamiętaj, że może mieć to wpływ na wydajność</string>
<string name="auto_backup_period">Okres tworzenia automatycznych kopii zapasowych</string>
<string name="auto_backups_folder">Folder kopii zapasowych</string>

View file

@ -29,6 +29,7 @@
<string name="auto_backups_folder_hint">保存所有自动备份文件的文件夹</string>
<string name="auto_backups_folder_rechoose">你需要重新选择备份文件夹,这样 NotallyX 有写入它的权限。你也可以按:取消“跳过导入备份文件夹的值</string>
<string name="auto_backups_folder_set">先在上方设置备份文件夹</string>
<string name="auto_save_after_idle_time">在指定的空闲时间后自动保存笔记</string>
<string name="auto_sort_by_checked">将所选项目排到末尾</string>
<string name="back">返回</string>
<string name="backup">备份</string>
@ -37,6 +38,7 @@
<string name="backup_period_days">自动备份周期/天</string>
<string name="backup_periodic">定期备份</string>
<string name="backup_periodic_hint">启用此选项后将自动在配置的备份文件夹中创建备份文件。如果你启用了节能模式,这可能无法正常工作</string>
<string name="behaviour">行为</string>
<string name="biometric_lock">使用生物识别或PIN解锁应用</string>
<string name="biometrics_disable_success">已停用生物特征/Pin 锁</string>
<string name="biometrics_failure">未能通过生物特征/PIN验证身份</string>
@ -158,6 +160,7 @@
<string name="import_backup">导入备份</string>
<string name="import_backup_password_hint">如果你的备份文件没有密码保护,只需按下“导入”即可。如有,起输入正确的密码</string>
<string name="import_other">从其它APP导入笔记</string>
<string name="import_settings">导入设置</string>
<string name="import_settings_failure">导入设置</string>
<string name="import_settings_message">为了导入设置,请选择有效的 NotallyX 设置 JSON 文件</string>
<string name="import_settings_success">成功地导入了设置</string>

View file

@ -23,13 +23,14 @@
<string name="auto_backup_error_message">An error occurred during auto backup:\n\'%1$s\'\nPlease check your settings or report a bug</string>
<string name="auto_backup_failed">NotallyX Auto Backup failed</string>
<string name="auto_backup_last">Last Backup</string>
<string name="auto_backup_on_save">Backup on Note save automatically</string>
<string name="auto_backup_on_save_hint">By enabling this, a backup (\"NotallyX_AutoBackup.zip\") is automatically created in the configured \"Backups Folder\" whenever a note is saved.\nBe aware this might affect performance</string>
<string name="auto_backup_on_save">Backup on exit Note automatically</string>
<string name="auto_backup_on_save_hint">By enabling this, a backup (\"NotallyX_AutoBackup.zip\") is automatically created in the configured \"Backups Folder\" whenever a note is exited.\nBe aware this might affect performance</string>
<string name="auto_backup_period">Auto backup period</string>
<string name="auto_backups_folder">Backups Folder</string>
<string name="auto_backups_folder_hint">Folder in which all auto backups will be stored in.</string>
<string name="auto_backups_folder_rechoose">You need to re-choose your Backups Folder so that NotallyX has permission to write to it.\nYou can also press cancel to skip importing Backups Folder value</string>
<string name="auto_backups_folder_set">Set up a Backups Folder above first</string>
<string name="auto_save_after_idle_time">Auto save note after specified idle time</string>
<string name="auto_sort_by_checked">Sort checked items to the end</string>
<string name="back">Back</string>
<string name="backup">Backup</string>
@ -38,6 +39,7 @@
<string name="backup_period_days">Auto backup period in days</string>
<string name="backup_periodic">Periodic Backups</string>
<string name="backup_periodic_hint">By enabling this, backups are automatically created in the configured Backups Folder.\nThis may not work if you have power saving mode enabled</string>
<string name="behaviour">Behaviour</string>
<string name="biometric_lock">Lock app with device biometric or PIN</string>
<string name="biometrics_disable_success">Biometric/PIN lock has been disabled</string>
<string name="biometrics_failure">Failed to authenticate via Biometric/PIN</string>

Binary file not shown.

View file

@ -0,0 +1 @@
* Fix Backup Export wenn Biometrische Sperre aktiv ist

View file

@ -0,0 +1 @@
* Fix exporting backups with biometric lock enabled

View file

@ -21,5 +21,5 @@ org.gradle.parallel=true
android.experimental.enableNewResourceShrinker.preciseShrinking=true
android.defaults.buildfeatures.buildconfig=true
app.lastVersionName=7.2.0
app.versionCode=7200
app.versionName=7.2.0
app.versionCode=7210
app.versionName=7.2.1