Merge pull request #503 from PhilKes/feat/persist-note-viewmode

Persist viewMode for each note individually
This commit is contained in:
Phil 2025-03-29 14:10:16 +01:00 committed by GitHub
commit 54d835e40b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 339 additions and 69 deletions

View file

@ -0,0 +1,164 @@
{
"formatVersion": 1,
"database": {
"version": 9,
"identityHash": "042b20b5b4cfc8415e6cf6348196e869",
"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 NOT NULL)",
"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": true
}
],
"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, '042b20b5b4cfc8415e6cf6348196e869')"
]
}
}

View file

@ -19,6 +19,7 @@ import com.philkes.notallyx.data.model.BaseNote
import com.philkes.notallyx.data.model.Color
import com.philkes.notallyx.data.model.Converters
import com.philkes.notallyx.data.model.Label
import com.philkes.notallyx.data.model.NoteViewMode
import com.philkes.notallyx.data.model.toColorString
import com.philkes.notallyx.presentation.view.misc.NotNullLiveData
import com.philkes.notallyx.presentation.viewmodel.preference.BiometricLock
@ -32,7 +33,7 @@ import net.sqlcipher.database.SQLiteDatabase
import net.sqlcipher.database.SupportFactory
@TypeConverters(Converters::class)
@Database(entities = [BaseNote::class, Label::class], version = 8)
@Database(entities = [BaseNote::class, Label::class], version = 9)
abstract class NotallyDatabase : RoomDatabase() {
abstract fun getLabelDao(): LabelDao
@ -131,6 +132,7 @@ abstract class NotallyDatabase : RoomDatabase() {
Migration6,
Migration7,
Migration8,
Migration9,
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
SQLiteDatabase.loadLibs(context)
@ -261,5 +263,14 @@ abstract class NotallyDatabase : RoomDatabase() {
cursor.close()
}
}
object Migration9 : Migration(8, 9) {
override fun migrate(db: SupportSQLiteDatabase) {
db.execSQL(
"ALTER TABLE `BaseNote` ADD COLUMN `viewMode` TEXT DEFAULT '${NoteViewMode.EDIT.name}'"
)
}
}
}
}

View file

@ -17,6 +17,7 @@ import com.philkes.notallyx.data.model.BaseNote
import com.philkes.notallyx.data.model.FileAttachment
import com.philkes.notallyx.data.model.Folder
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.utils.log
import com.philkes.notallyx.utils.startsWithAnyOf
@ -155,6 +156,7 @@ fun EvernoteNote.mapToBaseNote(): BaseNote {
files = files,
audios = audios,
reminders = mutableListOf(),
NoteViewMode.EDIT,
)
}

View file

@ -14,6 +14,7 @@ import com.philkes.notallyx.data.model.BaseNote
import com.philkes.notallyx.data.model.FileAttachment
import com.philkes.notallyx.data.model.Folder
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.utils.listFilesRecursive
import com.philkes.notallyx.utils.log
@ -162,6 +163,7 @@ class GoogleKeepImporter : ExternalImporter {
files = files,
audios = audios,
reminders = mutableListOf(),
NoteViewMode.EDIT,
)
}

View file

@ -9,6 +9,7 @@ import com.philkes.notallyx.data.imports.ImportProgress
import com.philkes.notallyx.data.model.BaseNote
import com.philkes.notallyx.data.model.Folder
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.utils.MIME_TYPE_JSON
import com.philkes.notallyx.utils.readFileContents
@ -59,6 +60,7 @@ class PlainTextImporter : ExternalImporter {
files = listOf(),
audios = listOf(),
reminders = listOf(),
NoteViewMode.EDIT,
)
)
}

View file

