Skip to content

Commit

Permalink
Added option to import books from CSV.
Browse files Browse the repository at this point in the history
  • Loading branch information
mateusz-bak committed May 29, 2022
1 parent e67ed43 commit 4e9bc35
Show file tree
Hide file tree
Showing 28 changed files with 210 additions and 0 deletions.
106 changes: 106 additions & 0 deletions app/src/main/java/software/mdev/bookstracker/other/Backup.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import android.view.View
import android.widget.ProgressBar
import androidx.core.content.FileProvider.getUriForFile
import androidx.sqlite.db.SimpleSQLiteQuery
import com.github.doyaaaaaken.kotlincsv.dsl.csvReader
import kotlinx.android.synthetic.main.fragment_add_book_search.*
import kotlinx.coroutines.*
import software.mdev.bookstracker.BuildConfig
Expand All @@ -21,6 +22,7 @@ import software.mdev.bookstracker.data.db.entities.Year
import software.mdev.bookstracker.ui.bookslist.ListActivity
import java.io.*
import java.lang.StringBuilder
import java.text.Normalizer
import java.text.SimpleDateFormat
import java.util.*
import java.util.zip.*
Expand Down Expand Up @@ -125,6 +127,10 @@ class Backup {
activity.selectBackup.launch("*/*")
}

fun runImporterCSV(activity: ListActivity) {
activity.selectCSV.launch("text/*")
}

