Included XML in the list of supported export formats

This commit is contained in:
Om Godse 2021-07-14 16:37:36 +05:30
parent 18a8816837
commit 471de05c96
13 changed files with 71 additions and 28 deletions

View file

@ -1,4 +1,4 @@
*Please use the issues tab only for bug reports*
*Please use the pull requests tab only for translations or bug reports*
### Background
Although there are many notes apps out there, they're all hideous, glitchy, low quality or all 3 at the same time.
@ -23,7 +23,7 @@ Well, Notally is none of these things. It's extremely light, minimalistic and el
* APK size of 1.5 MB (1.9 MB Uncompressed)
* Add labels to your notes for quick organisation
* Archive notes to keep them around, but out of your way
* Export notes as plain text, HTML or PDF files with formatting
* Export notes as plain text, XML, HTML or PDF files with formatting
* Create rich text notes with support for bold, italics, mono space and strike-through
* Add clickable links to notes with support for phone numbers, email addresses and web urls

View file

@ -13,9 +13,9 @@ android {
applicationId "com.omgodse.notally"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 33
versionName "3.8"
resConfigs "en", "ca", "cs", "de", "es", "fr", "hu", "in", "it", "ja", "nb", "nl", "pl", "pt-rBR", "ru", "sv", "tl", "tr", "uk"
versionCode 34
versionName "3.9"
resConfigs "en", "ca", "cs", "de", "es", "fr", "hu", "in", "it", "ja", "nb", "nl", "pl", "pt-rBR", "ru", "sk", "sv", "tl", "tr", "uk"
vectorDrawables.generatedDensities = []
}
@ -56,7 +56,7 @@ dependencies {
implementation "androidx.navigation:navigation-fragment-ktx:$navVersion"
implementation "org.ocpsoft.prettytime:prettytime:4.0.6.Final"
implementation "com.google.android.material:material:1.3.0"
implementation "com.google.android.material:material:1.4.0"
implementation project(":Post")
}

View file

