mirror of
https://github.com/PhilKes/NotallyX.git
synced 2025-06-28 20:29:54 +00:00
Persist viewMode for each note individually
This commit is contained in:
parent
860db3e6bb
commit
c586eab072
23 changed files with 268 additions and 48 deletions
164
app/schemas/com.philkes.notallyx.data.NotallyDatabase/9.json
Normal file
164
app/schemas/com.philkes.notallyx.data.NotallyDatabase/9.json
Normal file
|
@ -0,0 +1,164 @@
|
||||||
|
{
|
||||||
|
"formatVersion": 1,
|
||||||
|
"database": {
|
||||||
|
"version": 9,
|
||||||
|
"identityHash": "794af16cac662f9dc12be0736752f1a5",
|
||||||
|
"entities": [
|
||||||
|
{
|
||||||
|
"tableName": "BaseNote",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `type` TEXT NOT NULL, `folder` TEXT NOT NULL, `color` TEXT NOT NULL, `title` TEXT NOT NULL, `pinned` INTEGER NOT NULL, `timestamp` INTEGER NOT NULL, `modifiedTimestamp` INTEGER NOT NULL, `labels` TEXT NOT NULL, `body` TEXT NOT NULL, `spans` TEXT NOT NULL, `items` TEXT NOT NULL, `images` TEXT NOT NULL, `files` TEXT NOT NULL, `audios` TEXT NOT NULL, `reminders` TEXT NOT NULL, `viewMode` TEXT)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "type",
|
||||||
|
"columnName": "type",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "folder",
|
||||||
|
"columnName": "folder",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "color",
|
||||||
|
"columnName": "color",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "title",
|
||||||
|
"columnName": "title",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "pinned",
|
||||||
|
"columnName": "pinned",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "timestamp",
|
||||||
|
"columnName": "timestamp",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "modifiedTimestamp",
|
||||||
|
"columnName": "modifiedTimestamp",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "labels",
|
||||||
|
"columnName": "labels",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "body",
|
||||||
|
"columnName": "body",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "spans",
|
||||||
|
"columnName": "spans",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "items",
|
||||||
|
"columnName": "items",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "images",
|
||||||
|
"columnName": "images",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "files",
|
||||||
|
"columnName": "files",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "audios",
|
||||||
|
"columnName": "audios",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "reminders",
|
||||||
|
"columnName": "reminders",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "viewMode",
|
||||||
|
"columnName": "viewMode",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": true,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_BaseNote_id_folder_pinned_timestamp_labels",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"id",
|
||||||
|
"folder",
|
||||||
|
"pinned",
|
||||||
|
"timestamp",
|
||||||
|
"labels"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_BaseNote_id_folder_pinned_timestamp_labels` ON `${TABLE_NAME}` (`id`, `folder`, `pinned`, `timestamp`, `labels`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "Label",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`value` TEXT NOT NULL, PRIMARY KEY(`value`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "value",
|
||||||
|
"columnName": "value",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"value"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"views": [],
|
||||||
|
"setupQueries": [
|
||||||
|
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||||
|
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '794af16cac662f9dc12be0736752f1a5')"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,7 +32,7 @@ import net.sqlcipher.database.SQLiteDatabase
|
||||||
import net.sqlcipher.database.SupportFactory
|
import net.sqlcipher.database.SupportFactory
|
||||||
|
|
||||||
@TypeConverters(Converters::class)
|
@TypeConverters(Converters::class)
|
||||||
@Database(entities = [BaseNote::class, Label::class], version = 8)
|
@Database(entities = [BaseNote::class, Label::class], version = 9)
|
||||||
abstract class NotallyDatabase : RoomDatabase() {
|
abstract class NotallyDatabase : RoomDatabase() {
|
||||||
|
|
||||||
abstract fun getLabelDao(): LabelDao
|
abstract fun getLabelDao(): LabelDao
|
||||||
|
@ -131,6 +131,7 @@ abstract class NotallyDatabase : RoomDatabase() {
|
||||||
Migration6,
|
Migration6,
|
||||||
Migration7,
|
Migration7,
|
||||||
Migration8,
|
Migration8,
|
||||||
|
Migration9,
|
||||||
)
|
)
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
SQLiteDatabase.loadLibs(context)
|
SQLiteDatabase.loadLibs(context)
|
||||||
|
@ -261,5 +262,12 @@ abstract class NotallyDatabase : RoomDatabase() {
|
||||||
cursor.close()
|
cursor.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object Migration9 : Migration(8, 9) {
|
||||||
|
|
||||||
|
override fun migrate(db: SupportSQLiteDatabase) {
|
||||||
|
db.execSQL("ALTER TABLE `BaseNote` ADD COLUMN `viewMode` TEXT DEFAULT NULL")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,6 +155,7 @@ fun EvernoteNote.mapToBaseNote(): BaseNote {
|
||||||
files = files,
|
files = files,
|
||||||
audios = audios,
|
audios = audios,
|
||||||
reminders = mutableListOf(),
|
reminders = mutableListOf(),
|
||||||
|
null,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -162,6 +162,7 @@ class GoogleKeepImporter : ExternalImporter {
|
||||||
files = files,
|
files = files,
|
||||||
audios = audios,
|
audios = audios,
|
||||||
reminders = mutableListOf(),
|
reminders = mutableListOf(),
|
||||||
|
null,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,7 @@ class PlainTextImporter : ExternalImporter {
|
||||||
files = listOf(),
|
files = listOf(),
|
||||||
audios = listOf(),
|
audios = listOf(),
|
||||||
reminders = listOf(),
|
reminders = listOf(),
|
||||||
|
null,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ data class BaseNote(
|
||||||
val files: List<FileAttachment>,
|
val files: List<FileAttachment>,
|
||||||
val audios: List<Audio>,
|
val audios: List<Audio>,
|
||||||
val reminders: List<Reminder>,
|
val reminders: List<Reminder>,
|
||||||
|
val viewMode: NoteViewMode?,
|
||||||
) : Item {
|
) : Item {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -53,6 +54,7 @@ data class BaseNote(
|
||||||
if (files != other.files) return false
|
if (files != other.files) return false
|
||||||
if (audios != other.audios) return false
|
if (audios != other.audios) return false
|
||||||
if (reminders != other.reminders) return false
|
if (reminders != other.reminders) return false
|
||||||
|
if (viewMode != other.viewMode) return false
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -73,6 +75,7 @@ data class BaseNote(
|
||||||
result = 31 * result + files.hashCode()
|
result = 31 * result + files.hashCode()
|
||||||
result = 31 * result + audios.hashCode()
|
result = 31 * result + audios.hashCode()
|
||||||
result = 31 * result + reminders.hashCode()
|
result = 31 * result + reminders.hashCode()
|
||||||
|
result = 31 * result + (viewMode?.hashCode() ?: 0)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,8 +34,7 @@ data class ListItem(
|
||||||
if (other !is ListItem) {
|
if (other !is ListItem) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return (this.id == other.id &&
|
return (this.body == other.body &&
|
||||||
this.body == other.body &&
|
|
||||||
this.order == other.order &&
|
this.order == other.order &&
|
||||||
this.checked == other.checked &&
|
this.checked == other.checked &&
|
||||||
this.isChild == other.isChild)
|
this.isChild == other.isChild)
|
||||||
|
|
|
@ -100,23 +100,26 @@ fun BaseNote.toJson(): String {
|
||||||
fun String.toBaseNote(): BaseNote {
|
fun String.toBaseNote(): BaseNote {
|
||||||
val jsonObject = JSONObject(this)
|
val jsonObject = JSONObject(this)
|
||||||
val id = jsonObject.getLongOrDefault("id", -1L)
|
val id = jsonObject.getLongOrDefault("id", -1L)
|
||||||
val type = Type.valueOfOrDefault(jsonObject.getStringOrDefault("type", Type.NOTE.name))
|
val type = Type.valueOfOrDefault(jsonObject.getStringOrDefault("type", Type.NOTE.name)!!)
|
||||||
val folder = Folder.valueOfOrDefault(jsonObject.getStringOrDefault("folder", Folder.NOTES.name))
|
val folder =
|
||||||
|
Folder.valueOfOrDefault(jsonObject.getStringOrDefault("folder", Folder.NOTES.name)!!)
|
||||||
val color =
|
val color =
|
||||||
jsonObject.getStringOrDefault("color", COLOR_DEFAULT).takeIf { it.isValid() }
|
jsonObject.getStringOrDefault("color", COLOR_DEFAULT)!!.takeIf { it.isValid() }
|
||||||
?: COLOR_DEFAULT
|
?: COLOR_DEFAULT
|
||||||
val title = jsonObject.getStringOrDefault("title", "")
|
val title = jsonObject.getStringOrDefault("title", "")!!
|
||||||
val pinned = jsonObject.getBooleanOrDefault("pinned", false)
|
val pinned = jsonObject.getBooleanOrDefault("pinned", false)
|
||||||
val timestamp = jsonObject.getLongOrDefault("timestamp", System.currentTimeMillis())
|
val timestamp = jsonObject.getLongOrDefault("timestamp", System.currentTimeMillis())
|
||||||
val modifiedTimestamp = jsonObject.getLongOrDefault("modifiedTimestamp", timestamp)
|
val modifiedTimestamp = jsonObject.getLongOrDefault("modifiedTimestamp", timestamp)
|
||||||
val labels = Converters.jsonToLabels(jsonObject.getArrayOrEmpty("labels"))
|
val labels = Converters.jsonToLabels(jsonObject.getArrayOrEmpty("labels"))
|
||||||
val body = jsonObject.getStringOrDefault("body", "")
|
val body = jsonObject.getStringOrDefault("body", "")!!
|
||||||
val spans = Converters.jsonToSpans(jsonObject.getArrayOrEmpty("spans"))
|
val spans = Converters.jsonToSpans(jsonObject.getArrayOrEmpty("spans"))
|
||||||
val items = Converters.jsonToItems(jsonObject.getArrayOrEmpty("items"))
|
val items = Converters.jsonToItems(jsonObject.getArrayOrEmpty("items"))
|
||||||
val images = Converters.jsonToFiles(jsonObject.getArrayOrEmpty("images"))
|
val images = Converters.jsonToFiles(jsonObject.getArrayOrEmpty("images"))
|
||||||
val files = Converters.jsonToFiles(jsonObject.getArrayOrEmpty("files"))
|
val files = Converters.jsonToFiles(jsonObject.getArrayOrEmpty("files"))
|
||||||
val audios = Converters.jsonToAudios(jsonObject.getArrayOrEmpty("audios"))
|
val audios = Converters.jsonToAudios(jsonObject.getArrayOrEmpty("audios"))
|
||||||
val reminders = Converters.jsonToReminders(jsonObject.getArrayOrEmpty("reminders"))
|
val reminders = Converters.jsonToReminders(jsonObject.getArrayOrEmpty("reminders"))
|
||||||
|
val viewMode =
|
||||||
|
jsonObject.getStringOrDefault("viewMode", null)?.let { NoteViewMode.valueOfOrDefault(it) }
|
||||||
return BaseNote(
|
return BaseNote(
|
||||||
id,
|
id,
|
||||||
type,
|
type,
|
||||||
|
@ -134,10 +137,11 @@ fun String.toBaseNote(): BaseNote {
|
||||||
files,
|
files,
|
||||||
audios,
|
audios,
|
||||||
reminders,
|
reminders,
|
||||||
|
viewMode,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun JSONObject.getStringOrDefault(key: String, defaultValue: String): String {
|
private fun JSONObject.getStringOrDefault(key: String, defaultValue: String?): String? {
|
||||||
return try {
|
return try {
|
||||||
getString(key)
|
getString(key)
|
||||||
} catch (exception: JSONException) {
|
} catch (exception: JSONException) {
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
package com.philkes.notallyx.data.model
|
||||||
|
|
||||||
|
import com.philkes.notallyx.R
|
||||||
|
import com.philkes.notallyx.presentation.viewmodel.preference.StaticTextProvider
|
||||||
|
|
||||||
|
enum class NoteViewMode(override val textResId: Int) : StaticTextProvider {
|
||||||
|
READ_ONLY(R.string.read_only),
|
||||||
|
EDIT(R.string.edit);
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun valueOfOrDefault(value: String) =
|
||||||
|
try {
|
||||||
|
NoteViewMode.valueOf(value)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,7 @@ import android.util.TypedValue
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.View.GONE
|
import android.view.View.GONE
|
||||||
|
import android.view.ViewGroup
|
||||||
import android.view.ViewGroup.LayoutParams
|
import android.view.ViewGroup.LayoutParams
|
||||||
import android.view.ViewGroup.VISIBLE
|
import android.view.ViewGroup.VISIBLE
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
|
@ -40,6 +41,7 @@ import com.philkes.notallyx.data.NotallyDatabase
|
||||||
import com.philkes.notallyx.data.model.Audio
|
import com.philkes.notallyx.data.model.Audio
|
||||||
import com.philkes.notallyx.data.model.FileAttachment
|
import com.philkes.notallyx.data.model.FileAttachment
|
||||||
import com.philkes.notallyx.data.model.Folder
|
import com.philkes.notallyx.data.model.Folder
|
||||||
|
import com.philkes.notallyx.data.model.NoteViewMode
|
||||||
import com.philkes.notallyx.data.model.Type
|
import com.philkes.notallyx.data.model.Type
|
||||||
import com.philkes.notallyx.data.model.isImageMimeType
|
import com.philkes.notallyx.data.model.isImageMimeType
|
||||||
import com.philkes.notallyx.databinding.ActivityEditBinding
|
import com.philkes.notallyx.databinding.ActivityEditBinding
|
||||||
|
@ -80,7 +82,6 @@ import com.philkes.notallyx.presentation.viewmodel.ExportMimeType
|
||||||
import com.philkes.notallyx.presentation.viewmodel.NotallyModel
|
import com.philkes.notallyx.presentation.viewmodel.NotallyModel
|
||||||
import com.philkes.notallyx.presentation.viewmodel.preference.DateFormat
|
import com.philkes.notallyx.presentation.viewmodel.preference.DateFormat
|
||||||
import com.philkes.notallyx.presentation.viewmodel.preference.ListItemSort
|
import com.philkes.notallyx.presentation.viewmodel.preference.ListItemSort
|
||||||
import com.philkes.notallyx.presentation.viewmodel.preference.NoteViewMode
|
|
||||||
import com.philkes.notallyx.presentation.viewmodel.preference.NotesSortBy
|
import com.philkes.notallyx.presentation.viewmodel.preference.NotesSortBy
|
||||||
import com.philkes.notallyx.presentation.widget.WidgetProvider
|
import com.philkes.notallyx.presentation.widget.WidgetProvider
|
||||||
import com.philkes.notallyx.utils.FileError
|
import com.philkes.notallyx.utils.FileError
|
||||||
|
@ -125,10 +126,9 @@ abstract class EditActivity(private val type: Type) :
|
||||||
protected var colorInt: Int = -1
|
protected var colorInt: Int = -1
|
||||||
protected var inputMethodManager: InputMethodManager? = null
|
protected var inputMethodManager: InputMethodManager? = null
|
||||||
|
|
||||||
protected var viewMode: NotNullLiveData<NoteViewMode>? = null
|
|
||||||
protected lateinit var toggleViewMode: ImageButton
|
protected lateinit var toggleViewMode: ImageButton
|
||||||
protected val canEdit
|
protected val canEdit
|
||||||
get() = viewMode?.value == NoteViewMode.EDIT
|
get() = notallyModel.viewMode.value == NoteViewMode.EDIT
|
||||||
|
|
||||||
private val autoSaveHandler = Handler(Looper.getMainLooper())
|
private val autoSaveHandler = Handler(Looper.getMainLooper())
|
||||||
private val autoSaveRunnable = Runnable {
|
private val autoSaveRunnable = Runnable {
|
||||||
|
@ -550,21 +550,13 @@ abstract class EditActivity(private val type: Type) :
|
||||||
binding.BottomAppBarRight.apply {
|
binding.BottomAppBarRight.apply {
|
||||||
removeAllViews()
|
removeAllViews()
|
||||||
|
|
||||||
toggleViewMode =
|
addToggleViewMode()
|
||||||
addIconButton(R.string.edit, R.drawable.visibility) {
|
notallyModel.viewMode.value =
|
||||||
viewMode!!.value =
|
when {
|
||||||
when (viewMode!!.value) {
|
notallyModel.isNewNote -> NoteViewMode.EDIT
|
||||||
NoteViewMode.EDIT -> NoteViewMode.READ_ONLY
|
notallyModel.viewMode.value != null -> notallyModel.viewMode.value!!
|
||||||
NoteViewMode.READ_ONLY -> NoteViewMode.EDIT
|
else -> preferences.defaultNoteViewMode.value
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (viewMode == null) {
|
|
||||||
viewMode =
|
|
||||||
NotNullLiveData(
|
|
||||||
if (notallyModel.isNewNote) NoteViewMode.EDIT
|
|
||||||
else preferences.defaultNoteViewMode.value
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
addIconButton(R.string.more, R.drawable.more_vert, marginStart = 0) {
|
addIconButton(R.string.more, R.drawable.more_vert, marginStart = 0) {
|
||||||
MoreNoteBottomSheet(
|
MoreNoteBottomSheet(
|
||||||
|
@ -578,6 +570,19 @@ abstract class EditActivity(private val type: Type) :
|
||||||
setBottomAppBarColor(colorInt)
|
setBottomAppBarColor(colorInt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected fun ViewGroup.addToggleViewMode() {
|
||||||
|
toggleViewMode =
|
||||||
|
addIconButton(R.string.edit, R.drawable.visibility) {
|
||||||
|
notallyModel.viewMode.value =
|
||||||
|
when (notallyModel.viewMode.value) {
|
||||||
|
NoteViewMode.EDIT -> NoteViewMode.READ_ONLY
|
||||||
|
NoteViewMode.READ_ONLY -> NoteViewMode.EDIT
|
||||||
|
null -> NoteViewMode.EDIT
|
||||||
|
}
|
||||||
|
notallyModel.viewModeChangedByUser = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected fun createFolderActions() =
|
protected fun createFolderActions() =
|
||||||
when (notallyModel.folder) {
|
when (notallyModel.folder) {
|
||||||
Folder.NOTES ->
|
Folder.NOTES ->
|
||||||
|
@ -658,14 +663,14 @@ abstract class EditActivity(private val type: Type) :
|
||||||
binding.EnterTitle.initHistory(changeHistory) { text ->
|
binding.EnterTitle.initHistory(changeHistory) { text ->
|
||||||
notallyModel.title = text.trim().toString()
|
notallyModel.title = text.trim().toString()
|
||||||
}
|
}
|
||||||
viewMode!!.observe(this) { value ->
|
notallyModel.viewMode.observe(this) { value ->
|
||||||
toggleViewMode.setImageResource(
|
toggleViewMode.setImageResource(
|
||||||
when (value) {
|
when (value) {
|
||||||
NoteViewMode.READ_ONLY -> R.drawable.edit
|
NoteViewMode.READ_ONLY -> R.drawable.edit
|
||||||
NoteViewMode.EDIT -> R.drawable.visibility
|
else -> R.drawable.visibility
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
toggleCanEdit(value)
|
value?.let { toggleCanEdit(it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.recyclerview.widget.SortedList
|
import androidx.recyclerview.widget.SortedList
|
||||||
import com.philkes.notallyx.R
|
import com.philkes.notallyx.R
|
||||||
import com.philkes.notallyx.data.model.ListItem
|
import com.philkes.notallyx.data.model.ListItem
|
||||||
|
import com.philkes.notallyx.data.model.NoteViewMode
|
||||||
import com.philkes.notallyx.data.model.Type
|
import com.philkes.notallyx.data.model.Type
|
||||||
import com.philkes.notallyx.presentation.addIconButton
|
import com.philkes.notallyx.presentation.addIconButton
|
||||||
import com.philkes.notallyx.presentation.hideKeyboardOnFocusedItem
|
import com.philkes.notallyx.presentation.hideKeyboardOnFocusedItem
|
||||||
|
@ -26,7 +27,6 @@ import com.philkes.notallyx.presentation.view.note.listitem.sorting.SortedItemsL
|
||||||
import com.philkes.notallyx.presentation.view.note.listitem.splitByChecked
|
import com.philkes.notallyx.presentation.view.note.listitem.splitByChecked
|
||||||
import com.philkes.notallyx.presentation.view.note.listitem.toMutableList
|
import com.philkes.notallyx.presentation.view.note.listitem.toMutableList
|
||||||
import com.philkes.notallyx.presentation.viewmodel.preference.NotallyXPreferences
|
import com.philkes.notallyx.presentation.viewmodel.preference.NotallyXPreferences
|
||||||
import com.philkes.notallyx.presentation.viewmodel.preference.NoteViewMode
|
|
||||||
import com.philkes.notallyx.presentation.viewmodel.preference.autoSortByCheckedEnabled
|
import com.philkes.notallyx.presentation.viewmodel.preference.autoSortByCheckedEnabled
|
||||||
import com.philkes.notallyx.utils.findAllOccurrences
|
import com.philkes.notallyx.utils.findAllOccurrences
|
||||||
import com.philkes.notallyx.utils.indices
|
import com.philkes.notallyx.utils.indices
|
||||||
|
@ -104,14 +104,7 @@ class EditListActivity : EditActivity(Type.LIST), MoreListActions {
|
||||||
super.initBottomMenu()
|
super.initBottomMenu()
|
||||||
binding.BottomAppBarRight.apply {
|
binding.BottomAppBarRight.apply {
|
||||||
removeAllViews()
|
removeAllViews()
|
||||||
toggleViewMode =
|
addToggleViewMode()
|
||||||
addIconButton(R.string.edit, R.drawable.visibility) {
|
|
||||||
viewMode!!.value =
|
|
||||||
when (viewMode!!.value) {
|
|
||||||
NoteViewMode.EDIT -> NoteViewMode.READ_ONLY
|
|
||||||
NoteViewMode.READ_ONLY -> NoteViewMode.EDIT
|
|
||||||
}
|
|
||||||
}
|
|
||||||
addIconButton(R.string.more, R.drawable.more_vert, marginStart = 0) {
|
addIconButton(R.string.more, R.drawable.more_vert, marginStart = 0) {
|
||||||
MoreListBottomSheet(
|
MoreListBottomSheet(
|
||||||
this@EditListActivity,
|
this@EditListActivity,
|
||||||
|
|
|
@ -26,6 +26,7 @@ import androidx.core.view.updateLayoutParams
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.philkes.notallyx.R
|
import com.philkes.notallyx.R
|
||||||
|
import com.philkes.notallyx.data.model.NoteViewMode
|
||||||
import com.philkes.notallyx.data.model.Type
|
import com.philkes.notallyx.data.model.Type
|
||||||
import com.philkes.notallyx.data.model.createNoteUrl
|
import com.philkes.notallyx.data.model.createNoteUrl
|
||||||
import com.philkes.notallyx.data.model.getNoteIdFromUrl
|
import com.philkes.notallyx.data.model.getNoteIdFromUrl
|
||||||
|
@ -48,7 +49,6 @@ import com.philkes.notallyx.presentation.showToast
|
||||||
import com.philkes.notallyx.presentation.view.note.TextFormattingAdapter
|
import com.philkes.notallyx.presentation.view.note.TextFormattingAdapter
|
||||||
import com.philkes.notallyx.presentation.view.note.action.AddNoteActions
|
import com.philkes.notallyx.presentation.view.note.action.AddNoteActions
|
||||||
import com.philkes.notallyx.presentation.view.note.action.AddNoteBottomSheet
|
import com.philkes.notallyx.presentation.view.note.action.AddNoteBottomSheet
|
||||||
import com.philkes.notallyx.presentation.viewmodel.preference.NoteViewMode
|
|
||||||
import com.philkes.notallyx.utils.LinkMovementMethod
|
import com.philkes.notallyx.utils.LinkMovementMethod
|
||||||
import com.philkes.notallyx.utils.copyToClipBoard
|
import com.philkes.notallyx.utils.copyToClipBoard
|
||||||
import com.philkes.notallyx.utils.findAllOccurrences
|
import com.philkes.notallyx.utils.findAllOccurrences
|
||||||
|
|
|
@ -6,10 +6,10 @@ import androidx.core.widget.NestedScrollView
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.recyclerview.widget.SortedList
|
import androidx.recyclerview.widget.SortedList
|
||||||
import com.philkes.notallyx.data.model.ListItem
|
import com.philkes.notallyx.data.model.ListItem
|
||||||
|
import com.philkes.notallyx.data.model.NoteViewMode
|
||||||
import com.philkes.notallyx.presentation.view.note.listitem.HighlightText
|
import com.philkes.notallyx.presentation.view.note.listitem.HighlightText
|
||||||
import com.philkes.notallyx.presentation.view.note.listitem.ListManager
|
import com.philkes.notallyx.presentation.view.note.listitem.ListManager
|
||||||
import com.philkes.notallyx.presentation.viewmodel.preference.NotallyXPreferences
|
import com.philkes.notallyx.presentation.viewmodel.preference.NotallyXPreferences
|
||||||
import com.philkes.notallyx.presentation.viewmodel.preference.NoteViewMode
|
|
||||||
import com.philkes.notallyx.presentation.viewmodel.preference.TextSize
|
import com.philkes.notallyx.presentation.viewmodel.preference.TextSize
|
||||||
|
|
||||||
class CheckedListItemAdapter(
|
class CheckedListItemAdapter(
|
||||||
|
|
|
@ -7,10 +7,10 @@ import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.ListAdapter
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.philkes.notallyx.data.model.ListItem
|
import com.philkes.notallyx.data.model.ListItem
|
||||||
|
import com.philkes.notallyx.data.model.NoteViewMode
|
||||||
import com.philkes.notallyx.presentation.view.note.listitem.HighlightText
|
import com.philkes.notallyx.presentation.view.note.listitem.HighlightText
|
||||||
import com.philkes.notallyx.presentation.view.note.listitem.ListManager
|
import com.philkes.notallyx.presentation.view.note.listitem.ListManager
|
||||||
import com.philkes.notallyx.presentation.viewmodel.preference.NotallyXPreferences
|
import com.philkes.notallyx.presentation.viewmodel.preference.NotallyXPreferences
|
||||||
import com.philkes.notallyx.presentation.viewmodel.preference.NoteViewMode
|
|
||||||
import com.philkes.notallyx.presentation.viewmodel.preference.TextSize
|
import com.philkes.notallyx.presentation.viewmodel.preference.TextSize
|
||||||
|
|
||||||
class ListItemAdapter(
|
class ListItemAdapter(
|
||||||
|
|
|
@ -7,11 +7,11 @@ import androidx.core.widget.NestedScrollView
|
||||||
import androidx.recyclerview.widget.NestedScrollViewItemTouchHelper
|
import androidx.recyclerview.widget.NestedScrollViewItemTouchHelper
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.philkes.notallyx.data.model.ListItem
|
import com.philkes.notallyx.data.model.ListItem
|
||||||
|
import com.philkes.notallyx.data.model.NoteViewMode
|
||||||
import com.philkes.notallyx.databinding.RecyclerListItemBinding
|
import com.philkes.notallyx.databinding.RecyclerListItemBinding
|
||||||
import com.philkes.notallyx.presentation.view.note.listitem.ListItemDragCallback
|
import com.philkes.notallyx.presentation.view.note.listitem.ListItemDragCallback
|
||||||
import com.philkes.notallyx.presentation.view.note.listitem.ListManager
|
import com.philkes.notallyx.presentation.view.note.listitem.ListManager
|
||||||
import com.philkes.notallyx.presentation.viewmodel.preference.NotallyXPreferences
|
import com.philkes.notallyx.presentation.viewmodel.preference.NotallyXPreferences
|
||||||
import com.philkes.notallyx.presentation.viewmodel.preference.NoteViewMode
|
|
||||||
import com.philkes.notallyx.presentation.viewmodel.preference.TextSize
|
import com.philkes.notallyx.presentation.viewmodel.preference.TextSize
|
||||||
|
|
||||||
data class ListItemHighlight(
|
data class ListItemHighlight(
|
||||||
|
|
|
@ -21,6 +21,7 @@ import cn.leaqi.drawer.SwipeDrawer.STATE_OPEN
|
||||||
import com.philkes.notallyx.data.imports.txt.extractListItems
|
import com.philkes.notallyx.data.imports.txt.extractListItems
|
||||||
import com.philkes.notallyx.data.imports.txt.findListSyntaxRegex
|
import com.philkes.notallyx.data.imports.txt.findListSyntaxRegex
|
||||||
import com.philkes.notallyx.data.model.ListItem
|
import com.philkes.notallyx.data.model.ListItem
|
||||||
|
import com.philkes.notallyx.data.model.NoteViewMode
|
||||||
import com.philkes.notallyx.databinding.RecyclerListItemBinding
|
import com.philkes.notallyx.databinding.RecyclerListItemBinding
|
||||||
import com.philkes.notallyx.presentation.clone
|
import com.philkes.notallyx.presentation.clone
|
||||||
import com.philkes.notallyx.presentation.createListTextWatcherWithHistory
|
import com.philkes.notallyx.presentation.createListTextWatcherWithHistory
|
||||||
|
@ -30,7 +31,6 @@ import com.philkes.notallyx.presentation.view.misc.EditTextAutoClearFocus
|
||||||
import com.philkes.notallyx.presentation.view.note.listitem.ListManager
|
import com.philkes.notallyx.presentation.view.note.listitem.ListManager
|
||||||
import com.philkes.notallyx.presentation.view.note.listitem.firstBodyOrEmptyString
|
import com.philkes.notallyx.presentation.view.note.listitem.firstBodyOrEmptyString
|
||||||
import com.philkes.notallyx.presentation.viewmodel.preference.ListItemSort
|
import com.philkes.notallyx.presentation.viewmodel.preference.ListItemSort
|
||||||
import com.philkes.notallyx.presentation.viewmodel.preference.NoteViewMode
|
|
||||||
import com.philkes.notallyx.presentation.viewmodel.preference.TextSize
|
import com.philkes.notallyx.presentation.viewmodel.preference.TextSize
|
||||||
import com.philkes.notallyx.utils.changehistory.EditTextState
|
import com.philkes.notallyx.utils.changehistory.EditTextState
|
||||||
import com.philkes.notallyx.utils.copyToClipBoard
|
import com.philkes.notallyx.utils.copyToClipBoard
|
||||||
|
|
|
@ -26,6 +26,7 @@ import com.philkes.notallyx.data.model.BaseNote
|
||||||
import com.philkes.notallyx.data.model.FileAttachment
|
import com.philkes.notallyx.data.model.FileAttachment
|
||||||
import com.philkes.notallyx.data.model.Folder
|
import com.philkes.notallyx.data.model.Folder
|
||||||
import com.philkes.notallyx.data.model.ListItem
|
import com.philkes.notallyx.data.model.ListItem
|
||||||
|
import com.philkes.notallyx.data.model.NoteViewMode
|
||||||
import com.philkes.notallyx.data.model.Reminder
|
import com.philkes.notallyx.data.model.Reminder
|
||||||
import com.philkes.notallyx.data.model.SpanRepresentation
|
import com.philkes.notallyx.data.model.SpanRepresentation
|
||||||
import com.philkes.notallyx.data.model.Type
|
import com.philkes.notallyx.data.model.Type
|
||||||
|
@ -86,10 +87,14 @@ class NotallyModel(private val app: Application) : AndroidViewModel(app) {
|
||||||
var body: Editable = SpannableStringBuilder()
|
var body: Editable = SpannableStringBuilder()
|
||||||
|
|
||||||
val items = ArrayList<ListItem>()
|
val items = ArrayList<ListItem>()
|
||||||
|
|
||||||
val images = NotNullLiveData<List<FileAttachment>>(emptyList())
|
val images = NotNullLiveData<List<FileAttachment>>(emptyList())
|
||||||
val files = NotNullLiveData<List<FileAttachment>>(emptyList())
|
val files = NotNullLiveData<List<FileAttachment>>(emptyList())
|
||||||
val audios = NotNullLiveData<List<Audio>>(emptyList())
|
val audios = NotNullLiveData<List<Audio>>(emptyList())
|
||||||
|
|
||||||
val reminders = NotNullLiveData<List<Reminder>>(emptyList())
|
val reminders = NotNullLiveData<List<Reminder>>(emptyList())
|
||||||
|
val viewMode = MutableLiveData<NoteViewMode?>(null)
|
||||||
|
var viewModeChangedByUser = false
|
||||||
|
|
||||||
val addingFiles = MutableLiveData<Progress>()
|
val addingFiles = MutableLiveData<Progress>()
|
||||||
val eventBus = MutableLiveData<Event<List<FileError>>>()
|
val eventBus = MutableLiveData<Event<List<FileError>>>()
|
||||||
|
@ -248,6 +253,8 @@ class NotallyModel(private val app: Application) : AndroidViewModel(app) {
|
||||||
files.value = baseNote.files
|
files.value = baseNote.files
|
||||||
audios.value = baseNote.audios
|
audios.value = baseNote.audios
|
||||||
reminders.value = baseNote.reminders
|
reminders.value = baseNote.reminders
|
||||||
|
viewMode.value = baseNote.viewMode
|
||||||
|
viewModeChangedByUser = false
|
||||||
} else {
|
} else {
|
||||||
originalNote = createBaseNote()
|
originalNote = createBaseNote()
|
||||||
app.showToast(R.string.cant_find_note)
|
app.showToast(R.string.cant_find_note)
|
||||||
|
@ -328,6 +335,12 @@ class NotallyModel(private val app: Application) : AndroidViewModel(app) {
|
||||||
val spans = getFilteredSpans(body)
|
val spans = getFilteredSpans(body)
|
||||||
val body = this.body.toString()
|
val body = this.body.toString()
|
||||||
val nonEmptyItems = this.items.filter { item -> item.body.isNotEmpty() }
|
val nonEmptyItems = this.items.filter { item -> item.body.isNotEmpty() }
|
||||||
|
val viewMode =
|
||||||
|
if (isNewNote) {
|
||||||
|
null
|
||||||
|
} else if (viewModeChangedByUser) {
|
||||||
|
viewMode.value
|
||||||
|
} else originalNote?.viewMode
|
||||||
return BaseNote(
|
return BaseNote(
|
||||||
id,
|
id,
|
||||||
type,
|
type,
|
||||||
|
@ -345,6 +358,7 @@ class NotallyModel(private val app: Application) : AndroidViewModel(app) {
|
||||||
files.value,
|
files.value,
|
||||||
audios.value,
|
audios.value,
|
||||||
reminders.value,
|
reminders.value,
|
||||||
|
viewMode,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import androidx.preference.PreferenceManager
|
||||||
import androidx.security.crypto.EncryptedSharedPreferences
|
import androidx.security.crypto.EncryptedSharedPreferences
|
||||||
import androidx.security.crypto.MasterKey
|
import androidx.security.crypto.MasterKey
|
||||||
import com.philkes.notallyx.R
|
import com.philkes.notallyx.R
|
||||||
|
import com.philkes.notallyx.data.model.NoteViewMode
|
||||||
import com.philkes.notallyx.data.model.Type
|
import com.philkes.notallyx.data.model.Type
|
||||||
import com.philkes.notallyx.presentation.viewmodel.preference.Constants.PASSWORD_EMPTY
|
import com.philkes.notallyx.presentation.viewmodel.preference.Constants.PASSWORD_EMPTY
|
||||||
import com.philkes.notallyx.utils.backup.importPreferences
|
import com.philkes.notallyx.utils.backup.importPreferences
|
||||||
|
|
|
@ -366,11 +366,6 @@ enum class BiometricLock(override val textResId: Int) : StaticTextProvider {
|
||||||
DISABLED(R.string.disabled),
|
DISABLED(R.string.disabled),
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class NoteViewMode(override val textResId: Int) : StaticTextProvider {
|
|
||||||
READ_ONLY(R.string.read_only),
|
|
||||||
EDIT(R.string.edit),
|
|
||||||
}
|
|
||||||
|
|
||||||
object Constants {
|
object Constants {
|
||||||
const val PASSWORD_EMPTY = "None"
|
const val PASSWORD_EMPTY = "None"
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import com.philkes.notallyx.data.model.Converters
|
||||||
import com.philkes.notallyx.data.model.FileAttachment
|
import com.philkes.notallyx.data.model.FileAttachment
|
||||||
import com.philkes.notallyx.data.model.Folder
|
import com.philkes.notallyx.data.model.Folder
|
||||||
import com.philkes.notallyx.data.model.Label
|
import com.philkes.notallyx.data.model.Label
|
||||||
|
import com.philkes.notallyx.data.model.NoteViewMode
|
||||||
import com.philkes.notallyx.data.model.Type
|
import com.philkes.notallyx.data.model.Type
|
||||||
import com.philkes.notallyx.data.model.parseToColorString
|
import com.philkes.notallyx.data.model.parseToColorString
|
||||||
import com.philkes.notallyx.presentation.getQuantityString
|
import com.philkes.notallyx.presentation.getQuantityString
|
||||||
|
@ -280,6 +281,11 @@ private fun Cursor.toBaseNote(): BaseNote {
|
||||||
Converters.jsonToReminders(getString(remindersIndex))
|
Converters.jsonToReminders(getString(remindersIndex))
|
||||||
} else emptyList()
|
} else emptyList()
|
||||||
|
|
||||||
|
val viewModeIndex = getColumnIndex("viewMode")
|
||||||
|
val viewMode =
|
||||||
|
if (viewModeIndex != -1) {
|
||||||
|
NoteViewMode.valueOfOrDefault(getString(viewModeIndex))
|
||||||
|
} else null
|
||||||
return BaseNote(
|
return BaseNote(
|
||||||
0,
|
0,
|
||||||
type,
|
type,
|
||||||
|
@ -297,6 +303,7 @@ private fun Cursor.toBaseNote(): BaseNote {
|
||||||
files,
|
files,
|
||||||
audios,
|
audios,
|
||||||
reminders,
|
reminders,
|
||||||
|
viewMode,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,6 +113,7 @@ private fun XmlPullParser.parseBaseNote(rootTag: String, folder: Folder): BaseNo
|
||||||
emptyList(),
|
emptyList(),
|
||||||
emptyList(),
|
emptyList(),
|
||||||
emptyList(),
|
emptyList(),
|
||||||
|
null,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -252,6 +252,7 @@ class GoogleKeepImporterTest {
|
||||||
files,
|
files,
|
||||||
audios,
|
audios,
|
||||||
reminders,
|
reminders,
|
||||||
|
null,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@ package com.philkes.notallyx.data.model
|
||||||
|
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
import org.mockito.Mockito.anyString
|
||||||
|
import org.mockito.Mockito.mockStatic
|
||||||
|
|
||||||
class ModelExtensionsTest {
|
class ModelExtensionsTest {
|
||||||
|
|
||||||
|
@ -59,6 +61,8 @@ class ModelExtensionsTest {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
val colorMock = mockStatic(android.graphics.Color::class.java)
|
||||||
|
colorMock.`when`<Int> { android.graphics.Color.parseColor(anyString()) }.thenReturn(1)
|
||||||
|
|
||||||
val baseNote = json.toBaseNote()
|
val baseNote = json.toBaseNote()
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue