mirror of
https://github.com/KokaKiwi/BarInsta
synced 2024-11-22 22:57:29 +00:00
Merge branch 'master' into per-flavor-update-check
This commit is contained in:
commit
0c11053b93
@ -108,7 +108,7 @@ dependencies {
|
|||||||
def nav_version = '2.3.4'
|
def nav_version = '2.3.4'
|
||||||
def exoplayer_version = '2.13.2'
|
def exoplayer_version = '2.13.2'
|
||||||
|
|
||||||
implementation 'com.google.android.material:material:1.4.0-alpha01'
|
implementation 'com.google.android.material:material:1.4.0-alpha02'
|
||||||
|
|
||||||
implementation "com.google.android.exoplayer:exoplayer-core:$exoplayer_version"
|
implementation "com.google.android.exoplayer:exoplayer-core:$exoplayer_version"
|
||||||
implementation "com.google.android.exoplayer:exoplayer-dash:$exoplayer_version"
|
implementation "com.google.android.exoplayer:exoplayer-dash:$exoplayer_version"
|
||||||
|
@ -8,7 +8,6 @@ import android.content.ComponentName;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.ServiceConnection;
|
import android.content.ServiceConnection;
|
||||||
import android.content.res.TypedArray;
|
|
||||||
import android.database.MatrixCursor;
|
import android.database.MatrixCursor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
@ -24,6 +23,7 @@ import android.view.WindowManager;
|
|||||||
import android.widget.AutoCompleteTextView;
|
import android.widget.AutoCompleteTextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.annotation.IdRes;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.ActionBar;
|
import androidx.appcompat.app.ActionBar;
|
||||||
@ -47,15 +47,16 @@ import androidx.navigation.ui.NavigationUI;
|
|||||||
|
|
||||||
import com.google.android.material.appbar.AppBarLayout;
|
import com.google.android.material.appbar.AppBarLayout;
|
||||||
import com.google.android.material.appbar.CollapsingToolbarLayout;
|
import com.google.android.material.appbar.CollapsingToolbarLayout;
|
||||||
|
import com.google.android.material.badge.BadgeDrawable;
|
||||||
import com.google.android.material.behavior.HideBottomViewOnScrollBehavior;
|
import com.google.android.material.behavior.HideBottomViewOnScrollBehavior;
|
||||||
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.Iterators;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Collections;
|
||||||
import java.util.Deque;
|
import java.util.Deque;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import awais.instagrabber.BuildConfig;
|
import awais.instagrabber.BuildConfig;
|
||||||
@ -69,6 +70,7 @@ import awais.instagrabber.fragments.directmessages.DirectMessageInboxFragmentDir
|
|||||||
import awais.instagrabber.fragments.main.FeedFragment;
|
import awais.instagrabber.fragments.main.FeedFragment;
|
||||||
import awais.instagrabber.fragments.settings.PreferenceKeys;
|
import awais.instagrabber.fragments.settings.PreferenceKeys;
|
||||||
import awais.instagrabber.models.IntentModel;
|
import awais.instagrabber.models.IntentModel;
|
||||||
|
import awais.instagrabber.models.Tab;
|
||||||
import awais.instagrabber.models.enums.SuggestionType;
|
import awais.instagrabber.models.enums.SuggestionType;
|
||||||
import awais.instagrabber.repositories.responses.search.SearchItem;
|
import awais.instagrabber.repositories.responses.search.SearchItem;
|
||||||
import awais.instagrabber.repositories.responses.search.SearchResponse;
|
import awais.instagrabber.repositories.responses.search.SearchResponse;
|
||||||
@ -83,6 +85,7 @@ import awais.instagrabber.utils.TextUtils;
|
|||||||
import awais.instagrabber.utils.Utils;
|
import awais.instagrabber.utils.Utils;
|
||||||
import awais.instagrabber.utils.emoji.EmojiParser;
|
import awais.instagrabber.utils.emoji.EmojiParser;
|
||||||
import awais.instagrabber.viewmodels.AppStateViewModel;
|
import awais.instagrabber.viewmodels.AppStateViewModel;
|
||||||
|
import awais.instagrabber.viewmodels.DirectInboxViewModel;
|
||||||
import awais.instagrabber.webservices.SearchService;
|
import awais.instagrabber.webservices.SearchService;
|
||||||
import retrofit2.Call;
|
import retrofit2.Call;
|
||||||
import retrofit2.Callback;
|
import retrofit2.Callback;
|
||||||
@ -93,15 +96,8 @@ import static awais.instagrabber.utils.Utils.settingsHelper;
|
|||||||
|
|
||||||
public class MainActivity extends BaseLanguageActivity implements FragmentManager.OnBackStackChangedListener {
|
public class MainActivity extends BaseLanguageActivity implements FragmentManager.OnBackStackChangedListener {
|
||||||
private static final String TAG = "MainActivity";
|
private static final String TAG = "MainActivity";
|
||||||
|
|
||||||
private static final List<Integer> SHOW_BOTTOM_VIEW_DESTINATIONS = Arrays.asList(
|
|
||||||
R.id.directMessagesInboxFragment,
|
|
||||||
R.id.feedFragment,
|
|
||||||
R.id.profileFragment,
|
|
||||||
R.id.discoverFragment,
|
|
||||||
R.id.morePreferencesFragment);
|
|
||||||
private static final Map<Integer, Integer> NAV_TO_MENU_ID_MAP = new HashMap<>();
|
|
||||||
private static final String FIRST_FRAGMENT_GRAPH_INDEX_KEY = "firstFragmentGraphIndex";
|
private static final String FIRST_FRAGMENT_GRAPH_INDEX_KEY = "firstFragmentGraphIndex";
|
||||||
|
private static final String LAST_SELECT_NAV_MENU_ID = "lastSelectedNavMenuId";
|
||||||
|
|
||||||
private ActivityMainBinding binding;
|
private ActivityMainBinding binding;
|
||||||
private LiveData<NavController> currentNavControllerLiveData;
|
private LiveData<NavController> currentNavControllerLiveData;
|
||||||
@ -113,10 +109,13 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
|
|||||||
private boolean showSearch = true;
|
private boolean showSearch = true;
|
||||||
private Handler suggestionsFetchHandler;
|
private Handler suggestionsFetchHandler;
|
||||||
private int firstFragmentGraphIndex;
|
private int firstFragmentGraphIndex;
|
||||||
|
private int lastSelectedNavMenuId;
|
||||||
private boolean isActivityCheckerServiceBound = false;
|
private boolean isActivityCheckerServiceBound = false;
|
||||||
private boolean isBackStackEmpty = false;
|
private boolean isBackStackEmpty = false;
|
||||||
private boolean isLoggedIn;
|
private boolean isLoggedIn;
|
||||||
private HideBottomViewOnScrollBehavior<BottomNavigationView> behavior;
|
private HideBottomViewOnScrollBehavior<BottomNavigationView> behavior;
|
||||||
|
private List<Tab> currentTabs;
|
||||||
|
private List<Integer> showBottomViewDestinations = Collections.emptyList();
|
||||||
|
|
||||||
private final ServiceConnection serviceConnection = new ServiceConnection() {
|
private final ServiceConnection serviceConnection = new ServiceConnection() {
|
||||||
@Override
|
@Override
|
||||||
@ -132,14 +131,6 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static {
|
|
||||||
NAV_TO_MENU_ID_MAP.put(R.navigation.direct_messages_nav_graph, R.id.direct_messages_nav_graph);
|
|
||||||
NAV_TO_MENU_ID_MAP.put(R.navigation.feed_nav_graph, R.id.feed_nav_graph);
|
|
||||||
NAV_TO_MENU_ID_MAP.put(R.navigation.profile_nav_graph, R.id.profile_nav_graph);
|
|
||||||
NAV_TO_MENU_ID_MAP.put(R.navigation.discover_nav_graph, R.id.discover_nav_graph);
|
|
||||||
NAV_TO_MENU_ID_MAP.put(R.navigation.more_nav_graph, R.id.more_nav_graph);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(@Nullable final Bundle savedInstanceState) {
|
protected void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
@ -184,6 +175,7 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
|
|||||||
initEmojiCompat();
|
initEmojiCompat();
|
||||||
searchService = SearchService.getInstance();
|
searchService = SearchService.getInstance();
|
||||||
// initDmService();
|
// initDmService();
|
||||||
|
initDmUnreadCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initDmService() {
|
private void initDmService() {
|
||||||
@ -193,6 +185,16 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
|
|||||||
DMSyncAlarmReceiver.setAlarm(this);
|
DMSyncAlarmReceiver.setAlarm(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initDmUnreadCount() {
|
||||||
|
if (!isLoggedIn) return;
|
||||||
|
final DirectInboxViewModel directInboxViewModel = new ViewModelProvider(this).get(DirectInboxViewModel.class);
|
||||||
|
directInboxViewModel.getUnseenCount().observe(this, unseenCountResource -> {
|
||||||
|
if (unseenCountResource == null) return;
|
||||||
|
final Integer unseenCount = unseenCountResource.data;
|
||||||
|
setNavBarDMUnreadCountBadge(unseenCount == null ? 0 : unseenCount);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(final Menu menu) {
|
public boolean onCreateOptionsMenu(final Menu menu) {
|
||||||
getMenuInflater().inflate(R.menu.main_menu, menu);
|
getMenuInflater().inflate(R.menu.main_menu, menu);
|
||||||
@ -217,6 +219,7 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
|
|||||||
@Override
|
@Override
|
||||||
protected void onSaveInstanceState(@NonNull final Bundle outState) {
|
protected void onSaveInstanceState(@NonNull final Bundle outState) {
|
||||||
outState.putString(FIRST_FRAGMENT_GRAPH_INDEX_KEY, String.valueOf(firstFragmentGraphIndex));
|
outState.putString(FIRST_FRAGMENT_GRAPH_INDEX_KEY, String.valueOf(firstFragmentGraphIndex));
|
||||||
|
outState.putString(LAST_SELECT_NAV_MENU_ID, String.valueOf(binding.bottomNavView.getSelectedItemId()));
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,6 +232,12 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
|
|||||||
firstFragmentGraphIndex = Integer.parseInt(key);
|
firstFragmentGraphIndex = Integer.parseInt(key);
|
||||||
} catch (NumberFormatException ignored) { }
|
} catch (NumberFormatException ignored) { }
|
||||||
}
|
}
|
||||||
|
final String lastSelected = (String) savedInstanceState.get(LAST_SELECT_NAV_MENU_ID);
|
||||||
|
if (lastSelected != null) {
|
||||||
|
try {
|
||||||
|
lastSelectedNavMenuId = Integer.parseInt(lastSelected);
|
||||||
|
} catch (NumberFormatException ignored) { }
|
||||||
|
}
|
||||||
setupBottomNavigationBar(false);
|
setupBottomNavigationBar(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,11 +272,9 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
|
|||||||
final NavController navController = currentNavControllerLiveData.getValue();
|
final NavController navController = currentNavControllerLiveData.getValue();
|
||||||
if (navController != null) {
|
if (navController != null) {
|
||||||
@SuppressLint("RestrictedApi") final Deque<NavBackStackEntry> backStack = navController.getBackStack();
|
@SuppressLint("RestrictedApi") final Deque<NavBackStackEntry> backStack = navController.getBackStack();
|
||||||
if (backStack != null) {
|
|
||||||
currentNavControllerBackStack = backStack.size();
|
currentNavControllerBackStack = backStack.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (isTaskRoot() && isBackStackEmpty && currentNavControllerBackStack == 2) {
|
if (isTaskRoot() && isBackStackEmpty && currentNavControllerBackStack == 2) {
|
||||||
finishAfterTransition();
|
finishAfterTransition();
|
||||||
return;
|
return;
|
||||||
@ -318,7 +325,7 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
|
|||||||
final Bundle bundle = new Bundle();
|
final Bundle bundle = new Bundle();
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case TYPE_LOCATION:
|
case TYPE_LOCATION:
|
||||||
bundle.putLong("locationId", Long.valueOf(query));
|
bundle.putLong("locationId", Long.parseLong(query));
|
||||||
navController.navigate(R.id.action_global_locationFragment, bundle);
|
navController.navigate(R.id.action_global_locationFragment, bundle);
|
||||||
break;
|
break;
|
||||||
case TYPE_HASHTAG:
|
case TYPE_HASHTAG:
|
||||||
@ -368,14 +375,16 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
|
|||||||
cursor = null;
|
cursor = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final List<SearchItem> result = new ArrayList<SearchItem>();
|
final List<SearchItem> result = new ArrayList<>();
|
||||||
if (isLoggedIn) {
|
if (isLoggedIn) {
|
||||||
if (body.getList() != null) result.addAll(searchHash ? body.getList()
|
if (body.getList() != null) {
|
||||||
|
result.addAll(searchHash ? body.getList()
|
||||||
.stream()
|
.stream()
|
||||||
.filter(i -> i.getUser() == null)
|
.filter(i -> i.getUser() == null)
|
||||||
.collect(Collectors.toList()) : body.getList());
|
.collect(Collectors.toList())
|
||||||
|
: body.getList());
|
||||||
}
|
}
|
||||||
else {
|
} else {
|
||||||
if (body.getUsers() != null && !searchHash) result.addAll(body.getUsers());
|
if (body.getUsers() != null && !searchHash) result.addAll(body.getUsers());
|
||||||
if (body.getHashtags() != null) result.addAll(body.getHashtags());
|
if (body.getHashtags() != null) result.addAll(body.getHashtags());
|
||||||
if (body.getPlaces() != null) result.addAll(body.getPlaces());
|
if (body.getPlaces() != null) result.addAll(body.getPlaces());
|
||||||
@ -420,10 +429,11 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(@NonNull final Call<SearchResponse> call,
|
public void onFailure(@NonNull final Call<SearchResponse> call,
|
||||||
Throwable t) {
|
@NonNull Throwable t) {
|
||||||
if (!call.isCanceled() && t != null)
|
if (!call.isCanceled()) {
|
||||||
Log.e(TAG, "Exception on search:", t);
|
Log.e(TAG, "Exception on search:", t);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private final Runnable runnable = () -> {
|
private final Runnable runnable = () -> {
|
||||||
@ -474,36 +484,18 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupBottomNavigationBar(final boolean setDefaultFromSettings) {
|
private void setupBottomNavigationBar(final boolean setDefaultTabFromSettings) {
|
||||||
int main_nav_ids = R.array.main_nav_ids;
|
currentTabs = !isLoggedIn ? setupAnonBottomNav() : setupMainBottomNav();
|
||||||
if (!isLoggedIn) {
|
final List<Integer> mainNavList = currentTabs.stream()
|
||||||
main_nav_ids = R.array.logged_out_main_nav_ids;
|
.map(Tab::getNavigationResId)
|
||||||
final int selectedItemId = binding.bottomNavView.getSelectedItemId();
|
.collect(Collectors.toList());
|
||||||
binding.bottomNavView.getMenu().clear();
|
showBottomViewDestinations = currentTabs.stream()
|
||||||
binding.bottomNavView.inflateMenu(R.menu.logged_out_bottom_navigation_menu);
|
.map(Tab::getStartDestinationFragmentId)
|
||||||
if (selectedItemId == R.id.profile_nav_graph
|
.collect(Collectors.toList());
|
||||||
|| selectedItemId == R.id.more_nav_graph) {
|
if (setDefaultTabFromSettings) {
|
||||||
binding.bottomNavView.setSelectedItemId(selectedItemId);
|
setSelectedTab(currentTabs);
|
||||||
} else {
|
} else {
|
||||||
setBottomNavSelectedItem(R.navigation.profile_nav_graph);
|
binding.bottomNavView.setSelectedItemId(lastSelectedNavMenuId);
|
||||||
}
|
|
||||||
}
|
|
||||||
final List<Integer> mainNavList = getMainNavList(main_nav_ids);
|
|
||||||
if (setDefaultFromSettings) {
|
|
||||||
final String defaultTabResNameString = settingsHelper.getString(Constants.DEFAULT_TAB);
|
|
||||||
try {
|
|
||||||
int navId = 0;
|
|
||||||
if (!TextUtils.isEmpty(defaultTabResNameString)) {
|
|
||||||
navId = getResources().getIdentifier(defaultTabResNameString, "navigation", getPackageName());
|
|
||||||
}
|
|
||||||
final int defaultNavId = navId <= 0 ? R.navigation.profile_nav_graph
|
|
||||||
: navId;
|
|
||||||
final int index = mainNavList.indexOf(defaultNavId);
|
|
||||||
if (index >= 0) firstFragmentGraphIndex = index;
|
|
||||||
setBottomNavSelectedItem(defaultNavId);
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
Log.e(TAG, "Error parsing id", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
final LiveData<NavController> navControllerLiveData = setupWithNavController(
|
final LiveData<NavController> navControllerLiveData = setupWithNavController(
|
||||||
binding.bottomNavView,
|
binding.bottomNavView,
|
||||||
@ -526,27 +518,86 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setBottomNavSelectedItem(final int navId) {
|
private void setSelectedTab(final List<Tab> tabs) {
|
||||||
final Integer menuId = NAV_TO_MENU_ID_MAP.get(navId);
|
final String defaultTabResNameString = settingsHelper.getString(Constants.DEFAULT_TAB);
|
||||||
if (menuId != null) {
|
try {
|
||||||
binding.bottomNavView.setSelectedItemId(menuId);
|
int navId = 0;
|
||||||
|
if (!TextUtils.isEmpty(defaultTabResNameString)) {
|
||||||
|
navId = getResources().getIdentifier(defaultTabResNameString, "navigation", getPackageName());
|
||||||
|
}
|
||||||
|
final int navGraph = isLoggedIn ? R.navigation.feed_nav_graph
|
||||||
|
: R.navigation.profile_nav_graph;
|
||||||
|
final int defaultNavId = navId <= 0 ? navGraph : navId;
|
||||||
|
int index = Iterators.indexOf(tabs.iterator(), tab -> {
|
||||||
|
if (tab == null) return false;
|
||||||
|
return tab.getNavigationResId() == defaultNavId;
|
||||||
|
});
|
||||||
|
if (index < 0 || index >= tabs.size()) index = 0;
|
||||||
|
firstFragmentGraphIndex = index;
|
||||||
|
setBottomNavSelectedTab(tabs.get(index));
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error parsing id", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
private List<Tab> setupAnonBottomNav() {
|
||||||
private List<Integer> getMainNavList(final int main_nav_ids) {
|
final int selectedItemId = binding.bottomNavView.getSelectedItemId();
|
||||||
final TypedArray navIds = getResources().obtainTypedArray(main_nav_ids);
|
final Tab profileTab = new Tab(R.drawable.ic_person_24,
|
||||||
final List<Integer> mainNavList = new ArrayList<>(navIds.length());
|
getString(R.string.profile),
|
||||||
final int length = navIds.length();
|
false,
|
||||||
for (int i = 0; i < length; i++) {
|
"profile_nav_graph",
|
||||||
final int resourceId = navIds.getResourceId(i, -1);
|
R.navigation.profile_nav_graph,
|
||||||
if (resourceId < 0) continue;
|
R.id.profile_nav_graph,
|
||||||
mainNavList.add(resourceId);
|
R.id.profileFragment);
|
||||||
|
final Tab moreTab = new Tab(R.drawable.ic_more_horiz_24,
|
||||||
|
getString(R.string.more),
|
||||||
|
false,
|
||||||
|
"more_nav_graph",
|
||||||
|
R.navigation.more_nav_graph,
|
||||||
|
R.id.more_nav_graph,
|
||||||
|
R.id.morePreferencesFragment);
|
||||||
|
final Menu menu = binding.bottomNavView.getMenu();
|
||||||
|
menu.clear();
|
||||||
|
menu.add(0, profileTab.getNavigationRootId(), 0, profileTab.getTitle()).setIcon(profileTab.getIconResId());
|
||||||
|
menu.add(0, moreTab.getNavigationRootId(), 0, moreTab.getTitle()).setIcon(moreTab.getIconResId());
|
||||||
|
if (selectedItemId != R.id.profile_nav_graph && selectedItemId != R.id.more_nav_graph) {
|
||||||
|
setBottomNavSelectedTab(profileTab);
|
||||||
}
|
}
|
||||||
navIds.recycle();
|
return ImmutableList.of(profileTab, moreTab);
|
||||||
return mainNavList;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<Tab> setupMainBottomNav() {
|
||||||
|
final Menu menu = binding.bottomNavView.getMenu();
|
||||||
|
menu.clear();
|
||||||
|
final List<Tab> navTabList = Utils.getNavTabList(this).first;
|
||||||
|
for (final Tab tab : navTabList) {
|
||||||
|
menu.add(0, tab.getNavigationRootId(), 0, tab.getTitle()).setIcon(tab.getIconResId());
|
||||||
|
}
|
||||||
|
return navTabList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setBottomNavSelectedTab(@NonNull final Tab tab) {
|
||||||
|
binding.bottomNavView.setSelectedItemId(tab.getNavigationRootId());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setBottomNavSelectedTab(@SuppressWarnings("SameParameterValue") @IdRes final int navGraphRootId) {
|
||||||
|
binding.bottomNavView.setSelectedItemId(navGraphRootId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// @NonNull
|
||||||
|
// private List<Integer> getMainNavList(final int main_nav_ids) {
|
||||||
|
// final TypedArray navIds = getResources().obtainTypedArray(main_nav_ids);
|
||||||
|
// final List<Integer> mainNavList = new ArrayList<>(navIds.length());
|
||||||
|
// final int length = navIds.length();
|
||||||
|
// for (int i = 0; i < length; i++) {
|
||||||
|
// final int resourceId = navIds.getResourceId(i, -1);
|
||||||
|
// if (resourceId < 0) continue;
|
||||||
|
// mainNavList.add(resourceId);
|
||||||
|
// }
|
||||||
|
// navIds.recycle();
|
||||||
|
// return mainNavList;
|
||||||
|
// }
|
||||||
|
|
||||||
private void setupNavigation(final Toolbar toolbar, final NavController navController) {
|
private void setupNavigation(final Toolbar toolbar, final NavController navController) {
|
||||||
if (navController == null) return;
|
if (navController == null) return;
|
||||||
NavigationUI.setupWithNavController(toolbar, navController);
|
NavigationUI.setupWithNavController(toolbar, navController);
|
||||||
@ -564,7 +615,7 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
|
|||||||
final int destinationId = destination.getId();
|
final int destinationId = destination.getId();
|
||||||
@SuppressLint("RestrictedApi") final Deque<NavBackStackEntry> backStack = navController.getBackStack();
|
@SuppressLint("RestrictedApi") final Deque<NavBackStackEntry> backStack = navController.getBackStack();
|
||||||
setupMenu(backStack.size(), destinationId);
|
setupMenu(backStack.size(), destinationId);
|
||||||
final boolean contains = SHOW_BOTTOM_VIEW_DESTINATIONS.contains(destinationId);
|
final boolean contains = showBottomViewDestinations.contains(destinationId);
|
||||||
binding.bottomNavView.setVisibility(contains ? View.VISIBLE : View.GONE);
|
binding.bottomNavView.setVisibility(contains ? View.VISIBLE : View.GONE);
|
||||||
if (contains && behavior != null) {
|
if (contains && behavior != null) {
|
||||||
behavior.slideUp(binding.bottomNavView);
|
behavior.slideUp(binding.bottomNavView);
|
||||||
@ -674,7 +725,7 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
|
|||||||
});
|
});
|
||||||
final int selectedItemId = binding.bottomNavView.getSelectedItemId();
|
final int selectedItemId = binding.bottomNavView.getSelectedItemId();
|
||||||
if (selectedItemId != R.navigation.direct_messages_nav_graph) {
|
if (selectedItemId != R.navigation.direct_messages_nav_graph) {
|
||||||
setBottomNavSelectedItem(R.navigation.direct_messages_nav_graph);
|
setBottomNavSelectedTab(R.id.direct_messages_nav_graph);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -746,7 +797,7 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
|
|||||||
final NavController navController = currentNavControllerLiveData.getValue();
|
final NavController navController = currentNavControllerLiveData.getValue();
|
||||||
if (navController == null) return;
|
if (navController == null) return;
|
||||||
final Bundle bundle = new Bundle();
|
final Bundle bundle = new Bundle();
|
||||||
bundle.putLong("locationId", Long.valueOf(locationId));
|
bundle.putLong("locationId", Long.parseLong(locationId));
|
||||||
navController.navigate(R.id.action_global_locationFragment, bundle);
|
navController.navigate(R.id.action_global_locationFragment, bundle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -853,4 +904,27 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
|
|||||||
public Toolbar getToolbar() {
|
public Toolbar getToolbar() {
|
||||||
return binding.toolbar;
|
return binding.toolbar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Tab> getCurrentTabs() {
|
||||||
|
return currentTabs;
|
||||||
|
}
|
||||||
|
|
||||||
|
// public boolean isNavRootInCurrentTabs(@IdRes final int navRootId) {
|
||||||
|
// return showBottomViewDestinations.stream().anyMatch(id -> id == navRootId);
|
||||||
|
// }
|
||||||
|
|
||||||
|
private void setNavBarDMUnreadCountBadge(final int unseenCount) {
|
||||||
|
final BadgeDrawable badge = binding.bottomNavView.getOrCreateBadge(R.id.direct_messages_nav_graph);
|
||||||
|
if (badge == null) return;
|
||||||
|
if (unseenCount == 0) {
|
||||||
|
badge.setVisible(false);
|
||||||
|
badge.clearNumber();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (badge.getVerticalOffset() != 10) {
|
||||||
|
badge.setVerticalOffset(10);
|
||||||
|
}
|
||||||
|
badge.setNumber(unseenCount);
|
||||||
|
badge.setVisible(true);
|
||||||
|
}
|
||||||
}
|
}
|
@ -17,6 +17,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
import awais.instagrabber.adapters.viewholder.directmessages.DirectItemActionLogViewHolder;
|
import awais.instagrabber.adapters.viewholder.directmessages.DirectItemActionLogViewHolder;
|
||||||
import awais.instagrabber.adapters.viewholder.directmessages.DirectItemAnimatedMediaViewHolder;
|
import awais.instagrabber.adapters.viewholder.directmessages.DirectItemAnimatedMediaViewHolder;
|
||||||
@ -34,6 +35,7 @@ import awais.instagrabber.adapters.viewholder.directmessages.DirectItemTextViewH
|
|||||||
import awais.instagrabber.adapters.viewholder.directmessages.DirectItemVideoCallEventViewHolder;
|
import awais.instagrabber.adapters.viewholder.directmessages.DirectItemVideoCallEventViewHolder;
|
||||||
import awais.instagrabber.adapters.viewholder.directmessages.DirectItemViewHolder;
|
import awais.instagrabber.adapters.viewholder.directmessages.DirectItemViewHolder;
|
||||||
import awais.instagrabber.adapters.viewholder.directmessages.DirectItemVoiceMediaViewHolder;
|
import awais.instagrabber.adapters.viewholder.directmessages.DirectItemVoiceMediaViewHolder;
|
||||||
|
import awais.instagrabber.adapters.viewholder.directmessages.DirectItemXmaViewHolder;
|
||||||
import awais.instagrabber.customviews.emoji.Emoji;
|
import awais.instagrabber.customviews.emoji.Emoji;
|
||||||
import awais.instagrabber.databinding.LayoutDmActionLogBinding;
|
import awais.instagrabber.databinding.LayoutDmActionLogBinding;
|
||||||
import awais.instagrabber.databinding.LayoutDmAnimatedMediaBinding;
|
import awais.instagrabber.databinding.LayoutDmAnimatedMediaBinding;
|
||||||
@ -207,6 +209,11 @@ public final class DirectItemsAdapter extends RecyclerView.Adapter<RecyclerView.
|
|||||||
final LayoutDmRavenMediaBinding binding = LayoutDmRavenMediaBinding.inflate(layoutInflater, baseBinding.message, false);
|
final LayoutDmRavenMediaBinding binding = LayoutDmRavenMediaBinding.inflate(layoutInflater, baseBinding.message, false);
|
||||||
return new DirectItemRavenMediaViewHolder(baseBinding, binding, currentUser, thread, callback);
|
return new DirectItemRavenMediaViewHolder(baseBinding, binding, currentUser, thread, callback);
|
||||||
}
|
}
|
||||||
|
case XMA: {
|
||||||
|
final LayoutDmAnimatedMediaBinding binding = LayoutDmAnimatedMediaBinding.inflate(layoutInflater, baseBinding.message, false);
|
||||||
|
return new DirectItemXmaViewHolder(baseBinding, binding, currentUser, thread, callback);
|
||||||
|
}
|
||||||
|
case UNKNOWN:
|
||||||
default: {
|
default: {
|
||||||
final LayoutDmTextBinding binding = LayoutDmTextBinding.inflate(layoutInflater, baseBinding.message, false);
|
final LayoutDmTextBinding binding = LayoutDmTextBinding.inflate(layoutInflater, baseBinding.message, false);
|
||||||
return new DirectItemDefaultViewHolder(baseBinding, binding, currentUser, thread, callback);
|
return new DirectItemDefaultViewHolder(baseBinding, binding, currentUser, thread, callback);
|
||||||
@ -240,7 +247,11 @@ public final class DirectItemsAdapter extends RecyclerView.Adapter<RecyclerView.
|
|||||||
if (itemOrHeader.isHeader()) {
|
if (itemOrHeader.isHeader()) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return itemOrHeader.item.getItemType().getId();
|
final DirectItemType itemType = itemOrHeader.item.getItemType();
|
||||||
|
if (itemType == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return itemType.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -394,7 +405,7 @@ public final class DirectItemsAdapter extends RecyclerView.Adapter<RecyclerView.
|
|||||||
|
|
||||||
void onReactionClick(DirectItem item, int position);
|
void onReactionClick(DirectItem item, int position);
|
||||||
|
|
||||||
void onOptionSelect(DirectItem item, @IdRes int itemId);
|
void onOptionSelect(DirectItem item, @IdRes int itemId, final Function<DirectItem, Void> callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface DirectItemInternalLongClickListener {
|
public interface DirectItemInternalLongClickListener {
|
||||||
|
@ -10,7 +10,6 @@ import android.view.ViewGroup;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.cursoradapter.widget.CursorAdapter;
|
import androidx.cursoradapter.widget.CursorAdapter;
|
||||||
|
|
||||||
import awais.instagrabber.R;
|
|
||||||
import awais.instagrabber.databinding.ItemSuggestionBinding;
|
import awais.instagrabber.databinding.ItemSuggestionBinding;
|
||||||
import awais.instagrabber.models.enums.SuggestionType;
|
import awais.instagrabber.models.enums.SuggestionType;
|
||||||
|
|
||||||
|
156
app/src/main/java/awais/instagrabber/adapters/TabsAdapter.java
Normal file
156
app/src/main/java/awais/instagrabber/adapters/TabsAdapter.java
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
package awais.instagrabber.adapters;
|
||||||
|
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.StringRes;
|
||||||
|
import androidx.recyclerview.widget.DiffUtil;
|
||||||
|
import androidx.recyclerview.widget.ListAdapter;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import awais.instagrabber.R;
|
||||||
|
import awais.instagrabber.adapters.viewholder.TabViewHolder;
|
||||||
|
import awais.instagrabber.databinding.ItemFavSectionHeaderBinding;
|
||||||
|
import awais.instagrabber.databinding.ItemTabOrderPrefBinding;
|
||||||
|
import awais.instagrabber.models.Tab;
|
||||||
|
import awais.instagrabber.utils.Utils;
|
||||||
|
|
||||||
|
public class TabsAdapter extends ListAdapter<TabsAdapter.TabOrHeader, RecyclerView.ViewHolder> {
|
||||||
|
private static final DiffUtil.ItemCallback<TabOrHeader> DIFF_CALLBACK = new DiffUtil.ItemCallback<TabOrHeader>() {
|
||||||
|
@Override
|
||||||
|
public boolean areItemsTheSame(@NonNull final TabOrHeader oldItem, @NonNull final TabOrHeader newItem) {
|
||||||
|
if (oldItem.isHeader() && newItem.isHeader()) {
|
||||||
|
return oldItem.header == newItem.header;
|
||||||
|
}
|
||||||
|
if (!oldItem.isHeader() && !newItem.isHeader()) {
|
||||||
|
final Tab oldTab = oldItem.tab;
|
||||||
|
final Tab newTab = newItem.tab;
|
||||||
|
return oldTab.getIconResId() == newTab.getIconResId()
|
||||||
|
&& Objects.equals(oldTab.getTitle(), newTab.getTitle());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean areContentsTheSame(@NonNull final TabOrHeader oldItem, @NonNull final TabOrHeader newItem) {
|
||||||
|
if (oldItem.isHeader() && newItem.isHeader()) {
|
||||||
|
return oldItem.header == newItem.header;
|
||||||
|
}
|
||||||
|
if (!oldItem.isHeader() && !newItem.isHeader()) {
|
||||||
|
final Tab oldTab = oldItem.tab;
|
||||||
|
final Tab newTab = newItem.tab;
|
||||||
|
return oldTab.getIconResId() == newTab.getIconResId()
|
||||||
|
&& Objects.equals(oldTab.getTitle(), newTab.getTitle());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final TabAdapterCallback tabAdapterCallback;
|
||||||
|
|
||||||
|
private List<Tab> current = new ArrayList<>();
|
||||||
|
private List<Tab> others = new ArrayList<>();
|
||||||
|
|
||||||
|
public TabsAdapter(@NonNull final TabAdapterCallback tabAdapterCallback) {
|
||||||
|
super(DIFF_CALLBACK);
|
||||||
|
this.tabAdapterCallback = tabAdapterCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) {
|
||||||
|
final LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
|
||||||
|
if (viewType == 1) {
|
||||||
|
final ItemTabOrderPrefBinding binding = ItemTabOrderPrefBinding.inflate(layoutInflater, parent, false);
|
||||||
|
return new TabViewHolder(binding, tabAdapterCallback);
|
||||||
|
}
|
||||||
|
final ItemFavSectionHeaderBinding headerBinding = ItemFavSectionHeaderBinding.inflate(layoutInflater, parent, false);
|
||||||
|
return new DirectUsersAdapter.HeaderViewHolder(headerBinding);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, final int position) {
|
||||||
|
if (holder instanceof DirectUsersAdapter.HeaderViewHolder) {
|
||||||
|
((DirectUsersAdapter.HeaderViewHolder) holder).bind(R.string.other_tabs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (holder instanceof TabViewHolder) {
|
||||||
|
final Tab tab = getItem(position).tab;
|
||||||
|
((TabViewHolder) holder).bind(tab, others.contains(tab), current.size() == 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemViewType(final int position) {
|
||||||
|
return getItem(position).isHeader() ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void submitList(final List<Tab> current, final List<Tab> others, final Runnable commitCallback) {
|
||||||
|
final ImmutableList.Builder<TabOrHeader> builder = ImmutableList.builder();
|
||||||
|
if (current != null) {
|
||||||
|
builder.addAll(current.stream()
|
||||||
|
.map(TabOrHeader::new)
|
||||||
|
.collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
builder.add(new TabOrHeader(R.string.other_tabs));
|
||||||
|
if (others != null) {
|
||||||
|
builder.addAll(others.stream()
|
||||||
|
.map(TabOrHeader::new)
|
||||||
|
.collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
// Mutable non-null copies
|
||||||
|
this.current = current != null ? new ArrayList<>(current) : new ArrayList<>();
|
||||||
|
this.others = others != null ? new ArrayList<>(others) : new ArrayList<>();
|
||||||
|
submitList(builder.build(), commitCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void submitList(final List<Tab> current, final List<Tab> others) {
|
||||||
|
submitList(current, others, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void moveItem(final int from, final int to) {
|
||||||
|
final List<Tab> currentCopy = new ArrayList<>(current);
|
||||||
|
Utils.moveItem(from, to, currentCopy);
|
||||||
|
submitList(currentCopy, others);
|
||||||
|
tabAdapterCallback.onOrderChange(currentCopy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCurrentCount() {
|
||||||
|
return current.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class TabOrHeader {
|
||||||
|
Tab tab;
|
||||||
|
int header;
|
||||||
|
|
||||||
|
public TabOrHeader(final Tab tab) {
|
||||||
|
this.tab = tab;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TabOrHeader(@StringRes final int header) {
|
||||||
|
this.header = header;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isHeader() {
|
||||||
|
return header != 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface TabAdapterCallback {
|
||||||
|
void onStartDrag(TabViewHolder viewHolder);
|
||||||
|
|
||||||
|
void onOrderChange(List<Tab> newOrderTabs);
|
||||||
|
|
||||||
|
void onAdd(Tab tab);
|
||||||
|
|
||||||
|
void onRemove(Tab tab);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,88 @@
|
|||||||
|
package awais.instagrabber.adapters.viewholder;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.res.ColorStateList;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
import androidx.core.widget.ImageViewCompat;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.google.android.material.color.MaterialColors;
|
||||||
|
|
||||||
|
import awais.instagrabber.R;
|
||||||
|
import awais.instagrabber.adapters.TabsAdapter;
|
||||||
|
import awais.instagrabber.databinding.ItemTabOrderPrefBinding;
|
||||||
|
import awais.instagrabber.models.Tab;
|
||||||
|
|
||||||
|
public class TabViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
private final ItemTabOrderPrefBinding binding;
|
||||||
|
private final TabsAdapter.TabAdapterCallback tabAdapterCallback;
|
||||||
|
private final int highlightColor;
|
||||||
|
private final Drawable originalBgColor;
|
||||||
|
|
||||||
|
private boolean draggable = true;
|
||||||
|
|
||||||
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
|
public TabViewHolder(@NonNull final ItemTabOrderPrefBinding binding,
|
||||||
|
@NonNull final TabsAdapter.TabAdapterCallback tabAdapterCallback) {
|
||||||
|
super(binding.getRoot());
|
||||||
|
this.binding = binding;
|
||||||
|
this.tabAdapterCallback = tabAdapterCallback;
|
||||||
|
highlightColor = MaterialColors.getColor(itemView.getContext(), R.attr.colorControlHighlight, 0);
|
||||||
|
originalBgColor = itemView.getBackground();
|
||||||
|
binding.handle.setOnTouchListener((v, event) -> {
|
||||||
|
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
|
||||||
|
tabAdapterCallback.onStartDrag(this);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void bind(@NonNull final Tab tab,
|
||||||
|
final boolean isInOthers,
|
||||||
|
final boolean isCurrentFull) {
|
||||||
|
draggable = !isInOthers;
|
||||||
|
binding.icon.setImageResource(tab.getIconResId());
|
||||||
|
binding.title.setText(tab.getTitle());
|
||||||
|
binding.handle.setVisibility(isInOthers ? View.GONE : View.VISIBLE);
|
||||||
|
binding.addRemove.setImageResource(isInOthers ? R.drawable.ic_round_add_circle_24
|
||||||
|
: R.drawable.ic_round_remove_circle_24);
|
||||||
|
final ColorStateList tintList = ColorStateList.valueOf(ContextCompat.getColor(
|
||||||
|
itemView.getContext(),
|
||||||
|
isInOthers ? R.color.green_500
|
||||||
|
: R.color.red_500));
|
||||||
|
ImageViewCompat.setImageTintList(binding.addRemove, tintList);
|
||||||
|
binding.addRemove.setOnClickListener(v -> {
|
||||||
|
if (isInOthers) {
|
||||||
|
tabAdapterCallback.onAdd(tab);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tabAdapterCallback.onRemove(tab);
|
||||||
|
});
|
||||||
|
final boolean enabled = tab.isRemovable()
|
||||||
|
&& !(isInOthers && isCurrentFull); // All slots are full in current
|
||||||
|
binding.addRemove.setEnabled(enabled);
|
||||||
|
binding.addRemove.setAlpha(enabled ? 1 : 0.5F);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDraggable() {
|
||||||
|
return draggable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDragging(final boolean isDragging) {
|
||||||
|
if (isDragging) {
|
||||||
|
if (highlightColor != 0) {
|
||||||
|
itemView.setBackgroundColor(highlightColor);
|
||||||
|
} else {
|
||||||
|
itemView.setAlpha(0.5F);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
itemView.setAlpha(1);
|
||||||
|
itemView.setBackground(originalBgColor);
|
||||||
|
}
|
||||||
|
}
|
@ -8,8 +8,13 @@ import androidx.core.util.Pair;
|
|||||||
import androidx.recyclerview.widget.ItemTouchHelper;
|
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||||
|
|
||||||
import com.facebook.drawee.backends.pipeline.Fresco;
|
import com.facebook.drawee.backends.pipeline.Fresco;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import awais.instagrabber.R;
|
||||||
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
|
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
|
||||||
|
import awais.instagrabber.customviews.DirectItemContextMenu;
|
||||||
import awais.instagrabber.databinding.LayoutDmAnimatedMediaBinding;
|
import awais.instagrabber.databinding.LayoutDmAnimatedMediaBinding;
|
||||||
import awais.instagrabber.databinding.LayoutDmBaseBinding;
|
import awais.instagrabber.databinding.LayoutDmBaseBinding;
|
||||||
import awais.instagrabber.repositories.responses.AnimatedMediaFixedHeight;
|
import awais.instagrabber.repositories.responses.AnimatedMediaFixedHeight;
|
||||||
@ -19,6 +24,7 @@ import awais.instagrabber.repositories.responses.directmessages.DirectItem;
|
|||||||
import awais.instagrabber.repositories.responses.directmessages.DirectItemAnimatedMedia;
|
import awais.instagrabber.repositories.responses.directmessages.DirectItemAnimatedMedia;
|
||||||
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
|
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
|
||||||
import awais.instagrabber.utils.NumberUtils;
|
import awais.instagrabber.utils.NumberUtils;
|
||||||
|
import awais.instagrabber.utils.Utils;
|
||||||
|
|
||||||
public class DirectItemAnimatedMediaViewHolder extends DirectItemViewHolder {
|
public class DirectItemAnimatedMediaViewHolder extends DirectItemViewHolder {
|
||||||
|
|
||||||
@ -65,4 +71,14 @@ public class DirectItemAnimatedMediaViewHolder extends DirectItemViewHolder {
|
|||||||
public int getSwipeDirection() {
|
public int getSwipeDirection() {
|
||||||
return ItemTouchHelper.ACTION_STATE_IDLE;
|
return ItemTouchHelper.ACTION_STATE_IDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<DirectItemContextMenu.MenuItem> getLongClickOptions() {
|
||||||
|
return ImmutableList.of(
|
||||||
|
new DirectItemContextMenu.MenuItem(R.id.detail, R.string.dms_inbox_giphy, item -> {
|
||||||
|
Utils.openURL(itemView.getContext(), "https://giphy.com/gifs/" + item.getAnimatedMedia().getId());
|
||||||
|
return null;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ public class DirectItemDefaultViewHolder extends DirectItemViewHolder {
|
|||||||
final DirectItemCallback callback) {
|
final DirectItemCallback callback) {
|
||||||
super(baseBinding, currentUser, thread, callback);
|
super(baseBinding, currentUser, thread, callback);
|
||||||
this.binding = binding;
|
this.binding = binding;
|
||||||
|
setItemView(binding.getRoot());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -32,6 +33,11 @@ public class DirectItemDefaultViewHolder extends DirectItemViewHolder {
|
|||||||
binding.tvMessage.setText(context.getText(R.string.dms_inbox_raven_message_unknown));
|
binding.tvMessage.setText(context.getText(R.string.dms_inbox_raven_message_unknown));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean showBackground() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean allowLongClick() {
|
protected boolean allowLongClick() {
|
||||||
return false;
|
return false;
|
||||||
|
@ -5,7 +5,13 @@ import android.view.ViewGroup;
|
|||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import awais.instagrabber.R;
|
||||||
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
|
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
|
||||||
|
import awais.instagrabber.customviews.DirectItemContextMenu;
|
||||||
import awais.instagrabber.databinding.LayoutDmBaseBinding;
|
import awais.instagrabber.databinding.LayoutDmBaseBinding;
|
||||||
import awais.instagrabber.databinding.LayoutDmLinkBinding;
|
import awais.instagrabber.databinding.LayoutDmLinkBinding;
|
||||||
import awais.instagrabber.repositories.responses.User;
|
import awais.instagrabber.repositories.responses.User;
|
||||||
@ -14,6 +20,7 @@ import awais.instagrabber.repositories.responses.directmessages.DirectItemLink;
|
|||||||
import awais.instagrabber.repositories.responses.directmessages.DirectItemLinkContext;
|
import awais.instagrabber.repositories.responses.directmessages.DirectItemLinkContext;
|
||||||
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
|
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
|
||||||
import awais.instagrabber.utils.TextUtils;
|
import awais.instagrabber.utils.TextUtils;
|
||||||
|
import awais.instagrabber.utils.Utils;
|
||||||
|
|
||||||
public class DirectItemLinkViewHolder extends DirectItemViewHolder {
|
public class DirectItemLinkViewHolder extends DirectItemViewHolder {
|
||||||
|
|
||||||
@ -80,4 +87,16 @@ public class DirectItemLinkViewHolder extends DirectItemViewHolder {
|
|||||||
protected boolean showBackground() {
|
protected boolean showBackground() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<DirectItemContextMenu.MenuItem> getLongClickOptions() {
|
||||||
|
return ImmutableList.of(
|
||||||
|
new DirectItemContextMenu.MenuItem(R.id.copy, R.string.copy, item -> {
|
||||||
|
final DirectItemLink link = item.getLink();
|
||||||
|
if (link == null || TextUtils.isEmpty(link.getText())) return null;
|
||||||
|
Utils.copyText(itemView.getContext(), link.getText());
|
||||||
|
return null;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,11 +12,14 @@ import androidx.recyclerview.widget.ItemTouchHelper;
|
|||||||
import com.facebook.drawee.drawable.ScalingUtils;
|
import com.facebook.drawee.drawable.ScalingUtils;
|
||||||
import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder;
|
import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder;
|
||||||
import com.facebook.drawee.generic.RoundingParams;
|
import com.facebook.drawee.generic.RoundingParams;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import awais.instagrabber.R;
|
import awais.instagrabber.R;
|
||||||
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
|
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
|
||||||
|
import awais.instagrabber.customviews.DirectItemContextMenu;
|
||||||
import awais.instagrabber.databinding.LayoutDmBaseBinding;
|
import awais.instagrabber.databinding.LayoutDmBaseBinding;
|
||||||
import awais.instagrabber.databinding.LayoutDmMediaShareBinding;
|
import awais.instagrabber.databinding.LayoutDmMediaShareBinding;
|
||||||
import awais.instagrabber.models.enums.DirectItemType;
|
import awais.instagrabber.models.enums.DirectItemType;
|
||||||
@ -30,6 +33,7 @@ import awais.instagrabber.repositories.responses.directmessages.DirectItemFelixS
|
|||||||
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
|
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
|
||||||
import awais.instagrabber.utils.NumberUtils;
|
import awais.instagrabber.utils.NumberUtils;
|
||||||
import awais.instagrabber.utils.ResponseBodyUtils;
|
import awais.instagrabber.utils.ResponseBodyUtils;
|
||||||
|
import awais.instagrabber.utils.Utils;
|
||||||
|
|
||||||
public class DirectItemMediaShareViewHolder extends DirectItemViewHolder {
|
public class DirectItemMediaShareViewHolder extends DirectItemViewHolder {
|
||||||
private static final String TAG = DirectItemMediaShareViewHolder.class.getSimpleName();
|
private static final String TAG = DirectItemMediaShareViewHolder.class.getSimpleName();
|
||||||
@ -38,6 +42,7 @@ public class DirectItemMediaShareViewHolder extends DirectItemViewHolder {
|
|||||||
private final RoundingParams incomingRoundingParams;
|
private final RoundingParams incomingRoundingParams;
|
||||||
private final RoundingParams outgoingRoundingParams;
|
private final RoundingParams outgoingRoundingParams;
|
||||||
private DirectItemType itemType;
|
private DirectItemType itemType;
|
||||||
|
private Caption caption;
|
||||||
|
|
||||||
public DirectItemMediaShareViewHolder(@NonNull final LayoutDmBaseBinding baseBinding,
|
public DirectItemMediaShareViewHolder(@NonNull final LayoutDmBaseBinding baseBinding,
|
||||||
@NonNull final LayoutDmMediaShareBinding binding,
|
@NonNull final LayoutDmMediaShareBinding binding,
|
||||||
@ -113,7 +118,7 @@ public class DirectItemMediaShareViewHolder extends DirectItemViewHolder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setupCaption(@NonNull final Media media) {
|
private void setupCaption(@NonNull final Media media) {
|
||||||
final Caption caption = media.getCaption();
|
caption = media.getCaption();
|
||||||
if (caption != null) {
|
if (caption != null) {
|
||||||
binding.caption.setVisibility(View.VISIBLE);
|
binding.caption.setVisibility(View.VISIBLE);
|
||||||
binding.caption.setText(caption.getText());
|
binding.caption.setText(caption.getText());
|
||||||
@ -177,4 +182,16 @@ public class DirectItemMediaShareViewHolder extends DirectItemViewHolder {
|
|||||||
}
|
}
|
||||||
return super.getSwipeDirection();
|
return super.getSwipeDirection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<DirectItemContextMenu.MenuItem> getLongClickOptions() {
|
||||||
|
final ImmutableList.Builder<DirectItemContextMenu.MenuItem> builder = ImmutableList.builder();
|
||||||
|
if (caption != null && !TextUtils.isEmpty(caption.getText())) {
|
||||||
|
builder.add(new DirectItemContextMenu.MenuItem(R.id.copy, R.string.copy_caption, item -> {
|
||||||
|
Utils.copyText(itemView.getContext(), caption.getText());
|
||||||
|
return null;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,6 @@ import awais.instagrabber.databinding.LayoutDmBaseBinding;
|
|||||||
import awais.instagrabber.databinding.LayoutDmRavenMediaBinding;
|
import awais.instagrabber.databinding.LayoutDmRavenMediaBinding;
|
||||||
import awais.instagrabber.models.enums.MediaItemType;
|
import awais.instagrabber.models.enums.MediaItemType;
|
||||||
import awais.instagrabber.models.enums.RavenMediaViewMode;
|
import awais.instagrabber.models.enums.RavenMediaViewMode;
|
||||||
import awais.instagrabber.repositories.responses.ImageVersions2;
|
|
||||||
import awais.instagrabber.repositories.responses.Media;
|
import awais.instagrabber.repositories.responses.Media;
|
||||||
import awais.instagrabber.repositories.responses.User;
|
import awais.instagrabber.repositories.responses.User;
|
||||||
import awais.instagrabber.repositories.responses.directmessages.DirectItem;
|
import awais.instagrabber.repositories.responses.directmessages.DirectItem;
|
||||||
|
@ -8,13 +8,16 @@ import androidx.constraintlayout.widget.ConstraintLayout;
|
|||||||
|
|
||||||
import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder;
|
import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder;
|
||||||
import com.facebook.drawee.generic.RoundingParams;
|
import com.facebook.drawee.generic.RoundingParams;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import awais.instagrabber.R;
|
import awais.instagrabber.R;
|
||||||
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
|
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
|
||||||
|
import awais.instagrabber.customviews.DirectItemContextMenu;
|
||||||
import awais.instagrabber.databinding.LayoutDmBaseBinding;
|
import awais.instagrabber.databinding.LayoutDmBaseBinding;
|
||||||
import awais.instagrabber.databinding.LayoutDmReelShareBinding;
|
import awais.instagrabber.databinding.LayoutDmReelShareBinding;
|
||||||
import awais.instagrabber.models.enums.MediaItemType;
|
import awais.instagrabber.models.enums.MediaItemType;
|
||||||
import awais.instagrabber.repositories.responses.ImageVersions2;
|
|
||||||
import awais.instagrabber.repositories.responses.Media;
|
import awais.instagrabber.repositories.responses.Media;
|
||||||
import awais.instagrabber.repositories.responses.User;
|
import awais.instagrabber.repositories.responses.User;
|
||||||
import awais.instagrabber.repositories.responses.directmessages.DirectItem;
|
import awais.instagrabber.repositories.responses.directmessages.DirectItem;
|
||||||
@ -22,10 +25,12 @@ import awais.instagrabber.repositories.responses.directmessages.DirectItemReelSh
|
|||||||
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
|
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
|
||||||
import awais.instagrabber.utils.ResponseBodyUtils;
|
import awais.instagrabber.utils.ResponseBodyUtils;
|
||||||
import awais.instagrabber.utils.TextUtils;
|
import awais.instagrabber.utils.TextUtils;
|
||||||
|
import awais.instagrabber.utils.Utils;
|
||||||
|
|
||||||
public class DirectItemReelShareViewHolder extends DirectItemViewHolder {
|
public class DirectItemReelShareViewHolder extends DirectItemViewHolder {
|
||||||
|
|
||||||
private final LayoutDmReelShareBinding binding;
|
private final LayoutDmReelShareBinding binding;
|
||||||
|
private String type;
|
||||||
|
|
||||||
public DirectItemReelShareViewHolder(@NonNull final LayoutDmBaseBinding baseBinding,
|
public DirectItemReelShareViewHolder(@NonNull final LayoutDmBaseBinding baseBinding,
|
||||||
@NonNull final LayoutDmReelShareBinding binding,
|
@NonNull final LayoutDmReelShareBinding binding,
|
||||||
@ -40,7 +45,7 @@ public class DirectItemReelShareViewHolder extends DirectItemViewHolder {
|
|||||||
@Override
|
@Override
|
||||||
public void bindItem(final DirectItem item, final MessageDirection messageDirection) {
|
public void bindItem(final DirectItem item, final MessageDirection messageDirection) {
|
||||||
final DirectItemReelShare reelShare = item.getReelShare();
|
final DirectItemReelShare reelShare = item.getReelShare();
|
||||||
final String type = reelShare.getType();
|
type = reelShare.getType();
|
||||||
if (type == null) return;
|
if (type == null) return;
|
||||||
final boolean isSelf = isSelf(item);
|
final boolean isSelf = isSelf(item);
|
||||||
final Media media = reelShare.getMedia();
|
final Media media = reelShare.getMedia();
|
||||||
@ -170,4 +175,20 @@ public class DirectItemReelShareViewHolder extends DirectItemViewHolder {
|
|||||||
protected boolean canForward() {
|
protected boolean canForward() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<DirectItemContextMenu.MenuItem> getLongClickOptions() {
|
||||||
|
final ImmutableList.Builder<DirectItemContextMenu.MenuItem> builder = ImmutableList.builder();
|
||||||
|
if (type != null && type.equals("reply")) {
|
||||||
|
builder.add(new DirectItemContextMenu.MenuItem(R.id.copy, R.string.copy_reply, item -> {
|
||||||
|
final DirectItemReelShare reelShare = item.getReelShare();
|
||||||
|
if (reelShare == null) return null;
|
||||||
|
final String text = reelShare.getText();
|
||||||
|
if (TextUtils.isEmpty(text)) return null;
|
||||||
|
Utils.copyText(itemView.getContext(), text);
|
||||||
|
return null;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,20 @@ package awais.instagrabber.adapters.viewholder.directmessages;
|
|||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import awais.instagrabber.R;
|
||||||
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
|
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
|
||||||
|
import awais.instagrabber.customviews.DirectItemContextMenu;
|
||||||
import awais.instagrabber.databinding.LayoutDmBaseBinding;
|
import awais.instagrabber.databinding.LayoutDmBaseBinding;
|
||||||
import awais.instagrabber.databinding.LayoutDmTextBinding;
|
import awais.instagrabber.databinding.LayoutDmTextBinding;
|
||||||
import awais.instagrabber.repositories.responses.User;
|
import awais.instagrabber.repositories.responses.User;
|
||||||
import awais.instagrabber.repositories.responses.directmessages.DirectItem;
|
import awais.instagrabber.repositories.responses.directmessages.DirectItem;
|
||||||
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
|
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
|
||||||
|
import awais.instagrabber.utils.TextUtils;
|
||||||
|
import awais.instagrabber.utils.Utils;
|
||||||
|
|
||||||
public class DirectItemTextViewHolder extends DirectItemViewHolder {
|
public class DirectItemTextViewHolder extends DirectItemViewHolder {
|
||||||
|
|
||||||
@ -35,4 +43,15 @@ public class DirectItemTextViewHolder extends DirectItemViewHolder {
|
|||||||
protected boolean showBackground() {
|
protected boolean showBackground() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<DirectItemContextMenu.MenuItem> getLongClickOptions() {
|
||||||
|
return ImmutableList.of(
|
||||||
|
new DirectItemContextMenu.MenuItem(R.id.copy, R.string.copy, item -> {
|
||||||
|
if (TextUtils.isEmpty(item.getText())) return null;
|
||||||
|
Utils.copyText(itemView.getContext(), item.getText());
|
||||||
|
return null;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,7 +134,7 @@ public abstract class DirectItemViewHolder extends RecyclerView.ViewHolder imple
|
|||||||
containerLayoutParams.setMarginStart(0);
|
containerLayoutParams.setMarginStart(0);
|
||||||
containerLayoutParams.setMarginEnd(0);
|
containerLayoutParams.setMarginEnd(0);
|
||||||
}
|
}
|
||||||
if (itemType == DirectItemType.TEXT || itemType == DirectItemType.LINK) {
|
if (itemType == DirectItemType.TEXT || itemType == DirectItemType.LINK || itemType == DirectItemType.UNKNOWN) {
|
||||||
binding.messageInfo.setPadding(0, 0, dmRadius, dmRadiusSmall);
|
binding.messageInfo.setPadding(0, 0, dmRadius, dmRadiusSmall);
|
||||||
} else {
|
} else {
|
||||||
if (showMessageInfo()) {
|
if (showMessageInfo()) {
|
||||||
@ -543,22 +543,13 @@ public abstract class DirectItemViewHolder extends RecyclerView.ViewHolder imple
|
|||||||
if (thread.getInputMode() != 1 && messageDirection == MessageDirection.OUTGOING) {
|
if (thread.getInputMode() != 1 && messageDirection == MessageDirection.OUTGOING) {
|
||||||
builder.add(new DirectItemContextMenu.MenuItem(R.id.unsend, R.string.dms_inbox_unsend));
|
builder.add(new DirectItemContextMenu.MenuItem(R.id.unsend, R.string.dms_inbox_unsend));
|
||||||
}
|
}
|
||||||
final DirectItemType itemType = item.getItemType();
|
|
||||||
switch (itemType) {
|
|
||||||
case ANIMATED_MEDIA:
|
|
||||||
builder.add(new DirectItemContextMenu.MenuItem(R.id.detail, R.string.dms_inbox_giphy));
|
|
||||||
break;
|
|
||||||
case VOICE_MEDIA:
|
|
||||||
builder.add(new DirectItemContextMenu.MenuItem(R.id.detail, R.string.action_download));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
final boolean showReactions = thread.getInputMode() != 1 && allowReaction();
|
final boolean showReactions = thread.getInputMode() != 1 && allowReaction();
|
||||||
final ImmutableList<DirectItemContextMenu.MenuItem> menuItems = builder.build();
|
final ImmutableList<DirectItemContextMenu.MenuItem> menuItems = builder.build();
|
||||||
if (!showReactions && menuItems.isEmpty()) return;
|
if (!showReactions && menuItems.isEmpty()) return;
|
||||||
final DirectItemContextMenu menu = new DirectItemContextMenu(itemView.getContext(), showReactions, menuItems);
|
final DirectItemContextMenu menu = new DirectItemContextMenu(itemView.getContext(), showReactions, menuItems);
|
||||||
menu.setOnDismissListener(() -> setSelected(false));
|
menu.setOnDismissListener(() -> setSelected(false));
|
||||||
menu.setOnReactionClickListener(emoji -> callback.onReaction(item, emoji));
|
menu.setOnReactionClickListener(emoji -> callback.onReaction(item, emoji));
|
||||||
menu.setOnOptionSelectListener(itemId -> callback.onOptionSelect(item, itemId));
|
menu.setOnOptionSelectListener((itemId, cb) -> callback.onOptionSelect(item, itemId, cb));
|
||||||
menu.show(itemView, location);
|
menu.show(itemView, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,12 +12,14 @@ import com.google.android.exoplayer2.Player;
|
|||||||
import com.google.android.exoplayer2.SimpleExoPlayer;
|
import com.google.android.exoplayer2.SimpleExoPlayer;
|
||||||
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
|
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
|
||||||
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.primitives.Floats;
|
import com.google.common.primitives.Floats;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import awais.instagrabber.R;
|
import awais.instagrabber.R;
|
||||||
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
|
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
|
||||||
|
import awais.instagrabber.customviews.DirectItemContextMenu;
|
||||||
import awais.instagrabber.databinding.LayoutDmBaseBinding;
|
import awais.instagrabber.databinding.LayoutDmBaseBinding;
|
||||||
import awais.instagrabber.databinding.LayoutDmVoiceMediaBinding;
|
import awais.instagrabber.databinding.LayoutDmVoiceMediaBinding;
|
||||||
import awais.instagrabber.repositories.responses.Audio;
|
import awais.instagrabber.repositories.responses.Audio;
|
||||||
@ -174,6 +176,13 @@ public class DirectItemVoiceMediaViewHolder extends DirectItemViewHolder {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<DirectItemContextMenu.MenuItem> getLongClickOptions() {
|
||||||
|
return ImmutableList.of(
|
||||||
|
new DirectItemContextMenu.MenuItem(R.id.download, R.string.action_download)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private static class AudioItemState {
|
private static class AudioItemState {
|
||||||
private boolean prepared;
|
private boolean prepared;
|
||||||
|
|
||||||
|
@ -0,0 +1,69 @@
|
|||||||
|
package awais.instagrabber.adapters.viewholder.directmessages;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.core.util.Pair;
|
||||||
|
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||||
|
|
||||||
|
import com.facebook.drawee.backends.pipeline.Fresco;
|
||||||
|
|
||||||
|
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
|
||||||
|
import awais.instagrabber.databinding.LayoutDmAnimatedMediaBinding;
|
||||||
|
import awais.instagrabber.databinding.LayoutDmBaseBinding;
|
||||||
|
import awais.instagrabber.repositories.responses.User;
|
||||||
|
import awais.instagrabber.repositories.responses.directmessages.DirectItem;
|
||||||
|
import awais.instagrabber.repositories.responses.directmessages.DirectItemXma;
|
||||||
|
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
|
||||||
|
import awais.instagrabber.utils.NumberUtils;
|
||||||
|
|
||||||
|
public class DirectItemXmaViewHolder extends DirectItemViewHolder {
|
||||||
|
|
||||||
|
private final LayoutDmAnimatedMediaBinding binding;
|
||||||
|
|
||||||
|
public DirectItemXmaViewHolder(@NonNull final LayoutDmBaseBinding baseBinding,
|
||||||
|
@NonNull final LayoutDmAnimatedMediaBinding binding,
|
||||||
|
final User currentUser,
|
||||||
|
final DirectThread thread,
|
||||||
|
final DirectItemCallback callback) {
|
||||||
|
super(baseBinding, currentUser, thread, callback);
|
||||||
|
this.binding = binding;
|
||||||
|
setItemView(binding.getRoot());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void bindItem(final DirectItem item, final MessageDirection messageDirection) {
|
||||||
|
final DirectItemXma xma = item.getXma();
|
||||||
|
final DirectItemXma.XmaUrlInfo playableUrlInfo = xma.getPlayableUrlInfo();
|
||||||
|
final DirectItemXma.XmaUrlInfo previewUrlInfo = xma.getPreviewUrlInfo();
|
||||||
|
if (playableUrlInfo == null && previewUrlInfo == null) {
|
||||||
|
binding.ivAnimatedMessage.setController(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final DirectItemXma.XmaUrlInfo urlInfo = playableUrlInfo != null ? playableUrlInfo : previewUrlInfo;
|
||||||
|
final String url = urlInfo.getUrl();
|
||||||
|
final Pair<Integer, Integer> widthHeight = NumberUtils.calculateWidthHeight(
|
||||||
|
urlInfo.getHeight(),
|
||||||
|
urlInfo.getWidth(),
|
||||||
|
mediaImageMaxHeight,
|
||||||
|
mediaImageMaxWidth
|
||||||
|
);
|
||||||
|
binding.ivAnimatedMessage.setVisibility(View.VISIBLE);
|
||||||
|
final ViewGroup.LayoutParams layoutParams = binding.ivAnimatedMessage.getLayoutParams();
|
||||||
|
final int width = widthHeight.first != null ? widthHeight.first : 0;
|
||||||
|
final int height = widthHeight.second != null ? widthHeight.second : 0;
|
||||||
|
layoutParams.width = width;
|
||||||
|
layoutParams.height = height;
|
||||||
|
binding.ivAnimatedMessage.requestLayout();
|
||||||
|
binding.ivAnimatedMessage.setController(Fresco.newDraweeControllerBuilder()
|
||||||
|
.setUri(url)
|
||||||
|
.setAutoPlayAnimations(true)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSwipeDirection() {
|
||||||
|
return ItemTouchHelper.ACTION_STATE_IDLE;
|
||||||
|
}
|
||||||
|
}
|
@ -29,12 +29,14 @@ import androidx.constraintlayout.widget.ConstraintLayout;
|
|||||||
import androidx.core.util.Pair;
|
import androidx.core.util.Pair;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
import awais.instagrabber.R;
|
import awais.instagrabber.R;
|
||||||
import awais.instagrabber.animations.RoundedRectRevealOutlineProvider;
|
import awais.instagrabber.animations.RoundedRectRevealOutlineProvider;
|
||||||
import awais.instagrabber.customviews.emoji.Emoji;
|
import awais.instagrabber.customviews.emoji.Emoji;
|
||||||
import awais.instagrabber.customviews.emoji.ReactionsManager;
|
import awais.instagrabber.customviews.emoji.ReactionsManager;
|
||||||
import awais.instagrabber.databinding.LayoutDirectItemOptionsBinding;
|
import awais.instagrabber.databinding.LayoutDirectItemOptionsBinding;
|
||||||
|
import awais.instagrabber.repositories.responses.directmessages.DirectItem;
|
||||||
|
|
||||||
import static android.view.View.MeasureSpec.makeMeasureSpec;
|
import static android.view.View.MeasureSpec.makeMeasureSpec;
|
||||||
|
|
||||||
@ -345,7 +347,7 @@ public class DirectItemContextMenu extends PopupWindow {
|
|||||||
textView.setText(context.getString(menuItem.getTitleRes()));
|
textView.setText(context.getString(menuItem.getTitleRes()));
|
||||||
textView.setOnClickListener(v -> {
|
textView.setOnClickListener(v -> {
|
||||||
if (onOptionSelectListener != null) {
|
if (onOptionSelectListener != null) {
|
||||||
onOptionSelectListener.onSelect(menuItem.getItemId());
|
onOptionSelectListener.onSelect(menuItem.getItemId(), menuItem.getCallback());
|
||||||
}
|
}
|
||||||
dismiss();
|
dismiss();
|
||||||
});
|
});
|
||||||
@ -397,9 +399,19 @@ public class DirectItemContextMenu extends PopupWindow {
|
|||||||
@StringRes
|
@StringRes
|
||||||
private final int titleRes;
|
private final int titleRes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback function
|
||||||
|
*/
|
||||||
|
private final Function<DirectItem, Void> callback;
|
||||||
|
|
||||||
public MenuItem(@IdRes final int itemId, @StringRes final int titleRes) {
|
public MenuItem(@IdRes final int itemId, @StringRes final int titleRes) {
|
||||||
|
this(itemId, titleRes, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MenuItem(@IdRes final int itemId, @StringRes final int titleRes, @Nullable final Function<DirectItem, Void> callback) {
|
||||||
this.itemId = itemId;
|
this.itemId = itemId;
|
||||||
this.titleRes = titleRes;
|
this.titleRes = titleRes;
|
||||||
|
this.callback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getItemId() {
|
public int getItemId() {
|
||||||
@ -409,10 +421,14 @@ public class DirectItemContextMenu extends PopupWindow {
|
|||||||
public int getTitleRes() {
|
public int getTitleRes() {
|
||||||
return titleRes;
|
return titleRes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Function<DirectItem, Void> getCallback() {
|
||||||
|
return callback;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface OnOptionSelectListener {
|
public interface OnOptionSelectListener {
|
||||||
void onSelect(int itemId);
|
void onSelect(int itemId, @Nullable Function<DirectItem, Void> callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface OnReactionClickListener {
|
public interface OnReactionClickListener {
|
||||||
|
@ -22,6 +22,7 @@ import androidx.work.WorkManager;
|
|||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -74,11 +75,10 @@ public class PostsRecyclerView extends RecyclerView {
|
|||||||
}
|
}
|
||||||
final List<Media> models = mediaViewModel.getList().getValue();
|
final List<Media> models = mediaViewModel.getList().getValue();
|
||||||
final List<Media> modelsCopy = models == null ? new ArrayList<>() : new ArrayList<>(models);
|
final List<Media> modelsCopy = models == null ? new ArrayList<>() : new ArrayList<>(models);
|
||||||
if (settingsHelper.getBoolean(Constants.TOGGLE_KEYWORD_FILTER)){
|
if (settingsHelper.getBoolean(Constants.TOGGLE_KEYWORD_FILTER)) {
|
||||||
final ArrayList<String> items = new ArrayList<>(settingsHelper.getStringSet(Constants.KEYWORD_FILTERS));
|
final ArrayList<String> items = new ArrayList<>(settingsHelper.getStringSet(Constants.KEYWORD_FILTERS));
|
||||||
modelsCopy.addAll(new KeywordsFilterUtils(items).filter(result));
|
modelsCopy.addAll(new KeywordsFilterUtils(items).filter(result));
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
modelsCopy.addAll(result);
|
modelsCopy.addAll(result);
|
||||||
}
|
}
|
||||||
mediaViewModel.getList().postValue(modelsCopy);
|
mediaViewModel.getList().postValue(modelsCopy);
|
||||||
@ -194,7 +194,9 @@ public class PostsRecyclerView extends RecyclerView {
|
|||||||
private void initSelf() {
|
private void initSelf() {
|
||||||
mediaViewModel = new ViewModelProvider(viewModelStoreOwner).get(MediaViewModel.class);
|
mediaViewModel = new ViewModelProvider(viewModelStoreOwner).get(MediaViewModel.class);
|
||||||
mediaViewModel.getList().observe(lifeCycleOwner, list -> {
|
mediaViewModel.getList().observe(lifeCycleOwner, list -> {
|
||||||
if (list.size() > 0) feedAdapter.submitList(list, () -> {
|
if (list.size() <= 0) return;
|
||||||
|
feedAdapter.submitList(list, () -> {
|
||||||
|
// postDelayed(this::fetchMoreIfPossible, 1000);
|
||||||
if (!shouldScrollToTop) return;
|
if (!shouldScrollToTop) return;
|
||||||
smoothScrollToPosition(0);
|
smoothScrollToPosition(0);
|
||||||
shouldScrollToTop = false;
|
shouldScrollToTop = false;
|
||||||
@ -217,6 +219,20 @@ public class PostsRecyclerView extends RecyclerView {
|
|||||||
dispatchFetchStatus();
|
dispatchFetchStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void fetchMoreIfPossible() {
|
||||||
|
if (!postFetcher.hasMore()) return;
|
||||||
|
if (feedAdapter.getItemCount() == 0) return;
|
||||||
|
final LayoutManager layoutManager = getLayoutManager();
|
||||||
|
if (!(layoutManager instanceof StaggeredGridLayoutManager)) return;
|
||||||
|
final int[] itemPositions = ((StaggeredGridLayoutManager) layoutManager).findLastCompletelyVisibleItemPositions(null);
|
||||||
|
final boolean allNoPosition = Arrays.stream(itemPositions).allMatch(position -> position == RecyclerView.NO_POSITION);
|
||||||
|
if (allNoPosition) return;
|
||||||
|
final boolean match = Arrays.stream(itemPositions).anyMatch(position -> position == feedAdapter.getItemCount() - 1);
|
||||||
|
if (!match) return;
|
||||||
|
postFetcher.fetch();
|
||||||
|
dispatchFetchStatus();
|
||||||
|
}
|
||||||
|
|
||||||
private void initDownloadWorkerListener() {
|
private void initDownloadWorkerListener() {
|
||||||
WorkManager.getInstance(getContext())
|
WorkManager.getInstance(getContext())
|
||||||
.getWorkInfosByTagLiveData("download")
|
.getWorkInfosByTagLiveData("download")
|
||||||
|
@ -47,7 +47,7 @@ public class FavoriteDataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final void insertOrUpdateFavorite(@NonNull final Favorite favorite) {
|
public final void insertOrUpdateFavorite(@NonNull final Favorite favorite) {
|
||||||
if (favorite.getId() > 0) {
|
if (favorite.getId() != 0) {
|
||||||
favoriteDao.updateFavorites(favorite);
|
favoriteDao.updateFavorites(favorite);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,275 @@
|
|||||||
|
package awais.instagrabber.dialogs;
|
||||||
|
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Pair;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.fragment.app.DialogFragment;
|
||||||
|
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||||
|
import androidx.recyclerview.widget.ItemTouchHelper.SimpleCallback;
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import awais.instagrabber.R;
|
||||||
|
import awais.instagrabber.adapters.DirectUsersAdapter;
|
||||||
|
import awais.instagrabber.adapters.TabsAdapter;
|
||||||
|
import awais.instagrabber.adapters.viewholder.TabViewHolder;
|
||||||
|
import awais.instagrabber.fragments.settings.PreferenceKeys;
|
||||||
|
import awais.instagrabber.models.Tab;
|
||||||
|
import awais.instagrabber.utils.Utils;
|
||||||
|
|
||||||
|
import static androidx.recyclerview.widget.ItemTouchHelper.ACTION_STATE_DRAG;
|
||||||
|
import static androidx.recyclerview.widget.ItemTouchHelper.DOWN;
|
||||||
|
import static androidx.recyclerview.widget.ItemTouchHelper.UP;
|
||||||
|
|
||||||
|
public class TabOrderPreferenceDialogFragment extends DialogFragment {
|
||||||
|
private Callback callback;
|
||||||
|
private Context context;
|
||||||
|
private List<Tab> tabsInPref;
|
||||||
|
private ItemTouchHelper itemTouchHelper;
|
||||||
|
private AlertDialog dialog;
|
||||||
|
private List<Tab> newOrderTabs;
|
||||||
|
private List<Tab> newOtherTabs;
|
||||||
|
|
||||||
|
private final TabsAdapter.TabAdapterCallback tabAdapterCallback = new TabsAdapter.TabAdapterCallback() {
|
||||||
|
@Override
|
||||||
|
public void onStartDrag(final TabViewHolder viewHolder) {
|
||||||
|
if (itemTouchHelper == null || viewHolder == null) return;
|
||||||
|
itemTouchHelper.startDrag(viewHolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onOrderChange(final List<Tab> newOrderTabs) {
|
||||||
|
if (newOrderTabs == null || tabsInPref == null || dialog == null) return;
|
||||||
|
TabOrderPreferenceDialogFragment.this.newOrderTabs = newOrderTabs;
|
||||||
|
setSaveButtonState(newOrderTabs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAdd(final Tab tab) {
|
||||||
|
// Add this tab to newOrderTabs
|
||||||
|
newOrderTabs = ImmutableList.<Tab>builder()
|
||||||
|
.addAll(newOrderTabs)
|
||||||
|
.add(tab)
|
||||||
|
.build();
|
||||||
|
// Remove this tab from newOtherTabs
|
||||||
|
if (newOtherTabs != null) {
|
||||||
|
newOtherTabs = newOtherTabs.stream()
|
||||||
|
.filter(t -> !t.equals(tab))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
setSaveButtonState(newOrderTabs);
|
||||||
|
// submit these tab lists to adapter
|
||||||
|
if (adapter == null) return;
|
||||||
|
adapter.submitList(newOrderTabs, newOtherTabs, () -> list.postDelayed(() -> adapter.notifyDataSetChanged(), 300));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRemove(final Tab tab) {
|
||||||
|
// Remove this tab from newOrderTabs
|
||||||
|
newOrderTabs = newOrderTabs.stream()
|
||||||
|
.filter(t -> !t.equals(tab))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
// Add this tab to newOtherTabs
|
||||||
|
if (newOtherTabs != null) {
|
||||||
|
newOtherTabs = ImmutableList.<Tab>builder()
|
||||||
|
.addAll(newOtherTabs)
|
||||||
|
.add(tab)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
setSaveButtonState(newOrderTabs);
|
||||||
|
// submit these tab lists to adapter
|
||||||
|
if (adapter == null) return;
|
||||||
|
adapter.submitList(newOrderTabs, newOtherTabs, () -> list.postDelayed(() -> {
|
||||||
|
adapter.notifyDataSetChanged();
|
||||||
|
if (tab.getNavigationRootId() == R.id.direct_messages_nav_graph) {
|
||||||
|
final ConfirmDialogFragment dialogFragment = ConfirmDialogFragment.newInstance(
|
||||||
|
111, 0, R.string.dm_remove_warning, R.string.ok, 0, 0
|
||||||
|
);
|
||||||
|
dialogFragment.show(getChildFragmentManager(), "dm_warning_dialog");
|
||||||
|
}
|
||||||
|
}, 500));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setSaveButtonState(final List<Tab> newOrderTabs) {
|
||||||
|
dialog.getButton(AlertDialog.BUTTON_POSITIVE)
|
||||||
|
.setEnabled(!newOrderTabs.equals(tabsInPref));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
private final SimpleCallback simpleCallback = new SimpleCallback(UP | DOWN, 0) {
|
||||||
|
private int movePosition = RecyclerView.NO_POSITION;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMovementFlags(@NonNull final RecyclerView recyclerView, @NonNull final RecyclerView.ViewHolder viewHolder) {
|
||||||
|
if (viewHolder instanceof DirectUsersAdapter.HeaderViewHolder) return 0;
|
||||||
|
if (viewHolder instanceof TabViewHolder && !((TabViewHolder) viewHolder).isDraggable()) return 0;
|
||||||
|
return super.getMovementFlags(recyclerView, viewHolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onChildDraw(@NonNull final Canvas c,
|
||||||
|
@NonNull final RecyclerView recyclerView,
|
||||||
|
@NonNull final RecyclerView.ViewHolder viewHolder,
|
||||||
|
final float dX,
|
||||||
|
final float dY,
|
||||||
|
final int actionState,
|
||||||
|
final boolean isCurrentlyActive) {
|
||||||
|
if (actionState != ACTION_STATE_DRAG) {
|
||||||
|
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final TabsAdapter adapter = (TabsAdapter) recyclerView.getAdapter();
|
||||||
|
if (adapter == null) {
|
||||||
|
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Do not allow dragging into 'Other tabs' category
|
||||||
|
float edgeY = dY;
|
||||||
|
final int lastPosition = adapter.getCurrentCount() - 1;
|
||||||
|
final View view = viewHolder.itemView;
|
||||||
|
// final int topEdge = recyclerView.getTop();
|
||||||
|
final int bottomEdge = view.getHeight() * adapter.getCurrentCount() - view.getBottom();
|
||||||
|
// if (movePosition == 0 && dY < topEdge) {
|
||||||
|
// edgeY = topEdge;
|
||||||
|
// } else
|
||||||
|
if (movePosition >= lastPosition && dY >= bottomEdge) {
|
||||||
|
edgeY = bottomEdge;
|
||||||
|
}
|
||||||
|
super.onChildDraw(c, recyclerView, viewHolder, dX, edgeY, actionState, isCurrentlyActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onMove(@NonNull final RecyclerView recyclerView,
|
||||||
|
@NonNull final RecyclerView.ViewHolder viewHolder,
|
||||||
|
@NonNull final RecyclerView.ViewHolder target) {
|
||||||
|
final TabsAdapter adapter = (TabsAdapter) recyclerView.getAdapter();
|
||||||
|
if (adapter == null) return false;
|
||||||
|
movePosition = target.getBindingAdapterPosition();
|
||||||
|
if (movePosition >= adapter.getCurrentCount()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final int from = viewHolder.getBindingAdapterPosition();
|
||||||
|
final int to = target.getBindingAdapterPosition();
|
||||||
|
adapter.moveItem(from, to);
|
||||||
|
// adapter.notifyItemMoved(from, to);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSwiped(@NonNull final RecyclerView.ViewHolder viewHolder, final int direction) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSelectedChanged(@Nullable final RecyclerView.ViewHolder viewHolder, final int actionState) {
|
||||||
|
super.onSelectedChanged(viewHolder, actionState);
|
||||||
|
if (!(viewHolder instanceof TabViewHolder)) {
|
||||||
|
movePosition = RecyclerView.NO_POSITION;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (actionState == ACTION_STATE_DRAG) {
|
||||||
|
((TabViewHolder) viewHolder).setDragging(true);
|
||||||
|
movePosition = viewHolder.getBindingAdapterPosition();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearView(@NonNull final RecyclerView recyclerView,
|
||||||
|
@NonNull final RecyclerView.ViewHolder viewHolder) {
|
||||||
|
super.clearView(recyclerView, viewHolder);
|
||||||
|
((TabViewHolder) viewHolder).setDragging(false);
|
||||||
|
movePosition = RecyclerView.NO_POSITION;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
private TabsAdapter adapter;
|
||||||
|
private RecyclerView list;
|
||||||
|
|
||||||
|
public static TabOrderPreferenceDialogFragment newInstance() {
|
||||||
|
final Bundle args = new Bundle();
|
||||||
|
final TabOrderPreferenceDialogFragment fragment = new TabOrderPreferenceDialogFragment();
|
||||||
|
fragment.setArguments(args);
|
||||||
|
return fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TabOrderPreferenceDialogFragment() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttach(@NonNull final Context context) {
|
||||||
|
super.onAttach(context);
|
||||||
|
try {
|
||||||
|
callback = (Callback) getParentFragment();
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
// throw new ClassCastException("Calling fragment must implement TabOrderPreferenceDialogFragment.Callback interface");
|
||||||
|
}
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public Dialog onCreateDialog(@Nullable final Bundle savedInstanceState) {
|
||||||
|
return new MaterialAlertDialogBuilder(context)
|
||||||
|
.setView(createView())
|
||||||
|
.setPositiveButton(R.string.save, (d, w) -> {
|
||||||
|
final boolean hasChanged = newOrderTabs != null && !newOrderTabs.equals(tabsInPref);
|
||||||
|
if (hasChanged) {
|
||||||
|
saveNewOrder();
|
||||||
|
}
|
||||||
|
if (callback == null) return;
|
||||||
|
callback.onSave(hasChanged);
|
||||||
|
})
|
||||||
|
.setNegativeButton(R.string.cancel, (dialog, which) -> {
|
||||||
|
if (callback == null) return;
|
||||||
|
callback.onCancel();
|
||||||
|
})
|
||||||
|
.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveNewOrder() {
|
||||||
|
final String newOrderString = newOrderTabs.stream()
|
||||||
|
.map(Tab::getGraphName)
|
||||||
|
.collect(Collectors.joining(","));
|
||||||
|
Utils.settingsHelper.putString(PreferenceKeys.PREF_TAB_ORDER, newOrderString);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStart() {
|
||||||
|
super.onStart();
|
||||||
|
final Dialog dialog = getDialog();
|
||||||
|
if (!(dialog instanceof AlertDialog)) return;
|
||||||
|
this.dialog = (AlertDialog) dialog;
|
||||||
|
this.dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private View createView() {
|
||||||
|
list = new RecyclerView(context);
|
||||||
|
list.setLayoutManager(new LinearLayoutManager(context));
|
||||||
|
itemTouchHelper = new ItemTouchHelper(simpleCallback);
|
||||||
|
itemTouchHelper.attachToRecyclerView(list);
|
||||||
|
adapter = new TabsAdapter(tabAdapterCallback);
|
||||||
|
list.setAdapter(adapter);
|
||||||
|
final Pair<List<Tab>, List<Tab>> navTabListPair = Utils.getNavTabList(context);
|
||||||
|
tabsInPref = navTabListPair.first;
|
||||||
|
// initially set newOrderTabs and newOtherTabs same as current tabs
|
||||||
|
newOrderTabs = navTabListPair.first;
|
||||||
|
newOtherTabs = navTabListPair.second;
|
||||||
|
adapter.submitList(navTabListPair.first, navTabListPair.second);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Callback {
|
||||||
|
void onSave(final boolean orderHasChanged);
|
||||||
|
|
||||||
|
void onCancel();
|
||||||
|
}
|
||||||
|
}
|
@ -65,13 +65,14 @@ import awais.instagrabber.webservices.GraphQLService;
|
|||||||
import awais.instagrabber.webservices.LocationService;
|
import awais.instagrabber.webservices.LocationService;
|
||||||
import awais.instagrabber.webservices.ServiceCallback;
|
import awais.instagrabber.webservices.ServiceCallback;
|
||||||
import awais.instagrabber.webservices.StoriesService;
|
import awais.instagrabber.webservices.StoriesService;
|
||||||
//import awaisomereport.LogCollector;
|
|
||||||
|
|
||||||
import static androidx.core.content.PermissionChecker.checkSelfPermission;
|
import static androidx.core.content.PermissionChecker.checkSelfPermission;
|
||||||
import static awais.instagrabber.utils.DownloadUtils.WRITE_PERMISSION;
|
import static awais.instagrabber.utils.DownloadUtils.WRITE_PERMISSION;
|
||||||
//import static awais.instagrabber.utils.Utils.logCollector;
|
|
||||||
import static awais.instagrabber.utils.Utils.settingsHelper;
|
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||||
|
|
||||||
|
//import awaisomereport.LogCollector;
|
||||||
|
//import static awais.instagrabber.utils.Utils.logCollector;
|
||||||
|
|
||||||
public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
|
public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
|
||||||
private static final String TAG = "LocationFragment";
|
private static final String TAG = "LocationFragment";
|
||||||
private static final int STORAGE_PERM_REQUEST_CODE = 8020;
|
private static final int STORAGE_PERM_REQUEST_CODE = 8020;
|
||||||
|
@ -20,8 +20,6 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
|||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.lifecycle.Observer;
|
import androidx.lifecycle.Observer;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.lifecycle.ViewModelStoreOwner;
|
|
||||||
import androidx.navigation.NavController;
|
|
||||||
import androidx.navigation.NavDirections;
|
import androidx.navigation.NavDirections;
|
||||||
import androidx.navigation.fragment.NavHostFragment;
|
import androidx.navigation.fragment.NavHostFragment;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
@ -29,7 +27,6 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
|||||||
|
|
||||||
import com.google.android.material.badge.BadgeDrawable;
|
import com.google.android.material.badge.BadgeDrawable;
|
||||||
import com.google.android.material.badge.BadgeUtils;
|
import com.google.android.material.badge.BadgeUtils;
|
||||||
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
|
||||||
import com.google.android.material.snackbar.Snackbar;
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -66,9 +63,7 @@ public class DirectMessageInboxFragment extends Fragment implements SwipeRefresh
|
|||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
fragmentActivity = (MainActivity) getActivity();
|
fragmentActivity = (MainActivity) getActivity();
|
||||||
if (fragmentActivity != null) {
|
if (fragmentActivity != null) {
|
||||||
final NavController navController = NavHostFragment.findNavController(this);
|
viewModel = new ViewModelProvider(fragmentActivity).get(DirectInboxViewModel.class);
|
||||||
final ViewModelStoreOwner viewModelStoreOwner = navController.getViewModelStoreOwner(R.id.direct_messages_nav_graph);
|
|
||||||
viewModel = new ViewModelProvider(viewModelStoreOwner).get(DirectInboxViewModel.class);
|
|
||||||
}
|
}
|
||||||
setHasOptionsMenu(true);
|
setHasOptionsMenu(true);
|
||||||
}
|
}
|
||||||
@ -101,6 +96,7 @@ public class DirectMessageInboxFragment extends Fragment implements SwipeRefresh
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("UnsafeExperimentalUsageError")
|
||||||
@Override
|
@Override
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
@ -201,11 +197,6 @@ public class DirectMessageInboxFragment extends Fragment implements SwipeRefresh
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
viewModel.getUnseenCount().observe(getViewLifecycleOwner(), unseenCountResource -> {
|
|
||||||
if (unseenCountResource == null) return;
|
|
||||||
final Integer unseenCount = unseenCountResource.data;
|
|
||||||
setBottomNavBarBadge(unseenCount == null ? 0 : unseenCount);
|
|
||||||
});
|
|
||||||
viewModel.getPendingRequestsTotal().observe(getViewLifecycleOwner(), this::attachPendingRequestsBadge);
|
viewModel.getPendingRequestsTotal().observe(getViewLifecycleOwner(), this::attachPendingRequestsBadge);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,12 +204,7 @@ public class DirectMessageInboxFragment extends Fragment implements SwipeRefresh
|
|||||||
private void attachPendingRequestsBadge(@Nullable final Integer count) {
|
private void attachPendingRequestsBadge(@Nullable final Integer count) {
|
||||||
if (pendingRequestsMenuItem == null) {
|
if (pendingRequestsMenuItem == null) {
|
||||||
final Handler handler = new Handler();
|
final Handler handler = new Handler();
|
||||||
handler.postDelayed(new Runnable() {
|
handler.postDelayed(() -> attachPendingRequestsBadge(count), 500);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
attachPendingRequestsBadge(count);
|
|
||||||
}
|
|
||||||
}, 500);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (pendingRequestTotalBadgeDrawable == null) {
|
if (pendingRequestTotalBadgeDrawable == null) {
|
||||||
@ -277,20 +263,4 @@ public class DirectMessageInboxFragment extends Fragment implements SwipeRefresh
|
|||||||
});
|
});
|
||||||
binding.inboxList.addOnScrollListener(lazyLoader);
|
binding.inboxList.addOnScrollListener(lazyLoader);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setBottomNavBarBadge(final int unseenCount) {
|
|
||||||
final BottomNavigationView bottomNavView = fragmentActivity.getBottomNavView();
|
|
||||||
final BadgeDrawable badge = bottomNavView.getOrCreateBadge(R.id.direct_messages_nav_graph);
|
|
||||||
if (badge == null) return;
|
|
||||||
if (unseenCount == 0) {
|
|
||||||
badge.setVisible(false);
|
|
||||||
badge.clearNumber();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (badge.getVerticalOffset() != 10) {
|
|
||||||
badge.setVerticalOffset(10);
|
|
||||||
}
|
|
||||||
badge.setNumber(unseenCount);
|
|
||||||
badge.setVisible(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -79,11 +79,13 @@ public class DirectMessageSettingsFragment extends Fragment implements ConfirmDi
|
|||||||
final DirectMessageSettingsFragmentArgs args = DirectMessageSettingsFragmentArgs.fromBundle(arguments);
|
final DirectMessageSettingsFragmentArgs args = DirectMessageSettingsFragmentArgs.fromBundle(arguments);
|
||||||
final MainActivity fragmentActivity = (MainActivity) requireActivity();
|
final MainActivity fragmentActivity = (MainActivity) requireActivity();
|
||||||
final AppStateViewModel appStateViewModel = new ViewModelProvider(fragmentActivity).get(AppStateViewModel.class);
|
final AppStateViewModel appStateViewModel = new ViewModelProvider(fragmentActivity).get(AppStateViewModel.class);
|
||||||
viewModel = new ViewModelProvider(this, new DirectSettingsViewModelFactory(fragmentActivity.getApplication(),
|
final DirectSettingsViewModelFactory viewModelFactory = new DirectSettingsViewModelFactory(
|
||||||
|
fragmentActivity.getApplication(),
|
||||||
args.getThreadId(),
|
args.getThreadId(),
|
||||||
args.getPending(),
|
args.getPending(),
|
||||||
appStateViewModel.getCurrentUser()))
|
appStateViewModel.getCurrentUser()
|
||||||
.get(DirectSettingsViewModel.class);
|
);
|
||||||
|
viewModel = new ViewModelProvider(this, viewModelFactory).get(DirectSettingsViewModel.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
|
@ -58,6 +58,7 @@ import java.io.File;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
import awais.instagrabber.ProfileNavGraphDirections;
|
import awais.instagrabber.ProfileNavGraphDirections;
|
||||||
import awais.instagrabber.R;
|
import awais.instagrabber.R;
|
||||||
@ -258,7 +259,7 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onOptionSelect(final DirectItem item, final int itemId) {
|
public void onOptionSelect(final DirectItem item, final int itemId, final Function<DirectItem, Void> cb) {
|
||||||
if (itemId == R.id.unsend) {
|
if (itemId == R.id.unsend) {
|
||||||
handleSentMessage(viewModel.unsend(item));
|
handleSentMessage(viewModel.unsend(item));
|
||||||
return;
|
return;
|
||||||
@ -275,21 +276,17 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
final NavController navController = NavHostFragment.findNavController(DirectMessageThreadFragment.this);
|
final NavController navController = NavHostFragment.findNavController(DirectMessageThreadFragment.this);
|
||||||
navController.navigate(actionGlobalUserSearch);
|
navController.navigate(actionGlobalUserSearch);
|
||||||
}
|
}
|
||||||
if (itemId == R.id.detail) {
|
if (itemId == R.id.download) {
|
||||||
final Context context = getContext();
|
downloadItem(item);
|
||||||
if (context == null) return;
|
return;
|
||||||
final DirectItemType itemType = item.getItemType();
|
|
||||||
switch (itemType) {
|
|
||||||
case ANIMATED_MEDIA:
|
|
||||||
Utils.openURL(context, "https://giphy.com/gifs/" + item.getAnimatedMedia().getId());
|
|
||||||
break;
|
|
||||||
case VOICE_MEDIA:
|
|
||||||
downloadItem(item.getVoiceMedia() == null ? null : item.getVoiceMedia().getMedia(), context);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
// otherwise call callback if present
|
||||||
|
if (cb != null) {
|
||||||
|
cb.apply(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private final DirectItemLongClickListener directItemLongClickListener = position -> {
|
private final DirectItemLongClickListener directItemLongClickListener = position -> {
|
||||||
// viewModel.setSelectedPosition(position);
|
// viewModel.setSelectedPosition(position);
|
||||||
};
|
};
|
||||||
@ -319,6 +316,7 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
};
|
};
|
||||||
private final MutableLiveData<Integer> inputLength = new MutableLiveData<>(0);
|
private final MutableLiveData<Integer> inputLength = new MutableLiveData<>(0);
|
||||||
private MenuItem markAsSeenMenuItem;
|
private MenuItem markAsSeenMenuItem;
|
||||||
|
private Media tempMedia;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||||
@ -329,11 +327,13 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
final Bundle arguments = getArguments();
|
final Bundle arguments = getArguments();
|
||||||
if (arguments == null) return;
|
if (arguments == null) return;
|
||||||
final DirectMessageThreadFragmentArgs fragmentArgs = DirectMessageThreadFragmentArgs.fromBundle(arguments);
|
final DirectMessageThreadFragmentArgs fragmentArgs = DirectMessageThreadFragmentArgs.fromBundle(arguments);
|
||||||
viewModel = new ViewModelProvider(this, new DirectThreadViewModelFactory(fragmentActivity.getApplication(),
|
final DirectThreadViewModelFactory viewModelFactory = new DirectThreadViewModelFactory(
|
||||||
|
fragmentActivity.getApplication(),
|
||||||
fragmentArgs.getThreadId(),
|
fragmentArgs.getThreadId(),
|
||||||
fragmentArgs.getPending(),
|
fragmentArgs.getPending(),
|
||||||
appStateViewModel.getCurrentUser()))
|
appStateViewModel.getCurrentUser()
|
||||||
.get(DirectThreadViewModel.class);
|
);
|
||||||
|
viewModel = new ViewModelProvider(this, viewModelFactory).get(DirectThreadViewModel.class);
|
||||||
setHasOptionsMenu(true);
|
setHasOptionsMenu(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -454,7 +454,9 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
final Context context = getContext();
|
final Context context = getContext();
|
||||||
if (context == null) return;
|
if (context == null) return;
|
||||||
if (requestCode == STORAGE_PERM_REQUEST_CODE && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
if (requestCode == STORAGE_PERM_REQUEST_CODE && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||||
// downloadItem(context);
|
if (tempMedia == null) return;
|
||||||
|
downloadItem(context, tempMedia);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (requestCode == AUDIO_RECORD_PERM_REQUEST_CODE) {
|
if (requestCode == AUDIO_RECORD_PERM_REQUEST_CODE) {
|
||||||
if (PermissionUtils.hasAudioRecordPerms(context)) {
|
if (PermissionUtils.hasAudioRecordPerms(context)) {
|
||||||
@ -1317,18 +1319,31 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
appExecutors.mainThread().execute(prevTitleRunnable, 1000);
|
appExecutors.mainThread().execute(prevTitleRunnable, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void downloadItem(final DirectItem item) {
|
||||||
|
final Context context = getContext();
|
||||||
|
if (context == null) return;
|
||||||
|
final DirectItemType itemType = item.getItemType();
|
||||||
|
//noinspection SwitchStatementWithTooFewBranches
|
||||||
|
switch (itemType) {
|
||||||
|
case VOICE_MEDIA:
|
||||||
|
downloadItem(context, item.getVoiceMedia() == null ? null : item.getVoiceMedia().getMedia());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// currently ONLY for voice
|
// currently ONLY for voice
|
||||||
private void downloadItem(final Media media, final Context context) {
|
private void downloadItem(@NonNull final Context context, final Media media) {
|
||||||
if (media == null) {
|
if (media == null) {
|
||||||
Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||||
} else {
|
return;
|
||||||
|
}
|
||||||
if (ContextCompat.checkSelfPermission(context, DownloadUtils.PERMS[0]) == PackageManager.PERMISSION_GRANTED) {
|
if (ContextCompat.checkSelfPermission(context, DownloadUtils.PERMS[0]) == PackageManager.PERMISSION_GRANTED) {
|
||||||
DownloadUtils.download(context, media);
|
DownloadUtils.download(context, media);
|
||||||
} else {
|
|
||||||
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
|
|
||||||
}
|
|
||||||
Toast.makeText(context, R.string.downloader_downloading_media, Toast.LENGTH_SHORT).show();
|
Toast.makeText(context, R.string.downloader_downloading_media, Toast.LENGTH_SHORT).show();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
tempMedia = media;
|
||||||
|
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
|
@ -13,8 +13,6 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
|||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.lifecycle.Observer;
|
import androidx.lifecycle.Observer;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.lifecycle.ViewModelStoreOwner;
|
|
||||||
import androidx.navigation.NavController;
|
|
||||||
import androidx.navigation.fragment.NavHostFragment;
|
import androidx.navigation.fragment.NavHostFragment;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||||
@ -24,7 +22,6 @@ import com.google.android.material.snackbar.Snackbar;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import awais.instagrabber.R;
|
|
||||||
import awais.instagrabber.activities.MainActivity;
|
import awais.instagrabber.activities.MainActivity;
|
||||||
import awais.instagrabber.adapters.DirectMessageInboxAdapter;
|
import awais.instagrabber.adapters.DirectMessageInboxAdapter;
|
||||||
import awais.instagrabber.customviews.helpers.RecyclerLazyLoaderAtEdge;
|
import awais.instagrabber.customviews.helpers.RecyclerLazyLoaderAtEdge;
|
||||||
@ -51,9 +48,7 @@ public class DirectPendingInboxFragment extends Fragment implements SwipeRefresh
|
|||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
fragmentActivity = (MainActivity) getActivity();
|
fragmentActivity = (MainActivity) getActivity();
|
||||||
if (fragmentActivity != null) {
|
if (fragmentActivity != null) {
|
||||||
final NavController navController = NavHostFragment.findNavController(this);
|
viewModel = new ViewModelProvider(fragmentActivity).get(DirectPendingInboxViewModel.class);
|
||||||
final ViewModelStoreOwner viewModelStoreOwner = navController.getViewModelStoreOwner(R.id.direct_messages_nav_graph);
|
|
||||||
viewModel = new ViewModelProvider(viewModelStoreOwner).get(DirectPendingInboxViewModel.class);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,6 @@ import android.text.style.RelativeSizeSpan;
|
|||||||
import android.text.style.StyleSpan;
|
import android.text.style.StyleSpan;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.ActionMode;
|
import android.view.ActionMode;
|
||||||
import android.view.Gravity;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
@ -307,6 +306,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
|||||||
private AccountRepository accountRepository;
|
private AccountRepository accountRepository;
|
||||||
private FavoriteRepository favoriteRepository;
|
private FavoriteRepository favoriteRepository;
|
||||||
private AppStateViewModel appStateViewModel;
|
private AppStateViewModel appStateViewModel;
|
||||||
|
private boolean disableDm = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||||
@ -322,8 +322,10 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
|||||||
mediaService = isLoggedIn ? MediaService.getInstance(null, null, 0) : null;
|
mediaService = isLoggedIn ? MediaService.getInstance(null, null, 0) : null;
|
||||||
userService = isLoggedIn ? UserService.getInstance() : null;
|
userService = isLoggedIn ? UserService.getInstance() : null;
|
||||||
graphQLService = isLoggedIn ? null : GraphQLService.getInstance();
|
graphQLService = isLoggedIn ? null : GraphQLService.getInstance();
|
||||||
accountRepository = AccountRepository.getInstance(AccountDataSource.getInstance(getContext()));
|
final Context context = getContext();
|
||||||
favoriteRepository = FavoriteRepository.getInstance(FavoriteDataSource.getInstance(getContext()));
|
if (context == null) return;
|
||||||
|
accountRepository = AccountRepository.getInstance(AccountDataSource.getInstance(context));
|
||||||
|
favoriteRepository = FavoriteRepository.getInstance(FavoriteDataSource.getInstance(context));
|
||||||
appStateViewModel = new ViewModelProvider(fragmentActivity).get(AppStateViewModel.class);
|
appStateViewModel = new ViewModelProvider(fragmentActivity).get(AppStateViewModel.class);
|
||||||
setHasOptionsMenu(true);
|
setHasOptionsMenu(true);
|
||||||
}
|
}
|
||||||
@ -578,6 +580,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void init() {
|
private void init() {
|
||||||
|
disableDm = !Utils.isNavRootInCurrentTabs("direct_messages_nav_graph");
|
||||||
if (getArguments() != null) {
|
if (getArguments() != null) {
|
||||||
final ProfileFragmentArgs fragmentArgs = ProfileFragmentArgs.fromBundle(getArguments());
|
final ProfileFragmentArgs fragmentArgs = ProfileFragmentArgs.fromBundle(getArguments());
|
||||||
username = fragmentArgs.getUsername();
|
username = fragmentArgs.getUsername();
|
||||||
@ -604,12 +607,16 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
|||||||
usernameTemp = usernameTemp.substring(1);
|
usernameTemp = usernameTemp.substring(1);
|
||||||
}
|
}
|
||||||
if (TextUtils.isEmpty(usernameTemp)) {
|
if (TextUtils.isEmpty(usernameTemp)) {
|
||||||
profileModel = appStateViewModel.getCurrentUser();
|
appStateViewModel.getCurrentUserLiveData().observe(getViewLifecycleOwner(), user -> {
|
||||||
|
if (user == null) return;
|
||||||
|
profileModel = user;
|
||||||
username = profileModel.getUsername();
|
username = profileModel.getUsername();
|
||||||
setUsernameDelayed();
|
setUsernameDelayed();
|
||||||
setProfileDetails();
|
setProfileDetails();
|
||||||
|
});
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else if (isLoggedIn) {
|
if (isLoggedIn) {
|
||||||
userService.getUsernameInfo(usernameTemp, new ServiceCallback<User>() {
|
userService.getUsernameInfo(usernameTemp, new ServiceCallback<User>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(final User user) {
|
public void onSuccess(final User user) {
|
||||||
@ -643,8 +650,8 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
|||||||
} catch (final Throwable ignored) {}
|
} catch (final Throwable ignored) {}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
graphQLService.fetchUser(usernameTemp, new ServiceCallback<User>() {
|
graphQLService.fetchUser(usernameTemp, new ServiceCallback<User>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(final User user) {
|
public void onSuccess(final User user) {
|
||||||
@ -663,7 +670,6 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private void setProfileDetails() {
|
private void setProfileDetails() {
|
||||||
final Context context = getContext();
|
final Context context = getContext();
|
||||||
@ -936,7 +942,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
|||||||
}
|
}
|
||||||
profileDetailsBinding.btnSaved.setVisibility(View.GONE);
|
profileDetailsBinding.btnSaved.setVisibility(View.GONE);
|
||||||
profileDetailsBinding.btnLiked.setVisibility(View.GONE);
|
profileDetailsBinding.btnLiked.setVisibility(View.GONE);
|
||||||
profileDetailsBinding.btnDM.setVisibility(View.VISIBLE);
|
profileDetailsBinding.btnDM.setVisibility(disableDm ? View.GONE : View.VISIBLE);
|
||||||
profileDetailsBinding.btnFollow.setVisibility(View.VISIBLE);
|
profileDetailsBinding.btnFollow.setVisibility(View.VISIBLE);
|
||||||
final Context context = getContext();
|
final Context context = getContext();
|
||||||
if (context == null) return;
|
if (context == null) return;
|
||||||
@ -987,6 +993,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateAccountInfo() {
|
private void updateAccountInfo() {
|
||||||
|
if (profileModel == null) return;
|
||||||
accountRepository.insertOrUpdateAccount(
|
accountRepository.insertOrUpdateAccount(
|
||||||
profileModel.getPk(),
|
profileModel.getPk(),
|
||||||
profileModel.getUsername(),
|
profileModel.getUsername(),
|
||||||
@ -1113,6 +1120,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
|||||||
PostItemType.TAGGED);
|
PostItemType.TAGGED);
|
||||||
NavHostFragment.findNavController(this).navigate(action);
|
NavHostFragment.findNavController(this).navigate(action);
|
||||||
});
|
});
|
||||||
|
if (!disableDm) {
|
||||||
profileDetailsBinding.btnDM.setOnClickListener(v -> {
|
profileDetailsBinding.btnDM.setOnClickListener(v -> {
|
||||||
profileDetailsBinding.btnDM.setEnabled(false);
|
profileDetailsBinding.btnDM.setEnabled(false);
|
||||||
new CreateThreadAction(cookie, profileModel.getPk(), thread -> {
|
new CreateThreadAction(cookie, profileModel.getPk(), thread -> {
|
||||||
@ -1130,6 +1138,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
|||||||
profileDetailsBinding.btnDM.setEnabled(true);
|
profileDetailsBinding.btnDM.setEnabled(true);
|
||||||
}).execute();
|
}).execute();
|
||||||
});
|
});
|
||||||
|
}
|
||||||
profileDetailsBinding.mainProfileImage.setOnClickListener(v -> {
|
profileDetailsBinding.mainProfileImage.setOnClickListener(v -> {
|
||||||
if (!hasStories) {
|
if (!hasStories) {
|
||||||
// show profile pic
|
// show profile pic
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package awais.instagrabber.fragments.settings;
|
package awais.instagrabber.fragments.settings;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.TypedArray;
|
import android.util.Pair;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.preference.ListPreference;
|
import androidx.preference.ListPreference;
|
||||||
@ -12,13 +12,17 @@ import androidx.preference.SwitchPreferenceCompat;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import awais.instagrabber.R;
|
import awais.instagrabber.R;
|
||||||
|
import awais.instagrabber.dialogs.ConfirmDialogFragment;
|
||||||
|
import awais.instagrabber.dialogs.TabOrderPreferenceDialogFragment;
|
||||||
|
import awais.instagrabber.models.Tab;
|
||||||
import awais.instagrabber.utils.Constants;
|
import awais.instagrabber.utils.Constants;
|
||||||
import awais.instagrabber.utils.CookieUtils;
|
import awais.instagrabber.utils.CookieUtils;
|
||||||
import awais.instagrabber.utils.TextUtils;
|
import awais.instagrabber.utils.TextUtils;
|
||||||
|
import awais.instagrabber.utils.Utils;
|
||||||
|
|
||||||
import static awais.instagrabber.utils.Utils.settingsHelper;
|
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||||
|
|
||||||
public class GeneralPreferencesFragment extends BasePreferencesFragment {
|
public class GeneralPreferencesFragment extends BasePreferencesFragment implements TabOrderPreferenceDialogFragment.Callback {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void setupPreferenceScreen(final PreferenceScreen screen) {
|
void setupPreferenceScreen(final PreferenceScreen screen) {
|
||||||
@ -28,10 +32,12 @@ public class GeneralPreferencesFragment extends BasePreferencesFragment {
|
|||||||
final boolean isLoggedIn = !TextUtils.isEmpty(cookie) && CookieUtils.getUserIdFromCookie(cookie) > 0;
|
final boolean isLoggedIn = !TextUtils.isEmpty(cookie) && CookieUtils.getUserIdFromCookie(cookie) > 0;
|
||||||
if (isLoggedIn) {
|
if (isLoggedIn) {
|
||||||
screen.addPreference(getDefaultTabPreference(context));
|
screen.addPreference(getDefaultTabPreference(context));
|
||||||
|
screen.addPreference(getTabOrderPreference(context));
|
||||||
}
|
}
|
||||||
screen.addPreference(getUpdateCheckPreference(context));
|
screen.addPreference(getUpdateCheckPreference(context));
|
||||||
screen.addPreference(getFlagSecurePreference(context));
|
screen.addPreference(getFlagSecurePreference(context));
|
||||||
final List<Preference> preferences = FlavorSettings.getInstance().getPreferences(context,
|
final List<Preference> preferences = FlavorSettings.getInstance()
|
||||||
|
.getPreferences(context,
|
||||||
getChildFragmentManager(),
|
getChildFragmentManager(),
|
||||||
SettingCategory.GENERAL);
|
SettingCategory.GENERAL);
|
||||||
if (preferences != null) {
|
if (preferences != null) {
|
||||||
@ -44,24 +50,36 @@ public class GeneralPreferencesFragment extends BasePreferencesFragment {
|
|||||||
private Preference getDefaultTabPreference(@NonNull final Context context) {
|
private Preference getDefaultTabPreference(@NonNull final Context context) {
|
||||||
final ListPreference preference = new ListPreference(context);
|
final ListPreference preference = new ListPreference(context);
|
||||||
preference.setSummaryProvider(ListPreference.SimpleSummaryProvider.getInstance());
|
preference.setSummaryProvider(ListPreference.SimpleSummaryProvider.getInstance());
|
||||||
final TypedArray mainNavIds = getResources().obtainTypedArray(R.array.main_nav_ids);
|
final Pair<List<Tab>, List<Tab>> listPair = Utils.getNavTabList(context);
|
||||||
final int length = mainNavIds.length();
|
final List<Tab> tabs = listPair.first;
|
||||||
final String[] values = new String[length];
|
final String[] titles = tabs.stream()
|
||||||
for (int i = 0; i < length; i++) {
|
.map(Tab::getTitle)
|
||||||
final int resourceId = mainNavIds.getResourceId(i, -1);
|
.toArray(String[]::new);
|
||||||
if (resourceId < 0) continue;
|
final String[] navGraphFileNames = tabs.stream()
|
||||||
values[i] = getResources().getResourceEntryName(resourceId);
|
.map(Tab::getGraphName)
|
||||||
}
|
.toArray(String[]::new);
|
||||||
mainNavIds.recycle();
|
|
||||||
preference.setKey(Constants.DEFAULT_TAB);
|
preference.setKey(Constants.DEFAULT_TAB);
|
||||||
preference.setTitle(R.string.pref_start_screen);
|
preference.setTitle(R.string.pref_start_screen);
|
||||||
preference.setDialogTitle(R.string.pref_start_screen);
|
preference.setDialogTitle(R.string.pref_start_screen);
|
||||||
preference.setEntries(R.array.main_nav_ids_values);
|
preference.setEntries(titles);
|
||||||
preference.setEntryValues(values);
|
preference.setEntryValues(navGraphFileNames);
|
||||||
preference.setIconSpaceReserved(false);
|
preference.setIconSpaceReserved(false);
|
||||||
return preference;
|
return preference;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private Preference getTabOrderPreference(@NonNull final Context context) {
|
||||||
|
final Preference preference = new Preference(context);
|
||||||
|
preference.setTitle(R.string.tab_order);
|
||||||
|
preference.setIconSpaceReserved(false);
|
||||||
|
preference.setOnPreferenceClickListener(preference1 -> {
|
||||||
|
final TabOrderPreferenceDialogFragment dialogFragment = TabOrderPreferenceDialogFragment.newInstance();
|
||||||
|
dialogFragment.show(getChildFragmentManager(), "tab_order_dialog");
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
return preference;
|
||||||
|
}
|
||||||
|
|
||||||
private Preference getUpdateCheckPreference(@NonNull final Context context) {
|
private Preference getUpdateCheckPreference(@NonNull final Context context) {
|
||||||
final SwitchPreferenceCompat preference = new SwitchPreferenceCompat(context);
|
final SwitchPreferenceCompat preference = new SwitchPreferenceCompat(context);
|
||||||
preference.setKey(Constants.CHECK_UPDATES);
|
preference.setKey(Constants.CHECK_UPDATES);
|
||||||
@ -82,4 +100,22 @@ public class GeneralPreferencesFragment extends BasePreferencesFragment {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSave(final boolean orderHasChanged) {
|
||||||
|
if (!orderHasChanged) return;
|
||||||
|
final ConfirmDialogFragment dialogFragment = ConfirmDialogFragment.newInstance(
|
||||||
|
111,
|
||||||
|
0,
|
||||||
|
R.string.tab_order_start_next_launch,
|
||||||
|
R.string.ok,
|
||||||
|
0,
|
||||||
|
0);
|
||||||
|
dialogFragment.show(getChildFragmentManager(), "tab_order_set_dialog");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCancel() {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ import java.util.List;
|
|||||||
import awais.instagrabber.BuildConfig;
|
import awais.instagrabber.BuildConfig;
|
||||||
import awais.instagrabber.R;
|
import awais.instagrabber.R;
|
||||||
import awais.instagrabber.activities.Login;
|
import awais.instagrabber.activities.Login;
|
||||||
|
import awais.instagrabber.activities.MainActivity;
|
||||||
import awais.instagrabber.databinding.PrefAccountSwitcherBinding;
|
import awais.instagrabber.databinding.PrefAccountSwitcherBinding;
|
||||||
import awais.instagrabber.db.datasources.AccountDataSource;
|
import awais.instagrabber.db.datasources.AccountDataSource;
|
||||||
import awais.instagrabber.db.entities.Account;
|
import awais.instagrabber.db.entities.Account;
|
||||||
@ -38,6 +39,7 @@ import awais.instagrabber.utils.Constants;
|
|||||||
import awais.instagrabber.utils.CookieUtils;
|
import awais.instagrabber.utils.CookieUtils;
|
||||||
import awais.instagrabber.utils.FlavorTown;
|
import awais.instagrabber.utils.FlavorTown;
|
||||||
import awais.instagrabber.utils.TextUtils;
|
import awais.instagrabber.utils.TextUtils;
|
||||||
|
import awais.instagrabber.utils.Utils;
|
||||||
import awais.instagrabber.webservices.ServiceCallback;
|
import awais.instagrabber.webservices.ServiceCallback;
|
||||||
import awais.instagrabber.webservices.UserService;
|
import awais.instagrabber.webservices.UserService;
|
||||||
|
|
||||||
@ -55,8 +57,10 @@ public class MorePreferencesFragment extends BasePreferencesFragment {
|
|||||||
void setupPreferenceScreen(final PreferenceScreen screen) {
|
void setupPreferenceScreen(final PreferenceScreen screen) {
|
||||||
final String cookie = settingsHelper.getString(Constants.COOKIE);
|
final String cookie = settingsHelper.getString(Constants.COOKIE);
|
||||||
final boolean isLoggedIn = !TextUtils.isEmpty(cookie) && CookieUtils.getUserIdFromCookie(cookie) > 0;
|
final boolean isLoggedIn = !TextUtils.isEmpty(cookie) && CookieUtils.getUserIdFromCookie(cookie) > 0;
|
||||||
|
final MainActivity activity = (MainActivity) getActivity();
|
||||||
// screen.addPreference(new MoreHeaderPreference(getContext()));
|
// screen.addPreference(new MoreHeaderPreference(getContext()));
|
||||||
final Context context = getContext();
|
final Context context = getContext();
|
||||||
|
final Resources resources = context.getResources();
|
||||||
if (context == null) return;
|
if (context == null) return;
|
||||||
accountRepository = AccountRepository.getInstance(AccountDataSource.getInstance(context));
|
accountRepository = AccountRepository.getInstance(AccountDataSource.getInstance(context));
|
||||||
final PreferenceCategory accountCategory = new PreferenceCategory(context);
|
final PreferenceCategory accountCategory = new PreferenceCategory(context);
|
||||||
@ -135,6 +139,13 @@ public class MorePreferencesFragment extends BasePreferencesFragment {
|
|||||||
screen.addPreference(getDivider(context));
|
screen.addPreference(getDivider(context));
|
||||||
final NavController navController = NavHostFragment.findNavController(this);
|
final NavController navController = NavHostFragment.findNavController(this);
|
||||||
if (isLoggedIn) {
|
if (isLoggedIn) {
|
||||||
|
boolean showActivity = true;
|
||||||
|
boolean showExplore = false;
|
||||||
|
if (activity != null) {
|
||||||
|
showActivity = !Utils.isNavRootInCurrentTabs("notification_viewer_nav_graph");
|
||||||
|
showExplore = !Utils.isNavRootInCurrentTabs("discover_nav_graph");
|
||||||
|
}
|
||||||
|
if (showActivity) {
|
||||||
screen.addPreference(getPreference(R.string.action_notif, R.drawable.ic_not_liked, preference -> {
|
screen.addPreference(getPreference(R.string.action_notif, R.drawable.ic_not_liked, preference -> {
|
||||||
if (isSafeToNavigate(navController)) {
|
if (isSafeToNavigate(navController)) {
|
||||||
final NavDirections navDirections = MorePreferencesFragmentDirections.actionGlobalNotificationsViewerFragment("notif");
|
final NavDirections navDirections = MorePreferencesFragmentDirections.actionGlobalNotificationsViewerFragment("notif");
|
||||||
@ -142,6 +153,16 @@ public class MorePreferencesFragment extends BasePreferencesFragment {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}));
|
}));
|
||||||
|
}
|
||||||
|
if (showExplore) {
|
||||||
|
screen.addPreference(getPreference(R.string.title_discover, R.drawable.ic_explore_24, preference -> {
|
||||||
|
if (isSafeToNavigate(navController)) {
|
||||||
|
navController.navigate(R.id.discover_nav_graph);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
screen.addPreference(getPreference(R.string.action_ayml, R.drawable.ic_suggested_users, preference -> {
|
screen.addPreference(getPreference(R.string.action_ayml, R.drawable.ic_suggested_users, preference -> {
|
||||||
if (isSafeToNavigate(navController)) {
|
if (isSafeToNavigate(navController)) {
|
||||||
final NavDirections navDirections = MorePreferencesFragmentDirections.actionGlobalNotificationsViewerFragment("ayml");
|
final NavDirections navDirections = MorePreferencesFragmentDirections.actionGlobalNotificationsViewerFragment("ayml");
|
||||||
@ -157,6 +178,13 @@ public class MorePreferencesFragment extends BasePreferencesFragment {
|
|||||||
return true;
|
return true;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if favorites has been added as a tab. And if so, do not add in this list
|
||||||
|
boolean showFavorites = true;
|
||||||
|
if (activity != null) {
|
||||||
|
showFavorites = !Utils.isNavRootInCurrentTabs("favorites_nav_graph");
|
||||||
|
}
|
||||||
|
if (showFavorites) {
|
||||||
screen.addPreference(getPreference(R.string.title_favorites, R.drawable.ic_star_24, preference -> {
|
screen.addPreference(getPreference(R.string.title_favorites, R.drawable.ic_star_24, preference -> {
|
||||||
if (isSafeToNavigate(navController)) {
|
if (isSafeToNavigate(navController)) {
|
||||||
final NavDirections navDirections = MorePreferencesFragmentDirections.actionMorePreferencesFragmentToFavoritesFragment();
|
final NavDirections navDirections = MorePreferencesFragmentDirections.actionMorePreferencesFragmentToFavoritesFragment();
|
||||||
@ -164,6 +192,7 @@ public class MorePreferencesFragment extends BasePreferencesFragment {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}));
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
screen.addPreference(getDivider(context));
|
screen.addPreference(getDivider(context));
|
||||||
screen.addPreference(getPreference(R.string.action_settings, R.drawable.ic_outline_settings_24, preference -> {
|
screen.addPreference(getPreference(R.string.action_settings, R.drawable.ic_outline_settings_24, preference -> {
|
||||||
|
@ -15,7 +15,7 @@ public class NotificationsPreferencesFragment extends BasePreferencesFragment {
|
|||||||
final Context context = getContext();
|
final Context context = getContext();
|
||||||
if (context == null) return;
|
if (context == null) return;
|
||||||
screen.addPreference(getActivityNotificationsPreference(context));
|
screen.addPreference(getActivityNotificationsPreference(context));
|
||||||
screen.addPreference(getDMNotificationsPreference(context));
|
// screen.addPreference(getDMNotificationsPreference(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Preference getActivityNotificationsPreference(@NonNull final Context context) {
|
private Preference getActivityNotificationsPreference(@NonNull final Context context) {
|
||||||
|
@ -6,4 +6,5 @@ public final class PreferenceKeys {
|
|||||||
public static final String PREF_ENABLE_DM_AUTO_REFRESH_FREQ_UNIT = "enable_dm_auto_refresh_freq_unit";
|
public static final String PREF_ENABLE_DM_AUTO_REFRESH_FREQ_UNIT = "enable_dm_auto_refresh_freq_unit";
|
||||||
public static final String PREF_ENABLE_DM_AUTO_REFRESH_FREQ_NUMBER = "enable_dm_auto_refresh_freq_number";
|
public static final String PREF_ENABLE_DM_AUTO_REFRESH_FREQ_NUMBER = "enable_dm_auto_refresh_freq_number";
|
||||||
public static final String PREF_ENABLE_SENTRY = "enable_sentry";
|
public static final String PREF_ENABLE_SENTRY = "enable_sentry";
|
||||||
|
public static final String PREF_TAB_ORDER = "tab_order";
|
||||||
}
|
}
|
||||||
|
110
app/src/main/java/awais/instagrabber/models/Tab.java
Normal file
110
app/src/main/java/awais/instagrabber/models/Tab.java
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
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/<b>graphName</b>
|
||||||
|
*/
|
||||||
|
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.
|
||||||
|
* <p>eg: inside R.navigation.direct_messages_nav_graph, the id of the root tag is R.id.direct_messages_nav_graph.
|
||||||
|
* <p>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 + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,7 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public enum DirectItemType implements Serializable {
|
public enum DirectItemType implements Serializable {
|
||||||
|
UNKNOWN(0),
|
||||||
@SerializedName("text")
|
@SerializedName("text")
|
||||||
TEXT(1),
|
TEXT(1),
|
||||||
@SerializedName("like")
|
@SerializedName("like")
|
||||||
@ -40,7 +41,9 @@ public enum DirectItemType implements Serializable {
|
|||||||
@SerializedName("felix_share")
|
@SerializedName("felix_share")
|
||||||
FELIX_SHARE(16), // media_share but igtv
|
FELIX_SHARE(16), // media_share but igtv
|
||||||
@SerializedName("location")
|
@SerializedName("location")
|
||||||
LOCATION(17);
|
LOCATION(17),
|
||||||
|
@SerializedName("xma")
|
||||||
|
XMA(18); // self avatar stickers
|
||||||
|
|
||||||
private final int id;
|
private final int id;
|
||||||
private static final Map<Integer, DirectItemType> map = new HashMap<>();
|
private static final Map<Integer, DirectItemType> map = new HashMap<>();
|
||||||
@ -60,6 +63,7 @@ public enum DirectItemType implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static DirectItemType valueOf(final int id) {
|
public static DirectItemType valueOf(final int id) {
|
||||||
|
if (!map.containsKey(id)) return DirectItemType.UNKNOWN;
|
||||||
return map.get(id);
|
return map.get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@ package awais.instagrabber.repositories;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import awais.instagrabber.repositories.responses.search.SearchResponse;
|
import awais.instagrabber.repositories.responses.search.SearchResponse;
|
||||||
|
|
||||||
import retrofit2.Call;
|
import retrofit2.Call;
|
||||||
import retrofit2.http.GET;
|
import retrofit2.http.GET;
|
||||||
import retrofit2.http.QueryMap;
|
import retrofit2.http.QueryMap;
|
||||||
|
@ -41,6 +41,7 @@ public class DirectItem implements Cloneable, Serializable {
|
|||||||
private final DirectItem repliedToMessage;
|
private final DirectItem repliedToMessage;
|
||||||
private final DirectItemVoiceMedia voiceMedia;
|
private final DirectItemVoiceMedia voiceMedia;
|
||||||
private final Location location;
|
private final Location location;
|
||||||
|
private final DirectItemXma xma;
|
||||||
private final int hideInThread;
|
private final int hideInThread;
|
||||||
private Date date;
|
private Date date;
|
||||||
private boolean isPending;
|
private boolean isPending;
|
||||||
@ -72,6 +73,7 @@ public class DirectItem implements Cloneable, Serializable {
|
|||||||
final DirectItem repliedToMessage,
|
final DirectItem repliedToMessage,
|
||||||
final DirectItemVoiceMedia voiceMedia,
|
final DirectItemVoiceMedia voiceMedia,
|
||||||
final Location location,
|
final Location location,
|
||||||
|
final DirectItemXma xma,
|
||||||
final int hideInThread,
|
final int hideInThread,
|
||||||
final boolean showForwardAttribution) {
|
final boolean showForwardAttribution) {
|
||||||
this.itemId = itemId;
|
this.itemId = itemId;
|
||||||
@ -99,6 +101,7 @@ public class DirectItem implements Cloneable, Serializable {
|
|||||||
this.repliedToMessage = repliedToMessage;
|
this.repliedToMessage = repliedToMessage;
|
||||||
this.voiceMedia = voiceMedia;
|
this.voiceMedia = voiceMedia;
|
||||||
this.location = location;
|
this.location = location;
|
||||||
|
this.xma = xma;
|
||||||
this.hideInThread = hideInThread;
|
this.hideInThread = hideInThread;
|
||||||
this.showForwardAttribution = showForwardAttribution;
|
this.showForwardAttribution = showForwardAttribution;
|
||||||
}
|
}
|
||||||
@ -208,6 +211,10 @@ public class DirectItem implements Cloneable, Serializable {
|
|||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DirectItemXma getXma() {
|
||||||
|
return xma;
|
||||||
|
}
|
||||||
|
|
||||||
public int getHideInThread() {
|
public int getHideInThread() {
|
||||||
return hideInThread;
|
return hideInThread;
|
||||||
}
|
}
|
||||||
@ -286,6 +293,7 @@ public class DirectItem implements Cloneable, Serializable {
|
|||||||
Objects.equals(repliedToMessage, that.repliedToMessage) &&
|
Objects.equals(repliedToMessage, that.repliedToMessage) &&
|
||||||
Objects.equals(voiceMedia, that.voiceMedia) &&
|
Objects.equals(voiceMedia, that.voiceMedia) &&
|
||||||
Objects.equals(location, that.location) &&
|
Objects.equals(location, that.location) &&
|
||||||
|
Objects.equals(xma, that.xma) &&
|
||||||
Objects.equals(date, that.date);
|
Objects.equals(date, that.date);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,6 +302,6 @@ public class DirectItem implements Cloneable, Serializable {
|
|||||||
return Objects
|
return Objects
|
||||||
.hash(itemId, userId, timestamp, itemType, text, like, link, clientContext, reelShare, storyShare, mediaShare, profile, placeholder,
|
.hash(itemId, userId, timestamp, itemType, text, like, link, clientContext, reelShare, storyShare, mediaShare, profile, placeholder,
|
||||||
media, previewMedias, actionLog, videoCallEvent, clip, felixShare, visualMedia, animatedMedia, reactions, repliedToMessage,
|
media, previewMedias, actionLog, videoCallEvent, clip, felixShare, visualMedia, animatedMedia, reactions, repliedToMessage,
|
||||||
voiceMedia, location, hideInThread, date, isPending, showForwardAttribution);
|
voiceMedia, location, xma, hideInThread, date, isPending, showForwardAttribution);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,104 @@
|
|||||||
|
package awais.instagrabber.repositories.responses.directmessages;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class DirectItemXma {
|
||||||
|
private final XmaUrlInfo previewUrlInfo;
|
||||||
|
private final XmaUrlInfo playableUrlInfo;
|
||||||
|
|
||||||
|
public DirectItemXma(final XmaUrlInfo previewUrlInfo, final XmaUrlInfo playableUrlInfo) {
|
||||||
|
this.previewUrlInfo = previewUrlInfo;
|
||||||
|
this.playableUrlInfo = playableUrlInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public XmaUrlInfo getPreviewUrlInfo() {
|
||||||
|
return previewUrlInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public XmaUrlInfo getPlayableUrlInfo() {
|
||||||
|
return playableUrlInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final DirectItemXma that = (DirectItemXma) o;
|
||||||
|
return Objects.equals(previewUrlInfo, that.previewUrlInfo) &&
|
||||||
|
Objects.equals(playableUrlInfo, that.playableUrlInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(previewUrlInfo, playableUrlInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "DirectItemXma{" +
|
||||||
|
"previewUrlInfo=" + previewUrlInfo +
|
||||||
|
", playableUrlInfo=" + playableUrlInfo +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class XmaUrlInfo implements Serializable {
|
||||||
|
private final String url;
|
||||||
|
private final long urlExpirationTimestampUs;
|
||||||
|
private final int width;
|
||||||
|
private final int height;
|
||||||
|
|
||||||
|
public XmaUrlInfo(final String url, final long urlExpirationTimestampUs, final int width, final int height) {
|
||||||
|
this.url = url;
|
||||||
|
this.urlExpirationTimestampUs = urlExpirationTimestampUs;
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getUrlExpirationTimestampUs() {
|
||||||
|
return urlExpirationTimestampUs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getWidth() {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHeight() {
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final XmaUrlInfo that = (XmaUrlInfo) o;
|
||||||
|
return urlExpirationTimestampUs == that.urlExpirationTimestampUs &&
|
||||||
|
width == that.width &&
|
||||||
|
height == that.height &&
|
||||||
|
Objects.equals(url, that.url);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(url, urlExpirationTimestampUs, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "XmaUrlInfo{" +
|
||||||
|
"url='" + url + '\'' +
|
||||||
|
", urlExpirationTimestampUs=" + urlExpirationTimestampUs +
|
||||||
|
", width=" + width +
|
||||||
|
", height=" + height +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,5 @@
|
|||||||
package awais.instagrabber.repositories.responses.notification;
|
package awais.instagrabber.repositories.responses.notification;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
public class NotificationCounts {
|
public class NotificationCounts {
|
||||||
private final int commentLikes;
|
private final int commentLikes;
|
||||||
private final int usertags;
|
private final int usertags;
|
||||||
|
@ -2,8 +2,6 @@ package awais.instagrabber.repositories.responses.search;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import awais.instagrabber.repositories.responses.User;
|
|
||||||
|
|
||||||
public class SearchResponse {
|
public class SearchResponse {
|
||||||
// app
|
// app
|
||||||
private final List<SearchItem> list;
|
private final List<SearchItem> list;
|
||||||
|
@ -44,9 +44,9 @@ public final class DMUtils {
|
|||||||
|
|
||||||
public static boolean isRead(@NonNull final DirectThread thread) {
|
public static boolean isRead(@NonNull final DirectThread thread) {
|
||||||
final boolean read;
|
final boolean read;
|
||||||
// if (thread.getDirectStory() != null) {
|
// if (thread.getDirectStory() != null) {
|
||||||
// return false;
|
// return false;
|
||||||
// }
|
// }
|
||||||
final DirectItem item = thread.getFirstDirectItem();
|
final DirectItem item = thread.getFirstDirectItem();
|
||||||
final long viewerId = thread.getViewerId();
|
final long viewerId = thread.getViewerId();
|
||||||
if (item != null && item.getUserId() == viewerId) {
|
if (item != null && item.getUserId() == viewerId) {
|
||||||
@ -188,6 +188,9 @@ public final class DMUtils {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case XMA:
|
||||||
|
subtitle = resources.getString(R.string.dms_inbox_shared_sticker, username != null ? username : "");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
message = resources.getString(R.string.dms_inbox_raven_message_unknown);
|
message = resources.getString(R.string.dms_inbox_raven_message_unknown);
|
||||||
}
|
}
|
||||||
@ -213,7 +216,14 @@ public final class DMUtils {
|
|||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.filter(user -> user.getPk() == userId)
|
.filter(user -> user.getPk() == userId)
|
||||||
.findFirst();
|
.findFirst();
|
||||||
return senderOptional.map(User::getUsername).orElse(null);
|
return senderOptional.map(user -> {
|
||||||
|
// return full name for fb users
|
||||||
|
final String username = user.getUsername();
|
||||||
|
if (TextUtils.isEmpty(username)) {
|
||||||
|
return user.getFullName();
|
||||||
|
}
|
||||||
|
return username;
|
||||||
|
}).orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getMediaSpecificSubtitle(final String username, final Resources resources, final MediaItemType mediaType) {
|
public static String getMediaSpecificSubtitle(final String username, final Resources resources, final MediaItemType mediaType) {
|
||||||
|
@ -51,6 +51,7 @@ public final class DirectItemFactory {
|
|||||||
repliedToMessage,
|
repliedToMessage,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
|
null,
|
||||||
0,
|
0,
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
@ -132,6 +133,7 @@ public final class DirectItemFactory {
|
|||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
|
null,
|
||||||
0,
|
0,
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
@ -213,6 +215,7 @@ public final class DirectItemFactory {
|
|||||||
null,
|
null,
|
||||||
voiceMedia,
|
voiceMedia,
|
||||||
null,
|
null,
|
||||||
|
null,
|
||||||
0,
|
0,
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
@ -253,6 +256,7 @@ public final class DirectItemFactory {
|
|||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
|
null,
|
||||||
0,
|
0,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
@ -156,12 +156,21 @@ public final class ExportImportUtils {
|
|||||||
query,
|
query,
|
||||||
favoriteType,
|
favoriteType,
|
||||||
favsObject.optString("s"),
|
favsObject.optString("s"),
|
||||||
favoriteType == FavoriteType.HASHTAG ? null
|
favoriteType == FavoriteType.USER ? favsObject.optString("pic_url") : null,
|
||||||
: favsObject.optString("pic_url"),
|
|
||||||
new Date(favsObject.getLong("d")));
|
new Date(favsObject.getLong("d")));
|
||||||
// Log.d(TAG, "importJson: favoriteModel: " + favoriteModel);
|
// Log.d(TAG, "importJson: favoriteModel: " + favoriteModel);
|
||||||
FavoriteRepository.getInstance(FavoriteDataSource.getInstance(context))
|
final FavoriteRepository favRepo = FavoriteRepository.getInstance(FavoriteDataSource.getInstance(context));
|
||||||
.insertOrUpdateFavorite(favorite, null);
|
favRepo.getFavorite(query, favoriteType, new RepositoryCallback<Favorite>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(final Favorite result) {
|
||||||
|
// local has priority since it's more frequently updated
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDataNotAvailable() {
|
||||||
|
favRepo.insertOrUpdateFavorite(favorite, null);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ import static awais.instagrabber.fragments.settings.PreferenceKeys.PREF_ENABLE_D
|
|||||||
import static awais.instagrabber.fragments.settings.PreferenceKeys.PREF_ENABLE_DM_AUTO_REFRESH_FREQ_UNIT;
|
import static awais.instagrabber.fragments.settings.PreferenceKeys.PREF_ENABLE_DM_AUTO_REFRESH_FREQ_UNIT;
|
||||||
import static awais.instagrabber.fragments.settings.PreferenceKeys.PREF_ENABLE_DM_NOTIFICATIONS;
|
import static awais.instagrabber.fragments.settings.PreferenceKeys.PREF_ENABLE_DM_NOTIFICATIONS;
|
||||||
import static awais.instagrabber.fragments.settings.PreferenceKeys.PREF_ENABLE_SENTRY;
|
import static awais.instagrabber.fragments.settings.PreferenceKeys.PREF_ENABLE_SENTRY;
|
||||||
|
import static awais.instagrabber.fragments.settings.PreferenceKeys.PREF_TAB_ORDER;
|
||||||
import static awais.instagrabber.utils.Constants.APP_LANGUAGE;
|
import static awais.instagrabber.utils.Constants.APP_LANGUAGE;
|
||||||
import static awais.instagrabber.utils.Constants.APP_THEME;
|
import static awais.instagrabber.utils.Constants.APP_THEME;
|
||||||
import static awais.instagrabber.utils.Constants.APP_UA;
|
import static awais.instagrabber.utils.Constants.APP_UA;
|
||||||
@ -37,12 +38,12 @@ import static awais.instagrabber.utils.Constants.DOWNLOAD_USER_FOLDER;
|
|||||||
import static awais.instagrabber.utils.Constants.FLAG_SECURE;
|
import static awais.instagrabber.utils.Constants.FLAG_SECURE;
|
||||||
import static awais.instagrabber.utils.Constants.FOLDER_PATH;
|
import static awais.instagrabber.utils.Constants.FOLDER_PATH;
|
||||||
import static awais.instagrabber.utils.Constants.FOLDER_SAVE_TO;
|
import static awais.instagrabber.utils.Constants.FOLDER_SAVE_TO;
|
||||||
|
import static awais.instagrabber.utils.Constants.KEYWORD_FILTERS;
|
||||||
import static awais.instagrabber.utils.Constants.MARK_AS_SEEN;
|
import static awais.instagrabber.utils.Constants.MARK_AS_SEEN;
|
||||||
import static awais.instagrabber.utils.Constants.MUTED_VIDEOS;
|
import static awais.instagrabber.utils.Constants.MUTED_VIDEOS;
|
||||||
import static awais.instagrabber.utils.Constants.PREF_DARK_THEME;
|
import static awais.instagrabber.utils.Constants.PREF_DARK_THEME;
|
||||||
import static awais.instagrabber.utils.Constants.PREF_EMOJI_VARIANTS;
|
import static awais.instagrabber.utils.Constants.PREF_EMOJI_VARIANTS;
|
||||||
import static awais.instagrabber.utils.Constants.PREF_HASHTAG_POSTS_LAYOUT;
|
import static awais.instagrabber.utils.Constants.PREF_HASHTAG_POSTS_LAYOUT;
|
||||||
import static awais.instagrabber.utils.Constants.KEYWORD_FILTERS;
|
|
||||||
import static awais.instagrabber.utils.Constants.PREF_LIGHT_THEME;
|
import static awais.instagrabber.utils.Constants.PREF_LIGHT_THEME;
|
||||||
import static awais.instagrabber.utils.Constants.PREF_LIKED_POSTS_LAYOUT;
|
import static awais.instagrabber.utils.Constants.PREF_LIKED_POSTS_LAYOUT;
|
||||||
import static awais.instagrabber.utils.Constants.PREF_LOCATION_POSTS_LAYOUT;
|
import static awais.instagrabber.utils.Constants.PREF_LOCATION_POSTS_LAYOUT;
|
||||||
@ -155,7 +156,7 @@ public final class SettingsHelper {
|
|||||||
CUSTOM_DATE_TIME_FORMAT, DEVICE_UUID, SKIPPED_VERSION, DEFAULT_TAB, PREF_DARK_THEME, PREF_LIGHT_THEME,
|
CUSTOM_DATE_TIME_FORMAT, DEVICE_UUID, SKIPPED_VERSION, DEFAULT_TAB, PREF_DARK_THEME, PREF_LIGHT_THEME,
|
||||||
PREF_POSTS_LAYOUT, PREF_PROFILE_POSTS_LAYOUT, PREF_TOPIC_POSTS_LAYOUT, PREF_HASHTAG_POSTS_LAYOUT,
|
PREF_POSTS_LAYOUT, PREF_PROFILE_POSTS_LAYOUT, PREF_TOPIC_POSTS_LAYOUT, PREF_HASHTAG_POSTS_LAYOUT,
|
||||||
PREF_LOCATION_POSTS_LAYOUT, PREF_LIKED_POSTS_LAYOUT, PREF_TAGGED_POSTS_LAYOUT, PREF_SAVED_POSTS_LAYOUT,
|
PREF_LOCATION_POSTS_LAYOUT, PREF_LIKED_POSTS_LAYOUT, PREF_TAGGED_POSTS_LAYOUT, PREF_SAVED_POSTS_LAYOUT,
|
||||||
STORY_SORT, PREF_EMOJI_VARIANTS, PREF_REACTIONS, PREF_ENABLE_DM_AUTO_REFRESH_FREQ_UNIT})
|
STORY_SORT, PREF_EMOJI_VARIANTS, PREF_REACTIONS, PREF_ENABLE_DM_AUTO_REFRESH_FREQ_UNIT, PREF_TAB_ORDER})
|
||||||
public @interface StringSettings {}
|
public @interface StringSettings {}
|
||||||
|
|
||||||
@StringDef({DOWNLOAD_USER_FOLDER, FOLDER_SAVE_TO, AUTOPLAY_VIDEOS, SHOW_QUICK_ACCESS_DIALOG, MUTED_VIDEOS,
|
@StringDef({DOWNLOAD_USER_FOLDER, FOLDER_SAVE_TO, AUTOPLAY_VIDEOS, SHOW_QUICK_ACCESS_DIALOG, MUTED_VIDEOS,
|
||||||
|
@ -2,8 +2,6 @@ package awais.instagrabber.utils;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.text.SpannableString;
|
import android.text.SpannableString;
|
||||||
import android.text.SpannableStringBuilder;
|
|
||||||
import android.text.Spanned;
|
|
||||||
import android.text.format.DateFormat;
|
import android.text.format.DateFormat;
|
||||||
import android.text.format.DateUtils;
|
import android.text.format.DateUtils;
|
||||||
import android.text.style.URLSpan;
|
import android.text.style.URLSpan;
|
||||||
@ -11,17 +9,12 @@ import android.util.Patterns;
|
|||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import awais.instagrabber.customviews.CommentMentionClickSpan;
|
|
||||||
|
|
||||||
public final class TextUtils {
|
public final class TextUtils {
|
||||||
// extracted from String class
|
// extracted from String class
|
||||||
|
@ -8,6 +8,7 @@ import android.content.ContentResolver;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
@ -30,6 +31,7 @@ import android.webkit.MimeTypeMap;
|
|||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.DrawableRes;
|
import androidx.annotation.DrawableRes;
|
||||||
|
import androidx.annotation.IdRes;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.ActionBar;
|
import androidx.appcompat.app.ActionBar;
|
||||||
@ -40,6 +42,8 @@ import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat;
|
|||||||
import com.google.android.exoplayer2.database.ExoDatabaseProvider;
|
import com.google.android.exoplayer2.database.ExoDatabaseProvider;
|
||||||
import com.google.android.exoplayer2.upstream.cache.LeastRecentlyUsedCacheEvictor;
|
import com.google.android.exoplayer2.upstream.cache.LeastRecentlyUsedCacheEvictor;
|
||||||
import com.google.android.exoplayer2.upstream.cache.SimpleCache;
|
import com.google.android.exoplayer2.upstream.cache.SimpleCache;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.Ordering;
|
||||||
import com.google.common.io.Files;
|
import com.google.common.io.Files;
|
||||||
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
@ -47,22 +51,25 @@ import org.json.JSONObject;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
//import javax.crypto.Mac;
|
|
||||||
//import javax.crypto.spec.SecretKeySpec;
|
|
||||||
|
|
||||||
import awais.instagrabber.R;
|
import awais.instagrabber.R;
|
||||||
|
import awais.instagrabber.fragments.settings.PreferenceKeys;
|
||||||
import awais.instagrabber.models.PostsLayoutPreferences;
|
import awais.instagrabber.models.PostsLayoutPreferences;
|
||||||
|
import awais.instagrabber.models.Tab;
|
||||||
import awais.instagrabber.models.enums.FavoriteType;
|
import awais.instagrabber.models.enums.FavoriteType;
|
||||||
//import awaisomereport.LogCollector;
|
|
||||||
|
|
||||||
public final class Utils {
|
public final class Utils {
|
||||||
private static final String TAG = "Utils";
|
private static final String TAG = "Utils";
|
||||||
private static final int VIDEO_CACHE_MAX_BYTES = 10 * 1024 * 1024;
|
private static final int VIDEO_CACHE_MAX_BYTES = 10 * 1024 * 1024;
|
||||||
|
|
||||||
// public static LogCollector logCollector;
|
// public static LogCollector logCollector;
|
||||||
public static SettingsHelper settingsHelper;
|
public static SettingsHelper settingsHelper;
|
||||||
public static boolean sessionVolumeFull = false;
|
public static boolean sessionVolumeFull = false;
|
||||||
public static final MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
|
public static final MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
|
||||||
@ -74,6 +81,7 @@ public final class Utils {
|
|||||||
private static int actionBarHeight;
|
private static int actionBarHeight;
|
||||||
public static Handler applicationHandler;
|
public static Handler applicationHandler;
|
||||||
public static String cacheDir;
|
public static String cacheDir;
|
||||||
|
public static String tabOrderString;
|
||||||
private static int defaultStatusBarColor;
|
private static int defaultStatusBarColor;
|
||||||
|
|
||||||
public static int convertDpToPx(final float dp) {
|
public static int convertDpToPx(final float dp) {
|
||||||
@ -93,34 +101,34 @@ public final class Utils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Map<String, String> sign(final Map<String, Object> form) {
|
public static Map<String, String> sign(final Map<String, Object> form) {
|
||||||
// final String signed = sign(Constants.SIGNATURE_KEY, new JSONObject(form).toString());
|
// final String signed = sign(Constants.SIGNATURE_KEY, new JSONObject(form).toString());
|
||||||
// if (signed == null) {
|
// if (signed == null) {
|
||||||
// return null;
|
// return null;
|
||||||
// }
|
// }
|
||||||
final Map<String, String> map = new HashMap<>();
|
final Map<String, String> map = new HashMap<>();
|
||||||
// map.put("ig_sig_key_version", Constants.SIGNATURE_VERSION);
|
// map.put("ig_sig_key_version", Constants.SIGNATURE_VERSION);
|
||||||
// map.put("signed_body", signed);
|
// map.put("signed_body", signed);
|
||||||
map.put("signed_body", "SIGNATURE." + new JSONObject(form).toString());
|
map.put("signed_body", "SIGNATURE." + new JSONObject(form).toString());
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
// public static String sign(final String key, final String message) {
|
// public static String sign(final String key, final String message) {
|
||||||
// try {
|
// try {
|
||||||
// final Mac hasher = Mac.getInstance("HmacSHA256");
|
// final Mac hasher = Mac.getInstance("HmacSHA256");
|
||||||
// hasher.init(new SecretKeySpec(key.getBytes(), "HmacSHA256"));
|
// hasher.init(new SecretKeySpec(key.getBytes(), "HmacSHA256"));
|
||||||
// byte[] hash = hasher.doFinal(message.getBytes());
|
// byte[] hash = hasher.doFinal(message.getBytes());
|
||||||
// final StringBuilder hexString = new StringBuilder();
|
// final StringBuilder hexString = new StringBuilder();
|
||||||
// for (byte b : hash) {
|
// for (byte b : hash) {
|
||||||
// final String hex = Integer.toHexString(0xff & b);
|
// final String hex = Integer.toHexString(0xff & b);
|
||||||
// if (hex.length() == 1) hexString.append('0');
|
// if (hex.length() == 1) hexString.append('0');
|
||||||
// hexString.append(hex);
|
// hexString.append(hex);
|
||||||
// }
|
// }
|
||||||
// return hexString.toString() + "." + message;
|
// return hexString.toString() + "." + message;
|
||||||
// } catch (Exception e) {
|
// } catch (Exception e) {
|
||||||
// Log.e(TAG, "Error signing", e);
|
// Log.e(TAG, "Error signing", e);
|
||||||
// return null;
|
// return null;
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
public static String getMimeType(@NonNull final Uri uri, final ContentResolver contentResolver) {
|
public static String getMimeType(@NonNull final Uri uri, final ContentResolver contentResolver) {
|
||||||
String mimeType;
|
String mimeType;
|
||||||
@ -371,4 +379,116 @@ public final class Utils {
|
|||||||
if (window == null) return;
|
if (window == null) return;
|
||||||
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <T> void moveItem(int sourceIndex, int targetIndex, List<T> list) {
|
||||||
|
if (sourceIndex <= targetIndex) {
|
||||||
|
Collections.rotate(list.subList(sourceIndex, targetIndex + 1), -1);
|
||||||
|
} else {
|
||||||
|
Collections.rotate(list.subList(targetIndex, sourceIndex + 1), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final List<Integer> NON_REMOVABLE_NAV_ROOT_IDS = ImmutableList.of(R.id.profile_nav_graph, R.id.more_nav_graph);
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public static Pair<List<Tab>, List<Tab>> getNavTabList(@NonNull final Context context) {
|
||||||
|
final Resources resources = context.getResources();
|
||||||
|
final String[] titleArray = resources.getStringArray(R.array.main_nav_titles);
|
||||||
|
|
||||||
|
TypedArray typedArray = resources.obtainTypedArray(R.array.main_nav_graphs);
|
||||||
|
int length = typedArray.length();
|
||||||
|
final String[] navGraphNames = new String[length];
|
||||||
|
final int[] navigationResIds = new int[length];
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
final int resourceId = typedArray.getResourceId(i, 0);
|
||||||
|
if (resourceId == 0) continue;
|
||||||
|
navigationResIds[i] = resourceId;
|
||||||
|
navGraphNames[i] = resources.getResourceEntryName(resourceId);
|
||||||
|
}
|
||||||
|
typedArray.recycle();
|
||||||
|
|
||||||
|
typedArray = resources.obtainTypedArray(R.array.main_nav_graph_root_ids);
|
||||||
|
length = typedArray.length();
|
||||||
|
final int[] navRootIds = new int[length];
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
final int resourceId = typedArray.getResourceId(i, 0);
|
||||||
|
if (resourceId == 0) continue;
|
||||||
|
navRootIds[i] = resourceId;
|
||||||
|
}
|
||||||
|
typedArray.recycle();
|
||||||
|
|
||||||
|
typedArray = resources.obtainTypedArray(R.array.main_nav_drawables);
|
||||||
|
length = typedArray.length();
|
||||||
|
final int[] iconIds = new int[length];
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
final int resourceId = typedArray.getResourceId(i, 0);
|
||||||
|
if (resourceId == 0) continue;
|
||||||
|
iconIds[i] = resourceId;
|
||||||
|
}
|
||||||
|
typedArray.recycle();
|
||||||
|
|
||||||
|
typedArray = resources.obtainTypedArray(R.array.main_nav_start_dest_frag_ids);
|
||||||
|
length = typedArray.length();
|
||||||
|
final int[] startDestFragIds = new int[length];
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
final int resourceId = typedArray.getResourceId(i, 0);
|
||||||
|
if (resourceId == 0) continue;
|
||||||
|
startDestFragIds[i] = resourceId;
|
||||||
|
}
|
||||||
|
typedArray.recycle();
|
||||||
|
|
||||||
|
final List<String> currentOrderGraphNames = getCurrentOrderOfGraphNamesFromPref(navGraphNames);
|
||||||
|
|
||||||
|
if (titleArray.length != iconIds.length || titleArray.length != navGraphNames.length) {
|
||||||
|
throw new RuntimeException(String.format("Array lengths don't match!: titleArray%s, navGraphNames: %s, iconIds: %s",
|
||||||
|
Arrays.toString(titleArray), Arrays.toString(navGraphNames), Arrays.toString(iconIds)));
|
||||||
|
}
|
||||||
|
final List<Tab> tabs = new ArrayList<>();
|
||||||
|
final List<Tab> otherTabs = new ArrayList<>(); // Will contain tabs not in current list
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
final String navGraphName = navGraphNames[i];
|
||||||
|
final int navRootId = navRootIds[i];
|
||||||
|
final Tab tab = new Tab(iconIds[i],
|
||||||
|
titleArray[i],
|
||||||
|
!NON_REMOVABLE_NAV_ROOT_IDS.contains(navRootId),
|
||||||
|
navGraphName,
|
||||||
|
navigationResIds[i],
|
||||||
|
navRootId,
|
||||||
|
startDestFragIds[i]);
|
||||||
|
if (!currentOrderGraphNames.contains(navGraphName)) {
|
||||||
|
otherTabs.add(tab);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
tabs.add(tab);
|
||||||
|
}
|
||||||
|
Collections.sort(tabs, Ordering.explicit(currentOrderGraphNames).onResultOf(tab -> {
|
||||||
|
if (tab == null) return null;
|
||||||
|
return tab.getGraphName();
|
||||||
|
}));
|
||||||
|
return new Pair<>(tabs, otherTabs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private static List<String> getCurrentOrderOfGraphNamesFromPref(@NonNull final String[] navGraphNames) {
|
||||||
|
tabOrderString = settingsHelper.getString(PreferenceKeys.PREF_TAB_ORDER);
|
||||||
|
final List<String> navGraphNameList = Arrays.asList(navGraphNames);
|
||||||
|
if (TextUtils.isEmpty(tabOrderString)) {
|
||||||
|
// Use top 5 entries for default list
|
||||||
|
return navGraphNameList.subList(0, 5);
|
||||||
|
}
|
||||||
|
// Make sure that the list from preference does not contain any invalid values
|
||||||
|
final List<String> orderGraphNames = Arrays.stream(tabOrderString.split(","))
|
||||||
|
.filter(s -> !TextUtils.isEmpty(s))
|
||||||
|
.filter(navGraphNameList::contains)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
if (orderGraphNames.isEmpty()) {
|
||||||
|
// Use top 5 entries for default list
|
||||||
|
return navGraphNameList.subList(0, 5);
|
||||||
|
}
|
||||||
|
return orderGraphNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isNavRootInCurrentTabs(final String navRootString) {
|
||||||
|
return tabOrderString.contains(navRootString);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
package awais.instagrabber.viewmodels;
|
package awais.instagrabber.viewmodels;
|
||||||
|
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.lifecycle.AndroidViewModel;
|
import androidx.lifecycle.AndroidViewModel;
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
|
||||||
import awais.instagrabber.db.datasources.AccountDataSource;
|
import awais.instagrabber.db.datasources.AccountDataSource;
|
||||||
import awais.instagrabber.db.repositories.AccountRepository;
|
import awais.instagrabber.db.repositories.AccountRepository;
|
||||||
@ -21,8 +24,8 @@ public class AppStateViewModel extends AndroidViewModel {
|
|||||||
|
|
||||||
private final String cookie;
|
private final String cookie;
|
||||||
private final boolean isLoggedIn;
|
private final boolean isLoggedIn;
|
||||||
|
private final MutableLiveData<User> currentUser = new MutableLiveData<>();
|
||||||
|
|
||||||
private User currentUser;
|
|
||||||
private AccountRepository accountRepository;
|
private AccountRepository accountRepository;
|
||||||
private UserService userService;
|
private UserService userService;
|
||||||
|
|
||||||
@ -38,6 +41,10 @@ public class AppStateViewModel extends AndroidViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public User getCurrentUser() {
|
public User getCurrentUser() {
|
||||||
|
return currentUser.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public LiveData<User> getCurrentUserLiveData() {
|
||||||
return currentUser;
|
return currentUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,11 +53,13 @@ public class AppStateViewModel extends AndroidViewModel {
|
|||||||
userService.getUserInfo(uid, new ServiceCallback<User>() {
|
userService.getUserInfo(uid, new ServiceCallback<User>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(final User user) {
|
public void onSuccess(final User user) {
|
||||||
currentUser = user;
|
currentUser.postValue(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(final Throwable t) {}
|
public void onFailure(final Throwable t) {
|
||||||
|
Log.e(TAG, "onFailure: ", t);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -241,6 +241,7 @@ public class DirectThreadViewModel extends AndroidViewModel {
|
|||||||
if (users != null && users.getValue() != null) {
|
if (users != null && users.getValue() != null) {
|
||||||
final List<User> userList = users.getValue();
|
final List<User> userList = users.getValue();
|
||||||
match = userList.stream()
|
match = userList.stream()
|
||||||
|
.filter(Objects::nonNull)
|
||||||
.filter(user -> user.getPk() == userId)
|
.filter(user -> user.getPk() == userId)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
@ -250,6 +251,7 @@ public class DirectThreadViewModel extends AndroidViewModel {
|
|||||||
if (leftUsers != null && leftUsers.getValue() != null) {
|
if (leftUsers != null && leftUsers.getValue() != null) {
|
||||||
final List<User> userList = leftUsers.getValue();
|
final List<User> userList = leftUsers.getValue();
|
||||||
match = userList.stream()
|
match = userList.stream()
|
||||||
|
.filter(Objects::nonNull)
|
||||||
.filter(user -> user.getPk() == userId)
|
.filter(user -> user.getPk() == userId)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
|
@ -12,12 +12,12 @@ import java.util.Map;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import awais.instagrabber.repositories.FeedRepository;
|
import awais.instagrabber.repositories.FeedRepository;
|
||||||
|
import awais.instagrabber.repositories.responses.Media;
|
||||||
|
import awais.instagrabber.repositories.responses.PostsFetchResponse;
|
||||||
import awais.instagrabber.repositories.responses.feed.EndOfFeedDemarcator;
|
import awais.instagrabber.repositories.responses.feed.EndOfFeedDemarcator;
|
||||||
import awais.instagrabber.repositories.responses.feed.EndOfFeedGroup;
|
import awais.instagrabber.repositories.responses.feed.EndOfFeedGroup;
|
||||||
import awais.instagrabber.repositories.responses.feed.EndOfFeedGroupSet;
|
import awais.instagrabber.repositories.responses.feed.EndOfFeedGroupSet;
|
||||||
import awais.instagrabber.repositories.responses.feed.FeedFetchResponse;
|
import awais.instagrabber.repositories.responses.feed.FeedFetchResponse;
|
||||||
import awais.instagrabber.repositories.responses.Media;
|
|
||||||
import awais.instagrabber.repositories.responses.PostsFetchResponse;
|
|
||||||
import awais.instagrabber.utils.TextUtils;
|
import awais.instagrabber.utils.TextUtils;
|
||||||
import retrofit2.Call;
|
import retrofit2.Call;
|
||||||
import retrofit2.Callback;
|
import retrofit2.Callback;
|
||||||
|
@ -12,12 +12,12 @@ import java.util.stream.Collectors;
|
|||||||
import awais.instagrabber.repositories.NewsRepository;
|
import awais.instagrabber.repositories.NewsRepository;
|
||||||
import awais.instagrabber.repositories.responses.AymlResponse;
|
import awais.instagrabber.repositories.responses.AymlResponse;
|
||||||
import awais.instagrabber.repositories.responses.AymlUser;
|
import awais.instagrabber.repositories.responses.AymlUser;
|
||||||
import awais.instagrabber.repositories.responses.notification.NotificationCounts;
|
|
||||||
import awais.instagrabber.repositories.responses.UserSearchResponse;
|
|
||||||
import awais.instagrabber.repositories.responses.NewsInboxResponse;
|
import awais.instagrabber.repositories.responses.NewsInboxResponse;
|
||||||
|
import awais.instagrabber.repositories.responses.User;
|
||||||
|
import awais.instagrabber.repositories.responses.UserSearchResponse;
|
||||||
import awais.instagrabber.repositories.responses.notification.Notification;
|
import awais.instagrabber.repositories.responses.notification.Notification;
|
||||||
import awais.instagrabber.repositories.responses.notification.NotificationArgs;
|
import awais.instagrabber.repositories.responses.notification.NotificationArgs;
|
||||||
import awais.instagrabber.repositories.responses.User;
|
import awais.instagrabber.repositories.responses.notification.NotificationCounts;
|
||||||
import awais.instagrabber.utils.Constants;
|
import awais.instagrabber.utils.Constants;
|
||||||
import retrofit2.Call;
|
import retrofit2.Call;
|
||||||
import retrofit2.Callback;
|
import retrofit2.Callback;
|
||||||
|
@ -1,15 +1,10 @@
|
|||||||
package awais.instagrabber.webservices;
|
package awais.instagrabber.webservices;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
|
||||||
import awais.instagrabber.repositories.SearchRepository;
|
import awais.instagrabber.repositories.SearchRepository;
|
||||||
import awais.instagrabber.repositories.responses.search.SearchResponse;
|
import awais.instagrabber.repositories.responses.search.SearchResponse;
|
||||||
import awais.instagrabber.utils.TextUtils;
|
|
||||||
import retrofit2.Call;
|
import retrofit2.Call;
|
||||||
import retrofit2.Callback;
|
|
||||||
import retrofit2.Response;
|
|
||||||
import retrofit2.Retrofit;
|
import retrofit2.Retrofit;
|
||||||
|
|
||||||
public class SearchService extends BaseService {
|
public class SearchService extends BaseService {
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="24"
|
|
||||||
android:viewportHeight="24">
|
|
||||||
<path
|
|
||||||
android:fillColor="@android:color/white"
|
|
||||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM11,19.93c-3.95,-0.49 -7,-3.85 -7,-7.93 0,-0.62 0.08,-1.21 0.21,-1.79L9,15v1c0,1.1 0.9,2 2,2v1.93zM17.9,17.39c-0.26,-0.81 -1,-1.39 -1.9,-1.39h-1v-3c0,-0.55 -0.45,-1 -1,-1L8,12v-2h2c0.55,0 1,-0.45 1,-1L11,7h2c1.1,0 2,-0.9 2,-2v-0.41c2.93,1.19 5,4.06 5,7.41 0,2.08 -0.8,3.97 -2.1,5.39z" />
|
|
||||||
</vector>
|
|
10
app/src/main/res/drawable/ic_explore_24.xml
Normal file
10
app/src/main/res/drawable/ic_explore_24.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M12,10.9c-0.61,0 -1.1,0.49 -1.1,1.1s0.49,1.1 1.1,1.1c0.61,0 1.1,-0.49 1.1,-1.1s-0.49,-1.1 -1.1,-1.1zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM14.19,14.19L6,18l3.81,-8.19L18,6l-3.81,8.19z"/>
|
||||||
|
</vector>
|
@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="24"
|
|
||||||
android:viewportHeight="24">
|
|
||||||
<path
|
|
||||||
android:fillColor="@android:color/white"
|
|
||||||
android:pathData="M13.5,0.67s0.74,2.65 0.74,4.8c0,2.06 -1.35,3.73 -3.41,3.73 -2.07,0 -3.63,-1.67 -3.63,-3.73l0.03,-0.36C5.21,7.51 4,10.62 4,14c0,4.42 3.58,8 8,8s8,-3.58 8,-8C20,8.61 17.41,3.8 13.5,0.67zM11.71,19c-1.78,0 -3.22,-1.4 -3.22,-3.14 0,-1.62 1.05,-2.76 2.81,-3.12 1.77,-0.36 3.6,-1.21 4.62,-2.58 0.39,1.29 0.59,2.65 0.59,4.04 0,2.65 -2.15,4.8 -4.8,4.8z" />
|
|
||||||
</vector>
|
|
10
app/src/main/res/drawable/ic_home_24.xml
Normal file
10
app/src/main/res/drawable/ic_home_24.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M10,20v-6h4v6h5v-8h3L12,3 2,12h3v8z"/>
|
||||||
|
</vector>
|
10
app/src/main/res/drawable/ic_message_24.xml
Normal file
10
app/src/main/res/drawable/ic_message_24.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M20,2L4,2c-1.1,0 -1.99,0.9 -1.99,2L2,22l4,-4h14c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM18,14L6,14v-2h12v2zM18,11L6,11L6,9h12v2zM18,8L6,8L6,6h12v2z"/>
|
||||||
|
</vector>
|
10
app/src/main/res/drawable/ic_person_24.xml
Normal file
10
app/src/main/res/drawable/ic_person_24.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/>
|
||||||
|
</vector>
|
10
app/src/main/res/drawable/ic_round_add_circle_24.xml
Normal file
10
app/src/main/res/drawable/ic_round_add_circle_24.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM16,13h-3v3c0,0.55 -0.45,1 -1,1s-1,-0.45 -1,-1v-3L8,13c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1h3L11,8c0,-0.55 0.45,-1 1,-1s1,0.45 1,1v3h3c0.55,0 1,0.45 1,1s-0.45,1 -1,1z"/>
|
||||||
|
</vector>
|
10
app/src/main/res/drawable/ic_round_drag_handle_24.xml
Normal file
10
app/src/main/res/drawable/ic_round_drag_handle_24.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M19,9H5c-0.55,0 -1,0.45 -1,1s0.45,1 1,1h14c0.55,0 1,-0.45 1,-1s-0.45,-1 -1,-1zM5,15h14c0.55,0 1,-0.45 1,-1s-0.45,-1 -1,-1H5c-0.55,0 -1,0.45 -1,1s0.45,1 1,1z"/>
|
||||||
|
</vector>
|
10
app/src/main/res/drawable/ic_round_remove_circle_24.xml
Normal file
10
app/src/main/res/drawable/ic_round_remove_circle_24.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM16,13L8,13c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1h8c0.55,0 1,0.45 1,1s-0.45,1 -1,1z"/>
|
||||||
|
</vector>
|
@ -47,7 +47,6 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="bottom"
|
android:layout_gravity="bottom"
|
||||||
app:labelVisibilityMode="labeled"
|
app:labelVisibilityMode="auto"
|
||||||
app:layout_behavior="@string/hide_bottom_view_on_scroll_behavior"
|
app:layout_behavior="@string/hide_bottom_view_on_scroll_behavior" />
|
||||||
app:menu="@menu/main_bottom_navigation_menu" />
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
45
app/src/main/res/layout/item_tab_order_pref.xml
Normal file
45
app/src/main/res/layout/item_tab_order_pref.xml
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="56dp"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
|
android:id="@+id/add_remove"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:scaleType="centerInside"
|
||||||
|
tools:srcCompat="@drawable/ic_round_add_circle_24"
|
||||||
|
tools:tint="@color/green_500" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
|
android:id="@+id/icon"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:scaleType="centerInside"
|
||||||
|
tools:srcCompat="@drawable/ic_home_24" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
|
||||||
|
tools:text="@string/feed" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
|
android:id="@+id/handle"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:scaleType="centerInside"
|
||||||
|
app:srcCompat="@drawable/ic_round_drag_handle_24" />
|
||||||
|
</LinearLayout>
|
@ -1,12 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item
|
|
||||||
android:id="@+id/profile_nav_graph"
|
|
||||||
android:icon="@drawable/ic_profile_24"
|
|
||||||
android:title="@string/profile" />
|
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/more_nav_graph"
|
|
||||||
android:icon="@drawable/ic_more_horiz_24"
|
|
||||||
android:title="@string/more" />
|
|
||||||
</menu>
|
|
@ -1,30 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item
|
|
||||||
android:id="@+id/direct_messages_nav_graph"
|
|
||||||
android:icon="@drawable/ic_round_send_24"
|
|
||||||
android:title="@string/title_dm" />
|
|
||||||
<item
|
|
||||||
android:id="@+id/feed_nav_graph"
|
|
||||||
android:icon="@drawable/ic_feed"
|
|
||||||
android:title="@string/feed" />
|
|
||||||
<item
|
|
||||||
android:id="@+id/profile_nav_graph"
|
|
||||||
android:icon="@drawable/ic_profile_24"
|
|
||||||
android:title="@string/profile" />
|
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/discover_nav_graph"
|
|
||||||
android:icon="@drawable/ic_discover"
|
|
||||||
android:title="@string/title_discover" />
|
|
||||||
|
|
||||||
<!--<item-->
|
|
||||||
<!-- android:id="@+id/favouritesFragment"-->
|
|
||||||
<!-- android:icon="@drawable/ic_star_24"-->
|
|
||||||
<!-- android:title="@string/title_favorites"/>-->
|
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/more_nav_graph"
|
|
||||||
android:icon="@drawable/ic_more_horiz_24"
|
|
||||||
android:title="@string/more" />
|
|
||||||
</menu>
|
|
43
app/src/main/res/navigation/favorites_nav_graph.xml
Normal file
43
app/src/main/res/navigation/favorites_nav_graph.xml
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:id="@+id/favorites_nav_graph"
|
||||||
|
app:startDestination="@id/favoritesFragment">
|
||||||
|
|
||||||
|
<include app:graph="@navigation/profile_nav_graph" />
|
||||||
|
<include app:graph="@navigation/hashtag_nav_graph" />
|
||||||
|
<include app:graph="@navigation/location_nav_graph" />
|
||||||
|
<include app:graph="@navigation/comments_nav_graph" />
|
||||||
|
<include app:graph="@navigation/likes_nav_graph" />
|
||||||
|
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_global_profileFragment"
|
||||||
|
app:destination="@id/profile_nav_graph">
|
||||||
|
<argument
|
||||||
|
android:name="username"
|
||||||
|
app:argType="string"
|
||||||
|
app:nullable="true" />
|
||||||
|
</action>
|
||||||
|
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_global_hashTagFragment"
|
||||||
|
app:destination="@id/hashtag_nav_graph">
|
||||||
|
<argument
|
||||||
|
android:name="hashtag"
|
||||||
|
app:argType="string"
|
||||||
|
app:nullable="false" />
|
||||||
|
</action>
|
||||||
|
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_global_locationFragment"
|
||||||
|
app:destination="@id/location_nav_graph">
|
||||||
|
<argument
|
||||||
|
android:name="locationId"
|
||||||
|
app:argType="long" />
|
||||||
|
</action>
|
||||||
|
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/favoritesFragment"
|
||||||
|
android:name="awais.instagrabber.fragments.FavoritesFragment"
|
||||||
|
android:label="@string/title_favorites" />
|
||||||
|
</navigation>
|
@ -11,6 +11,7 @@
|
|||||||
<include app:graph="@navigation/likes_nav_graph" />
|
<include app:graph="@navigation/likes_nav_graph" />
|
||||||
<include app:graph="@navigation/notification_viewer_nav_graph" />
|
<include app:graph="@navigation/notification_viewer_nav_graph" />
|
||||||
<include app:graph="@navigation/story_list_nav_graph" />
|
<include app:graph="@navigation/story_list_nav_graph" />
|
||||||
|
<include app:graph="@navigation/discover_nav_graph" />
|
||||||
|
|
||||||
<action
|
<action
|
||||||
android:id="@+id/action_global_profileFragment"
|
android:id="@+id/action_global_profileFragment"
|
||||||
|
@ -13,7 +13,8 @@
|
|||||||
<argument
|
<argument
|
||||||
android:name="type"
|
android:name="type"
|
||||||
app:argType="string"
|
app:argType="string"
|
||||||
app:nullable="false" />
|
app:nullable="false"
|
||||||
|
android:defaultValue="notif"/>
|
||||||
<argument
|
<argument
|
||||||
android:name="targetId"
|
android:name="targetId"
|
||||||
android:defaultValue="0L"
|
android:defaultValue="0L"
|
||||||
|
@ -88,24 +88,61 @@
|
|||||||
<item>HH:mm:ss</item>
|
<item>HH:mm:ss</item>
|
||||||
<item>H:mm:ss</item>
|
<item>H:mm:ss</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<array name="main_nav_ids">
|
<array name="main_nav_graph_root_ids">
|
||||||
|
<item>@id/direct_messages_nav_graph</item>
|
||||||
|
<item>@id/feed_nav_graph</item>
|
||||||
|
<item>@id/profile_nav_graph</item>
|
||||||
|
<item>@id/discover_nav_graph</item>
|
||||||
|
<item>@id/more_nav_graph</item>
|
||||||
|
<!-- New graphs should go below -->
|
||||||
|
<item>@id/favorites_nav_graph</item>
|
||||||
|
<item>@id/notification_viewer_nav_graph</item>
|
||||||
|
</array>
|
||||||
|
<!-- Nav graphs should correspond 1-to-1 with the above nav graph ids -->
|
||||||
|
<array name="main_nav_graphs">
|
||||||
<item>@navigation/direct_messages_nav_graph</item>
|
<item>@navigation/direct_messages_nav_graph</item>
|
||||||
<item>@navigation/feed_nav_graph</item>
|
<item>@navigation/feed_nav_graph</item>
|
||||||
<item>@navigation/profile_nav_graph</item>
|
<item>@navigation/profile_nav_graph</item>
|
||||||
<item>@navigation/discover_nav_graph</item>
|
<item>@navigation/discover_nav_graph</item>
|
||||||
<item>@navigation/more_nav_graph</item>
|
<item>@navigation/more_nav_graph</item>
|
||||||
|
<item>@navigation/favorites_nav_graph</item>
|
||||||
|
<item>@navigation/notification_viewer_nav_graph</item>
|
||||||
</array>
|
</array>
|
||||||
<string-array name="main_nav_ids_values" translatable="false">
|
<!-- Titles should correspond 1-to-1 with the above nav graphs -->
|
||||||
|
<string-array name="main_nav_titles" translatable="false">
|
||||||
<item>@string/title_dm</item>
|
<item>@string/title_dm</item>
|
||||||
<item>@string/feed</item>
|
<item>@string/feed</item>
|
||||||
<item>@string/profile</item>
|
<item>@string/profile</item>
|
||||||
<item>@string/title_discover</item>
|
<item>@string/title_discover</item>
|
||||||
<item>@string/more</item>
|
<item>@string/more</item>
|
||||||
|
<item>@string/title_favorites</item>
|
||||||
|
<item>@string/title_notifications</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<array name="logged_out_main_nav_ids">
|
<!-- Drawable should correspond 1-to-1 with the above titles -->
|
||||||
<item>@navigation/profile_nav_graph</item>
|
<array name="main_nav_drawables" translatable="false">
|
||||||
<item>@navigation/more_nav_graph</item>
|
<item>@drawable/ic_message_24</item>
|
||||||
|
<item>@drawable/ic_home_24</item>
|
||||||
|
<item>@drawable/ic_person_24</item>
|
||||||
|
<item>@drawable/ic_explore_24</item>
|
||||||
|
<item>@drawable/ic_more_horiz_24</item>
|
||||||
|
<item>@drawable/ic_star_24</item>
|
||||||
|
<item>@drawable/ic_not_liked</item>
|
||||||
</array>
|
</array>
|
||||||
|
<!-- fragmentIds should correspond 1-to-1 with the above drawabled -->
|
||||||
|
<!-- these are the start destination of the corresponding nav graphs -->
|
||||||
|
<array name="main_nav_start_dest_frag_ids" translatable="false">
|
||||||
|
<item>@id/directMessagesInboxFragment</item>
|
||||||
|
<item>@id/feedFragment</item>
|
||||||
|
<item>@id/profileFragment</item>
|
||||||
|
<item>@id/discoverFragment</item>
|
||||||
|
<item>@id/morePreferencesFragment</item>
|
||||||
|
<item>@id/favoritesFragment</item>
|
||||||
|
<item>@id/notificationsViewer</item>
|
||||||
|
</array>
|
||||||
|
<!--<array name="logged_out_main_nav_graphs">-->
|
||||||
|
<!-- <item>@navigation/profile_nav_graph</item>-->
|
||||||
|
<!-- <item>@navigation/more_nav_graph</item>-->
|
||||||
|
<!--</array>-->
|
||||||
<string-array name="light_themes" translatable="false">
|
<string-array name="light_themes" translatable="false">
|
||||||
<item>@string/light_white_theme</item>
|
<item>@string/light_white_theme</item>
|
||||||
<item>@string/light_barinsta_theme</item>
|
<item>@string/light_barinsta_theme</item>
|
||||||
|
@ -4,4 +4,5 @@
|
|||||||
<item name="unsend" type="id" />
|
<item name="unsend" type="id" />
|
||||||
<item name="forward" type="id" />
|
<item name="forward" type="id" />
|
||||||
<item name="detail" type="id" />
|
<item name="detail" type="id" />
|
||||||
|
<item name="copy" type="id" />
|
||||||
</resources>
|
</resources>
|
@ -477,4 +477,10 @@
|
|||||||
<string name="crash_report_title">Select an email app to send crash logs</string>
|
<string name="crash_report_title">Select an email app to send crash logs</string>
|
||||||
<string name="skip_update">Skip this update</string>
|
<string name="skip_update">Skip this update</string>
|
||||||
<string name="on_latest_version">You\'re already on the latest version</string>
|
<string name="on_latest_version">You\'re already on the latest version</string>
|
||||||
|
<string name="tab_order">Screen order</string>
|
||||||
|
<string name="other_tabs">Other tabs</string>
|
||||||
|
<string name="tab_order_start_next_launch">The tab order will be reflected on next launch</string>
|
||||||
|
<string name="dm_remove_warning">If saved, all DM related features will be disabled on next launch</string>
|
||||||
|
<string name="copy_caption">Copy caption</string>
|
||||||
|
<string name="copy_reply">Copy reply</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
Reference in New Issue
Block a user