@ -11,6 +11,7 @@ import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.Toast
import androidx.core.content.FileProvider
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.LiveData
@ -140,10 +141,7 @@ abstract class NotallyFragment : Fragment(), OperationsParent, ItemListener {
private fun setupObserver() {
getObservable()?.observe(viewLifecycleOwner, { list ->
adapter?.submitList(list)
if (list.isNotEmpty()) {
binding?.RecyclerView?.visibility = View.VISIBLE
} else binding?.RecyclerView?.visibility = View.GONE
binding?.RecyclerView?.isVisible = list.isNotEmpty()
})
}
@ -176,6 +174,7 @@ abstract class NotallyFragment : Fragment(), OperationsParent, ItemListener {
MenuDialog(mContext)
.addItem(Operation(R.string.pdf, R.drawable.pdf) { exportBaseNoteToPDF(baseNote) })
.addItem(Operation(R.string.txt, R.drawable.txt) { exportBaseNoteToTXT(baseNote) })
.addItem(Operation(R.string.xml, R.drawable.xml) { exportBaseNoteToXML(baseNote) })
.addItem(Operation(R.string.html, R.drawable.html) { exportBaseNoteToHTML(baseNote) })
.show()
}
@ -196,7 +195,7 @@ abstract class NotallyFragment : Fragment(), OperationsParent, ItemListener {
}
override fun onFailure(message: String?) {
Toast.makeText(context, R.string.something_went_wrong, Toast.LENGTH_SHORT).show()
Toast.makeText(mContext, R.string.something_went_wrong, Toast.LENGTH_SHORT).show()
}
})
}
@ -208,6 +207,13 @@ abstract class NotallyFragment : Fragment(), OperationsParent, ItemListener {
}
}
private fun exportBaseNoteToXML(baseNote: BaseNote) {
lifecycleScope.launch {
val file = model.getXMLFile(baseNote)
showFileOptionsDialog(file, "text/xml")
}
}
private fun exportBaseNoteToHTML(baseNote: BaseNote) {
lifecycleScope.launch {
val file = model.getHTMLFile(baseNote, settingsHelper.getShowDateCreated())
@ -227,29 +233,29 @@ abstract class NotallyFragment : Fragment(), OperationsParent, ItemListener {
private fun viewFile(uri: Uri, mimeType: String) {
val intent = Intent(Intent.ACTION_VIEW).apply {
setDataAndType(uri, mimeType)
flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
}
val intent = Intent(Intent.ACTION_VIEW)
intent.setDataAndType(uri, mimeType)
intent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
val chooser = Intent.createChooser(intent, mContext.getString(R.string.view_note))
startActivity(chooser)
}
private fun shareFile(uri: Uri, mimeType: String) {
val intent = Intent(Intent.ACTION_SEND).apply {
type = mimeType
putExtra(Intent.EXTRA_STREAM, uri)
}
val intent = Intent(Intent.ACTION_SEND)
intent.type = mimeType
intent.putExtra(Intent.EXTRA_STREAM, uri)
val chooser = Intent.createChooser(intent, mContext.getString(R.string.share_note))
startActivity(chooser)
}
private fun saveFileToDevice(file: File, mimeType: String) {
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
type = mimeType
addCategory(Intent.CATEGORY_OPENABLE)
putExtra(Intent.EXTRA_TITLE, file.nameWithoutExtension)
}
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT)
intent.type = mimeType
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.putExtra(Intent.EXTRA_TITLE, file.nameWithoutExtension)
model.currentFile = file
startActivityForResult(intent, Constants.RequestCodeExportFile)
}

View file

@ -132,6 +132,15 @@ class BaseNoteModel(private val app: Application) : AndroidViewModel(app) {
}
suspend fun getXMLFile(baseNote: BaseNote) = withContext(Dispatchers.IO) {
val fileName = getFileName(baseNote)
val file = File(getExportedPath(), "$fileName.xml")
val outputStream = FileOutputStream(file)
XMLUtils.writeBaseNoteToStream(baseNote, outputStream)
outputStream.close()
file
}
suspend fun getTXTFile(baseNote: BaseNote, showDateCreated: Boolean) = withContext(Dispatchers.IO) {
val fileName = getFileName(baseNote)
val file = File(getExportedPath(), "$fileName.txt")
@ -233,6 +242,7 @@ class BaseNoteModel(private val app: Application) : AndroidViewModel(app) {
private fun getHTML(baseNote: BaseNote, showDateCreated: Boolean) = buildString {
val date = formatter.format(baseNote.timestamp)
append("<!DOCTYPE html>")
append("<html><head><meta charset=\"UTF-8\"></head><body>")
append("<h2>${Html.escapeHtml(baseNote.title)}</h2>")
@ -243,7 +253,7 @@ class BaseNoteModel(private val app: Application) : AndroidViewModel(app) {
when (baseNote.type) {
Type.NOTE -> {
val body = baseNote.body.applySpans(baseNote.spans).toHtml()
append("<p>$body</p>")
append(body)
}
Type.LIST -> {
append("<ol>")

View file

@ -113,6 +113,22 @@ object XMLUtils {
xmlSerializer.endDocument()
}
fun writeBaseNoteToStream(baseNote: BaseNote, stream: OutputStream) {
val xmlSerializer = Xml.newSerializer()
xmlSerializer.setOutput(stream, null)
xmlSerializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true)
xmlSerializer.startDocument("UTF-8", true)
when (baseNote.type) {
Type.NOTE -> appendNote(baseNote, xmlSerializer)
Type.LIST -> appendList(baseNote, xmlSerializer)
}
xmlSerializer.endDocument()
}
private fun appendNote(note: BaseNote, xmlSerializer: XmlSerializer) {
xmlSerializer.startTag(null, XMLTags.Note)

View file

@ -5,5 +5,5 @@
android:viewportHeight="24">
<path
android:fillColor="#000000"
android:pathData="M9.4,16.6L4.8,12l4.6,-4.6L8,6l-6,6 6,6 1.4,-1.4zM14.6,16.6l4.6,-4.6 -4.6,-4.6L16,6l6,6 -6,6 -1.4,-1.4z" />
android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM18.92,8h-2.95c-0.32,-1.25 -0.78,-2.45 -1.38,-3.56 1.84,0.63 3.37,1.91 4.33,3.56zM12,4.04c0.83,1.2 1.48,2.53 1.91,3.96h-3.82c0.43,-1.43 1.08,-2.76 1.91,-3.96zM4.26,14C4.1,13.36 4,12.69 4,12s0.1,-1.36 0.26,-2h3.38c-0.08,0.66 -0.14,1.32 -0.14,2s0.06,1.34 0.14,2L4.26,14zM5.08,16h2.95c0.32,1.25 0.78,2.45 1.38,3.56 -1.84,-0.63 -3.37,-1.9 -4.33,-3.56zM8.03,8L5.08,8c0.96,-1.66 2.49,-2.93 4.33,-3.56C8.81,5.55 8.35,6.75 8.03,8zM12,19.96c-0.83,-1.2 -1.48,-2.53 -1.91,-3.96h3.82c-0.43,1.43 -1.08,2.76 -1.91,3.96zM14.34,14L9.66,14c-0.09,-0.66 -0.16,-1.32 -0.16,-2s0.07,-1.35 0.16,-2h4.68c0.09,0.65 0.16,1.32 0.16,2s-0.07,1.34 -0.16,2zM14.59,19.56c0.6,-1.11 1.06,-2.31 1.38,-3.56h2.95c-0.96,1.65 -2.49,2.93 -4.33,3.56zM16.36,14c0.08,-0.66 0.14,-1.32 0.14,-2s-0.06,-1.34 -0.14,-2h3.38c0.16,0.64 0.26,1.31 0.26,2s-0.1,1.36 -0.26,2h-3.38z" />
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#000000"
android:pathData="M9.4,16.6L4.8,12l4.6,-4.6L8,6l-6,6 6,6 1.4,-1.4zM14.6,16.6l4.6,-4.6 -4.6,-4.6L16,6l6,6 -6,6 -1.4,-1.4z" />
</vector>

View file

@ -37,6 +37,7 @@
<string name="export">Export</string>
<string name="pdf" translatable="false">PDF</string>
<string name="txt" translatable="false">TXT</string>
<string name="xml" translatable="false">XML</string>
<string name="html" translatable="false">HTML</string>
<string name="save_to_device">Save to device</string>
<string name="edit_label">Edit label</string>

View file

@ -4,7 +4,7 @@ buildscript {
minSdkVersion = 21
targetSdkVersion = 30
compileSdkVersion = 30
kotlinVersion = "1.5.10"
kotlinVersion = "1.5.21"
buildToolsVersion = "30.0.3"
}
@ -14,7 +14,7 @@ buildscript {
}
dependencies {
classpath "com.android.tools.build:gradle:4.2.1"
classpath "com.android.tools.build:gradle:4.2.2"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
}
}

View file

@ -13,6 +13,7 @@ Add clickable links to notes with support for phone numbers, email addresses and
• PDF
• TXT
• XML
• HTML
<b>Convenience</b>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 124 KiB

After

Width:  |  Height:  |  Size: 133 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 124 KiB

After

Width:  |  Height:  |  Size: 111 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 125 KiB

After

Width:  |  Height:  |  Size: 168 KiB

Before After
Before After