Compare commits

...

16 Commits

Author SHA1 Message Date
Matéo Duparc 0f312347dd
libpdfviewer: update to PdfViewer 12 2022-03-06 21:39:38 +01:00
Daniel Micay e68880b45d add separate release target for Play Store 2022-02-25 12:26:41 -05:00
Daniel Micay 74a9f9983d increment version to 12 2022-02-25 11:20:16 -05:00
smdyv e6add76a9f Handle out-of-date WebView
Disable the open document menu item and show the user a relevant view.
2022-02-25 09:59:58 -05:00
Daniel Micay 2571335eeb increment version to 11 2022-02-23 17:15:05 -05:00
smdyv 6ed3aed8ad Display content edge-to-edge 2022-02-23 17:14:28 -05:00
dependabot[bot] 587d3a5c96 Bump gradle from 7.1.1 to 7.1.2
Bumps gradle from 7.1.1 to 7.1.2.

---
updated-dependencies:
- dependency-name: com.android.tools.build:gradle
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-23 14:15:56 -05:00
Daniel Micay d26851dfcf rename to app.grapheneos.pdfviewer 2022-02-23 08:50:50 -05:00
smdyv 660321cb38 Use vectors for menu icons
Material icons (rounded)
2022-02-20 12:23:43 -05:00
smdyv 7b0948383a Add margins to toolbar 2022-02-20 12:23:13 -05:00
smdyv 1fbfc86199 Disable animated layout changes for the top app bar
At least temporarily. Prevents unsightly layout shifts
2022-02-20 08:04:26 -05:00
smdyv 8453e2f2c6 Use M3 theme 2022-02-19 09:06:31 -05:00
smdyv 6468f5012f Use default window color in dark theme 2022-02-19 08:58:03 -05:00
MHShetty c7a0ae858e Use a grey background while viewing a document 2022-02-19 08:48:09 -05:00
smdyv f07b6350df Center canvas 2022-02-19 08:37:38 -05:00
smdyv c743c0d6a7 Create layout for the PDF viewer activity
Updating insets is no longer necessary because the layout reserves the
space for the top app bar and frees it up in full-screen mode so the
WebView can fill the entire screen.
2022-02-19 08:32:15 -05:00
60 changed files with 295 additions and 123 deletions

View File

@ -22,6 +22,13 @@ android {
keyAlias = keystoreProperties["keyAlias"] as String
keyPassword = keystoreProperties["keyPassword"] as String
}
create("play") {
storeFile = rootProject.file(keystoreProperties["storeFile"]!!)
storePassword = keystoreProperties["storePassword"] as String
keyAlias = keystoreProperties["uploadKeyAlias"] as String
keyPassword = keystoreProperties["uploadKeyPassword"] as String
}
}
}
@ -43,6 +50,13 @@ android {
}
}
create("play") {
initWith(getByName("release"))
if (useKeystoreProperties) {
signingConfig = signingConfigs.getByName("play")
}
}
buildFeatures {
viewBinding = true
}

View File

@ -2,6 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.grapheneos.pdfviewer"
android:targetSandboxVersion="2">
<original-package android:name="org.grapheneos.pdfviewer" />
<application>
<meta-data android:name="android.webkit.WebView.MetricsOptOut"
android:value="true" />

View File

