Skip to content

Commit

Permalink
add export page (enabled in debug builds only for now)...
Browse files Browse the repository at this point in the history
fetch and format page byte size properly
minor refinements/experimental code
  • Loading branch information
edeso committed Apr 9, 2024
1 parent a2eaf9b commit 4ebb706
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import androidx.fragment.app.Fragment;
import com.nkanaev.comics.R;
import com.nkanaev.comics.fragment.ReaderFragment;
import androidx.annotation.NonNull;

import java.io.File;

Expand Down Expand Up @@ -99,4 +100,11 @@ public void onBackPressed() {
super.onBackPressed();
finish();
}

/*
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
*/
}
180 changes: 149 additions & 31 deletions app/src/main/java/com/nkanaev/comics/fragment/ReaderFragment.java
Original file line number Diff line number Diff line change
@@ -1,31 +1,34 @@
package com.nkanaev.comics.fragment;

import android.Manifest;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;
import android.util.SparseArray;
import android.util.TypedValue;
import android.view.*;
import android.view.animation.Animation;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.*;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.interpolator.view.animation.FastOutSlowInInterpolator;
import androidx.viewpager.widget.PagerAdapter;
Expand All @@ -49,17 +52,20 @@
import com.squareup.picasso.Target;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.*;


public class ReaderFragment extends Fragment implements View.OnTouchListener {
public static final String PARAM_HANDLER = "PARAM_HANDLER";
public static final String PARAM_URI = "PARAM_URI";
public static final String PARAM_MODE = "PARAM_MODE";

public static final String STATE_FULLSCREEN = "STATE_FULLSCREEN";
public static final String STATE_PAGEINFO = "STATE_PAGEINFO";
public static final String STATE_NEW_COMIC = "STATE_NEW_COMIC";
Expand Down Expand Up @@ -112,6 +118,17 @@ public enum Mode {
RESOURCE_VIEW_MODE.put(R.id.view_mode_fit_width, Constants.PageViewMode.FIT_WIDTH);
}

/*
private ActivityResultLauncher<String> requestPermissionLauncher =
registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> {
if (isGranted) {
Toast.makeText(getContext(), "Permission is accepted", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getContext(), "Permission is denied", Toast.LENGTH_SHORT).show();
}
});
*/

public static ReaderFragment create(int comicId) {
ReaderFragment fragment = new ReaderFragment();
Bundle args = new Bundle();
Expand Down Expand Up @@ -241,22 +258,6 @@ public void run() {
mPageViewMode = Constants.PageViewMode.values()[viewModeInt];
mIsLeftToRight = mPreferences.getBoolean(Constants.SETTINGS_READING_LEFT_TO_RIGHT, true);

// workaround: extract rar achive
/*
if (mParser instanceof RarParser) {
File cacheDir = new File(getActivity().getExternalCacheDir(), "c");
if (!cacheDir.exists()) {
cacheDir.mkdir();
}
else {
for (File f : cacheDir.listFiles()) {
f.delete();
}
}
((RarParser)mParser).setCacheDirectory(cacheDir);
}
*/

setHasOptionsMenu(true);
}

Expand Down Expand Up @@ -404,6 +405,14 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat
super.onViewCreated(view, savedInstanceState);
}

@Override
public void onPrepareOptionsMenu(@NonNull Menu menu) {
super.onPrepareOptionsMenu(menu);

// TODO: fix up page export permission bs
menu.findItem(R.id.menu_reader_export).setVisible(BuildConfig.DEBUG);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.reader, menu);
Expand Down Expand Up @@ -521,13 +530,33 @@ public boolean onOptionsItemSelected(MenuItem item) {
degrees = 0;
degrees += 90;
mRotations.put(pos,degrees);
//apply rotation
// apply rotation during (re)load
mViewPager.getAdapter().notifyDataSetChanged();
//updatePageViews(mViewPager,pos,true);
// work in progress,
// rotating imageview does not reset boundings unfortunately, dunno howto fix for now
// also touch events are registered to the imageview and rotate with the image, not good
//rotatePage(pos, degrees);
break;
case R.id.menu_reader_export:
exportCurrentPage();
break;
}
return super.onOptionsItemSelected(item);
}

private void rotatePage(int pos, int degrees){
try {
MyTarget t = mTargets.get(pos);
View v = t.mLayout.get();
PageImageView piv = v.findViewById(R.id.pageImageView);
piv.rotate(degrees);
} catch (NullPointerException ne) {
// huh, wasn't there, need to reload it
mViewPager.getAdapter().notifyDataSetChanged();
}
}

