From a418180ded3bce55676fca346c70560da4a0889e Mon Sep 17 00:00:00 2001 From: Naveen Singh Date: Fri, 23 Oct 2026 06:30:16 +0530 Subject: [PATCH] feat: add share button reader --- CHANGELOG.md | 4 ++ .../documents/activities/MainActivity.kt | 21 ++-------- .../documents/activities/PDFViewerActivity.kt | 2 + .../activities/StructuredDocumentActivity.kt | 2 + .../fossify/documents/extensions/Activity.kt | 41 +++++++++++++++++++ .../ui/screens/DocumentsSelectionTopBar.kt | 2 +- .../documents/ui/screens/PdfDocumentScreen.kt | 2 + .../documents/ui/screens/PdfViewerChrome.kt | 5 +++ .../ui/screens/StructuredDocumentScreen.kt | 11 +++++ app/src/main/res/values/strings.xml | 1 - 10 files changed, 71 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 28ba4685..c4f7eff1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added +- Added a share button to document readers ([#98]) + ### Fixed - Fixed list/grid view resetting when reopening the app @@ -45,6 +48,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [#77]: https://github.com/FossifyOrg/Documents/issues/77 [#79]: https://github.com/FossifyOrg/Documents/issues/79 [#87]: https://github.com/FossifyOrg/Documents/issues/87 +[#98]: https://github.com/FossifyOrg/Documents/issues/98 [Unreleased]: https://github.com/FossifyOrg/Documents/compare/1.1.0...HEAD [1.1.0]: https://github.com/FossifyOrg/Documents/compare/1.0.1...1.1.0 diff --git a/app/src/main/java/org/fossify/documents/activities/MainActivity.kt b/app/src/main/java/org/fossify/documents/activities/MainActivity.kt index 996c9bd7..5447f4a4 100644 --- a/app/src/main/java/org/fossify/documents/activities/MainActivity.kt +++ b/app/src/main/java/org/fossify/documents/activities/MainActivity.kt @@ -1,7 +1,6 @@ package org.fossify.documents.activities import android.content.ActivityNotFoundException -import android.content.ClipData import android.content.Intent import android.net.Uri import android.os.Bundle @@ -27,6 +26,7 @@ import org.fossify.commons.helpers.LICENSE_PDF_VIEWER import org.fossify.commons.models.FAQItem import org.fossify.documents.BuildConfig import org.fossify.documents.R +import org.fossify.documents.extensions.shareDocuments import org.fossify.documents.extensions.startAboutActivity import org.fossify.documents.models.DocumentEntry import org.fossify.documents.models.DocumentKind @@ -241,25 +241,10 @@ class MainActivity : BaseComposeActivity() { return@validateDocuments } - val uris = ArrayList(readable.map { it.uri.toUri() }) + val uris = readable.map { it.uri.toUri() } val mimeType = readable.map { it.mimeType }.filter { it.isNotBlank() }.distinct() .singleOrNull() ?: "*/*" - val intent = Intent( - if (uris.size == 1) Intent.ACTION_SEND else Intent.ACTION_SEND_MULTIPLE - ).apply { - type = mimeType - addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - clipData = ClipData.newUri(contentResolver, readable.first().name, uris.first()).apply { - uris.drop(1).forEach { addItem(ClipData.Item(it)) } - } - if (uris.size == 1) { - putExtra(Intent.EXTRA_STREAM, uris.first()) - } else { - putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris) - } - } - - launchExternalIntent(Intent.createChooser(intent, getString(R.string.share_documents))) + shareDocuments(uris, mimeType) } } diff --git a/app/src/main/java/org/fossify/documents/activities/PDFViewerActivity.kt b/app/src/main/java/org/fossify/documents/activities/PDFViewerActivity.kt index aa16e871..751c4815 100644 --- a/app/src/main/java/org/fossify/documents/activities/PDFViewerActivity.kt +++ b/app/src/main/java/org/fossify/documents/activities/PDFViewerActivity.kt @@ -27,6 +27,7 @@ import org.fossify.commons.extensions.toast import org.fossify.documents.R import org.fossify.documents.data.DocumentsRepository import org.fossify.documents.extensions.config +import org.fossify.documents.extensions.shareDocuments import org.fossify.documents.helpers.PdfDocumentAdapter import org.fossify.documents.ui.screens.PdfDocumentScreen import org.fossify.documents.ui.theme.DocumentsAppThemeSurface @@ -94,6 +95,7 @@ class PDFViewerActivity : BaseComposeActivity() { isCopying = viewModel.isCopying, onPrint = { printPdf(uri, title) }, onOpenWith = { openWith(uri) }, + onShare = { shareDocuments(listOf(uri), "application/pdf") }, onFullscreenChange = ::setFullscreen, nightMode = nightMode, showPageIndicator = showPageIndicator, diff --git a/app/src/main/java/org/fossify/documents/activities/StructuredDocumentActivity.kt b/app/src/main/java/org/fossify/documents/activities/StructuredDocumentActivity.kt index fc6f4b99..ddfc9d2f 100644 --- a/app/src/main/java/org/fossify/documents/activities/StructuredDocumentActivity.kt +++ b/app/src/main/java/org/fossify/documents/activities/StructuredDocumentActivity.kt @@ -22,6 +22,7 @@ import org.fossify.commons.extensions.showErrorToast import org.fossify.commons.extensions.toast import org.fossify.documents.data.DocumentsRepository import org.fossify.documents.data.isAllowedExternalDocumentLink +import org.fossify.documents.extensions.shareDocuments import org.fossify.documents.models.DocumentKind import org.fossify.documents.ui.screens.StructuredDocumentScreen import org.fossify.documents.ui.theme.DocumentsAppThemeSurface @@ -79,6 +80,7 @@ class StructuredDocumentActivity : BaseComposeActivity() { null }, onOpenWith = { openWith(uri) }, + onShare = { shareDocuments(listOf(uri)) }, onOpenLink = ::openLink, ) } diff --git a/app/src/main/java/org/fossify/documents/extensions/Activity.kt b/app/src/main/java/org/fossify/documents/extensions/Activity.kt index 680bf8c8..d53ae7ab 100644 --- a/app/src/main/java/org/fossify/documents/extensions/Activity.kt +++ b/app/src/main/java/org/fossify/documents/extensions/Activity.kt @@ -2,15 +2,20 @@ package org.fossify.documents.extensions import android.app.Activity import android.content.ActivityNotFoundException +import android.content.ClipData import android.content.Intent import android.net.Uri import android.os.Build +import android.os.TransactionTooLargeException import android.provider.Settings import androidx.annotation.RequiresApi import org.fossify.commons.activities.AboutActivity import org.fossify.commons.activities.CustomizationActivity +import org.fossify.commons.extensions.getMimeTypeFromUri import org.fossify.commons.extensions.hideKeyboard import org.fossify.commons.extensions.openDeviceSettings +import org.fossify.commons.extensions.showErrorToast +import org.fossify.commons.extensions.toast import org.fossify.commons.helpers.APP_FAQ import org.fossify.commons.helpers.APP_ICON_IDS import org.fossify.commons.helpers.APP_LAUNCHER_NAME @@ -23,6 +28,42 @@ import org.fossify.commons.helpers.SHOW_FAQ_BEFORE_MAIL import org.fossify.commons.models.FAQItem import org.fossify.documents.R +@Suppress("TooGenericExceptionCaught") +internal fun Activity.shareDocuments(uris: List, mimeType: String = "") { + if (uris.isEmpty()) return + + try { + val contentType = mimeType.ifBlank { getMimeTypeFromUri(uris.first()) } + .ifBlank { "application/octet-stream" } + val clips = ClipData.newUri( + contentResolver, + getString(org.fossify.commons.R.string.share), + uris.first(), + ).apply { + uris.drop(1).forEach { addItem(ClipData.Item(it)) } + } + val intent = Intent(if (uris.size == 1) Intent.ACTION_SEND else Intent.ACTION_SEND_MULTIPLE).apply { + type = contentType + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + clipData = clips + if (uris.size == 1) { + putExtra(Intent.EXTRA_STREAM, uris.first()) + } else { + putParcelableArrayListExtra(Intent.EXTRA_STREAM, ArrayList(uris)) + } + } + startActivity(Intent.createChooser(intent, getString(org.fossify.commons.R.string.share_via))) + } catch (_: ActivityNotFoundException) { + toast(org.fossify.commons.R.string.no_app_found) + } catch (error: RuntimeException) { + if (error.cause is TransactionTooLargeException) { + toast(org.fossify.commons.R.string.maximum_share_reached) + } else { + showErrorToast(error) + } + } +} + internal fun Activity.startAboutActivity( appNameId: Int, licenseMask: Long, diff --git a/app/src/main/java/org/fossify/documents/ui/screens/DocumentsSelectionTopBar.kt b/app/src/main/java/org/fossify/documents/ui/screens/DocumentsSelectionTopBar.kt index f5372bd7..44104374 100644 --- a/app/src/main/java/org/fossify/documents/ui/screens/DocumentsSelectionTopBar.kt +++ b/app/src/main/java/org/fossify/documents/ui/screens/DocumentsSelectionTopBar.kt @@ -89,7 +89,7 @@ private fun DocumentsSelectionActions( IconButton(onClick = { actions.onShareDocuments(uiState.selectedDocuments.distinctBy { it.uri }) }) { Icon( imageVector = Icons.Outlined.Share, - contentDescription = stringResource(id = R.string.share_documents), + contentDescription = stringResource(id = org.fossify.commons.R.string.share), tint = SimpleTheme.colorScheme.primary, ) } diff --git a/app/src/main/java/org/fossify/documents/ui/screens/PdfDocumentScreen.kt b/app/src/main/java/org/fossify/documents/ui/screens/PdfDocumentScreen.kt index 296748b0..647f27bf 100644 --- a/app/src/main/java/org/fossify/documents/ui/screens/PdfDocumentScreen.kt +++ b/app/src/main/java/org/fossify/documents/ui/screens/PdfDocumentScreen.kt @@ -57,6 +57,7 @@ internal fun PdfDocumentScreen( isCopying: Boolean, onPrint: () -> Unit, onOpenWith: () -> Unit, + onShare: () -> Unit, onFullscreenChange: (Boolean) -> Unit, nightMode: Boolean, showPageIndicator: Boolean, @@ -196,6 +197,7 @@ internal fun PdfDocumentScreen( onOutline = { showOutline = true }, hasOutline = bookmarks.isNotEmpty(), onPrint = onPrint, + onShare = onShare, menu = { PdfReadingMenu( nightMode = nightMode, diff --git a/app/src/main/java/org/fossify/documents/ui/screens/PdfViewerChrome.kt b/app/src/main/java/org/fossify/documents/ui/screens/PdfViewerChrome.kt index 8af8c342..9e982504 100644 --- a/app/src/main/java/org/fossify/documents/ui/screens/PdfViewerChrome.kt +++ b/app/src/main/java/org/fossify/documents/ui/screens/PdfViewerChrome.kt @@ -20,6 +20,7 @@ import androidx.compose.material.icons.filled.Print import androidx.compose.material.icons.filled.Search import androidx.compose.material.icons.filled.ZoomIn import androidx.compose.material.icons.filled.ZoomOut +import androidx.compose.material.icons.outlined.Share import androidx.compose.material3.AlertDialog import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api @@ -60,6 +61,7 @@ internal fun PdfTopBar( onOutline: () -> Unit, hasOutline: Boolean, onPrint: () -> Unit, + onShare: () -> Unit, menu: @Composable () -> Unit, isLoaded: Boolean, ) { @@ -99,6 +101,9 @@ internal fun PdfTopBar( IconButton(onClick = onSearch, enabled = isLoaded) { Icon(Icons.Filled.Search, stringResource(R.string.search_text_in_document)) } + IconButton(onClick = onShare, enabled = isLoaded) { + Icon(Icons.Outlined.Share, stringResource(org.fossify.commons.R.string.share)) + } if (hasOutline) { IconButton(onClick = onOutline, enabled = isLoaded) { Icon(Icons.AutoMirrored.Filled.List, stringResource(R.string.pdf_contents)) diff --git a/app/src/main/java/org/fossify/documents/ui/screens/StructuredDocumentScreen.kt b/app/src/main/java/org/fossify/documents/ui/screens/StructuredDocumentScreen.kt index 33d92684..1f182e80 100644 --- a/app/src/main/java/org/fossify/documents/ui/screens/StructuredDocumentScreen.kt +++ b/app/src/main/java/org/fossify/documents/ui/screens/StructuredDocumentScreen.kt @@ -38,6 +38,7 @@ import androidx.compose.material.icons.filled.KeyboardArrowDown import androidx.compose.material.icons.filled.KeyboardArrowUp import androidx.compose.material.icons.filled.Search import androidx.compose.material.icons.outlined.Edit +import androidx.compose.material.icons.outlined.Share import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton @@ -86,6 +87,7 @@ internal fun StructuredDocumentScreen( onBack: () -> Unit, onEdit: (() -> Unit)?, onOpenWith: () -> Unit, + onShare: () -> Unit, onOpenLink: (Uri) -> Unit, ) { var searchActive by rememberSaveable { mutableStateOf(false) } @@ -115,6 +117,7 @@ internal fun StructuredDocumentScreen( }, onEdit = onEdit, onOpenWith = onOpenWith, + onShare = onShare, scrolledColor = scrolledColor, scrollBehavior = scrollBehavior, statusBarColor = statusBarColor, @@ -157,6 +160,7 @@ private fun StructuredDocumentTopBar( onSearch: (() -> Unit)?, onEdit: (() -> Unit)?, onOpenWith: () -> Unit, + onShare: () -> Unit, scrolledColor: Color, scrollBehavior: TopAppBarScrollBehavior, statusBarColor: Int, @@ -210,6 +214,13 @@ private fun StructuredDocumentTopBar( ) } } + IconButton(onClick = onShare) { + Icon( + imageVector = Icons.Outlined.Share, + contentDescription = stringResource(org.fossify.commons.R.string.share), + tint = scrolledColor, + ) + } if (onEdit != null) { IconButton(onClick = onEdit) { Icon( diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d1230aca..e038dd46 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -72,7 +72,6 @@ Remember PDF page Remove from Documents Retry - Share documents Some selected documents are no longer available. Saved %1$d / %2$d