@ -25,6 +25,7 @@ data class BaseNote(
val files: List<FileAttachment>,
val audios: List<Audio>,
val reminders: List<Reminder>,
val viewMode: NoteViewMode,
) : Item {
companion object {
@ -53,6 +54,7 @@ data class BaseNote(
if (files != other.files) return false
if (audios != other.audios) return false
if (reminders != other.reminders) return false
if (viewMode != other.viewMode) return false
return true
}
@ -73,6 +75,7 @@ data class BaseNote(
result = 31 * result + files.hashCode()
result = 31 * result + audios.hashCode()
result = 31 * result + reminders.hashCode()
result = 31 * result + viewMode.hashCode()
return result
}
}

View file

@ -146,7 +146,7 @@ object Converters {
JSONObject().apply {
put("id", reminder.id) // Store date as long timestamp
put("dateTime", reminder.dateTime.time) // Store date as long timestamp
put("repetition", reminder.repetition?.let { repetitionToJson(it) })
put("repetition", reminder.repetition?.let { repetitionToJsonObject(it) })
}
}
return JSONArray(objects)
@ -165,10 +165,14 @@ object Converters {
@TypeConverter
fun repetitionToJson(repetition: Repetition): String {
return repetitionToJsonObject(repetition).toString()
}
fun repetitionToJsonObject(repetition: Repetition): JSONObject {
val jsonObject = JSONObject()
jsonObject.put("value", repetition.value)
jsonObject.put("unit", repetition.unit.name) // Store the TimeUnit as a string
return jsonObject.toString()
return jsonObject
}
@TypeConverter

View file

@ -34,8 +34,7 @@ data class ListItem(
if (other !is ListItem) {
return false
}
return (this.id == other.id &&
this.body == other.body &&
return (this.body == other.body &&
this.order == other.order &&
this.checked == other.checked &&
this.isChild == other.isChild)

View file

@ -80,7 +80,8 @@ fun BaseNote.toJson(): String {
.put("color", color)
.put("title", title)
.put("pinned", pinned)
.put("date-created", timestamp)
.put("timestamp", timestamp)
.put("modifiedTimestamp", modifiedTimestamp)
.put("labels", JSONArray(labels))
when (type) {
@ -94,6 +95,7 @@ fun BaseNote.toJson(): String {
}
}
jsonObject.put("reminders", Converters.remindersToJSONArray(reminders))
jsonObject.put("viewMode", viewMode.name)
return jsonObject.toString(2)
}
@ -117,6 +119,7 @@ fun String.toBaseNote(): BaseNote {
val files = Converters.jsonToFiles(jsonObject.getArrayOrEmpty("files"))
val audios = Converters.jsonToAudios(jsonObject.getArrayOrEmpty("audios"))
val reminders = Converters.jsonToReminders(jsonObject.getArrayOrEmpty("reminders"))
val viewMode = NoteViewMode.valueOfOrDefault(jsonObject.getStringOrDefault("viewMode", ""))
return BaseNote(
id,
type,
@ -134,6 +137,7 @@ fun String.toBaseNote(): BaseNote {
files,
audios,
reminders,
viewMode,
)
}

View file

@ -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) {
EDIT
}
}
}

View file

@ -647,13 +647,6 @@ class SettingsFragment : Fragment() {
model.savePreference(autoSaveAfterIdleTime, newValue)
}
defaultNoteViewMode.observe(viewLifecycleOwner) { value ->
DefaultNoteViewMode.setup(defaultNoteViewMode, value, requireContext()) { newValue
->
model.savePreference(defaultNoteViewMode, newValue)
}
}
ClearData.setOnClickListener {
MaterialAlertDialogBuilder(requireContext())
.setMessage(R.string.clear_data_message)

View file

@ -17,6 +17,7 @@ import android.util.TypedValue
import android.view.MenuItem
import android.view.View
import android.view.View.GONE
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams
import android.view.ViewGroup.VISIBLE
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.FileAttachment
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.isImageMimeType
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.preference.DateFormat
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.widget.WidgetProvider
import com.philkes.notallyx.utils.FileError
@ -125,10 +126,9 @@ abstract class EditActivity(private val type: Type) :
protected var colorInt: Int = -1
protected var inputMethodManager: InputMethodManager? = null
protected var viewMode: NotNullLiveData<NoteViewMode>? = null
protected lateinit var toggleViewMode: ImageButton
protected val canEdit
get() = viewMode?.value == NoteViewMode.EDIT
get() = notallyModel.viewMode.value == NoteViewMode.EDIT
private val autoSaveHandler = Handler(Looper.getMainLooper())
private val autoSaveRunnable = Runnable {
@ -550,22 +550,7 @@ abstract class EditActivity(private val type: Type) :
binding.BottomAppBarRight.apply {
removeAllViews()
toggleViewMode =
addIconButton(R.string.edit, R.drawable.visibility) {
viewMode!!.value =
when (viewMode!!.value) {
NoteViewMode.EDIT -> NoteViewMode.READ_ONLY
NoteViewMode.READ_ONLY -> NoteViewMode.EDIT
}
}
if (viewMode == null) {
viewMode =
NotNullLiveData(
if (notallyModel.isNewNote) NoteViewMode.EDIT
else preferences.defaultNoteViewMode.value
)
}
addToggleViewMode()
addIconButton(R.string.more, R.drawable.more_vert, marginStart = 0) {
MoreNoteBottomSheet(
this@EditActivity,
@ -578,6 +563,17 @@ abstract class EditActivity(private val type: Type) :
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
}
}
}
protected fun createFolderActions() =
when (notallyModel.folder) {
Folder.NOTES ->
@ -658,14 +654,14 @@ abstract class EditActivity(private val type: Type) :
binding.EnterTitle.initHistory(changeHistory) { text ->
notallyModel.title = text.trim().toString()
}
viewMode!!.observe(this) { value ->
notallyModel.viewMode.observe(this) { value ->
toggleViewMode.setImageResource(
when (value) {
NoteViewMode.READ_ONLY -> R.drawable.edit
NoteViewMode.EDIT -> R.drawable.visibility
else -> R.drawable.visibility
}
)
toggleCanEdit(value)
value?.let { toggleCanEdit(it) }
}
}

View file

@ -6,6 +6,7 @@ import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.SortedList
import com.philkes.notallyx.R
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.presentation.addIconButton
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.toMutableList
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.utils.findAllOccurrences
import com.philkes.notallyx.utils.indices
@ -104,14 +104,7 @@ class EditListActivity : EditActivity(Type.LIST), MoreListActions {
super.initBottomMenu()
binding.BottomAppBarRight.apply {
removeAllViews()
toggleViewMode =
addIconButton(R.string.edit, R.drawable.visibility) {
viewMode!!.value =
when (viewMode!!.value) {
NoteViewMode.EDIT -> NoteViewMode.READ_ONLY
NoteViewMode.READ_ONLY -> NoteViewMode.EDIT
}
}
addToggleViewMode()
addIconButton(R.string.more, R.drawable.more_vert, marginStart = 0) {
MoreListBottomSheet(
this@EditListActivity,

View file

@ -26,6 +26,7 @@ import androidx.core.view.updateLayoutParams
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.dialog.MaterialAlertDialogBuilder
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.createNoteUrl
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.action.AddNoteActions
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.copyToClipBoard
import com.philkes.notallyx.utils.findAllOccurrences

View file

@ -6,10 +6,10 @@ import androidx.core.widget.NestedScrollView
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.SortedList
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.ListManager
import com.philkes.notallyx.presentation.viewmodel.preference.NotallyXPreferences
import com.philkes.notallyx.presentation.viewmodel.preference.NoteViewMode
import com.philkes.notallyx.presentation.viewmodel.preference.TextSize
class CheckedListItemAdapter(

View file

@ -7,10 +7,10 @@ import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
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.ListManager
import com.philkes.notallyx.presentation.viewmodel.preference.NotallyXPreferences
import com.philkes.notallyx.presentation.viewmodel.preference.NoteViewMode
import com.philkes.notallyx.presentation.viewmodel.preference.TextSize
class ListItemAdapter(

View file

@ -7,11 +7,11 @@ import androidx.core.widget.NestedScrollView
import androidx.recyclerview.widget.NestedScrollViewItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
import com.philkes.notallyx.data.model.ListItem
import com.philkes.notallyx.data.model.NoteViewMode
import com.philkes.notallyx.databinding.RecyclerListItemBinding
import com.philkes.notallyx.presentation.view.note.listitem.ListItemDragCallback
import com.philkes.notallyx.presentation.view.note.listitem.ListManager
import com.philkes.notallyx.presentation.viewmodel.preference.NotallyXPreferences
import com.philkes.notallyx.presentation.viewmodel.preference.NoteViewMode
import com.philkes.notallyx.presentation.viewmodel.preference.TextSize
data class ListItemHighlight(

View file

@ -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.findListSyntaxRegex
import com.philkes.notallyx.data.model.ListItem
import com.philkes.notallyx.data.model.NoteViewMode
import com.philkes.notallyx.databinding.RecyclerListItemBinding
import com.philkes.notallyx.presentation.clone
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.firstBodyOrEmptyString
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.utils.changehistory.EditTextState
import com.philkes.notallyx.utils.copyToClipBoard

View file

@ -26,6 +26,7 @@ import com.philkes.notallyx.data.model.BaseNote
import com.philkes.notallyx.data.model.FileAttachment
import com.philkes.notallyx.data.model.Folder
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.SpanRepresentation
import com.philkes.notallyx.data.model.Type
@ -86,10 +87,13 @@ class NotallyModel(private val app: Application) : AndroidViewModel(app) {
var body: Editable = SpannableStringBuilder()
val items = ArrayList<ListItem>()
val images = NotNullLiveData<List<FileAttachment>>(emptyList())
val files = NotNullLiveData<List<FileAttachment>>(emptyList())
val audios = NotNullLiveData<List<Audio>>(emptyList())
val reminders = NotNullLiveData<List<Reminder>>(emptyList())
val viewMode = NotNullLiveData(NoteViewMode.EDIT)
val addingFiles = MutableLiveData<Progress>()
val eventBus = MutableLiveData<Event<List<FileError>>>()
@ -248,6 +252,7 @@ class NotallyModel(private val app: Application) : AndroidViewModel(app) {
files.value = baseNote.files
audios.value = baseNote.audios
reminders.value = baseNote.reminders
viewMode.value = baseNote.viewMode
} else {
originalNote = createBaseNote()
app.showToast(R.string.cant_find_note)
@ -345,6 +350,7 @@ class NotallyModel(private val app: Application) : AndroidViewModel(app) {
files.value,
audios.value,
reminders.value,
viewMode.value,
)
}

View file

@ -76,13 +76,6 @@ class NotallyXPreferences private constructor(private val context: Context) {
10,
R.string.max_lines_to_display_title,
)
val defaultNoteViewMode =
createEnumPreference(
preferences,
"defaultNoteViewMode",
NoteViewMode.EDIT,
R.string.default_note_view_mode,
)
val labelsHidden = StringSetPreference("labelsHiddenInNavigation", preferences, setOf())
val labelTagsHiddenInOverview =
BooleanPreference(
@ -237,7 +230,6 @@ class NotallyXPreferences private constructor(private val context: Context) {
backupPassword,
backupOnSave,
autoSaveAfterIdleTime,
defaultNoteViewMode,
)
.forEach { it.refresh() }
}

View file

@ -366,11 +366,6 @@ enum class BiometricLock(override val textResId: Int) : StaticTextProvider {
DISABLED(R.string.disabled),
}
enum class NoteViewMode(override val textResId: Int) : StaticTextProvider {
READ_ONLY(R.string.read_only),
EDIT(R.string.edit),
}
object Constants {
const val PASSWORD_EMPTY = "None"
}

View file

@ -22,6 +22,7 @@ import com.philkes.notallyx.data.model.Converters
import com.philkes.notallyx.data.model.FileAttachment
import com.philkes.notallyx.data.model.Folder
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.parseToColorString
import com.philkes.notallyx.presentation.getQuantityString
@ -280,6 +281,11 @@ private fun Cursor.toBaseNote(): BaseNote {
Converters.jsonToReminders(getString(remindersIndex))
} else emptyList()
val viewModeIndex = getColumnIndex("viewMode")
val viewMode =
if (viewModeIndex != -1) {
NoteViewMode.valueOfOrDefault(getString(viewModeIndex))
} else NoteViewMode.EDIT
return BaseNote(
0,
type,
@ -297,6 +303,7 @@ private fun Cursor.toBaseNote(): BaseNote {
files,
audios,
reminders,
viewMode,
)
}

View file

@ -4,6 +4,7 @@ import com.philkes.notallyx.data.model.BaseNote
import com.philkes.notallyx.data.model.Folder
import com.philkes.notallyx.data.model.Label
import com.philkes.notallyx.data.model.ListItem
import com.philkes.notallyx.data.model.NoteViewMode
import com.philkes.notallyx.data.model.SpanRepresentation
import com.philkes.notallyx.data.model.Type
import com.philkes.notallyx.data.model.parseToColorString
@ -113,6 +114,7 @@ private fun XmlPullParser.parseBaseNote(rootTag: String, folder: Folder): BaseNo
emptyList(),
emptyList(),
emptyList(),
NoteViewMode.EDIT,
)
}

View file

@ -53,10 +53,6 @@
android:id="@+id/StartView"
layout="@layout/preference" />
<include
android:id="@+id/DefaultNoteViewMode"
layout="@layout/preference" />
<include
android:id="@+id/AutoSaveAfterIdle"
layout="@layout/preference_seekbar" />

View file

@ -5,6 +5,7 @@ import com.philkes.notallyx.data.model.BaseNote
import com.philkes.notallyx.data.model.FileAttachment
import com.philkes.notallyx.data.model.Folder
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.SpanRepresentation
import com.philkes.notallyx.data.model.Type
@ -252,6 +253,7 @@ class GoogleKeepImporterTest {
files,
audios,
reminders,
NoteViewMode.EDIT,
)
}
}

View file

@ -1,7 +1,11 @@
package com.philkes.notallyx.data.model
import com.philkes.notallyx.test.createListItem
import java.util.Date
import org.junit.Assert.assertEquals
import org.junit.Test
import org.mockito.Mockito.anyString
import org.mockito.Mockito.mockStatic
class ModelExtensionsTest {
@ -14,9 +18,10 @@ class ModelExtensionsTest {
"color": "#E2F6D3",
"title": "Test",
"pinned": false,
"date-created": 1742822848689,
"timestamp": 1742822848689,
"modifiedTimestamp": 1742823434623,
"labels": [
"Ggg"
"TestLabel"
],
"items": [
{
@ -56,9 +61,12 @@ class ModelExtensionsTest {
"dateTime": 1742822940000,
"repetition": "{\"value\":1,\"unit\":\"DAYS\"}"
}
]
],
"viewMode": "READ_ONLY"
}
"""
val colorMock = mockStatic(android.graphics.Color::class.java)
colorMock.`when`<Int> { android.graphics.Color.parseColor(anyString()) }.thenReturn(1)
val baseNote = json.toBaseNote()
@ -77,6 +85,77 @@ class ModelExtensionsTest {
baseNote.items,
)
assertEquals(1, baseNote.reminders.size)
assertEquals(1742822848689, baseNote.timestamp)
assertEquals(1742823434623, baseNote.modifiedTimestamp)
assertEquals(NoteViewMode.READ_ONLY, baseNote.viewMode)
assertEquals(listOf("TestLabel"), baseNote.labels)
assertEquals(Repetition(1, RepetitionTimeUnit.DAYS), baseNote.reminders[0].repetition)
}
@Test
fun `BaseNote toJson()`() {
val baseNote =
BaseNote(
id = 1,
Type.LIST,
Folder.DELETED,
"#E2F6D3",
"Title",
true,
12354632465L,
945869546L,
listOf("label"),
"Body",
listOf(SpanRepresentation(0, 10, bold = true)),
mutableListOf(
createListItem("Item1", true, false),
createListItem("Item2", true, true),
),
listOf(FileAttachment("localImage", "originalImage", "image/jpeg")),
listOf(FileAttachment("localFile", "originalFile", "text/plain")),
listOf(Audio("audio", 10L, 12312334L)),
listOf(Reminder(1, Date(1743253506957), Repetition(10, RepetitionTimeUnit.WEEKS))),
NoteViewMode.READ_ONLY,
)
val json = baseNote.toJson()
assertEquals(
"""
{
"reminders": [{
"dateTime": 1743253506957,
"id": 1,
"repetition": {
"unit": "WEEKS",
"value": 10
}
}],
"pinned": true,
"color": "#E2F6D3",
"modifiedTimestamp": 945869546,
"type": "LIST",
"title": "Title",
"viewMode": "READ_ONLY",
"items": [
{
"checked": true,
"body": "Item1",
"isChild": false
},
{
"checked": true,
"body": "Item2",
"isChild": true
}
],
"timestamp": 12354632465,
"labels": ["label"]
}
"""
.trimIndent()
.trimStart(),
json,
)
}
}