diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/components/CustomSelectionContainer.kt b/app/src/main/java/ua/acclorite/book_story/presentation/components/CustomSelectionContainer.kt
index 0f4fba42..3944725f 100644
--- a/app/src/main/java/ua/acclorite/book_story/presentation/components/CustomSelectionContainer.kt
+++ b/app/src/main/java/ua/acclorite/book_story/presentation/components/CustomSelectionContainer.kt
@@ -29,8 +29,10 @@ import ua.acclorite.book_story.R
private const val MENU_ITEM_COPY = 0
-private const val MENU_ITEM_TRANSLATE = 1
-private const val MENU_ITEM_DICTIONARY = 2
+private const val MENU_ITEM_SHARE = 1
+private const val MENU_ITEM_WEB = 2
+private const val MENU_ITEM_TRANSLATE = 3
+private const val MENU_ITEM_DICTIONARY = 4
/**
* Custom Text ActionMode callback. Used in pair with [CustomSelectionToolbar]. Follow [TextToolbar] for more info.
@@ -39,6 +41,8 @@ private class CustomTextActionModeCallback(
private val context: Context,
var rect: Rect = Rect.Zero,
var onCopyRequested: (() -> Unit)? = null,
+ var onShareRequested: (() -> Unit)? = null,
+ var onWebSearchRequested: (() -> Unit)? = null,
var onTranslateRequested: (() -> Unit)? = null,
var onDictionaryRequested: (() -> Unit)? = null
) : ActionMode.Callback {
@@ -51,13 +55,23 @@ private class CustomTextActionModeCallback(
.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER)
}
+ onShareRequested?.let {
+ menu.add(0, MENU_ITEM_SHARE, 1, context.getString(R.string.share))
+ .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER)
+ }
+
+ onWebSearchRequested?.let {
+ menu.add(0, MENU_ITEM_WEB, 2, context.getString(R.string.web_search))
+ .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER)
+ }
+
onTranslateRequested?.let {
- menu.add(0, MENU_ITEM_TRANSLATE, 1, context.getString(R.string.translate))
+ menu.add(0, MENU_ITEM_TRANSLATE, 3, context.getString(R.string.translate))
.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER)
}
onDictionaryRequested?.let {
- menu.add(0, MENU_ITEM_DICTIONARY, 2, context.getString(R.string.dictionary))
+ menu.add(0, MENU_ITEM_DICTIONARY, 4, context.getString(R.string.dictionary))
.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER)
}
@@ -71,6 +85,8 @@ private class CustomTextActionModeCallback(
override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean {
when (item!!.itemId) {
MENU_ITEM_COPY -> onCopyRequested?.invoke()
+ MENU_ITEM_SHARE -> onShareRequested?.invoke()
+ MENU_ITEM_WEB -> onWebSearchRequested?.invoke()
MENU_ITEM_TRANSLATE -> onTranslateRequested?.invoke()
MENU_ITEM_DICTIONARY -> onDictionaryRequested?.invoke()
else -> return false
@@ -116,12 +132,15 @@ private class FloatingTextActionModeCallback(
}
/**
- * Custom Selection Toolbar. Used in pair with [CustomSelectionContainer] to display custom toolbar.
+ * Custom Selection Toolbar.
+ * Used in pair with [CustomSelectionContainer] to display custom toolbar.
*/
private class CustomSelectionToolbar(
private val view: View,
context: Context,
private val onCopyRequest: (() -> Unit)?,
+ private val onShareRequest: ((String) -> Unit)?,
+ private val onWebSearchRequest: ((String) -> Unit)?,
private val onTranslateRequest: ((String) -> Unit)?,
private val onDictionaryRequest: ((String) -> Unit)?
) : TextToolbar {
@@ -145,6 +164,36 @@ private class CustomSelectionToolbar(
onCopyRequested?.invoke()
onCopyRequest?.invoke()
}
+ callback.onShareRequested = {
+ val previousClipboard = clipboardManager.primaryClip
+ onCopyRequested?.invoke()
+ val currentClipboard = clipboardManager.text
+
+ onShareRequest?.invoke(currentClipboard.toString())
+
+ if (previousClipboard != null) {
+ clipboardManager.setPrimaryClip(
+ previousClipboard
+ )
+ } else {
+ clipboardManager.setPrimaryClip(ClipData.newPlainText(null, " "))
+ }
+ }
+ callback.onWebSearchRequested = {
+ val previousClipboard = clipboardManager.primaryClip
+ onCopyRequested?.invoke()
+ val currentClipboard = clipboardManager.text
+
+ onWebSearchRequest?.invoke(currentClipboard.toString())
+
+ if (previousClipboard != null) {
+ clipboardManager.setPrimaryClip(
+ previousClipboard
+ )
+ } else {
+ clipboardManager.setPrimaryClip(ClipData.newPlainText(null, " "))
+ }
+ }
callback.onTranslateRequested = {
val previousClipboard = clipboardManager.primaryClip
onCopyRequested?.invoke()
@@ -205,6 +254,8 @@ private class CustomSelectionToolbar(
@Composable
fun CustomSelectionContainer(
onCopyRequested: (() -> Unit),
+ onShareRequested: ((String) -> Unit),
+ onWebSearchRequested: ((String) -> Unit),
onTranslateRequested: ((String) -> Unit),
onDictionaryRequested: ((String) -> Unit),
content: @Composable (toolbarHidden: Boolean) -> Unit
@@ -220,6 +271,12 @@ fun CustomSelectionContainer(
onCopyRequest = {
onCopyRequested()
},
+ onShareRequest = {
+ onShareRequested(it)
+ },
+ onWebSearchRequest = {
+ onWebSearchRequested(it)
+ },
onTranslateRequest = {
onTranslateRequested(it)
},
diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/ReaderScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/ReaderScreen.kt
index 951a0c19..9c3c0a53 100644
--- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/ReaderScreen.kt
+++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/ReaderScreen.kt
@@ -274,6 +274,36 @@ private fun ReaderScreen(
).show()
}
},
+ onShareRequested = { textToShare ->
+ onEvent(
+ ReaderEvent.OnOpenShareApp(
+ textToShare = textToShare,
+ context,
+ noAppsFound = {
+ Toast.makeText(
+ context,
+ context.getString(R.string.error_no_share_app),
+ Toast.LENGTH_SHORT
+ ).show()
+ }
+ )
+ )
+ },
+ onWebSearchRequested = { textToSearch ->
+ onEvent(
+ ReaderEvent.OnOpenWebBrowser(
+ textToSearch = textToSearch,
+ context,
+ noAppsFound = {
+ Toast.makeText(
+ context,
+ context.getString(R.string.error_no_browser),
+ Toast.LENGTH_SHORT
+ ).show()
+ }
+ )
+ )
+ },
onTranslateRequested = { textToTranslate ->
onEvent(
ReaderEvent.OnOpenTranslator(
@@ -298,7 +328,7 @@ private fun ReaderScreen(
noAppsFound = {
Toast.makeText(
context,
- context.getString(R.string.error_no_browser),
+ context.getString(R.string.error_no_dictionary),
Toast.LENGTH_SHORT
).show()
}
diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/data/ReaderEvent.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/data/ReaderEvent.kt
index 1fc25861..36a149af 100644
--- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/data/ReaderEvent.kt
+++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/data/ReaderEvent.kt
@@ -51,6 +51,18 @@ sealed class ReaderEvent {
val noAppsFound: () -> Unit
) : ReaderEvent()
+ data class OnOpenShareApp(
+ val textToShare: String,
+ val context: ComponentActivity,
+ val noAppsFound: () -> Unit
+ ) : ReaderEvent()
+
+ data class OnOpenWebBrowser(
+ val textToSearch: String,
+ val context: ComponentActivity,
+ val noAppsFound: () -> Unit
+ ) : ReaderEvent()
+
data class OnOpenDictionary(
val textToDefine: String,
val context: ComponentActivity,
diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/data/ReaderViewModel.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/data/ReaderViewModel.kt
index 98dccf54..2f74e5c0 100644
--- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/data/ReaderViewModel.kt
+++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/reader/data/ReaderViewModel.kt
@@ -360,6 +360,55 @@ class ReaderViewModel @Inject constructor(
}
}
+ is ReaderEvent.OnOpenShareApp -> {
+ launch {
+ val shareIntent = Intent()
+
+ shareIntent.action = Intent.ACTION_SEND
+ shareIntent.type = "text/plain"
+ shareIntent.putExtra(
+ Intent.EXTRA_SUBJECT,
+ event.context.getString(R.string.app_name)
+ )
+ shareIntent.putExtra(
+ Intent.EXTRA_TEXT,
+ event.textToShare.trim()
+ )
+
+ var shareFailure = false
+ shareIntent.launchActivity(event.context, createChooser = true) {
+ shareFailure = true
+ }
+ if (!shareFailure) {
+ return@launch
+ }
+
+ event.noAppsFound()
+ }
+ }
+
+ is ReaderEvent.OnOpenWebBrowser -> {
+ launch {
+ val browserIntent = Intent()
+
+ browserIntent.action = Intent.ACTION_WEB_SEARCH
+ browserIntent.putExtra(
+ SearchManager.QUERY,
+ event.textToSearch
+ )
+
+ var browserFailure = false
+ browserIntent.launchActivity(event.context) {
+ browserFailure = true
+ }
+ if (!browserFailure) {
+ return@launch
+ }
+
+ event.noAppsFound()
+ }
+ }
+
is ReaderEvent.OnOpenDictionary -> {
launch {
val dictionaryIntent = Intent()
diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml
index 497e2f34..6d393843 100644
--- a/app/src/main/res/values-uk/strings.xml
+++ b/app/src/main/res/values-uk/strings.xml
@@ -101,7 +101,9 @@
Помилка: %1$s
Цей файл пустий або пошкоджений.
Не знайдено жодного перекладача.
+ Не знайдено жодного словника.
Не знайдено жодного браузера.
+ Не знайдено застосунка щоб поділитися.
Вміст книги пустий. Будь ласка, перевірте вміст книги та оновіть її.
@@ -160,6 +162,8 @@
Завантажити
Готово
Увімкнути
+ Веб-пошук
+ Поділитися
файли
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 86cbf832..e2480a92 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -118,7 +118,9 @@
Error: %1$s
This file is empty or corrupted.
No translator app found.
+ No dictionary app found.
No browser app found.
+ No app to share found.
The book content is empty. Please, make sure that the book content is not empty and update it.
@@ -176,6 +178,8 @@
Download
Done
Enable
+ Web search
+ Share
files