// Import a backup overwriting any existing data and checking if the file is valid
suspend fun importBackup(context: Context, fileUri: Uri): Boolean {
when (validateBackup(fileUri, context)) {
Expand Down Expand Up @@ -251,6 +257,26 @@ class Backup {
}
}

fun importCSV(context: Context, fileUri: Uri): Boolean {
try {
val fileStream = context.contentResolver.openInputStream(fileUri)!!
val books = parseGoodReadsCSV(fileStream)

for (book in books)
(context as ListActivity).booksViewModel.upsert(book)

(context as ListActivity).showSnackbar(context.getString(R.string.backup_import_success))
} catch (e: Exception) {
val string = "${context.getString(R.string.csv_import_failure)}: $e"
(context as ListActivity).showSnackbar(string)
e.printStackTrace()
return false
}

restartActivity(context)
return true
}

private fun zipAll(directory: String, zipFile: String) {
val sourceFile = File(directory)
val outputZipFile = File(zipFile)
Expand Down Expand Up @@ -341,4 +367,84 @@ class Backup {
progressBar?.bringToFront()
}
}

private fun parseGoodReadsCSV(inputStream: InputStream): List<Book> {
val rows = csvReader().readAllWithHeader(inputStream)
var newBooks: MutableList<Book> = ArrayList()

for (row in rows)
newBooks.add(parseGoodReadsBook(row))

return newBooks
}

private fun parseGoodReadsBook(row: Map<String, String>): Book {
val regexUnaccented = "\\p{InCombiningDiacriticalMarks}+".toRegex()

fun CharSequence.unaccented(): String {
val temp = Normalizer.normalize(this, Normalizer.Form.NFD)
return regexUnaccented.replace(temp, "")
}

val title = row["Title"] ?: Constants.EMPTY_STRING

var author: String = row["Author"] ?: Constants.EMPTY_STRING
val additionalAuthors = row["Additional Authors"] ?: Constants.EMPTY_STRING
if (additionalAuthors.isNotEmpty())
author = "$author, $additionalAuthors"

var dateAdded = Constants.DATABASE_EMPTY_VALUE
if (row["Date Added"]?.isNotEmpty() == true) {
dateAdded = row["Date Added"]?.let {
SimpleDateFormat("yyyy/MM/dd").parse(it).time
}.toString()
}

var dateStarted = Constants.DATABASE_EMPTY_VALUE
if (row["Date Started"]?.isNotEmpty() == true) {
dateStarted = row["Date Started"]?.let {
SimpleDateFormat("yyyy/MM/dd").parse(it).time
}.toString()
}

val bookStatus = when (row["Exclusive Shelf"]) {
"currently-reading" -> Constants.BOOK_STATUS_IN_PROGRESS
"to-read" -> Constants.BOOK_STATUS_TO_READ
else -> Constants.BOOK_STATUS_READ
}

var dateFinished = Constants.DATABASE_EMPTY_VALUE
if (row["Date Read"]?.isNotEmpty() == true) {
dateFinished = row["Date Read"]?.let {
SimpleDateFormat("yyyy/MM/dd").parse(it).time
}.toString()
} else if (bookStatus == Constants.BOOK_STATUS_READ) {
dateFinished = dateAdded
}

return Book(
bookTitle = title,
bookAuthor = author,
bookRating = row["My Rating"]?.toFloatOrNull() ?: 0F,
bookStatus = bookStatus,
bookPriority = Constants.DATABASE_EMPTY_VALUE,
bookStartDate = dateStarted,
bookFinishDate = dateFinished,
bookNumberOfPages = row["Number of Pages"]?.toIntOrNull() ?: 0,
bookTitle_ASCII = title.unaccented().replace("ł", "l", false),
bookAuthor_ASCII = author.unaccented().replace("ł", "l", false),
bookIsDeleted = false,
bookCoverUrl = Constants.DATABASE_EMPTY_VALUE,
bookOLID = Constants.DATABASE_EMPTY_VALUE,
bookISBN10 = row["ISBN"]?.removeSurrounding("=\"", "\"")
?: Constants.DATABASE_EMPTY_VALUE,
bookISBN13 = row["ISBN13"]?.removeSurrounding("=\"", "\"")
?: Constants.DATABASE_EMPTY_VALUE,
bookPublishYear = row["Original Publication Year"]?.toIntOrNull() ?: 0,
bookIsFav = false,
bookCoverImg = null,
bookNotes = row["My Review"] ?: Constants.DATABASE_EMPTY_VALUE,
bookTags = null,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ object Constants {
const val KEY_IMPORT = "KEY_IMPORT"
const val KEY_CHANGELOG = "KEY_CHANGELOG"
const val KEY_FEEDBACK = "KEY_FEEDBACK"
const val KEY_CSV_IMPORT = "KEY_CSV_IMPORT"

const val EMPTY_STRING = ""

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -983,6 +983,18 @@ class ListActivity : AppCompatActivity() {
}
}

val selectCSV =
registerForActivityResult(ActivityResultContracts.GetContent()) { fileUri: Uri? ->
try {
CoroutineScope(Dispatchers.IO).launch {
if (fileUri != null) Backup().importCSV(listActivity, fileUri)
}
} catch (e: IOException) {
showSnackbar(e.toString())
e.printStackTrace()
}
}

override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import software.mdev.bookstracker.ui.bookslist.viewmodel.BooksViewModel
import android.content.Intent
import android.net.Uri
import android.os.Build
import software.mdev.bookstracker.other.Backup


class SettingsFragment : PreferenceFragmentCompat(), OnSharedPreferenceChangeListener {
Expand All @@ -34,6 +35,7 @@ class SettingsFragment : PreferenceFragmentCompat(), OnSharedPreferenceChangeLis
val preferenceChangelog = findPreference<Preference>(Constants.KEY_CHANGELOG)
val preferenceBackup = findPreference<Preference>(Constants.KEY_BACKUP)
val preferenceFeedback = findPreference<Preference>(Constants.KEY_FEEDBACK)
val preferenceCsvImport = findPreference<Preference>(Constants.KEY_CSV_IMPORT)

if (preferenceCheckForUpdates != null) {
val updater = Updater()
Expand Down Expand Up @@ -73,6 +75,13 @@ class SettingsFragment : PreferenceFragmentCompat(), OnSharedPreferenceChangeLis
true
}
}

if (preferenceCsvImport != null) {
preferenceCsvImport.onPreferenceClickListener = Preference.OnPreferenceClickListener {
Backup().runImporterCSV(activity as ListActivity)
true
}
}
}

override fun onResume() {
Expand Down
10 changes: 10 additions & 0 deletions app/src/main/res/drawable/ic_iconscout_file_import_24.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#0092E4"
android:pathData="M11,20H6a1,1 0,0 1,-1 -1V5A1,1 0,0 1,6 4h5V7a3,3 0,0 0,3 3h3v2a1,1 0,0 0,2 0V9s0,0 0,-0.06a1.31,1.31 0,0 0,-0.06 -0.27l0,-0.09a1.32,1.32 0,0 0,-0.19 -0.29h0l-6,-6h0a1.32,1.32 0,0 0,-0.29 -0.19,0.32 0.32,0 0,0 -0.09,0L12.06,2H6A3,3 0,0 0,3 5V19a3,3 0,0 0,3 3h5a1,1 0,0 0,0 -2ZM13,5.41 L15.59,8H14a1,1 0,0 1,-1 -1ZM19,15H13.41l1.3,-1.29a1,1 0,0 0,-1.42 -1.42l-3,3a1.15,1.15 0,0 0,-0.21 0.33,1 1,0 0,0 0,0.76 0.93,0.93 0,0 0,0.21 0.33l3,3a1,1 0,0 0,1.42 0,1 1,0 0,0 0,-1.42L13.41,17H19a1,1 0,0 0,0 -2Z" />
</vector>
3 changes: 3 additions & 0 deletions app/src/main/res/values-cs-rCZ/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,7 @@
<string name="changelog_1_14_0_h">Fixed backup in F-Droid variant.</string>
<string name="changelog_1_14_2_a">Improved backup for bigger libraries.</string>
<string name="changelog_1_14_2_b">Improved translations.</string>
<string name="import_csv_summary">Migrate from other reading apps</string>
<string name="import_csv_title">Import books from CSV</string>
<string name="csv_import_failure">CSV import failed</string>
</resources>
3 changes: 3 additions & 0 deletions app/src/main/res/values-da-rDK/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,7 @@
<string name="changelog_1_14_0_h">Fast backup i F-Droid variant.</string>
<string name="changelog_1_14_2_a">Forbedret backup af større biblioteker.</string>
<string name="changelog_1_14_2_b">Forbedrede oversættelser.</string>
<string name="import_csv_summary">Migrate from other reading apps</string>
<string name="import_csv_title">Import books from CSV</string>
<string name="csv_import_failure">CSV import failed</string>
</resources>
3 changes: 3 additions & 0 deletions app/src/main/res/values-de-rDE/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,7 @@
<string name="changelog_1_14_0_h">Fehlerkorrektur in F-Droid Variante.</string>
<string name="changelog_1_14_2_a">Verbessertes Backup für größere Bibliotheken.</string>
<string name="changelog_1_14_2_b">Verbesserte Übersetzungen.</string>
<string name="import_csv_summary">Migrate from other reading apps</string>
<string name="import_csv_title">Import books from CSV</string>
<string name="csv_import_failure">CSV import failed</string>
</resources>
3 changes: 3 additions & 0 deletions app/src/main/res/values-el-rGR/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,7 @@
<string name="changelog_1_14_0_h">Fixed backup in F-Droid variant.</string>
<string name="changelog_1_14_2_a">Improved backup for bigger libraries.</string>
<string name="changelog_1_14_2_b">Improved translations.</string>
<string name="import_csv_summary">Migrate from other reading apps</string>
<string name="import_csv_title">Import books from CSV</string>
<string name="csv_import_failure">CSV import failed</string>
</resources>
3 changes: 3 additions & 0 deletions app/src/main/res/values-es-rES/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,7 @@
<string name="changelog_1_14_0_h">Copia de seguridad fija en la variante F-Droid.</string>
<string name="changelog_1_14_2_a">Copia de seguridad mejorada para bibliotecas más grandes.</string>
<string name="changelog_1_14_2_b">Traducciones mejoradas.</string>
<string name="import_csv_summary">Migrate from other reading apps</string>
<string name="import_csv_title">Import books from CSV</string>
<string name="csv_import_failure">CSV import failed</string>
</resources>
3 changes: 3 additions & 0 deletions app/src/main/res/values-fi-rFI/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,7 @@
<string name="changelog_1_14_0_h">Fixed backup in F-Droid variant.</string>
<string name="changelog_1_14_2_a">Improved backup for bigger libraries.</string>
<string name="changelog_1_14_2_b">Improved translations.</string>
<string name="import_csv_summary">Migrate from other reading apps</string>
<string name="import_csv_title">Import books from CSV</string>
<string name="csv_import_failure">CSV import failed</string>
</resources>
3 changes: 3 additions & 0 deletions app/src/main/res/values-fr-rFR/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,7 @@
<string name="changelog_1_14_0_h">Sauvegarde réparée dans la variante F-Droid.</string>
<string name="changelog_1_14_2_a">Amélioration de la sauvegarde pour les bibliothèques plus grandes.</string>
<string name="changelog_1_14_2_b">Traductions améliorées.</string>
<string name="import_csv_summary">Migrate from other reading apps</string>
<string name="import_csv_title">Import books from CSV</string>
<string name="csv_import_failure">CSV import failed</string>
</resources>
3 changes: 3 additions & 0 deletions app/src/main/res/values-hu-rHU/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,7 @@
<string name="changelog_1_14_0_h">Fixed backup in F-Droid variant.</string>
<string name="changelog_1_14_2_a">Improved backup for bigger libraries.</string>
<string name="changelog_1_14_2_b">Improved translations.</string>
<string name="import_csv_summary">Migrate from other reading apps</string>
<string name="import_csv_title">Import books from CSV</string>
<string name="csv_import_failure">CSV import failed</string>
</resources>
3 changes: 3 additions & 0 deletions app/src/main/res/values-it-rIT/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,7 @@
<string name="changelog_1_14_0_h">Backup fisso nella variante F-Droid.</string>
<string name="changelog_1_14_2_a">Backup migliorato per librerie più grandi.</string>
<string name="changelog_1_14_2_b">Traduzioni migliorate.</string>
<string name="import_csv_summary">Migrate from other reading apps</string>
<string name="import_csv_title">Import books from CSV</string>
<string name="csv_import_failure">CSV import failed</string>
</resources>
3 changes: 3 additions & 0 deletions app/src/main/res/values-nl-rNL/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,7 @@
<string name="changelog_1_14_0_h">Fixed backup in F-Droid variant.</string>
<string name="changelog_1_14_2_a">Improved backup for bigger libraries.</string>
<string name="changelog_1_14_2_b">Improved translations.</string>
<string name="import_csv_summary">Migrate from other reading apps</string>
<string name="import_csv_title">Import books from CSV</string>
<string name="csv_import_failure">CSV import failed</string>
</resources>
3 changes: 3 additions & 0 deletions app/src/main/res/values-no-rNO/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,7 @@
<string name="changelog_1_14_0_h">Fixed backup in F-Droid variant.</string>
<string name="changelog_1_14_2_a">Improved backup for bigger libraries.</string>
<string name="changelog_1_14_2_b">Improved translations.</string>
<string name="import_csv_summary">Migrate from other reading apps</string>
<string name="import_csv_title">Import books from CSV</string>
<string name="csv_import_failure">CSV import failed</string>
</resources>
3 changes: 3 additions & 0 deletions app/src/main/res/values-pl-rPL/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,7 @@
<string name="changelog_1_14_0_h">Naprawiono kopię zapasową w wariancie F-Droid.</string>
<string name="changelog_1_14_2_a">Ulepszono kopię zapasową dla większych bilbiotek.</string>
<string name="changelog_1_14_2_b">Ulepszono tłumaczenia.</string>
<string name="import_csv_summary">Migrate from other reading apps</string>
<string name="import_csv_title">Import books from CSV</string>
<string name="csv_import_failure">CSV import failed</string>
</resources>
3 changes: 3 additions & 0 deletions app/src/main/res/values-pt-rBR/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,7 @@
<string name="changelog_1_14_0_h">Fixed backup in F-Droid variant.</string>
<string name="changelog_1_14_2_a">Improved backup for bigger libraries.</string>
<string name="changelog_1_14_2_b">Improved translations.</string>
<string name="import_csv_summary">Migrate from other reading apps</string>
<string name="import_csv_title">Import books from CSV</string>
<string name="csv_import_failure">CSV import failed</string>
</resources>
3 changes: 3 additions & 0 deletions app/src/main/res/values-pt-rPT/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,7 @@
<string name="changelog_1_14_0_h">Fixed backup in F-Droid variant.</string>
<string name="changelog_1_14_2_a">Improved backup for bigger libraries.</string>
<string name="changelog_1_14_2_b">Improved translations.</string>
<string name="import_csv_summary">Migrate from other reading apps</string>
<string name="import_csv_title">Import books from CSV</string>
<string name="csv_import_failure">CSV import failed</string>
</resources>
3 changes: 3 additions & 0 deletions app/src/main/res/values-ro-rRO/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,7 @@
<string name="changelog_1_14_0_h">Fixed backup in F-Droid variant.</string>
<string name="changelog_1_14_2_a">Improved backup for bigger libraries.</string>
<string name="changelog_1_14_2_b">Improved translations.</string>
<string name="import_csv_summary">Migrate from other reading apps</string>
<string name="import_csv_title">Import books from CSV</string>
<string name="csv_import_failure">CSV import failed</string>
</resources>
3 changes: 3 additions & 0 deletions app/src/main/res/values-ru-rRU/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,7 @@
<string name="changelog_1_14_0_h">Fixed backup in F-Droid variant.</string>
<string name="changelog_1_14_2_a">Improved backup for bigger libraries.</string>
<string name="changelog_1_14_2_b">Improved translations.</string>
<string name="import_csv_summary">Migrate from other reading apps</string>
<string name="import_csv_title">Import books from CSV</string>
<string name="csv_import_failure">CSV import failed</string>
</resources>
3 changes: 3 additions & 0 deletions app/src/main/res/values-sr-rSP/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,7 @@
<string name="changelog_1_14_0_h">Fixed backup in F-Droid variant.</string>
<string name="changelog_1_14_2_a">Improved backup for bigger libraries.</string>
<string name="changelog_1_14_2_b">Improved translations.</string>
<string name="import_csv_summary">Migrate from other reading apps</string>
<string name="import_csv_title">Import books from CSV</string>
<string name="csv_import_failure">CSV import failed</string>
</resources>
3 changes: 3 additions & 0 deletions app/src/main/res/values-sv-rSE/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,7 @@
<string name="changelog_1_14_0_h">Fixed backup in F-Droid variant.</string>
<string name="changelog_1_14_2_a">Improved backup for bigger libraries.</string>
<string name="changelog_1_14_2_b">Improved translations.</string>
<string name="import_csv_summary">Migrate from other reading apps</string>
<string name="import_csv_title">Import books from CSV</string>
<string name="csv_import_failure">CSV import failed</string>
</resources>
3 changes: 3 additions & 0 deletions app/src/main/res/values-ta-rIN/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,7 @@
<string name="changelog_1_14_0_h">Fixed backup in F-Droid variant.</string>
<string name="changelog_1_14_2_a">Improved backup for bigger libraries.</string>
<string name="changelog_1_14_2_b">Improved translations.</string>
<string name="import_csv_summary">Migrate from other reading apps</string>
<string name="import_csv_title">Import books from CSV</string>
<string name="csv_import_failure">CSV import failed</string>
</resources>
3 changes: 3 additions & 0 deletions app/src/main/res/values-tr-rTR/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,7 @@
<string name="changelog_1_14_0_h">Fixed backup in F-Droid variant.</string>
<string name="changelog_1_14_2_a">Improved backup for bigger libraries.</string>
<string name="changelog_1_14_2_b">Improved translations.</string>
<string name="import_csv_summary">Migrate from other reading apps</string>
<string name="import_csv_title">Import books from CSV</string>
<string name="csv_import_failure">CSV import failed</string>
</resources>
3 changes: 3 additions & 0 deletions app/src/main/res/values-uk-rUA/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,7 @@
<string name="changelog_1_14_0_h">Fixed backup in F-Droid variant.</string>
<string name="changelog_1_14_2_a">Improved backup for bigger libraries.</string>
<string name="changelog_1_14_2_b">Improved translations.</string>
<string name="import_csv_summary">Migrate from other reading apps</string>
<string name="import_csv_title">Import books from CSV</string>
<string name="csv_import_failure">CSV import failed</string>
</resources>
3 changes: 3 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -327,4 +327,7 @@
<string name="changelog_1_14_0_h">Fixed backup in F-Droid variant.</string>
<string name="changelog_1_14_2_a">Improved backup for bigger libraries.</string>
<string name="changelog_1_14_2_b">Improved translations.</string>
<string name="import_csv_summary">Migrate from other reading apps</string>
<string name="import_csv_title">Import books from CSV</string>
<string name="csv_import_failure">CSV import failed</string>
</resources>
6 changes: 6 additions & 0 deletions app/src/main/res/xml/preferences.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@
android:summary="@string/backup_summary"
android:title="@string/backup_title" />

<Preference
android:icon="@drawable/ic_iconscout_file_import_24"
android:key="KEY_CSV_IMPORT"
android:summary="@string/import_csv_summary"
android:title="@string/import_csv_title" />

<PreferenceCategory
android:key="customization"
android:title="@string/customization">
Expand Down

0 comments on commit 4e9bc35

Please sign in to comment.