Skip to content

Commit

Permalink
Merge pull request #186 from xizzhu/consolidate-veses-for-sharing
Browse files Browse the repository at this point in the history
Allowed consolidating verses for sharing
  • Loading branch information
xizzhu committed May 26, 2020
2 parents a520e14 + 153713d commit c02fd22
Show file tree
Hide file tree
Showing 15 changed files with 287 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ class AndroidSettingsStorageTest : BaseSqliteTest() {
@Test
fun testSaveThenRead() {
runBlocking {
androidSettingsStorage.saveSettings(Settings(false, true, 2, false, false))
androidSettingsStorage.saveSettings(Settings(false, true, 2, false, false, false))

val expected = Settings(false, true, 2, false, false)
val expected = Settings(false, true, 2, false, false, false)
val actual = androidSettingsStorage.readSettings()
assertEquals(expected, actual)
}
Expand All @@ -59,10 +59,10 @@ class AndroidSettingsStorageTest : BaseSqliteTest() {
@Test
fun testSaveOverrideThenRead() {
runBlocking {
androidSettingsStorage.saveSettings(Settings(true, false, 3, true, true))
androidSettingsStorage.saveSettings(Settings(false, true, 2, false, false))
androidSettingsStorage.saveSettings(Settings(true, false, 3, true, true, true))
androidSettingsStorage.saveSettings(Settings(false, true, 2, false, false, false))

val expected = Settings(false, true, 2, false, false)
val expected = Settings(false, true, 2, false, false, false)
val actual = androidSettingsStorage.readSettings()
assertEquals(expected, actual)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ import kotlinx.coroutines.flow.Flow
import me.xizzhu.android.joshua.core.repository.SettingsRepository

data class Settings(val keepScreenOn: Boolean, val nightModeOn: Boolean, val fontSizeScale: Int,
val simpleReadingModeOn: Boolean, val hideSearchButton: Boolean) {
val simpleReadingModeOn: Boolean, val hideSearchButton: Boolean,
val consolidateVersesForSharing: Boolean) {
companion object {
val DEFAULT = Settings(true, false, 2, false, false)
val DEFAULT = Settings(true, false, 2, false, false, false)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,15 @@ class AndroidSettingsStorage(private val androidDatabase: AndroidDatabase) : Loc
Pair(MetadataDao.KEY_NIGHT_MODE_ON, Settings.DEFAULT.nightModeOn.toString()),
Pair(MetadataDao.KEY_FONT_SIZE_SCALE, Settings.DEFAULT.fontSizeScale.toString()),
Pair(MetadataDao.KEY_SIMPLE_READING_MODE_ON, Settings.DEFAULT.simpleReadingModeOn.toString()),
Pair(MetadataDao.KEY_HIDE_SEARCH_BUTTON, Settings.DEFAULT.hideSearchButton.toString())
Pair(MetadataDao.KEY_HIDE_SEARCH_BUTTON, Settings.DEFAULT.hideSearchButton.toString()),
Pair(MetadataDao.KEY_CONSOLIDATE_VERSES_FOR_SHARING, Settings.DEFAULT.consolidateVersesForSharing.toString())
))
return@withContext Settings(values.getValue(MetadataDao.KEY_SCREEN_ON).toBoolean(),
values.getValue(MetadataDao.KEY_NIGHT_MODE_ON).toBoolean(),
values.getValue(MetadataDao.KEY_FONT_SIZE_SCALE).toInt(),
values.getValue(MetadataDao.KEY_SIMPLE_READING_MODE_ON).toBoolean(),
values.getValue(MetadataDao.KEY_HIDE_SEARCH_BUTTON).toBoolean()
values.getValue(MetadataDao.KEY_HIDE_SEARCH_BUTTON).toBoolean(),
values.getValue(MetadataDao.KEY_CONSOLIDATE_VERSES_FOR_SHARING).toBoolean()
)
}

Expand All @@ -47,7 +49,8 @@ class AndroidSettingsStorage(private val androidDatabase: AndroidDatabase) : Loc
Pair(MetadataDao.KEY_NIGHT_MODE_ON, settings.nightModeOn.toString()),
Pair(MetadataDao.KEY_FONT_SIZE_SCALE, settings.fontSizeScale.toString()),
Pair(MetadataDao.KEY_SIMPLE_READING_MODE_ON, settings.simpleReadingModeOn.toString()),
Pair(MetadataDao.KEY_HIDE_SEARCH_BUTTON, settings.hideSearchButton.toString())
Pair(MetadataDao.KEY_HIDE_SEARCH_BUTTON, settings.hideSearchButton.toString()),
Pair(MetadataDao.KEY_CONSOLIDATE_VERSES_FOR_SHARING, settings.consolidateVersesForSharing.toString())
))
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class MetadataDao(sqliteHelper: SQLiteOpenHelper) {
const val KEY_NIGHT_MODE_ON = "nightModeOn"
const val KEY_SIMPLE_READING_MODE_ON = "simpleReadingModeOn"
const val KEY_HIDE_SEARCH_BUTTON = "hideSearchButton"
const val KEY_CONSOLIDATE_VERSES_FOR_SHARING = "consolidateVersesForSharing"
const val KEY_FONT_SIZE_SCALE = "fontSizeScale"
const val KEY_TRANSLATION_LIST_REFRESH_TIMESTAMP = "translationListRefreshTimestamp"
const val KEY_BOOKMARKS_SORT_ORDER = "bookmarksSortOrder"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package me.xizzhu.android.joshua.reading.verse

import android.content.DialogInterface
import android.os.Looper
import android.view.Menu
import android.view.MenuItem
import androidx.annotation.UiThread
Expand Down Expand Up @@ -76,33 +77,43 @@ class VersePresenter(
private fun copyToClipBoard() {
if (selectedVerses.isEmpty()) return

try {
activity.copyToClipBoard(
"${currentTranslationViewData.currentTranslation} ${currentVerseIndexViewData.bookName}",
selectedVerses.toStringForSharing(currentVerseIndexViewData.bookName)
)
activity.toast(R.string.toast_verses_copied)
} catch (e: Exception) {
Log.e(tag, "Failed to copy", e)
activity.toast(R.string.toast_unknown_error)
} finally {
actionMode?.finish()
coroutineScope.launch {
try {
activity.copyToClipBoard(
"${currentTranslationViewData.currentTranslation} ${currentVerseIndexViewData.bookName}",
selectedVerses.toStringForSharing(
currentVerseIndexViewData.bookName,
viewModel.settings().first().consolidateVersesForSharing
)
)
activity.toast(R.string.toast_verses_copied)
} catch (e: Exception) {
Log.e(tag, "Failed to copy", e)
activity.toast(R.string.toast_unknown_error)
} finally {
actionMode?.finish()
}
}
}

private fun share() {
if (selectedVerses.isEmpty()) return

try {
activity.share(
activity.getString(R.string.text_share_with),
selectedVerses.toStringForSharing(currentVerseIndexViewData.bookName)
)
} catch (e: Exception) {
Log.e(tag, "Failed to share", e)
activity.toast(R.string.toast_unknown_error)
} finally {
actionMode?.finish()
coroutineScope.launch {
try {
activity.share(
activity.getString(R.string.text_share_with),
selectedVerses.toStringForSharing(
currentVerseIndexViewData.bookName,
viewModel.settings().first().consolidateVersesForSharing
)
)
} catch (e: Exception) {
Log.e(tag, "Failed to share", e)
activity.toast(R.string.toast_unknown_error)
} finally {
actionMode?.finish()
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,96 @@ fun List<Verse>.toVerseItems(bookmarks: List<Bookmark>, highlights: List<Highlig
return items
}

fun Collection<Verse>.toStringForSharing(bookName: String): String {
val stringBuilder = StringBuilder()
sortedBy { verse ->
fun Collection<Verse>.toStringForSharing(bookName: String, consolidateVerses: Boolean): String {
val sortedVerses = sortedBy { verse ->
val verseIndex = verse.verseIndex
verseIndex.bookIndex * 100000 + verseIndex.chapterIndex * 1000 + verseIndex.verseIndex
}.forEach { verse -> stringBuilder.append(verse, bookName) }
}

if (!consolidateVerses || size == 1) {
return StringBuilder().apply {
sortedVerses.forEach { verse -> append(verse, bookName) }
}.toString()
}

// format (without parallel):
// <book name> <chapter index>:<start verse index>-<end verse index>
// <verse text>
// <book name> <chapter index>:<verse index>
// <verse text>
//
// format (with parallel):
// <book name> <chapter index>:<start verse index>-<end verse index>
// <primary translation>: <verse text>
// <parallel translation 1>: <verse text>
// <parallel translation 2>: <verse text>
// <book name> <chapter index>:<verse index>
// <primary translation>: <verse text>
// <parallel translation 1>: <verse text>
// <parallel translation 2>: <verse text>

// step 1: find all start - end verse index pairs
val verseGroups = arrayListOf<Pair<Int, Int>>()
sortedVerses.forEach { verse ->
val lastVerseIndexPair = verseGroups.lastOrNull()
if (lastVerseIndexPair != null && lastVerseIndexPair.second + 1 == verse.verseIndex.verseIndex) {
verseGroups[verseGroups.size - 1] = lastVerseIndexPair.copy(second = verse.verseIndex.verseIndex)
} else {
verseGroups.add(Pair(verse.verseIndex.verseIndex, verse.verseIndex.verseIndex))
}
}

// step 2: build the string for sharing
val stringBuilder = StringBuilder()

var currentVerseGroupIndex = 0
val parallelVersesBuilder = Array(sortedVerses.first().parallel.size) { StringBuilder() }
sortedVerses.forEach { verse ->
val currentVerseGroup = verseGroups[currentVerseGroupIndex]

// start of the verse group
if (verse.verseIndex.verseIndex == currentVerseGroup.first) {
if (stringBuilder.isNotEmpty()) stringBuilder.append("\n\n")

stringBuilder.append(bookName).append(' ')
.append(verse.verseIndex.chapterIndex + 1).append(':').append(verse.verseIndex.verseIndex + 1)
if (currentVerseGroup.first < currentVerseGroup.second) {
stringBuilder.append('-').append(currentVerseGroup.second + 1)
}
stringBuilder.append('\n')

if (verse.parallel.isNotEmpty()) {
stringBuilder.append(verse.text.translationShortName).append(": ")

verse.parallel.forEachIndexed { index, parallel ->
with(parallelVersesBuilder[index]) {
clear()
append(parallel.translationShortName).append(": ")
}
}
}
}

if (verse.verseIndex.verseIndex > currentVerseGroup.first) stringBuilder.append(' ')
stringBuilder.append(verse.text.text)

verse.parallel.forEachIndexed { index, parallel ->
with(parallelVersesBuilder[index]) {
if (verse.verseIndex.verseIndex > currentVerseGroup.first) append(' ')
append(parallel.text)
}
}

// end of the verse group
if (verse.verseIndex.verseIndex == currentVerseGroup.second) {
parallelVersesBuilder.forEach { parallelBuilder ->
stringBuilder.append('\n').append(parallelBuilder)
}

currentVerseGroupIndex++
}
}

return stringBuilder.toString()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ class SettingsActivity : BaseActivity() {
SettingsViewHolder(
findViewById(R.id.display), findViewById(R.id.font_size), findViewById(R.id.keep_screen_on),
findViewById(R.id.night_mode_on), findViewById(R.id.reading), findViewById(R.id.simple_reading_mode),
findViewById(R.id.hide_search_button), findViewById(R.id.backup_restore), findViewById(R.id.backup),
findViewById(R.id.hide_search_button), findViewById(R.id.consolidated_sharing),
findViewById(R.id.backup_restore), findViewById(R.id.backup),
findViewById(R.id.restore), findViewById(R.id.about), findViewById(R.id.rate), findViewById(R.id.version)
)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ import kotlin.math.roundToInt
data class SettingsViewHolder(val display: SettingSectionHeader, val fontSize: SettingButton,
val keepScreenOn: SwitchCompat, val nightModeOn: SwitchCompat,
val reading: SettingSectionHeader, val simpleReadingMode: SwitchCompat,
val hideSearchButton: SwitchCompat, val backupRestore: SettingSectionHeader,
val hideSearchButton: SwitchCompat, val consolidatedSharing: SwitchCompat,
val backupRestore: SettingSectionHeader,
val backup: SettingButton, val restore: SettingButton, val about: SettingSectionHeader,
val rate: SettingButton, val version: SettingButton) : ViewHolder

Expand Down Expand Up @@ -95,6 +96,8 @@ class SettingsPresenter(

viewHolder.hideSearchButton.setOnCheckedChangeListener { _, isChecked -> saveHideSearchButton(isChecked) }

viewHolder.consolidatedSharing.setOnCheckedChangeListener { _, isChecked -> saveConsolidateVersesForSharing(isChecked) }

viewHolder.backup.setOnClickListener {
try {
activity.startActivityForResult(
Expand Down Expand Up @@ -197,6 +200,18 @@ class SettingsPresenter(
}
}

private fun saveConsolidateVersesForSharing(consolidateVerses: Boolean) {
coroutineScope.launch {
try {
viewModel.saveConsolidateVersesForSharing(consolidateVerses)
} catch (e: Exception) {
Log.e(tag, "Failed to save consolidating verses for sharing", e)
activity.dialog(true, R.string.dialog_update_settings_error,
DialogInterface.OnClickListener { _, _ -> saveConsolidateVersesForSharing(consolidateVerses) })
}
}
}

fun onCreateDocumentForBackup(resultCode: Int, data: Intent?) {
if (resultCode != Activity.RESULT_OK) return
data?.data?.let { backup(it) } ?: activity.toast(R.string.toast_unknown_error)
Expand Down Expand Up @@ -318,6 +333,7 @@ class SettingsPresenter(
nightModeOn.setTextColor(primaryTextColor)
simpleReadingMode.setTextColor(primaryTextColor)
hideSearchButton.setTextColor(primaryTextColor)
consolidatedSharing.setTextColor(primaryTextColor)
backup.setTextColor(primaryTextColor, secondaryTextColor)
restore.setTextColor(primaryTextColor, secondaryTextColor)
rate.setTextColor(primaryTextColor, secondaryTextColor)
Expand Down Expand Up @@ -347,6 +363,7 @@ class SettingsPresenter(
reading.setTextSize(bodyTextSize.roundToInt())
simpleReadingMode.setTextSize(TypedValue.COMPLEX_UNIT_PX, bodyTextSize)
hideSearchButton.setTextSize(TypedValue.COMPLEX_UNIT_PX, bodyTextSize)
consolidatedSharing.setTextSize(TypedValue.COMPLEX_UNIT_PX, bodyTextSize)
backupRestore.setTextSize(bodyTextSize.roundToInt())
backup.setTextSize(bodyTextSize.roundToInt(), captionTextSize.roundToInt())
restore.setTextSize(bodyTextSize.roundToInt(), captionTextSize.roundToInt())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,14 @@ class SettingsViewModel(settingsManager: SettingsManager,
}
}

suspend fun saveConsolidateVersesForSharing(consolidateVerses: Boolean) {
currentSettings().let { current ->
if (consolidateVerses != current.consolidateVersesForSharing) {
settingsManager.saveSettings(current.copy(consolidateVersesForSharing = consolidateVerses))
}
}
}

suspend fun backup(to: OutputStream) {
to.write(backupManager.prepareForBackup().toByteArray(Charsets.UTF_8))
}
Expand Down
10 changes: 10 additions & 0 deletions app/src/main/res/layout/activity_settings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,16 @@
android:paddingEnd="@dimen/padding"
android:text="@string/settings_title_hide_search_button" />

<androidx.appcompat.widget.SwitchCompat
android:id="@+id/consolidated_sharing"
style="@style/Text.Body"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="@dimen/item_height"
android:paddingStart="@dimen/padding"
android:paddingEnd="@dimen/padding"
android:text="@string/settings_title_consolidated_sharing" />

<me.xizzhu.android.joshua.settings.widgets.SettingSectionHeader
android:id="@+id/backup_restore"
android:layout_width="match_parent"
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
<string name="settings_header_reading">Reading</string>
<string name="settings_title_simple_reading">Simple reading</string>
<string name="settings_title_hide_search_button">Hide search button</string>
<string name="settings_title_consolidated_sharing">Consolidate verses when sharing</string>
<string name="settings_header_backup_restore">Backup &amp; restore</string>
<string name="settings_title_backup">Backup all my data</string>
<string name="settings_title_restore">Restore</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class SettingsRepositoryTest : BaseUnitTest() {

@Test
fun testObserveInitialSettings() = testDispatcher.runBlockingTest {
val settings = Settings(false, true, 3, false, false)
val settings = Settings(false, true, 3, false, false, true)
`when`(localSettingsStorage.readSettings()).thenReturn(settings)
settingsRepository = SettingsRepository(localSettingsStorage)

Expand All @@ -54,7 +54,7 @@ class SettingsRepositoryTest : BaseUnitTest() {
`when`(localSettingsStorage.readSettings()).thenReturn(Settings.DEFAULT)
settingsRepository = SettingsRepository(localSettingsStorage)

val settings = Settings(false, true, 1, true, true)
val settings = Settings(false, true, 1, true, true, true)
settingsRepository.saveSettings(settings)
assertEquals(settings, settingsRepository.settings().first())
}
Expand Down

0 comments on commit c02fd22

Please sign in to comment.