mirror of
https://github.com/SimpleMobileTools/Simple-Notes.git
synced 2025-04-23 19:57:23 +02:00
adding a new ChecklistFragment and rename NoteFragment to TextFragment
This commit is contained in:
parent
2d36835ebb
commit
22be4e4ac4
@ -32,7 +32,7 @@ import com.simplemobiletools.notes.pro.extensions.*
|
|||||||
import com.simplemobiletools.notes.pro.helpers.MIME_TEXT_PLAIN
|
import com.simplemobiletools.notes.pro.helpers.MIME_TEXT_PLAIN
|
||||||
import com.simplemobiletools.notes.pro.helpers.NotesHelper
|
import com.simplemobiletools.notes.pro.helpers.NotesHelper
|
||||||
import com.simplemobiletools.notes.pro.helpers.OPEN_NOTE_ID
|
import com.simplemobiletools.notes.pro.helpers.OPEN_NOTE_ID
|
||||||
import com.simplemobiletools.notes.pro.helpers.TYPE_NOTE
|
import com.simplemobiletools.notes.pro.helpers.TYPE_TEXT
|
||||||
import com.simplemobiletools.notes.pro.models.Note
|
import com.simplemobiletools.notes.pro.models.Note
|
||||||
import kotlinx.android.synthetic.main.activity_main.*
|
import kotlinx.android.synthetic.main.activity_main.*
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@ -400,7 +400,7 @@ class MainActivity : SimpleActivity() {
|
|||||||
title += " (file)"
|
title += " (file)"
|
||||||
}
|
}
|
||||||
|
|
||||||
val note = Note(null, title, "", TYPE_NOTE, path)
|
val note = Note(null, title, "", TYPE_TEXT, path)
|
||||||
addNewNote(note)
|
addNewNote(note)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,11 @@ import android.view.ViewGroup
|
|||||||
import androidx.fragment.app.FragmentManager
|
import androidx.fragment.app.FragmentManager
|
||||||
import androidx.fragment.app.FragmentStatePagerAdapter
|
import androidx.fragment.app.FragmentStatePagerAdapter
|
||||||
import com.simplemobiletools.commons.extensions.showErrorToast
|
import com.simplemobiletools.commons.extensions.showErrorToast
|
||||||
|
import com.simplemobiletools.notes.pro.fragments.ChecklistFragment
|
||||||
import com.simplemobiletools.notes.pro.fragments.NoteFragment
|
import com.simplemobiletools.notes.pro.fragments.NoteFragment
|
||||||
|
import com.simplemobiletools.notes.pro.fragments.TextFragment
|
||||||
import com.simplemobiletools.notes.pro.helpers.NOTE_ID
|
import com.simplemobiletools.notes.pro.helpers.NOTE_ID
|
||||||
|
import com.simplemobiletools.notes.pro.helpers.TYPE_TEXT
|
||||||
import com.simplemobiletools.notes.pro.models.Note
|
import com.simplemobiletools.notes.pro.models.Note
|
||||||
|
|
||||||
class NotesPagerAdapter(fm: FragmentManager, val notes: List<Note>, val activity: Activity) : FragmentStatePagerAdapter(fm) {
|
class NotesPagerAdapter(fm: FragmentManager, val notes: List<Note>, val activity: Activity) : FragmentStatePagerAdapter(fm) {
|
||||||
@ -17,14 +20,15 @@ class NotesPagerAdapter(fm: FragmentManager, val notes: List<Note>, val activity
|
|||||||
|
|
||||||
override fun getItem(position: Int): NoteFragment {
|
override fun getItem(position: Int): NoteFragment {
|
||||||
val bundle = Bundle()
|
val bundle = Bundle()
|
||||||
val id = notes[position].id
|
val note = notes[position]
|
||||||
|
val id = note.id
|
||||||
bundle.putLong(NOTE_ID, id!!)
|
bundle.putLong(NOTE_ID, id!!)
|
||||||
|
|
||||||
if (fragments.containsKey(position)) {
|
if (fragments.containsKey(position)) {
|
||||||
return fragments[position]!!
|
return fragments[position]!!
|
||||||
}
|
}
|
||||||
|
|
||||||
val fragment = NoteFragment()
|
val fragment = if (note.type == TYPE_TEXT) TextFragment() else ChecklistFragment()
|
||||||
fragment.arguments = bundle
|
fragment.arguments = bundle
|
||||||
fragments[position] = fragment
|
fragments[position] = fragment
|
||||||
return fragment
|
return fragment
|
||||||
@ -32,23 +36,23 @@ class NotesPagerAdapter(fm: FragmentManager, val notes: List<Note>, val activity
|
|||||||
|
|
||||||
override fun getPageTitle(position: Int) = notes[position].title
|
override fun getPageTitle(position: Int) = notes[position].title
|
||||||
|
|
||||||
fun getCurrentNotesView(position: Int) = fragments[position]?.getNotesView()
|
fun getCurrentNotesView(position: Int) = (fragments[position] as? TextFragment)?.getNotesView()
|
||||||
|
|
||||||
fun getCurrentNoteViewText(position: Int) = fragments[position]?.getCurrentNoteViewText()
|
fun getCurrentNoteViewText(position: Int) = (fragments[position] as? TextFragment)?.getCurrentNoteViewText()
|
||||||
|
|
||||||
fun appendText(position: Int, text: String) = fragments[position]?.getNotesView()?.append(text)
|
fun appendText(position: Int, text: String) = (fragments[position] as? TextFragment)?.getNotesView()?.append(text)
|
||||||
|
|
||||||
fun saveCurrentNote(position: Int, force: Boolean) = fragments[position]?.saveText(force)
|
fun saveCurrentNote(position: Int, force: Boolean) = (fragments[position] as? TextFragment)?.saveText(force)
|
||||||
|
|
||||||
fun focusEditText(position: Int) = fragments[position]?.focusEditText()
|
fun focusEditText(position: Int) = (fragments[position] as? TextFragment)?.focusEditText()
|
||||||
|
|
||||||
fun anyHasUnsavedChanges() = fragments.values.any { it.hasUnsavedChanges() }
|
fun anyHasUnsavedChanges() = fragments.values.any { (it as? TextFragment)?.hasUnsavedChanges() == true }
|
||||||
|
|
||||||
fun saveAllFragmentTexts() = fragments.values.forEach { it.saveText(false) }
|
fun saveAllFragmentTexts() = fragments.values.forEach { (it as? TextFragment)?.saveText(false) }
|
||||||
|
|
||||||
fun undo(position: Int) = fragments[position]?.undo()
|
fun undo(position: Int) = (fragments[position] as? TextFragment)?.undo()
|
||||||
|
|
||||||
fun redo(position: Int) = fragments[position]?.redo()
|
fun redo(position: Int) = (fragments[position] as? TextFragment)?.redo()
|
||||||
|
|
||||||
override fun finishUpdate(container: ViewGroup) {
|
override fun finishUpdate(container: ViewGroup) {
|
||||||
try {
|
try {
|
||||||
|
@ -6,7 +6,7 @@ import androidx.room.Room
|
|||||||
import androidx.room.RoomDatabase
|
import androidx.room.RoomDatabase
|
||||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||||
import com.simplemobiletools.notes.pro.R
|
import com.simplemobiletools.notes.pro.R
|
||||||
import com.simplemobiletools.notes.pro.helpers.TYPE_NOTE
|
import com.simplemobiletools.notes.pro.helpers.TYPE_TEXT
|
||||||
import com.simplemobiletools.notes.pro.interfaces.NotesDao
|
import com.simplemobiletools.notes.pro.interfaces.NotesDao
|
||||||
import com.simplemobiletools.notes.pro.interfaces.WidgetsDao
|
import com.simplemobiletools.notes.pro.interfaces.WidgetsDao
|
||||||
import com.simplemobiletools.notes.pro.models.Note
|
import com.simplemobiletools.notes.pro.models.Note
|
||||||
@ -49,7 +49,7 @@ abstract class NotesDatabase : RoomDatabase() {
|
|||||||
private fun insertFirstNote(context: Context) {
|
private fun insertFirstNote(context: Context) {
|
||||||
Executors.newSingleThreadScheduledExecutor().execute {
|
Executors.newSingleThreadScheduledExecutor().execute {
|
||||||
val generalNote = context.resources.getString(R.string.general_note)
|
val generalNote = context.resources.getString(R.string.general_note)
|
||||||
val note = Note(null, generalNote, "", TYPE_NOTE)
|
val note = Note(null, generalNote, "", TYPE_TEXT)
|
||||||
db!!.NotesDao().insertOrUpdate(note)
|
db!!.NotesDao().insertOrUpdate(note)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ import com.simplemobiletools.notes.pro.R
|
|||||||
import com.simplemobiletools.notes.pro.activities.SimpleActivity
|
import com.simplemobiletools.notes.pro.activities.SimpleActivity
|
||||||
import com.simplemobiletools.notes.pro.extensions.notesDB
|
import com.simplemobiletools.notes.pro.extensions.notesDB
|
||||||
import com.simplemobiletools.notes.pro.helpers.NotesHelper
|
import com.simplemobiletools.notes.pro.helpers.NotesHelper
|
||||||
import com.simplemobiletools.notes.pro.helpers.TYPE_NOTE
|
import com.simplemobiletools.notes.pro.helpers.TYPE_TEXT
|
||||||
import com.simplemobiletools.notes.pro.models.Note
|
import com.simplemobiletools.notes.pro.models.Note
|
||||||
import kotlinx.android.synthetic.main.dialog_import_folder.view.*
|
import kotlinx.android.synthetic.main.dialog_import_folder.view.*
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@ -70,7 +70,7 @@ class ImportFolderDialog(val activity: SimpleActivity, val path: String, val cal
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun saveNote(title: String, value: String, path: String) {
|
private fun saveNote(title: String, value: String, path: String) {
|
||||||
val note = Note(null, title, value, TYPE_NOTE, path)
|
val note = Note(null, title, value, TYPE_TEXT, path)
|
||||||
NotesHelper(activity).insertOrUpdateNote(note)
|
NotesHelper(activity).insertOrUpdateNote(note)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ import com.simplemobiletools.commons.extensions.value
|
|||||||
import com.simplemobiletools.notes.pro.R
|
import com.simplemobiletools.notes.pro.R
|
||||||
import com.simplemobiletools.notes.pro.extensions.notesDB
|
import com.simplemobiletools.notes.pro.extensions.notesDB
|
||||||
import com.simplemobiletools.notes.pro.helpers.TYPE_CHECKLIST
|
import com.simplemobiletools.notes.pro.helpers.TYPE_CHECKLIST
|
||||||
import com.simplemobiletools.notes.pro.helpers.TYPE_NOTE
|
import com.simplemobiletools.notes.pro.helpers.TYPE_TEXT
|
||||||
import com.simplemobiletools.notes.pro.models.Note
|
import com.simplemobiletools.notes.pro.models.Note
|
||||||
import kotlinx.android.synthetic.main.dialog_new_note.view.*
|
import kotlinx.android.synthetic.main.dialog_new_note.view.*
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ class NewNoteDialog(val activity: Activity, callback: (note: Note) -> Unit) {
|
|||||||
title.isEmpty() -> activity.toast(R.string.no_title)
|
title.isEmpty() -> activity.toast(R.string.no_title)
|
||||||
activity.notesDB.getNoteIdWithTitle(title) != null -> activity.toast(R.string.title_taken)
|
activity.notesDB.getNoteIdWithTitle(title) != null -> activity.toast(R.string.title_taken)
|
||||||
else -> {
|
else -> {
|
||||||
val type = if (view.note_checklist.isChecked) TYPE_CHECKLIST else TYPE_NOTE
|
val type = if (view.note_checklist.isChecked) TYPE_CHECKLIST else TYPE_TEXT
|
||||||
val newNote = Note(null, title, "", type)
|
val newNote = Note(null, title, "", type)
|
||||||
callback(newNote)
|
callback(newNote)
|
||||||
dismiss()
|
dismiss()
|
||||||
|
@ -7,7 +7,7 @@ import com.simplemobiletools.commons.extensions.humanizePath
|
|||||||
import com.simplemobiletools.commons.extensions.setupDialogStuff
|
import com.simplemobiletools.commons.extensions.setupDialogStuff
|
||||||
import com.simplemobiletools.notes.pro.R
|
import com.simplemobiletools.notes.pro.R
|
||||||
import com.simplemobiletools.notes.pro.activities.SimpleActivity
|
import com.simplemobiletools.notes.pro.activities.SimpleActivity
|
||||||
import com.simplemobiletools.notes.pro.helpers.TYPE_NOTE
|
import com.simplemobiletools.notes.pro.helpers.TYPE_TEXT
|
||||||
import com.simplemobiletools.notes.pro.models.Note
|
import com.simplemobiletools.notes.pro.models.Note
|
||||||
import kotlinx.android.synthetic.main.dialog_open_file.*
|
import kotlinx.android.synthetic.main.dialog_open_file.*
|
||||||
import kotlinx.android.synthetic.main.dialog_open_file.view.*
|
import kotlinx.android.synthetic.main.dialog_open_file.view.*
|
||||||
@ -45,7 +45,7 @@ class OpenFileDialog(val activity: SimpleActivity, val path: String, val callbac
|
|||||||
|
|
||||||
private fun saveNote(storeContent: String, storePath: String) {
|
private fun saveNote(storeContent: String, storePath: String) {
|
||||||
val filename = path.getFilenameFromPath()
|
val filename = path.getFilenameFromPath()
|
||||||
val note = Note(null, filename, storeContent, TYPE_NOTE, storePath)
|
val note = Note(null, filename, storeContent, TYPE_TEXT, storePath)
|
||||||
callback(note)
|
callback(note)
|
||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
package com.simplemobiletools.notes.pro.fragments
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import com.simplemobiletools.notes.pro.R
|
||||||
|
import com.simplemobiletools.notes.pro.helpers.NOTE_ID
|
||||||
|
import com.simplemobiletools.notes.pro.helpers.NotesHelper
|
||||||
|
import com.simplemobiletools.notes.pro.models.Note
|
||||||
|
|
||||||
|
class ChecklistFragment : NoteFragment() {
|
||||||
|
private var noteId = 0L
|
||||||
|
private var note: Note? = null
|
||||||
|
|
||||||
|
lateinit var view: ViewGroup
|
||||||
|
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
|
view = inflater.inflate(R.layout.fragment_checklist, container, false) as ViewGroup
|
||||||
|
noteId = arguments!!.getLong(NOTE_ID)
|
||||||
|
return view
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
|
||||||
|
NotesHelper(activity!!).getNoteWithId(noteId) {
|
||||||
|
if (it != null) {
|
||||||
|
note = it
|
||||||
|
setupFragment()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupFragment() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -1,297 +1,5 @@
|
|||||||
package com.simplemobiletools.notes.pro.fragments
|
package com.simplemobiletools.notes.pro.fragments
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import androidx.fragment.app.Fragment
|
||||||
import android.graphics.Typeface
|
|
||||||
import android.os.Build
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.text.Editable
|
|
||||||
import android.text.Selection
|
|
||||||
import android.text.TextWatcher
|
|
||||||
import android.text.style.UnderlineSpan
|
|
||||||
import android.text.util.Linkify
|
|
||||||
import android.util.TypedValue
|
|
||||||
import android.view.Gravity
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.view.inputmethod.EditorInfo
|
|
||||||
import androidx.annotation.RequiresApi
|
|
||||||
import com.simplemobiletools.commons.extensions.*
|
|
||||||
import com.simplemobiletools.notes.pro.R
|
|
||||||
import com.simplemobiletools.notes.pro.activities.MainActivity
|
|
||||||
import com.simplemobiletools.notes.pro.extensions.config
|
|
||||||
import com.simplemobiletools.notes.pro.extensions.getTextSize
|
|
||||||
import com.simplemobiletools.notes.pro.extensions.updateWidgets
|
|
||||||
import com.simplemobiletools.notes.pro.helpers.*
|
|
||||||
import com.simplemobiletools.notes.pro.models.Note
|
|
||||||
import com.simplemobiletools.notes.pro.models.TextHistory
|
|
||||||
import com.simplemobiletools.notes.pro.models.TextHistoryItem
|
|
||||||
import kotlinx.android.synthetic.main.fragment_note.*
|
|
||||||
import kotlinx.android.synthetic.main.fragment_note.view.*
|
|
||||||
import kotlinx.android.synthetic.main.note_view_horiz_scrollable.view.*
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
// text history handling taken from https://gist.github.com/zeleven/0cfa738c1e8b65b23ff7df1fc30c9f7e
|
abstract class NoteFragment : Fragment()
|
||||||
class NoteFragment : androidx.fragment.app.Fragment() {
|
|
||||||
private val TEXT = "text"
|
|
||||||
|
|
||||||
private var textHistory = TextHistory()
|
|
||||||
private var isUndoOrRedo = false
|
|
||||||
private var skipTextUpdating = false
|
|
||||||
private var noteId = 0L
|
|
||||||
private var note: Note? = null
|
|
||||||
|
|
||||||
lateinit var view: ViewGroup
|
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
|
||||||
view = inflater.inflate(R.layout.fragment_note, container, false) as ViewGroup
|
|
||||||
noteId = arguments!!.getLong(NOTE_ID)
|
|
||||||
retainInstance = true
|
|
||||||
|
|
||||||
val layoutToInflate = if (config!!.enableLineWrap) R.layout.note_view_static else R.layout.note_view_horiz_scrollable
|
|
||||||
inflater.inflate(layoutToInflate, view.notes_relative_layout, true)
|
|
||||||
if (config!!.clickableLinks) {
|
|
||||||
view.notes_view.apply {
|
|
||||||
linksClickable = true
|
|
||||||
autoLinkMask = Linkify.WEB_URLS or Linkify.EMAIL_ADDRESSES
|
|
||||||
movementMethod = MyMovementMethod.getInstance()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
view.notes_horizontal_scrollview?.onGlobalLayout {
|
|
||||||
view.notes_view.minWidth = view.notes_horizontal_scrollview.width
|
|
||||||
}
|
|
||||||
|
|
||||||
return view
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.O)
|
|
||||||
override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
|
|
||||||
NotesHelper(activity!!).getNoteWithId(noteId) {
|
|
||||||
if (it != null) {
|
|
||||||
note = it
|
|
||||||
setupFragment()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPause() {
|
|
||||||
super.onPause()
|
|
||||||
if (config!!.autosaveNotes) {
|
|
||||||
saveText(false)
|
|
||||||
}
|
|
||||||
view.notes_view.removeTextChangedListener(textWatcher)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setMenuVisibility(menuVisible: Boolean) {
|
|
||||||
super.setMenuVisibility(menuVisible)
|
|
||||||
if (!menuVisible && noteId != 0L && config?.autosaveNotes == true) {
|
|
||||||
saveText(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (menuVisible && noteId != 0L) {
|
|
||||||
val currentText = getCurrentNoteViewText()
|
|
||||||
if (currentText != null) {
|
|
||||||
(activity as MainActivity).currentNoteTextChanged(currentText, isUndoAvailable(), isRedoAvailable())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSaveInstanceState(outState: Bundle) {
|
|
||||||
super.onSaveInstanceState(outState)
|
|
||||||
if (note != null) {
|
|
||||||
outState.putString(TEXT, getCurrentNoteViewText())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewStateRestored(savedInstanceState: Bundle?) {
|
|
||||||
super.onViewStateRestored(savedInstanceState)
|
|
||||||
if (savedInstanceState != null && note != null && savedInstanceState.containsKey(TEXT)) {
|
|
||||||
skipTextUpdating = true
|
|
||||||
val newText = savedInstanceState.getString(TEXT) ?: ""
|
|
||||||
view.notes_view.setText(newText)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setupFragment() {
|
|
||||||
val config = config ?: return
|
|
||||||
view.notes_view.apply {
|
|
||||||
typeface = if (config.monospacedFont) Typeface.MONOSPACE else Typeface.DEFAULT
|
|
||||||
|
|
||||||
val fileContents = note!!.getNoteStoredValue()
|
|
||||||
if (fileContents == null) {
|
|
||||||
(activity as MainActivity).deleteNote(false)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
setColors(config.textColor, config.primaryColor, config.backgroundColor)
|
|
||||||
setTextSize(TypedValue.COMPLEX_UNIT_PX, context.getTextSize())
|
|
||||||
gravity = getTextGravity()
|
|
||||||
if (text.toString() != fileContents) {
|
|
||||||
if (!skipTextUpdating) {
|
|
||||||
setText(fileContents)
|
|
||||||
}
|
|
||||||
skipTextUpdating = false
|
|
||||||
setSelection(if (config.placeCursorToEnd) text.length else 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.showKeyboard) {
|
|
||||||
requestFocus()
|
|
||||||
}
|
|
||||||
|
|
||||||
imeOptions = if (config.useIncognitoMode) {
|
|
||||||
imeOptions or EditorInfo.IME_FLAG_NO_PERSONALIZED_LEARNING
|
|
||||||
} else {
|
|
||||||
imeOptions.removeBit(EditorInfo.IME_FLAG_NO_PERSONALIZED_LEARNING)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.showWordCount) {
|
|
||||||
view.notes_counter.beVisible()
|
|
||||||
view.notes_counter.setTextColor(config.textColor)
|
|
||||||
setWordCounter(view.notes_view.text.toString())
|
|
||||||
} else {
|
|
||||||
view.notes_counter.beGone()
|
|
||||||
}
|
|
||||||
|
|
||||||
view.notes_view.addTextChangedListener(textWatcher)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getNotesView() = view.notes_view
|
|
||||||
|
|
||||||
fun saveText(force: Boolean) {
|
|
||||||
if (note == null) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (note!!.path.isNotEmpty() && !File(note!!.path).exists()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (context == null || activity == null) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val newText = getCurrentNoteViewText()
|
|
||||||
val oldText = note!!.getNoteStoredValue()
|
|
||||||
if (newText != null && (newText != oldText || force)) {
|
|
||||||
note!!.value = newText
|
|
||||||
saveNoteValue(note!!)
|
|
||||||
context!!.updateWidgets()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun hasUnsavedChanges() = getCurrentNoteViewText() != note!!.getNoteStoredValue()
|
|
||||||
|
|
||||||
fun focusEditText() {
|
|
||||||
view.notes_view.requestFocus()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun saveNoteValue(note: Note) {
|
|
||||||
if (note.path.isEmpty()) {
|
|
||||||
NotesHelper(activity!!).insertOrUpdateNote(note) {
|
|
||||||
(activity as? MainActivity)?.noteSavedSuccessfully(note.title)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
val currentText = getCurrentNoteViewText()
|
|
||||||
if (currentText != null) {
|
|
||||||
val displaySuccess = activity?.config?.displaySuccess ?: false
|
|
||||||
(activity as? MainActivity)?.exportNoteValueToFile(note.path, currentText, displaySuccess)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getCurrentNoteViewText() = view.notes_view?.text?.toString()
|
|
||||||
|
|
||||||
@SuppressLint("RtlHardcoded")
|
|
||||||
private fun getTextGravity() = when (config!!.gravity) {
|
|
||||||
GRAVITY_CENTER -> Gravity.CENTER_HORIZONTAL
|
|
||||||
GRAVITY_RIGHT -> Gravity.RIGHT
|
|
||||||
else -> Gravity.LEFT
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setWordCounter(text: String) {
|
|
||||||
val words = text.replace("\n", " ").split(" ")
|
|
||||||
notes_counter.text = words.count { it.isNotEmpty() }.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun undo() {
|
|
||||||
val edit = textHistory.getPrevious() ?: return
|
|
||||||
|
|
||||||
val text = view.notes_view.editableText
|
|
||||||
val start = edit.start
|
|
||||||
val end = start + if (edit.after != null) edit.after.length else 0
|
|
||||||
|
|
||||||
isUndoOrRedo = true
|
|
||||||
try {
|
|
||||||
text.replace(start, end, edit.before)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
activity?.showErrorToast(e)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
isUndoOrRedo = false
|
|
||||||
|
|
||||||
for (span in text.getSpans(0, text.length, UnderlineSpan::class.java)) {
|
|
||||||
text.removeSpan(span)
|
|
||||||
}
|
|
||||||
|
|
||||||
Selection.setSelection(text, if (edit.before == null) {
|
|
||||||
start
|
|
||||||
} else {
|
|
||||||
start + edit.before.length
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fun redo() {
|
|
||||||
val edit = textHistory.getNext() ?: return
|
|
||||||
|
|
||||||
val text = view.notes_view.editableText
|
|
||||||
val start = edit.start
|
|
||||||
val end = start + if (edit.before != null) edit.before.length else 0
|
|
||||||
|
|
||||||
isUndoOrRedo = true
|
|
||||||
text.replace(start, end, edit.after)
|
|
||||||
isUndoOrRedo = false
|
|
||||||
|
|
||||||
for (o in text.getSpans(0, text.length, UnderlineSpan::class.java)) {
|
|
||||||
text.removeSpan(o)
|
|
||||||
}
|
|
||||||
|
|
||||||
Selection.setSelection(text, if (edit.after == null) {
|
|
||||||
start
|
|
||||||
} else {
|
|
||||||
start + edit.after.length
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isUndoAvailable() = textHistory.position > 0
|
|
||||||
|
|
||||||
fun isRedoAvailable() = textHistory.position < textHistory.history.size
|
|
||||||
|
|
||||||
private var textWatcher: TextWatcher = object : TextWatcher {
|
|
||||||
private var beforeChange: CharSequence? = null
|
|
||||||
private var afterChange: CharSequence? = null
|
|
||||||
|
|
||||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
|
|
||||||
if (!isUndoOrRedo) {
|
|
||||||
beforeChange = s.subSequence(start, start + count)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
|
||||||
if (!isUndoOrRedo) {
|
|
||||||
afterChange = s.subSequence(start, start + count)
|
|
||||||
textHistory.add(TextHistoryItem(start, beforeChange!!, afterChange!!))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun afterTextChanged(editable: Editable) {
|
|
||||||
val text = editable.toString()
|
|
||||||
setWordCounter(text)
|
|
||||||
(activity as MainActivity).currentNoteTextChanged(text, isUndoAvailable(), isRedoAvailable())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -0,0 +1,293 @@
|
|||||||
|
package com.simplemobiletools.notes.pro.fragments
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.graphics.Typeface
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.text.Editable
|
||||||
|
import android.text.Selection
|
||||||
|
import android.text.TextWatcher
|
||||||
|
import android.text.style.UnderlineSpan
|
||||||
|
import android.text.util.Linkify
|
||||||
|
import android.util.TypedValue
|
||||||
|
import android.view.Gravity
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.view.inputmethod.EditorInfo
|
||||||
|
import com.simplemobiletools.commons.extensions.*
|
||||||
|
import com.simplemobiletools.notes.pro.R
|
||||||
|
import com.simplemobiletools.notes.pro.activities.MainActivity
|
||||||
|
import com.simplemobiletools.notes.pro.extensions.config
|
||||||
|
import com.simplemobiletools.notes.pro.extensions.getTextSize
|
||||||
|
import com.simplemobiletools.notes.pro.extensions.updateWidgets
|
||||||
|
import com.simplemobiletools.notes.pro.helpers.*
|
||||||
|
import com.simplemobiletools.notes.pro.models.Note
|
||||||
|
import com.simplemobiletools.notes.pro.models.TextHistory
|
||||||
|
import com.simplemobiletools.notes.pro.models.TextHistoryItem
|
||||||
|
import kotlinx.android.synthetic.main.fragment_text.view.*
|
||||||
|
import kotlinx.android.synthetic.main.note_view_horiz_scrollable.view.*
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
// text history handling taken from https://gist.github.com/zeleven/0cfa738c1e8b65b23ff7df1fc30c9f7e
|
||||||
|
class TextFragment : NoteFragment() {
|
||||||
|
private val TEXT = "text"
|
||||||
|
|
||||||
|
private var textHistory = TextHistory()
|
||||||
|
private var isUndoOrRedo = false
|
||||||
|
private var skipTextUpdating = false
|
||||||
|
private var noteId = 0L
|
||||||
|
private var note: Note? = null
|
||||||
|
|
||||||
|
lateinit var view: ViewGroup
|
||||||
|
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
|
view = inflater.inflate(R.layout.fragment_text, container, false) as ViewGroup
|
||||||
|
noteId = arguments!!.getLong(NOTE_ID)
|
||||||
|
retainInstance = true
|
||||||
|
|
||||||
|
val layoutToInflate = if (config!!.enableLineWrap) R.layout.note_view_static else R.layout.note_view_horiz_scrollable
|
||||||
|
inflater.inflate(layoutToInflate, view.notes_relative_layout, true)
|
||||||
|
if (config!!.clickableLinks) {
|
||||||
|
view.notes_view.apply {
|
||||||
|
linksClickable = true
|
||||||
|
autoLinkMask = Linkify.WEB_URLS or Linkify.EMAIL_ADDRESSES
|
||||||
|
movementMethod = MyMovementMethod.getInstance()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
view.notes_horizontal_scrollview?.onGlobalLayout {
|
||||||
|
view.notes_view.minWidth = view.notes_horizontal_scrollview.width
|
||||||
|
}
|
||||||
|
|
||||||
|
return view
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
|
||||||
|
NotesHelper(activity!!).getNoteWithId(noteId) {
|
||||||
|
if (it != null) {
|
||||||
|
note = it
|
||||||
|
setupFragment()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPause() {
|
||||||
|
super.onPause()
|
||||||
|
if (config!!.autosaveNotes) {
|
||||||
|
saveText(false)
|
||||||
|
}
|
||||||
|
view.notes_view.removeTextChangedListener(textWatcher)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setMenuVisibility(menuVisible: Boolean) {
|
||||||
|
super.setMenuVisibility(menuVisible)
|
||||||
|
if (!menuVisible && noteId != 0L && config?.autosaveNotes == true) {
|
||||||
|
saveText(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (menuVisible && noteId != 0L) {
|
||||||
|
val currentText = getCurrentNoteViewText()
|
||||||
|
if (currentText != null) {
|
||||||
|
(activity as MainActivity).currentNoteTextChanged(currentText, isUndoAvailable(), isRedoAvailable())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
|
super.onSaveInstanceState(outState)
|
||||||
|
if (note != null) {
|
||||||
|
outState.putString(TEXT, getCurrentNoteViewText())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewStateRestored(savedInstanceState: Bundle?) {
|
||||||
|
super.onViewStateRestored(savedInstanceState)
|
||||||
|
if (savedInstanceState != null && note != null && savedInstanceState.containsKey(TEXT)) {
|
||||||
|
skipTextUpdating = true
|
||||||
|
val newText = savedInstanceState.getString(TEXT) ?: ""
|
||||||
|
view.notes_view.setText(newText)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupFragment() {
|
||||||
|
val config = config ?: return
|
||||||
|
view.notes_view.apply {
|
||||||
|
typeface = if (config.monospacedFont) Typeface.MONOSPACE else Typeface.DEFAULT
|
||||||
|
|
||||||
|
val fileContents = note!!.getNoteStoredValue()
|
||||||
|
if (fileContents == null) {
|
||||||
|
(activity as MainActivity).deleteNote(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
setColors(config.textColor, config.primaryColor, config.backgroundColor)
|
||||||
|
setTextSize(TypedValue.COMPLEX_UNIT_PX, context.getTextSize())
|
||||||
|
gravity = getTextGravity()
|
||||||
|
if (text.toString() != fileContents) {
|
||||||
|
if (!skipTextUpdating) {
|
||||||
|
setText(fileContents)
|
||||||
|
}
|
||||||
|
skipTextUpdating = false
|
||||||
|
setSelection(if (config.placeCursorToEnd) text.length else 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.showKeyboard) {
|
||||||
|
requestFocus()
|
||||||
|
}
|
||||||
|
|
||||||
|
imeOptions = if (config.useIncognitoMode) {
|
||||||
|
imeOptions or EditorInfo.IME_FLAG_NO_PERSONALIZED_LEARNING
|
||||||
|
} else {
|
||||||
|
imeOptions.removeBit(EditorInfo.IME_FLAG_NO_PERSONALIZED_LEARNING)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.showWordCount) {
|
||||||
|
view.notes_counter.beVisible()
|
||||||
|
view.notes_counter.setTextColor(config.textColor)
|
||||||
|
setWordCounter(view.notes_view.text.toString())
|
||||||
|
} else {
|
||||||
|
view.notes_counter.beGone()
|
||||||
|
}
|
||||||
|
|
||||||
|
view.notes_view.addTextChangedListener(textWatcher)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getNotesView() = view.notes_view
|
||||||
|
|
||||||
|
fun saveText(force: Boolean) {
|
||||||
|
if (note == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (note!!.path.isNotEmpty() && !File(note!!.path).exists()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context == null || activity == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val newText = getCurrentNoteViewText()
|
||||||
|
val oldText = note!!.getNoteStoredValue()
|
||||||
|
if (newText != null && (newText != oldText || force)) {
|
||||||
|
note!!.value = newText
|
||||||
|
saveNoteValue(note!!)
|
||||||
|
context!!.updateWidgets()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hasUnsavedChanges() = getCurrentNoteViewText() != note!!.getNoteStoredValue()
|
||||||
|
|
||||||
|
fun focusEditText() {
|
||||||
|
view.notes_view.requestFocus()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun saveNoteValue(note: Note) {
|
||||||
|
if (note.path.isEmpty()) {
|
||||||
|
NotesHelper(activity!!).insertOrUpdateNote(note) {
|
||||||
|
(activity as? MainActivity)?.noteSavedSuccessfully(note.title)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val currentText = getCurrentNoteViewText()
|
||||||
|
if (currentText != null) {
|
||||||
|
val displaySuccess = activity?.config?.displaySuccess ?: false
|
||||||
|
(activity as? MainActivity)?.exportNoteValueToFile(note.path, currentText, displaySuccess)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getCurrentNoteViewText() = view.notes_view?.text?.toString()
|
||||||
|
|
||||||
|
@SuppressLint("RtlHardcoded")
|
||||||
|
private fun getTextGravity() = when (config!!.gravity) {
|
||||||
|
GRAVITY_CENTER -> Gravity.CENTER_HORIZONTAL
|
||||||
|
GRAVITY_RIGHT -> Gravity.RIGHT
|
||||||
|
else -> Gravity.LEFT
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setWordCounter(text: String) {
|
||||||
|
val words = text.replace("\n", " ").split(" ")
|
||||||
|
view.notes_counter.text = words.count { it.isNotEmpty() }.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun undo() {
|
||||||
|
val edit = textHistory.getPrevious() ?: return
|
||||||
|
|
||||||
|
val text = view.notes_view.editableText
|
||||||
|
val start = edit.start
|
||||||
|
val end = start + if (edit.after != null) edit.after.length else 0
|
||||||
|
|
||||||
|
isUndoOrRedo = true
|
||||||
|
try {
|
||||||
|
text.replace(start, end, edit.before)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
activity?.showErrorToast(e)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
isUndoOrRedo = false
|
||||||
|
|
||||||
|
for (span in text.getSpans(0, text.length, UnderlineSpan::class.java)) {
|
||||||
|
text.removeSpan(span)
|
||||||
|
}
|
||||||
|
|
||||||
|
Selection.setSelection(text, if (edit.before == null) {
|
||||||
|
start
|
||||||
|
} else {
|
||||||
|
start + edit.before.length
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun redo() {
|
||||||
|
val edit = textHistory.getNext() ?: return
|
||||||
|
|
||||||
|
val text = view.notes_view.editableText
|
||||||
|
val start = edit.start
|
||||||
|
val end = start + if (edit.before != null) edit.before.length else 0
|
||||||
|
|
||||||
|
isUndoOrRedo = true
|
||||||
|
text.replace(start, end, edit.after)
|
||||||
|
isUndoOrRedo = false
|
||||||
|
|
||||||
|
for (o in text.getSpans(0, text.length, UnderlineSpan::class.java)) {
|
||||||
|
text.removeSpan(o)
|
||||||
|
}
|
||||||
|
|
||||||
|
Selection.setSelection(text, if (edit.after == null) {
|
||||||
|
start
|
||||||
|
} else {
|
||||||
|
start + edit.after.length
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isUndoAvailable() = textHistory.position > 0
|
||||||
|
|
||||||
|
fun isRedoAvailable() = textHistory.position < textHistory.history.size
|
||||||
|
|
||||||
|
private var textWatcher: TextWatcher = object : TextWatcher {
|
||||||
|
private var beforeChange: CharSequence? = null
|
||||||
|
private var afterChange: CharSequence? = null
|
||||||
|
|
||||||
|
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
|
||||||
|
if (!isUndoOrRedo) {
|
||||||
|
beforeChange = s.subSequence(start, start + count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
||||||
|
if (!isUndoOrRedo) {
|
||||||
|
afterChange = s.subSequence(start, start + count)
|
||||||
|
textHistory.add(TextHistoryItem(start, beforeChange!!, afterChange!!))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun afterTextChanged(editable: Editable) {
|
||||||
|
val text = editable.toString()
|
||||||
|
setWordCounter(text)
|
||||||
|
(activity as MainActivity).currentNoteTextChanged(text, isUndoAvailable(), isRedoAvailable())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -33,7 +33,7 @@ const val FONT_SIZE_LARGE = 2
|
|||||||
const val FONT_SIZE_EXTRA_LARGE = 3
|
const val FONT_SIZE_EXTRA_LARGE = 3
|
||||||
|
|
||||||
// note types
|
// note types
|
||||||
const val TYPE_NOTE = 0
|
const val TYPE_TEXT = 0
|
||||||
const val TYPE_CHECKLIST = 1
|
const val TYPE_CHECKLIST = 1
|
||||||
|
|
||||||
// mime types
|
// mime types
|
||||||
|
@ -29,7 +29,7 @@ class NotesHelper(val activity: Activity) {
|
|||||||
|
|
||||||
if (notes.isEmpty()) {
|
if (notes.isEmpty()) {
|
||||||
val generalNote = activity.resources.getString(R.string.general_note)
|
val generalNote = activity.resources.getString(R.string.general_note)
|
||||||
val note = Note(null, generalNote, "", TYPE_NOTE)
|
val note = Note(null, generalNote, "", TYPE_TEXT)
|
||||||
activity.notesDB.insertOrUpdate(note)
|
activity.notesDB.insertOrUpdate(note)
|
||||||
notes.add(note)
|
notes.add(note)
|
||||||
}
|
}
|
||||||
|
10
app/src/main/res/layout/fragment_checklist.xml
Normal file
10
app/src/main/res/layout/fragment_checklist.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<com.simplemobiletools.commons.views.MyRecyclerView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:id="@+id/checklist"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:overScrollMode="never"
|
||||||
|
app:layoutManager="com.simplemobiletools.commons.views.MyLinearLayoutManager"/>
|
Loading…
x
Reference in New Issue
Block a user