Compare commits
42 Commits
06e54dbb03
...
2766000ebc
Author | SHA1 | Date |
---|---|---|
Matéo Duparc | 2766000ebc | |
Daniel Micay | 9e40a05be3 | |
Pratyush | 18761b3e4a | |
Pratyush | 43f971c028 | |
Pratyush | 2b81d4dcc3 | |
Pratyush | 5a55c8045b | |
Pratyush | 718b448cc5 | |
Pratyush | afaf71a4a2 | |
Pratyush | 8a308b69e5 | |
dependabot[bot] | ea5c34ed52 | |
Daniel Micay | fee1b1516f | |
dependabot[bot] | bc77ecbcc6 | |
Daniel Micay | 955bed3614 | |
Daniel Micay | ee3605428e | |
Daniel Micay | e967af2397 | |
Daniel Micay | 9ea5cb1802 | |
Daniel Micay | a307f2892c | |
Pratyush | 8c795d4552 | |
Daniel Micay | d7ca71770f | |
Daniel Micay | a29ec202a7 | |
Pratyush | ea9a57fabe | |
Pratyush | 68fc48d3a9 | |
quh4gko8 | 3ebdfd0a11 | |
quh4gko8 | ff11df007f | |
Daniel Micay | fa2db54804 | |
Patryk Mis | 7634c00f59 | |
Daniel Micay | f67021e975 | |
dependabot[bot] | adb87cbaef | |
Daniel Micay | 09ccfb069d | |
Daniel Micay | 2a91d95eef | |
dependabot[bot] | a48213c450 | |
dependabot[bot] | 2f4c1ebfed | |
Daniel Micay | 22b400c68f | |
Daniel Micay | 6a6a263b0b | |
Daniel Micay | 8cd685c8c7 | |
Daniel Micay | be3f43e7a4 | |
Daniel Micay | 5eb98841d6 | |
Daniel Micay | e297fdf7e4 | |
Daniel Micay | 9355f54956 | |
dependabot[bot] | 5dfdaa2c17 | |
June | 3411fb0426 | |
dependabot[bot] | af567a5c0c |
|
@ -32,12 +32,14 @@ android {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
compileSdk = 32
|
compileSdk = 33
|
||||||
buildToolsVersion = "32.0.0"
|
buildToolsVersion = "33.0.0"
|
||||||
|
|
||||||
|
namespace = "app.grapheneos.pdfviewer"
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdk = 21
|
minSdk = 21
|
||||||
targetSdk = 32
|
targetSdk = 33
|
||||||
resourceConfigurations.add("en")
|
resourceConfigurations.add("en")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,6 +75,6 @@ android {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("androidx.appcompat:appcompat:1.4.1")
|
implementation("androidx.appcompat:appcompat:1.5.1")
|
||||||
implementation("com.google.android.material:material:1.5.0")
|
implementation("com.google.android.material:material:1.6.1")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
<lint>
|
<lint>
|
||||||
<!-- full backups are desired -->
|
<!-- overly aggressive check -->
|
||||||
<issue id="AllowBackup">
|
<issue id="VectorPath">
|
||||||
<ignore path="src/main/AndroidManifest.xml"/>
|
<ignore path="src/main/res/drawable/ic_rotate_left_24dp.xml"/>
|
||||||
|
<ignore path="src/main/res/drawable/ic_rotate_right_24dp.xml"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
<!-- Google app indexing doesn't make any sense for this app -->
|
<!-- Google app indexing doesn't make any sense for this app -->
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 070a365be5a7579f4ddd5a9a2d4efcd281c2d64f
|
Subproject commit cc3d3bf299ae11f8f72ae8d64cbf19b340f9a996
|
|
@ -1,6 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="app.grapheneos.pdfviewer"
|
|
||||||
android:targetSandboxVersion="2">
|
android:targetSandboxVersion="2">
|
||||||
<original-package android:name="org.grapheneos.pdfviewer" />
|
<original-package android:name="org.grapheneos.pdfviewer" />
|
||||||
|
|
||||||
|
|
|
@ -210,6 +210,7 @@ function loadDocument() {
|
||||||
}
|
}
|
||||||
|
|
||||||
loadingTask.promise.then(function (newDoc) {
|
loadingTask.promise.then(function (newDoc) {
|
||||||
|
channel.onLoaded();
|
||||||
pdfDoc = newDoc;
|
pdfDoc = newDoc;
|
||||||
channel.setNumPages(pdfDoc.numPages);
|
channel.setNumPages(pdfDoc.numPages);
|
||||||
pdfDoc.getMetadata().then(function (data) {
|
pdfDoc.getMetadata().then(function (data) {
|
||||||
|
|
|
@ -31,6 +31,7 @@ import androidx.core.view.ViewCompat;
|
||||||
import androidx.core.view.WindowCompat;
|
import androidx.core.view.WindowCompat;
|
||||||
import androidx.core.view.WindowInsetsCompat;
|
import androidx.core.view.WindowInsetsCompat;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.loader.app.LoaderManager;
|
import androidx.loader.app.LoaderManager;
|
||||||
import androidx.loader.content.Loader;
|
import androidx.loader.content.Loader;
|
||||||
|
|
||||||
|
@ -40,7 +41,9 @@ import app.grapheneos.pdfviewer.databinding.PdfviewerBinding;
|
||||||
import app.grapheneos.pdfviewer.fragment.DocumentPropertiesFragment;
|
import app.grapheneos.pdfviewer.fragment.DocumentPropertiesFragment;
|
||||||
import app.grapheneos.pdfviewer.fragment.PasswordPromptFragment;
|
import app.grapheneos.pdfviewer.fragment.PasswordPromptFragment;
|
||||||
import app.grapheneos.pdfviewer.fragment.JumpToPageFragment;
|
import app.grapheneos.pdfviewer.fragment.JumpToPageFragment;
|
||||||
|
import app.grapheneos.pdfviewer.ktx.ViewKt;
|
||||||
import app.grapheneos.pdfviewer.loader.DocumentPropertiesLoader;
|
import app.grapheneos.pdfviewer.loader.DocumentPropertiesLoader;
|
||||||
|
import app.grapheneos.pdfviewer.viewModel.PasswordStatus;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -119,8 +122,8 @@ public class PdfViewer implements LoaderManager.LoaderCallbacks<List<CharSequenc
|
||||||
AppCompatActivity activity;
|
AppCompatActivity activity;
|
||||||
String fileName;
|
String fileName;
|
||||||
Long fileSize;
|
Long fileSize;
|
||||||
private Snackbar snackbar;
|
|
||||||
private PasswordPromptFragment mPasswordPromptFragment;
|
private PasswordPromptFragment mPasswordPromptFragment;
|
||||||
|
public PasswordStatus passwordValidationViewModel;
|
||||||
|
|
||||||
private class Channel {
|
private class Channel {
|
||||||
@JavascriptInterface
|
@JavascriptInterface
|
||||||
|
@ -157,16 +160,23 @@ public class PdfViewer implements LoaderManager.LoaderCallbacks<List<CharSequenc
|
||||||
|
|
||||||
@JavascriptInterface
|
@JavascriptInterface
|
||||||
public void showPasswordPrompt() {
|
public void showPasswordPrompt() {
|
||||||
if (getPasswordPromptFragment().isAdded()) {
|
if (!getPasswordPromptFragment().isAdded()) {
|
||||||
getPasswordPromptFragment().dismiss();
|
getPasswordPromptFragment().show(activity.getSupportFragmentManager(), PasswordPromptFragment.class.getName());
|
||||||
}
|
}
|
||||||
getPasswordPromptFragment().show(activity.getSupportFragmentManager(), PasswordPromptFragment.class.getName());
|
passwordValidationViewModel.passwordMissing();
|
||||||
}
|
}
|
||||||
|
|
||||||
@JavascriptInterface
|
@JavascriptInterface
|
||||||
public void invalidPassword() {
|
public void invalidPassword() {
|
||||||
activity.runOnUiThread(PdfViewer.this::notifyInvalidPassword);
|
activity.runOnUiThread(() -> passwordValidationViewModel.invalid());
|
||||||
showPasswordPrompt();
|
}
|
||||||
|
|
||||||
|
@JavascriptInterface
|
||||||
|
public void onLoaded() {
|
||||||
|
passwordValidationViewModel.validated();
|
||||||
|
if (getPasswordPromptFragment().isAdded()) {
|
||||||
|
getPasswordPromptFragment().dismiss();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JavascriptInterface
|
@JavascriptInterface
|
||||||
|
@ -175,15 +185,12 @@ public class PdfViewer implements LoaderManager.LoaderCallbacks<List<CharSequenc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notifyInvalidPassword() {
|
|
||||||
snackbar.setText(R.string.password_prompt_invalid_password).show();
|
|
||||||
}
|
|
||||||
|
|
||||||
public PdfViewer(@NonNull AppCompatActivity activity) {
|
public PdfViewer(@NonNull AppCompatActivity activity) {
|
||||||
this.activity = activity;
|
this.activity = activity;
|
||||||
binding = PdfviewerBinding.inflate(activity.getLayoutInflater());
|
binding = PdfviewerBinding.inflate(activity.getLayoutInflater());
|
||||||
activity.setContentView(binding.getRoot());
|
activity.setContentView(binding.getRoot());
|
||||||
activity.setSupportActionBar(binding.toolbar);
|
activity.setSupportActionBar(binding.toolbar);
|
||||||
|
passwordValidationViewModel = new ViewModelProvider(activity, ViewModelProvider.AndroidViewModelFactory.getInstance(activity.getApplication())).get(PasswordStatus.class);
|
||||||
|
|
||||||
WindowCompat.setDecorFitsSystemWindows(activity.getWindow(), false);
|
WindowCompat.setDecorFitsSystemWindows(activity.getWindow(), false);
|
||||||
|
|
||||||
|
@ -283,8 +290,7 @@ public class PdfViewer implements LoaderManager.LoaderCallbacks<List<CharSequenc
|
||||||
public boolean onTapUp() {
|
public boolean onTapUp() {
|
||||||
binding.webview.evaluateJavascript("isTextSelected()", selection -> {
|
binding.webview.evaluateJavascript("isTextSelected()", selection -> {
|
||||||
if (!Boolean.parseBoolean(selection)) {
|
if (!Boolean.parseBoolean(selection)) {
|
||||||
if ((activity.getWindow().getDecorView().getSystemUiVisibility() &
|
if (activity.getSupportActionBar().isShowing()) {
|
||||||
View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
|
|
||||||
hideSystemUi();
|
hideSystemUi();
|
||||||
} else {
|
} else {
|
||||||
showSystemUi();
|
showSystemUi();
|
||||||
|
@ -315,8 +321,6 @@ public class PdfViewer implements LoaderManager.LoaderCallbacks<List<CharSequenc
|
||||||
mTextView.setTextColor(ColorStateList.valueOf(Color.WHITE));
|
mTextView.setTextColor(ColorStateList.valueOf(Color.WHITE));
|
||||||
mTextView.setTextSize(18);
|
mTextView.setTextSize(18);
|
||||||
mTextView.setPadding(PADDING, 0, PADDING, 0);
|
mTextView.setPadding(PADDING, 0, PADDING, 0);
|
||||||
|
|
||||||
snackbar = Snackbar.make(binding.getRoot(), "", Snackbar.LENGTH_LONG);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
|
@ -456,21 +460,12 @@ public class PdfViewer implements LoaderManager.LoaderCallbacks<List<CharSequenc
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showSystemUi() {
|
private void showSystemUi() {
|
||||||
activity.getWindow().getDecorView().setSystemUiVisibility(
|
ViewKt.showSystemUi(binding.getRoot());
|
||||||
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
|
|
||||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
|
|
||||||
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
|
|
||||||
activity.getSupportActionBar().show();
|
activity.getSupportActionBar().show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void hideSystemUi() {
|
private void hideSystemUi() {
|
||||||
activity.getWindow().getDecorView().setSystemUiVisibility(
|
ViewKt.hideSystemUi(binding.getRoot());
|
||||||
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
|
|
||||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
|
|
||||||
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
|
|
||||||
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
|
|
||||||
View.SYSTEM_UI_FLAG_FULLSCREEN |
|
|
||||||
View.SYSTEM_UI_FLAG_IMMERSIVE);
|
|
||||||
activity.getSupportActionBar().hide();
|
activity.getSupportActionBar().hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,14 +39,13 @@ public class Utils {
|
||||||
|
|
||||||
final Calendar calendar = Calendar.getInstance();
|
final Calendar calendar = Calendar.getInstance();
|
||||||
final int currentYear = calendar.get(Calendar.YEAR);
|
final int currentYear = calendar.get(Calendar.YEAR);
|
||||||
int year;
|
|
||||||
|
|
||||||
// Year is required
|
// Year is required
|
||||||
String field = date.substring(position += 2, 6);
|
String field = date.substring(position += 2, 6);
|
||||||
if (!TextUtils.isDigitsOnly(field)) {
|
if (!TextUtils.isDigitsOnly(field)) {
|
||||||
throw new ParseException("Invalid year", position);
|
throw new ParseException("Invalid year", position);
|
||||||
}
|
}
|
||||||
year = Integer.parseInt(field);
|
int year = Integer.parseInt(field);
|
||||||
if (year > currentYear) {
|
if (year > currentYear) {
|
||||||
year = currentYear;
|
year = currentYear;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,15 +15,21 @@ import androidx.fragment.app.DialogFragment
|
||||||
import app.grapheneos.pdfviewer.PdfViewer
|
import app.grapheneos.pdfviewer.PdfViewer
|
||||||
import app.grapheneos.pdfviewer.R
|
import app.grapheneos.pdfviewer.R
|
||||||
import app.grapheneos.pdfviewer.databinding.PasswordDialogFragmentBinding
|
import app.grapheneos.pdfviewer.databinding.PasswordDialogFragmentBinding
|
||||||
|
import app.grapheneos.pdfviewer.viewModel.PasswordStatus
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
import com.google.android.material.textfield.TextInputEditText
|
||||||
|
import com.google.android.material.textfield.TextInputLayout
|
||||||
|
|
||||||
class PasswordPromptFragment(private val pdfViewer: PdfViewer) : DialogFragment() {
|
class PasswordPromptFragment(private val pdfViewer: PdfViewer) : DialogFragment() {
|
||||||
|
|
||||||
private lateinit var passwordEditText : EditText
|
private lateinit var passwordLayout : TextInputLayout
|
||||||
|
private lateinit var passwordEditText : TextInputEditText
|
||||||
|
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
val passwordPrompt = AlertDialog.Builder(requireContext())
|
val passwordPrompt = MaterialAlertDialogBuilder(requireContext())
|
||||||
val passwordDialogFragmentBinding =
|
val passwordDialogFragmentBinding =
|
||||||
PasswordDialogFragmentBinding.inflate(LayoutInflater.from(requireContext()))
|
PasswordDialogFragmentBinding.inflate(LayoutInflater.from(requireContext()))
|
||||||
|
passwordLayout = passwordDialogFragmentBinding.pdfPasswordTextInputLayout
|
||||||
passwordEditText = passwordDialogFragmentBinding.pdfPasswordEditText
|
passwordEditText = passwordDialogFragmentBinding.pdfPasswordEditText
|
||||||
passwordPrompt.setView(passwordDialogFragmentBinding.root)
|
passwordPrompt.setView(passwordDialogFragmentBinding.root)
|
||||||
passwordEditText.addTextChangedListener(object : TextWatcher {
|
passwordEditText.addTextChangedListener(object : TextWatcher {
|
||||||
|
@ -38,15 +44,39 @@ class PasswordPromptFragment(private val pdfViewer: PdfViewer) : DialogFragment(
|
||||||
sendPassword()
|
sendPassword()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
passwordPrompt.setPositiveButton(R.string.open) { _, _ -> sendPassword() }
|
passwordPrompt.setPositiveButton(R.string.open, null)
|
||||||
passwordPrompt.setNegativeButton(R.string.cancel, null)
|
passwordPrompt.setNegativeButton(R.string.cancel, null)
|
||||||
val dialog = passwordPrompt.create()
|
val dialog = passwordPrompt.create()
|
||||||
|
passwordPrompt.setCancelable(false)
|
||||||
|
isCancelable = false
|
||||||
dialog.setCanceledOnTouchOutside(false)
|
dialog.setCanceledOnTouchOutside(false)
|
||||||
dialog.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE)
|
dialog.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE)
|
||||||
|
pdfViewer.passwordValidationViewModel.status.observe(
|
||||||
|
this
|
||||||
|
) {
|
||||||
|
when (it) {
|
||||||
|
PasswordStatus.Status.MissingPassword -> {
|
||||||
|
passwordEditText.editableText.clear()
|
||||||
|
passwordDialogFragmentBinding.title.setText(R.string.password_prompt_description)
|
||||||
|
}
|
||||||
|
PasswordStatus.Status.InvalidPassword -> {
|
||||||
|
passwordEditText.editableText.clear()
|
||||||
|
passwordDialogFragmentBinding.pdfPasswordTextInputLayout.error =
|
||||||
|
"invalid password"
|
||||||
|
}
|
||||||
|
PasswordStatus.Status.Validated -> {
|
||||||
|
//Activity will dismiss the dialog
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
throw NullPointerException("status shouldn't be null")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return dialog
|
return dialog
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updatePositiveButton() {
|
private fun updatePositiveButton() {
|
||||||
|
passwordLayout.error = ""
|
||||||
val btn = (dialog as AlertDialog).getButton(DialogInterface.BUTTON_POSITIVE)
|
val btn = (dialog as AlertDialog).getButton(DialogInterface.BUTTON_POSITIVE)
|
||||||
btn.isEnabled = passwordEditText.text?.isNotEmpty() ?: false
|
btn.isEnabled = passwordEditText.text?.isNotEmpty() ?: false
|
||||||
}
|
}
|
||||||
|
@ -55,7 +85,6 @@ class PasswordPromptFragment(private val pdfViewer: PdfViewer) : DialogFragment(
|
||||||
val password = passwordEditText.text.toString()
|
val password = passwordEditText.text.toString()
|
||||||
if (!TextUtils.isEmpty(password)) {
|
if (!TextUtils.isEmpty(password)) {
|
||||||
pdfViewer.loadPdfWithPassword(password)
|
pdfViewer.loadPdfWithPassword(password)
|
||||||
dialog?.dismiss()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,4 +93,11 @@ class PasswordPromptFragment(private val pdfViewer: PdfViewer) : DialogFragment(
|
||||||
updatePositiveButton()
|
updatePositiveButton()
|
||||||
passwordEditText.requestFocus()
|
passwordEditText.requestFocus()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
(dialog as AlertDialog).getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener {
|
||||||
|
sendPassword()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
package app.grapheneos.pdfviewer.ktx
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import androidx.core.view.ViewCompat
|
||||||
|
import androidx.core.view.WindowInsetsCompat
|
||||||
|
import androidx.core.view.WindowInsetsControllerCompat
|
||||||
|
|
||||||
|
private val systemBars = WindowInsetsCompat.Type.statusBars()
|
||||||
|
|
||||||
|
fun View.hideSystemUi() {
|
||||||
|
val controller = ViewCompat.getWindowInsetsController(this) ?: return
|
||||||
|
controller.systemBarsBehavior =
|
||||||
|
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
||||||
|
controller.hide(systemBars)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun View.showSystemUi() {
|
||||||
|
ViewCompat.getWindowInsetsController(this)?.show(systemBars)
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package app.grapheneos.pdfviewer.viewModel
|
||||||
|
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
|
||||||
|
class PasswordStatus : ViewModel() {
|
||||||
|
|
||||||
|
enum class Status {
|
||||||
|
MissingPassword,
|
||||||
|
InvalidPassword,
|
||||||
|
Validated
|
||||||
|
}
|
||||||
|
|
||||||
|
val status: MutableLiveData<Status> = MutableLiveData(Status.MissingPassword)
|
||||||
|
|
||||||
|
fun passwordMissing() {
|
||||||
|
status.postValue(Status.MissingPassword)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun invalid() {
|
||||||
|
status.postValue(Status.InvalidPassword)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun validated() {
|
||||||
|
status.postValue(Status.Validated)
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,7 +5,8 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<TextView
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
android:id="@+id/title"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="24dp"
|
android:layout_marginStart="24dp"
|
||||||
|
@ -17,6 +18,7 @@
|
||||||
android:textSize="20sp" />
|
android:textSize="20sp" />
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:id="@+id/pdf_password_text_input_layout"
|
||||||
style="@style/Widget.Material3.TextInputLayout.OutlinedBox"
|
style="@style/Widget.Material3.TextInputLayout.OutlinedBox"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
android:id="@+id/toolbar"
|
android:id="@+id/toolbar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="?attr/actionBarSize"
|
android:layout_height="?attr/actionBarSize"
|
||||||
android:background="#212121"
|
|
||||||
app:popupTheme="@style/AppTheme.PopupOverlay" />
|
app:popupTheme="@style/AppTheme.PopupOverlay" />
|
||||||
|
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
<resources>
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
<!-- Base application theme. -->
|
<!-- Base application theme. -->
|
||||||
<style name="AppTheme" parent="Theme.Material3.DayNight.NoActionBar">
|
<style name="AppTheme" parent="Theme.Material3.DayNight.NoActionBar">
|
||||||
<!-- Customize your theme here. -->
|
<!-- Customize your theme here. -->
|
||||||
<item name="colorPrimary">#DEFFFFFF</item>
|
<item name="colorPrimary">#DEFFFFFF</item>
|
||||||
<item name="android:statusBarColor">#212121</item>
|
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||||
<item name="android:navigationBarColor">@android:color/transparent</item>
|
<item name="android:navigationBarColor">@android:color/transparent</item>
|
||||||
|
<item name="android:windowLightNavigationBar" tools:ignore="NewApi">false</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.Material3.Dark" />
|
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.Material3.DynamicColors.Dark" />
|
||||||
|
|
||||||
</resources>
|
</resources>
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
<string name="app_name">PDF Viewer</string>
|
<string name="app_name">PDF Viewer</string>
|
||||||
<!--<string name="action_settings">Settings</string>-->
|
<!--<string name="action_settings">Settings</string>-->
|
||||||
<string name="action_previous">Previous page</string>
|
<string name="action_previous">Previous page</string>
|
||||||
|
@ -15,11 +15,10 @@
|
||||||
<string name="document_properties_retrieval_failed">Failed to obtain document metadata</string>
|
<string name="document_properties_retrieval_failed">Failed to obtain document metadata</string>
|
||||||
|
|
||||||
<string name="webview_out_of_date_title">WebView out-of-date</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 %1$d. The WebView should be at least version %2$d for the PDF Viewer to work.</string>
|
<string name="webview_out_of_date_message" tools:ignore="PluralsCandidate">Your current WebView version is %1$d. The WebView should be at least version %2$d for the PDF Viewer to work.</string>
|
||||||
|
|
||||||
<string name="password_prompt_hint">Password</string>
|
<string name="password_prompt_hint">Password</string>
|
||||||
<string name="password_prompt_description">Enter the password to decrypt this PDF file</string>
|
<string name="password_prompt_description">Enter the password to decrypt this PDF file</string>
|
||||||
<string name="password_prompt_invalid_password">Invalid password</string>
|
|
||||||
<string name="open">Open</string>
|
<string name="open">Open</string>
|
||||||
<string name="cancel">Cancel</string>
|
<string name="cancel">Cancel</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
<resources>
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
<!-- Base application theme. -->
|
<!-- Base application theme. -->
|
||||||
<style name="AppTheme" parent="Theme.Material3.DayNight.NoActionBar">
|
<style name="AppTheme" parent="Theme.Material3.DayNight.NoActionBar">
|
||||||
<!-- Customize your theme here. -->
|
<!-- Customize your theme here. -->
|
||||||
<item name="colorPrimary">#000000</item>
|
<item name="colorPrimary">#000000</item>
|
||||||
<item name="android:statusBarColor">#212121</item>
|
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||||
<item name="android:navigationBarColor">@android:color/transparent</item>
|
<item name="android:navigationBarColor">@android:color/transparent</item>
|
||||||
|
<item name="android:windowLightNavigationBar" tools:ignore="NewApi">true</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.Material3.Dark" />
|
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.Material3.DynamicColors.Dark" />
|
||||||
|
|
||||||
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.Material3.Light" />
|
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.Material3.DynamicColors.Light" />
|
||||||
|
|
||||||
</resources>
|
</resources>
|
|
@ -1,11 +1,17 @@
|
||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
// dependabot cannot handle google()
|
||||||
mavenCentral()
|
maven {
|
||||||
|
url = uri("https://dl.google.com/dl/android/maven2")
|
||||||
|
}
|
||||||
|
// dependabot cannot handle mavenCentral()
|
||||||
|
maven {
|
||||||
|
url = uri("https://repo.maven.apache.org/maven2")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath("com.android.tools.build:gradle:7.1.3")
|
classpath("com.android.tools.build:gradle:7.3.0")
|
||||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21")
|
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.20")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -1,6 +1,6 @@
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionSha256Sum=29e49b10984e585d8118b7d0bc452f944e386458df27371b49b4ac1dec4b7fda
|
distributionSha256Sum=f6b8596b10cce501591e92f229816aa4046424f3b24d771751b06779d58c8ec4
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|
|
@ -205,6 +205,12 @@ set -- \
|
||||||
org.gradle.wrapper.GradleWrapperMain \
|
org.gradle.wrapper.GradleWrapperMain \
|
||||||
"$@"
|
"$@"
|
||||||
|
|
||||||
|
# Stop when "xargs" is not available.
|
||||||
|
if ! command -v xargs >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "xargs is not available"
|
||||||
|
fi
|
||||||
|
|
||||||
# Use "xargs" to parse quoted args.
|
# Use "xargs" to parse quoted args.
|
||||||
#
|
#
|
||||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
@rem limitations under the License.
|
@rem limitations under the License.
|
||||||
@rem
|
@rem
|
||||||
|
|
||||||
@if "%DEBUG%" == "" @echo off
|
@if "%DEBUG%"=="" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
@rem
|
@rem
|
||||||
@rem Gradle startup script for Windows
|
@rem Gradle startup script for Windows
|
||||||
|
@ -25,7 +25,7 @@
|
||||||
if "%OS%"=="Windows_NT" setlocal
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
set DIRNAME=%~dp0
|
set DIRNAME=%~dp0
|
||||||
if "%DIRNAME%" == "" set DIRNAME=.
|
if "%DIRNAME%"=="" set DIRNAME=.
|
||||||
set APP_BASE_NAME=%~n0
|
set APP_BASE_NAME=%~n0
|
||||||
set APP_HOME=%DIRNAME%
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
set JAVA_EXE=java.exe
|
set JAVA_EXE=java.exe
|
||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if "%ERRORLEVEL%" == "0" goto execute
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
@ -75,13 +75,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
:end
|
:end
|
||||||
@rem End local scope for the variables with windows NT shell
|
@rem End local scope for the variables with windows NT shell
|
||||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||||
|
|
||||||
:fail
|
:fail
|
||||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
rem the _cmd.exe /c_ return code!
|
rem the _cmd.exe /c_ return code!
|
||||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
set EXIT_CODE=%ERRORLEVEL%
|
||||||
exit /b 1
|
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||||
|
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||||
|
exit /b %EXIT_CODE%
|
||||||
|
|
||||||
:mainEnd
|
:mainEnd
|
||||||
if "%OS%"=="Windows_NT" endlocal
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
Loading…
Reference in New Issue