@ -1,11 +1,11 @@
body, canvas, #padding {
body, canvas {
padding: 0;
margin: 0;
}
#padding {
min-width: 100%;
background: black;
canvas {
margin: auto;
display: block;
}
.textLayer {

View File

@ -7,7 +7,6 @@
<script src="pdf.js"></script>
</head>
<body>
<div id="padding"></div>
<canvas id="content"></canvas>
<div id="text" class="textLayer"></div>
<script src="viewer.js"></script>

View File

@ -2,7 +2,6 @@
pdfjsLib.GlobalWorkerOptions.workerSrc = "/pdf.worker.js";
const padding = document.getElementById("padding");
let pdfDoc = null;
let pageRendering = false;
let renderPending = false;
@ -56,7 +55,6 @@ function display(newCanvas, zoom) {
canvas.width = newCanvas.width;
canvas.style.height = newCanvas.style.height;
canvas.style.width = newCanvas.style.width;
padding.style.width = canvas.style.width;
canvas.getContext("2d", { alpha: false }).drawImage(newCanvas, 0, 0);
if (!zoom) {
scrollTo(0, 0);
@ -200,14 +198,6 @@ function isTextSelected() {
return window.getSelection().toString() !== "";
}
function updateInset() {
const windowInsetTop = channel.getWindowInsetTop() / window.devicePixelRatio + "px";
padding.style.paddingTop = windowInsetTop;
textLayerDiv.style.top = windowInsetTop;
}
updateInset();
pdfjsLib.getDocument("https://localhost/placeholder.pdf").promise.then(function(newDoc) {
pdfDoc = newDoc;
channel.setNumPages(pdfDoc.numPages);

View File

@ -1,16 +1,18 @@
package org.grapheneos.pdfviewer;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.webkit.CookieManager;
import android.webkit.JavascriptInterface;
import android.webkit.WebResourceRequest;
@ -22,11 +24,12 @@ import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.loader.app.LoaderManager;
import androidx.loader.content.Loader;
import org.grapheneos.pdfviewer.databinding.PdfviewerBinding;
import org.grapheneos.pdfviewer.fragment.DocumentPropertiesFragment;
import org.grapheneos.pdfviewer.fragment.JumpToPageFragment;
import org.grapheneos.pdfviewer.loader.DocumentPropertiesLoader;
@ -36,10 +39,11 @@ import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
public class PdfViewer extends WebView implements LoaderManager.LoaderCallbacks<List<CharSequence>> {
public class PdfViewer implements LoaderManager.LoaderCallbacks<List<CharSequence>> {
public static final String TAG = "PdfViewer";
private static final String KEY_PROPERTIES = "properties";
private static final int MIN_WEBVIEW_RELEASE = 89;
private static final String CONTENT_SECURITY_POLICY =
"default-src 'none'; " +
@ -93,31 +97,64 @@ public class PdfViewer extends WebView implements LoaderManager.LoaderCallbacks<
private float mZoomRatio = 1f;
private int mDocumentOrientationDegrees;
private int mDocumentState;
private int windowInsetTop;
private List<CharSequence> mDocumentProperties;
private InputStream mInputStream;
private PdfviewerBinding binding;
private TextView mTextView;
private Toast mToast;
public AppCompatActivity activity;
AppCompatActivity activity;
String fileName;
Long fileSize;
void init(Context context) {
setBackgroundColor(Color.TRANSPARENT);
private class Channel {
@JavascriptInterface
public int getPage() {
return mPage;
}
@JavascriptInterface
public float getZoomRatio() {
return mZoomRatio;
}
@JavascriptInterface
public int getDocumentOrientationDegrees() {
return mDocumentOrientationDegrees;
}
@JavascriptInterface
public void setNumPages(int numPages) {
mNumPages = numPages;
activity.runOnUiThread(activity::invalidateOptionsMenu);
}
@JavascriptInterface
public void setDocumentProperties(final String properties) {
if (mDocumentProperties != null) {
throw new SecurityException("mDocumentProperties not null");
}
final Bundle args = new Bundle();
args.putString(KEY_PROPERTIES, properties);
activity.runOnUiThread(() -> LoaderManager.getInstance(PdfViewer.this.activity).restartLoader(DocumentPropertiesLoader.ID, args, PdfViewer.this));
}
}
public PdfViewer(@NonNull AppCompatActivity activity) {
this.activity = activity;
LayoutInflater inflater = activity.getLayoutInflater();
binding = PdfviewerBinding.inflate(inflater);
activity.setContentView(binding.getRoot());
binding.webview.setBackgroundColor(Color.TRANSPARENT);
if (BuildConfig.DEBUG) {
WebView.setWebContentsDebuggingEnabled(true);
}
setOnApplyWindowInsetsListener((view, insets) -> {
windowInsetTop = insets.getSystemWindowInsetTop();
evaluateJavascript("updateInset()", null);
return insets;
});
final WebSettings settings = getSettings();
final WebSettings settings = binding.webview.getSettings();
settings.setAllowContentAccess(false);
settings.setAllowFileAccess(false);
settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
@ -125,12 +162,12 @@ public class PdfViewer extends WebView implements LoaderManager.LoaderCallbacks<
CookieManager.getInstance().setAcceptCookie(false);
addJavascriptInterface(new Channel(), "channel");
binding.webview.addJavascriptInterface(new Channel(), "channel");
setWebViewClient(new WebViewClient() {
binding.webview.setWebViewClient(new WebViewClient() {
private WebResourceResponse fromAsset(final String mime, final String path) {
try {
InputStream inputStream = context.getAssets().open(path.substring(1));
InputStream inputStream = activity.getAssets().open(path.substring(1));
return new WebResourceResponse(mime, null, inputStream);
} catch (IOException e) {
return null;
@ -188,7 +225,7 @@ public class PdfViewer extends WebView implements LoaderManager.LoaderCallbacks<
}
});
GestureHelper.attach(context, this,
GestureHelper.attach(activity, binding.webview,
new GestureHelper.GestureListener() {
@Override
public void onZoomIn(float value) {
@ -206,72 +243,40 @@ public class PdfViewer extends WebView implements LoaderManager.LoaderCallbacks<
}
});
mTextView = new TextView(context);
mTextView = new TextView(activity);
mTextView.setBackgroundColor(Color.DKGRAY);
mTextView.setTextColor(ColorStateList.valueOf(Color.WHITE));
mTextView.setTextSize(18);
mTextView.setPadding(PADDING, 0, PADDING, 0);
}
public PdfViewer(@NonNull Context context) {
super(context);
init(context);
}
public PdfViewer(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context);
}
public PdfViewer(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
public void onCreateOptionMenu(Menu menu) {
MenuInflater inflater = activity.getMenuInflater();
inflater.inflate(R.menu.pdf_viewer, menu);
}
private class Channel {
@JavascriptInterface
public int getWindowInsetTop() {
return windowInsetTop;
}
@JavascriptInterface
public int getPage() {
return mPage;
}
@JavascriptInterface
public float getZoomRatio() {
return mZoomRatio;
}
@JavascriptInterface
public int getDocumentOrientationDegrees() {
return mDocumentOrientationDegrees;
}
@JavascriptInterface
public void setNumPages(int numPages) {
mNumPages = numPages;
activity.runOnUiThread(activity::invalidateOptionsMenu);
}
@JavascriptInterface
public void setDocumentProperties(final String properties) {
if (mDocumentProperties != null) {
throw new SecurityException("mDocumentProperties not null");
public void onResume() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// The user could have left the activity to update the WebView
activity.invalidateOptionsMenu();
if (getWebViewRelease() >= MIN_WEBVIEW_RELEASE) {
binding.webviewOutOfDateLayout.setVisibility(View.GONE);
binding.webview.setVisibility(View.VISIBLE);
} else {
binding.webview.setVisibility(View.GONE);
binding.webviewOutOfDateMessage.setText(activity.getString(R.string.webview_out_of_date_message, getWebViewRelease(), MIN_WEBVIEW_RELEASE));
binding.webviewOutOfDateLayout.setVisibility(View.VISIBLE);
}
final Bundle args = new Bundle();
args.putString(KEY_PROPERTIES, properties);
activity.runOnUiThread(() -> LoaderManager.getInstance(PdfViewer.this.activity).restartLoader(DocumentPropertiesLoader.ID, args, PdfViewer.this));
}
}
@RequiresApi(api = Build.VERSION_CODES.O)
private int getWebViewRelease() {
PackageInfo webViewPackage = WebView.getCurrentWebViewPackage();
String webViewVersionName = webViewPackage.versionName;
return Integer.parseInt(webViewVersionName.substring(0, webViewVersionName.indexOf(".")));
}
@NonNull
@Override
public Loader<List<CharSequence>> onCreateLoader(int id, Bundle args) {
@ -295,12 +300,12 @@ public class PdfViewer extends WebView implements LoaderManager.LoaderCallbacks<
mInputStream = inputStream;
this.fileName = fileName;
this.fileSize = fileSize;
loadUrl("https://localhost/viewer.html");
binding.webview.loadUrl("https://localhost/viewer.html");
activity.invalidateOptionsMenu();
}
private void renderPage(final int zoom) {
evaluateJavascript("onRenderPage(" + zoom + ")", null);
binding.webview.evaluateJavascript("onRenderPage(" + zoom + ")", null);
}
private void documentOrientationChanged(final int orientationDegreesOffset) {

View File

@ -6,14 +6,15 @@ import android.os.Bundle;
import android.widget.ArrayAdapter;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.grapheneos.pdfviewer.R;
import java.util.ArrayList;
import java.util.List;
import org.grapheneos.pdfviewer.R;
public class DocumentPropertiesFragment extends DialogFragment {
public static final String TAG = "DocumentPropertiesFragment";
@ -44,7 +45,7 @@ public class DocumentPropertiesFragment extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Activity activity = requireActivity();
final AlertDialog.Builder dialog = new AlertDialog.Builder(activity)
final MaterialAlertDialogBuilder dialog = new MaterialAlertDialogBuilder(activity)
.setPositiveButton(android.R.string.ok, null);
if (mDocumentProperties != null) {

View File

@ -7,9 +7,10 @@ import android.widget.FrameLayout;
import android.widget.NumberPicker;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.grapheneos.pdfviewer.PdfViewer;
public class JumpToPageFragment extends DialogFragment {
@ -42,7 +43,7 @@ public class JumpToPageFragment extends DialogFragment {
FrameLayout.LayoutParams.WRAP_CONTENT,
Gravity.CENTER));
return new AlertDialog.Builder(requireActivity())
return new MaterialAlertDialogBuilder(requireActivity())
.setView(layout)
.setPositiveButton(android.R.string.ok, (dialogInterface, i) -> {
mPicker.clearFocus();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 132 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 360 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 433 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 427 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 422 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 412 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 116 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 226 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 271 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 272 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 249 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 136 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 392 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 536 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 535 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 486 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 470 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 213 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 601 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 798 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 787 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 737 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 731 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 197 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 206 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 770 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 954 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 925 B

View File

@ -1,10 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M18.41,16.59L13.82,12l4.59,-4.59L17,6l-6,6 6,6zM6,6h2v12H6z"/>
</vector>

View File

@ -1,10 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M5.59,7.41L10.18,12l-4.59,4.59L7,18l6,-6 -6,-6zM16,6h2v12h-2z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#000000"
android:pathData="M12,7c0.55,0 1,0.45 1,1v4c0,0.55 -0.45,1 -1,1s-1,-0.45 -1,-1L11,8c0,-0.55 0.45,-1 1,-1zM11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8zM13,17h-2v-2h2v2z" />
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?attr/colorControlNormal"
android:pathData="M17.7,15.89L13.82,12l3.89,-3.89c0.39,-0.39 0.39,-1.02 0,-1.41 -0.39,-0.39 -1.02,-0.39 -1.41,0l-4.59,4.59c-0.39,0.39 -0.39,1.02 0,1.41l4.59,4.59c0.39,0.39 1.02,0.39 1.41,0 0.38,-0.38 0.38,-1.02 -0.01,-1.4zM7,6c0.55,0 1,0.45 1,1v10c0,0.55 -0.45,1 -1,1s-1,-0.45 -1,-1V7c0,-0.55 0.45,-1 1,-1z" />
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?attr/colorControlNormal"
android:pathData="M6,2c-1.1,0 -1.99,0.9 -1.99,2L4,20c0,1.1 0.89,2 1.99,2L18,22c1.1,0 2,-0.9 2,-2L20,8.83c0,-0.53 -0.21,-1.04 -0.59,-1.41l-4.83,-4.83c-0.37,-0.38 -0.88,-0.59 -1.41,-0.59L6,2zM13,8L13,3.5L18.5,9L14,9c-0.55,0 -1,-0.45 -1,-1z" />
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?attr/colorControlNormal"
android:pathData="M6.29,8.11L10.18,12l-3.89,3.89c-0.39,0.39 -0.39,1.02 0,1.41 0.39,0.39 1.02,0.39 1.41,0l4.59,-4.59c0.39,-0.39 0.39,-1.02 0,-1.41L7.7,6.7c-0.39,-0.39 -1.02,-0.39 -1.41,0 -0.38,0.39 -0.38,1.03 0,1.41zM17,6c0.55,0 1,0.45 1,1v10c0,0.55 -0.45,1 -1,1s-1,-0.45 -1,-1V7c0,-0.55 0.45,-1 1,-1z" />
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?attr/colorControlNormal"
android:pathData="M14.91,6.71c-0.39,-0.39 -1.02,-0.39 -1.41,0L8.91,11.3c-0.39,0.39 -0.39,1.02 0,1.41l4.59,4.59c0.39,0.39 1.02,0.39 1.41,0 0.39,-0.39 0.39,-1.02 0,-1.41L11.03,12l3.88,-3.88c0.38,-0.39 0.38,-1.03 0,-1.41z" />
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?attr/colorControlNormal"
android:pathData="M9.31,6.71c-0.39,0.39 -0.39,1.02 0,1.41L13.19,12l-3.88,3.88c-0.39,0.39 -0.39,1.02 0,1.41 0.39,0.39 1.02,0.39 1.41,0l4.59,-4.59c0.39,-0.39 0.39,-1.02 0,-1.41L10.72,6.7c-0.38,-0.38 -1.02,-0.38 -1.41,0.01z" />
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?attr/colorControlNormal"
android:pathData="M11.5,9C10.12,9 9,10.12 9,11.5s1.12,2.5 2.5,2.5 2.5,-1.12 2.5,-2.5S12.88,9 11.5,9zM20,4L4,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2zM16.08,17.5l-2.2,-2.2c-0.9,0.58 -2.03,0.84 -3.22,0.62 -1.88,-0.35 -3.38,-1.93 -3.62,-3.83 -0.38,-3.01 2.18,-5.52 5.21,-5.04 1.88,0.3 3.39,1.84 3.7,3.71 0.19,1.16 -0.08,2.23 -0.64,3.12l2.2,2.19c0.39,0.39 0.39,1.03 0,1.42 -0.4,0.4 -1.04,0.4 -1.43,0.01z" />
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?attr/colorControlNormal"
android:pathData="M6.56,7.98C6.1,7.52 5.31,7.6 5,8.17c-0.28,0.51 -0.5,1.03 -0.67,1.58 -0.19,0.63 0.31,1.25 0.96,1.25h0.01c0.43,0 0.82,-0.28 0.94,-0.7 0.12,-0.4 0.28,-0.79 0.48,-1.17 0.22,-0.37 0.15,-0.84 -0.16,-1.15zM5.31,13h-0.02c-0.65,0 -1.15,0.62 -0.96,1.25 0.16,0.54 0.38,1.07 0.66,1.58 0.31,0.57 1.11,0.66 1.57,0.2 0.3,-0.31 0.38,-0.77 0.17,-1.15 -0.2,-0.37 -0.36,-0.76 -0.48,-1.16 -0.12,-0.44 -0.51,-0.72 -0.94,-0.72zM8.16,19.02c0.51,0.28 1.04,0.5 1.59,0.66 0.62,0.18 1.24,-0.32 1.24,-0.96v-0.03c0,-0.43 -0.28,-0.82 -0.7,-0.94 -0.4,-0.12 -0.78,-0.28 -1.15,-0.48 -0.38,-0.21 -0.86,-0.14 -1.16,0.17l-0.03,0.03c-0.45,0.45 -0.36,1.24 0.21,1.55zM13,4.07v-0.66c0,-0.89 -1.08,-1.34 -1.71,-0.71L9.17,4.83c-0.4,0.4 -0.4,1.04 0,1.43l2.13,2.08c0.63,0.62 1.7,0.17 1.7,-0.72L13,6.09c2.84,0.48 5,2.94 5,5.91 0,2.73 -1.82,5.02 -4.32,5.75 -0.41,0.12 -0.68,0.51 -0.68,0.94v0.02c0,0.65 0.61,1.14 1.23,0.96C17.57,18.71 20,15.64 20,12c0,-4.08 -3.05,-7.44 -7,-7.93z" />
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?attr/colorControlNormal"
android:pathData="M14.83,4.83L12.7,2.7c-0.62,-0.62 -1.7,-0.18 -1.7,0.71v0.66C7.06,4.56 4,7.92 4,12c0,3.64 2.43,6.71 5.77,7.68 0.62,0.18 1.23,-0.32 1.23,-0.96v-0.03c0,-0.43 -0.27,-0.82 -0.68,-0.94C7.82,17.03 6,14.73 6,12c0,-2.97 2.16,-5.43 5,-5.91v1.53c0,0.89 1.07,1.33 1.7,0.71l2.13,-2.08c0.4,-0.38 0.4,-1.02 0,-1.42zM19.67,9.76c-0.16,-0.55 -0.38,-1.08 -0.66,-1.59 -0.31,-0.57 -1.1,-0.66 -1.56,-0.2l-0.01,0.01c-0.31,0.31 -0.38,0.78 -0.17,1.16 0.2,0.37 0.36,0.76 0.48,1.16 0.12,0.42 0.51,0.7 0.94,0.7h0.02c0.65,0 1.15,-0.62 0.96,-1.24zM13,18.68v0.02c0,0.65 0.62,1.14 1.24,0.96 0.55,-0.16 1.08,-0.38 1.59,-0.66 0.57,-0.31 0.66,-1.1 0.2,-1.56l-0.02,-0.02c-0.31,-0.31 -0.78,-0.38 -1.16,-0.17 -0.37,0.21 -0.76,0.37 -1.16,0.49 -0.41,0.12 -0.69,0.51 -0.69,0.94zM17.44,16.03c0.46,0.46 1.25,0.37 1.56,-0.2 0.28,-0.51 0.5,-1.04 0.67,-1.59 0.18,-0.62 -0.31,-1.24 -0.96,-1.24h-0.02c-0.44,0 -0.82,0.28 -0.94,0.7 -0.12,0.4 -0.28,0.79 -0.48,1.17 -0.21,0.38 -0.13,0.86 0.17,1.16z" />
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?attr/colorControlNormal"
android:pathData="M15.5,14h-0.79l-0.28,-0.27c1.2,-1.4 1.82,-3.31 1.48,-5.34 -0.47,-2.78 -2.79,-5 -5.59,-5.34 -4.23,-0.52 -7.78,3.04 -7.27,7.27 0.34,2.8 2.56,5.12 5.34,5.59 2.03,0.34 3.94,-0.28 5.34,-1.48l0.27,0.28v0.79l4.26,4.25c0.41,0.41 1.07,0.41 1.48,0l0.01,-0.01c0.41,-0.41 0.41,-1.07 0,-1.48L15.5,14zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14zM9.5,7c-0.28,0 -0.5,0.22 -0.5,0.5L9,9L7.5,9c-0.28,0 -0.5,0.22 -0.5,0.5s0.22,0.5 0.5,0.5L9,10v1.5c0,0.28 0.22,0.5 0.5,0.5s0.5,-0.22 0.5,-0.5L10,10h1.5c0.28,0 0.5,-0.22 0.5,-0.5s-0.22,-0.5 -0.5,-0.5L10,9L10,7.5c0,-0.28 -0.22,-0.5 -0.5,-0.5z" />
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?attr/colorControlNormal"
android:pathData="M15.5,14h-0.79l-0.28,-0.27c1.2,-1.4 1.82,-3.31 1.48,-5.34 -0.47,-2.78 -2.79,-5 -5.59,-5.34 -4.23,-0.52 -7.79,3.04 -7.27,7.27 0.34,2.8 2.56,5.12 5.34,5.59 2.03,0.34 3.94,-0.28 5.34,-1.48l0.27,0.28v0.79l4.26,4.25c0.41,0.41 1.07,0.41 1.48,0l0.01,-0.01c0.41,-0.41 0.41,-1.07 0,-1.48L15.5,14zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14zM7.5,9h4c0.28,0 0.5,0.22 0.5,0.5s-0.22,0.5 -0.5,0.5h-4c-0.28,0 -0.5,-0.22 -0.5,-0.5s0.22,-0.5 0.5,-0.5z" />
</vector>

View File

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<ScrollView
android:id="@+id/webview_out_of_date_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:visibility="gone"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/error_image_view"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_marginTop="32dp"
android:importantForAccessibility="no"
android:src="@drawable/ic_error_outline_24dp"
app:layout_constraintBottom_toTopOf="@id/webview_out_of_date_title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed"
app:tint="?attr/colorPrimary" />
<TextView
android:id="@+id/webview_out_of_date_title"
style="@style/TextAppearance.Material3.TitleLarge"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="32dp"
android:elegantTextHeight="true"
android:gravity="center"
android:text="@string/webview_out_of_date_title"
app:layout_constraintBottom_toTopOf="@id/webview_out_of_date_message"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/error_image_view" />
<TextView
android:id="@+id/webview_out_of_date_message"
style="@style/TextAppearance.Material3.BodyMedium"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="32dp"
android:layout_marginBottom="32dp"
android:elegantTextHeight="true"
android:gravity="center"
android:lineSpacingMultiplier="1.2"
android:text="@string/webview_out_of_date_message"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/webview_out_of_date_title" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -9,55 +9,55 @@
<item
android:id="@+id/action_previous"
android:icon="@drawable/ic_navigate_before_white_24dp"
android:icon="@drawable/ic_navigate_before_24dp"
android:title="@string/action_previous"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_next"
android:icon="@drawable/ic_navigate_next_white_24dp"
android:icon="@drawable/ic_navigate_next_24dp"
android:title="@string/action_next"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_zoom_out"
android:icon="@drawable/ic_zoom_out_white_24dp"
android:icon="@drawable/ic_zoom_out_24dp"
android:title="@string/action_zoom_out"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_zoom_in"
android:icon="@drawable/ic_zoom_in_white_24dp"
android:icon="@drawable/ic_zoom_in_24dp"
android:title="@string/action_zoom_in"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_first"
android:icon="@drawable/baseline_first_page_24"
android:icon="@drawable/ic_first_page_24dp"
android:title="@string/action_first"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_last"
android:icon="@drawable/baseline_last_page_24"
android:icon="@drawable/ic_last_page_24dp"
android:title="@string/action_last"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_jump_to_page"
android:icon="@drawable/ic_pageview_white_24dp"
android:icon="@drawable/ic_pageview_24dp"
android:title="@string/action_jump_to_page"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_rotate_clockwise"
android:icon="@drawable/ic_rotate_right_white_24dp"
android:icon="@drawable/ic_rotate_right_24dp"
android:title="@string/action_rotate_clockwise"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_rotate_counterclockwise"
android:icon="@drawable/ic_rotate_left_white_24dp"
android:icon="@drawable/ic_rotate_left_24dp"
android:title="@string/action_rotate_counterclockwise"
app:showAsAction="ifRoom" />

View File

@ -19,4 +19,7 @@
<string name="invalid_mime_type">Cannot open file with invalid MIME type</string>
<string name="legacy_file_uri">Cannot open legacy file paths from insecure apps</string>
<string name="io_error">Received I/O error trying to open content</string>
<string name="webview_out_of_date_title">WebView out-of-date</string>
<string name="webview_out_of_date_message">Your current WebView version is %d. The WebView should be at least version %d for the PDF Viewer to work.</string>
</resources>

View File

@ -4,7 +4,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath("com.android.tools.build:gradle:7.1.1")
classpath("com.android.tools.build:gradle:7.1.2")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10")
}
}