diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 90374fab..dd2875db 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -92,6 +92,11 @@
+
+
+
NOTE_URL_POSTFIX_LIST
+ Type.NOTE -> NOTE_URL_POSTFIX_NOTE
+ }
+ return "$NOTE_URL_PREFIX$this$postfix"
+}
+
+fun String.getNoteIdFromUrl(): Long {
+ return substringAfter(NOTE_URL_PREFIX).substringBefore("/").toLong()
+}
+
+fun String.getNoteTypeFromUrl(): Type {
+ return Type.valueOf(substringAfterLast("/"))
+}
+
+fun String.getUrl(start: Int, end: Int): String {
+ return if (end <= length) {
+ substring(start, end).toUrl()
+ } else substring(start, length).toUrl()
+}
+
+private fun String.toUrl(): String {
+ return when {
+ matches(Patterns.PHONE.toRegex()) -> "tel:$this"
+ matches(Patterns.EMAIL_ADDRESS.toRegex()) -> "mailto:$this"
+ matches(Patterns.DOMAIN_NAME.toRegex()) -> "http://$this"
+ else -> this
+ }
+}
+
+val FileAttachment.isImage: Boolean
+ get() {
+ return mimeType.startsWith("image/")
+ }
+
+val String.toPreservedByteArray: ByteArray
+ get() {
+ return this.toByteArray(Charsets.ISO_8859_1)
+ }
+
+val ByteArray.toPreservedString: String
+ get() {
+ return String(this, Charsets.ISO_8859_1)
+ }
diff --git a/app/src/main/java/com/philkes/notallyx/utils/Extensions.kt b/app/src/main/java/com/philkes/notallyx/presentation/UiExtensions.kt
similarity index 89%
rename from app/src/main/java/com/philkes/notallyx/utils/Extensions.kt
rename to app/src/main/java/com/philkes/notallyx/presentation/UiExtensions.kt
index 2ab2780d..bbc2b26e 100644
--- a/app/src/main/java/com/philkes/notallyx/utils/Extensions.kt
+++ b/app/src/main/java/com/philkes/notallyx/presentation/UiExtensions.kt
@@ -1,7 +1,9 @@
-package com.philkes.notallyx.utils
+package com.philkes.notallyx.presentation
import android.app.Activity
import android.app.KeyguardManager
+import android.content.ClipData
+import android.content.ClipboardManager
import android.content.Context
import android.content.pm.PackageManager
import android.content.res.Resources
@@ -24,25 +26,28 @@ import android.view.KeyEvent
import android.view.Menu
import android.view.MenuItem
import android.view.View
+import android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
import android.widget.RadioButton
import android.widget.RadioGroup
import android.widget.TextView
+import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity.INPUT_METHOD_SERVICE
import androidx.appcompat.app.AppCompatActivity.KEYGUARD_SERVICE
import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.philkes.notallyx.R
-import com.philkes.notallyx.data.model.FileAttachment
import com.philkes.notallyx.data.model.Folder
import com.philkes.notallyx.data.model.SpanRepresentation
-import com.philkes.notallyx.presentation.activity.note.EditNoteActivity
+import com.philkes.notallyx.data.model.getUrl
import com.philkes.notallyx.presentation.view.misc.DateFormat
+import com.philkes.notallyx.presentation.view.misc.EditTextWithHistory
import com.philkes.notallyx.presentation.view.note.listitem.ListManager
import com.philkes.notallyx.utils.changehistory.ChangeHistory
-import com.philkes.notallyx.utils.changehistory.EditTextChange
+import com.philkes.notallyx.utils.changehistory.EditTextWithHistoryChange
import java.util.Date
import kotlin.math.roundToInt
import org.ocpsoft.prettytime.PrettyTime
@@ -64,7 +69,7 @@ fun String.applySpans(representations: List): Editable {
editable.setSpan(StyleSpan(Typeface.ITALIC), start, end)
}
if (link) {
- val url = linkData ?: getURL(start, end)
+ val url = linkData ?: getUrl(start, end)
editable.setSpan(URLSpan(url), start, end)
}
if (monospace) {
@@ -81,7 +86,7 @@ fun String.applySpans(representations: List): Editable {
}
/**
- * Extension function for Editable to modify or remove spans based on the selection range.
+ * Adjusts or removes spans based on the selection range.
*
* @param selectionStart the start index of the selection
* @param selectionEnd the end index of the selection
@@ -122,12 +127,6 @@ fun Editable.removeSelectionFromSpan(selectionStart: Int, selectionEnd: Int) {
}
}
-private fun String.getURL(start: Int, end: Int): String {
- return if (end <= length) {
- EditNoteActivity.getURLFrom(substring(start, end))
- } else EditNoteActivity.getURLFrom(substring(start, length))
-}
-
private fun Spannable.setSpan(span: Any, start: Int, end: Int) {
if (end <= length) {
setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
@@ -226,7 +225,7 @@ fun EditText.createListTextWatcherWithHistory(listManager: ListManager, position
}
}
-fun EditText.createTextWatcherWithHistory(
+fun EditTextWithHistory.createTextWatcherWithHistory(
changeHistory: ChangeHistory,
onTextChanged: ((text: CharSequence, start: Int, count: Int) -> Unit)? = null,
updateModel: (text: Editable) -> Unit,
@@ -235,7 +234,7 @@ fun EditText.createTextWatcherWithHistory(
private lateinit var currentTextBefore: Editable
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
- currentTextBefore = this@createTextWatcherWithHistory.text.clone()
+ currentTextBefore = this@createTextWatcherWithHistory.getTextClone()
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
@@ -248,11 +247,10 @@ fun EditText.createTextWatcherWithHistory(
updateModel.invoke(textAfter)
changeHistory.push(
- EditTextChange(
+ EditTextWithHistoryChange(
this@createTextWatcherWithHistory,
textBefore,
textAfter,
- this,
updateModel,
)
)
@@ -269,11 +267,6 @@ fun View.getQuantityString(id: Int, quantity: Int, vararg formatArgs: Any): Stri
return context.resources.getQuantityString(id, quantity, *formatArgs)
}
-val FileAttachment.isImage: Boolean
- get() {
- return mimeType.startsWith("image/")
- }
-
fun Folder.movedToResId(): Int {
return when (this) {
Folder.DELETED -> R.plurals.deleted_selected_notes
@@ -287,7 +280,6 @@ fun RadioGroup.checkedTag(): Any {
}
fun Context.canAuthenticateWithBiometrics(): Int {
- var canAuthenticate = true
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
val keyguardManager: KeyguardManager =
@@ -312,16 +304,6 @@ fun Context.canAuthenticateWithBiometrics(): Int {
return BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE
}
-val String.toPreservedByteArray: ByteArray
- get() {
- return this.toByteArray(Charsets.ISO_8859_1)
- }
-
-val ByteArray.toPreservedString: String
- get() {
- return String(this, Charsets.ISO_8859_1)
- }
-
fun LiveData.observeForeverSkipFirst(observer: Observer) {
var isFirstEvent = true
this.observeForever { value ->
@@ -345,3 +327,23 @@ private fun formatTimestamp(timestamp: Long, dateFormat: String): String {
else -> java.text.DateFormat.getDateInstance(java.text.DateFormat.FULL).format(date)
}
}
+
+fun Activity.copyToClipBoard(text: CharSequence) {
+ val clipboard: ClipboardManager =
+ getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
+ val clip = ClipData.newPlainText("label", text)
+ clipboard.setPrimaryClip(clip)
+}
+
+fun ClipboardManager.getLatestText(): CharSequence? {
+ return if (primaryClip!!.itemCount > 0) primaryClip!!.getItemAt(0)!!.text else null
+}
+
+fun MaterialAlertDialogBuilder.showAndFocus(view: View): AlertDialog {
+ val dialog = show()
+ view.requestFocus()
+ if (view is EditText) {
+ dialog.window?.setSoftInputMode(SOFT_INPUT_STATE_VISIBLE)
+ }
+ return dialog
+}
diff --git a/app/src/main/java/com/philkes/notallyx/presentation/activity/ConfigureWidgetActivity.kt b/app/src/main/java/com/philkes/notallyx/presentation/activity/ConfigureWidgetActivity.kt
index 355e0946..0b5aff41 100644
--- a/app/src/main/java/com/philkes/notallyx/presentation/activity/ConfigureWidgetActivity.kt
+++ b/app/src/main/java/com/philkes/notallyx/presentation/activity/ConfigureWidgetActivity.kt
@@ -3,30 +3,13 @@ package com.philkes.notallyx.presentation.activity
import android.appwidget.AppWidgetManager
import android.content.Intent
import android.os.Bundle
-import androidx.lifecycle.lifecycleScope
-import androidx.recyclerview.widget.LinearLayoutManager
-import androidx.recyclerview.widget.RecyclerView
-import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.philkes.notallyx.Preferences
-import com.philkes.notallyx.R
-import com.philkes.notallyx.data.NotallyDatabase
import com.philkes.notallyx.data.model.BaseNote
-import com.philkes.notallyx.data.model.Header
-import com.philkes.notallyx.databinding.ActivityConfigureWidgetBinding
-import com.philkes.notallyx.presentation.view.main.BaseNoteAdapter
-import com.philkes.notallyx.presentation.view.misc.View
-import com.philkes.notallyx.presentation.view.note.listitem.ListItemListener
-import com.philkes.notallyx.presentation.viewmodel.BaseNoteModel
+import com.philkes.notallyx.presentation.activity.note.PickNoteActivity
import com.philkes.notallyx.presentation.widget.WidgetProvider
-import com.philkes.notallyx.utils.IO.getExternalImagesDirectory
-import java.util.Collections
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-class ConfigureWidgetActivity : LockedActivity(), ListItemListener {
+class ConfigureWidgetActivity : PickNoteActivity() {
- private lateinit var adapter: BaseNoteAdapter
private val id by lazy {
intent.getIntExtra(
AppWidgetManager.EXTRA_APPWIDGET_ID,
@@ -36,58 +19,10 @@ class ConfigureWidgetActivity : LockedActivity()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- binding = ActivityConfigureWidgetBinding.inflate(layoutInflater)
- setContentView(binding.root)
val result = Intent()
result.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, id)
setResult(RESULT_CANCELED, result)
-
- val preferences = Preferences.getInstance(application)
-
- adapter =
- with(preferences) {
- BaseNoteAdapter(
- Collections.emptySet(),
- dateFormat.value,
- notesSorting.value.first,
- textSize.value,
- maxItems,
- maxLines,
- maxTitle,
- application.getExternalImagesDirectory(),
- this@ConfigureWidgetActivity,
- )
- }
-
- binding.RecyclerView.apply {
- adapter = this@ConfigureWidgetActivity.adapter
- setHasFixedSize(true)
- layoutManager =
- if (preferences.view.value == View.grid) {
- StaggeredGridLayoutManager(2, RecyclerView.VERTICAL)
- } else LinearLayoutManager(this@ConfigureWidgetActivity)
- }
-
- val database = NotallyDatabase.getDatabase(application)
-
- val pinned = Header(getString(R.string.pinned))
- val others = Header(getString(R.string.others))
-
- database.observe(this) {
- lifecycleScope.launch {
- val notes =
- withContext(Dispatchers.IO) {
- val raw = it.getBaseNoteDao().getAllNotes()
- BaseNoteModel.transform(raw, pinned, others)
- }
- adapter.submitList(notes)
- }
- }
-
- preferences.notesSorting.observe(this) { (sortBy, sortDirection) ->
- adapter.setSorting(sortBy, sortDirection)
- }
}
override fun onClick(position: Int) {
@@ -105,6 +40,4 @@ class ConfigureWidgetActivity : LockedActivity()
finish()
}
}
-
- override fun onLongClick(position: Int) {}
}
diff --git a/app/src/main/java/com/philkes/notallyx/presentation/activity/main/MainActivity.kt b/app/src/main/java/com/philkes/notallyx/presentation/activity/main/MainActivity.kt
index defee25c..fbf1efa9 100644
--- a/app/src/main/java/com/philkes/notallyx/presentation/activity/main/MainActivity.kt
+++ b/app/src/main/java/com/philkes/notallyx/presentation/activity/main/MainActivity.kt
@@ -39,14 +39,14 @@ import com.philkes.notallyx.databinding.DialogColorBinding
import com.philkes.notallyx.presentation.activity.LockedActivity
import com.philkes.notallyx.presentation.activity.note.EditListActivity
import com.philkes.notallyx.presentation.activity.note.EditNoteActivity
+import com.philkes.notallyx.presentation.add
+import com.philkes.notallyx.presentation.applySpans
+import com.philkes.notallyx.presentation.movedToResId
import com.philkes.notallyx.presentation.view.main.ColorAdapter
import com.philkes.notallyx.presentation.view.misc.MenuDialog
import com.philkes.notallyx.presentation.view.note.listitem.ListItemListener
import com.philkes.notallyx.presentation.viewmodel.BaseNoteModel
import com.philkes.notallyx.utils.Operations
-import com.philkes.notallyx.utils.add
-import com.philkes.notallyx.utils.applySpans
-import com.philkes.notallyx.utils.movedToResId
import java.io.File
import kotlinx.coroutines.launch
diff --git a/app/src/main/java/com/philkes/notallyx/presentation/activity/main/fragment/DeletedFragment.kt b/app/src/main/java/com/philkes/notallyx/presentation/activity/main/fragment/DeletedFragment.kt
index ea00781d..ee43deaf 100644
--- a/app/src/main/java/com/philkes/notallyx/presentation/activity/main/fragment/DeletedFragment.kt
+++ b/app/src/main/java/com/philkes/notallyx/presentation/activity/main/fragment/DeletedFragment.kt
@@ -4,7 +4,7 @@ import android.view.Menu
import android.view.MenuInflater
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.philkes.notallyx.R
-import com.philkes.notallyx.utils.add
+import com.philkes.notallyx.presentation.add
class DeletedFragment : NotallyFragment() {
diff --git a/app/src/main/java/com/philkes/notallyx/presentation/activity/main/fragment/LabelsFragment.kt b/app/src/main/java/com/philkes/notallyx/presentation/activity/main/fragment/LabelsFragment.kt
index dedee67a..5248853a 100644
--- a/app/src/main/java/com/philkes/notallyx/presentation/activity/main/fragment/LabelsFragment.kt
+++ b/app/src/main/java/com/philkes/notallyx/presentation/activity/main/fragment/LabelsFragment.kt
@@ -19,12 +19,13 @@ import com.philkes.notallyx.R
import com.philkes.notallyx.data.model.Label
import com.philkes.notallyx.databinding.DialogInputBinding
import com.philkes.notallyx.databinding.FragmentNotesBinding
+import com.philkes.notallyx.presentation.add
+import com.philkes.notallyx.presentation.showAndFocus
import com.philkes.notallyx.presentation.view.Constants
import com.philkes.notallyx.presentation.view.main.LabelAdapter
import com.philkes.notallyx.presentation.view.misc.MenuDialog
import com.philkes.notallyx.presentation.view.note.listitem.ListItemListener
import com.philkes.notallyx.presentation.viewmodel.BaseNoteModel
-import com.philkes.notallyx.utils.add
class LabelsFragment : Fragment(), ListItemListener {
@@ -113,9 +114,7 @@ class LabelsFragment : Fragment(), ListItemListener {
}
}
}
- .show()
-
- dialogBinding.EditText.requestFocus()
+ .showAndFocus(dialogBinding.EditText)
}
private fun confirmDeletion(value: String) {
@@ -152,8 +151,6 @@ class LabelsFragment : Fragment(), ListItemListener {
}
}
}
- .show()
-
- dialogBinding.EditText.requestFocus()
+ .showAndFocus(dialogBinding.EditText)
}
}
diff --git a/app/src/main/java/com/philkes/notallyx/presentation/activity/main/fragment/NotallyFragment.kt b/app/src/main/java/com/philkes/notallyx/presentation/activity/main/fragment/NotallyFragment.kt
index d328ae3c..2f3a0321 100644
--- a/app/src/main/java/com/philkes/notallyx/presentation/activity/main/fragment/NotallyFragment.kt
+++ b/app/src/main/java/com/philkes/notallyx/presentation/activity/main/fragment/NotallyFragment.kt
@@ -25,12 +25,12 @@ import com.philkes.notallyx.presentation.activity.note.EditActivity.Companion.FO
import com.philkes.notallyx.presentation.activity.note.EditActivity.Companion.NOTE_ID
import com.philkes.notallyx.presentation.activity.note.EditListActivity
import com.philkes.notallyx.presentation.activity.note.EditNoteActivity
+import com.philkes.notallyx.presentation.movedToResId
import com.philkes.notallyx.presentation.view.Constants
import com.philkes.notallyx.presentation.view.main.BaseNoteAdapter
import com.philkes.notallyx.presentation.view.misc.View as ViewPref
import com.philkes.notallyx.presentation.view.note.listitem.ListItemListener
import com.philkes.notallyx.presentation.viewmodel.BaseNoteModel
-import com.philkes.notallyx.utils.movedToResId
abstract class NotallyFragment : Fragment(), ListItemListener {
diff --git a/app/src/main/java/com/philkes/notallyx/presentation/activity/main/fragment/NotesFragment.kt b/app/src/main/java/com/philkes/notallyx/presentation/activity/main/fragment/NotesFragment.kt
index 44900c36..53bc7109 100644
--- a/app/src/main/java/com/philkes/notallyx/presentation/activity/main/fragment/NotesFragment.kt
+++ b/app/src/main/java/com/philkes/notallyx/presentation/activity/main/fragment/NotesFragment.kt
@@ -4,7 +4,7 @@ import android.view.Menu
import android.view.MenuInflater
import androidx.navigation.fragment.findNavController
import com.philkes.notallyx.R
-import com.philkes.notallyx.utils.add
+import com.philkes.notallyx.presentation.add
class NotesFragment : NotallyFragment() {
diff --git a/app/src/main/java/com/philkes/notallyx/presentation/activity/main/fragment/SettingsFragment.kt b/app/src/main/java/com/philkes/notallyx/presentation/activity/main/fragment/SettingsFragment.kt
index a699e9b7..7660b6aa 100644
--- a/app/src/main/java/com/philkes/notallyx/presentation/activity/main/fragment/SettingsFragment.kt
+++ b/app/src/main/java/com/philkes/notallyx/presentation/activity/main/fragment/SettingsFragment.kt
@@ -30,6 +30,8 @@ import com.philkes.notallyx.databinding.NotesSortDialogBinding
import com.philkes.notallyx.databinding.PreferenceBinding
import com.philkes.notallyx.databinding.PreferenceSeekbarBinding
import com.philkes.notallyx.databinding.TextInputDialogBinding
+import com.philkes.notallyx.presentation.canAuthenticateWithBiometrics
+import com.philkes.notallyx.presentation.checkedTag
import com.philkes.notallyx.presentation.view.misc.AutoBackup
import com.philkes.notallyx.presentation.view.misc.AutoBackupMax
import com.philkes.notallyx.presentation.view.misc.AutoBackupPeriodDays
@@ -53,8 +55,6 @@ import com.philkes.notallyx.presentation.viewmodel.BaseNoteModel
import com.philkes.notallyx.utils.Operations
import com.philkes.notallyx.utils.backup.BackupProgress
import com.philkes.notallyx.utils.backup.Export.scheduleAutoBackup
-import com.philkes.notallyx.utils.canAuthenticateWithBiometrics
-import com.philkes.notallyx.utils.checkedTag
import com.philkes.notallyx.utils.security.decryptDatabase
import com.philkes.notallyx.utils.security.encryptDatabase
import com.philkes.notallyx.utils.security.showBiometricOrPinPrompt
diff --git a/app/src/main/java/com/philkes/notallyx/presentation/activity/note/EditActivity.kt b/app/src/main/java/com/philkes/notallyx/presentation/activity/note/EditActivity.kt
index b3cba620..7c2a327b 100644
--- a/app/src/main/java/com/philkes/notallyx/presentation/activity/note/EditActivity.kt
+++ b/app/src/main/java/com/philkes/notallyx/presentation/activity/note/EditActivity.kt
@@ -11,7 +11,6 @@ import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.text.Editable
-import android.text.TextWatcher
import android.util.TypedValue
import android.view.MenuItem
import android.view.View
@@ -34,6 +33,8 @@ import com.philkes.notallyx.data.model.Type
import com.philkes.notallyx.databinding.ActivityEditBinding
import com.philkes.notallyx.databinding.DialogProgressBinding
import com.philkes.notallyx.presentation.activity.LockedActivity
+import com.philkes.notallyx.presentation.add
+import com.philkes.notallyx.presentation.displayFormattedTimestamp
import com.philkes.notallyx.presentation.view.Constants
import com.philkes.notallyx.presentation.view.misc.NotesSorting.autoSortByCreationDate
import com.philkes.notallyx.presentation.view.misc.NotesSorting.autoSortByModifiedDate
@@ -45,10 +46,7 @@ import com.philkes.notallyx.presentation.view.note.preview.PreviewImageAdapter
import com.philkes.notallyx.presentation.viewmodel.NotallyModel
import com.philkes.notallyx.utils.FileError
import com.philkes.notallyx.utils.Operations
-import com.philkes.notallyx.utils.add
import com.philkes.notallyx.utils.changehistory.ChangeHistory
-import com.philkes.notallyx.utils.createTextWatcherWithHistory
-import com.philkes.notallyx.utils.displayFormattedTimestamp
import java.io.File
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -56,7 +54,6 @@ import kotlinx.coroutines.launch
abstract class EditActivity(private val type: Type) : LockedActivity() {
internal val model: NotallyModel by viewModels()
internal lateinit var changeHistory: ChangeHistory
- internal lateinit var enterTitleTextWatcher: TextWatcher
override fun finish() {
lifecycleScope.launch(Dispatchers.Main) {
@@ -118,6 +115,7 @@ abstract class EditActivity(private val type: Type) : LockedActivity {
val list =
data?.getParcelableArrayListExtra(
@@ -127,6 +125,7 @@ abstract class EditActivity(private val type: Type) : LockedActivity {
val list = data?.getStringArrayListExtra(SelectLabelsActivity.SELECTED_LABELS)
if (list != null && list != model.labels) {
@@ -134,6 +133,7 @@ abstract class EditActivity(private val type: Type) : LockedActivity model.addAudio()
REQUEST_PLAY_AUDIO -> {
val audio = data?.getParcelableExtra