private void setCurrentPage(int page) {
setCurrentPage(page, true);
}
Expand Down Expand Up @@ -570,34 +599,48 @@ private void updatePageImageInfo() {
new Thread(new Runnable() {
@Override
public void run() {
Map<String, String> metadata = null;
Map<String, Object> metadata = null;
try {
metadata = mParser.getPageMetaData(pageNum);
} catch (IOException e) {
Log.e("", "", e);
}
String metaText = "";
if (metadata != null && !metadata.isEmpty()) {
String name = metadata.get(Parser.PAGEMETADATA_KEY_NAME);
String name = (String) metadata.get(Parser.PAGEMETADATA_KEY_NAME);
if (name != null)
metaText += name;
String t = metadata.get(Parser.PAGEMETADATA_KEY_MIME);
String w = metadata.get(Parser.PAGEMETADATA_KEY_WIDTH);
String h = metadata.get(Parser.PAGEMETADATA_KEY_HEIGHT);
Object t = metadata.get(Parser.PAGEMETADATA_KEY_MIME);
Object w = metadata.get(Parser.PAGEMETADATA_KEY_WIDTH);
Object h = metadata.get(Parser.PAGEMETADATA_KEY_HEIGHT);
if (t != null)
metaText += (metaText.isEmpty() ? "" : "\n")
+ String.valueOf(t) + ", "
+ String.valueOf(w) + "x" + String.valueOf(h) + "px";
// append Byte size
Object size = metadata.get(Parser.PAGEMETADATA_KEY_SIZE);
if (size != null) {
DecimalFormat formatter = (DecimalFormat) NumberFormat.getInstance(Locale.US);
DecimalFormatSymbols symbols = formatter.getDecimalFormatSymbols();
symbols.setGroupingSeparator('.');
formatter.setDecimalFormatSymbols(symbols);
try {
metaText += (t != null ? ", " : "") + formatter.format(Long.valueOf(size.toString())) + " Bytes";
} catch (Exception e) {
// eat it
}
}
// append the rest, ignore the already added from above
List<String> ignoredKeys =
List<String> keysToIgnore =
Arrays.asList(new String[]{
Parser.PAGEMETADATA_KEY_NAME,
Parser.PAGEMETADATA_KEY_MIME,
Parser.PAGEMETADATA_KEY_WIDTH,
Parser.PAGEMETADATA_KEY_HEIGHT});
for (Map.Entry<String, String> entry : metadata.entrySet()) {
Parser.PAGEMETADATA_KEY_HEIGHT,
Parser.PAGEMETADATA_KEY_SIZE});
for (Map.Entry<String, Object> entry : metadata.entrySet()) {
String key = entry.getKey();
if (ignoredKeys.contains(key))
if (keysToIgnore.contains(key))
continue;
metaText += (metaText.isEmpty() ? "" : "\n") +
key + ": " + String.valueOf(entry.getValue());
Expand Down Expand Up @@ -658,6 +701,7 @@ public Object instantiateItem(ViewGroup container, int position) {
loadImage(t);
mTargets.put(position, t);

layout.setTag(Integer.valueOf(position));
return layout;
}

Expand Down Expand Up @@ -1044,4 +1088,78 @@ private void updateSeekBar() {
mPageSeekBar.getProgressDrawable().setBounds(bounds);
}

private void exportCurrentPage() {
int pageNum = getCurrentPage();
int index = pageNum-1;
File folder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
FileOutputStream fOut = null;
Bitmap bitmap = null;
try {
if (folder==null)
throw new Exception("Cannot determine Downloads folder.");
else if (!folder.isDirectory() && !folder.mkdirs())
throw new Exception("Couldn't create Downloads folder.");
else if (mFile==null)
throw new Exception("Not a file");

String permission = Manifest.permission.WRITE_EXTERNAL_STORAGE;

/*
new Handler().post(new Runnable() {
@Override
public void run() {
requestPermissionLauncher.launch(permission, ActivityOptionsCompat.makeBasic());
}
});
*/

//if (true) return;

if (ContextCompat.checkSelfPermission(getActivity(), permission)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{permission},
1);
// still no permission?
if (ContextCompat.checkSelfPermission(getActivity(), permission)
!= PackageManager.PERMISSION_GRANTED)
throw new Exception("No write permission.");
}

Map metadata = mParser.getPageMetaData(index);
String mime = (String) metadata.get(Parser.PAGEMETADATA_KEY_MIME);
File file = new File(folder,
(mFile.isDirectory()?mFile.getName():Utils.removeExtensionIfAny(mFile.getName()))+
".page"+pageNum+".jpg");
if (mime!=null && mime.endsWith("/jpeg")) {
InputStream is = mParser.getPage(index);
Utils.copyToFile(is, file);
}
else {
bitmap = null; //BitmapFactory.decodeStream(is);
if (bitmap == null){
MyTarget t = mTargets.get(index);
View v = t.mLayout.get();
PageImageView piv = v.findViewById(R.id.pageImageView);
bitmap = ((BitmapDrawable)piv.getDrawable()).getBitmap();
}
fOut = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 95, fOut);
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
Utils.close(fOut);
//Utils.close(bitmap);
}
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == 1) {
if (permissions[0].equals(Manifest.permission.WRITE_EXTERNAL_STORAGE)
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.d("granted","profit+1");
}
}
}
}
9 changes: 9 additions & 0 deletions app/src/main/res/drawable/ic_download_18.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:fillColor="#fff"
android:pathData="M480,640L280,440L336,382L440,486L440,160L520,160L520,486L624,382L680,440L480,640ZM240,800Q207,800 183.5,776.5Q160,753 160,720L160,600L240,600L240,720Q240,720 240,720Q240,720 240,720L720,720Q720,720 720,720Q720,720 720,720L720,600L800,600L800,720Q800,753 776.5,776.5Q753,800 720,800L240,800Z"/>
</vector>
4 changes: 4 additions & 0 deletions app/src/main/res/menu/reader.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,8 @@
</group>
</menu>
</item>
<item android:id="@+id/menu_reader_export"
android:title="@string/action_view_export"
android:icon="@drawable/ic_download_18"
app:showAsAction="ifRoom"/>
</menu>

0 comments on commit 4ebb706

Please sign in to comment.