main commit
Post-processing infrastructure * remove interfaces with one implementation * fix download resources with unknow length * marquee style for ProgressDrawable * "view details" option in mission context menu * notification for finished downloads * postprocessing infrastructure: sub-missions, circular file, layers for layers of abstractions for Java IO streams * Mp4 muxing (only DASH brand) * WebM muxing * Captions downloading * alert dialog for overwrite existing downloads finished or not. Misc changes * delete SQLiteDownloadDataSource.java * delete DownloadMissionSQLiteHelper.java * implement Localization from #114 Misc fixes (this branch) * restore old mission listeners variables. Prevents registered listeners get de-referenced on low-end devices * DownloadManagerService.checkForRunningMission() now return false if the mission has a error. * use Intent.FLAG_ACTIVITY_NEW_TASK when launching an activity from gigaget threads (apparently it is required in old versions of android) More changes * proper error handling "infrastructure" * queue instead of multiple downloads * move serialized pending downloads (.giga files) to app data * stop downloads when swicthing to mobile network (never works, see 2nd point) * save the thread count for next downloads * a lot of incoherences fixed * delete DownloadManagerTest.java (too many changes to keep this file updated)
This commit is contained in:
parent
2dc2a56671
commit
21e205a6be
48 changed files with 4379 additions and 1119 deletions
169
app/src/main/java/us/shandian/giga/ui/common/Deleter.java
Normal file
169
app/src/main/java/us/shandian/giga/ui/common/Deleter.java
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
package us.shandian.giga.ui.common;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.view.View;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import us.shandian.giga.get.Mission;
|
||||
import us.shandian.giga.service.DownloadManager;
|
||||
import us.shandian.giga.service.DownloadManager.MissionIterator;
|
||||
import us.shandian.giga.ui.adapter.MissionAdapter;
|
||||
|
||||
public class Deleter {
|
||||
private static final int TIMEOUT = 5000;// ms
|
||||
private static final int DELAY = 350;// ms
|
||||
private static final String BUNDLE_NAMES = "us.shandian.giga.ui.common.deleter.names";
|
||||
private static final String BUNDLE_LOCATIONS = "us.shandian.giga.ui.common.deleter.locations";
|
||||
|
||||
private Snackbar snackbar;
|
||||
private ArrayList<Mission> items;
|
||||
private boolean running = true;
|
||||
|
||||
private Context mContext;
|
||||
private MissionAdapter mAdapter;
|
||||
private DownloadManager mDownloadManager;
|
||||
private MissionIterator mIterator;
|
||||
private Handler mHandler;
|
||||
private View mView;
|
||||
|
||||
private final Runnable rShow;
|
||||
private final Runnable rNext;
|
||||
private final Runnable rCommit;
|
||||
|
||||
public Deleter(Bundle b, View v, Context c, MissionAdapter a, DownloadManager d, MissionIterator i, Handler h) {
|
||||
mView = v;
|
||||
mContext = c;
|
||||
mAdapter = a;
|
||||
mDownloadManager = d;
|
||||
mIterator = i;
|
||||
mHandler = h;
|
||||
|
||||
// use variables to know the reference of the lambdas
|
||||
rShow = this::show;
|
||||
rNext = this::next;
|
||||
rCommit = this::commit;
|
||||
|
||||
items = new ArrayList<>(2);
|
||||
|
||||
if (b != null) {
|
||||
String[] names = b.getStringArray(BUNDLE_NAMES);
|
||||
String[] locations = b.getStringArray(BUNDLE_LOCATIONS);
|
||||
|
||||
if (names == null || locations == null) return;
|
||||
if (names.length < 1 || locations.length < 1) return;
|
||||
if (names.length != locations.length) return;
|
||||
|
||||
items.ensureCapacity(names.length);
|
||||
|
||||
for (int j = 0; j < locations.length; j++) {
|
||||
Mission mission = mDownloadManager.getAnyMission(locations[j], names[j]);
|
||||
if (mission == null) continue;
|
||||
|
||||
items.add(mission);
|
||||
mIterator.hide(mission);
|
||||
}
|
||||
|
||||
if (items.size() > 0) resume();
|
||||
}
|
||||
}
|
||||
|
||||
public void append(Mission item) {
|
||||
mIterator.hide(item);
|
||||
items.add(0, item);
|
||||
|
||||
show();
|
||||
}
|
||||
|
||||
private void forget() {
|
||||
mIterator.unHide(items.remove(0));
|
||||
mAdapter.applyChanges();
|
||||
|
||||
show();
|
||||
}
|
||||
|
||||
private void show() {
|
||||
if (items.size() < 1) return;
|
||||
|
||||
pause();
|
||||
running = true;
|
||||
|
||||
mHandler.postDelayed(rNext, DELAY);
|
||||
}
|
||||
|
||||
private void next() {
|
||||
if (items.size() < 1) return;
|
||||
|
||||
String msg = mContext.getString(R.string.file_deleted).concat(":\n").concat(items.get(0).name);
|
||||
|
||||
snackbar = Snackbar.make(mView, msg, Snackbar.LENGTH_INDEFINITE);
|
||||
snackbar.setAction(R.string.undo, s -> forget());
|
||||
snackbar.setActionTextColor(Color.YELLOW);
|
||||
snackbar.show();
|
||||
|
||||
mHandler.postDelayed(rCommit, TIMEOUT);
|
||||
}
|
||||
|
||||
private void commit() {
|
||||
if (items.size() < 1) return;
|
||||
|
||||
while (items.size() > 0) {
|
||||
Mission mission = items.remove(0);
|
||||
if (mission.deleted) continue;
|
||||
|
||||
mIterator.unHide(mission);
|
||||
mDownloadManager.deleteMission(mission);
|
||||
break;
|
||||
}
|
||||
|
||||
if (items.size() < 1) {
|
||||
pause();
|
||||
return;
|
||||
}
|
||||
|
||||
show();
|
||||
}
|
||||
|
||||
private void pause() {
|
||||
running = false;
|
||||
mHandler.removeCallbacks(rNext);
|
||||
mHandler.removeCallbacks(rShow);
|
||||
mHandler.removeCallbacks(rCommit);
|
||||
if (snackbar != null) snackbar.dismiss();
|
||||
}
|
||||
|
||||
public void resume() {
|
||||
if (running) return;
|
||||
mHandler.postDelayed(rShow, (int) (DELAY * 1.5f));// 150% of the delay
|
||||
}
|
||||
|
||||
public void dispose(Bundle bundle) {
|
||||
if (items.size() < 1) return;
|
||||
|
||||
pause();
|
||||
|
||||
if (bundle == null) {
|
||||
for (Mission mission : items) mDownloadManager.deleteMission(mission);
|
||||
items = null;
|
||||
return;
|
||||
}
|
||||
|
||||
String[] names = new String[items.size()];
|
||||
String[] locations = new String[items.size()];
|
||||
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
Mission mission = items.get(i);
|
||||
names[i] = mission.name;
|
||||
locations[i] = mission.location;
|
||||
}
|
||||
|
||||
bundle.putStringArray(BUNDLE_NAMES, names);
|
||||
bundle.putStringArray(BUNDLE_LOCATIONS, locations);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,25 +1,36 @@
|
|||
package us.shandian.giga.ui.common;
|
||||
package us.shandian.giga.ui.common;// TODO: ¡git it!
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.annotation.ColorRes;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.support.annotation.ColorInt;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
|
||||
public class ProgressDrawable extends Drawable {
|
||||
private float mProgress;
|
||||
private final int mBackgroundColor;
|
||||
private final int mForegroundColor;
|
||||
private static final int MARQUEE_INTERVAL = 150;
|
||||
|
||||
public ProgressDrawable(Context context, @ColorRes int background, @ColorRes int foreground) {
|
||||
this(ContextCompat.getColor(context, background), ContextCompat.getColor(context, foreground));
|
||||
private float mProgress;
|
||||
private int mBackgroundColor, mForegroundColor;
|
||||
private Handler mMarqueeHandler;
|
||||
private float mMarqueeProgress;
|
||||
private Path mMarqueeLine;
|
||||
private int mMarqueeSize;
|
||||
private long mMarqueeNext;
|
||||
|
||||
public ProgressDrawable() {
|
||||
mMarqueeLine = null;// marquee disabled
|
||||
mMarqueeProgress = 0f;
|
||||
mMarqueeSize = 0;
|
||||
mMarqueeNext = 0;
|
||||
}
|
||||
|
||||
public ProgressDrawable(int background, int foreground) {
|
||||
public void setColors(@ColorInt int background, @ColorInt int foreground) {
|
||||
mBackgroundColor = background;
|
||||
mForegroundColor = foreground;
|
||||
}
|
||||
|
|
@ -29,10 +40,20 @@ public class ProgressDrawable extends Drawable {
|
|||
invalidateSelf();
|
||||
}
|
||||
|
||||
public void setMarquee(boolean marquee) {
|
||||
if (marquee == (mMarqueeLine != null)) {
|
||||
return;
|
||||
}
|
||||
mMarqueeLine = marquee ? new Path() : null;
|
||||
mMarqueeHandler = marquee ? new Handler(Looper.getMainLooper()) : null;
|
||||
mMarqueeSize = 0;
|
||||
mMarqueeNext = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(@NonNull Canvas canvas) {
|
||||
int width = canvas.getWidth();
|
||||
int height = canvas.getHeight();
|
||||
int width = getBounds().width();
|
||||
int height = getBounds().height();
|
||||
|
||||
Paint paint = new Paint();
|
||||
|
||||
|
|
@ -40,6 +61,42 @@ public class ProgressDrawable extends Drawable {
|
|||
canvas.drawRect(0, 0, width, height, paint);
|
||||
|
||||
paint.setColor(mForegroundColor);
|
||||
|
||||
if (mMarqueeLine != null) {
|
||||
if (mMarqueeSize < 1) setupMarquee(width, height);
|
||||
|
||||
int size = mMarqueeSize;
|
||||
Paint paint2 = new Paint();
|
||||
paint2.setColor(mForegroundColor);
|
||||
paint2.setStrokeWidth(size);
|
||||
paint2.setStyle(Paint.Style.STROKE);
|
||||
|
||||
size *= 2;
|
||||
|
||||
if (mMarqueeProgress >= size) {
|
||||
mMarqueeProgress = 1;
|
||||
} else {
|
||||
mMarqueeProgress++;
|
||||
}
|
||||
|
||||
// render marquee
|
||||
width += size * 2;
|
||||
Path marquee = new Path();
|
||||
for (float i = -size; i < width; i += size) {
|
||||
marquee.addPath(mMarqueeLine, i + mMarqueeProgress, 0);
|
||||
}
|
||||
marquee.close();
|
||||
|
||||
canvas.drawPath(marquee, paint2);// draw marquee
|
||||
|
||||
if (System.currentTimeMillis() >= mMarqueeNext) {
|
||||
// program next update
|
||||
mMarqueeNext = System.currentTimeMillis() + MARQUEE_INTERVAL;
|
||||
mMarqueeHandler.postDelayed(this::invalidateSelf, MARQUEE_INTERVAL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
canvas.drawRect(0, 0, (int) (mProgress * width), height, paint);
|
||||
}
|
||||
|
||||
|
|
@ -58,4 +115,17 @@ public class ProgressDrawable extends Drawable {
|
|||
return PixelFormat.OPAQUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBoundsChange(Rect rect) {
|
||||
if (mMarqueeLine != null) setupMarquee(rect.width(), rect.height());
|
||||
}
|
||||
|
||||
private void setupMarquee(int width, int height) {
|
||||
mMarqueeSize = (int) ((width * 10f) / 100f);// the size is 10% of the width
|
||||
|
||||
mMarqueeLine.rewind();
|
||||
mMarqueeLine.moveTo(-mMarqueeSize, -mMarqueeSize);
|
||||
mMarqueeLine.lineTo(-mMarqueeSize * 4, height + mMarqueeSize);
|
||||
mMarqueeLine.close();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue