Merge branch 'master' into pr/925

This commit is contained in:
Austin Huang 2021-04-03 12:41:00 -04:00
commit f55e519895
No known key found for this signature in database
GPG Key ID: 84C23AA04587A91F
14 changed files with 263 additions and 67 deletions

View File

@ -130,6 +130,9 @@
android:name="android.support.PARENT_ACTIVITY"
android:value=".activities.MainActivity" />
</activity>
<activity
android:name=".utils.ProcessPhoenix"
android:theme="@style/Theme.AppCompat.Translucent" />
<provider
android:name="androidx.core.content.FileProvider"

View File

@ -12,7 +12,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.FragmentActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import java.util.Collections;
@ -25,8 +24,10 @@ import awais.instagrabber.db.datasources.AccountDataSource;
import awais.instagrabber.db.entities.Account;
import awais.instagrabber.db.repositories.AccountRepository;
import awais.instagrabber.db.repositories.RepositoryCallback;
import awais.instagrabber.utils.AppExecutors;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.CookieUtils;
import awais.instagrabber.utils.ProcessPhoenix;
import awais.instagrabber.utils.TextUtils;
import awais.instagrabber.utils.Utils;
@ -55,9 +56,14 @@ public class AccountSwitcherDialogFragment extends DialogFragment {
}
CookieUtils.setupCookies(model.getCookie());
settingsHelper.putString(Constants.COOKIE, model.getCookie());
final FragmentActivity activity = getActivity();
if (activity != null) activity.recreate();
dismiss();
// final FragmentActivity activity = getActivity();
// if (activity != null) activity.recreate();
// dismiss();
AppExecutors.getInstance().mainThread().execute(() -> {
final Context context = getContext();
if (context == null) return;
ProcessPhoenix.triggerRebirth(context);
}, 200);
};
private final AccountSwitcherAdapter.OnAccountLongClickListener accountLongClickListener = (model, isCurrent) -> {

View File

@ -78,8 +78,7 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe
try {
binding.swipeRefreshLayout.setRefreshing(false);
Toast.makeText(getContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
}
catch(Throwable e) {}
} catch (Throwable ignored) {}
}
};
@ -92,10 +91,10 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe
@Override
public void onPreviewClick(final Notification model) {
final NotificationImage notificationImage = model.getArgs().getMedia().get(0);
final long mediaId = Long.valueOf(notificationImage.getId().split("_")[0]);
final long mediaId = Long.parseLong(notificationImage.getId().split("_")[0]);
if (model.getType() == NotificationType.RESPONDED_STORY) {
final NavDirections action = NotificationsViewerFragmentDirections
.actionNotificationsViewerFragmentToStoryViewerFragment(
.actionNotificationsToStory(
StoryViewerOptions.forStory(
mediaId,
model.getArgs().getUsername()));
@ -277,8 +276,7 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe
}
private void openProfile(final String username) {
final NavDirections action = NotificationsViewerFragmentDirections
.actionGlobalProfileFragment("@" + username);
final NavDirections action = NotificationsViewerFragmentDirections.actionGlobalProfileFragment("@" + username);
NavHostFragment.findNavController(this).navigate(action);
}
}

View File

@ -137,14 +137,14 @@ public class StoryViewerFragment extends Fragment {
private String[] mentions;
private QuizModel quiz;
private SliderModel slider;
private MenuItem menuDownload;
private MenuItem menuDm;
private MenuItem menuDownload, menuDm, menuProfile;
private SimpleExoPlayer player;
// private boolean isHashtag;
// private boolean isLoc;
// private String highlight;
private String actionBarTitle;
private String actionBarTitle, actionBarSubtitle;
private boolean fetching = false, sticking = false, shouldRefresh = true;
private boolean downloadVisible = false, dmVisible = false, profileVisible = true;
private int currentFeedStoryIndex;
private double sliderValue;
private StoriesViewModel storiesViewModel;
@ -195,8 +195,10 @@ public class StoryViewerFragment extends Fragment {
menuInflater.inflate(R.menu.story_menu, menu);
menuDownload = menu.findItem(R.id.action_download);
menuDm = menu.findItem(R.id.action_dms);
menuDownload.setVisible(false);
menuDm.setVisible(false);
menuProfile = menu.findItem(R.id.action_profile);
menuDownload.setVisible(downloadVisible);
menuDm.setVisible(dmVisible);
menuProfile.setVisible(profileVisible);
}
@Override
@ -215,7 +217,8 @@ public class StoryViewerFragment extends Fragment {
else
ActivityCompat.requestPermissions(requireActivity(), DownloadUtils.PERMS, 8020);
return true;
} else if (itemId == R.id.action_dms) {
}
if (itemId == R.id.action_dms) {
final EditText input = new EditText(context);
input.setHint(R.string.reply_hint);
new AlertDialog.Builder(context)
@ -259,6 +262,9 @@ public class StoryViewerFragment extends Fragment {
.show();
return true;
}
if (itemId == R.id.action_profile) {
openProfile("@" + currentStory.getUsername());
}
return false;
}
@ -281,7 +287,9 @@ public class StoryViewerFragment extends Fragment {
final ActionBar actionBar = fragmentActivity.getSupportActionBar();
if (actionBar != null) {
actionBar.setTitle(actionBarTitle);
actionBar.setSubtitle(actionBarSubtitle);
}
setHasOptionsMenu(true);
}
@Override
@ -697,6 +705,10 @@ public class StoryViewerFragment extends Fragment {
lastSlidePos = 0;
if (menuDownload != null) menuDownload.setVisible(false);
if (menuDm != null) menuDm.setVisible(false);
if (menuProfile != null) menuProfile.setVisible(false);
downloadVisible = false;
dmVisible = false;
profileVisible = false;
binding.imageViewer.setController(null);
releasePlayer();
String currentStoryMediaId = null;
@ -846,7 +858,6 @@ public class StoryViewerFragment extends Fragment {
final MediaItemType itemType = currentStory.getItemType();
if (menuDownload != null) menuDownload.setVisible(false);
url = itemType == MediaItemType.MEDIA_TYPE_IMAGE ? currentStory.getStoryUrl() : currentStory.getVideoUrl();
if (itemType != MediaItemType.MEDIA_TYPE_LIVE) {
@ -900,9 +911,10 @@ public class StoryViewerFragment extends Fragment {
else setupImage();
final ActionBar actionBar = fragmentActivity.getSupportActionBar();
actionBarSubtitle = Utils.datetimeParser.format(new Date(currentStory.getTimestamp() * 1000L));
if (actionBar != null) {
try {
actionBar.setSubtitle(Utils.datetimeParser.format(new Date(currentStory.getTimestamp() * 1000L)));
actionBar.setSubtitle(actionBarSubtitle);
} catch (Exception e) {
Log.e(TAG, "refreshStory: ", e);
}
@ -948,11 +960,17 @@ public class StoryViewerFragment extends Fragment {
final ImageInfo imageInfo,
final Animatable animatable) {
if (menuDownload != null) {
downloadVisible = true;
menuDownload.setVisible(true);
}
if (currentStory.canReply() && menuDm != null) {
dmVisible = true;
menuDm.setVisible(true);
}
if (!TextUtils.isEmpty(currentStory.getUsername())) {
profileVisible = true;
menuProfile.setVisible(true);
}
binding.progressView.setVisibility(View.GONE);
}
})
@ -982,9 +1000,18 @@ public class StoryViewerFragment extends Fragment {
@Nullable final MediaSource.MediaPeriodId mediaPeriodId,
@NonNull final LoadEventInfo loadEventInfo,
@NonNull final MediaLoadData mediaLoadData) {
if (menuDownload != null) menuDownload.setVisible(true);
if (currentStory.canReply() && menuDm != null)
if (menuDownload != null) {
downloadVisible = true;
menuDownload.setVisible(true);
}
if (currentStory.canReply() && menuDm != null) {
dmVisible = true;
menuDm.setVisible(true);
}
if (!TextUtils.isEmpty(currentStory.getUsername()) && menuProfile != null) {
profileVisible = true;
menuProfile.setVisible(true);
}
binding.progressView.setVisibility(View.GONE);
}
@ -993,9 +1020,18 @@ public class StoryViewerFragment extends Fragment {
@Nullable final MediaSource.MediaPeriodId mediaPeriodId,
@NonNull final LoadEventInfo loadEventInfo,
@NonNull final MediaLoadData mediaLoadData) {
if (menuDownload != null) menuDownload.setVisible(true);
if (currentStory.canReply() && menuDm != null)
if (menuDownload != null) {
downloadVisible = true;
menuDownload.setVisible(true);
}
if (currentStory.canReply() && menuDm != null) {
dmVisible = true;
menuDm.setVisible(true);
}
if (!TextUtils.isEmpty(currentStory.getUsername()) && menuProfile != null) {
profileVisible = true;
menuProfile.setVisible(true);
}
binding.progressView.setVisibility(View.VISIBLE);
}
@ -1014,8 +1050,18 @@ public class StoryViewerFragment extends Fragment {
@NonNull final MediaLoadData mediaLoadData,
@NonNull final IOException error,
final boolean wasCanceled) {
if (menuDownload != null) menuDownload.setVisible(false);
if (menuDm != null) menuDm.setVisible(false);
if (menuDownload != null) {
downloadVisible = false;
menuDownload.setVisible(false);
}
if (menuDm != null) {
dmVisible = false;
menuDm.setVisible(false);
}
if (menuProfile != null) {
profileVisible = false;
menuProfile.setVisible(false);
}
binding.progressView.setVisibility(View.GONE);
}
});

View File

@ -83,9 +83,12 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre
new FeedStoriesAdapter.OnFeedStoryClickListener() {
@Override
public void onFeedStoryClick(FeedStoryModel model, int position) {
final NavDirections action = FeedFragmentDirections
.actionFeedFragmentToStoryViewerFragment(StoryViewerOptions.forFeedStoryPosition(position));
NavHostFragment.findNavController(FeedFragment.this).navigate(action);
final NavController navController = NavHostFragment.findNavController(FeedFragment.this);
if (isSafeToNavigate(navController)) {
final NavDirections action = FeedFragmentDirections
.actionFeedFragmentToStoryViewerFragment(StoryViewerOptions.forFeedStoryPosition(position));
navController.navigate(action);
}
}
@Override
@ -437,4 +440,9 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre
binding.feedRecyclerView.smoothScrollToPosition(0);
// binding.storiesContainer.setExpanded(true);
}
private boolean isSafeToNavigate(final NavController navController) {
return navController.getCurrentDestination() != null
&& navController.getCurrentDestination().getId() == R.id.feedFragment;
}
}

View File

@ -11,8 +11,6 @@ import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.navigation.NavController;
import androidx.navigation.NavDirections;
@ -35,9 +33,11 @@ import awais.instagrabber.db.repositories.AccountRepository;
import awais.instagrabber.db.repositories.RepositoryCallback;
import awais.instagrabber.dialogs.AccountSwitcherDialogFragment;
import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.utils.AppExecutors;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.CookieUtils;
import awais.instagrabber.utils.FlavorTown;
import awais.instagrabber.utils.ProcessPhoenix;
import awais.instagrabber.utils.TextUtils;
import awais.instagrabber.utils.Utils;
import awais.instagrabber.webservices.ServiceCallback;
@ -71,11 +71,15 @@ public class MorePreferencesFragment extends BasePreferencesFragment {
accountCategory.setSummary(R.string.account_hint);
accountCategory.addPreference(getAccountSwitcherPreference(cookie, context));
accountCategory.addPreference(getPreference(R.string.logout, R.string.logout_summary, R.drawable.ic_logout_24, preference -> {
if (getContext() == null) return false;
final Context context1 = getContext();
if (context1 == null) return false;
CookieUtils.setupCookies("LOGOUT");
shouldRecreate();
Toast.makeText(context, R.string.logout_success, Toast.LENGTH_SHORT).show();
// shouldRecreate();
Toast.makeText(context1, R.string.logout_success, Toast.LENGTH_SHORT).show();
settingsHelper.putString(Constants.COOKIE, "");
AppExecutors.getInstance().mainThread().execute(() -> {
ProcessPhoenix.triggerRebirth(context1);
}, 200);
return true;
}));
}
@ -103,9 +107,14 @@ public class MorePreferencesFragment extends BasePreferencesFragment {
CookieUtils.removeAllAccounts(context, new RepositoryCallback<Void>() {
@Override
public void onSuccess(final Void result) {
shouldRecreate();
Toast.makeText(context, R.string.logout_success, Toast.LENGTH_SHORT).show();
// shouldRecreate();
final Context context1 = getContext();
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);
}
@Override
@ -265,9 +274,14 @@ public class MorePreferencesFragment extends BasePreferencesFragment {
new RepositoryCallback<Account>() {
@Override
public void onSuccess(final Account result) {
final FragmentActivity activity = getActivity();
if (activity == null) return;
activity.recreate();
// final FragmentActivity activity = getActivity();
// if (activity == null) return;
// activity.recreate();
AppExecutors.getInstance().mainThread().execute(() -> {
final Context context = getContext();
if (context == null) return;
ProcessPhoenix.triggerRebirth(context);
}, 200);
}
@Override

View File

@ -0,0 +1,111 @@
/*
* Copyright (C) 2014 Jake Wharton
*
* 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.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Process;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
/**
* Process Phoenix facilitates restarting your application process. This should only be used for
* things like fundamental state changes in your debug builds (e.g., changing from staging to
* production).
* <p>
* Trigger process recreation by calling {@link #triggerRebirth} with a {@link Context} instance.
*/
public final class ProcessPhoenix extends Activity {
private static final String KEY_RESTART_INTENTS = "phoenix_restart_intents";
/**
* Call to restart the application process using the {@linkplain Intent#CATEGORY_DEFAULT default}
* activity as an intent.
* <p>
* Behavior of the current process after invoking this method is undefined.
*/
public static void triggerRebirth(Context context) {
triggerRebirth(context, getRestartIntent(context));
}
/**
* Call to restart the application process using the specified intents.
* <p>
* Behavior of the current process after invoking this method is undefined.
*/
public static void triggerRebirth(Context context, Intent... nextIntents) {
Intent intent = new Intent(context, ProcessPhoenix.class);
intent.addFlags(FLAG_ACTIVITY_NEW_TASK); // In case we are called with non-Activity context.
intent.putParcelableArrayListExtra(KEY_RESTART_INTENTS, new ArrayList<>(Arrays.asList(nextIntents)));
context.startActivity(intent);
if (context instanceof Activity) {
((Activity) context).finish();
}
Runtime.getRuntime().exit(0); // Kill kill kill!
}
private static Intent getRestartIntent(Context context) {
String packageName = context.getPackageName();
Intent defaultIntent = context.getPackageManager().getLaunchIntentForPackage(packageName);
if (defaultIntent != null) {
defaultIntent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
return defaultIntent;
}
throw new IllegalStateException("Unable to determine default activity for "
+ packageName
+ ". Does an activity specify the DEFAULT category in its intent filter?");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ArrayList<Intent> intents = getIntent().getParcelableArrayListExtra(KEY_RESTART_INTENTS);
startActivities(intents.toArray(new Intent[intents.size()]));
finish();
Runtime.getRuntime().exit(0); // Kill kill kill!
}
/**
* Checks if the current process is a temporary Phoenix Process.
* This can be used to avoid initialisation of unused resources or to prevent running code that
* is not multi-process ready.
*
* @return true if the current process is a temporary Phoenix Process
*/
public static boolean isPhoenixProcess(Context context) {
int currentPid = Process.myPid();
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> runningProcesses = manager.getRunningAppProcesses();
if (runningProcesses != null) {
for (ActivityManager.RunningAppProcessInfo processInfo : runningProcesses) {
if (processInfo.pid == currentPid && processInfo.processName.endsWith(":phoenix")) {
return true;
}
}
}
return false;
}
}

View File

@ -31,7 +31,6 @@ import android.webkit.MimeTypeMap;
import android.widget.Toast;
import androidx.annotation.DrawableRes;
import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
@ -474,7 +473,11 @@ public final class Utils {
final List<String> navGraphNameList = Arrays.asList(navGraphNames);
if (TextUtils.isEmpty(tabOrderString)) {
// Use top 5 entries for default list
return navGraphNameList.subList(0, 5);
final List<String> top5navGraphNames = navGraphNameList.subList(0, 5);
final String newOrderString = android.text.TextUtils.join(",", top5navGraphNames);
Utils.settingsHelper.putString(PreferenceKeys.PREF_TAB_ORDER, newOrderString);
tabOrderString = newOrderString;
return top5navGraphNames;
}
// Make sure that the list from preference does not contain any invalid values
final List<String> orderGraphNames = Arrays.stream(tabOrderString.split(","))
@ -489,6 +492,7 @@ public final class Utils {
}
public static boolean isNavRootInCurrentTabs(final String navRootString) {
if (navRootString == null || tabOrderString == null) return false;
return tabOrderString.contains(navRootString);
}
}

View File

@ -56,9 +56,11 @@ public class NewsService extends BaseService {
callback.onSuccess(null);
return;
}
final List<Notification> result = new ArrayList<>();
result.addAll(body.getNewStories());
result.addAll(body.getOldStories());
final List<Notification> result = new ArrayList<Notification>();
final List<Notification> newStories = body.getNewStories();
if (newStories != null) result.addAll(newStories);
final List<Notification> oldStories = body.getOldStories();
if (oldStories != null) result.addAll(oldStories);
callback.onSuccess(result);
}

View File

@ -326,6 +326,7 @@
<androidx.constraintlayout.widget.Barrier
android:id="@+id/highlights_barrier"
android:layout_width="wrap_content"
app:constraint_referenced_ids="mainPostCount, mainFollowers, mainFollowing"
android:layout_height="wrap_content"
app:barrierDirection="bottom" />

View File

@ -5,13 +5,18 @@
<item
android:id="@+id/action_dms"
android:icon="@drawable/ic_round_send_24"
android:title="@string/action_dms"
android:titleCondensed="@string/action_dms"
app:showAsAction="always" />
android:title="@string/reply_story"
android:titleCondensed="@string/reply_story"
app:showAsAction="never" />
<item
android:id="@+id/action_profile"
android:title="@string/open_profile"
android:titleCondensed="@string/open_profile"
app:showAsAction="never" />
<item
android:id="@+id/action_download"
android:icon="@drawable/ic_download"
android:title="@string/action_download"
android:titleCondensed="@string/action_download"
app:showAsAction="always" />
app:showAsAction="never" />
</menu>

View File

@ -5,25 +5,6 @@
android:id="@+id/notification_viewer_nav_graph"
app:startDestination="@id/notificationsViewer">
<fragment
android:id="@+id/notificationsViewer"
android:name="awais.instagrabber.fragments.NotificationsViewerFragment"
android:label="@string/title_notifications"
tools:layout="@layout/fragment_notifications_viewer">
<argument
android:name="type"
app:argType="string"
app:nullable="false"
android:defaultValue="notif"/>
<argument
android:name="targetId"
android:defaultValue="0L"
app:argType="long" />
<action
android:id="@+id/action_notificationsViewerFragment_to_storyViewerFragment"
app:destination="@id/storyViewerFragment" />
</fragment>
<include app:graph="@navigation/profile_nav_graph" />
<action
@ -100,4 +81,23 @@
android:name="options"
app:argType="awais.instagrabber.repositories.requests.StoryViewerOptions" />
</fragment>
<fragment
android:id="@+id/notificationsViewer"
android:name="awais.instagrabber.fragments.NotificationsViewerFragment"
android:label="@string/title_notifications"
tools:layout="@layout/fragment_notifications_viewer">
<argument
android:name="type"
app:argType="string"
app:nullable="false"
android:defaultValue="notif"/>
<argument
android:name="targetId"
android:defaultValue="0L"
app:argType="long" />
<action
android:id="@+id/action_notifications_to_story"
app:destination="@id/storyViewerFragment" />
</fragment>
</navigation>

View File

@ -1 +0,0 @@
{}

View File

@ -1 +0,0 @@
{}