From 087a01cf72c158337a8a181a51dce9cb3a264c51 Mon Sep 17 00:00:00 2001 From: June Date: Thu, 31 Mar 2022 18:15:19 +0100 Subject: [PATCH 01/19] Update gradle wrapper to 7.4.2 Signed-off-by: June --- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ffe61b4..5c51a4a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=e5444a57cda4a95f90b0c9446a9e1b47d3d7f69057765bfb54bd4f482542d548 -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-bin.zip +distributionSha256Sum=29e49b10984e585d8118b7d0bc452f944e386458df27371b49b4ac1dec4b7fda +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From ec965ddaaaaaea8e0fc7bc289e27b16f69b49ea5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Apr 2022 21:09:30 +0000 Subject: [PATCH 02/19] Bump kotlin-gradle-plugin from 1.6.10 to 1.6.20 Bumps [kotlin-gradle-plugin](https://github.com/JetBrains/kotlin) from 1.6.10 to 1.6.20. - [Release notes](https://github.com/JetBrains/kotlin/releases) - [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md) - [Commits](https://github.com/JetBrains/kotlin/commits) --- updated-dependencies: - dependency-name: org.jetbrains.kotlin:kotlin-gradle-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 3502229..3bacf30 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,7 +5,7 @@ buildscript { } dependencies { classpath("com.android.tools.build:gradle:7.1.2") - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.20") } } From 975dfb966c5901f23920643371e791df66228008 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Apr 2022 21:07:08 +0000 Subject: [PATCH 03/19] Bump gradle from 7.1.2 to 7.1.3 Bumps gradle from 7.1.2 to 7.1.3. --- updated-dependencies: - dependency-name: com.android.tools.build:gradle dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 3bacf30..5721698 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,7 +4,7 @@ buildscript { mavenCentral() } dependencies { - classpath("com.android.tools.build:gradle:7.1.2") + classpath("com.android.tools.build:gradle:7.1.3") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.20") } } From 6847883605a02a8135f4a8034e4edf0d07a1e215 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Apr 2022 21:18:59 +0000 Subject: [PATCH 04/19] Bump actions/setup-java from 2 to 3 Bumps [actions/setup-java](https://github.com/actions/setup-java) from 2 to 3. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d109a0d..882de70 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,7 +11,7 @@ jobs: with: submodules: true - name: Set up JDK 17 - uses: actions/setup-java@v2 + uses: actions/setup-java@v3 with: distribution: 'temurin' java-version: 17 From eb6c14740f6dfbafdf41b19c1fddb5f085a1003b Mon Sep 17 00:00:00 2001 From: Patryk Mis Date: Thu, 14 Apr 2022 12:58:43 +0200 Subject: [PATCH 05/19] Update Gradle Wrapper --- gradle/wrapper/gradle-wrapper.jar | Bin 59536 -> 59821 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7454180f2ae8848c63b8b4dea2cb829da983f2fa..41d9927a4d4fb3f96a785543079b8df6723c946b 100644 GIT binary patch delta 8958 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 From c0eea02bb19695d6ca40839c7631c2b1adf971e2 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Wed, 20 Apr 2022 06:27:40 -0400 Subject: [PATCH 06/19] update CI JDK to 18 --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 882de70..350d32a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,11 +10,11 @@ jobs: - uses: actions/checkout@v3 with: submodules: true - - name: Set up JDK 17 + - name: Set up JDK 18 uses: actions/setup-java@v3 with: distribution: 'temurin' - java-version: 17 + java-version: 18 cache: gradle - name: Build with Gradle run: ./gradlew build --no-daemon From ba9a6c8206f874604648e0a348c4a48e9e0c6ea2 Mon Sep 17 00:00:00 2001 From: Pratyush Date: Fri, 22 Apr 2022 09:52:19 +0530 Subject: [PATCH 07/19] replace deprecated startActivityForResult --- .../app/grapheneos/pdfviewer/PdfViewer.java | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/app/grapheneos/pdfviewer/PdfViewer.java b/app/src/main/java/app/grapheneos/pdfviewer/PdfViewer.java index a1e72bf..00f6547 100644 --- a/app/src/main/java/app/grapheneos/pdfviewer/PdfViewer.java +++ b/app/src/main/java/app/grapheneos/pdfviewer/PdfViewer.java @@ -1,7 +1,6 @@ package app.grapheneos.pdfviewer; import android.annotation.SuppressLint; -import android.app.Activity; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.res.ColorStateList; @@ -25,6 +24,8 @@ import android.webkit.WebViewClient; import android.widget.TextView; import android.widget.Toast; +import androidx.activity.result.ActivityResultLauncher; +import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.core.graphics.Insets; @@ -99,7 +100,6 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader private static final float MAX_ZOOM_RATIO = 1.5f; private static final int ALPHA_LOW = 130; private static final int ALPHA_HIGH = 255; - private static final int ACTION_OPEN_DOCUMENT_REQUEST_CODE = 1; private static final int STATE_LOADED = 1; private static final int STATE_END = 2; private static final int PADDING = 10; @@ -118,6 +118,20 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader private Toast mToast; private Snackbar snackbar; + private final ActivityResultLauncher openDocumentLauncher = registerForActivityResult( + new ActivityResultContracts.StartActivityForResult(), result -> { + if (result == null) return; + if (result.getResultCode() != RESULT_OK) return; + Intent resultData = result.getData(); + if (resultData != null) { + mUri = result.getData().getData(); + mPage = 1; + mDocumentProperties = null; + loadPdf(); + invalidateOptionsMenu(); + } + }); + private class Channel { @JavascriptInterface public int getPage() { @@ -396,7 +410,7 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setType("application/pdf"); - startActivityForResult(intent, ACTION_OPEN_DOCUMENT_REQUEST_CODE); + openDocumentLauncher.launch(intent); } private void shareDocument() { @@ -478,21 +492,6 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader savedInstanceState.putInt(STATE_DOCUMENT_ORIENTATION_DEGREES, mDocumentOrientationDegrees); } - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent resultData) { - super.onActivityResult(requestCode, resultCode, resultData); - - if (requestCode == ACTION_OPEN_DOCUMENT_REQUEST_CODE && resultCode == Activity.RESULT_OK) { - if (resultData != null) { - mUri = resultData.getData(); - mPage = 1; - mDocumentProperties = null; - loadPdf(); - invalidateOptionsMenu(); - } - } - } - private void showPageNumber() { if (mToast != null) { mToast.cancel(); From d71f804b5a2630eb74ed119ce86bdb20c2e4ab46 Mon Sep 17 00:00:00 2001 From: smdyv <88971341+smdyv@users.noreply.github.com> Date: Fri, 22 Apr 2022 20:55:24 +0200 Subject: [PATCH 08/19] Replace feature graphic --- app/src/main/feature_graphic.png | Bin 15330 -> 6825 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/app/src/main/feature_graphic.png b/app/src/main/feature_graphic.png index 460809710c1467f6a103680fa2e58beae676ef96..14035b3f83686a50b9cea39cef55596553ebe723 100644 GIT binary patch literal 6825 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 HkBk0)&|Fa0 literal 15330 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 Date: Tue, 19 Apr 2022 21:09:08 +0000 Subject: [PATCH 09/19] Bump kotlin-gradle-plugin from 1.6.20 to 1.6.21 Bumps [kotlin-gradle-plugin](https://github.com/JetBrains/kotlin) from 1.6.20 to 1.6.21. - [Release notes](https://github.com/JetBrains/kotlin/releases) - [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md) - [Commits](https://github.com/JetBrains/kotlin/commits) --- updated-dependencies: - dependency-name: org.jetbrains.kotlin:kotlin-gradle-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 5721698..860101c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,7 +5,7 @@ buildscript { } dependencies { classpath("com.android.tools.build:gradle:7.1.3") - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.20") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21") } } From eb6eb8046cacc35c50989607c87198ae1b6c9239 Mon Sep 17 00:00:00 2001 From: Pratyush Date: Fri, 22 Apr 2022 11:04:05 +0530 Subject: [PATCH 10/19] added feature to save document --- .../java/app/grapheneos/pdfviewer/KtUtils.kt | 25 +++++++++ .../app/grapheneos/pdfviewer/PdfViewer.java | 52 ++++++++++++++++++- app/src/main/res/drawable/ic_save_24dp.xml | 10 ++++ app/src/main/res/menu/pdf_viewer.xml | 6 +++ app/src/main/res/values/strings.xml | 2 + 5 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/app/grapheneos/pdfviewer/KtUtils.kt create mode 100644 app/src/main/res/drawable/ic_save_24dp.xml diff --git a/app/src/main/java/app/grapheneos/pdfviewer/KtUtils.kt b/app/src/main/java/app/grapheneos/pdfviewer/KtUtils.kt new file mode 100644 index 0000000..3f67aa6 --- /dev/null +++ b/app/src/main/java/app/grapheneos/pdfviewer/KtUtils.kt @@ -0,0 +1,25 @@ +package app.grapheneos.pdfviewer + +import android.content.Context +import android.net.Uri +import java.io.FileNotFoundException +import java.io.IOException +import java.io.InputStream +import java.io.OutputStream + +@Throws(FileNotFoundException::class, IOException::class) +fun saveAs(context: Context, existingUri: Uri, saveAs: Uri) { + + context.asInputStream(existingUri)?.use { inputStream -> + context.asOutputStream(saveAs)?.use { outputStream -> + outputStream.write(inputStream.readBytes()) + } + } + +} + +@Throws(FileNotFoundException::class) +private fun Context.asInputStream(uri: Uri): InputStream? = contentResolver.openInputStream(uri) + +@Throws(FileNotFoundException::class) +private fun Context.asOutputStream(uri: Uri): OutputStream? = contentResolver.openOutputStream(uri) diff --git a/app/src/main/java/app/grapheneos/pdfviewer/PdfViewer.java b/app/src/main/java/app/grapheneos/pdfviewer/PdfViewer.java index 00f6547..32abbc0 100644 --- a/app/src/main/java/app/grapheneos/pdfviewer/PdfViewer.java +++ b/app/src/main/java/app/grapheneos/pdfviewer/PdfViewer.java @@ -132,6 +132,19 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader } }); + private final ActivityResultLauncher saveAsLauncher = registerForActivityResult( + new ActivityResultContracts.StartActivityForResult(), result -> { + if (result == null) return; + if (result.getResultCode() != RESULT_OK) return; + Intent resultData = result.getData(); + if (resultData != null) { + Uri path = resultData.getData(); + if (path != null) { + saveDocumentAs(path); + } + } + }); + private class Channel { @JavascriptInterface public int getPage() { @@ -514,10 +527,10 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader @Override public boolean onPrepareOptionsMenu(Menu menu) { - final int[] ids = { R.id.action_zoom_in, R.id.action_zoom_out, R.id.action_jump_to_page, + final int[] ids = {R.id.action_zoom_in, R.id.action_zoom_out, R.id.action_jump_to_page, R.id.action_next, R.id.action_previous, R.id.action_first, R.id.action_last, R.id.action_rotate_clockwise, R.id.action_rotate_counterclockwise, - R.id.action_view_document_properties, R.id.action_share }; + R.id.action_view_document_properties, R.id.action_share, R.id.action_save_as}; if (mDocumentState < STATE_LOADED) { for (final int id : ids) { final MenuItem item = menu.findItem(id); @@ -541,6 +554,7 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader enableDisableMenuItem(menu.findItem(R.id.action_share), mUri != null); enableDisableMenuItem(menu.findItem(R.id.action_next), mPage < mNumPages); enableDisableMenuItem(menu.findItem(R.id.action_previous), mPage > 1); + enableDisableMenuItem(menu.findItem(R.id.action_save_as), mUri != null); return true; } @@ -587,8 +601,42 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader } else if (itemId == R.id.action_share) { shareDocument(); return true; + } else if (itemId == R.id.action_save_as) { + saveDocument(); } return super.onOptionsItemSelected(item); } + + private void saveDocument() { + Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT); + intent.addCategory(Intent.CATEGORY_OPENABLE); + intent.setType("application/pdf"); + intent.putExtra(Intent.EXTRA_TITLE, getCurrentDocumentName()); + saveAsLauncher.launch(intent); + } + + private String getCurrentDocumentName() { + if (mDocumentProperties == null || mDocumentProperties.isEmpty()) return ""; + String fileName = ""; + String title = ""; + for (CharSequence property : mDocumentProperties) { + if (property.toString().startsWith("File name:")) { + fileName = property.toString().replace("File name:", ""); + } + if (property.toString().startsWith("Title:-")) { + title = property.toString().replace("Title:-", ""); + } + } + return fileName.length() > 2 ? fileName : title; + } + + private void saveDocumentAs(Uri uri) { + try { + KtUtilsKt.saveAs(this, mUri, uri); + } catch (IOException e) { + e.printStackTrace(); + snackbar.setText(R.string.error_while_saving).show(); + } + } } diff --git a/app/src/main/res/drawable/ic_save_24dp.xml b/app/src/main/res/drawable/ic_save_24dp.xml new file mode 100644 index 0000000..1ce5843 --- /dev/null +++ b/app/src/main/res/drawable/ic_save_24dp.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/menu/pdf_viewer.xml b/app/src/main/res/menu/pdf_viewer.xml index acdd788..6649c21 100644 --- a/app/src/main/res/menu/pdf_viewer.xml +++ b/app/src/main/res/menu/pdf_viewer.xml @@ -73,6 +73,12 @@ android:title="@string/action_rotate_counterclockwise" app:showAsAction="ifRoom" /> + + Cannot open file with invalid MIME type Cannot open legacy file paths from insecure apps Received I/O error trying to open content + Error encountered while saving WebView out-of-date Your current WebView version is %d. The WebView should be at least version %d for the PDF Viewer to work. Share + Save as From 21d7b9d76e2601c8a042bdd9abc2baf43ae155ed Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Fri, 6 May 2022 06:42:03 -0400 Subject: [PATCH 11/19] fix warning about non-positional format parameters --- app/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fc27a87..98aa476 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -23,7 +23,7 @@ Error encountered while saving WebView out-of-date - Your current WebView version is %d. The WebView should be at least version %d for the PDF Viewer to work. + Your current WebView version is %1$d. The WebView should be at least version %2$d for the PDF Viewer to work. Share Save as From 96651d02af7c0425714a7c246fde21f9e742bba7 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Fri, 6 May 2022 06:43:47 -0400 Subject: [PATCH 12/19] remove obsolete zoom in / zoom out menu actions --- .../java/app/grapheneos/pdfviewer/PdfViewer.java | 16 ++++------------ app/src/main/res/menu/pdf_viewer.xml | 12 ------------ app/src/main/res/values/strings.xml | 2 -- 3 files changed, 4 insertions(+), 26 deletions(-) diff --git a/app/src/main/java/app/grapheneos/pdfviewer/PdfViewer.java b/app/src/main/java/app/grapheneos/pdfviewer/PdfViewer.java index 32abbc0..2a1d873 100644 --- a/app/src/main/java/app/grapheneos/pdfviewer/PdfViewer.java +++ b/app/src/main/java/app/grapheneos/pdfviewer/PdfViewer.java @@ -527,10 +527,10 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader @Override public boolean onPrepareOptionsMenu(Menu menu) { - final int[] ids = {R.id.action_zoom_in, R.id.action_zoom_out, R.id.action_jump_to_page, - R.id.action_next, R.id.action_previous, R.id.action_first, R.id.action_last, - R.id.action_rotate_clockwise, R.id.action_rotate_counterclockwise, - R.id.action_view_document_properties, R.id.action_share, R.id.action_save_as}; + final int[] ids = {R.id.action_jump_to_page, R.id.action_next, R.id.action_previous, + R.id.action_first, R.id.action_last, R.id.action_rotate_clockwise, + R.id.action_rotate_counterclockwise, R.id.action_view_document_properties, + R.id.action_share, R.id.action_save_as}; if (mDocumentState < STATE_LOADED) { for (final int id : ids) { final MenuItem item = menu.findItem(id); @@ -549,8 +549,6 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader } enableDisableMenuItem(menu.findItem(R.id.action_open), getWebViewRelease() >= MIN_WEBVIEW_RELEASE); - enableDisableMenuItem(menu.findItem(R.id.action_zoom_in), mZoomRatio != MAX_ZOOM_RATIO); - enableDisableMenuItem(menu.findItem(R.id.action_zoom_out), mZoomRatio != MIN_ZOOM_RATIO); enableDisableMenuItem(menu.findItem(R.id.action_share), mUri != null); enableDisableMenuItem(menu.findItem(R.id.action_next), mPage < mNumPages); enableDisableMenuItem(menu.findItem(R.id.action_previous), mPage > 1); @@ -577,12 +575,6 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader } else if (itemId == R.id.action_open) { openDocument(); return true; - } else if (itemId == R.id.action_zoom_out) { - zoomOut(0.25f, true); - return true; - } else if (itemId == R.id.action_zoom_in) { - zoomIn(0.25f, true); - return true; } else if (itemId == R.id.action_rotate_clockwise) { documentOrientationChanged(90); return true; diff --git a/app/src/main/res/menu/pdf_viewer.xml b/app/src/main/res/menu/pdf_viewer.xml index 6649c21..e9cd998 100644 --- a/app/src/main/res/menu/pdf_viewer.xml +++ b/app/src/main/res/menu/pdf_viewer.xml @@ -25,18 +25,6 @@ android:title="@string/action_open" app:showAsAction="ifRoom" /> - - - - Open document First page Last page - Zoom out - Zoom in Rotate clockwise Rotate counterclockwise Jump to page From 61d204d18848d1a6ab19ad927ba5f175bc09141e Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Fri, 6 May 2022 06:46:42 -0400 Subject: [PATCH 13/19] move share action lower in the menu --- app/src/main/res/menu/pdf_viewer.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/src/main/res/menu/pdf_viewer.xml b/app/src/main/res/menu/pdf_viewer.xml index e9cd998..c77b3de 100644 --- a/app/src/main/res/menu/pdf_viewer.xml +++ b/app/src/main/res/menu/pdf_viewer.xml @@ -25,12 +25,6 @@ android:title="@string/action_open" app:showAsAction="ifRoom" /> - - + + Date: Fri, 6 May 2022 06:54:58 -0400 Subject: [PATCH 14/19] reorder action strings --- app/src/main/res/values/strings.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d2e23d4..c750141 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -7,9 +7,11 @@ Open document First page Last page + Jump to page Rotate clockwise Rotate counterclockwise - Jump to page + Share + Save as Properties Invalid date @@ -22,6 +24,4 @@ WebView out-of-date Your current WebView version is %1$d. The WebView should be at least version %2$d for the PDF Viewer to work. - Share - Save as From 87c71ddac2da57929da99b1ceeb9f4ea5bdb11a9 Mon Sep 17 00:00:00 2001 From: Pratyush Date: Sun, 1 May 2022 20:16:40 +0530 Subject: [PATCH 15/19] added support for encrypted PDF based on https://github.com/GrapheneOS/PdfViewer/pull/17 Signed-off-by: Pratyush Co-authored-by: Tommy-Geenexus Co-authored-by: empratyush --- app/src/main/assets/viewer.js | 34 +++++--- .../app/grapheneos/pdfviewer/PdfViewer.java | 78 +++++++++++++++++++ .../fragment/PasswordPromptFragment.kt | 67 ++++++++++++++++ .../res/layout/password_dialog_fragment.xml | 38 +++++++++ app/src/main/res/values/strings.xml | 6 ++ 5 files changed, 212 insertions(+), 11 deletions(-) create mode 100644 app/src/main/java/app/grapheneos/pdfviewer/fragment/PasswordPromptFragment.kt create mode 100644 app/src/main/res/layout/password_dialog_fragment.xml diff --git a/app/src/main/assets/viewer.js b/app/src/main/assets/viewer.js index c5e4ef2..0e04afa 100644 --- a/app/src/main/assets/viewer.js +++ b/app/src/main/assets/viewer.js @@ -198,15 +198,27 @@ function isTextSelected() { return window.getSelection().toString() !== ""; } -pdfjsLib.getDocument("https://localhost/placeholder.pdf").promise.then(function(newDoc) { - pdfDoc = newDoc; - channel.setNumPages(pdfDoc.numPages); - pdfDoc.getMetadata().then(function(data) { - channel.setDocumentProperties(JSON.stringify(data.info)); - }).catch(function(error) { - console.log("getMetadata error: " + error); +function loadDocument() { + const pdfPassword = channel.getPassword(); + const loadingTask = pdfjsLib.getDocument({ url: "https://localhost/placeholder.pdf", password: pdfPassword }); + loadingTask.onPassword = (_, error) => { + if (error === pdfjsLib.PasswordResponses.NEED_PASSWORD) { + channel.showPasswordPrompt(); + } else if (error === pdfjsLib.PasswordResponses.INCORRECT_PASSWORD) { + channel.invalidPassword(); + } + } + + loadingTask.promise.then(function (newDoc) { + pdfDoc = newDoc; + channel.setNumPages(pdfDoc.numPages); + pdfDoc.getMetadata().then(function (data) { + channel.setDocumentProperties(JSON.stringify(data.info)); + }).catch(function (error) { + console.log("getMetadata error: " + error); + }); + renderPage(channel.getPage(), false, false); + }, function (reason) { + console.error(reason.name + ": " + reason.message); }); - renderPage(channel.getPage(), false, false); -}).catch(function(error) { - console.log("getDocument error: " + error); -}); +} diff --git a/app/src/main/java/app/grapheneos/pdfviewer/PdfViewer.java b/app/src/main/java/app/grapheneos/pdfviewer/PdfViewer.java index 2a1d873..ceb67c2 100644 --- a/app/src/main/java/app/grapheneos/pdfviewer/PdfViewer.java +++ b/app/src/main/java/app/grapheneos/pdfviewer/PdfViewer.java @@ -32,6 +32,7 @@ import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowCompat; import androidx.core.view.WindowInsetsCompat; +import androidx.fragment.app.Fragment; import androidx.loader.app.LoaderManager; import androidx.loader.content.Loader; @@ -39,11 +40,13 @@ import com.google.android.material.snackbar.Snackbar; import app.grapheneos.pdfviewer.databinding.PdfviewerBinding; import app.grapheneos.pdfviewer.fragment.DocumentPropertiesFragment; +import app.grapheneos.pdfviewer.fragment.PasswordPromptFragment; import app.grapheneos.pdfviewer.fragment.JumpToPageFragment; import app.grapheneos.pdfviewer.loader.DocumentPropertiesLoader; import java.io.IOException; import java.io.InputStream; +import java.io.FileNotFoundException; import java.util.HashMap; import java.util.List; @@ -54,6 +57,7 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader private static final String STATE_PAGE = "page"; private static final String STATE_ZOOM_RATIO = "zoomRatio"; private static final String STATE_DOCUMENT_ORIENTATION_DEGREES = "documentOrientationDegrees"; + private static final String STATE_ENCRYPTED_DOCUMENT_PASSWORD = "encrypted_document_password"; private static final String KEY_PROPERTIES = "properties"; private static final int MIN_WEBVIEW_RELEASE = 89; @@ -110,6 +114,7 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader private float mZoomRatio = 1f; private int mDocumentOrientationDegrees; private int mDocumentState; + private String mEncryptedDocumentPassword; private List mDocumentProperties; private InputStream mInputStream; @@ -117,6 +122,7 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader private TextView mTextView; private Toast mToast; private Snackbar snackbar; + private PasswordPromptFragment mPasswordPromptFragment; private final ActivityResultLauncher openDocumentLauncher = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), result -> { @@ -127,6 +133,7 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader mUri = result.getData().getData(); mPage = 1; mDocumentProperties = null; + mEncryptedDocumentPassword = ""; loadPdf(); invalidateOptionsMenu(); } @@ -177,6 +184,29 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader args.putString(KEY_PROPERTIES, properties); runOnUiThread(() -> LoaderManager.getInstance(PdfViewer.this).restartLoader(DocumentPropertiesLoader.ID, args, PdfViewer.this)); } + + @JavascriptInterface + public void showPasswordPrompt() { + if (getPasswordPromptFragment().isAdded()) { + getPasswordPromptFragment().dismiss(); + } + getPasswordPromptFragment().show(getSupportFragmentManager(), PasswordPromptFragment.class.getName()); + } + + @JavascriptInterface + public void invalidPassword() { + runOnUiThread(PdfViewer.this::notifyInvalidPassword); + showPasswordPrompt(); + } + + @JavascriptInterface + public String getPassword() { + return mEncryptedDocumentPassword != null ? mEncryptedDocumentPassword : ""; + } + } + + private void notifyInvalidPassword() { + snackbar.setText(R.string.password_prompt_invalid_password).show(); } @Override @@ -241,6 +271,12 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader Log.d(TAG, "path " + path); if ("/placeholder.pdf".equals(path)) { + maybeCloseInputStream(); + try { + mInputStream = getContentResolver().openInputStream(mUri); + } catch (FileNotFoundException ignored) { + snackbar.setText(R.string.io_error).show(); + } return new WebResourceResponse("application/pdf", null, mInputStream); } @@ -274,6 +310,7 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader public void onPageFinished(WebView view, String url) { mDocumentState = STATE_LOADED; invalidateOptionsMenu(); + loadPdfWithPassword(mEncryptedDocumentPassword); } }); @@ -341,6 +378,7 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader mPage = savedInstanceState.getInt(STATE_PAGE); mZoomRatio = savedInstanceState.getFloat(STATE_ZOOM_RATIO); mDocumentOrientationDegrees = savedInstanceState.getInt(STATE_DOCUMENT_ORIENTATION_DEGREES); + mEncryptedDocumentPassword = savedInstanceState.getString(STATE_ENCRYPTED_DOCUMENT_PASSWORD); } if (mUri != null) { @@ -353,6 +391,38 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader } } + @Override + protected void onDestroy() { + super.onDestroy(); + binding.webview.removeJavascriptInterface("channel"); + binding.getRoot().removeView(binding.webview); + binding.webview.destroy(); + maybeCloseInputStream(); + } + + void maybeCloseInputStream() { + InputStream stream = mInputStream; + if (stream == null) { + return; + } + mInputStream = null; + try { + stream.close(); + } catch (IOException ignored) {} + } + + private PasswordPromptFragment getPasswordPromptFragment() { + if (mPasswordPromptFragment == null) { + final Fragment fragment = getSupportFragmentManager().findFragmentByTag(PasswordPromptFragment.class.getName()); + if (fragment != null) { + mPasswordPromptFragment = (PasswordPromptFragment) fragment; + } else { + mPasswordPromptFragment = new PasswordPromptFragment(); + } + } + return mPasswordPromptFragment; + } + @Override protected void onResume() { super.onResume(); @@ -403,10 +473,17 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader return; } + mDocumentState = 0; showSystemUi(); + invalidateOptionsMenu(); binding.webview.loadUrl("https://localhost/viewer.html"); } + public void loadPdfWithPassword(final String password) { + mEncryptedDocumentPassword = password; + binding.webview.evaluateJavascript("loadDocument()", null); + } + private void renderPage(final int zoom) { binding.webview.evaluateJavascript("onRenderPage(" + zoom + ")", null); } @@ -503,6 +580,7 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader savedInstanceState.putInt(STATE_PAGE, mPage); savedInstanceState.putFloat(STATE_ZOOM_RATIO, mZoomRatio); savedInstanceState.putInt(STATE_DOCUMENT_ORIENTATION_DEGREES, mDocumentOrientationDegrees); + savedInstanceState.putString(STATE_ENCRYPTED_DOCUMENT_PASSWORD, mEncryptedDocumentPassword); } private void showPageNumber() { diff --git a/app/src/main/java/app/grapheneos/pdfviewer/fragment/PasswordPromptFragment.kt b/app/src/main/java/app/grapheneos/pdfviewer/fragment/PasswordPromptFragment.kt new file mode 100644 index 0000000..545b5f0 --- /dev/null +++ b/app/src/main/java/app/grapheneos/pdfviewer/fragment/PasswordPromptFragment.kt @@ -0,0 +1,67 @@ +package app.grapheneos.pdfviewer.fragment + +import android.app.Dialog +import android.content.DialogInterface +import android.os.Bundle +import android.text.Editable +import android.text.TextUtils +import android.text.TextWatcher +import android.view.LayoutInflater +import android.view.WindowManager +import android.view.inputmethod.EditorInfo.IME_ACTION_DONE +import androidx.appcompat.app.AlertDialog +import androidx.fragment.app.DialogFragment +import app.grapheneos.pdfviewer.PdfViewer +import app.grapheneos.pdfviewer.R +import app.grapheneos.pdfviewer.databinding.PasswordDialogFragmentBinding +import com.google.android.material.textfield.TextInputEditText + +class PasswordPromptFragment : DialogFragment() { + + private lateinit var passwordEditText : TextInputEditText + + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + val passwordPrompt = AlertDialog.Builder(requireContext()) + val passwordDialogFragmentBinding = + PasswordDialogFragmentBinding.inflate(LayoutInflater.from(requireContext())) + passwordEditText = passwordDialogFragmentBinding.pdfPasswordEditText + passwordPrompt.setView(passwordDialogFragmentBinding.root) + passwordEditText.addTextChangedListener(object : TextWatcher { + override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {} + override fun onTextChanged(input: CharSequence, i: Int, i1: Int, i2: Int) { + updatePositiveButton() + } + override fun afterTextChanged(editable: Editable) {} + }) + passwordEditText.setOnEditorActionListener { _, actionId, _ -> + if (actionId != IME_ACTION_DONE) return@setOnEditorActionListener false + sendPassword() + true + } + passwordPrompt.setPositiveButton(R.string.open) { _, _ -> sendPassword() } + passwordPrompt.setNegativeButton(R.string.cancel, null) + val dialog = passwordPrompt.create() + dialog.setCanceledOnTouchOutside(false) + dialog.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE) + return dialog + } + + private fun updatePositiveButton() { + val btn = (dialog as AlertDialog).getButton(DialogInterface.BUTTON_POSITIVE) + btn.isEnabled = passwordEditText.text?.isNotEmpty() ?: false + } + + private fun sendPassword() { + val password = passwordEditText.text.toString() + if (!TextUtils.isEmpty(password)) { + (activity as PdfViewer).loadPdfWithPassword(password) + dialog?.dismiss() + } + } + + override fun onStart() { + super.onStart() + updatePositiveButton() + passwordEditText.requestFocus() + } +} diff --git a/app/src/main/res/layout/password_dialog_fragment.xml b/app/src/main/res/layout/password_dialog_fragment.xml new file mode 100644 index 0000000..a2448fd --- /dev/null +++ b/app/src/main/res/layout/password_dialog_fragment.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c750141..004fbb6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -24,4 +24,10 @@ WebView out-of-date Your current WebView version is %1$d. The WebView should be at least version %2$d for the PDF Viewer to work. + + Password + Enter the password to decrypt this PDF file + Invalid password + Open + Cancel From db98371c9d18156667ada1ebbc10d50e8b9a3d50 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Fri, 6 May 2022 07:00:16 -0400 Subject: [PATCH 16/19] increment version to 14 --- app/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 01fe6bd..f1e0110 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -39,7 +39,7 @@ android { applicationId = "app.grapheneos.pdfviewer" minSdk = 26 targetSdk = 32 - versionCode = 13 + versionCode = 14 versionName = versionCode.toString() resourceConfigurations.add("en") } From c6113df31ddfa4c24204f7714be7fe85e4b1bc0a Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Fri, 6 May 2022 07:15:06 -0400 Subject: [PATCH 17/19] extend Permissions Policy These aren't supported by Chromium yet but they're standardized and it makes sense to explicitly forbid them. --- app/src/main/java/app/grapheneos/pdfviewer/PdfViewer.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/app/grapheneos/pdfviewer/PdfViewer.java b/app/src/main/java/app/grapheneos/pdfviewer/PdfViewer.java index ceb67c2..1809a39 100644 --- a/app/src/main/java/app/grapheneos/pdfviewer/PdfViewer.java +++ b/app/src/main/java/app/grapheneos/pdfviewer/PdfViewer.java @@ -83,6 +83,7 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader "document-domain=(), " + "encrypted-media=(), " + "fullscreen=(), " + + "gamepad=(), " + "geolocation=(), " + "gyroscope=(), " + "hid=(), " + @@ -96,6 +97,7 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader "publickey-credentials-get=(), " + "screen-wake-lock=(), " + "serial=(), " + + "speaker-selection=(), " + "sync-xhr=(), " + "usb=(), " + "xr-spatial-tracking=()"; From 1a3e816cfc781c6a6afa501fa14c7843475cb049 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Fri, 6 May 2022 10:09:15 -0400 Subject: [PATCH 18/19] simplify error string for error while opening PDF --- app/src/main/java/app/grapheneos/pdfviewer/PdfViewer.java | 4 ++-- app/src/main/res/values/strings.xml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/app/grapheneos/pdfviewer/PdfViewer.java b/app/src/main/java/app/grapheneos/pdfviewer/PdfViewer.java index 1809a39..51f5de1 100644 --- a/app/src/main/java/app/grapheneos/pdfviewer/PdfViewer.java +++ b/app/src/main/java/app/grapheneos/pdfviewer/PdfViewer.java @@ -277,7 +277,7 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader try { mInputStream = getContentResolver().openInputStream(mUri); } catch (FileNotFoundException ignored) { - snackbar.setText(R.string.io_error).show(); + snackbar.setText(R.string.error_while_opening).show(); } return new WebResourceResponse("application/pdf", null, mInputStream); } @@ -471,7 +471,7 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader } mInputStream = getContentResolver().openInputStream(mUri); } catch (IOException e) { - snackbar.setText(R.string.io_error).show(); + snackbar.setText(R.string.error_while_opening).show(); return; } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 004fbb6..e68fa0f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -19,7 +19,7 @@ Cannot open file with invalid MIME type Cannot open legacy file paths from insecure apps - Received I/O error trying to open content + Error encountered trying to open content Error encountered while saving WebView out-of-date From 6a7982ce8039372b6719784c14ea870175c2283f Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Fri, 6 May 2022 10:12:07 -0400 Subject: [PATCH 19/19] move snackbar to root view --- app/src/main/java/app/grapheneos/pdfviewer/PdfViewer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/app/grapheneos/pdfviewer/PdfViewer.java b/app/src/main/java/app/grapheneos/pdfviewer/PdfViewer.java index 51f5de1..00bde52 100644 --- a/app/src/main/java/app/grapheneos/pdfviewer/PdfViewer.java +++ b/app/src/main/java/app/grapheneos/pdfviewer/PdfViewer.java @@ -363,7 +363,7 @@ public class PdfViewer extends AppCompatActivity implements LoaderManager.Loader // loader manager impl so that the result will be delivered. LoaderManager.getInstance(this); - snackbar = Snackbar.make(binding.webview, "", Snackbar.LENGTH_LONG); + snackbar = Snackbar.make(binding.getRoot(), "", Snackbar.LENGTH_LONG); final Intent intent = getIntent(); if (Intent.ACTION_VIEW.equals(intent.getAction())) {