mirror of
https://github.com/KokaKiwi/BarInsta
synced 2024-11-22 22:57:29 +00:00
Add downloaded indicator to Posts view
This commit is contained in:
parent
450dbba6de
commit
d0bfe73ae6
@ -1,5 +1,6 @@
|
|||||||
package awais.instagrabber.adapters.viewholder;
|
package awais.instagrabber.adapters.viewholder;
|
||||||
|
|
||||||
|
import android.content.res.ColorStateList;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@ -17,6 +18,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import awais.instagrabber.R;
|
import awais.instagrabber.R;
|
||||||
import awais.instagrabber.adapters.FeedAdapterV2;
|
import awais.instagrabber.adapters.FeedAdapterV2;
|
||||||
|
import awais.instagrabber.asyncs.DownloadedCheckerAsyncTask;
|
||||||
import awais.instagrabber.databinding.ItemFeedGridBinding;
|
import awais.instagrabber.databinding.ItemFeedGridBinding;
|
||||||
import awais.instagrabber.models.FeedModel;
|
import awais.instagrabber.models.FeedModel;
|
||||||
import awais.instagrabber.models.PostChild;
|
import awais.instagrabber.models.PostChild;
|
||||||
@ -131,5 +133,29 @@ public class FeedGridItemViewHolder extends RecyclerView.ViewHolder {
|
|||||||
.setImageRequest(requestBuilder)
|
.setImageRequest(requestBuilder)
|
||||||
.setOldController(binding.postImage.getController());
|
.setOldController(binding.postImage.getController());
|
||||||
binding.postImage.setController(builder.build());
|
binding.postImage.setController(builder.build());
|
||||||
|
final DownloadedCheckerAsyncTask task = new DownloadedCheckerAsyncTask(result -> {
|
||||||
|
final List<Boolean> checkList = result.get(feedModel.getPostId());
|
||||||
|
if (checkList == null || checkList.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (feedModel.getItemType()) {
|
||||||
|
case MEDIA_TYPE_IMAGE:
|
||||||
|
case MEDIA_TYPE_VIDEO:
|
||||||
|
binding.downloaded.setVisibility(checkList.get(0) ? View.VISIBLE : View.GONE);
|
||||||
|
binding.downloaded.setImageTintList(ColorStateList.valueOf(itemView.getResources().getColor(R.color.green_A400)));
|
||||||
|
break;
|
||||||
|
case MEDIA_TYPE_SLIDER:
|
||||||
|
binding.downloaded.setVisibility(checkList.get(0) ? View.VISIBLE : View.GONE);
|
||||||
|
boolean allDownloaded = checkList.size() == feedModel.getSliderItems().size();
|
||||||
|
if (allDownloaded) {
|
||||||
|
allDownloaded = checkList.stream().allMatch(downloaded -> downloaded);
|
||||||
|
}
|
||||||
|
binding.downloaded.setImageTintList(ColorStateList.valueOf(itemView.getResources().getColor(
|
||||||
|
allDownloaded ? R.color.green_A400 : R.color.yellow_400)));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
});
|
||||||
|
task.execute(feedModel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,241 +1,241 @@
|
|||||||
package awais.instagrabber.asyncs;
|
// package awais.instagrabber.asyncs;
|
||||||
|
//
|
||||||
import android.app.PendingIntent;
|
// import android.app.PendingIntent;
|
||||||
import android.content.ContentResolver;
|
// import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
// import android.content.Context;
|
||||||
import android.content.Intent;
|
// import android.content.Intent;
|
||||||
import android.content.res.Resources;
|
// import android.content.res.Resources;
|
||||||
import android.graphics.Bitmap;
|
// import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapFactory;
|
// import android.graphics.BitmapFactory;
|
||||||
import android.media.MediaMetadataRetriever;
|
// import android.media.MediaMetadataRetriever;
|
||||||
import android.media.MediaScannerConnection;
|
// import android.media.MediaScannerConnection;
|
||||||
import android.net.Uri;
|
// import android.net.Uri;
|
||||||
import android.os.AsyncTask;
|
// import android.os.AsyncTask;
|
||||||
import android.os.Build;
|
// import android.os.Build;
|
||||||
import android.util.Log;
|
// import android.util.Log;
|
||||||
import android.util.Pair;
|
// import android.util.Pair;
|
||||||
|
//
|
||||||
import androidx.annotation.NonNull;
|
// import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
// import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.StringRes;
|
// import androidx.annotation.StringRes;
|
||||||
import androidx.core.app.NotificationCompat;
|
// import androidx.core.app.NotificationCompat;
|
||||||
import androidx.core.app.NotificationManagerCompat;
|
// import androidx.core.app.NotificationManagerCompat;
|
||||||
import androidx.core.content.FileProvider;
|
// import androidx.core.content.FileProvider;
|
||||||
|
//
|
||||||
import java.io.BufferedInputStream;
|
// import java.io.BufferedInputStream;
|
||||||
import java.io.File;
|
// import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
// import java.io.FileOutputStream;
|
||||||
import java.io.InputStream;
|
// import java.io.InputStream;
|
||||||
import java.net.URL;
|
// import java.net.URL;
|
||||||
import java.net.URLConnection;
|
// import java.net.URLConnection;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
// import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
//
|
||||||
import awais.instagrabber.BuildConfig;
|
// import awais.instagrabber.BuildConfig;
|
||||||
import awais.instagrabber.R;
|
// import awais.instagrabber.R;
|
||||||
import awais.instagrabber.interfaces.FetchListener;
|
// import awais.instagrabber.interfaces.FetchListener;
|
||||||
import awais.instagrabber.utils.Constants;
|
// import awais.instagrabber.utils.Constants;
|
||||||
import awais.instagrabber.utils.Utils;
|
// import awais.instagrabber.utils.Utils;
|
||||||
|
//
|
||||||
import static awais.instagrabber.utils.Constants.NOTIF_GROUP_NAME;
|
// import static awais.instagrabber.utils.Constants.NOTIF_GROUP_NAME;
|
||||||
import static awais.instagrabber.utils.Utils.logCollector;
|
// import static awais.instagrabber.utils.Utils.logCollector;
|
||||||
import static awaisomereport.LogCollector.LogFile;
|
// import static awaisomereport.LogCollector.LogFile;
|
||||||
|
//
|
||||||
public final class DownloadAsync extends AsyncTask<Void, Float, File> {
|
// public final class DownloadAsync extends AsyncTask<Void, Float, File> {
|
||||||
private static final String TAG = "DownloadAsync";
|
// private static final String TAG = "DownloadAsync";
|
||||||
|
//
|
||||||
private static int lastNotifId = 1;
|
// private static int lastNotifId = 1;
|
||||||
private final int currentNotifId;
|
// private final int currentNotifId;
|
||||||
private final AtomicReference<Context> context;
|
// private final AtomicReference<Context> context;
|
||||||
private final File outFile;
|
// private final File outFile;
|
||||||
private final String url;
|
// private final String url;
|
||||||
private final FetchListener<File> fetchListener;
|
// private final FetchListener<File> fetchListener;
|
||||||
private final Resources resources;
|
// private final Resources resources;
|
||||||
private final NotificationCompat.Builder downloadNotif;
|
// private final NotificationCompat.Builder downloadNotif;
|
||||||
private String shortCode, username;
|
// private String shortCode, username;
|
||||||
private final NotificationManagerCompat notificationManager;
|
// private final NotificationManagerCompat notificationManager;
|
||||||
|
//
|
||||||
public DownloadAsync(@NonNull final Context context,
|
// public DownloadAsync(@NonNull final Context context,
|
||||||
final String url,
|
// final String url,
|
||||||
final File outFile,
|
// final File outFile,
|
||||||
final FetchListener<File> fetchListener) {
|
// final FetchListener<File> fetchListener) {
|
||||||
this.context = new AtomicReference<>(context);
|
// this.context = new AtomicReference<>(context);
|
||||||
this.resources = context.getResources();
|
// this.resources = context.getResources();
|
||||||
this.url = url;
|
// this.url = url;
|
||||||
this.outFile = outFile;
|
// this.outFile = outFile;
|
||||||
this.fetchListener = fetchListener;
|
// this.fetchListener = fetchListener;
|
||||||
this.shortCode = this.username = resources.getString(R.string.downloader_started);
|
// this.shortCode = this.username = resources.getString(R.string.downloader_started);
|
||||||
this.currentNotifId = ++lastNotifId;
|
// this.currentNotifId = ++lastNotifId;
|
||||||
if (++lastNotifId + 1 == Integer.MAX_VALUE) lastNotifId = 1;
|
// if (++lastNotifId + 1 == Integer.MAX_VALUE) lastNotifId = 1;
|
||||||
|
//
|
||||||
@StringRes final int titleRes = R.string.downloader_downloading_post;
|
// @StringRes final int titleRes = R.string.downloader_downloading_post;
|
||||||
downloadNotif = new NotificationCompat.Builder(context, Constants.DOWNLOAD_CHANNEL_ID)
|
// downloadNotif = new NotificationCompat.Builder(context, Constants.DOWNLOAD_CHANNEL_ID)
|
||||||
.setCategory(NotificationCompat.CATEGORY_STATUS)
|
// .setCategory(NotificationCompat.CATEGORY_STATUS)
|
||||||
.setSmallIcon(R.mipmap.ic_launcher)
|
// .setSmallIcon(R.mipmap.ic_launcher)
|
||||||
.setContentText(shortCode == null ? username : shortCode)
|
// .setContentText(shortCode == null ? username : shortCode)
|
||||||
.setOngoing(true)
|
// .setOngoing(true)
|
||||||
.setProgress(100, 0, false)
|
// .setProgress(100, 0, false)
|
||||||
.setAutoCancel(false)
|
// .setAutoCancel(false)
|
||||||
.setOnlyAlertOnce(true)
|
// .setOnlyAlertOnce(true)
|
||||||
.setContentTitle(resources.getString(titleRes));
|
// .setContentTitle(resources.getString(titleRes));
|
||||||
|
//
|
||||||
notificationManager = NotificationManagerCompat.from(context.getApplicationContext());
|
// notificationManager = NotificationManagerCompat.from(context.getApplicationContext());
|
||||||
notificationManager.notify(currentNotifId, downloadNotif.build());
|
// notificationManager.notify(currentNotifId, downloadNotif.build());
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
public DownloadAsync setItems(final String shortCode, final String username) {
|
// public DownloadAsync setItems(final String shortCode, final String username) {
|
||||||
this.shortCode = shortCode;
|
// this.shortCode = shortCode;
|
||||||
this.username = username;
|
// this.username = username;
|
||||||
if (downloadNotif != null) downloadNotif.setContentText(this.shortCode == null ? this.username : this.shortCode);
|
// if (downloadNotif != null) downloadNotif.setContentText(this.shortCode == null ? this.username : this.shortCode);
|
||||||
return this;
|
// return this;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Nullable
|
// @Nullable
|
||||||
@Override
|
// @Override
|
||||||
protected File doInBackground(final Void... voids) {
|
// protected File doInBackground(final Void... voids) {
|
||||||
try {
|
// try {
|
||||||
final URLConnection urlConnection = new URL(url).openConnection();
|
// final URLConnection urlConnection = new URL(url).openConnection();
|
||||||
final long fileSize = Build.VERSION.SDK_INT >= 24 ? urlConnection.getContentLengthLong() :
|
// final long fileSize = Build.VERSION.SDK_INT >= 24 ? urlConnection.getContentLengthLong() :
|
||||||
urlConnection.getContentLength();
|
// urlConnection.getContentLength();
|
||||||
float totalRead = 0;
|
// float totalRead = 0;
|
||||||
|
//
|
||||||
try (final BufferedInputStream bis = new BufferedInputStream(urlConnection.getInputStream());
|
// try (final BufferedInputStream bis = new BufferedInputStream(urlConnection.getInputStream());
|
||||||
final FileOutputStream fos = new FileOutputStream(outFile)) {
|
// final FileOutputStream fos = new FileOutputStream(outFile)) {
|
||||||
final byte[] buffer = new byte[0x2000];
|
// final byte[] buffer = new byte[0x2000];
|
||||||
|
//
|
||||||
int count;
|
// int count;
|
||||||
boolean deletedIPTC = false;
|
// boolean deletedIPTC = false;
|
||||||
while ((count = bis.read(buffer, 0, 0x2000)) != -1) {
|
// while ((count = bis.read(buffer, 0, 0x2000)) != -1) {
|
||||||
totalRead = totalRead + count;
|
// totalRead = totalRead + count;
|
||||||
|
//
|
||||||
if (!deletedIPTC) {
|
// if (!deletedIPTC) {
|
||||||
int iptcStart = -1;
|
// int iptcStart = -1;
|
||||||
int fbmdStart = -1;
|
// int fbmdStart = -1;
|
||||||
int fbmdBytesLen = -1;
|
// int fbmdBytesLen = -1;
|
||||||
|
//
|
||||||
for (int i = 0; i < buffer.length; ++i) {
|
// for (int i = 0; i < buffer.length; ++i) {
|
||||||
if (buffer[i] == (byte) 0xFF && buffer[i + 1] == (byte) 0xED)
|
// if (buffer[i] == (byte) 0xFF && buffer[i + 1] == (byte) 0xED)
|
||||||
iptcStart = i;
|
// iptcStart = i;
|
||||||
else if (buffer[i] == (byte) 'F' && buffer[i + 1] == (byte) 'B'
|
// else if (buffer[i] == (byte) 'F' && buffer[i + 1] == (byte) 'B'
|
||||||
&& buffer[i + 2] == (byte) 'M' && buffer[i + 3] == (byte) 'D') {
|
// && buffer[i + 2] == (byte) 'M' && buffer[i + 3] == (byte) 'D') {
|
||||||
fbmdStart = i;
|
// fbmdStart = i;
|
||||||
fbmdBytesLen = buffer[i - 10] << 24 | (buffer[i - 9] & 0xFF) << 16 |
|
// fbmdBytesLen = buffer[i - 10] << 24 | (buffer[i - 9] & 0xFF) << 16 |
|
||||||
(buffer[i - 8] & 0xFF) << 8 | (buffer[i - 7] & 0xFF) |
|
// (buffer[i - 8] & 0xFF) << 8 | (buffer[i - 7] & 0xFF) |
|
||||||
(buffer[i - 6] & 0xFF);
|
// (buffer[i - 6] & 0xFF);
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
if (iptcStart != -1 && fbmdStart != -1 && fbmdBytesLen != -1) {
|
// if (iptcStart != -1 && fbmdStart != -1 && fbmdBytesLen != -1) {
|
||||||
final int fbmdDataLen = (iptcStart + (fbmdStart - iptcStart) + (fbmdBytesLen - iptcStart)) - 4;
|
// final int fbmdDataLen = (iptcStart + (fbmdStart - iptcStart) + (fbmdBytesLen - iptcStart)) - 4;
|
||||||
|
//
|
||||||
fos.write(buffer, 0, iptcStart);
|
// fos.write(buffer, 0, iptcStart);
|
||||||
fos.write(buffer, fbmdDataLen + iptcStart, count - fbmdDataLen - iptcStart);
|
// fos.write(buffer, fbmdDataLen + iptcStart, count - fbmdDataLen - iptcStart);
|
||||||
|
//
|
||||||
publishProgress(totalRead * 100f / fileSize);
|
// publishProgress(totalRead * 100f / fileSize);
|
||||||
|
//
|
||||||
deletedIPTC = true;
|
// deletedIPTC = true;
|
||||||
continue;
|
// continue;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
fos.write(buffer, 0, count);
|
// fos.write(buffer, 0, count);
|
||||||
publishProgress(totalRead * 100f / fileSize);
|
// publishProgress(totalRead * 100f / fileSize);
|
||||||
}
|
// }
|
||||||
fos.flush();
|
// fos.flush();
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
return outFile;
|
// return outFile;
|
||||||
} catch (final Exception e) {
|
// } catch (final Exception e) {
|
||||||
if (logCollector != null)
|
// if (logCollector != null)
|
||||||
logCollector.appendException(e, LogFile.ASYNC_DOWNLOADER, "doInBackground",
|
// logCollector.appendException(e, LogFile.ASYNC_DOWNLOADER, "doInBackground",
|
||||||
new Pair<>("context", context.get()),
|
// new Pair<>("context", context.get()),
|
||||||
new Pair<>("resources", resources),
|
// new Pair<>("resources", resources),
|
||||||
new Pair<>("lastNotifId", lastNotifId),
|
// new Pair<>("lastNotifId", lastNotifId),
|
||||||
new Pair<>("downloadNotif", downloadNotif),
|
// new Pair<>("downloadNotif", downloadNotif),
|
||||||
new Pair<>("currentNotifId", currentNotifId),
|
// new Pair<>("currentNotifId", currentNotifId),
|
||||||
new Pair<>("notificationManager", notificationManager));
|
// new Pair<>("notificationManager", notificationManager));
|
||||||
if (BuildConfig.DEBUG) Log.e(TAG, "", e);
|
// if (BuildConfig.DEBUG) Log.e(TAG, "", e);
|
||||||
}
|
// }
|
||||||
return null;
|
// return null;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
protected void onPreExecute() {
|
// protected void onPreExecute() {
|
||||||
if (fetchListener != null) fetchListener.doBefore();
|
// if (fetchListener != null) fetchListener.doBefore();
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
protected void onProgressUpdate(@NonNull final Float... values) {
|
// protected void onProgressUpdate(@NonNull final Float... values) {
|
||||||
if (downloadNotif != null) {
|
// if (downloadNotif != null) {
|
||||||
downloadNotif.setProgress(100, values[0].intValue(), false);
|
// downloadNotif.setProgress(100, values[0].intValue(), false);
|
||||||
notificationManager.notify(currentNotifId, downloadNotif.build());
|
// notificationManager.notify(currentNotifId, downloadNotif.build());
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
protected void onPostExecute(final File result) {
|
// protected void onPostExecute(final File result) {
|
||||||
if (result != null) {
|
// if (result != null) {
|
||||||
final Context context = this.context.get();
|
// final Context context = this.context.get();
|
||||||
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(result.getAbsoluteFile())));
|
// context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(result.getAbsoluteFile())));
|
||||||
MediaScannerConnection.scanFile(context, new String[]{result.getAbsolutePath()}, null, null);
|
// MediaScannerConnection.scanFile(context, new String[]{result.getAbsolutePath()}, null, null);
|
||||||
|
//
|
||||||
if (notificationManager != null) {
|
// if (notificationManager != null) {
|
||||||
final Uri uri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider", result);
|
// final Uri uri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider", result);
|
||||||
|
//
|
||||||
final ContentResolver contentResolver = context.getContentResolver();
|
// final ContentResolver contentResolver = context.getContentResolver();
|
||||||
Bitmap bitmap = null;
|
// Bitmap bitmap = null;
|
||||||
if (Utils.isImage(uri, contentResolver)) {
|
// if (Utils.isImage(uri, contentResolver)) {
|
||||||
try (final InputStream inputStream = contentResolver.openInputStream(uri)) {
|
// try (final InputStream inputStream = contentResolver.openInputStream(uri)) {
|
||||||
bitmap = BitmapFactory.decodeStream(inputStream);
|
// bitmap = BitmapFactory.decodeStream(inputStream);
|
||||||
} catch (final Exception e) {
|
// } catch (final Exception e) {
|
||||||
if (logCollector != null)
|
// if (logCollector != null)
|
||||||
logCollector.appendException(e, LogFile.ASYNC_DOWNLOADER, "onPostExecute::bitmap_1");
|
// logCollector.appendException(e, LogFile.ASYNC_DOWNLOADER, "onPostExecute::bitmap_1");
|
||||||
if (BuildConfig.DEBUG) Log.e(TAG, "", e);
|
// if (BuildConfig.DEBUG) Log.e(TAG, "", e);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
if (bitmap == null) {
|
// if (bitmap == null) {
|
||||||
final MediaMetadataRetriever retriever = new MediaMetadataRetriever();
|
// final MediaMetadataRetriever retriever = new MediaMetadataRetriever();
|
||||||
try {
|
// try {
|
||||||
try {
|
// try {
|
||||||
retriever.setDataSource(context, uri);
|
// retriever.setDataSource(context, uri);
|
||||||
} catch (final Exception e) {
|
// } catch (final Exception e) {
|
||||||
retriever.setDataSource(result.getAbsolutePath());
|
// retriever.setDataSource(result.getAbsolutePath());
|
||||||
}
|
// }
|
||||||
bitmap = retriever.getFrameAtTime();
|
// bitmap = retriever.getFrameAtTime();
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
|
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
|
||||||
try {
|
// try {
|
||||||
retriever.close();
|
// retriever.close();
|
||||||
} catch (final Exception e) {
|
// } catch (final Exception e) {
|
||||||
if (logCollector != null)
|
// if (logCollector != null)
|
||||||
logCollector.appendException(e, LogFile.ASYNC_DOWNLOADER, "onPostExecute::bitmap_2");
|
// logCollector.appendException(e, LogFile.ASYNC_DOWNLOADER, "onPostExecute::bitmap_2");
|
||||||
}
|
// }
|
||||||
} catch (final Exception e) {
|
// } catch (final Exception e) {
|
||||||
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
|
// if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
|
||||||
if (logCollector != null)
|
// if (logCollector != null)
|
||||||
logCollector.appendException(e, LogFile.ASYNC_DOWNLOADER, "onPostExecute::bitmap_3");
|
// logCollector.appendException(e, LogFile.ASYNC_DOWNLOADER, "onPostExecute::bitmap_3");
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
final String downloadComplete = resources.getString(R.string.downloader_complete);
|
// final String downloadComplete = resources.getString(R.string.downloader_complete);
|
||||||
|
//
|
||||||
downloadNotif.setContentText(null).setContentTitle(downloadComplete).setProgress(0, 0, false)
|
// downloadNotif.setContentText(null).setContentTitle(downloadComplete).setProgress(0, 0, false)
|
||||||
.setWhen(System.currentTimeMillis()).setOngoing(false).setOnlyAlertOnce(false).setAutoCancel(true)
|
// .setWhen(System.currentTimeMillis()).setOngoing(false).setOnlyAlertOnce(false).setAutoCancel(true)
|
||||||
.setGroup(NOTIF_GROUP_NAME).setGroupSummary(true).setContentIntent(
|
// .setGroup(NOTIF_GROUP_NAME).setGroupSummary(true).setContentIntent(
|
||||||
PendingIntent.getActivity(context, 2020, new Intent(Intent.ACTION_VIEW, uri)
|
// PendingIntent.getActivity(context, 2020, new Intent(Intent.ACTION_VIEW, uri)
|
||||||
.addFlags(
|
// .addFlags(
|
||||||
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_FROM_BACKGROUND | Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
// Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_FROM_BACKGROUND | Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||||
.putExtra(Intent.EXTRA_STREAM, uri), PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_ONE_SHOT));
|
// .putExtra(Intent.EXTRA_STREAM, uri), PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_ONE_SHOT));
|
||||||
|
//
|
||||||
if (bitmap != null)
|
// if (bitmap != null)
|
||||||
downloadNotif.setStyle(new NotificationCompat.BigPictureStyle().setBigContentTitle(downloadComplete).bigPicture(bitmap))
|
// downloadNotif.setStyle(new NotificationCompat.BigPictureStyle().setBigContentTitle(downloadComplete).bigPicture(bitmap))
|
||||||
.setLargeIcon(bitmap).setBadgeIconType(NotificationCompat.BADGE_ICON_SMALL);
|
// .setLargeIcon(bitmap).setBadgeIconType(NotificationCompat.BADGE_ICON_SMALL);
|
||||||
|
//
|
||||||
notificationManager.cancel(currentNotifId);
|
// notificationManager.cancel(currentNotifId);
|
||||||
notificationManager.notify(currentNotifId + 1, downloadNotif.build());
|
// notificationManager.notify(currentNotifId + 1, downloadNotif.build());
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
if (fetchListener != null) fetchListener.onResult(result);
|
// if (fetchListener != null) fetchListener.onResult(result);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
@ -0,0 +1,42 @@
|
|||||||
|
package awais.instagrabber.asyncs;
|
||||||
|
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import awais.instagrabber.models.FeedModel;
|
||||||
|
import awais.instagrabber.utils.DownloadUtils;
|
||||||
|
|
||||||
|
public final class DownloadedCheckerAsyncTask extends AsyncTask<FeedModel, Void, Map<String, List<Boolean>>> {
|
||||||
|
private static final String TAG = "DownloadedCheckerAsyncTask";
|
||||||
|
|
||||||
|
private final OnCheckResultListener listener;
|
||||||
|
|
||||||
|
public DownloadedCheckerAsyncTask(final OnCheckResultListener listener) {
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Map<String, List<Boolean>> doInBackground(final FeedModel... feedModels) {
|
||||||
|
if (feedModels == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final Map<String, List<Boolean>> map = new HashMap<>();
|
||||||
|
for (final FeedModel feedModel : feedModels) {
|
||||||
|
map.put(feedModel.getPostId(), DownloadUtils.checkDownloaded(feedModel));
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(final Map<String, List<Boolean>> result) {
|
||||||
|
if (listener == null) return;
|
||||||
|
listener.onResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface OnCheckResultListener {
|
||||||
|
void onResult(final Map<String, List<Boolean>> result);
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +1,11 @@
|
|||||||
package awais.instagrabber.asyncs;
|
package awais.instagrabber.asyncs;
|
||||||
|
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Environment;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -26,9 +24,6 @@ import awais.instagrabber.utils.TextUtils;
|
|||||||
import awais.instagrabber.utils.Utils;
|
import awais.instagrabber.utils.Utils;
|
||||||
import awaisomereport.LogCollector;
|
import awaisomereport.LogCollector;
|
||||||
|
|
||||||
import static awais.instagrabber.utils.Constants.DOWNLOAD_USER_FOLDER;
|
|
||||||
import static awais.instagrabber.utils.Constants.FOLDER_PATH;
|
|
||||||
import static awais.instagrabber.utils.Constants.FOLDER_SAVE_TO;
|
|
||||||
import static awais.instagrabber.utils.Utils.logCollector;
|
import static awais.instagrabber.utils.Utils.logCollector;
|
||||||
|
|
||||||
public final class PostFetcher extends AsyncTask<Void, Void, FeedModel> {
|
public final class PostFetcher extends AsyncTask<Void, Void, FeedModel> {
|
||||||
@ -78,19 +73,6 @@ public final class PostFetcher extends AsyncTask<Void, Void, FeedModel> {
|
|||||||
owner.optBoolean("requested_by_viewer")
|
owner.optBoolean("requested_by_viewer")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
final String username = profileModel == null ? "" : profileModel.getUsername();
|
|
||||||
// to check if file exists
|
|
||||||
final File downloadDir = new File(Environment.getExternalStorageDirectory(), "Download" +
|
|
||||||
(Utils.settingsHelper.getBoolean(DOWNLOAD_USER_FOLDER) ? ("/" + username) : ""));
|
|
||||||
File customDir = null;
|
|
||||||
if (Utils.settingsHelper.getBoolean(FOLDER_SAVE_TO)) {
|
|
||||||
final String customPath = Utils.settingsHelper.getString(FOLDER_PATH +
|
|
||||||
(Utils.settingsHelper.getBoolean(DOWNLOAD_USER_FOLDER)
|
|
||||||
? ("/" + username)
|
|
||||||
: ""));
|
|
||||||
if (!TextUtils.isEmpty(customPath)) customDir = new File(customPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
final long timestamp = media.getLong("taken_at_timestamp");
|
final long timestamp = media.getLong("taken_at_timestamp");
|
||||||
|
|
||||||
final boolean isVideo = media.has("is_video") && media.optBoolean("is_video");
|
final boolean isVideo = media.has("is_video") && media.optBoolean("is_video");
|
||||||
@ -138,7 +120,6 @@ public final class PostFetcher extends AsyncTask<Void, Void, FeedModel> {
|
|||||||
? null
|
? null
|
||||||
: media.getJSONObject("location").optString("id"))
|
: media.getJSONObject("location").optString("id"))
|
||||||
.setCommentsCount(commentsCount);
|
.setCommentsCount(commentsCount);
|
||||||
// DownloadUtils.checkExistence(downloadDir, customDir, false, feedModelBuilder);
|
|
||||||
if (isSlider) {
|
if (isSlider) {
|
||||||
final JSONArray children = media.getJSONObject("edge_sidecar_to_children").getJSONArray("edges");
|
final JSONArray children = media.getJSONObject("edge_sidecar_to_children").getJSONArray("edges");
|
||||||
final List<PostChild> postModels = new ArrayList<>();
|
final List<PostChild> postModels = new ArrayList<>();
|
||||||
@ -158,7 +139,6 @@ public final class PostFetcher extends AsyncTask<Void, Void, FeedModel> {
|
|||||||
.setHeight(childNode.getJSONObject("dimensions").getInt("height"))
|
.setHeight(childNode.getJSONObject("dimensions").getInt("height"))
|
||||||
.setWidth(childNode.getJSONObject("dimensions").getInt("width"))
|
.setWidth(childNode.getJSONObject("dimensions").getInt("width"))
|
||||||
.build());
|
.build());
|
||||||
// DownloadUtils.checkExistence(downloadDir, customDir, true, postModels.get(i));
|
|
||||||
}
|
}
|
||||||
feedModelBuilder.setSliderItems(postModels);
|
feedModelBuilder.setSliderItems(postModels);
|
||||||
}
|
}
|
||||||
|
@ -14,8 +14,14 @@ import androidx.recyclerview.widget.StaggeredGridLayoutManager;
|
|||||||
import androidx.transition.ChangeBounds;
|
import androidx.transition.ChangeBounds;
|
||||||
import androidx.transition.Transition;
|
import androidx.transition.Transition;
|
||||||
import androidx.transition.TransitionManager;
|
import androidx.transition.TransitionManager;
|
||||||
|
import androidx.work.Data;
|
||||||
|
import androidx.work.WorkInfo;
|
||||||
|
import androidx.work.WorkManager;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import awais.instagrabber.adapters.FeedAdapterV2;
|
import awais.instagrabber.adapters.FeedAdapterV2;
|
||||||
@ -24,9 +30,11 @@ import awais.instagrabber.customviews.helpers.PostFetcher;
|
|||||||
import awais.instagrabber.customviews.helpers.RecyclerLazyLoaderAtBottom;
|
import awais.instagrabber.customviews.helpers.RecyclerLazyLoaderAtBottom;
|
||||||
import awais.instagrabber.interfaces.FetchListener;
|
import awais.instagrabber.interfaces.FetchListener;
|
||||||
import awais.instagrabber.models.FeedModel;
|
import awais.instagrabber.models.FeedModel;
|
||||||
|
import awais.instagrabber.models.PostChild;
|
||||||
import awais.instagrabber.models.PostsLayoutPreferences;
|
import awais.instagrabber.models.PostsLayoutPreferences;
|
||||||
import awais.instagrabber.utils.Utils;
|
import awais.instagrabber.utils.Utils;
|
||||||
import awais.instagrabber.viewmodels.FeedViewModel;
|
import awais.instagrabber.viewmodels.FeedViewModel;
|
||||||
|
import awais.instagrabber.workers.DownloadWorker;
|
||||||
|
|
||||||
public class PostsRecyclerView extends RecyclerView {
|
public class PostsRecyclerView extends RecyclerView {
|
||||||
private static final String TAG = "PostsRecyclerView";
|
private static final String TAG = "PostsRecyclerView";
|
||||||
@ -146,7 +154,7 @@ public class PostsRecyclerView extends RecyclerView {
|
|||||||
initAdapter();
|
initAdapter();
|
||||||
initLayoutManager();
|
initLayoutManager();
|
||||||
initSelf();
|
initSelf();
|
||||||
|
initDownloadWorkerListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initTransition() {
|
private void initTransition() {
|
||||||
@ -189,6 +197,51 @@ public class PostsRecyclerView extends RecyclerView {
|
|||||||
dispatchFetchStatus();
|
dispatchFetchStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initDownloadWorkerListener() {
|
||||||
|
WorkManager.getInstance(getContext())
|
||||||
|
.getWorkInfosByTagLiveData("download")
|
||||||
|
.observe(lifeCycleOwner, workInfoList -> {
|
||||||
|
for (final WorkInfo workInfo : workInfoList) {
|
||||||
|
if (workInfo == null) continue;
|
||||||
|
final Data progress = workInfo.getProgress();
|
||||||
|
final float progressPercent = progress.getFloat(DownloadWorker.PROGRESS, 0);
|
||||||
|
if (progressPercent != 100) continue;
|
||||||
|
final String url = progress.getString(DownloadWorker.URL);
|
||||||
|
final List<FeedModel> feedModels = feedViewModel.getList().getValue();
|
||||||
|
for (int i = 0; i < feedModels.size(); i++) {
|
||||||
|
final FeedModel feedModel = feedModels.get(i);
|
||||||
|
final List<String> displayUrls = getDisplayUrl(feedModel);
|
||||||
|
if (displayUrls.contains(url)) {
|
||||||
|
feedAdapter.notifyItemChanged(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getDisplayUrl(final FeedModel feedModel) {
|
||||||
|
List<String> urls = Collections.emptyList();
|
||||||
|
switch (feedModel.getItemType()) {
|
||||||
|
case MEDIA_TYPE_IMAGE:
|
||||||
|
case MEDIA_TYPE_VIDEO:
|
||||||
|
urls = Collections.singletonList(feedModel.getDisplayUrl());
|
||||||
|
break;
|
||||||
|
case MEDIA_TYPE_SLIDER:
|
||||||
|
final List<PostChild> sliderItems = feedModel.getSliderItems();
|
||||||
|
if (sliderItems != null) {
|
||||||
|
final ImmutableList.Builder<String> builder = ImmutableList.builder();
|
||||||
|
for (final PostChild child : sliderItems) {
|
||||||
|
builder.add(child.getDisplayUrl());
|
||||||
|
}
|
||||||
|
urls = builder.build();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
return urls;
|
||||||
|
}
|
||||||
|
|
||||||
private void updateLayout() {
|
private void updateLayout() {
|
||||||
post(() -> {
|
post(() -> {
|
||||||
TransitionManager.beginDelayedTransition(this, transition);
|
TransitionManager.beginDelayedTransition(this, transition);
|
||||||
|
@ -6,9 +6,7 @@ import android.content.Intent;
|
|||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.graphics.drawable.Animatable;
|
import android.graphics.drawable.Animatable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Environment;
|
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
@ -55,7 +53,6 @@ import com.google.android.exoplayer2.source.MediaSourceEventListener;
|
|||||||
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
|
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
|
||||||
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -65,7 +62,6 @@ import java.util.List;
|
|||||||
import awais.instagrabber.BuildConfig;
|
import awais.instagrabber.BuildConfig;
|
||||||
import awais.instagrabber.R;
|
import awais.instagrabber.R;
|
||||||
import awais.instagrabber.adapters.StoriesAdapter;
|
import awais.instagrabber.adapters.StoriesAdapter;
|
||||||
import awais.instagrabber.asyncs.DownloadAsync;
|
|
||||||
import awais.instagrabber.asyncs.PostFetcher;
|
import awais.instagrabber.asyncs.PostFetcher;
|
||||||
import awais.instagrabber.asyncs.QuizAction;
|
import awais.instagrabber.asyncs.QuizAction;
|
||||||
import awais.instagrabber.asyncs.RespondAction;
|
import awais.instagrabber.asyncs.RespondAction;
|
||||||
@ -97,8 +93,6 @@ import awaisomereport.LogCollector;
|
|||||||
|
|
||||||
import static awais.instagrabber.customviews.helpers.SwipeGestureListener.SWIPE_THRESHOLD;
|
import static awais.instagrabber.customviews.helpers.SwipeGestureListener.SWIPE_THRESHOLD;
|
||||||
import static awais.instagrabber.customviews.helpers.SwipeGestureListener.SWIPE_VELOCITY_THRESHOLD;
|
import static awais.instagrabber.customviews.helpers.SwipeGestureListener.SWIPE_VELOCITY_THRESHOLD;
|
||||||
import static awais.instagrabber.utils.Constants.FOLDER_PATH;
|
|
||||||
import static awais.instagrabber.utils.Constants.FOLDER_SAVE_TO;
|
|
||||||
import static awais.instagrabber.utils.Constants.MARK_AS_SEEN;
|
import static awais.instagrabber.utils.Constants.MARK_AS_SEEN;
|
||||||
import static awais.instagrabber.utils.Utils.logCollector;
|
import static awais.instagrabber.utils.Utils.logCollector;
|
||||||
import static awais.instagrabber.utils.Utils.settingsHelper;
|
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||||
@ -359,7 +353,8 @@ public class StoryViewerFragment extends Fragment {
|
|||||||
binding.btnBackward.setVisibility(currentFeedStoryIndex == 0 ? View.INVISIBLE : View.VISIBLE);
|
binding.btnBackward.setVisibility(currentFeedStoryIndex == 0 ? View.INVISIBLE : View.VISIBLE);
|
||||||
binding.btnForward.setVisibility(currentFeedStoryIndex == finalModels.size() - 1 ? View.INVISIBLE : View.VISIBLE);
|
binding.btnForward.setVisibility(currentFeedStoryIndex == finalModels.size() - 1 ? View.INVISIBLE : View.VISIBLE);
|
||||||
binding.btnBackward.setOnClickListener(v -> paginateStories(finalModels.get(currentFeedStoryIndex - 1), context, true, false));
|
binding.btnBackward.setOnClickListener(v -> paginateStories(finalModels.get(currentFeedStoryIndex - 1), context, true, false));
|
||||||
binding.btnForward.setOnClickListener(v -> paginateStories(finalModels.get(currentFeedStoryIndex + 1), context, false, currentFeedStoryIndex == finalModels.size() - 2));
|
binding.btnForward.setOnClickListener(v -> paginateStories(finalModels.get(currentFeedStoryIndex + 1), context, false,
|
||||||
|
currentFeedStoryIndex == finalModels.size() - 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.imageViewer.setTapListener(simpleOnGestureListener);
|
binding.imageViewer.setTapListener(simpleOnGestureListener);
|
||||||
@ -517,7 +512,7 @@ public class StoryViewerFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
storiesViewModel.getList().setValue(Collections.emptyList());
|
storiesViewModel.getList().setValue(Collections.emptyList());
|
||||||
if (currentStoryMediaId == null) return;
|
if (currentStoryMediaId == null) return;
|
||||||
final ServiceCallback storyCallback = new ServiceCallback<List<StoryModel>>() {
|
final ServiceCallback<List<StoryModel>> storyCallback = new ServiceCallback<List<StoryModel>>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(final List<StoryModel> storyModels) {
|
public void onSuccess(final List<StoryModel> storyModels) {
|
||||||
fetching = false;
|
fetching = false;
|
||||||
@ -612,43 +607,13 @@ public class StoryViewerFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void downloadStory() {
|
private void downloadStory() {
|
||||||
int error = 0;
|
|
||||||
final Context context = getContext();
|
final Context context = getContext();
|
||||||
if (context == null) return;
|
if (context == null) return;
|
||||||
if (currentStory != null) {
|
if (currentStory == null) {
|
||||||
File dir = new File(Environment.getExternalStorageDirectory(), "Download");
|
|
||||||
|
|
||||||
if (settingsHelper.getBoolean(FOLDER_SAVE_TO)) {
|
|
||||||
final String customPath = settingsHelper.getString(FOLDER_PATH);
|
|
||||||
if (!TextUtils.isEmpty(customPath)) dir = new File(customPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (settingsHelper.getBoolean(Constants.DOWNLOAD_USER_FOLDER) && !TextUtils.isEmpty(currentStoryUsername))
|
|
||||||
dir = new File(dir, currentStoryUsername);
|
|
||||||
|
|
||||||
if (dir.exists() || dir.mkdirs()) {
|
|
||||||
final String storyUrl = currentStory.getItemType() == MediaItemType.MEDIA_TYPE_VIDEO
|
|
||||||
? currentStory.getVideoUrl()
|
|
||||||
: currentStory.getStoryUrl();
|
|
||||||
final File saveFile = new File(
|
|
||||||
dir,
|
|
||||||
currentStory.getStoryMediaId()
|
|
||||||
+ "_" + currentStory.getTimestamp()
|
|
||||||
+ DownloadUtils.getFileExtensionFromUrl(storyUrl));
|
|
||||||
|
|
||||||
new DownloadAsync(context, storyUrl, saveFile, result -> {
|
|
||||||
final int toastRes = result != null && result.exists() ? R.string.downloader_complete
|
|
||||||
: R.string.downloader_error_download_file;
|
|
||||||
Toast.makeText(context, toastRes, Toast.LENGTH_SHORT).show();
|
|
||||||
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
||||||
|
|
||||||
} else error = 1;
|
|
||||||
} else error = 2;
|
|
||||||
|
|
||||||
if (error == 1)
|
|
||||||
Toast.makeText(context, R.string.downloader_error_creating_folder, Toast.LENGTH_SHORT).show();
|
|
||||||
else if (error == 2)
|
|
||||||
Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DownloadUtils.download(context, currentStory);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupImage() {
|
private void setupImage() {
|
||||||
|
@ -26,7 +26,7 @@ public final class StoryModel implements Serializable {
|
|||||||
private String[] mentions;
|
private String[] mentions;
|
||||||
private int position;
|
private int position;
|
||||||
private boolean isCurrentSlide = false;
|
private boolean isCurrentSlide = false;
|
||||||
private boolean canReply = false;
|
private final boolean canReply;
|
||||||
|
|
||||||
public StoryModel(final String storyMediaId, final String storyUrl, final MediaItemType itemType,
|
public StoryModel(final String storyMediaId, final String storyUrl, final MediaItemType itemType,
|
||||||
final long timestamp, final String username, final String userId, final boolean canReply) {
|
final long timestamp, final String username, final String userId, final boolean canReply) {
|
||||||
|
@ -44,7 +44,7 @@ public class DeleteImageIntentService extends IntentService {
|
|||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
deleted = file.delete();
|
deleted = file.delete();
|
||||||
if (!deleted) {
|
if (!deleted) {
|
||||||
Log.w(TAG, "onHandleIntent: file not delete!");
|
Log.w(TAG, "onHandleIntent: file not deleted!");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
deleted = true;
|
deleted = true;
|
||||||
|
@ -6,8 +6,6 @@ import android.content.Context;
|
|||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.util.Log;
|
|
||||||
import android.util.Pair;
|
|
||||||
import android.webkit.MimeTypeMap;
|
import android.webkit.MimeTypeMap;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
@ -26,21 +24,20 @@ import androidx.work.WorkRequest;
|
|||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FilenameFilter;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import awais.instagrabber.BuildConfig;
|
|
||||||
import awais.instagrabber.R;
|
import awais.instagrabber.R;
|
||||||
import awais.instagrabber.models.BasePostModel;
|
|
||||||
import awais.instagrabber.models.FeedModel;
|
import awais.instagrabber.models.FeedModel;
|
||||||
import awais.instagrabber.models.PostChild;
|
import awais.instagrabber.models.PostChild;
|
||||||
|
import awais.instagrabber.models.StoryModel;
|
||||||
|
import awais.instagrabber.models.enums.MediaItemType;
|
||||||
import awais.instagrabber.workers.DownloadWorker;
|
import awais.instagrabber.workers.DownloadWorker;
|
||||||
import awaisomereport.LogCollector;
|
|
||||||
|
|
||||||
import static awais.instagrabber.utils.Constants.FOLDER_PATH;
|
import static awais.instagrabber.utils.Constants.FOLDER_PATH;
|
||||||
import static awais.instagrabber.utils.Constants.FOLDER_SAVE_TO;
|
import static awais.instagrabber.utils.Constants.FOLDER_SAVE_TO;
|
||||||
@ -48,15 +45,6 @@ import static awais.instagrabber.utils.Constants.FOLDER_SAVE_TO;
|
|||||||
public final class DownloadUtils {
|
public final class DownloadUtils {
|
||||||
public static final String WRITE_PERMISSION = Manifest.permission.WRITE_EXTERNAL_STORAGE;
|
public static final String WRITE_PERMISSION = Manifest.permission.WRITE_EXTERNAL_STORAGE;
|
||||||
public static final String[] PERMS = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
|
public static final String[] PERMS = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
|
||||||
private static int lastNotificationId = UUID.randomUUID().hashCode();
|
|
||||||
|
|
||||||
public synchronized static int getNextDownloadNotificationId(@NonNull final Context context) {
|
|
||||||
lastNotificationId = lastNotificationId + 1;
|
|
||||||
if (lastNotificationId == Integer.MAX_VALUE) {
|
|
||||||
lastNotificationId = UUID.randomUUID().hashCode();
|
|
||||||
}
|
|
||||||
return lastNotificationId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private static File getDownloadDir() {
|
private static File getDownloadDir() {
|
||||||
@ -73,6 +61,13 @@ public final class DownloadUtils {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static File getDownloadDir(@NonNull final Context context, @Nullable final String username) {
|
private static File getDownloadDir(@NonNull final Context context, @Nullable final String username) {
|
||||||
|
return getDownloadDir(context, username, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static File getDownloadDir(final Context context,
|
||||||
|
@Nullable final String username,
|
||||||
|
final boolean skipCreateDir) {
|
||||||
File dir = getDownloadDir();
|
File dir = getDownloadDir();
|
||||||
|
|
||||||
if (Utils.settingsHelper.getBoolean(Constants.DOWNLOAD_USER_FOLDER) && !TextUtils.isEmpty(username)) {
|
if (Utils.settingsHelper.getBoolean(Constants.DOWNLOAD_USER_FOLDER) && !TextUtils.isEmpty(username)) {
|
||||||
@ -80,7 +75,7 @@ public final class DownloadUtils {
|
|||||||
dir = new File(dir, finaleUsername);
|
dir = new File(dir, finaleUsername);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dir.exists() && !dir.mkdirs()) {
|
if (context != null && !skipCreateDir && !dir.exists() && !dir.mkdirs()) {
|
||||||
Toast.makeText(context, R.string.error_creating_folders, Toast.LENGTH_SHORT).show();
|
Toast.makeText(context, R.string.error_creating_folders, Toast.LENGTH_SHORT).show();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -183,42 +178,29 @@ public final class DownloadUtils {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void checkExistence(final File downloadDir,
|
public static List<Boolean> checkDownloaded(@NonNull final FeedModel feedModel) {
|
||||||
final File customDir,
|
final List<Boolean> checkList = new LinkedList<>();
|
||||||
final boolean isSlider,
|
final File downloadDir = getDownloadDir(null, "@" + feedModel.getProfileModel().getUsername(), true);
|
||||||
@NonNull final BasePostModel model) {
|
switch (feedModel.getItemType()) {
|
||||||
boolean exists = false;
|
case MEDIA_TYPE_IMAGE:
|
||||||
|
case MEDIA_TYPE_VIDEO: {
|
||||||
try {
|
final String url = feedModel.getDisplayUrl();
|
||||||
final String displayUrl = model.getDisplayUrl();
|
final File file = getDownloadSaveFile(downloadDir, feedModel.getPostId(), url);
|
||||||
int index = displayUrl.indexOf('?');
|
checkList.add(file.exists());
|
||||||
if (index < 0) {
|
break;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
final String fileName = model.getPostId() + '_';
|
case MEDIA_TYPE_SLIDER:
|
||||||
final String extension = displayUrl.substring(index - 4, index);
|
final List<PostChild> sliderItems = feedModel.getSliderItems();
|
||||||
|
for (int i = 0; i < sliderItems.size(); i++) {
|
||||||
final String fileWithoutPrefix = fileName + '0' + extension;
|
final PostChild child = sliderItems.get(i);
|
||||||
exists = new File(downloadDir, fileWithoutPrefix).exists();
|
final String url = child.getDisplayUrl();
|
||||||
if (!exists) {
|
final File file = getDownloadChildSaveFile(downloadDir, feedModel.getPostId(), i + 1, url);
|
||||||
final String fileWithPrefix = fileName + "[\\d]+(|_slide_[\\d]+)(\\.mp4|\\\\" + extension + ")";
|
checkList.add(file.exists());
|
||||||
final FilenameFilter filenameFilter = (dir, name) -> Pattern.matches(fileWithPrefix, name);
|
|
||||||
|
|
||||||
File[] files = downloadDir.listFiles(filenameFilter);
|
|
||||||
if ((files == null || files.length < 1) && customDir != null)
|
|
||||||
files = customDir.listFiles(filenameFilter);
|
|
||||||
|
|
||||||
if (files != null && files.length >= 1) exists = true;
|
|
||||||
}
|
}
|
||||||
} catch (final Exception e) {
|
break;
|
||||||
if (Utils.logCollector != null)
|
default:
|
||||||
Utils.logCollector.appendException(e, LogCollector.LogFile.UTILS, "checkExistence",
|
|
||||||
new Pair<>("isSlider", isSlider),
|
|
||||||
new Pair<>("model", model));
|
|
||||||
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
|
|
||||||
}
|
}
|
||||||
|
return checkList;
|
||||||
model.setDownloaded(exists);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void showDownloadDialog(@NonNull Context context,
|
public static void showDownloadDialog(@NonNull Context context,
|
||||||
@ -253,6 +235,19 @@ public final class DownloadUtils {
|
|||||||
DownloadUtils.download(context, feedModel);
|
DownloadUtils.download(context, feedModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void download(@NonNull final Context context,
|
||||||
|
@NonNull final StoryModel storyModel) {
|
||||||
|
final File downloadDir = getDownloadDir(context, "@" + storyModel.getUsername());
|
||||||
|
final String url = storyModel.getItemType() == MediaItemType.MEDIA_TYPE_VIDEO
|
||||||
|
? storyModel.getVideoUrl()
|
||||||
|
: storyModel.getStoryUrl();
|
||||||
|
final File saveFile = new File(downloadDir,
|
||||||
|
storyModel.getStoryMediaId()
|
||||||
|
+ "_" + storyModel.getTimestamp()
|
||||||
|
+ DownloadUtils.getFileExtensionFromUrl(url));
|
||||||
|
download(context, url, saveFile.getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
public static void download(@NonNull final Context context,
|
public static void download(@NonNull final Context context,
|
||||||
@NonNull final FeedModel feedModel) {
|
@NonNull final FeedModel feedModel) {
|
||||||
download(context, feedModel, -1);
|
download(context, feedModel, -1);
|
||||||
|
@ -244,7 +244,6 @@ public class ProfileService extends BaseService {
|
|||||||
}
|
}
|
||||||
final FeedModel feedModel = builder.build();
|
final FeedModel feedModel = builder.build();
|
||||||
feedModels.add(feedModel);
|
feedModels.add(feedModel);
|
||||||
// DownloadUtils.checkExistence(downloadDir, customDir, isSlider, model);
|
|
||||||
}
|
}
|
||||||
return new PostsFetchResponse(feedModels, hasNextPage, endCursor);
|
return new PostsFetchResponse(feedModels, hasNextPage, endCursor);
|
||||||
}
|
}
|
||||||
|
@ -59,8 +59,8 @@ import static awais.instagrabber.utils.Utils.logCollector;
|
|||||||
|
|
||||||
public class DownloadWorker extends Worker {
|
public class DownloadWorker extends Worker {
|
||||||
private static final String TAG = "DownloadWorker";
|
private static final String TAG = "DownloadWorker";
|
||||||
private static final String PROGRESS = "PROGRESS";
|
public static final String PROGRESS = "PROGRESS";
|
||||||
private static final String URL = "URL";
|
public static final String URL = "URL";
|
||||||
private static final String DOWNLOAD_GROUP = "DOWNLOAD_GROUP";
|
private static final String DOWNLOAD_GROUP = "DOWNLOAD_GROUP";
|
||||||
|
|
||||||
public static final String KEY_DOWNLOAD_REQUEST_JSON = "download_request_json";
|
public static final String KEY_DOWNLOAD_REQUEST_JSON = "download_request_json";
|
||||||
@ -167,6 +167,9 @@ public class DownloadWorker extends Worker {
|
|||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
Log.e(TAG, "Error while downloading: " + url, e);
|
Log.e(TAG, "Error while downloading: " + url, e);
|
||||||
}
|
}
|
||||||
|
setProgressAsync(new Data.Builder().putString(URL, url)
|
||||||
|
.putFloat(PROGRESS, 100)
|
||||||
|
.build());
|
||||||
updateDownloadProgress(notificationId, position, total, 100);
|
updateDownloadProgress(notificationId, position, total, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
10
app/src/main/res/drawable/ic_download_circle_24.xml
Normal file
10
app/src/main/res/drawable/ic_download_circle_24.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<!-- drawable/download_circle.xml -->
|
||||||
|
<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="#000"
|
||||||
|
android:pathData="M12 2C17.5 2 22 6.5 22 12C22 17.5 17.5 22 12 22C6.5 22 2 17.5 2 12C2 6.5 6.5 2 12 2M8 17H16V15H8V17M16 10H13.5V6H10.5V10H8L12 14L16 10Z" />
|
||||||
|
</vector>
|
@ -66,15 +66,15 @@
|
|||||||
tools:text="Full name Full name Full name Full name Full name Full name Full name " />
|
tools:text="Full name Full name Full name Full name Full name Full name Full name " />
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatImageView
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
android:id="@+id/isDownloaded"
|
android:id="@+id/downloaded"
|
||||||
android:layout_width="24dp"
|
android:layout_width="24dp"
|
||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
android:layout_margin="8dp"
|
android:layout_margin="8dp"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:srcCompat="@drawable/ic_cloud_download_24"
|
app:srcCompat="@drawable/ic_download_circle_24"
|
||||||
app:tint="@color/green_400"
|
app:tint="@color/green_A400"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatImageView
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
@ -94,7 +94,7 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="@color/black_a50"
|
android:background="@color/black_a50"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:visibility="visible">
|
tools:visibility="gone">
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatImageView
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
android:layout_width="28dp"
|
android:layout_width="28dp"
|
||||||
|
@ -77,9 +77,20 @@
|
|||||||
<color name="brown_800">#4E342E</color>
|
<color name="brown_800">#4E342E</color>
|
||||||
<color name="brown_900">#3E2723</color>
|
<color name="brown_900">#3E2723</color>
|
||||||
|
|
||||||
<color name="green_200">#03dac6</color>
|
<color name="green_50">#E8F5E9</color>
|
||||||
|
<color name="green_100">#C8E6C9</color>
|
||||||
|
<color name="green_200">#A5D6A7</color>
|
||||||
|
<color name="green_300">#81C784</color>
|
||||||
<color name="green_400">#66BB6A</color>
|
<color name="green_400">#66BB6A</color>
|
||||||
<color name="green_500">#018786</color>
|
<color name="green_500">#4CAF50</color>
|
||||||
|
<color name="green_600">#43A047</color>
|
||||||
|
<color name="green_700">#388E3C</color>
|
||||||
|
<color name="green_800">#2E7D32</color>
|
||||||
|
<color name="green_900">#1B5E20</color>
|
||||||
|
<color name="green_A100">#B9F6CA</color>
|
||||||
|
<color name="green_A200">#69F0AE</color>
|
||||||
|
<color name="green_A400">#00E676</color>
|
||||||
|
<color name="green_A700">#00C853</color>
|
||||||
|
|
||||||
<color name="purple_200">#bb86fc</color>
|
<color name="purple_200">#bb86fc</color>
|
||||||
<color name="purple_600">#4b01d0</color>
|
<color name="purple_600">#4b01d0</color>
|
||||||
|
Loading…
Reference in New Issue
Block a user