mirror of https://github.com/tasks/tasks
parent
dd772f717b
commit
16b149b76d
@ -1,40 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2012 Todoroo Inc
|
||||
*
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
package com.todoroo.astrid.sync;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Convenience class for implementing sync result callbacks--if we need a sync
|
||||
* result callback that only implements a subset of the callback methods, it
|
||||
* can extend this empty implementation
|
||||
* @author Sam
|
||||
*
|
||||
*/
|
||||
public abstract class SyncResultCallbackAdapter implements SyncResultCallback {
|
||||
|
||||
@Override
|
||||
public void incrementMax(int incrementBy) {
|
||||
// Empty implementation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incrementProgress(int incrementBy) {
|
||||
// Empty implementation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void started() {
|
||||
// Empty implementation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finished() {
|
||||
// Empty implementation
|
||||
}
|
||||
|
||||
}
|
@ -1,168 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2012 Todoroo Inc
|
||||
*
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
package com.todoroo.astrid.helper;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.View;
|
||||
import android.view.animation.AlphaAnimation;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
import com.todoroo.andlib.utility.AndroidUtilities;
|
||||
import com.todoroo.astrid.sync.SyncResultCallbackAdapter;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class ProgressBarSyncResultCallback extends SyncResultCallbackAdapter {
|
||||
|
||||
private ProgressBar progressBar;
|
||||
private final Activity activity;
|
||||
private final Runnable onFinished;
|
||||
|
||||
private final AtomicInteger providers = new AtomicInteger(0);
|
||||
|
||||
public ProgressBarSyncResultCallback(Activity activity, Fragment fragment,
|
||||
int progressBarId, Runnable onFinished) {
|
||||
this.progressBar = (ProgressBar) fragment.getView().findViewById(progressBarId);
|
||||
this.activity = activity;
|
||||
this.onFinished = onFinished;
|
||||
|
||||
if(progressBar == null) {
|
||||
progressBar = new ProgressBar(activity);
|
||||
}
|
||||
|
||||
progressBar.setProgress(0);
|
||||
progressBar.setMax(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finished() {
|
||||
if(providers.decrementAndGet() == 0) {
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
progressBar.setMax(100);
|
||||
progressBar.setProgress(100);
|
||||
AlphaAnimation animation = new AlphaAnimation(1, 0);
|
||||
animation.setFillAfter(true);
|
||||
animation.setDuration(1000L);
|
||||
progressBar.startAnimation(animation);
|
||||
|
||||
onFinished.run();
|
||||
} catch (Exception e) {
|
||||
// ignore, view could have been destroyed
|
||||
}
|
||||
}
|
||||
});
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
AndroidUtilities.sleepDeep(1000);
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
progressBar.setVisibility(View.GONE);
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method helps rescaling a progress bar to increase the number of data points that form
|
||||
* the progress bar, but without reducing the % of progress already done.
|
||||
*
|
||||
* This is done by increasing the length of the progress bar and the amount of progress whilst
|
||||
* keeping the remaining amount of progress left remains the same. This code makes the
|
||||
* presumption that progress isn't reversed and only increases.
|
||||
*
|
||||
* @param p The current level of progress that has been made.
|
||||
* @param m The current total of data points which makes up the progress bar (the maximum).
|
||||
* @param x The number of data points to increase the progress bar by.
|
||||
* @return An integer array of two values - the first is the new value for progress and the
|
||||
* second is the new value for the maximum.
|
||||
*/
|
||||
public static int[] rescaleProgressValues(int p, int m, int x) {
|
||||
|
||||
/**
|
||||
* If we have no progress yet, then a straight-forward increment of the max will suffice
|
||||
* here (and is necessary, the below code will break otherwise).
|
||||
*/
|
||||
if (p == 0) {return new int[] {p, m + x};}
|
||||
|
||||
/**
|
||||
* This is more of an error in caller code. We shouldn't be asked to rescale a progress
|
||||
* bar that has currently reached 100%, but hasn't been declared as "finished". But in
|
||||
* case this happens, and since we can't correctly rescale a progress bar that's at 100%,
|
||||
* we just allow it to move back.
|
||||
*/
|
||||
if (p == m) {return new int[] {p, m + x};}
|
||||
|
||||
// This is what does the magic!
|
||||
double m2d = ((double)(m*(m+x-p))) / (m-p);
|
||||
int m2 = (int)Math.floor(m2d);
|
||||
int p2 = m2 + p - m - x;
|
||||
return new int[] {p2, m2};
|
||||
|
||||
}
|
||||
|
||||
private void rescaleProgressBarBy(int x) {
|
||||
int[] new_values = rescaleProgressValues(progressBar.getProgress(), progressBar.getMax(), x);
|
||||
|
||||
if (new_values[1] != -1) {progressBar.setMax(new_values[1]);}
|
||||
if (new_values[0] != -1) {progressBar.setProgress(new_values[0]);}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incrementMax(final int incrementBy) {
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
rescaleProgressBarBy(incrementBy);
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incrementProgress(final int incrementBy) {
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
progressBar.incrementProgressBy(incrementBy);
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void started() {
|
||||
if(providers.incrementAndGet() == 1) {
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
AlphaAnimation animation = new AlphaAnimation(0, 1);
|
||||
animation.setFillAfter(true);
|
||||
animation.setDuration(1000L);
|
||||
progressBar.startAnimation(animation);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -1,190 +0,0 @@
|
||||
package com.todoroo.astrid.service;
|
||||
|
||||
import com.todoroo.andlib.service.ContextManager;
|
||||
import com.todoroo.andlib.utility.DateUtilities;
|
||||
import com.todoroo.astrid.helper.ProgressBarSyncResultCallback;
|
||||
import com.todoroo.astrid.sync.SyncResultCallback;
|
||||
import com.todoroo.astrid.widget.TasksWidget;
|
||||
|
||||
public class SyncResultCallbackWrapper implements SyncResultCallback {
|
||||
private final SyncResultCallback wrapped;
|
||||
public SyncResultCallbackWrapper(SyncResultCallback wrap) {
|
||||
this.wrapped = wrap;
|
||||
}
|
||||
@Override
|
||||
public void incrementMax(int incrementBy) {
|
||||
wrapped.incrementMax(incrementBy);
|
||||
}
|
||||
@Override
|
||||
public void incrementProgress(int incrementBy) {
|
||||
wrapped.incrementProgress(incrementBy);
|
||||
}
|
||||
@Override
|
||||
public void started() {
|
||||
wrapped.started();
|
||||
}
|
||||
@Override
|
||||
public void finished() {
|
||||
wrapped.finished();
|
||||
}
|
||||
|
||||
public static class WidgetUpdatingCallbackWrapper extends SyncResultCallbackWrapper {
|
||||
|
||||
public WidgetUpdatingCallbackWrapper(SyncResultCallback wrap) {
|
||||
super(wrap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void started() {
|
||||
super.started();
|
||||
TasksWidget.suppressUpdateFlag = DateUtilities.now();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finished() {
|
||||
super.finished();
|
||||
TasksWidget.suppressUpdateFlag = 0L;
|
||||
TasksWidget.updateWidgets(ContextManager.getContext());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This class can be used if you want to claim a relative proportion of the SyncResultCallback,
|
||||
* but you may also want to increase the maximum size of data points as well. For example, there
|
||||
* may be 10 data points, and you want to make use of half of them to indicate that once you
|
||||
* are finished, you are half way through. But if you increase the maximum number of data
|
||||
* points, the remainder that you're not interacting with will need to increase by the same
|
||||
* proportion so that you still interact with half of the data points.
|
||||
*
|
||||
* Once you wrap this class around the original SyncResultCallback object and have finished
|
||||
* using it, you then invoke the getRemainderSize method afterwards to see how many data points are
|
||||
* left for you to use. You can then use the Rescaled wrapper to simplify caller logic afterwards.
|
||||
*/
|
||||
public static class Partial extends SyncResultCallbackWrapper {
|
||||
|
||||
protected final double factor;
|
||||
protected int fragment_size;
|
||||
protected int total_size;
|
||||
|
||||
/**
|
||||
* Wraps a SyncResultCallback object.
|
||||
*
|
||||
* @param wrap Original object to wrap.
|
||||
* @param fragment_size Number of data points that you want to interact with.
|
||||
* @param total_size Total number of data points remaining and available in the original object.
|
||||
*/
|
||||
public Partial(SyncResultCallback wrap,
|
||||
int fragment_size, int total_size) {
|
||||
super(wrap);
|
||||
this.factor = Math.ceil((double)total_size / fragment_size);
|
||||
this.fragment_size = fragment_size;
|
||||
this.total_size = total_size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incrementMax(int incrementBy) {
|
||||
this.fragment_size += incrementBy;
|
||||
int new_total = (int)(this.factor * this.fragment_size);
|
||||
super.incrementMax(new_total - total_size);
|
||||
this.total_size = new_total;
|
||||
}
|
||||
|
||||
public int getRemainderSize() {
|
||||
return this.total_size - this.fragment_size;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a SyncResultCallback object with a certain number of data points, treat it as if it
|
||||
* had a different number of data points, and allow the underlying wrapped object to receive a
|
||||
* proportionally equivalent amount of data points.
|
||||
*/
|
||||
public static class Rescaled extends SyncResultCallbackWrapper {
|
||||
|
||||
protected int input_size;
|
||||
protected int actual_size;
|
||||
protected int input_count;
|
||||
protected int actual_count;
|
||||
|
||||
public Rescaled(SyncResultCallback wrap,
|
||||
int input_size, int actual_size) {
|
||||
super(wrap);
|
||||
if (input_size <= 0) throw new IllegalArgumentException("input_size is not +ve");
|
||||
if (actual_size <= 0) throw new IllegalArgumentException("actual size is not +ve");
|
||||
this.input_size = input_size;
|
||||
this.actual_size = actual_size;
|
||||
this.input_count = 0;
|
||||
this.actual_count = 0;
|
||||
|
||||
// If we have more input data points than output, we'll increase the number of data
|
||||
// points in the underlying one, because otherwise incremental updates fed into us
|
||||
// might not show up in the underlying object.
|
||||
if (actual_size < input_size) {
|
||||
super.incrementMax(input_size - actual_size);
|
||||
this.actual_size = input_size;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incrementProgress(int incrementBy) {
|
||||
|
||||
// Shortcut if we're no longer rescaling.
|
||||
if (input_size == actual_size) {
|
||||
super.incrementProgress(incrementBy);
|
||||
return;
|
||||
}
|
||||
|
||||
int new_input_count = input_count + incrementBy;
|
||||
int new_actual_count = (new_input_count * actual_size) / input_size;
|
||||
if (new_actual_count > actual_count) {
|
||||
// This should always be the case, but we just sanity check it.
|
||||
super.incrementProgress(new_actual_count - actual_count);
|
||||
}
|
||||
this.input_count = new_input_count;
|
||||
this.actual_count = new_actual_count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incrementMax(int incrementBy) {
|
||||
|
||||
// Shortcut if we're not longer rescaling.
|
||||
if (input_size == actual_size) {
|
||||
super.incrementMax(incrementBy);
|
||||
return;
|
||||
}
|
||||
|
||||
// If we increase the maximum used by the input, we want to rescale the values such
|
||||
// that the progress (proportionally) remains the same - otherwise we'll appear to
|
||||
// have made backward progress on the input side, which we can't indicate to the
|
||||
// underlying object.
|
||||
int[] rescaled_input = ProgressBarSyncResultCallback.rescaleProgressValues(
|
||||
input_count, input_size, incrementBy
|
||||
);
|
||||
|
||||
this.input_count = rescaled_input[0];
|
||||
this.input_size = rescaled_input[1];
|
||||
|
||||
// No need to rescale internally if no data points exist.
|
||||
if (input_count == 0) {return;}
|
||||
|
||||
// The point of this class is to increase the size of input so that it increases the
|
||||
// amount of data points sent to the underlying object. Once the input size becomes the
|
||||
// same as underlying size, we don't need to do anything other than send the same
|
||||
// information to the underlying class.
|
||||
//
|
||||
// So:
|
||||
// If input remains smaller than actual, we do nothing here.
|
||||
// If input remains equal to actual, we just pass the same data along.
|
||||
// If input goes from smaller to bigger, we need to catch up to make it equal.
|
||||
if (input_count > actual_count) {
|
||||
super.incrementMax(input_count - actual_count);
|
||||
this.actual_count = input_count; // Switches off rescaling.
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package com.todoroo.astrid.service;
|
||||
|
||||
import com.todoroo.andlib.service.ContextManager;
|
||||
import com.todoroo.andlib.utility.DateUtilities;
|
||||
import com.todoroo.astrid.sync.SyncResultCallback;
|
||||
import com.todoroo.astrid.widget.TasksWidget;
|
||||
|
||||
public class WidgetUpdatingCallbackWrapper implements SyncResultCallback {
|
||||
|
||||
private SyncResultCallback wrap;
|
||||
|
||||
public WidgetUpdatingCallbackWrapper(SyncResultCallback wrap) {
|
||||
this.wrap = wrap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void started() {
|
||||
wrap.started();
|
||||
TasksWidget.suppressUpdateFlag = DateUtilities.now();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finished() {
|
||||
wrap.finished();
|
||||
TasksWidget.suppressUpdateFlag = 0L;
|
||||
TasksWidget.updateWidgets(ContextManager.getContext());
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package org.tasks.sync;
|
||||
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
|
||||
import com.todoroo.astrid.sync.SyncResultCallback;
|
||||
|
||||
public class IndeterminateProgressBarSyncResultCallback implements SyncResultCallback{
|
||||
|
||||
private final FragmentActivity activity;
|
||||
private Runnable onFinished;
|
||||
|
||||
public IndeterminateProgressBarSyncResultCallback(FragmentActivity activity, Runnable onFinished) {
|
||||
this.activity = activity;
|
||||
this.onFinished = onFinished;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finished() {
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
activity.setProgressBarIndeterminateVisibility(false);
|
||||
onFinished.run();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void started() {
|
||||
activity.setProgressBarIndeterminateVisibility(true);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue