diff --git a/app/build.gradle b/app/build.gradle index caf24a84..ee797097 100755 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,4 +1,5 @@ apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' apply plugin: "androidx.navigation.safeargs" apply from: 'sentry.gradle' diff --git a/app/src/main/java/awais/instagrabber/activities/MainActivity.java b/app/src/main/java/awais/instagrabber/activities/MainActivity.java index 00935c2f..c081b005 100644 --- a/app/src/main/java/awais/instagrabber/activities/MainActivity.java +++ b/app/src/main/java/awais/instagrabber/activities/MainActivity.java @@ -183,7 +183,7 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage } getSupportFragmentManager().addOnBackStackChangedListener(this); // Initialise the internal map - AppExecutors.getInstance().tasksThread().execute(() -> { + AppExecutors.INSTANCE.getTasksThread().execute(() -> { EmojiParser.setup(this); EmojiVariantManager.getInstance(); }); diff --git a/app/src/main/java/awais/instagrabber/adapters/FeedStoriesAdapter.java b/app/src/main/java/awais/instagrabber/adapters/FeedStoriesAdapter.java index 39c9e836..05966afd 100755 --- a/app/src/main/java/awais/instagrabber/adapters/FeedStoriesAdapter.java +++ b/app/src/main/java/awais/instagrabber/adapters/FeedStoriesAdapter.java @@ -4,19 +4,12 @@ import android.view.LayoutInflater; import android.view.ViewGroup; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import androidx.recyclerview.widget.DiffUtil; import androidx.recyclerview.widget.ListAdapter; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - import awais.instagrabber.adapters.viewholder.FeedStoryViewHolder; import awais.instagrabber.databinding.ItemHighlightBinding; import awais.instagrabber.models.FeedStoryModel; -import awais.instagrabber.utils.Constants; -import awais.instagrabber.utils.Utils; public final class FeedStoriesAdapter extends ListAdapter { private final OnFeedStoryClickListener listener; @@ -29,7 +22,7 @@ public final class FeedStoriesAdapter extends ListAdapter item, final boolean isSelected) { @@ -55,13 +55,13 @@ public class FilterViewHolder extends RecyclerView.ViewHolder { final Bitmap bitmap = BitmapUtils.getBitmapFromMemCache(filterKey); if (bitmap == null) { final GPUImageFilter filter = item.getInstance(); - appExecutors.tasksThread().submit(() -> { + appExecutors.getTasksThread().submit(() -> { GPUImage.getBitmapForMultipleFilters( originalBitmap, ImmutableList.builder().add(filter).addAll(tuneFilters).build(), filteredBitmap -> { BitmapUtils.addBitmapToMemoryCache(filterKey, filteredBitmap, true); - appExecutors.mainThread().execute(() -> binding.getRoot().post(() -> binding.preview.setImageBitmap(filteredBitmap))); + appExecutors.getMainThread().execute(() -> binding.getRoot().post(() -> binding.preview.setImageBitmap(filteredBitmap))); } ); }); diff --git a/app/src/main/java/awais/instagrabber/customviews/Tooltip.java b/app/src/main/java/awais/instagrabber/customviews/Tooltip.java index 42bbbb6e..5cde235b 100644 --- a/app/src/main/java/awais/instagrabber/customviews/Tooltip.java +++ b/app/src/main/java/awais/instagrabber/customviews/Tooltip.java @@ -22,7 +22,7 @@ public class Tooltip extends AppCompatTextView { private ViewPropertyAnimator animator; private boolean showing; - private final AppExecutors appExecutors = AppExecutors.getInstance(); + private final AppExecutors appExecutors = AppExecutors.INSTANCE; private final Runnable dismissRunnable = () -> { animator = animate().alpha(0).setListener(new AnimatorListenerAdapter() { @Override @@ -86,8 +86,8 @@ public class Tooltip extends AppCompatTextView { updateTooltipPosition(); showing = true; - appExecutors.mainThread().cancel(dismissRunnable); - appExecutors.mainThread().execute(dismissRunnable, 2000); + appExecutors.getMainThread().cancel(dismissRunnable); + appExecutors.getMainThread().execute(dismissRunnable, 2000); if (animator != null) { animator.setListener(null); animator.cancel(); @@ -109,7 +109,7 @@ public class Tooltip extends AppCompatTextView { animator = null; } - appExecutors.mainThread().cancel(dismissRunnable); + appExecutors.getMainThread().cancel(dismissRunnable); dismissRunnable.run(); } showing = false; diff --git a/app/src/main/java/awais/instagrabber/customviews/emoji/EmojiGridAdapter.java b/app/src/main/java/awais/instagrabber/customviews/emoji/EmojiGridAdapter.java index 1f0a7c7f..2dc2274e 100644 --- a/app/src/main/java/awais/instagrabber/customviews/emoji/EmojiGridAdapter.java +++ b/app/src/main/java/awais/instagrabber/customviews/emoji/EmojiGridAdapter.java @@ -53,7 +53,7 @@ public class EmojiGridAdapter extends RecyclerView.Adapter categoryMap = emojiParser.getCategoryMap(); emojiVariantManager = EmojiVariantManager.getInstance(); - appExecutors = AppExecutors.getInstance(); + appExecutors = AppExecutors.INSTANCE; setHasStableIds(true); if (emojiCategoryType == null) { // show all if type is null @@ -81,13 +81,13 @@ public class EmojiGridAdapter extends RecyclerView.Adapter { + appExecutors.getTasksThread().execute(() -> { final Optional first = emoji.getVariants() .stream() .filter(e -> e.getUnicode().equals(variant)) .findFirst(); if (!first.isPresent()) return; - appExecutors.mainThread().execute(() -> holder.bind(position, first.get(), emoji)); + appExecutors.getMainThread().execute(() -> holder.bind(position, first.get(), emoji)); }); return; } diff --git a/app/src/main/java/awais/instagrabber/customviews/emoji/EmojiVariantManager.java b/app/src/main/java/awais/instagrabber/customviews/emoji/EmojiVariantManager.java index 95eb3330..28a39d26 100644 --- a/app/src/main/java/awais/instagrabber/customviews/emoji/EmojiVariantManager.java +++ b/app/src/main/java/awais/instagrabber/customviews/emoji/EmojiVariantManager.java @@ -21,7 +21,7 @@ public class EmojiVariantManager { private static final String TAG = EmojiVariantManager.class.getSimpleName(); private static final Object LOCK = new Object(); - private final AppExecutors appExecutors = AppExecutors.getInstance(); + private final AppExecutors appExecutors = AppExecutors.INSTANCE; private final Map selectedVariantMap = new HashMap<>(); private static EmojiVariantManager instance; @@ -57,7 +57,7 @@ public class EmojiVariantManager { public void setVariant(final String parent, final String variant) { if (parent == null || variant == null) return; selectedVariantMap.put(parent, variant); - appExecutors.tasksThread().execute(() -> { + appExecutors.getTasksThread().execute(() -> { final JSONObject jsonObject = new JSONObject(selectedVariantMap); final String json = jsonObject.toString(); Utils.settingsHelper.putString(PREF_EMOJI_VARIANTS, json); diff --git a/app/src/main/java/awais/instagrabber/customviews/emoji/EmojiVariantPopup.java b/app/src/main/java/awais/instagrabber/customviews/emoji/EmojiVariantPopup.java index b0de3b6c..0d186256 100644 --- a/app/src/main/java/awais/instagrabber/customviews/emoji/EmojiVariantPopup.java +++ b/app/src/main/java/awais/instagrabber/customviews/emoji/EmojiVariantPopup.java @@ -57,7 +57,7 @@ public final class EmojiVariantPopup { this.rootView = rootView; this.listener = listener; emojiVariantManager = EmojiVariantManager.getInstance(); - appExecutors = AppExecutors.getInstance(); + appExecutors = AppExecutors.INSTANCE; } public void show(@NonNull final View view, @NonNull final Emoji emoji) { diff --git a/app/src/main/java/awais/instagrabber/customviews/emoji/ReactionsManager.java b/app/src/main/java/awais/instagrabber/customviews/emoji/ReactionsManager.java index 0e812528..7e08f1aa 100644 --- a/app/src/main/java/awais/instagrabber/customviews/emoji/ReactionsManager.java +++ b/app/src/main/java/awais/instagrabber/customviews/emoji/ReactionsManager.java @@ -11,7 +11,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; -import awais.instagrabber.utils.AppExecutors; import awais.instagrabber.utils.TextUtils; import awais.instagrabber.utils.Utils; import awais.instagrabber.utils.emoji.EmojiParser; @@ -22,7 +21,7 @@ public class ReactionsManager { private static final String TAG = ReactionsManager.class.getSimpleName(); private static final Object LOCK = new Object(); - private final AppExecutors appExecutors = AppExecutors.getInstance(); + // private final AppExecutors appExecutors = AppExecutors.INSTANCE; private final List reactions = new ArrayList<>(); private static ReactionsManager instance; diff --git a/app/src/main/java/awais/instagrabber/db/repositories/AccountRepository.java b/app/src/main/java/awais/instagrabber/db/repositories/AccountRepository.java index 1079712c..0dc1031c 100644 --- a/app/src/main/java/awais/instagrabber/db/repositories/AccountRepository.java +++ b/app/src/main/java/awais/instagrabber/db/repositories/AccountRepository.java @@ -23,7 +23,7 @@ public class AccountRepository { public static AccountRepository getInstance(final AccountDataSource accountDataSource) { if (instance == null) { - instance = new AccountRepository(AppExecutors.getInstance(), accountDataSource); + instance = new AccountRepository(AppExecutors.INSTANCE, accountDataSource); } return instance; } @@ -31,10 +31,10 @@ public class AccountRepository { public void getAccount(final long uid, final RepositoryCallback callback) { // request on the I/O thread - appExecutors.diskIO().execute(() -> { + appExecutors.getDiskIO().execute(() -> { final Account account = accountDataSource.getAccount(String.valueOf(uid)); // notify on the main thread - appExecutors.mainThread().execute(() -> { + appExecutors.getMainThread().execute(() -> { if (callback == null) return; if (account == null) { callback.onDataNotAvailable(); @@ -47,10 +47,10 @@ public class AccountRepository { public void getAllAccounts(final RepositoryCallback> callback) { // request on the I/O thread - appExecutors.diskIO().execute(() -> { + appExecutors.getDiskIO().execute(() -> { final List accounts = accountDataSource.getAllAccounts(); // notify on the main thread - appExecutors.mainThread().execute(() -> { + appExecutors.getMainThread().execute(() -> { if (callback == null) return; if (accounts == null) { callback.onDataNotAvailable(); @@ -65,7 +65,7 @@ public class AccountRepository { public void insertOrUpdateAccounts(final List accounts, final RepositoryCallback callback) { // request on the I/O thread - appExecutors.diskIO().execute(() -> { + appExecutors.getDiskIO().execute(() -> { for (final Account account : accounts) { accountDataSource.insertOrUpdateAccount(account.getUid(), account.getUsername(), @@ -74,7 +74,7 @@ public class AccountRepository { account.getProfilePic()); } // notify on the main thread - appExecutors.mainThread().execute(() -> { + appExecutors.getMainThread().execute(() -> { if (callback == null) return; callback.onSuccess(null); }); @@ -88,11 +88,11 @@ public class AccountRepository { final String profilePicUrl, final RepositoryCallback callback) { // request on the I/O thread - appExecutors.diskIO().execute(() -> { + appExecutors.getDiskIO().execute(() -> { accountDataSource.insertOrUpdateAccount(String.valueOf(uid), username, cookie, fullName, profilePicUrl); final Account updated = accountDataSource.getAccount(String.valueOf(uid)); // notify on the main thread - appExecutors.mainThread().execute(() -> { + appExecutors.getMainThread().execute(() -> { if (callback == null) return; if (updated == null) { callback.onDataNotAvailable(); @@ -106,10 +106,10 @@ public class AccountRepository { public void deleteAccount(final Account account, final RepositoryCallback callback) { // request on the I/O thread - appExecutors.diskIO().execute(() -> { + appExecutors.getDiskIO().execute(() -> { accountDataSource.deleteAccount(account); // notify on the main thread - appExecutors.mainThread().execute(() -> { + appExecutors.getMainThread().execute(() -> { if (callback == null) return; callback.onSuccess(null); }); @@ -118,10 +118,10 @@ public class AccountRepository { public void deleteAllAccounts(final RepositoryCallback callback) { // request on the I/O thread - appExecutors.diskIO().execute(() -> { + appExecutors.getDiskIO().execute(() -> { accountDataSource.deleteAllAccounts(); // notify on the main thread - appExecutors.mainThread().execute(() -> { + appExecutors.getMainThread().execute(() -> { if (callback == null) return; callback.onSuccess(null); }); diff --git a/app/src/main/java/awais/instagrabber/db/repositories/DMLastNotifiedRepository.java b/app/src/main/java/awais/instagrabber/db/repositories/DMLastNotifiedRepository.java index 9cb15291..07334503 100644 --- a/app/src/main/java/awais/instagrabber/db/repositories/DMLastNotifiedRepository.java +++ b/app/src/main/java/awais/instagrabber/db/repositories/DMLastNotifiedRepository.java @@ -22,7 +22,7 @@ public class DMLastNotifiedRepository { public static DMLastNotifiedRepository getInstance(final DMLastNotifiedDataSource dmLastNotifiedDataSource) { if (instance == null) { - instance = new DMLastNotifiedRepository(AppExecutors.getInstance(), dmLastNotifiedDataSource); + instance = new DMLastNotifiedRepository(AppExecutors.INSTANCE, dmLastNotifiedDataSource); } return instance; } @@ -30,10 +30,10 @@ public class DMLastNotifiedRepository { public void getDMLastNotified(final String threadId, final RepositoryCallback callback) { // request on the I/O thread - appExecutors.diskIO().execute(() -> { + appExecutors.getDiskIO().execute(() -> { final DMLastNotified dmLastNotified = dmLastNotifiedDataSource.getDMLastNotified(threadId); // notify on the main thread - appExecutors.mainThread().execute(() -> { + appExecutors.getMainThread().execute(() -> { if (callback == null) return; if (dmLastNotified == null) { callback.onDataNotAvailable(); @@ -46,10 +46,10 @@ public class DMLastNotifiedRepository { public void getAllDMDmLastNotified(final RepositoryCallback> callback) { // request on the I/O thread - appExecutors.diskIO().execute(() -> { + appExecutors.getDiskIO().execute(() -> { final List allDMDmLastNotified = dmLastNotifiedDataSource.getAllDMDmLastNotified(); // notify on the main thread - appExecutors.mainThread().execute(() -> { + appExecutors.getMainThread().execute(() -> { if (callback == null) return; if (allDMDmLastNotified == null) { callback.onDataNotAvailable(); @@ -64,14 +64,14 @@ public class DMLastNotifiedRepository { public void insertOrUpdateDMLastNotified(final List dmLastNotifiedList, final RepositoryCallback callback) { // request on the I/O thread - appExecutors.diskIO().execute(() -> { + appExecutors.getDiskIO().execute(() -> { for (final DMLastNotified dmLastNotified : dmLastNotifiedList) { dmLastNotifiedDataSource.insertOrUpdateDMLastNotified(dmLastNotified.getThreadId(), dmLastNotified.getLastNotifiedMsgTs(), dmLastNotified.getLastNotifiedAt()); } // notify on the main thread - appExecutors.mainThread().execute(() -> { + appExecutors.getMainThread().execute(() -> { if (callback == null) return; callback.onSuccess(null); }); @@ -83,11 +83,11 @@ public class DMLastNotifiedRepository { final LocalDateTime lastNotifiedAt, final RepositoryCallback callback) { // request on the I/O thread - appExecutors.diskIO().execute(() -> { + appExecutors.getDiskIO().execute(() -> { dmLastNotifiedDataSource.insertOrUpdateDMLastNotified(threadId, lastNotifiedMsgTs, lastNotifiedAt); final DMLastNotified updated = dmLastNotifiedDataSource.getDMLastNotified(threadId); // notify on the main thread - appExecutors.mainThread().execute(() -> { + appExecutors.getMainThread().execute(() -> { if (callback == null) return; if (updated == null) { callback.onDataNotAvailable(); @@ -101,10 +101,10 @@ public class DMLastNotifiedRepository { public void deleteDMLastNotified(final DMLastNotified dmLastNotified, final RepositoryCallback callback) { // request on the I/O thread - appExecutors.diskIO().execute(() -> { + appExecutors.getDiskIO().execute(() -> { dmLastNotifiedDataSource.deleteDMLastNotified(dmLastNotified); // notify on the main thread - appExecutors.mainThread().execute(() -> { + appExecutors.getMainThread().execute(() -> { if (callback == null) return; callback.onSuccess(null); }); @@ -113,10 +113,10 @@ public class DMLastNotifiedRepository { public void deleteAllDMLastNotified(final RepositoryCallback callback) { // request on the I/O thread - appExecutors.diskIO().execute(() -> { + appExecutors.getDiskIO().execute(() -> { dmLastNotifiedDataSource.deleteAllDMLastNotified(); // notify on the main thread - appExecutors.mainThread().execute(() -> { + appExecutors.getMainThread().execute(() -> { if (callback == null) return; callback.onSuccess(null); }); diff --git a/app/src/main/java/awais/instagrabber/db/repositories/FavoriteRepository.java b/app/src/main/java/awais/instagrabber/db/repositories/FavoriteRepository.java index 926692f7..eb130e22 100644 --- a/app/src/main/java/awais/instagrabber/db/repositories/FavoriteRepository.java +++ b/app/src/main/java/awais/instagrabber/db/repositories/FavoriteRepository.java @@ -22,17 +22,17 @@ public class FavoriteRepository { public static FavoriteRepository getInstance(final FavoriteDataSource favoriteDataSource) { if (instance == null) { - instance = new FavoriteRepository(AppExecutors.getInstance(), favoriteDataSource); + instance = new FavoriteRepository(AppExecutors.INSTANCE, favoriteDataSource); } return instance; } public void getFavorite(final String query, final FavoriteType type, final RepositoryCallback callback) { // request on the I/O thread - appExecutors.diskIO().execute(() -> { + appExecutors.getDiskIO().execute(() -> { final Favorite favorite = favoriteDataSource.getFavorite(query, type); // notify on the main thread - appExecutors.mainThread().execute(() -> { + appExecutors.getMainThread().execute(() -> { if (callback == null) return; if (favorite == null) { callback.onDataNotAvailable(); @@ -45,10 +45,10 @@ public class FavoriteRepository { public void getAllFavorites(final RepositoryCallback> callback) { // request on the I/O thread - appExecutors.diskIO().execute(() -> { + appExecutors.getDiskIO().execute(() -> { final List favorites = favoriteDataSource.getAllFavorites(); // notify on the main thread - appExecutors.mainThread().execute(() -> { + appExecutors.getMainThread().execute(() -> { if (callback == null) return; if (favorites == null) { callback.onDataNotAvailable(); @@ -62,10 +62,10 @@ public class FavoriteRepository { public void insertOrUpdateFavorite(final Favorite favorite, final RepositoryCallback callback) { // request on the I/O thread - appExecutors.diskIO().execute(() -> { + appExecutors.getDiskIO().execute(() -> { favoriteDataSource.insertOrUpdateFavorite(favorite); // notify on the main thread - appExecutors.mainThread().execute(() -> { + appExecutors.getMainThread().execute(() -> { if (callback == null) return; callback.onSuccess(null); }); @@ -76,10 +76,10 @@ public class FavoriteRepository { final FavoriteType type, final RepositoryCallback callback) { // request on the I/O thread - appExecutors.diskIO().execute(() -> { + appExecutors.getDiskIO().execute(() -> { favoriteDataSource.deleteFavorite(query, type); // notify on the main thread - appExecutors.mainThread().execute(() -> { + appExecutors.getMainThread().execute(() -> { if (callback == null) return; callback.onSuccess(null); }); diff --git a/app/src/main/java/awais/instagrabber/db/repositories/RecentSearchRepository.java b/app/src/main/java/awais/instagrabber/db/repositories/RecentSearchRepository.java index 0832a109..1ee00613 100644 --- a/app/src/main/java/awais/instagrabber/db/repositories/RecentSearchRepository.java +++ b/app/src/main/java/awais/instagrabber/db/repositories/RecentSearchRepository.java @@ -25,7 +25,7 @@ public class RecentSearchRepository { public static RecentSearchRepository getInstance(final RecentSearchDataSource recentSearchDataSource) { if (instance == null) { - instance = new RecentSearchRepository(AppExecutors.getInstance(), recentSearchDataSource); + instance = new RecentSearchRepository(AppExecutors.INSTANCE, recentSearchDataSource); } return instance; } @@ -34,10 +34,10 @@ public class RecentSearchRepository { @NonNull final FavoriteType type, final RepositoryCallback callback) { // request on the I/O thread - appExecutors.diskIO().execute(() -> { + appExecutors.getDiskIO().execute(() -> { final RecentSearch recentSearch = recentSearchDataSource.getRecentSearchByIgIdAndType(igId, type); // notify on the main thread - appExecutors.mainThread().execute(() -> { + appExecutors.getMainThread().execute(() -> { if (callback == null) return; if (recentSearch == null) { callback.onDataNotAvailable(); @@ -50,10 +50,10 @@ public class RecentSearchRepository { public void getAllRecentSearches(final RepositoryCallback> callback) { // request on the I/O thread - appExecutors.diskIO().execute(() -> { + appExecutors.getDiskIO().execute(() -> { final List recentSearches = recentSearchDataSource.getAllRecentSearches(); // notify on the main thread - appExecutors.mainThread().execute(() -> { + appExecutors.getMainThread().execute(() -> { if (callback == null) return; callback.onSuccess(recentSearches); }); @@ -73,14 +73,14 @@ public class RecentSearchRepository { @NonNull final FavoriteType type, final RepositoryCallback callback) { // request on the I/O thread - appExecutors.diskIO().execute(() -> { + appExecutors.getDiskIO().execute(() -> { RecentSearch recentSearch = recentSearchDataSource.getRecentSearchByIgIdAndType(igId, type); recentSearch = recentSearch == null ? new RecentSearch(igId, name, username, picUrl, type, LocalDateTime.now()) : new RecentSearch(recentSearch.getId(), igId, name, username, picUrl, type, LocalDateTime.now()); recentSearchDataSource.insertOrUpdateRecentSearch(recentSearch); // notify on the main thread - appExecutors.mainThread().execute(() -> { + appExecutors.getMainThread().execute(() -> { if (callback == null) return; callback.onSuccess(null); }); @@ -91,13 +91,13 @@ public class RecentSearchRepository { @NonNull final FavoriteType type, final RepositoryCallback callback) { // request on the I/O thread - appExecutors.diskIO().execute(() -> { + appExecutors.getDiskIO().execute(() -> { final RecentSearch recentSearch = recentSearchDataSource.getRecentSearchByIgIdAndType(igId, type); if (recentSearch != null) { recentSearchDataSource.deleteRecentSearch(recentSearch); } // notify on the main thread - appExecutors.mainThread().execute(() -> { + appExecutors.getMainThread().execute(() -> { if (callback == null) return; if (recentSearch == null) { callback.onDataNotAvailable(); @@ -111,11 +111,11 @@ public class RecentSearchRepository { public void deleteRecentSearch(@NonNull final RecentSearch recentSearch, final RepositoryCallback callback) { // request on the I/O thread - appExecutors.diskIO().execute(() -> { + appExecutors.getDiskIO().execute(() -> { recentSearchDataSource.deleteRecentSearch(recentSearch); // notify on the main thread - appExecutors.mainThread().execute(() -> { + appExecutors.getMainThread().execute(() -> { if (callback == null) return; callback.onSuccess(null); }); diff --git a/app/src/main/java/awais/instagrabber/dialogs/AccountSwitcherDialogFragment.java b/app/src/main/java/awais/instagrabber/dialogs/AccountSwitcherDialogFragment.java index e551c66c..25251c84 100644 --- a/app/src/main/java/awais/instagrabber/dialogs/AccountSwitcherDialogFragment.java +++ b/app/src/main/java/awais/instagrabber/dialogs/AccountSwitcherDialogFragment.java @@ -59,7 +59,7 @@ public class AccountSwitcherDialogFragment extends DialogFragment { // final FragmentActivity activity = getActivity(); // if (activity != null) activity.recreate(); // dismiss(); - AppExecutors.getInstance().mainThread().execute(() -> { + AppExecutors.INSTANCE.getMainThread().execute(() -> { final Context context = getContext(); if (context == null) return; ProcessPhoenix.triggerRebirth(context); diff --git a/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageThreadFragment.java b/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageThreadFragment.java index fe4343e7..28068735 100644 --- a/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageThreadFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageThreadFragment.java @@ -174,7 +174,7 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact private boolean hasKbOpenedOnce; private boolean wasToggled; - private final AppExecutors appExecutors = AppExecutors.getInstance(); + private final AppExecutors appExecutors = AppExecutors.INSTANCE; private final Animatable2Compat.AnimationCallback micToSendAnimationCallback = new Animatable2Compat.AnimationCallback() { @Override public void onAnimationEnd(final Drawable drawable) { @@ -545,7 +545,7 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact @SuppressLint("UnsafeOptInUsageError") private void cleanup() { if (prevTitleRunnable != null) { - appExecutors.mainThread().cancel(prevTitleRunnable); + appExecutors.getMainThread().cancel(prevTitleRunnable); } for (int childCount = binding.chats.getChildCount(), i = 0; i < childCount; ++i) { final RecyclerView.ViewHolder holder = binding.chats.getChildViewHolder(binding.chats.getChildAt(i)); @@ -1379,11 +1379,11 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact private void setTitle(final String title) { if (actionBar == null) return; if (prevTitleRunnable != null) { - appExecutors.mainThread().cancel(prevTitleRunnable); + appExecutors.getMainThread().cancel(prevTitleRunnable); } prevTitleRunnable = () -> actionBar.setTitle(title); // set title delayed to avoid title blink if fetch is fast - appExecutors.mainThread().execute(prevTitleRunnable, 1000); + appExecutors.getMainThread().execute(prevTitleRunnable, 1000); } private void downloadItem(final DirectItem item) { diff --git a/app/src/main/java/awais/instagrabber/fragments/imageedit/FiltersFragment.java b/app/src/main/java/awais/instagrabber/fragments/imageedit/FiltersFragment.java index 8ee8a1af..6cd0de96 100644 --- a/app/src/main/java/awais/instagrabber/fragments/imageedit/FiltersFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/imageedit/FiltersFragment.java @@ -116,7 +116,7 @@ public class FiltersFragment extends Fragment { @Override public void onCreate(@Nullable final Bundle savedInstanceState) { super.onCreate(savedInstanceState); - appExecutors = AppExecutors.getInstance(); + appExecutors = AppExecutors.INSTANCE; viewModel = new ViewModelProvider(this).get(FiltersFragmentViewModel.class); } @@ -194,7 +194,7 @@ public class FiltersFragment extends Fragment { final Context context = getContext(); if (context == null) return; binding.preview.setScaleType(GPUImage.ScaleType.CENTER_INSIDE); - appExecutors.tasksThread().execute(() -> { + appExecutors.getTasksThread().execute(() -> { binding.preview.setImage(sourceUri); setPreviewBounds(); }); @@ -230,7 +230,7 @@ public class FiltersFragment extends Fragment { binding.apply.setOnClickListener(v -> { if (callback == null) return; final List> appliedTunings = getAppliedTunings(); - appExecutors.tasksThread().submit(() -> { + appExecutors.getTasksThread().submit(() -> { final Bitmap bitmap = binding.preview.getGPUImage().getBitmapWithFilterApplied(); try { BitmapUtils.convertToJpegAndSaveToUri(context, bitmap, destUri); @@ -287,7 +287,7 @@ public class FiltersFragment extends Fragment { inputStream = context.getContentResolver().openInputStream(sourceUri); BitmapFactory.decodeStream(inputStream, null, options); final float ratio = (float) options.outWidth / options.outHeight; - appExecutors.mainThread().execute(() -> { + appExecutors.getMainThread().execute(() -> { final ViewGroup.LayoutParams previewLayoutParams = binding.preview.getLayoutParams(); if (options.outHeight > options.outWidth) { previewLayoutParams.width = (int) (binding.preview.getHeight() * ratio); @@ -472,7 +472,7 @@ public class FiltersFragment extends Fragment { bitmap, onFilterClickListener ); - appExecutors.mainThread().execute(() -> { + appExecutors.getMainThread().execute(() -> { binding.filters.setAdapter(filtersAdapter); filtersAdapter.submitList(FiltersHelper.getFilters(), () -> { if (appliedFilter == null) return; diff --git a/app/src/main/java/awais/instagrabber/fragments/imageedit/ImageEditFragment.java b/app/src/main/java/awais/instagrabber/fragments/imageedit/ImageEditFragment.java index 4a2c4881..7586bdce 100644 --- a/app/src/main/java/awais/instagrabber/fragments/imageedit/ImageEditFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/imageedit/ImageEditFragment.java @@ -183,7 +183,7 @@ public class ImageEditFragment extends Fragment { if (context == null) return; final Uri resultUri = viewModel.getResultUri().getValue(); if (resultUri == null) return; - Utils.mediaScanFile(context, new File(resultUri.toString()), (path, uri) -> AppExecutors.getInstance().mainThread().execute(() -> { + Utils.mediaScanFile(context, new File(resultUri.toString()), (path, uri) -> AppExecutors.INSTANCE.getMainThread().execute(() -> { final NavController navController = NavHostFragment.findNavController(this); setNavControllerResult(navController, resultUri); navController.navigateUp(); diff --git a/app/src/main/java/awais/instagrabber/fragments/settings/MorePreferencesFragment.java b/app/src/main/java/awais/instagrabber/fragments/settings/MorePreferencesFragment.java index e610fe56..dc8861db 100644 --- a/app/src/main/java/awais/instagrabber/fragments/settings/MorePreferencesFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/settings/MorePreferencesFragment.java @@ -94,7 +94,7 @@ public class MorePreferencesFragment extends BasePreferencesFragment { // shouldRecreate(); Toast.makeText(context1, R.string.logout_success, Toast.LENGTH_SHORT).show(); settingsHelper.putString(Constants.COOKIE, ""); - AppExecutors.getInstance().mainThread().execute(() -> ProcessPhoenix.triggerRebirth(context1), 200); + AppExecutors.INSTANCE.getMainThread().execute(() -> ProcessPhoenix.triggerRebirth(context1), 200); return true; })); } @@ -139,8 +139,7 @@ public class MorePreferencesFragment extends BasePreferencesFragment { if (context1 == null) return; Toast.makeText(context1, R.string.logout_success, Toast.LENGTH_SHORT).show(); settingsHelper.putString(Constants.COOKIE, ""); - AppExecutors.getInstance().mainThread() - .execute(() -> ProcessPhoenix.triggerRebirth(context1), 200); + AppExecutors.INSTANCE.getMainThread().execute(() -> ProcessPhoenix.triggerRebirth(context1), 200); } @Override @@ -307,7 +306,7 @@ public class MorePreferencesFragment extends BasePreferencesFragment { // final FragmentActivity activity = getActivity(); // if (activity == null) return; // activity.recreate(); - AppExecutors.getInstance().mainThread().execute(() -> { + AppExecutors.INSTANCE.getMainThread().execute(() -> { final Context context = getContext(); if (context == null) return; ProcessPhoenix.triggerRebirth(context); diff --git a/app/src/main/java/awais/instagrabber/models/Comment.java b/app/src/main/java/awais/instagrabber/models/Comment.java deleted file mode 100644 index d8ff3cb5..00000000 --- a/app/src/main/java/awais/instagrabber/models/Comment.java +++ /dev/null @@ -1,117 +0,0 @@ -package awais.instagrabber.models; - -import androidx.annotation.NonNull; - -import java.io.Serializable; -import java.util.Date; -import java.util.Objects; - -import awais.instagrabber.repositories.responses.User; -import awais.instagrabber.utils.Utils; - -public class Comment implements Serializable, Cloneable { - private final User user; - private final String id; - private final String text; - private long likes; - private final long timestamp; - private boolean liked; - private final int replyCount; - private final boolean isChild; - - public Comment(final String id, - final String text, - final long timestamp, - final long likes, - final boolean liked, - final User user, - final int replyCount, final boolean isChild) { - this.id = id; - this.text = text; - this.likes = likes; - this.liked = liked; - this.timestamp = timestamp; - this.user = user; - this.replyCount = replyCount; - this.isChild = isChild; - } - - public String getId() { - return id; - } - - public String getText() { - return text; - } - - @NonNull - public String getDateTime() { - return Utils.datetimeParser.format(new Date(timestamp * 1000L)); - } - - public long getLikes() { - return likes; - } - - public boolean getLiked() { - return liked; - } - - public void setLiked(boolean liked) { - this.likes = liked ? likes + 1 : likes - 1; - this.liked = liked; - } - - public User getUser() { - return user; - } - - public int getReplyCount() { - return replyCount; - } - - public boolean isChild() { - return isChild; - } - - @NonNull - @Override - public Object clone() throws CloneNotSupportedException { - return super.clone(); - } - - @Override - public boolean equals(final Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - final Comment comment = (Comment) o; - return likes == comment.likes && - timestamp == comment.timestamp && - liked == comment.liked && - replyCount == comment.replyCount && - Objects.equals(user, comment.user) && - Objects.equals(id, comment.id) && - Objects.equals(text, comment.text) && - isChild == comment.isChild; - } - - @Override - public int hashCode() { - return Objects.hash(user, id, text, likes, timestamp, liked, replyCount, isChild); - } - - @NonNull - @Override - public String toString() { - return "Comment{" + - "user=" + user + - ", id='" + id + '\'' + - ", text='" + text + '\'' + - ", likes=" + likes + - ", timestamp=" + timestamp + - ", liked=" + liked + - ", replyCount" + replyCount + - ", isChild" + isChild + - '}'; - } -} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/Comment.kt b/app/src/main/java/awais/instagrabber/models/Comment.kt new file mode 100644 index 00000000..87730c77 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/Comment.kt @@ -0,0 +1,69 @@ +package awais.instagrabber.models + +import awais.instagrabber.repositories.responses.User +import awais.instagrabber.utils.Utils +import java.io.Serializable +import java.util.* + +class Comment( + val id: String, + val text: String, + val timestamp: Long, + var likes: Long, + private var liked: Boolean, + val user: User, + val replyCount: Int, + val isChild: Boolean, +) : Serializable, Cloneable { + val dateTime: String + get() = Utils.datetimeParser.format(Date(timestamp * 1000L)) + + fun getLiked(): Boolean { + return liked + } + + fun setLiked(liked: Boolean) { + likes = if (liked) likes + 1 else likes - 1 + this.liked = liked + } + + @Throws(CloneNotSupportedException::class) + public override fun clone(): Any { + return super.clone() + } + + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as Comment + + if (id != other.id) return false + if (text != other.text) return false + if (timestamp != other.timestamp) return false + if (likes != other.likes) return false + if (liked != other.liked) return false + if (user != other.user) return false + if (replyCount != other.replyCount) return false + if (isChild != other.isChild) return false + + return true + } + + override fun hashCode(): Int { + var result = id.hashCode() + result = 31 * result + text.hashCode() + result = 31 * result + timestamp.hashCode() + result = 31 * result + likes.hashCode() + result = 31 * result + liked.hashCode() + result = 31 * result + user.hashCode() + result = 31 * result + replyCount + result = 31 * result + isChild.hashCode() + return result + } + + override fun toString(): String { + return "Comment(id='$id', text='$text', timestamp=$timestamp, likes=$likes, liked=$liked, user=$user, replyCount=$replyCount, isChild=$isChild)" + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/FeedStoryModel.java b/app/src/main/java/awais/instagrabber/models/FeedStoryModel.java deleted file mode 100755 index b87091e5..00000000 --- a/app/src/main/java/awais/instagrabber/models/FeedStoryModel.java +++ /dev/null @@ -1,78 +0,0 @@ -package awais.instagrabber.models; - -import androidx.annotation.NonNull; - -import java.io.Serializable; -import java.util.Date; - -import awais.instagrabber.repositories.responses.User; -import awais.instagrabber.utils.Utils; - -public final class FeedStoryModel implements Serializable { - private final String storyMediaId; - private final User profileModel; - private final StoryModel firstStoryModel; - private Boolean fullyRead; - private final boolean isLive, isBestie; - private final long timestamp; - private final int mediaCount; - - public FeedStoryModel(final String storyMediaId, - final User profileModel, - final boolean fullyRead, - final long timestamp, - final StoryModel firstStoryModel, - final int mediaCount, - final boolean isLive, - final boolean isBestie) { - this.storyMediaId = storyMediaId; - this.profileModel = profileModel; - this.fullyRead = fullyRead; - this.timestamp = timestamp; - this.firstStoryModel = firstStoryModel; - this.mediaCount = mediaCount; - this.isLive = isLive; - this.isBestie = isBestie; - } - - public String getStoryMediaId() { - return storyMediaId; - } - - public long getTimestamp() { - return timestamp; - } - - @NonNull - public String getDateTime() { - return Utils.datetimeParser.format(new Date(timestamp * 1000L)); - } - - public int getMediaCount() { - return mediaCount; - } - - public User getProfileModel() { - return profileModel; - } - - public StoryModel getFirstStoryModel() { - return firstStoryModel; - } - - public Boolean isFullyRead() { - return fullyRead; - } - - public void setFullyRead(final boolean fullyRead) { - this.fullyRead = fullyRead; - } - - public boolean isLive() { - return isLive; - } - - public boolean isBestie() { - return isBestie; - } -} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/FeedStoryModel.kt b/app/src/main/java/awais/instagrabber/models/FeedStoryModel.kt new file mode 100644 index 00000000..9c0e8371 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/FeedStoryModel.kt @@ -0,0 +1,20 @@ +package awais.instagrabber.models + +import awais.instagrabber.repositories.responses.User +import awais.instagrabber.utils.Utils +import java.io.Serializable +import java.util.* + +data class FeedStoryModel( + val storyMediaId: String, + val profileModel: User, + var isFullyRead: Boolean, + val timestamp: Long, + val firstStoryModel: StoryModel, + val mediaCount: Int, + val isLive: Boolean, + val isBestie: Boolean +) : Serializable { + val dateTime: String + get() = Utils.datetimeParser.format(Date(timestamp * 1000L)) +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/FollowModel.java b/app/src/main/java/awais/instagrabber/models/FollowModel.java deleted file mode 100755 index 62c1da79..00000000 --- a/app/src/main/java/awais/instagrabber/models/FollowModel.java +++ /dev/null @@ -1,68 +0,0 @@ -package awais.instagrabber.models; - -import androidx.annotation.Nullable; - -import java.io.Serializable; - -public final class FollowModel implements Serializable { - private final String id; - private final String username; - private final String fullName; - private final String profilePicUrl; - private String endCursor; - private boolean hasNextPage; - private boolean isShown = true; - - public FollowModel(final String id, final String username, final String fullName, final String profilePicUrl) { - this.id = id; - this.username = username; - this.fullName = fullName; - this.profilePicUrl = profilePicUrl; - } - - public String getId() { - return id; - } - - public String getUsername() { - return username; - } - - public String getFullName() { - return fullName; - } - - public String getProfilePicUrl() { - return profilePicUrl; - } - - public boolean isShown() { - return isShown; - } - - public void setShown(final boolean shown) { - isShown = shown; - } - - public void setPageCursor(final boolean hasNextPage, final String endCursor) { - this.endCursor = endCursor; - this.hasNextPage = hasNextPage; - } - - public boolean hasNextPage() { - return endCursor != null && hasNextPage; - } - - public String getEndCursor() { - return endCursor; - } - - @Override - public boolean equals(@Nullable final Object obj) { - if (obj instanceof FollowModel) { - final FollowModel model = (FollowModel) obj; - if (model.getId().equals(id) && model.getUsername().equals(username)) return true; - } - return super.equals(obj); - } -} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/FollowModel.kt b/app/src/main/java/awais/instagrabber/models/FollowModel.kt new file mode 100644 index 00000000..d71196e1 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/FollowModel.kt @@ -0,0 +1,49 @@ +package awais.instagrabber.models + +import java.io.Serializable + +class FollowModel( + val id: String, + val username: String, + val fullName: String, + val profilePicUrl: String +) : Serializable { + private var hasNextPage = false + get() = endCursor != null && field + + var isShown = true + + var endCursor: String? = null + private set + + fun setPageCursor(hasNextPage: Boolean, endCursor: String?) { + this.endCursor = endCursor + this.hasNextPage = hasNextPage + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as FollowModel + + if (id != other.id) return false + if (username != other.username) return false + if (fullName != other.fullName) return false + if (profilePicUrl != other.profilePicUrl) return false + if (isShown != other.isShown) return false + if (endCursor != other.endCursor) return false + + return true + } + + override fun hashCode(): Int { + var result = id.hashCode() + result = 31 * result + username.hashCode() + result = 31 * result + fullName.hashCode() + result = 31 * result + profilePicUrl.hashCode() + result = 31 * result + isShown.hashCode() + result = 31 * result + (endCursor?.hashCode() ?: 0) + return result + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/HighlightModel.java b/app/src/main/java/awais/instagrabber/models/HighlightModel.java deleted file mode 100755 index 86d0327d..00000000 --- a/app/src/main/java/awais/instagrabber/models/HighlightModel.java +++ /dev/null @@ -1,52 +0,0 @@ -package awais.instagrabber.models; - -import androidx.annotation.NonNull; - -import java.util.Date; - -import awais.instagrabber.utils.Utils; - -public final class HighlightModel { - private final String title; - private final String id; - private final String thumbnailUrl; - private final long timestamp; - private final int mediaCount; - - public HighlightModel(final String title, - final String id, - final String thumbnailUrl, - final long timestamp, - final int mediaCount) { - this.title = title; - this.id = id; - this.thumbnailUrl = thumbnailUrl; - this.timestamp = timestamp; - this.mediaCount = mediaCount; - } - - public String getTitle() { - return title; - } - - public String getId() { - return id; - } - - public String getThumbnailUrl() { - return thumbnailUrl; - } - - public long getTimestamp() { - return timestamp; - } - - @NonNull - public String getDateTime() { - return Utils.datetimeParser.format(new Date(timestamp * 1000L)); - } - - public int getMediaCount() { - return mediaCount; - } -} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/HighlightModel.kt b/app/src/main/java/awais/instagrabber/models/HighlightModel.kt new file mode 100644 index 00000000..61f8f235 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/HighlightModel.kt @@ -0,0 +1,15 @@ +package awais.instagrabber.models + +import awais.instagrabber.utils.Utils +import java.util.* + +data class HighlightModel( + val title: String, + val id: String, + val thumbnailUrl: String, + val timestamp: Long, + val mediaCount: Int +) { + val dateTime: String + get() = Utils.datetimeParser.format(Date(timestamp * 1000L)) +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/IntentModel.java b/app/src/main/java/awais/instagrabber/models/IntentModel.java deleted file mode 100755 index 3348bb2e..00000000 --- a/app/src/main/java/awais/instagrabber/models/IntentModel.java +++ /dev/null @@ -1,21 +0,0 @@ -package awais.instagrabber.models; - -import awais.instagrabber.models.enums.IntentModelType; - -public final class IntentModel { - private final IntentModelType type; - private final String text; - - public IntentModel(final IntentModelType type, final String text) { - this.type = type; - this.text = text; - } - - public IntentModelType getType() { - return type; - } - - public String getText() { - return text; - } -} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/IntentModel.kt b/app/src/main/java/awais/instagrabber/models/IntentModel.kt new file mode 100644 index 00000000..a07d9b71 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/IntentModel.kt @@ -0,0 +1,5 @@ +package awais.instagrabber.models + +import awais.instagrabber.models.enums.IntentModelType + +data class IntentModel(val type: IntentModelType, val text: String) \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/Resource.java b/app/src/main/java/awais/instagrabber/models/Resource.java deleted file mode 100644 index da93a0ea..00000000 --- a/app/src/main/java/awais/instagrabber/models/Resource.java +++ /dev/null @@ -1,64 +0,0 @@ -package awais.instagrabber.models; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import java.util.Objects; - -public class Resource { - public final Status status; - public final T data; - public final String message; - public final int resId; - - private Resource(@NonNull Status status, - @Nullable T data, - @Nullable String message, - int resId) { - this.status = status; - this.data = data; - this.message = message; - this.resId = resId; - } - - @NonNull - public static Resource success(@NonNull T data) { - return new Resource<>(Status.SUCCESS, data, null, 0); - } - - @NonNull - public static Resource error(String msg, @Nullable T data) { - return new Resource<>(Status.ERROR, data, msg, 0); - } - - @NonNull - public static Resource error(int resId, @Nullable T data) { - return new Resource<>(Status.ERROR, data, null, resId); - } - - @NonNull - public static Resource loading(@Nullable T data) { - return new Resource<>(Status.LOADING, data, null, 0); - } - - @Override - public boolean equals(final Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - final Resource resource = (Resource) o; - return status == resource.status && - Objects.equals(data, resource.data) && - Objects.equals(message, resource.message); - } - - @Override - public int hashCode() { - return Objects.hash(status, data, message); - } - - public enum Status { - SUCCESS, - ERROR, - LOADING - } -} diff --git a/app/src/main/java/awais/instagrabber/models/Resource.kt b/app/src/main/java/awais/instagrabber/models/Resource.kt new file mode 100644 index 00000000..4877c3df --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/Resource.kt @@ -0,0 +1,36 @@ +package awais.instagrabber.models + +import androidx.annotation.StringRes + +data class Resource( + @JvmField val status: Status, + @JvmField val data: T? = null, + @JvmField val message: String? = null, + @JvmField @StringRes val resId: Int = 0, +) { + enum class Status { + SUCCESS, ERROR, LOADING + } + + companion object { + @JvmStatic + fun success(data: T): Resource { + return Resource(Status.SUCCESS, data, null, 0) + } + + @JvmStatic + fun error(msg: String?, data: T?): Resource { + return Resource(Status.ERROR, data, msg, 0) + } + + @JvmStatic + fun error(resId: Int, data: T?): Resource { + return Resource(Status.ERROR, data, null, resId) + } + + @JvmStatic + fun loading(data: T?): Resource { + return Resource(Status.LOADING, data, null, 0) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/SavedImageEditState.java b/app/src/main/java/awais/instagrabber/models/SavedImageEditState.java deleted file mode 100644 index 7b8d0f4c..00000000 --- a/app/src/main/java/awais/instagrabber/models/SavedImageEditState.java +++ /dev/null @@ -1,66 +0,0 @@ -package awais.instagrabber.models; - -import android.graphics.RectF; - -import java.util.HashMap; -import java.util.Map; - -import awais.instagrabber.fragments.imageedit.filters.FiltersHelper; -import awais.instagrabber.utils.SerializablePair; - -public class SavedImageEditState { - - private final String sessionId; - private final String originalPath; - - private float[] cropImageMatrixValues; // 9 values of matrix - private RectF cropRect; - private HashMap> appliedTuningFilters; - private SerializablePair> appliedFilter; - - public SavedImageEditState(final String sessionId, String originalPath) { - this.sessionId = sessionId; - this.originalPath = originalPath; - } - - public String getSessionId() { - return sessionId; - } - - public String getOriginalPath() { - return originalPath; - } - - public float[] getCropImageMatrixValues() { - return cropImageMatrixValues; - } - - public void setCropImageMatrixValues(float[] cropImageMatrixValues) { - this.cropImageMatrixValues = cropImageMatrixValues; - } - - public RectF getCropRect() { - return cropRect; - } - - public void setCropRect(RectF cropRect) { - this.cropRect = cropRect; - } - - public HashMap> getAppliedTuningFilters() { - return appliedTuningFilters; - } - - public void setAppliedTuningFilters(final HashMap> appliedTuningFilters) { - this.appliedTuningFilters = appliedTuningFilters; - } - - public SerializablePair> getAppliedFilter() { - return appliedFilter; - } - - public void setAppliedFilter(final SerializablePair> appliedFilter) { - this.appliedFilter = appliedFilter; - } -} - diff --git a/app/src/main/java/awais/instagrabber/models/SavedImageEditState.kt b/app/src/main/java/awais/instagrabber/models/SavedImageEditState.kt new file mode 100644 index 00000000..5bab7545 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/SavedImageEditState.kt @@ -0,0 +1,13 @@ +package awais.instagrabber.models + +import android.graphics.RectF +import awais.instagrabber.fragments.imageedit.filters.FiltersHelper +import awais.instagrabber.utils.SerializablePair +import java.util.* + +data class SavedImageEditState(val sessionId: String, val originalPath: String) { + var cropImageMatrixValues: FloatArray? = null // 9 values of matrix + var cropRect: RectF? = null + var appliedTuningFilters: HashMap>? = null + var appliedFilter: SerializablePair>? = null +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/Tab.java b/app/src/main/java/awais/instagrabber/models/Tab.java deleted file mode 100644 index e4e608be..00000000 --- a/app/src/main/java/awais/instagrabber/models/Tab.java +++ /dev/null @@ -1,110 +0,0 @@ -package awais.instagrabber.models; - -import androidx.annotation.DrawableRes; -import androidx.annotation.IdRes; -import androidx.annotation.NavigationRes; -import androidx.annotation.NonNull; - -import java.util.Objects; - -public class Tab { - private final int iconResId; - private final String title; - private final boolean removable; - - /** - * This is name part of the navigation resource - * eg: @navigation/graphName - */ - private final String graphName; - - /** - * This is the actual resource id of the navigation resource (R.navigation.graphName = navigationResId) - */ - private final int navigationResId; - - /** - * This is the resource id of the root navigation tag of the navigation resource. - *

eg: inside R.navigation.direct_messages_nav_graph, the id of the root tag is R.id.direct_messages_nav_graph. - *

So this field would equal to the value of R.id.direct_messages_nav_graph - */ - private final int navigationRootId; - - /** - * This is the start destination of the nav graph - */ - private final int startDestinationFragmentId; - - public Tab(@DrawableRes final int iconResId, - @NonNull final String title, - final boolean removable, - @NonNull final String graphName, - @NavigationRes final int navigationResId, - @IdRes final int navigationRootId, - @IdRes final int startDestinationFragmentId) { - this.iconResId = iconResId; - this.title = title; - this.removable = removable; - this.graphName = graphName; - this.navigationResId = navigationResId; - this.navigationRootId = navigationRootId; - this.startDestinationFragmentId = startDestinationFragmentId; - } - - public int getIconResId() { - return iconResId; - } - - public String getTitle() { - return title; - } - - public boolean isRemovable() { - return removable; - } - - public String getGraphName() { - return graphName; - } - - public int getNavigationResId() { - return navigationResId; - } - - public int getNavigationRootId() { - return navigationRootId; - } - - public int getStartDestinationFragmentId() { - return startDestinationFragmentId; - } - - @Override - public boolean equals(final Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - final Tab tab = (Tab) o; - return iconResId == tab.iconResId && - removable == tab.removable && - navigationResId == tab.navigationResId && - navigationRootId == tab.navigationRootId && - startDestinationFragmentId == tab.startDestinationFragmentId && - Objects.equals(title, tab.title) && - Objects.equals(graphName, tab.graphName); - } - - @Override - public int hashCode() { - return Objects.hash(iconResId, title, removable, graphName, navigationResId, navigationRootId, startDestinationFragmentId); - } - - @NonNull - @Override - public String toString() { - return "Tab{" + - "title='" + title + '\'' + - ", removable=" + removable + - ", graphName='" + graphName + '\'' + - '}'; - } -} diff --git a/app/src/main/java/awais/instagrabber/models/Tab.kt b/app/src/main/java/awais/instagrabber/models/Tab.kt new file mode 100644 index 00000000..5a730d1e --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/Tab.kt @@ -0,0 +1,36 @@ +package awais.instagrabber.models + +import androidx.annotation.DrawableRes +import androidx.annotation.IdRes +import androidx.annotation.NavigationRes + +data class Tab( + @param:DrawableRes val iconResId: Int, + val title: String, + val isRemovable: Boolean, + + /** + * This is name part of the navigation resource + * eg: @navigation/ **graphName** + */ + val graphName: String, + + /** + * This is the actual resource id of the navigation resource (R.navigation.graphName = navigationResId) + */ + @param:NavigationRes val navigationResId: Int, + + /** + * This is the resource id of the root navigation tag of the navigation resource. + * + * eg: inside R.navigation.direct_messages_nav_graph, the id of the root tag is R.id.direct_messages_nav_graph. + * + * So this field would equal to the value of R.id.direct_messages_nav_graph + */ + @param:IdRes val navigationRootId: Int, + + /** + * This is the start destination of the nav graph + */ + @param:IdRes val startDestinationFragmentId: Int, +) \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/UploadPhotoOptions.java b/app/src/main/java/awais/instagrabber/models/UploadPhotoOptions.java deleted file mode 100644 index 47f7a4e7..00000000 --- a/app/src/main/java/awais/instagrabber/models/UploadPhotoOptions.java +++ /dev/null @@ -1,97 +0,0 @@ -package awais.instagrabber.models; - -public class UploadPhotoOptions { - private final String uploadId; - private final String name; - // private final Uri uri; - private final long byteLength; - private final boolean isSideCar; - private final String waterfallId; - - public static class Builder { - private String uploadId; - private String name; - // private Uri uri; - private boolean isSideCar; - private String waterfallId; - private long byteLength; - - private Builder() {} - - public Builder setUploadId(final String uploadId) { - this.uploadId = uploadId; - return this; - } - - public Builder setName(final String name) { - this.name = name; - return this; - } - - // public Builder setUri(final Uri uri) { - // this.uri = uri; - // return this; - // } - - public Builder setByteLength(final long byteLength) { - this.byteLength = byteLength; - return this; - } - - public Builder setIsSideCar(final boolean isSideCar) { - this.isSideCar = isSideCar; - return this; - } - - public Builder setWaterfallId(final String waterfallId) { - this.waterfallId = waterfallId; - return this; - } - - public UploadPhotoOptions build() { - return new UploadPhotoOptions(uploadId, name, /*uri,*/ byteLength, isSideCar, waterfallId); - } - } - - public static Builder builder() { - return new Builder(); - } - - public UploadPhotoOptions(final String uploadId, - final String name, - // final Uri uri, - final long byteLength, - final boolean isSideCar, - final String waterfallId) { - this.uploadId = uploadId; - this.name = name; - // this.uri = uri; - this.byteLength = byteLength; - this.isSideCar = isSideCar; - this.waterfallId = waterfallId; - } - - public String getUploadId() { - return uploadId; - } - - public String getName() { - return name; - } - - // public Uri getUri() { - // return uri; - // } - - public long getByteLength() { - return byteLength; - } - - public boolean isSideCar() { - return isSideCar; - } - - public String getWaterfallId() { - return waterfallId; - } -} diff --git a/app/src/main/java/awais/instagrabber/models/UploadPhotoOptions.kt b/app/src/main/java/awais/instagrabber/models/UploadPhotoOptions.kt new file mode 100644 index 00000000..47d9f4ee --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/UploadPhotoOptions.kt @@ -0,0 +1,9 @@ +package awais.instagrabber.models + +data class UploadPhotoOptions( + val uploadId: String? = null, + val name: String, + val byteLength: Long = 0, + val isSideCar: Boolean = false, + val waterfallId: String? = null, +) \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/models/UploadVideoOptions.java b/app/src/main/java/awais/instagrabber/models/UploadVideoOptions.java deleted file mode 100644 index f1820d11..00000000 --- a/app/src/main/java/awais/instagrabber/models/UploadVideoOptions.java +++ /dev/null @@ -1,217 +0,0 @@ -package awais.instagrabber.models; - -import awais.instagrabber.models.enums.MediaItemType; - -public class UploadVideoOptions { - private final String uploadId; - private final String name; - private final long byteLength; - private final long duration; - private final int width; - private final int height; - private final boolean isSideCar; - private final boolean forAlbum; // Stories - private final boolean isDirect; - private final boolean isDirectVoice; - private final boolean forDirectStory; - private final boolean isIgtvVideo; - private final String waterfallId; - private final long offset; - private final MediaItemType mediaType; - - public static class Builder { - private String uploadId; - private String name; - private long byteLength; - private long duration; - private int width; - private int height; - private boolean isSideCar; - private boolean forAlbum; // Stories - private boolean isDirect; - private boolean isDirectVoice; - private boolean forDirectStory; - private boolean isIgtvVideo; - private String waterfallId; - private long offset; - private MediaItemType mediaType; - - private Builder() {} - - public Builder setUploadId(final String uploadId) { - this.uploadId = uploadId; - return this; - } - - public Builder setName(final String name) { - this.name = name; - return this; - } - - public Builder setByteLength(final long byteLength) { - this.byteLength = byteLength; - return this; - } - - public Builder setDuration(final long duration) { - this.duration = duration; - return this; - } - - public Builder setWidth(final int width) { - this.width = width; - return this; - } - - public Builder setHeight(final int height) { - this.height = height; - return this; - } - - public Builder setIsSideCar(final boolean isSideCar) { - this.isSideCar = isSideCar; - return this; - } - - public Builder setForAlbum(final boolean forAlbum) { - this.forAlbum = forAlbum; - return this; - } - - public Builder setIsDirect(final boolean isDirect) { - this.isDirect = isDirect; - return this; - } - - public Builder setIsDirectVoice(final boolean isDirectVoice) { - this.isDirectVoice = isDirectVoice; - return this; - } - - public Builder setForDirectStory(final boolean forDirectStory) { - this.forDirectStory = forDirectStory; - return this; - } - - public Builder setIsIgtvVideo(final boolean isIgtvVideo) { - this.isIgtvVideo = isIgtvVideo; - return this; - } - - public Builder setWaterfallId(final String waterfallId) { - this.waterfallId = waterfallId; - return this; - } - - public Builder setOffset(final long offset) { - this.offset = offset; - return this; - } - - public Builder setMediaType(final MediaItemType mediaType) { - this.mediaType = mediaType; - return this; - } - - public UploadVideoOptions build() { - return new UploadVideoOptions(uploadId, name, byteLength, duration, width, height, isSideCar, forAlbum, isDirect, isDirectVoice, - forDirectStory, isIgtvVideo, waterfallId, offset, mediaType); - } - } - - public static Builder builder() { - return new Builder(); - } - - private UploadVideoOptions(final String uploadId, - final String name, - final long byteLength, - final long duration, - final int width, - final int height, - final boolean isSideCar, - final boolean forAlbum, - final boolean isDirect, - final boolean isDirectVoice, - final boolean forDirectStory, - final boolean isIgtvVideo, - final String waterfallId, - final long offset, - final MediaItemType mediaType) { - this.uploadId = uploadId; - this.name = name; - this.byteLength = byteLength; - this.duration = duration; - this.width = width; - this.height = height; - this.isSideCar = isSideCar; - this.forAlbum = forAlbum; - this.isDirect = isDirect; - this.isDirectVoice = isDirectVoice; - this.forDirectStory = forDirectStory; - this.isIgtvVideo = isIgtvVideo; - this.waterfallId = waterfallId; - this.offset = offset; - this.mediaType = mediaType; - } - - public String getUploadId() { - return uploadId; - } - - public String getName() { - return name; - } - - public long getByteLength() { - return byteLength; - } - - public long getDuration() { - return duration; - } - - public int getWidth() { - return width; - } - - public int getHeight() { - return height; - } - - public boolean isSideCar() { - return isSideCar; - } - - public boolean isForAlbum() { - return forAlbum; - } - - public boolean isDirect() { - return isDirect; - } - - public boolean isDirectVoice() { - return isDirectVoice; - } - - public boolean isForDirectStory() { - return forDirectStory; - } - - public boolean isIgtvVideo() { - return isIgtvVideo; - } - - public String getWaterfallId() { - return waterfallId; - } - - public long getOffset() { - return offset; - } - - public MediaItemType getMediaType() { - return mediaType; - } -} diff --git a/app/src/main/java/awais/instagrabber/models/UploadVideoOptions.kt b/app/src/main/java/awais/instagrabber/models/UploadVideoOptions.kt new file mode 100644 index 00000000..1c5a25a8 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/models/UploadVideoOptions.kt @@ -0,0 +1,22 @@ +package awais.instagrabber.models + +import awais.instagrabber.models.enums.MediaItemType + +data class UploadVideoOptions( + val uploadId: String, + val name: String, + val byteLength: Long = 0, + val duration: Long = 0, + val width: Int = 0, + val height: Int = 0, + val isSideCar: Boolean = false, + // Stories + val isForAlbum: Boolean = false, + val isDirect: Boolean = false, + val isDirectVoice: Boolean = false, + val isForDirectStory: Boolean = false, + val isIgtvVideo: Boolean = false, + val waterfallId: String? = null, + val offset: Long = 0, + val mediaType: MediaItemType? = null, +) \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/utils/AppExecutors.java b/app/src/main/java/awais/instagrabber/utils/AppExecutors.java deleted file mode 100644 index edba3e82..00000000 --- a/app/src/main/java/awais/instagrabber/utils/AppExecutors.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package awais.instagrabber.utils; - -import android.os.Handler; -import android.os.Looper; - -import androidx.annotation.NonNull; - -import com.google.common.util.concurrent.ListeningExecutorService; -import com.google.common.util.concurrent.MoreExecutors; - -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; - -/** - * Global executor pools for the whole application. - *

- * Grouping tasks like this avoids the effects of task starvation (e.g. disk reads don't wait behind - * webservice requests). - */ -public class AppExecutors { - - private static final int THREAD_COUNT = 3; - private static final Object LOCK = new Object(); - - private static AppExecutors instance; - - private final Executor diskIO; - private final Executor networkIO; - private final MainThreadExecutor mainThread; - private final ListeningExecutorService tasksThread; - - private AppExecutors(Executor diskIO, - Executor networkIO, - MainThreadExecutor mainThread, - ListeningExecutorService tasksThread) { - this.diskIO = diskIO; - this.networkIO = networkIO; - this.mainThread = mainThread; - this.tasksThread = tasksThread; - } - - public static AppExecutors getInstance() { - if (instance == null) { - synchronized (LOCK) { - if (instance == null) { - instance = new AppExecutors(Executors.newSingleThreadExecutor(), - Executors.newFixedThreadPool(THREAD_COUNT), - new MainThreadExecutor(), - MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10))); - } - } - } - return instance; - } - - - public Executor diskIO() { - return diskIO; - } - - public Executor networkIO() { - return networkIO; - } - - - public ListeningExecutorService tasksThread() { - return tasksThread; - } - - public MainThreadExecutor mainThread() { - return mainThread; - } - - public static class MainThreadExecutor implements Executor { - private final Handler mainThreadHandler = new Handler(Looper.getMainLooper()); - - @Override - public void execute(@NonNull Runnable command) { - mainThreadHandler.post(command); - } - - public void execute(final Runnable command, final int delay) { - mainThreadHandler.postDelayed(command, delay); - } - - public void cancel(@NonNull Runnable command) { - mainThreadHandler.removeCallbacks(command); - } - } -} diff --git a/app/src/main/java/awais/instagrabber/utils/AppExecutors.kt b/app/src/main/java/awais/instagrabber/utils/AppExecutors.kt new file mode 100644 index 00000000..f923daa2 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/utils/AppExecutors.kt @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package awais.instagrabber.utils + +import android.os.Handler +import android.os.Looper +import com.google.common.util.concurrent.ListeningExecutorService +import com.google.common.util.concurrent.MoreExecutors +import java.util.concurrent.Executor +import java.util.concurrent.Executors + +/** + * Global executor pools for the whole application. + * + * + * Grouping tasks like this avoids the effects of task starvation (e.g. disk reads don't wait behind + * webservice requests). + */ +object AppExecutors { + val diskIO: Executor = Executors.newSingleThreadExecutor() + val networkIO: Executor = Executors.newFixedThreadPool(3) + val mainThread: MainThreadExecutor = MainThreadExecutor() + val tasksThread: ListeningExecutorService = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10)) + + class MainThreadExecutor : Executor { + private val mainThreadHandler = Handler(Looper.getMainLooper()) + override fun execute(command: Runnable) { + mainThreadHandler.post(command) + } + + fun execute(command: Runnable?, delay: Int) { + mainThreadHandler.postDelayed(command!!, delay.toLong()) + } + + fun cancel(command: Runnable) { + mainThreadHandler.removeCallbacks(command) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/utils/BitmapUtils.java b/app/src/main/java/awais/instagrabber/utils/BitmapUtils.java index 4e7a300d..5a4783d0 100644 --- a/app/src/main/java/awais/instagrabber/utils/BitmapUtils.java +++ b/app/src/main/java/awais/instagrabber/utils/BitmapUtils.java @@ -28,7 +28,7 @@ import java.util.concurrent.Executors; public final class BitmapUtils { private static final String TAG = BitmapUtils.class.getSimpleName(); private static final LruCache bitmapMemoryCache; - private static final AppExecutors appExecutors = AppExecutors.getInstance(); + private static final AppExecutors appExecutors = AppExecutors.INSTANCE; private static final ExecutorService callbackHandlers = Executors .newCachedThreadPool(r -> new Thread(r, "bm-load-callback-handler#" + NumberUtils.random(0, 100))); public static final float THUMBNAIL_SIZE = 200f; @@ -128,7 +128,7 @@ public final class BitmapUtils { final ThumbnailLoadCallback callback) { if (contentResolver == null || uri == null || callback == null) return; final ListenableFuture future = appExecutors - .tasksThread() + .getTasksThread() .submit(() -> getBitmapResult(contentResolver, uri, reqWidth, reqHeight, maxDimenSize, addToCache)); Futures.addCallback(future, new FutureCallback() { @Override @@ -149,11 +149,11 @@ public final class BitmapUtils { @Nullable public static BitmapResult getBitmapResult(final ContentResolver contentResolver, - final Uri uri, - final float reqWidth, - final float reqHeight, - final float maxDimenSize, - final boolean addToCache) { + final Uri uri, + final float reqWidth, + final float reqHeight, + final float maxDimenSize, + final boolean addToCache) { BitmapFactory.Options bitmapOptions; float actualReqWidth = reqWidth; float actualReqHeight = reqHeight; diff --git a/app/src/main/java/awais/instagrabber/utils/ExportImportUtils.java b/app/src/main/java/awais/instagrabber/utils/ExportImportUtils.java index a0a2e190..350ba9a3 100755 --- a/app/src/main/java/awais/instagrabber/utils/ExportImportUtils.java +++ b/app/src/main/java/awais/instagrabber/utils/ExportImportUtils.java @@ -80,8 +80,6 @@ public final class ExportImportUtils { throw e; } catch (final Exception e) { if (fetchListener != null) fetchListener.onResult(false); -// if (logCollector != null) -// logCollector.appendException(e, LogFile.UTILS_IMPORT, "Import::pass"); if (BuildConfig.DEBUG) Log.e(TAG, "Error importing backup", e); } } else if (configType == 'Z') { @@ -99,7 +97,6 @@ public final class ExportImportUtils { throw e; } catch (final Exception e) { if (fetchListener != null) fetchListener.onResult(false); -// if (logCollector != null) logCollector.appendException(e, LogFile.UTILS_IMPORT, "Import"); if (BuildConfig.DEBUG) Log.e(TAG, "", e); } } @@ -122,7 +119,6 @@ public final class ExportImportUtils { if (fetchListener != null) fetchListener.onResult(true); } catch (final Exception e) { if (fetchListener != null) fetchListener.onResult(false); -// if (logCollector != null) logCollector.appendException(e, LogFile.UTILS_IMPORT, "importJson"); if (BuildConfig.DEBUG) Log.e(TAG, "", e); } } @@ -250,8 +246,6 @@ public final class ExportImportUtils { exportBytes = PasswordUtils.enc(exportString, bytes); } catch (final Exception e) { if (fetchListener != null) fetchListener.onResult(false); -// if (logCollector != null) -// logCollector.appendException(e, LogFile.UTILS_EXPORT, "Export::isPass"); if (BuildConfig.DEBUG) Log.e(TAG, "", e); } } else { @@ -264,8 +258,6 @@ public final class ExportImportUtils { if (fetchListener != null) fetchListener.onResult(true); } catch (final Exception e) { if (fetchListener != null) fetchListener.onResult(false); -// if (logCollector != null) -// logCollector.appendException(e, LogFile.UTILS_EXPORT, "Export::notPass"); if (BuildConfig.DEBUG) Log.e(TAG, "", e); } } else if (fetchListener != null) fetchListener.onResult(false); @@ -330,10 +322,10 @@ public final class ExportImportUtils { Log.e(TAG, "onFailure: ", t); callback.onCreated(null); } - }, AppExecutors.getInstance().tasksThread()); + }, AppExecutors.INSTANCE.getTasksThread()); return; } catch (final Exception e) { -// if (logCollector != null) logCollector.appendException(e, LogFile.UTILS_EXPORT, "getExportString"); + // if (logCollector != null) logCollector.appendException(e, LogFile.UTILS_EXPORT, "getExportString"); if (BuildConfig.DEBUG) Log.e(TAG, "", e); } callback.onCreated(null); @@ -342,7 +334,7 @@ public final class ExportImportUtils { @NonNull private static ListenableFuture getSettings(@NonNull final Context context) { final SharedPreferences sharedPreferences = context.getSharedPreferences(Constants.SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE); - return AppExecutors.getInstance().tasksThread().submit(() -> { + return AppExecutors.INSTANCE.getTasksThread().submit(() -> { final Map allPrefs = sharedPreferences.getAll(); if (allPrefs == null) { return new JSONObject(); @@ -382,9 +374,6 @@ public final class ExportImportUtils { jsonArray.put(jsonObject); } } catch (Exception e) { -// if (logCollector != null) { -// logCollector.appendException(e, LogFile.UTILS_EXPORT, "getFavorites"); -// } if (BuildConfig.DEBUG) { Log.e(TAG, "Error exporting favorites", e); } @@ -418,9 +407,6 @@ public final class ExportImportUtils { jsonArray.put(jsonObject); } } catch (Exception e) { -// if (logCollector != null) { -// logCollector.appendException(e, LogFile.UTILS_EXPORT, "getCookies"); -// } if (BuildConfig.DEBUG) { Log.e(TAG, "Error exporting accounts", e); } diff --git a/app/src/main/java/awais/instagrabber/utils/FlavorTown.java b/app/src/main/java/awais/instagrabber/utils/FlavorTown.java index 8f06eb8b..676ef8d1 100755 --- a/app/src/main/java/awais/instagrabber/utils/FlavorTown.java +++ b/app/src/main/java/awais/instagrabber/utils/FlavorTown.java @@ -32,14 +32,14 @@ public final class FlavorTown { final boolean force) { if (checking) return; checking = true; - AppExecutors.getInstance().networkIO().execute(() -> { + AppExecutors.INSTANCE.getNetworkIO().execute(() -> { final String onlineVersionName = UPDATE_CHECKER.getLatestVersion(); if (onlineVersionName == null) return; final String onlineVersion = getVersion(onlineVersionName); final String localVersion = getVersion(BuildConfig.VERSION_NAME); if (Objects.equals(onlineVersion, localVersion)) { if (force) { - AppExecutors.getInstance().mainThread().execute(() -> { + AppExecutors.INSTANCE.getMainThread().execute(() -> { final Context applicationContext = context.getApplicationContext(); // Check if app was closed or crashed before reaching here if (applicationContext == null) return; diff --git a/app/src/main/java/awais/instagrabber/utils/MediaController.java b/app/src/main/java/awais/instagrabber/utils/MediaController.java index 237dd85a..cbfec5c5 100644 --- a/app/src/main/java/awais/instagrabber/utils/MediaController.java +++ b/app/src/main/java/awais/instagrabber/utils/MediaController.java @@ -60,7 +60,7 @@ public class MediaController { public MediaController(final Context context, final OnLoadListener onLoadListener) { this.context = context; this.onLoadListener = onLoadListener; - appExecutors = AppExecutors.getInstance(); + appExecutors = AppExecutors.INSTANCE; } public void load() { @@ -285,9 +285,9 @@ public class MediaController { final AlbumEntry allVideosAlbumFinal, int delay) { if (broadcastPhotosRunnable != null) { - appExecutors.mainThread().cancel(broadcastPhotosRunnable); + appExecutors.getMainThread().cancel(broadcastPhotosRunnable); } - appExecutors.mainThread().execute(broadcastPhotosRunnable = () -> { + appExecutors.getMainThread().execute(broadcastPhotosRunnable = () -> { allMediaAlbums = mediaAlbumsSorted; allPhotoAlbums = photoAlbumsSorted; broadcastPhotosRunnable = null; diff --git a/app/src/main/java/awais/instagrabber/utils/MediaUploadHelper.java b/app/src/main/java/awais/instagrabber/utils/MediaUploadHelper.java deleted file mode 100644 index 86e2495f..00000000 --- a/app/src/main/java/awais/instagrabber/utils/MediaUploadHelper.java +++ /dev/null @@ -1,173 +0,0 @@ -package awais.instagrabber.utils; - -import androidx.annotation.NonNull; - -import com.google.common.collect.ImmutableMap; - -import org.json.JSONObject; - -import java.util.Date; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -import awais.instagrabber.models.UploadPhotoOptions; -import awais.instagrabber.models.UploadVideoOptions; -import awais.instagrabber.models.enums.MediaItemType; - -public final class MediaUploadHelper { - private static final long LOWER = 1000000000L; - private static final long UPPER = 9999999999L; - - private static Map createPhotoRuploadParams(final UploadPhotoOptions options) { - final String retryContextString = getRetryContextString(); - final Map params = new HashMap<>(); - params.put("retry_context", retryContextString); - params.put("media_type", "1"); - params.put("upload_id", options.getUploadId()); - params.put("xsharing_user_ids", "[]"); - final Map imageCompression = new HashMap<>(); - imageCompression.put("lib_name", "moz"); - imageCompression.put("lib_version", "3.1.m"); - imageCompression.put("quality", "80"); - params.put("image_compression", new JSONObject(imageCompression).toString()); - if (options.isSideCar()) { - params.put("is_sidecar", "1"); - } - return params; - } - - private static Map createVideoRuploadParams(final UploadVideoOptions options) { - final String retryContextString = getRetryContextString(); - final Map ruploadParams = new HashMap<>(); - ruploadParams.put("retry_context", retryContextString); - ruploadParams.put("media_type", "2"); - ruploadParams.put("xsharing_user_ids", "[]"); - ruploadParams.put("upload_id", options.getUploadId()); - ruploadParams.put("upload_media_width", String.valueOf(options.getWidth())); - ruploadParams.put("upload_media_height", String.valueOf(options.getHeight())); - ruploadParams.put("upload_media_duration_ms", String.valueOf(options.getDuration())); - if (options.isSideCar()) { - ruploadParams.put("is_sidecar", "1"); - } - if (options.isForAlbum()) { - ruploadParams.put("for_album", "1"); - } - if (options.isDirect()) { - ruploadParams.put("direct_v2", "1"); - } - if (options.isForDirectStory()) { - ruploadParams.put("for_direct_story", "1"); - ruploadParams.put("content_tags", ""); - } - if (options.isIgtvVideo()) { - ruploadParams.put("is_igtv_video", "1"); - } - if (options.isDirectVoice()) { - ruploadParams.put("is_direct_voice", "1"); - } - return ruploadParams; - } - - @NonNull - public static String getRetryContextString() { - final Map retryContext = new HashMap<>(); - retryContext.put("num_step_auto_retry", 0); - retryContext.put("num_reupload", 0); - retryContext.put("num_step_manual_retry", 0); - return new JSONObject(retryContext).toString(); - } - - public static UploadPhotoOptions createUploadPhotoOptions(final long byteLength) { - final String uploadId = generateUploadId(); - return UploadPhotoOptions.builder() - .setUploadId(uploadId) - .setName(generateName(uploadId)) - .setByteLength(byteLength) - .build(); - } - - public static UploadVideoOptions createUploadDmVideoOptions(final long byteLength, - final long duration, - final int width, - final int height) { - final String uploadId = generateUploadId(); - return UploadVideoOptions.builder() - .setUploadId(uploadId) - .setName(generateName(uploadId)) - .setByteLength(byteLength) - .setDuration(duration) - .setWidth(width) - .setHeight(height) - .setIsDirect(true) - .setMediaType(MediaItemType.MEDIA_TYPE_VIDEO) - .build(); - } - - public static UploadVideoOptions createUploadDmVoiceOptions(final long byteLength, - final long duration) { - final String uploadId = generateUploadId(); - return UploadVideoOptions.builder() - .setUploadId(uploadId) - .setName(generateName(uploadId)) - .setDuration(duration) - .setIsDirectVoice(true) - .setByteLength(byteLength) - .setMediaType(MediaItemType.MEDIA_TYPE_VOICE) - .build(); - } - - @NonNull - public static String generateUploadId() { - return String.valueOf(new Date().getTime() / 1000); - } - - @NonNull - public static String generateName(final String uploadId) { - final long random = NumberUtils.random(LOWER, UPPER + 1); - return String.format("%s_0_%s", uploadId, random); - } - - @NonNull - public static Map getUploadPhotoHeaders(@NonNull final UploadPhotoOptions options) { - final String waterfallId = TextUtils.isEmpty(options.getWaterfallId()) ? UUID.randomUUID().toString() : options.getWaterfallId(); - final String contentLength = String.valueOf(options.getByteLength()); - final Map headers = new HashMap<>(); - headers.put("X_FB_PHOTO_WATERFALL_ID", waterfallId); - headers.put("X-Entity-Type", "image/jpeg"); - headers.put("Offset", "0"); - headers.put("X-Instagram-Rupload-Params", new JSONObject(createPhotoRuploadParams(options)).toString()); - headers.put("X-Entity-Name", options.getName()); - headers.put("X-Entity-Length", contentLength); - headers.put("Content-Type", "application/octet-stream"); - headers.put("Content-Length", contentLength); - headers.put("Accept-Encoding", "gzip"); - return headers; - } - - @NonNull - public static Map getUploadVideoHeaders(@NonNull final UploadVideoOptions options) { - final Map ruploadParams = createVideoRuploadParams(options); - final String waterfallId = TextUtils.isEmpty(options.getWaterfallId()) ? UUID.randomUUID().toString() : options.getWaterfallId(); - final String contentLength = String.valueOf(options.getByteLength()); - return ImmutableMap.builder() - .putAll(getBaseUploadVideoHeaders(ruploadParams)) - .put("X_FB_PHOTO_WATERFALL_ID", waterfallId) - .put("X-Entity-Type", "video/mp4") - .put("Offset", String.valueOf(options.getOffset() > 0 ? options.getOffset() : 0)) - .put("X-Entity-Name", options.getName()) - .put("X-Entity-Length", contentLength) - .put("Content-Type", "application/octet-stream") - .put("Content-Length", contentLength) - .build(); - } - - private static Map getBaseUploadVideoHeaders(@NonNull final Map ruploadParams) { - return ImmutableMap.of( - "X-IG-Connection-Type", "WIFI", - "X-IG-Capabilities", "3brTvwE=", - "Accept-Encoding", "gzip", - "X-Instagram-Rupload-Params", new JSONObject(ruploadParams).toString() - ); - } -} diff --git a/app/src/main/java/awais/instagrabber/utils/MediaUploadHelper.kt b/app/src/main/java/awais/instagrabber/utils/MediaUploadHelper.kt new file mode 100644 index 00000000..2b5baddf --- /dev/null +++ b/app/src/main/java/awais/instagrabber/utils/MediaUploadHelper.kt @@ -0,0 +1,154 @@ +@file:JvmName("MediaUploadHelper") + +package awais.instagrabber.utils + +import awais.instagrabber.models.UploadPhotoOptions +import awais.instagrabber.models.UploadVideoOptions +import awais.instagrabber.models.enums.MediaItemType +import org.json.JSONObject +import java.util.* + + +private const val LOWER = 1000000000L +private const val UPPER = 9999999999L + +private fun createPhotoRuploadParams(options: UploadPhotoOptions): Map { + val imageCompression = mapOf( + "lib_name" to "moz", + "lib_version" to "3.1.m", + "quality" to "80", + ) + return listOfNotNull( + "retry_context" to retryContextString, + "media_type" to "1", + "upload_id" to (options.uploadId ?: ""), + "xsharing_user_ids" to "[]", + "image_compression" to JSONObject(imageCompression).toString(), + if (options.isSideCar) "is_sidecar" to "1" else null, + ).toMap() +} + +private fun createVideoRuploadParams(options: UploadVideoOptions): Map { + val retryContextString = retryContextString + return listOfNotNull( + "retry_context" to retryContextString, + "media_type" to "2", + "xsharing_user_ids" to "[]", + "upload_id" to options.uploadId, + "upload_media_width" to options.width.toString(), + "upload_media_height" to options.height.toString(), + "upload_media_duration_ms" to options.duration.toString(), + if (options.isSideCar) "is_sidecar" to "1" else null, + if (options.isForAlbum) "for_album" to "1" else null, + if (options.isDirect) "direct_v2" to "1" else null, + *(if (options.isForDirectStory) arrayOf( + "for_direct_story" to "1", + "content_tags" to "" + ) else emptyArray()), + if (options.isIgtvVideo) "is_igtv_video" to "1" else null, + if (options.isDirectVoice) "is_direct_voice" to "1" else null, + ).toMap() +} + +val retryContextString: String + get() { + return JSONObject( + mapOf( + "num_step_auto_retry" to 0, + "num_reupload" to 0, + "num_step_manual_retry" to 0, + ) + ).toString() + } + +fun createUploadPhotoOptions(byteLength: Long): UploadPhotoOptions { + val uploadId = generateUploadId() + return UploadPhotoOptions( + uploadId, + generateName(uploadId), + byteLength, + ) +} + +fun createUploadDmVideoOptions( + byteLength: Long, + duration: Long, + width: Int, + height: Int +): UploadVideoOptions { + val uploadId = generateUploadId() + return UploadVideoOptions( + uploadId, + generateName(uploadId), + byteLength, + duration, + width, + height, + true, + mediaType = MediaItemType.MEDIA_TYPE_VIDEO, + ) +} + +fun createUploadDmVoiceOptions( + byteLength: Long, + duration: Long +): UploadVideoOptions { + val uploadId = generateUploadId() + return UploadVideoOptions( + uploadId, + generateName(uploadId), + byteLength, + duration, + isDirectVoice = true, + mediaType = MediaItemType.MEDIA_TYPE_VOICE, + ) +} + +fun generateUploadId(): String { + return (Date().time / 1000).toString() +} + +fun generateName(uploadId: String): String { + val random = NumberUtils.random(LOWER, UPPER + 1) + return "${uploadId}_0_$random" +} + +fun getUploadPhotoHeaders(options: UploadPhotoOptions): Map { + val waterfallId = options.waterfallId ?: UUID.randomUUID().toString() + val contentLength = options.byteLength.toString() + return mapOf( + "X_FB_PHOTO_WATERFALL_ID" to waterfallId, + "X-Entity-Type" to "image/jpeg", + "Offset" to "0", + "X-Instagram-Rupload-Params" to JSONObject(createPhotoRuploadParams(options)).toString(), + "X-Entity-Name" to options.name, + "X-Entity-Length" to contentLength, + "Content-Type" to "application/octet-stream", + "Content-Length" to contentLength, + "Accept-Encoding" to "gzip", + ) +} + +fun getUploadVideoHeaders(options: UploadVideoOptions): Map { + val ruploadParams = createVideoRuploadParams(options) + val waterfallId = options.waterfallId ?: UUID.randomUUID().toString() + val contentLength = options.byteLength.toString() + return getBaseUploadVideoHeaders(ruploadParams) + mapOf( + "X_FB_PHOTO_WATERFALL_ID" to waterfallId, + "X-Entity-Type" to "video/mp4", + "Offset" to (if (options.offset > 0) options.offset else 0).toString(), + "X-Entity-Name" to options.name, + "X-Entity-Length" to contentLength, + "Content-Type" to "application/octet-stream", + "Content-Length" to contentLength, + ) +} + +private fun getBaseUploadVideoHeaders(ruploadParams: Map): Map { + return mapOf( + "X-IG-Connection-Type" to "WIFI", + "X-IG-Capabilities" to "3brTvwE=", + "Accept-Encoding" to "gzip", + "X-Instagram-Rupload-Params" to JSONObject(ruploadParams).toString() + ) +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/utils/MediaUploader.java b/app/src/main/java/awais/instagrabber/utils/MediaUploader.java index beb5c1af..2b197e8c 100644 --- a/app/src/main/java/awais/instagrabber/utils/MediaUploader.java +++ b/app/src/main/java/awais/instagrabber/utils/MediaUploader.java @@ -33,7 +33,7 @@ import okio.Source; public final class MediaUploader { private static final String TAG = MediaUploader.class.getSimpleName(); private static final String HOST = "https://i.instagram.com"; - private static final AppExecutors appExecutors = AppExecutors.getInstance(); + private static final AppExecutors appExecutors = AppExecutors.INSTANCE; public static void uploadPhoto(@NonNull final Uri uri, @NonNull final ContentResolver contentResolver, @@ -57,7 +57,7 @@ public final class MediaUploader { private static void uploadPhoto(@NonNull final Bitmap bitmap, @NonNull final OnMediaUploadCompleteListener listener) { - appExecutors.tasksThread().submit(() -> { + appExecutors.getTasksThread().submit(() -> { final File file; final long byteLength; try { @@ -70,7 +70,7 @@ public final class MediaUploader { final UploadPhotoOptions options = MediaUploadHelper.createUploadPhotoOptions(byteLength); final Map headers = MediaUploadHelper.getUploadPhotoHeaders(options); final String url = HOST + "/rupload_igphoto/" + options.getName() + "/"; - appExecutors.networkIO().execute(() -> { + appExecutors.getNetworkIO().execute(() -> { try (FileInputStream input = new FileInputStream(file)) { upload(input, url, headers, listener); } catch (IOException e) { @@ -87,10 +87,10 @@ public final class MediaUploader { final ContentResolver contentResolver, final UploadVideoOptions options, final OnMediaUploadCompleteListener listener) { - appExecutors.tasksThread().submit(() -> { + appExecutors.getTasksThread().submit(() -> { final Map headers = MediaUploadHelper.getUploadVideoHeaders(options); final String url = HOST + "/rupload_igvideo/" + options.getName() + "/"; - appExecutors.networkIO().execute(() -> { + appExecutors.getNetworkIO().execute(() -> { try (InputStream input = contentResolver.openInputStream(uri)) { if (input == null) { listener.onFailure(new RuntimeException("InputStream was null")); diff --git a/app/src/main/java/awais/instagrabber/utils/MediaUtils.java b/app/src/main/java/awais/instagrabber/utils/MediaUtils.java index c7ee7967..e7ca2707 100644 --- a/app/src/main/java/awais/instagrabber/utils/MediaUtils.java +++ b/app/src/main/java/awais/instagrabber/utils/MediaUtils.java @@ -25,7 +25,7 @@ public final class MediaUtils { public static void getVideoInfo(@NonNull final ContentResolver contentResolver, @NonNull final Uri uri, @NonNull final OnInfoLoadListener listener) { - AppExecutors.getInstance().tasksThread().submit(() -> { + AppExecutors.INSTANCE.getTasksThread().submit(() -> { try (Cursor cursor = MediaStore.Video.query(contentResolver, uri, PROJECTION_VIDEO)) { if (cursor == null) { if (listener != null) { @@ -63,7 +63,7 @@ public final class MediaUtils { public static void getVoiceInfo(@NonNull final ContentResolver contentResolver, @NonNull final Uri uri, @NonNull final OnInfoLoadListener listener) { - AppExecutors.getInstance().tasksThread().submit(() -> { + AppExecutors.INSTANCE.getTasksThread().submit(() -> { try (Cursor cursor = MediaStore.Video.query(contentResolver, uri, PROJECTION_AUDIO)) { if (cursor == null) { if (listener != null) { diff --git a/app/src/main/java/awais/instagrabber/utils/UpdateCheckCommon.java b/app/src/main/java/awais/instagrabber/utils/UpdateCheckCommon.java index 285fbb13..a4f4b255 100644 --- a/app/src/main/java/awais/instagrabber/utils/UpdateCheckCommon.java +++ b/app/src/main/java/awais/instagrabber/utils/UpdateCheckCommon.java @@ -23,7 +23,7 @@ public final class UpdateCheckCommon { public static void showUpdateDialog(@NonNull final Context context, @NonNull final String version, @NonNull final DialogInterface.OnClickListener onDownloadClickListener) { - AppExecutors.getInstance().mainThread().execute(() -> { + AppExecutors.INSTANCE.getMainThread().execute(() -> { new MaterialAlertDialogBuilder(context) .setTitle(context.getString(R.string.update_available, version)) .setNeutralButton(R.string.skip_update, (dialog, which) -> { diff --git a/app/src/main/java/awais/instagrabber/viewmodels/ImageEditViewModel.java b/app/src/main/java/awais/instagrabber/viewmodels/ImageEditViewModel.java index 9707e092..2f7f01b0 100644 --- a/app/src/main/java/awais/instagrabber/viewmodels/ImageEditViewModel.java +++ b/app/src/main/java/awais/instagrabber/viewmodels/ImageEditViewModel.java @@ -135,7 +135,7 @@ public class ImageEditViewModel extends AndroidViewModel { private void applyFilters() { final GPUImage gpuImage = new GPUImage(getApplication()); if ((tuningFilters != null && !tuningFilters.isEmpty()) || appliedFilter != null) { - AppExecutors.getInstance().tasksThread().submit(() -> { + AppExecutors.INSTANCE.getTasksThread().submit(() -> { final List list = new ArrayList<>(); if (tuningFilters != null) { for (Filter tuningFilter : tuningFilters) { diff --git a/app/src/main/java/awais/instagrabber/viewmodels/SearchFragmentViewModel.java b/app/src/main/java/awais/instagrabber/viewmodels/SearchFragmentViewModel.java index 229cc9c1..14c7964f 100644 --- a/app/src/main/java/awais/instagrabber/viewmodels/SearchFragmentViewModel.java +++ b/app/src/main/java/awais/instagrabber/viewmodels/SearchFragmentViewModel.java @@ -232,7 +232,7 @@ public class SearchFragmentViewModel extends AppStateViewModel { topResults.postValue(Resource.success(Collections.emptyList())); Log.e(TAG, "onFailure: ", t); } - }, AppExecutors.getInstance().mainThread()); + }, AppExecutors.INSTANCE.getMainThread()); } private void sendErrorResponse(@NonNull final FavoriteType type) { diff --git a/app/src/main/java/awais/instagrabber/webservices/interceptors/IgErrorsInterceptor.java b/app/src/main/java/awais/instagrabber/webservices/interceptors/IgErrorsInterceptor.java index b0fab4d2..7ad95782 100644 --- a/app/src/main/java/awais/instagrabber/webservices/interceptors/IgErrorsInterceptor.java +++ b/app/src/main/java/awais/instagrabber/webservices/interceptors/IgErrorsInterceptor.java @@ -108,9 +108,9 @@ public class IgErrorsInterceptor implements Interceptor { // final View view = mainActivity.getRootView(); // if (view == null) return; try { - AppExecutors.getInstance() - .mainThread() - .execute(() -> Toast.makeText(mainActivity.getApplicationContext(), message, Toast.LENGTH_LONG).show()); + AppExecutors.INSTANCE + .getMainThread() + .execute(() -> Toast.makeText(mainActivity.getApplicationContext(), message, Toast.LENGTH_LONG).show()); } catch (Exception e) { Log.e(TAG, "showSnackbar: ", e); } diff --git a/build.gradle b/build.gradle index afb10764..93e0391d 100755 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,6 @@ buildscript { + ext.kotlin_version = '1.5.0' + repositories { google() mavenCentral() @@ -6,6 +8,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:4.2.1' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" def nav_version = "2.3.5" classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version" }