Explorar el Código

Added export books option

Vadik Sirekanyan hace 2 años
padre
commit
4e792face4

+ 2 - 7
app/src/main/java/org/sirekanyan/knigopis/common/functions/IntentFactory.kt

@@ -1,16 +1,11 @@
 package org.sirekanyan.knigopis.common.functions
 
-import android.content.Context
 import android.content.Intent
-import org.sirekanyan.knigopis.R
 
 private const val TEXT_MIME_TYPE = "text/plain"
 
-fun Context.createProfileShareIntent(text: String) =
-    createTextShareIntent(text, getString(R.string.profile_title_share))
-
-private fun createTextShareIntent(text: String, title: String): Intent =
+fun createTextShareIntent(text: String): Intent =
     Intent(Intent.ACTION_SEND)
         .setType(TEXT_MIME_TYPE)
         .putExtra(Intent.EXTRA_TEXT, text)
-        .let { Intent.createChooser(it, title) }
+        .let { Intent.createChooser(it, null) }

+ 7 - 1
app/src/main/java/org/sirekanyan/knigopis/dependency/profile.kt

@@ -4,7 +4,13 @@ import org.sirekanyan.knigopis.common.extensions.app
 import org.sirekanyan.knigopis.feature.profile.*
 
 fun ProfileActivity.providePresenter(): ProfilePresenter {
-    val interactor = ProfileInteractorImpl(app.endpoint, app.bookRepository, app.tokenStorage)
+    val interactor =
+        ProfileInteractorImpl(
+            app.endpoint,
+            app.bookRepository,
+            app.tokenStorage,
+            ExportFormatter(app.resourceProvider),
+        )
     return ProfilePresenterImpl(this, interactor).also { presenter ->
         presenter.view = ProfileViewImpl(binding, presenter)
     }

+ 26 - 0
app/src/main/java/org/sirekanyan/knigopis/feature/profile/ExportFormatter.kt

@@ -0,0 +1,26 @@
+package org.sirekanyan.knigopis.feature.profile
+
+import org.sirekanyan.knigopis.common.android.ResourceProvider
+import org.sirekanyan.knigopis.common.extensions.getFullTitleString
+import org.sirekanyan.knigopis.model.BookDataModel
+import org.sirekanyan.knigopis.model.DateModel
+
+class ExportFormatter(private val resources: ResourceProvider) {
+
+    fun formatBooksForExport(books: List<BookDataModel>): String =
+        books.withIndex().joinToString("\n\n") { (index, book) -> formatBook(index, book) }
+
+    private fun formatBook(index: Int, book: BookDataModel): String {
+        val title = "${index + 1}. ${resources.getFullTitleString(book.title, book.author)}"
+        val details = if (book.isFinished) formatDate(book.date) else "${book.priority}%"
+        return listOf(title, details, book.notes).filter(String::isNotBlank).joinToString("\n")
+    }
+
+    private fun formatDate(d: DateModel): String =
+        buildString {
+            if (d.year.isBlank()) return toString() else append(d.year)
+            if (d.month.isBlank()) return toString() else append('-' + d.month.padStart(2, '0'))
+            if (d.day.isBlank()) return toString() else append('-' + d.day.padStart(2, '0'))
+        }
+
+}

+ 3 - 3
app/src/main/java/org/sirekanyan/knigopis/feature/profile/ProfileActivity.kt

@@ -4,7 +4,7 @@ import android.content.Context
 import android.content.Intent
 import android.os.Bundle
 import org.sirekanyan.knigopis.common.BaseActivity
-import org.sirekanyan.knigopis.common.functions.createProfileShareIntent
+import org.sirekanyan.knigopis.common.functions.createTextShareIntent
 import org.sirekanyan.knigopis.databinding.ProfileActivityBinding
 import org.sirekanyan.knigopis.dependency.providePresenter
 
@@ -31,8 +31,8 @@ class ProfileActivity : BaseActivity(), ProfilePresenter.Router {
         presenter.stop()
     }
 
-    override fun shareProfile(profileUrl: String) {
-        startActivity(createProfileShareIntent(profileUrl))
+    override fun shareText(content: String) {
+        startActivity(createTextShareIntent(content))
     }
 
     override fun exit() {

+ 7 - 0
app/src/main/java/org/sirekanyan/knigopis/feature/profile/ProfileInteractor.kt

@@ -19,6 +19,7 @@ interface ProfileInteractor {
 
     fun getProfile(): Single<ProfileModel>
     fun getBooks(): Observable<BookDataModel>
+    fun getBooksForExport(): Single<String>
     fun updateProfile(profile: ProfileModel): Completable
     fun logout()
 
@@ -28,6 +29,7 @@ class ProfileInteractorImpl(
     private val api: Endpoint,
     private val bookRepository: BookRepository,
     private val tokenStorage: TokenStorage,
+    private val exportFormatter: ExportFormatter,
 ) : ProfileInteractor {
 
     override fun getProfile(): Single<ProfileModel> =
@@ -49,6 +51,11 @@ class ProfileInteractorImpl(
             .map { (book) -> book }
             .io2main()
 
+    override fun getBooksForExport(): Single<String> =
+        bookRepository.findCached().toSingle(listOf()).map {
+            exportFormatter.formatBooksForExport(it.filterIsInstance<BookDataModel>())
+        }
+
     override fun updateProfile(profile: ProfileModel): Completable =
         api.updateProfile(profile.id, profile.toProfile())
             .io2main()

+ 16 - 2
app/src/main/java/org/sirekanyan/knigopis/feature/profile/ProfilePresenter.kt

@@ -16,7 +16,7 @@ interface ProfilePresenter : Presenter {
     fun back()
 
     interface Router {
-        fun shareProfile(profileUrl: String)
+        fun shareText(content: String)
         fun exit()
     }
 
@@ -72,7 +72,21 @@ class ProfilePresenterImpl(
     }
 
     override fun onShareOptionClicked() {
-        profile?.shareUrl?.let(router::shareProfile)
+        profile?.shareUrl?.let(router::shareText)
+    }
+
+    override fun onExportOptionClicked() {
+        interactor.getBooksForExport()
+            .bind({ content ->
+                if (content.isBlank()) {
+                    view.toast(R.string.profile_export_empty)
+                } else {
+                    router.shareText(content)
+                }
+            }, {
+                view.toast(R.string.profile_export_error)
+                logError("cannot export books", it)
+            })
     }
 
     override fun onLogoutOptionClicked() {

+ 5 - 0
app/src/main/java/org/sirekanyan/knigopis/feature/profile/ProfileView.kt

@@ -34,6 +34,7 @@ interface ProfileView : CommonView<ProfileActivityBinding> {
         fun onEditOptionClicked()
         fun onSaveOptionClicked(nickname: String)
         fun onShareOptionClicked()
+        fun onExportOptionClicked()
         fun onLogoutOptionClicked()
     }
 
@@ -150,6 +151,10 @@ class ProfileViewImpl(
                     callbacks.onShareOptionClicked()
                     true
                 }
+                R.id.option_export_profile -> {
+                    callbacks.onExportOptionClicked()
+                    true
+                }
                 R.id.option_logout_profile -> {
                     callbacks.onLogoutOptionClicked()
                     true

+ 5 - 0
app/src/main/res/menu/profile_menu.xml

@@ -15,6 +15,11 @@
         android:title="@string/profile.option.share"
         app:showAsAction="never" />
 
+    <item
+        android:id="@+id/option_export_profile"
+        android:title="@string/profile.option.export"
+        app:showAsAction="never" />
+
     <item
         android:id="@+id/option_logout_profile"
         android:title="@string/profile.option.logout"

+ 3 - 1
app/src/main/res/values-ru/strings.xml

@@ -69,9 +69,11 @@
     <string name="profile.option.edit">Изменить</string>
     <string name="profile.option.save">Сохранить</string>
     <string name="profile.option.share">Поделиться</string>
+    <string name="profile.option.export">Экспорт"</string>
     <string name="profile.option.logout">Выйти</string>
     <string name="profile.error.save">Не удалось обновить имя</string>
-    <string name="profile.title.share">Отправить ссылку на профиль</string>
+    <string name="profile.export.empty">Нет книг для экспорта</string>
+    <string name="profile.export.error">Ошибка при экспорте</string>
 
     <!-- 🏠 books tab -->
     <string name="books.error.empty">У вас пока нет книг</string>

+ 3 - 1
app/src/main/res/values/strings.xml

@@ -68,9 +68,11 @@
     <string name="profile.option.edit">Edit</string>
     <string name="profile.option.save">Save</string>
     <string name="profile.option.share">Share</string>
+    <string name="profile.option.export">Export</string>
     <string name="profile.option.logout">Logout</string>
     <string name="profile.error.save">Cannot update profile</string>
-    <string name="profile.title.share">Share your profile</string>
+    <string name="profile.export.empty">Nothing to export</string>
+    <string name="profile.export.error">Cannot export books</string>
 
     <!-- 🏠 books tab -->
     <string name="books.error.empty">You don\'t have any books</string>