mirror of
https://github.com/SimpleMobileTools/Simple-Notes.git
synced 2025-04-19 17:57:27 +02:00
Merge branch 'master' into fix-import-dialog
This commit is contained in:
commit
e93fb03484
@ -1,6 +1,12 @@
|
|||||||
Changelog
|
Changelog
|
||||||
==========
|
==========
|
||||||
|
|
||||||
|
Version 6.8.2 *(2021-09-13)*
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
* Added biometric protection on Android 11+
|
||||||
|
* Fixed a glitch with note content vanishing on export error
|
||||||
|
|
||||||
Version 6.8.1 *(2021-08-23)*
|
Version 6.8.1 *(2021-08-23)*
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
|
@ -16,8 +16,8 @@ android {
|
|||||||
applicationId "com.simplemobiletools.notes.pro"
|
applicationId "com.simplemobiletools.notes.pro"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 30
|
targetSdkVersion 30
|
||||||
versionCode 84
|
versionCode 85
|
||||||
versionName "6.8.1"
|
versionName "6.8.2"
|
||||||
setProperty("archivesBaseName", "notes")
|
setProperty("archivesBaseName", "notes")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'com.github.SimpleMobileTools:Simple-Commons:dc3f4b619e'
|
implementation 'com.github.SimpleMobileTools:Simple-Commons:7c0a8d628e'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
|
implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
|
||||||
implementation 'androidx.documentfile:documentfile:1.0.1'
|
implementation 'androidx.documentfile:documentfile:1.0.1'
|
||||||
|
|
||||||
|
@ -11,8 +11,6 @@
|
|||||||
android:name="android.hardware.faketouch"
|
android:name="android.hardware.faketouch"
|
||||||
android:required="false" />
|
android:required="false" />
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
|
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".App"
|
android:name=".App"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
|
@ -319,8 +319,11 @@ class MainActivity : SimpleActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun initViewPager(wantedNoteId: Long? = null) {
|
private fun initViewPager(wantedNoteId: Long? = null) {
|
||||||
NotesHelper(this).getNotes {
|
NotesHelper(this).getNotes { notes ->
|
||||||
mNotes = it
|
notes.filter { it.shouldBeUnlocked(this) }
|
||||||
|
.forEach(::removeProtection)
|
||||||
|
|
||||||
|
mNotes = notes
|
||||||
invalidateOptionsMenu()
|
invalidateOptionsMenu()
|
||||||
mCurrentNote = mNotes[0]
|
mCurrentNote = mNotes[0]
|
||||||
mAdapter = NotesPagerAdapter(supportFragmentManager, mNotes, this)
|
mAdapter = NotesPagerAdapter(supportFragmentManager, mNotes, this)
|
||||||
@ -750,7 +753,8 @@ class MainActivity : SimpleActivity() {
|
|||||||
|
|
||||||
RadioGroupDialog(this, items) {
|
RadioGroupDialog(this, items) {
|
||||||
val syncFile = it as Int == EXPORT_FILE_SYNC
|
val syncFile = it as Int == EXPORT_FILE_SYNC
|
||||||
tryExportNoteValueToFile(exportPath, textToExport, true) {
|
tryExportNoteValueToFile(exportPath, textToExport, true) { exportedSuccessfully ->
|
||||||
|
if (exportedSuccessfully) {
|
||||||
if (syncFile) {
|
if (syncFile) {
|
||||||
mCurrentNote.path = exportPath
|
mCurrentNote.path = exportPath
|
||||||
mCurrentNote.value = ""
|
mCurrentNote.value = ""
|
||||||
@ -764,6 +768,7 @@ class MainActivity : SimpleActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun tryExportAllNotes() {
|
private fun tryExportAllNotes() {
|
||||||
handlePermission(PERMISSION_WRITE_STORAGE) {
|
handlePermission(PERMISSION_WRITE_STORAGE) {
|
||||||
@ -792,7 +797,8 @@ class MainActivity : SimpleActivity() {
|
|||||||
toast(String.format(getString(R.string.filename_invalid_characters_placeholder, filename)))
|
toast(String.format(getString(R.string.filename_invalid_characters_placeholder, filename)))
|
||||||
} else {
|
} else {
|
||||||
val noteStoredValue = note.getNoteStoredValue(this) ?: ""
|
val noteStoredValue = note.getNoteStoredValue(this) ?: ""
|
||||||
tryExportNoteValueToFile(file.absolutePath, note.value, false) {
|
tryExportNoteValueToFile(file.absolutePath, note.value, false) { exportedSuccessfully ->
|
||||||
|
if (exportedSuccessfully) {
|
||||||
if (syncFile) {
|
if (syncFile) {
|
||||||
note.path = file.absolutePath
|
note.path = file.absolutePath
|
||||||
note.value = ""
|
note.value = ""
|
||||||
@ -802,13 +808,15 @@ class MainActivity : SimpleActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NotesHelper(this).insertOrUpdateNote(note)
|
NotesHelper(this).insertOrUpdateNote(note)
|
||||||
|
}
|
||||||
|
|
||||||
if (mCurrentNote.id == note.id) {
|
if (mCurrentNote.id == note.id) {
|
||||||
mCurrentNote.value = note.value
|
mCurrentNote.value = note.value
|
||||||
mCurrentNote.path = note.path
|
mCurrentNote.path = note.path
|
||||||
getPagerAdapter().updateCurrentNoteData(view_pager.currentItem, mCurrentNote.path, mCurrentNote.value)
|
getPagerAdapter().updateCurrentNoteData(view_pager.currentItem, mCurrentNote.path, mCurrentNote.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!it) {
|
if (!exportedSuccessfully) {
|
||||||
failCount++
|
failCount++
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -880,7 +888,7 @@ class MainActivity : SimpleActivity() {
|
|||||||
|
|
||||||
private fun exportNoteValueToUri(uri: Uri, content: String, callback: ((success: Boolean) -> Unit)? = null) {
|
private fun exportNoteValueToUri(uri: Uri, content: String, callback: ((success: Boolean) -> Unit)? = null) {
|
||||||
try {
|
try {
|
||||||
val outputStream = contentResolver.openOutputStream(uri, "wt")
|
val outputStream = contentResolver.openOutputStream(uri, "rwt")
|
||||||
outputStream!!.bufferedWriter().use { out ->
|
outputStream!!.bufferedWriter().use { out ->
|
||||||
out.write(content)
|
out.write(content)
|
||||||
}
|
}
|
||||||
@ -1087,14 +1095,15 @@ class MainActivity : SimpleActivity() {
|
|||||||
performSecurityCheck(
|
performSecurityCheck(
|
||||||
protectionType = mCurrentNote.protectionType,
|
protectionType = mCurrentNote.protectionType,
|
||||||
requiredHash = mCurrentNote.protectionHash,
|
requiredHash = mCurrentNote.protectionHash,
|
||||||
successCallback = { _, _ -> removeProtection() }
|
successCallback = { _, _ -> removeProtection(mCurrentNote) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun removeProtection() {
|
private fun removeProtection(note: Note) {
|
||||||
mCurrentNote.protectionHash = ""
|
note.protectionHash = ""
|
||||||
mCurrentNote.protectionType = PROTECTION_NONE
|
note.protectionType = PROTECTION_NONE
|
||||||
NotesHelper(this).insertOrUpdateNote(mCurrentNote) {
|
NotesHelper(this).insertOrUpdateNote(note) {
|
||||||
|
if (note == mCurrentNote) {
|
||||||
getCurrentFragment()?.apply {
|
getCurrentFragment()?.apply {
|
||||||
shouldShowLockedContent = true
|
shouldShowLockedContent = true
|
||||||
checkLockState()
|
checkLockState()
|
||||||
@ -1102,6 +1111,7 @@ class MainActivity : SimpleActivity() {
|
|||||||
invalidateOptionsMenu()
|
invalidateOptionsMenu()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun currentNoteTextChanged(newText: String, showUndo: Boolean, showRedo: Boolean) {
|
fun currentNoteTextChanged(newText: String, showUndo: Boolean, showRedo: Boolean) {
|
||||||
if (!isSearchActive) {
|
if (!isSearchActive) {
|
||||||
|
@ -104,16 +104,18 @@ class WidgetConfigureActivity : SimpleActivity() {
|
|||||||
|
|
||||||
if (mNotes.size == 1 && note == null) {
|
if (mNotes.size == 1 && note == null) {
|
||||||
note = mNotes.first()
|
note = mNotes.first()
|
||||||
|
if (note.shouldBeUnlocked(this)) {
|
||||||
|
updateCurrentNote(note)
|
||||||
|
} else {
|
||||||
performSecurityCheck(
|
performSecurityCheck(
|
||||||
protectionType = note.protectionType,
|
protectionType = note.protectionType,
|
||||||
requiredHash = note.protectionHash,
|
requiredHash = note.protectionHash,
|
||||||
successCallback = { _, _ -> updateCurrentNote(note) },
|
successCallback = { _, _ -> updateCurrentNote(note) },
|
||||||
failureCallback = { finish() }
|
failureCallback = { finish() }
|
||||||
)
|
)
|
||||||
} else {
|
|
||||||
if (note != null) {
|
|
||||||
updateCurrentNote(note)
|
|
||||||
}
|
}
|
||||||
|
} else if (note != null) {
|
||||||
|
updateCurrentNote(note)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -127,7 +129,7 @@ class WidgetConfigureActivity : SimpleActivity() {
|
|||||||
RadioGroupDialog(this, items, mCurrentNoteId.toInt()) {
|
RadioGroupDialog(this, items, mCurrentNoteId.toInt()) {
|
||||||
val selectedId = it as Int
|
val selectedId = it as Int
|
||||||
val note = mNotes.firstOrNull { it.id!!.toInt() == selectedId } ?: return@RadioGroupDialog
|
val note = mNotes.firstOrNull { it.id!!.toInt() == selectedId } ?: return@RadioGroupDialog
|
||||||
if (note.protectionType == PROTECTION_NONE) {
|
if (note.protectionType == PROTECTION_NONE || note.shouldBeUnlocked(this)) {
|
||||||
updateCurrentNote(note)
|
updateCurrentNote(note)
|
||||||
} else {
|
} else {
|
||||||
performSecurityCheck(
|
performSecurityCheck(
|
||||||
|
@ -78,11 +78,13 @@ class ChecklistFragment : NoteFragment(), ChecklistItemsListener {
|
|||||||
items.clear()
|
items.clear()
|
||||||
|
|
||||||
note.value.split("\n").map { it.trim() }.filter { it.isNotBlank() }.forEachIndexed { index, value ->
|
note.value.split("\n").map { it.trim() }.filter { it.isNotBlank() }.forEachIndexed { index, value ->
|
||||||
items.add(ChecklistItem(
|
items.add(
|
||||||
|
ChecklistItem(
|
||||||
id = index,
|
id = index,
|
||||||
title = value,
|
title = value,
|
||||||
isDone = false
|
isDone = false
|
||||||
))
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
saveChecklist()
|
saveChecklist()
|
||||||
@ -120,6 +122,10 @@ class ChecklistFragment : NoteFragment(), ChecklistItemsListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun checkLockState() {
|
override fun checkLockState() {
|
||||||
|
if (note == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
view.apply {
|
view.apply {
|
||||||
checklist_content_holder.beVisibleIf(!note!!.isLocked() || shouldShowLockedContent)
|
checklist_content_holder.beVisibleIf(!note!!.isLocked() || shouldShowLockedContent)
|
||||||
checklist_fab.beVisibleIf(!note!!.isLocked() || shouldShowLockedContent)
|
checklist_fab.beVisibleIf(!note!!.isLocked() || shouldShowLockedContent)
|
||||||
|
@ -176,6 +176,10 @@ class TextFragment : NoteFragment() {
|
|||||||
fun removeTextWatcher() = view.text_note_view.removeTextChangedListener(textWatcher)
|
fun removeTextWatcher() = view.text_note_view.removeTextChangedListener(textWatcher)
|
||||||
|
|
||||||
override fun checkLockState() {
|
override fun checkLockState() {
|
||||||
|
if (note == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
view.apply {
|
view.apply {
|
||||||
notes_counter.beVisibleIf((!note!!.isLocked() || shouldShowLockedContent) && config!!.showWordCount)
|
notes_counter.beVisibleIf((!note!!.isLocked() || shouldShowLockedContent) && config!!.showWordCount)
|
||||||
notes_scrollview.beVisibleIf(!note!!.isLocked() || shouldShowLockedContent)
|
notes_scrollview.beVisibleIf(!note!!.isLocked() || shouldShowLockedContent)
|
||||||
@ -263,11 +267,13 @@ class TextFragment : NoteFragment() {
|
|||||||
text.removeSpan(span)
|
text.removeSpan(span)
|
||||||
}
|
}
|
||||||
|
|
||||||
Selection.setSelection(text, if (edit.before == null) {
|
Selection.setSelection(
|
||||||
|
text, if (edit.before == null) {
|
||||||
start
|
start
|
||||||
} else {
|
} else {
|
||||||
start + edit.before.length
|
start + edit.before.length
|
||||||
})
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun redo() {
|
fun redo() {
|
||||||
@ -285,11 +291,13 @@ class TextFragment : NoteFragment() {
|
|||||||
text.removeSpan(o)
|
text.removeSpan(o)
|
||||||
}
|
}
|
||||||
|
|
||||||
Selection.setSelection(text, if (edit.after == null) {
|
Selection.setSelection(
|
||||||
|
text, if (edit.after == null) {
|
||||||
start
|
start
|
||||||
} else {
|
} else {
|
||||||
start + edit.after.length
|
start + edit.after.length
|
||||||
})
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isUndoAvailable() = textHistory.position > 0
|
fun isUndoAvailable() = textHistory.position > 0
|
||||||
|
@ -6,6 +6,8 @@ import androidx.room.ColumnInfo
|
|||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.Index
|
import androidx.room.Index
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
|
import com.simplemobiletools.commons.extensions.isBiometricIdAvailable
|
||||||
|
import com.simplemobiletools.commons.helpers.PROTECTION_FINGERPRINT
|
||||||
import com.simplemobiletools.commons.helpers.PROTECTION_NONE
|
import com.simplemobiletools.commons.helpers.PROTECTION_NONE
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@ -17,7 +19,8 @@ data class Note(
|
|||||||
@ColumnInfo(name = "type") var type: Int,
|
@ColumnInfo(name = "type") var type: Int,
|
||||||
@ColumnInfo(name = "path") var path: String,
|
@ColumnInfo(name = "path") var path: String,
|
||||||
@ColumnInfo(name = "protection_type") var protectionType: Int,
|
@ColumnInfo(name = "protection_type") var protectionType: Int,
|
||||||
@ColumnInfo(name = "protection_hash") var protectionHash: String) {
|
@ColumnInfo(name = "protection_hash") var protectionHash: String
|
||||||
|
) {
|
||||||
|
|
||||||
fun getNoteStoredValue(context: Context): String? {
|
fun getNoteStoredValue(context: Context): String? {
|
||||||
return if (path.isNotEmpty()) {
|
return if (path.isNotEmpty()) {
|
||||||
@ -37,4 +40,8 @@ data class Note(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun isLocked() = protectionType != PROTECTION_NONE
|
fun isLocked() = protectionType != PROTECTION_NONE
|
||||||
|
|
||||||
|
fun shouldBeUnlocked(context: Context): Boolean {
|
||||||
|
return protectionType == PROTECTION_FINGERPRINT && !context.isBiometricIdAvailable()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
2
fastlane/metadata/android/en-US/changelogs/85.txt
Normal file
2
fastlane/metadata/android/en-US/changelogs/85.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
* Added biometric protection on Android 11+
|
||||||
|
* Fixed a glitch with note content vanishing on export error
|
Loading…
x
Reference in New Issue
Block a user