mirror of
https://github.com/KokaKiwi/BarInsta
synced 2024-12-22 21:16:57 +00:00
Add favorites, also fixes the hashtag follow, and some theming
This commit is contained in:
parent
027b356357
commit
cf974a74f3
1
.gitignore
vendored
1
.gitignore
vendored
@ -17,3 +17,4 @@
|
||||
app/release
|
||||
|
||||
.idea/git_toolbox_prj.xml
|
||||
.idea/dbnavigator.xml
|
||||
|
@ -41,7 +41,7 @@ dependencies {
|
||||
def nav_version = "2.3.0"
|
||||
def preference_version = "1.1.1"
|
||||
|
||||
implementation 'com.google.android.material:material:1.2.1'
|
||||
implementation 'com.google.android.material:material:1.3.0-alpha02'
|
||||
implementation 'com.google.android.exoplayer:exoplayer:2.11.1'
|
||||
|
||||
implementation "androidx.appcompat:appcompat:$appcompat_version"
|
||||
|
@ -38,6 +38,7 @@ import androidx.navigation.ui.NavigationUI;
|
||||
|
||||
import com.google.android.material.appbar.AppBarLayout;
|
||||
import com.google.android.material.appbar.CollapsingToolbarLayout;
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@ -91,7 +92,8 @@ public class MainActivity extends BaseLanguageActivity {
|
||||
R.id.followViewerFragment,
|
||||
R.id.directMessagesSettingsFragment,
|
||||
R.id.notificationsViewer,
|
||||
R.id.themePreferencesFragment);
|
||||
R.id.themePreferencesFragment,
|
||||
R.id.favoritesFragment);
|
||||
private static final Map<Integer, Integer> NAV_TO_MENU_ID_MAP = new HashMap<>();
|
||||
private static final List<Integer> REMOVE_COLLAPSING_TOOLBAR_SCROLL_DESTINATIONS = Collections.singletonList(R.id.commentsViewerFragment);
|
||||
private static final String FIRST_FRAGMENT_GRAPH_INDEX_KEY = "firstFragmentGraphIndex";
|
||||
@ -582,4 +584,9 @@ public class MainActivity extends BaseLanguageActivity {
|
||||
unbindService(serviceConnection);
|
||||
isActivityCheckerServiceBound = false;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public BottomNavigationView getBottomNavView() {
|
||||
return binding.bottomNavView;
|
||||
}
|
||||
}
|
@ -0,0 +1,202 @@
|
||||
package awais.instagrabber.adapters;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.util.ObjectsCompat;
|
||||
import androidx.recyclerview.widget.AdapterListUpdateCallback;
|
||||
import androidx.recyclerview.widget.AsyncDifferConfig;
|
||||
import androidx.recyclerview.widget.AsyncListDiffer;
|
||||
import androidx.recyclerview.widget.DiffUtil;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import awais.instagrabber.R;
|
||||
import awais.instagrabber.adapters.viewholder.FavoriteViewHolder;
|
||||
import awais.instagrabber.databinding.ItemFavSectionHeaderBinding;
|
||||
import awais.instagrabber.databinding.ItemSuggestionBinding;
|
||||
import awais.instagrabber.models.enums.FavoriteType;
|
||||
import awais.instagrabber.utils.DataBox;
|
||||
|
||||
public class FavoritesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||
|
||||
private final OnFavoriteClickListener clickListener;
|
||||
private final OnFavoriteLongClickListener longClickListener;
|
||||
private final AsyncListDiffer<FavoriteModelOrHeader> differ;
|
||||
|
||||
private static final DiffUtil.ItemCallback<FavoriteModelOrHeader> diffCallback = new DiffUtil.ItemCallback<FavoriteModelOrHeader>() {
|
||||
@Override
|
||||
public boolean areItemsTheSame(@NonNull final FavoriteModelOrHeader oldItem, @NonNull final FavoriteModelOrHeader newItem) {
|
||||
boolean areSame = oldItem.isHeader() && newItem.isHeader();
|
||||
if (!areSame) {
|
||||
return false;
|
||||
}
|
||||
if (oldItem.isHeader()) {
|
||||
return ObjectsCompat.equals(oldItem.header, newItem.header);
|
||||
}
|
||||
if (oldItem.model != null && newItem.model != null) {
|
||||
return oldItem.model.getId() == newItem.model.getId();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areContentsTheSame(@NonNull final FavoriteModelOrHeader oldItem, @NonNull final FavoriteModelOrHeader newItem) {
|
||||
boolean areSame = oldItem.isHeader() && newItem.isHeader();
|
||||
if (!areSame) {
|
||||
return false;
|
||||
}
|
||||
if (oldItem.isHeader()) {
|
||||
return ObjectsCompat.equals(oldItem.header, newItem.header);
|
||||
}
|
||||
return ObjectsCompat.equals(oldItem.model, newItem.model);
|
||||
}
|
||||
};
|
||||
|
||||
public FavoritesAdapter(final OnFavoriteClickListener clickListener, final OnFavoriteLongClickListener longClickListener) {
|
||||
this.clickListener = clickListener;
|
||||
this.longClickListener = longClickListener;
|
||||
differ = new AsyncListDiffer<>(new AdapterListUpdateCallback(this),
|
||||
new AsyncDifferConfig.Builder<>(diffCallback).build());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) {
|
||||
final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
|
||||
if (viewType == 0) {
|
||||
// header
|
||||
return new FavSectionViewHolder(ItemFavSectionHeaderBinding.inflate(inflater, parent, false));
|
||||
}
|
||||
final ItemSuggestionBinding binding = ItemSuggestionBinding.inflate(inflater, parent, false);
|
||||
return new FavoriteViewHolder(binding);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, final int position) {
|
||||
if (getItemViewType(position) == 0) {
|
||||
final FavoriteModelOrHeader modelOrHeader = getItem(position);
|
||||
if (!modelOrHeader.isHeader()) return;
|
||||
((FavSectionViewHolder) holder).bind(modelOrHeader.header);
|
||||
return;
|
||||
}
|
||||
((FavoriteViewHolder) holder).bind(getItem(position).model, clickListener, longClickListener);
|
||||
}
|
||||
|
||||
protected FavoriteModelOrHeader getItem(int position) {
|
||||
return differ.getCurrentList().get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return differ.getCurrentList().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(final int position) {
|
||||
return getItem(position).isHeader() ? 0 : 1;
|
||||
}
|
||||
|
||||
public void submitList(@Nullable final List<DataBox.FavoriteModel> list) {
|
||||
if (list == null) {
|
||||
differ.submitList(null);
|
||||
return;
|
||||
}
|
||||
differ.submitList(sectionAndSort(list));
|
||||
}
|
||||
|
||||
public void submitList(@Nullable final List<DataBox.FavoriteModel> list, @Nullable final Runnable commitCallback) {
|
||||
if (list == null) {
|
||||
differ.submitList(null, commitCallback);
|
||||
return;
|
||||
}
|
||||
differ.submitList(sectionAndSort(list), commitCallback);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private List<FavoriteModelOrHeader> sectionAndSort(@NonNull final List<DataBox.FavoriteModel> list) {
|
||||
final List<DataBox.FavoriteModel> listCopy = new ArrayList<>(list);
|
||||
Collections.sort(listCopy, (o1, o2) -> {
|
||||
if (o1.getType() == o2.getType()) return 0;
|
||||
// keep users at top
|
||||
if (o1.getType() == FavoriteType.USER) return -1;
|
||||
if (o2.getType() == FavoriteType.USER) return 1;
|
||||
// keep locations at bottom
|
||||
if (o1.getType() == FavoriteType.LOCATION) return 1;
|
||||
if (o2.getType() == FavoriteType.LOCATION) return -1;
|
||||
return 0;
|
||||
});
|
||||
final List<FavoriteModelOrHeader> modelOrHeaders = new ArrayList<>();
|
||||
for (int i = 0; i < listCopy.size(); i++) {
|
||||
final DataBox.FavoriteModel model = listCopy.get(i);
|
||||
final FavoriteModelOrHeader prev = modelOrHeaders.isEmpty() ? null : modelOrHeaders.get(modelOrHeaders.size() - 1);
|
||||
boolean prevWasSameType = prev != null && prev.model.getType() == model.getType();
|
||||
if (prevWasSameType) {
|
||||
// just add model
|
||||
final FavoriteModelOrHeader modelOrHeader = new FavoriteModelOrHeader();
|
||||
modelOrHeader.model = model;
|
||||
modelOrHeaders.add(modelOrHeader);
|
||||
continue;
|
||||
}
|
||||
// add header and model
|
||||
FavoriteModelOrHeader modelOrHeader = new FavoriteModelOrHeader();
|
||||
modelOrHeader.header = model.getType();
|
||||
modelOrHeaders.add(modelOrHeader);
|
||||
modelOrHeader = new FavoriteModelOrHeader();
|
||||
modelOrHeader.model = model;
|
||||
modelOrHeaders.add(modelOrHeader);
|
||||
}
|
||||
return modelOrHeaders;
|
||||
}
|
||||
|
||||
private static class FavoriteModelOrHeader {
|
||||
FavoriteType header;
|
||||
DataBox.FavoriteModel model;
|
||||
|
||||
boolean isHeader() {
|
||||
return header != null;
|
||||
}
|
||||
}
|
||||
|
||||
public interface OnFavoriteClickListener {
|
||||
void onClick(final DataBox.FavoriteModel model);
|
||||
}
|
||||
|
||||
public interface OnFavoriteLongClickListener {
|
||||
boolean onLongClick(final DataBox.FavoriteModel model);
|
||||
}
|
||||
|
||||
public static class FavSectionViewHolder extends RecyclerView.ViewHolder {
|
||||
private final ItemFavSectionHeaderBinding binding;
|
||||
|
||||
public FavSectionViewHolder(@NonNull final ItemFavSectionHeaderBinding binding) {
|
||||
super(binding.getRoot());
|
||||
this.binding = binding;
|
||||
}
|
||||
|
||||
public void bind(final FavoriteType header) {
|
||||
if (header == null) return;
|
||||
final int headerText;
|
||||
switch (header) {
|
||||
case USER:
|
||||
headerText = R.string.accounts;
|
||||
break;
|
||||
case HASHTAG:
|
||||
headerText = R.string.hashtags;
|
||||
break;
|
||||
case LOCATION:
|
||||
headerText = R.string.locations;
|
||||
break;
|
||||
default:
|
||||
headerText = R.string.unknown;
|
||||
break;
|
||||
}
|
||||
binding.getRoot().setText(headerText);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package awais.instagrabber.adapters.viewholder;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import awais.instagrabber.adapters.FavoritesAdapter;
|
||||
import awais.instagrabber.databinding.ItemSuggestionBinding;
|
||||
import awais.instagrabber.models.enums.FavoriteType;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.DataBox;
|
||||
|
||||
public class FavoriteViewHolder extends RecyclerView.ViewHolder {
|
||||
private static final String TAG = "FavoriteViewHolder";
|
||||
|
||||
private final ItemSuggestionBinding binding;
|
||||
|
||||
public FavoriteViewHolder(@NonNull final ItemSuggestionBinding binding) {
|
||||
super(binding.getRoot());
|
||||
this.binding = binding;
|
||||
binding.isVerified.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
public void bind(final DataBox.FavoriteModel model,
|
||||
final FavoritesAdapter.OnFavoriteClickListener clickListener,
|
||||
final FavoritesAdapter.OnFavoriteLongClickListener longClickListener) {
|
||||
// Log.d(TAG, "bind: " + model);
|
||||
if (model == null) return;
|
||||
itemView.setOnClickListener(v -> {
|
||||
if (clickListener == null) return;
|
||||
clickListener.onClick(model);
|
||||
});
|
||||
itemView.setOnLongClickListener(v -> {
|
||||
if (clickListener == null) return false;
|
||||
return longClickListener.onLongClick(model);
|
||||
});
|
||||
if (model.getType() == FavoriteType.HASHTAG) {
|
||||
binding.ivProfilePic.setImageURI(Constants.DEFAULT_HASH_TAG_PIC);
|
||||
} else {
|
||||
binding.ivProfilePic.setImageURI(model.getPicUrl());
|
||||
}
|
||||
binding.tvFullName.setText(model.getDisplayName());
|
||||
binding.tvUsername.setVisibility(View.VISIBLE);
|
||||
String query = model.getQuery();
|
||||
switch (model.getType()) {
|
||||
case HASHTAG:
|
||||
query = "#" + query;
|
||||
break;
|
||||
case USER:
|
||||
query = "@" + query;
|
||||
break;
|
||||
case LOCATION:
|
||||
binding.tvUsername.setVisibility(View.GONE);
|
||||
break;
|
||||
default:
|
||||
// do nothing
|
||||
}
|
||||
binding.tvUsername.setText(query);
|
||||
}
|
||||
}
|
@ -212,9 +212,10 @@ public final class FeedFetcher extends AsyncTask<Void, Void, FeedModel[]> {
|
||||
feedModelsList.trimToSize();
|
||||
|
||||
final FeedModel[] feedModels = feedModelsList.toArray(new FeedModel[0]);
|
||||
if (feedModels[feedModels.length - 1] != null)
|
||||
feedModels[feedModels.length - 1].setPageCursor(hasNextPage, endCursor);
|
||||
|
||||
final int length = feedModels.length;
|
||||
if (length >= 1 && feedModels[length - 1] != null) {
|
||||
feedModels[length - 1].setPageCursor(hasNextPage, endCursor);
|
||||
}
|
||||
result = feedModels;
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,10 @@ import androidx.annotation.Nullable;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
@ -21,6 +25,8 @@ import awaisomereport.LogCollector;
|
||||
import static awais.instagrabber.utils.Utils.logCollector;
|
||||
|
||||
public final class HashtagFetcher extends AsyncTask<Void, Void, HashtagModel> {
|
||||
private static final String TAG = "HashtagFetcher";
|
||||
|
||||
private final FetchListener<HashtagModel> fetchListener;
|
||||
private final String hashtag;
|
||||
|
||||
@ -35,12 +41,14 @@ public final class HashtagFetcher extends AsyncTask<Void, Void, HashtagModel> {
|
||||
HashtagModel result = null;
|
||||
|
||||
try {
|
||||
final HttpURLConnection conn = (HttpURLConnection) new URL("https://www.instagram.com/explore/tags/" + hashtag + "/?__a=1").openConnection();
|
||||
final HttpURLConnection conn = (HttpURLConnection) new URL("https://www.instagram.com/explore/tags/" + hashtag + "/?__a=1")
|
||||
.openConnection();
|
||||
conn.setUseCaches(true);
|
||||
conn.connect();
|
||||
|
||||
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
||||
final JSONObject user = new JSONObject(NetworkUtils.readFromConnection(conn)).getJSONObject("graphql").getJSONObject(Constants.EXTRAS_HASHTAG);
|
||||
final JSONObject user = new JSONObject(NetworkUtils.readFromConnection(conn)).getJSONObject("graphql")
|
||||
.getJSONObject(Constants.EXTRAS_HASHTAG);
|
||||
|
||||
final JSONObject timelineMedia = user.getJSONObject("edge_hashtag_to_media");
|
||||
if (timelineMedia.has("edges")) {
|
||||
@ -53,13 +61,34 @@ public final class HashtagFetcher extends AsyncTask<Void, Void, HashtagModel> {
|
||||
user.getString("profile_pic_url"),
|
||||
timelineMedia.getLong("count"),
|
||||
user.optBoolean("is_following"));
|
||||
} else {
|
||||
BufferedReader bufferedReader = null;
|
||||
try {
|
||||
final InputStream responseInputStream = conn.getErrorStream();
|
||||
bufferedReader = new BufferedReader(new InputStreamReader(responseInputStream));
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
for (String line = bufferedReader.readLine(); line != null; line = bufferedReader.readLine()) {
|
||||
if (builder.length() != 0) {
|
||||
builder.append("\n");
|
||||
}
|
||||
builder.append(line);
|
||||
}
|
||||
Log.d(TAG, "doInBackground: " + builder.toString());
|
||||
} finally {
|
||||
if (bufferedReader != null) {
|
||||
try {
|
||||
bufferedReader.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
conn.disconnect();
|
||||
} catch (final Exception e) {
|
||||
if (logCollector != null)
|
||||
logCollector.appendException(e, LogCollector.LogFile.ASYNC_HASHTAG_FETCHER, "doInBackground");
|
||||
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
|
||||
if (BuildConfig.DEBUG) Log.e(TAG, "", e);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -10,6 +10,8 @@ import org.json.JSONObject;
|
||||
import java.io.File;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import awais.instagrabber.BuildConfig;
|
||||
import awais.instagrabber.interfaces.FetchListener;
|
||||
@ -28,18 +30,18 @@ import static awais.instagrabber.utils.Constants.FOLDER_PATH;
|
||||
import static awais.instagrabber.utils.Constants.FOLDER_SAVE_TO;
|
||||
import static awais.instagrabber.utils.Utils.logCollector;
|
||||
|
||||
public final class PostsFetcher extends AsyncTask<Void, Void, PostModel[]> {
|
||||
public final class PostsFetcher extends AsyncTask<Void, Void, List<PostModel>> {
|
||||
private static final String TAG = "PostsFetcher";
|
||||
private final PostItemType type;
|
||||
private final String endCursor;
|
||||
private final String id;
|
||||
private final FetchListener<PostModel[]> fetchListener;
|
||||
private final FetchListener<List<PostModel>> fetchListener;
|
||||
private String username = null;
|
||||
|
||||
public PostsFetcher(final String id,
|
||||
final PostItemType type,
|
||||
final String endCursor,
|
||||
final FetchListener<PostModel[]> fetchListener) {
|
||||
final FetchListener<List<PostModel>> fetchListener) {
|
||||
this.id = id;
|
||||
this.type = type;
|
||||
this.endCursor = endCursor == null ? "" : endCursor;
|
||||
@ -52,7 +54,7 @@ public final class PostsFetcher extends AsyncTask<Void, Void, PostModel[]> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PostModel[] doInBackground(final Void... voids) {
|
||||
protected List<PostModel> doInBackground(final Void... voids) {
|
||||
// final boolean isHashTag = id.charAt(0) == '#';
|
||||
// final boolean isSaved = id.charAt(0) == '$';
|
||||
// final boolean isTagged = id.charAt(0) == '%';
|
||||
@ -79,7 +81,7 @@ public final class PostsFetcher extends AsyncTask<Void, Void, PostModel[]> {
|
||||
default:
|
||||
url = "https://www.instagram.com/graphql/query/?query_id=17880160963012870&id=" + id + "&first=50&after=" + endCursor;
|
||||
}
|
||||
PostModel[] result = null;
|
||||
List<PostModel> result = new ArrayList<>();
|
||||
try {
|
||||
final HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
|
||||
conn.setUseCaches(false);
|
||||
@ -126,8 +128,7 @@ public final class PostsFetcher extends AsyncTask<Void, Void, PostModel[]> {
|
||||
}
|
||||
|
||||
final JSONArray edges = mediaPosts.getJSONArray("edges");
|
||||
final PostModel[] models = new PostModel[edges.length()];
|
||||
for (int i = 0; i < models.length; ++i) {
|
||||
for (int i = 0; i < edges.length(); ++i) {
|
||||
final JSONObject mediaNode = edges.getJSONObject(i).getJSONObject("node");
|
||||
final JSONArray captions = mediaNode.getJSONObject("edge_media_to_caption").getJSONArray("edges");
|
||||
|
||||
@ -139,34 +140,43 @@ public final class PostsFetcher extends AsyncTask<Void, Void, PostModel[]> {
|
||||
else if (isVideo) itemType = MediaItemType.MEDIA_TYPE_VIDEO;
|
||||
else itemType = MediaItemType.MEDIA_TYPE_IMAGE;
|
||||
|
||||
models[i] = new PostModel(itemType, mediaNode.getString(Constants.EXTRAS_ID),
|
||||
mediaNode.getString("display_url"), mediaNode.getString("thumbnail_src"),
|
||||
mediaNode.getString(Constants.EXTRAS_SHORTCODE),
|
||||
captions.length() > 0 ? captions.getJSONObject(0).getJSONObject("node").getString("text") : null,
|
||||
mediaNode.getLong("taken_at_timestamp"), mediaNode.optBoolean("viewer_has_liked"),
|
||||
mediaNode.optBoolean("viewer_has_saved"), mediaNode.getJSONObject("edge_liked_by").getLong("count"));
|
||||
|
||||
DownloadUtils.checkExistence(downloadDir, customDir, isSlider, models[i]);
|
||||
final PostModel model = new PostModel(
|
||||
itemType,
|
||||
mediaNode.getString(Constants.EXTRAS_ID),
|
||||
mediaNode.getString("display_url"),
|
||||
mediaNode.getString("thumbnail_src"),
|
||||
mediaNode.getString(Constants.EXTRAS_SHORTCODE),
|
||||
captions.length() > 0 ? captions.getJSONObject(0)
|
||||
.getJSONObject("node")
|
||||
.getString("text")
|
||||
: null,
|
||||
mediaNode.getLong("taken_at_timestamp"),
|
||||
mediaNode.optBoolean("viewer_has_liked"),
|
||||
mediaNode.optBoolean("viewer_has_saved"),
|
||||
mediaNode.getJSONObject("edge_liked_by")
|
||||
.getLong("count")
|
||||
);
|
||||
result.add(model);
|
||||
DownloadUtils.checkExistence(downloadDir, customDir, isSlider, model);
|
||||
}
|
||||
|
||||
if (models.length != 0 && models[models.length - 1] != null)
|
||||
models[models.length - 1].setPageCursor(hasNextPage, endCursor);
|
||||
|
||||
result = models;
|
||||
if (!result.isEmpty() && result.get(result.size() - 1) != null)
|
||||
result.get(result.size() - 1).setPageCursor(hasNextPage, endCursor);
|
||||
}
|
||||
|
||||
conn.disconnect();
|
||||
} catch (Exception e) {
|
||||
if (logCollector != null)
|
||||
if (logCollector != null) {
|
||||
logCollector.appendException(e, LogCollector.LogFile.ASYNC_MAIN_POSTS_FETCHER, "doInBackground");
|
||||
if (BuildConfig.DEBUG) Log.e(TAG, "", e);
|
||||
}
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.e(TAG, "Error fetching posts", e);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final PostModel[] postModels) {
|
||||
protected void onPostExecute(final List<PostModel> postModels) {
|
||||
if (fetchListener != null) fetchListener.onResult(postModels);
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,6 @@ public final class SuggestionsFetcher extends AsyncTask<String, String, Suggesti
|
||||
conn.connect();
|
||||
|
||||
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
||||
final String defaultHashTagPic = "https://www.instagram.com/static/images/hashtag/search-hashtag-default-avatar.png/1d8417c9a4f5.png";
|
||||
final JSONObject jsonObject = new JSONObject(NetworkUtils.readFromConnection(conn));
|
||||
conn.disconnect();
|
||||
|
||||
@ -63,7 +62,7 @@ public final class SuggestionsFetcher extends AsyncTask<String, String, Suggesti
|
||||
suggestionModels.add(new SuggestionModel(false,
|
||||
hashtag.getString(Constants.EXTRAS_NAME),
|
||||
null,
|
||||
hashtag.optString("profile_pic_url", defaultHashTagPic),
|
||||
hashtag.optString("profile_pic_url", Constants.DEFAULT_HASH_TAG_PIC),
|
||||
SuggestionType.TYPE_HASHTAG,
|
||||
hashtagsArrayJSONObject.optInt("position", suggestionModels.size() - 1)));
|
||||
}
|
||||
|
@ -10,6 +10,8 @@ import org.json.JSONObject;
|
||||
import java.io.File;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import awais.instagrabber.BuildConfig;
|
||||
import awais.instagrabber.interfaces.FetchListener;
|
||||
@ -28,25 +30,27 @@ import static awais.instagrabber.utils.Constants.FOLDER_PATH;
|
||||
import static awais.instagrabber.utils.Constants.FOLDER_SAVE_TO;
|
||||
import static awais.instagrabber.utils.Utils.logCollector;
|
||||
|
||||
public final class iLikedFetcher extends AsyncTask<Void, Void, PostModel[]> {
|
||||
private final String endCursor;
|
||||
private final FetchListener<PostModel[]> fetchListener;
|
||||
public final class iLikedFetcher extends AsyncTask<Void, Void, List<PostModel>> {
|
||||
private static final String TAG = "iLikedFetcher";
|
||||
|
||||
public iLikedFetcher(final FetchListener<PostModel[]> fetchListener) {
|
||||
private final String endCursor;
|
||||
private final FetchListener<List<PostModel>> fetchListener;
|
||||
|
||||
public iLikedFetcher(final FetchListener<List<PostModel>> fetchListener) {
|
||||
this.endCursor = "";
|
||||
this.fetchListener = fetchListener;
|
||||
}
|
||||
|
||||
public iLikedFetcher(final String endCursor, final FetchListener<PostModel[]> fetchListener) {
|
||||
public iLikedFetcher(final String endCursor, final FetchListener<List<PostModel>> fetchListener) {
|
||||
this.endCursor = endCursor == null ? "" : endCursor;
|
||||
this.fetchListener = fetchListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PostModel[] doInBackground(final Void... voids) {
|
||||
final String url = "https://i.instagram.com/api/v1/feed/liked/?max_id="+endCursor;
|
||||
protected List<PostModel> doInBackground(final Void... voids) {
|
||||
final String url = "https://i.instagram.com/api/v1/feed/liked/?max_id=" + endCursor;
|
||||
|
||||
PostModel[] result = null;
|
||||
List<PostModel> result = new ArrayList<>();
|
||||
try {
|
||||
final HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
|
||||
conn.setUseCaches(false);
|
||||
@ -68,8 +72,7 @@ public final class iLikedFetcher extends AsyncTask<Void, Void, PostModel[]> {
|
||||
}
|
||||
|
||||
final JSONArray edges = body.getJSONArray("items");
|
||||
final PostModel[] models = new PostModel[edges.length()];
|
||||
for (int i = 0; i < models.length; ++i) {
|
||||
for (int i = 0; i < edges.length(); ++i) {
|
||||
final JSONObject mediaNode = edges.getJSONObject(i);
|
||||
|
||||
final boolean isSlider = mediaNode.has("carousel_media_count");
|
||||
@ -80,48 +83,57 @@ public final class iLikedFetcher extends AsyncTask<Void, Void, PostModel[]> {
|
||||
else if (isVideo) itemType = MediaItemType.MEDIA_TYPE_VIDEO;
|
||||
else itemType = MediaItemType.MEDIA_TYPE_IMAGE;
|
||||
|
||||
models[i] = new PostModel(itemType, mediaNode.getString(Constants.EXTRAS_ID),
|
||||
isSlider
|
||||
? ResponseBodyUtils.getHighQualityImage(mediaNode.getJSONArray("carousel_media").getJSONObject(0))
|
||||
: ResponseBodyUtils.getHighQualityImage(mediaNode),
|
||||
isSlider
|
||||
? ResponseBodyUtils.getLowQualityImage(mediaNode.getJSONArray("carousel_media").getJSONObject(0))
|
||||
: ResponseBodyUtils.getLowQualityImage(mediaNode),
|
||||
final PostModel model = new PostModel(
|
||||
itemType,
|
||||
mediaNode.getString(Constants.EXTRAS_ID),
|
||||
isSlider ? ResponseBodyUtils.getHighQualityImage(mediaNode.getJSONArray("carousel_media")
|
||||
.getJSONObject(0))
|
||||
: ResponseBodyUtils.getHighQualityImage(mediaNode),
|
||||
isSlider ? ResponseBodyUtils.getLowQualityImage(mediaNode.getJSONArray("carousel_media")
|
||||
.getJSONObject(0))
|
||||
: ResponseBodyUtils.getLowQualityImage(mediaNode),
|
||||
mediaNode.getString("code"),
|
||||
mediaNode.isNull("caption") ? null : mediaNode.getJSONObject("caption").optString("text"),
|
||||
mediaNode.getLong("taken_at"), true,
|
||||
mediaNode.optBoolean("has_viewer_saved"), mediaNode.getLong("like_count"));
|
||||
|
||||
mediaNode.getLong("taken_at"),
|
||||
true,
|
||||
mediaNode.optBoolean("has_viewer_saved"),
|
||||
mediaNode.getLong("like_count"));
|
||||
result.add(model);
|
||||
String username = mediaNode.getJSONObject("user").getString("username");
|
||||
final File downloadDir = new File(Environment.getExternalStorageDirectory(), "Download" +
|
||||
(Utils.settingsHelper.getBoolean(DOWNLOAD_USER_FOLDER) ? ("/"+username) : ""));
|
||||
(Utils.settingsHelper.getBoolean(DOWNLOAD_USER_FOLDER) ? ("/" + username) : ""));
|
||||
File customDir = null;
|
||||
if (Utils.settingsHelper.getBoolean(FOLDER_SAVE_TO)) {
|
||||
final String customPath = Utils.settingsHelper.getString(FOLDER_PATH +
|
||||
(Utils.settingsHelper.getBoolean(DOWNLOAD_USER_FOLDER) ? ("/"+username) : ""));
|
||||
(Utils.settingsHelper.getBoolean(DOWNLOAD_USER_FOLDER)
|
||||
? ("/" + username)
|
||||
: ""));
|
||||
if (!TextUtils.isEmpty(customPath)) customDir = new File(customPath);
|
||||
}
|
||||
DownloadUtils.checkExistence(downloadDir, customDir, isSlider, models[i]);
|
||||
DownloadUtils.checkExistence(downloadDir, customDir, isSlider, model);
|
||||
}
|
||||
|
||||
if (models[models.length - 1] != null)
|
||||
models[models.length - 1].setPageCursor(hasNextPage, endCursor);
|
||||
|
||||
result = models;
|
||||
final int length = result.size();
|
||||
if (length >= 1 && result.get(length - 1) != null) {
|
||||
result.get(length - 1).setPageCursor(hasNextPage, endCursor);
|
||||
}
|
||||
}
|
||||
|
||||
conn.disconnect();
|
||||
} catch (Exception e) {
|
||||
if (logCollector != null)
|
||||
if (logCollector != null) {
|
||||
logCollector.appendException(e, LogCollector.LogFile.ASYNC_MAIN_POSTS_FETCHER, "doInBackground");
|
||||
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
|
||||
}
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.e(TAG, "", e);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final PostModel[] postModels) {
|
||||
protected void onPostExecute(final List<PostModel> postModels) {
|
||||
if (fetchListener != null) fetchListener.onResult(postModels);
|
||||
}
|
||||
}
|
||||
|
@ -1,181 +0,0 @@
|
||||
package awais.instagrabber.dialogs;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import awais.instagrabber.R;
|
||||
import awais.instagrabber.adapters.SimpleAdapter;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.CookieUtils;
|
||||
import awais.instagrabber.utils.DataBox;
|
||||
import awais.instagrabber.utils.DownloadUtils;
|
||||
import awais.instagrabber.utils.TextUtils;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
|
||||
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||
|
||||
public final class QuickAccessDialog extends BottomSheetDialogFragment implements DialogInterface.OnShowListener,
|
||||
View.OnClickListener, View.OnLongClickListener {
|
||||
private boolean cookieChanged, isQuery;
|
||||
private Activity activity;
|
||||
private String userQuery, displayName;
|
||||
private View btnFavorite, btnImportExport;
|
||||
private SimpleAdapter<DataBox.FavoriteModel> favoritesAdapter;
|
||||
private RecyclerView rvFavorites, rvQuickAccess;
|
||||
|
||||
public QuickAccessDialog setQuery(final String userQuery, final String displayName) {
|
||||
this.userQuery = userQuery;
|
||||
this.displayName = displayName;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
|
||||
final Dialog dialog = super.onCreateDialog(savedInstanceState);
|
||||
|
||||
dialog.setOnShowListener(this);
|
||||
|
||||
final Context context = getContext();
|
||||
activity = context instanceof Activity ? (Activity) context : getActivity();
|
||||
|
||||
final View contentView = View.inflate(activity, R.layout.dialog_quick_access, null);
|
||||
|
||||
btnFavorite = contentView.findViewById(R.id.btnFavorite);
|
||||
btnImportExport = contentView.findViewById(R.id.importExport);
|
||||
|
||||
isQuery = !TextUtils.isEmpty(userQuery);
|
||||
btnFavorite.setVisibility(isQuery ? View.VISIBLE : View.GONE);
|
||||
Utils.setTooltipText(btnImportExport, R.string.import_export);
|
||||
|
||||
favoritesAdapter = new SimpleAdapter<>(activity, Utils.dataBox.getAllFavorites(), this, this);
|
||||
|
||||
btnFavorite.setOnClickListener(this);
|
||||
btnImportExport.setOnClickListener(this);
|
||||
|
||||
rvFavorites = contentView.findViewById(R.id.rvFavorites);
|
||||
rvQuickAccess = contentView.findViewById(R.id.rvQuickAccess);
|
||||
|
||||
final DividerItemDecoration itemDecoration = new DividerItemDecoration(activity, DividerItemDecoration.VERTICAL);
|
||||
rvFavorites.addItemDecoration(itemDecoration);
|
||||
rvFavorites.setAdapter(favoritesAdapter);
|
||||
|
||||
final String cookieStr = settingsHelper.getString(Constants.COOKIE);
|
||||
if (!TextUtils.isEmpty(cookieStr)
|
||||
|| Utils.dataBox.getCookieCount() > 0 // fallback for export / import
|
||||
) {
|
||||
rvQuickAccess.addItemDecoration(itemDecoration);
|
||||
final ArrayList<DataBox.CookieModel> allCookies = Utils.dataBox.getAllCookies();
|
||||
if (!TextUtils.isEmpty(cookieStr) && allCookies != null) {
|
||||
for (final DataBox.CookieModel cookie : allCookies) {
|
||||
if (cookieStr.equals(cookie.getCookie())) {
|
||||
cookie.setSelected(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
rvQuickAccess.setAdapter(new SimpleAdapter<>(activity, allCookies, this, this));
|
||||
} else {
|
||||
((View) rvQuickAccess.getParent()).setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
dialog.setContentView(contentView);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(@NonNull final View v) {
|
||||
final Object tag = v.getTag();
|
||||
if (v == btnFavorite) {
|
||||
if (isQuery) {
|
||||
Utils.dataBox.addFavorite(new DataBox.FavoriteModel(userQuery, System.currentTimeMillis(), displayName));
|
||||
favoritesAdapter.setItems(Utils.dataBox.getAllFavorites());
|
||||
}
|
||||
} else if (v == btnImportExport) {
|
||||
if (ContextCompat.checkSelfPermission(activity, DownloadUtils.PERMS[0]) == PackageManager.PERMISSION_DENIED)
|
||||
requestPermissions(DownloadUtils.PERMS, 6007);
|
||||
else Utils.showImportExportDialog(v.getContext());
|
||||
|
||||
} else if (tag instanceof DataBox.FavoriteModel) {
|
||||
// if (MainActivityBackup.scanHack != null) {
|
||||
// MainActivityBackup.scanHack.onResult(((DataBox.FavoriteModel) tag).getQuery());
|
||||
// dismiss();
|
||||
// }
|
||||
|
||||
} else if (tag instanceof DataBox.CookieModel) {
|
||||
final DataBox.CookieModel cookieModel = (DataBox.CookieModel) tag;
|
||||
if (!cookieModel.isSelected()) {
|
||||
settingsHelper.putString(Constants.COOKIE, cookieModel.getCookie());
|
||||
CookieUtils.setupCookies(cookieModel.getCookie());
|
||||
cookieChanged = true;
|
||||
}
|
||||
dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(@NonNull final View v) {
|
||||
final Object tag = v.getTag();
|
||||
|
||||
if (tag instanceof DataBox.FavoriteModel) {
|
||||
final DataBox.FavoriteModel favoriteModel = (DataBox.FavoriteModel) tag;
|
||||
|
||||
new AlertDialog.Builder(activity).setPositiveButton(R.string.yes, (d, which) -> {
|
||||
Utils.dataBox.delFavorite(favoriteModel);
|
||||
favoritesAdapter.setItems(Utils.dataBox.getAllFavorites());
|
||||
})
|
||||
.setNegativeButton(R.string.no, null).setMessage(getString(R.string.quick_access_confirm_delete,
|
||||
favoriteModel.getQuery())).show();
|
||||
|
||||
} else if (tag instanceof DataBox.CookieModel) {
|
||||
final DataBox.CookieModel cookieModel = (DataBox.CookieModel) tag;
|
||||
|
||||
if (cookieModel.isSelected())
|
||||
Toast.makeText(v.getContext(), R.string.quick_access_cannot_delete_curr, Toast.LENGTH_SHORT).show();
|
||||
else
|
||||
new AlertDialog.Builder(activity)
|
||||
.setMessage(getString(R.string.quick_access_confirm_delete, cookieModel.getUsername()))
|
||||
.setPositiveButton(R.string.yes, (d, which) -> {
|
||||
Utils.dataBox.delUserCookie(cookieModel);
|
||||
rvQuickAccess.findViewWithTag(cookieModel).setVisibility(View.GONE);
|
||||
})
|
||||
.setNegativeButton(R.string.no, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDismiss(@NonNull final DialogInterface dialog) {
|
||||
super.onDismiss(dialog);
|
||||
if (cookieChanged && activity != null) activity.recreate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShow(final DialogInterface dialog) {
|
||||
if (settingsHelper.getBoolean(Constants.SHOW_QUICK_ACCESS_DIALOG))
|
||||
new AlertDialog.Builder(activity)
|
||||
.setMessage(R.string.quick_access_info_dialog)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.setNeutralButton(R.string.dont_show_again, (d, which) ->
|
||||
settingsHelper.putBoolean(Constants.SHOW_QUICK_ACCESS_DIALOG, false)).show();
|
||||
}
|
||||
}
|
@ -0,0 +1,215 @@
|
||||
package awais.instagrabber.fragments;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.navigation.NavController;
|
||||
import androidx.navigation.fragment.NavHostFragment;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.BrokenBarrierException;
|
||||
import java.util.concurrent.CyclicBarrier;
|
||||
|
||||
import awais.instagrabber.R;
|
||||
import awais.instagrabber.adapters.FavoritesAdapter;
|
||||
import awais.instagrabber.asyncs.LocationFetcher;
|
||||
import awais.instagrabber.asyncs.ProfileFetcher;
|
||||
import awais.instagrabber.databinding.FragmentFavoritesBinding;
|
||||
import awais.instagrabber.utils.DataBox;
|
||||
import awais.instagrabber.utils.TextUtils;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
import awais.instagrabber.viewmodels.FavoritesViewModel;
|
||||
|
||||
public class FavoritesFragment extends Fragment {
|
||||
private static final String TAG = "FavoritesFragment";
|
||||
|
||||
private boolean shouldRefresh = true;
|
||||
private FragmentFavoritesBinding binding;
|
||||
private RecyclerView root;
|
||||
private FavoritesViewModel favoritesViewModel;
|
||||
private FavoritesAdapter adapter;
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) {
|
||||
if (root != null) {
|
||||
shouldRefresh = false;
|
||||
return root;
|
||||
}
|
||||
binding = FragmentFavoritesBinding.inflate(getLayoutInflater());
|
||||
root = binding.getRoot();
|
||||
binding.favoriteList.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
return root;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull final View view, @Nullable final Bundle savedInstanceState) {
|
||||
if (!shouldRefresh) return;
|
||||
init();
|
||||
shouldRefresh = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
if (favoritesViewModel == null || adapter == null) return;
|
||||
// refresh list every time in onViewStateRestored since it is cheaper than implementing pull down to refresh
|
||||
favoritesViewModel.getList().observe(getViewLifecycleOwner(), adapter::submitList);
|
||||
final List<DataBox.FavoriteModel> allFavorites = Utils.dataBox.getAllFavorites();
|
||||
favoritesViewModel.getList().postValue(allFavorites);
|
||||
fetchMissingInfo(allFavorites);
|
||||
}
|
||||
|
||||
private void init() {
|
||||
favoritesViewModel = new ViewModelProvider(this).get(FavoritesViewModel.class);
|
||||
adapter = new FavoritesAdapter(model -> {
|
||||
// navigate
|
||||
switch (model.getType()) {
|
||||
case USER: {
|
||||
final String username = model.getQuery();
|
||||
// Log.d(TAG, "username: " + username);
|
||||
final NavController navController = NavHostFragment.findNavController(this);
|
||||
final Bundle bundle = new Bundle();
|
||||
bundle.putString("username", "@" + username);
|
||||
navController.navigate(R.id.action_global_profileFragment, bundle);
|
||||
break;
|
||||
}
|
||||
case LOCATION: {
|
||||
final String locationId = model.getQuery();
|
||||
// Log.d(TAG, "locationId: " + locationId);
|
||||
final NavController navController = NavHostFragment.findNavController(this);
|
||||
final Bundle bundle = new Bundle();
|
||||
bundle.putString("locationId", locationId);
|
||||
navController.navigate(R.id.action_global_locationFragment, bundle);
|
||||
break;
|
||||
}
|
||||
case HASHTAG: {
|
||||
final String hashtag = model.getQuery();
|
||||
// Log.d(TAG, "hashtag: " + hashtag);
|
||||
final NavController navController = NavHostFragment.findNavController(this);
|
||||
final Bundle bundle = new Bundle();
|
||||
bundle.putString("hashtag", "#" + hashtag);
|
||||
navController.navigate(R.id.action_global_hashTagFragment, bundle);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// do nothing
|
||||
}
|
||||
}, model -> {
|
||||
// delete
|
||||
final Context context = getContext();
|
||||
if (context == null) return false;
|
||||
new MaterialAlertDialogBuilder(context)
|
||||
.setMessage(getString(R.string.quick_access_confirm_delete, model.getQuery()))
|
||||
.setPositiveButton(R.string.yes, (d, which) -> {
|
||||
Utils.dataBox.deleteFavorite(model.getQuery(), model.getType());
|
||||
d.dismiss();
|
||||
favoritesViewModel.getList().postValue(Utils.dataBox.getAllFavorites());
|
||||
})
|
||||
.setNegativeButton(R.string.no, null)
|
||||
.show();
|
||||
return true;
|
||||
});
|
||||
binding.favoriteList.setAdapter(adapter);
|
||||
// favoritesViewModel.getList().observe(getViewLifecycleOwner(), adapter::submitList);
|
||||
|
||||
}
|
||||
|
||||
private void fetchMissingInfo(final List<DataBox.FavoriteModel> allFavorites) {
|
||||
final Runnable runnable = () -> {
|
||||
final List<DataBox.FavoriteModel> updatedList = new ArrayList<>(allFavorites);
|
||||
// cyclic barrier is to make the async calls synchronous
|
||||
final CyclicBarrier cyclicBarrier = new CyclicBarrier(2, () -> {
|
||||
// Log.d(TAG, "fetchMissingInfo: barrier action");
|
||||
favoritesViewModel.getList().postValue(new ArrayList<>(updatedList));
|
||||
});
|
||||
try {
|
||||
for (final DataBox.FavoriteModel model : allFavorites) {
|
||||
cyclicBarrier.reset();
|
||||
// if the model has missing pic or display name (for user and location), fetch those details
|
||||
switch (model.getType()) {
|
||||
case LOCATION:
|
||||
if (TextUtils.isEmpty(model.getDisplayName())
|
||||
|| TextUtils.isEmpty(model.getPicUrl())) {
|
||||
new LocationFetcher(model.getQuery(), result -> {
|
||||
try {
|
||||
if (result == null) return;
|
||||
final int i = updatedList.indexOf(model);
|
||||
updatedList.remove(i);
|
||||
final DataBox.FavoriteModel updated = new DataBox.FavoriteModel(
|
||||
model.getId(),
|
||||
model.getQuery(),
|
||||
model.getType(),
|
||||
result.getName(),
|
||||
result.getSdProfilePic(),
|
||||
model.getDateAdded()
|
||||
);
|
||||
Utils.dataBox.addFavorite(updated);
|
||||
updatedList.add(i, updated);
|
||||
} finally {
|
||||
try {
|
||||
cyclicBarrier.await();
|
||||
} catch (BrokenBarrierException | InterruptedException e) {
|
||||
Log.e(TAG, "fetchMissingInfo: ", e);
|
||||
}
|
||||
}
|
||||
}).execute();
|
||||
cyclicBarrier.await();
|
||||
}
|
||||
break;
|
||||
case USER:
|
||||
if (TextUtils.isEmpty(model.getDisplayName())
|
||||
|| TextUtils.isEmpty(model.getPicUrl())) {
|
||||
new ProfileFetcher(model.getQuery(), result -> {
|
||||
try {
|
||||
if (result == null) return;
|
||||
final int i = updatedList.indexOf(model);
|
||||
updatedList.remove(i);
|
||||
final DataBox.FavoriteModel updated = new DataBox.FavoriteModel(
|
||||
model.getId(),
|
||||
model.getQuery(),
|
||||
model.getType(),
|
||||
result.getName(),
|
||||
result.getSdProfilePic(),
|
||||
model.getDateAdded()
|
||||
);
|
||||
Utils.dataBox.addFavorite(updated);
|
||||
updatedList.add(i, updated);
|
||||
} finally {
|
||||
try {
|
||||
cyclicBarrier.await();
|
||||
} catch (BrokenBarrierException | InterruptedException e) {
|
||||
Log.e(TAG, "fetchMissingInfo: ", e);
|
||||
}
|
||||
}
|
||||
}).execute();
|
||||
cyclicBarrier.await();
|
||||
}
|
||||
break;
|
||||
case HASHTAG:
|
||||
default:
|
||||
// hashtags don't require displayName or pic
|
||||
// updatedList.add(model);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "fetchMissingInfo: ", e);
|
||||
}
|
||||
favoritesViewModel.getList().postValue(updatedList);
|
||||
};
|
||||
new Thread(runnable).start();
|
||||
}
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
package awais.instagrabber.fragments;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
@ -22,16 +21,18 @@ import androidx.activity.OnBackPressedDispatcher;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.navigation.NavDirections;
|
||||
import androidx.navigation.fragment.NavHostFragment;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import com.google.android.material.snackbar.BaseTransientBottomBar;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import awais.instagrabber.R;
|
||||
@ -49,21 +50,24 @@ import awais.instagrabber.databinding.FragmentHashtagBinding;
|
||||
import awais.instagrabber.interfaces.FetchListener;
|
||||
import awais.instagrabber.models.HashtagModel;
|
||||
import awais.instagrabber.models.PostModel;
|
||||
import awais.instagrabber.models.StoryModel;
|
||||
import awais.instagrabber.models.enums.DownloadMethod;
|
||||
import awais.instagrabber.models.enums.FavoriteType;
|
||||
import awais.instagrabber.models.enums.PostItemType;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.CookieUtils;
|
||||
import awais.instagrabber.utils.DataBox;
|
||||
import awais.instagrabber.utils.DownloadUtils;
|
||||
import awais.instagrabber.utils.TextUtils;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
import awais.instagrabber.viewmodels.PostsViewModel;
|
||||
import awais.instagrabber.webservices.ServiceCallback;
|
||||
import awais.instagrabber.webservices.TagsService;
|
||||
import awaisomereport.LogCollector;
|
||||
|
||||
import static awais.instagrabber.utils.Utils.logCollector;
|
||||
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||
|
||||
public class HashTagFragment extends Fragment {
|
||||
public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
|
||||
private static final String TAG = "HashTagFragment";
|
||||
|
||||
private MainActivity fragmentActivity;
|
||||
@ -79,7 +83,8 @@ public class HashTagFragment extends Fragment {
|
||||
private String endCursor;
|
||||
private AsyncTask<?, ?, ?> currentlyExecuting;
|
||||
private boolean isLoggedIn;
|
||||
private StoryModel[] storyModels;
|
||||
private TagsService tagsService;
|
||||
private boolean isPullToRefresh;
|
||||
|
||||
private final OnBackPressedCallback onBackPressedCallback = new OnBackPressedCallback(false) {
|
||||
@Override
|
||||
@ -116,19 +121,27 @@ public class HashTagFragment extends Fragment {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
private final FetchListener<PostModel[]> postsFetchListener = new FetchListener<PostModel[]>() {
|
||||
private final FetchListener<List<PostModel>> postsFetchListener = new FetchListener<List<PostModel>>() {
|
||||
@Override
|
||||
public void onResult(final PostModel[] result) {
|
||||
public void onResult(final List<PostModel> result) {
|
||||
binding.swipeRefreshLayout.setRefreshing(false);
|
||||
if (result == null) return;
|
||||
binding.mainPosts.post(() -> binding.mainPosts.setVisibility(View.VISIBLE));
|
||||
final List<PostModel> postModels = postsViewModel.getList().getValue();
|
||||
final List<PostModel> finalList = postModels == null || postModels.isEmpty() ? new ArrayList<>() : new ArrayList<>(postModels);
|
||||
finalList.addAll(Arrays.asList(result));
|
||||
List<PostModel> finalList = postModels == null || postModels.isEmpty()
|
||||
? new ArrayList<>()
|
||||
: new ArrayList<>(postModels);
|
||||
if (isPullToRefresh) {
|
||||
finalList = result;
|
||||
isPullToRefresh = false;
|
||||
} else {
|
||||
finalList.addAll(result);
|
||||
}
|
||||
finalList.addAll(result);
|
||||
postsViewModel.getList().postValue(finalList);
|
||||
PostModel model = null;
|
||||
if (result.length != 0) {
|
||||
model = result[result.length - 1];
|
||||
if (!result.isEmpty()) {
|
||||
model = result.get(result.size() - 1);
|
||||
}
|
||||
if (model == null) return;
|
||||
endCursor = model.getEndCursor();
|
||||
@ -141,6 +154,7 @@ public class HashTagFragment extends Fragment {
|
||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
fragmentActivity = (MainActivity) requireActivity();
|
||||
tagsService = TagsService.getInstance();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@ -158,10 +172,18 @@ public class HashTagFragment extends Fragment {
|
||||
@Override
|
||||
public void onViewCreated(@NonNull final View view, @Nullable final Bundle savedInstanceState) {
|
||||
if (!shouldRefresh) return;
|
||||
binding.swipeRefreshLayout.setOnRefreshListener(this);
|
||||
init();
|
||||
shouldRefresh = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
isPullToRefresh = true;
|
||||
endCursor = null;
|
||||
fetchHashtagModel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
@ -257,7 +279,6 @@ public class HashTagFragment extends Fragment {
|
||||
|
||||
private void fetchPosts() {
|
||||
stopCurrentExecutor();
|
||||
binding.btnFollowTag.setVisibility(View.VISIBLE);
|
||||
binding.swipeRefreshLayout.setRefreshing(true);
|
||||
if (TextUtils.isEmpty(hashtag)) return;
|
||||
currentlyExecuting = new PostsFetcher(hashtag.substring(1), PostItemType.HASHTAG, endCursor, postsFetchListener)
|
||||
@ -266,29 +287,109 @@ public class HashTagFragment extends Fragment {
|
||||
if (context == null) return;
|
||||
if (isLoggedIn) {
|
||||
new iStoryStatusFetcher(hashtagModel.getName(), null, false, true, false, false, stories -> {
|
||||
storyModels = stories;
|
||||
if (stories != null && stories.length > 0) {
|
||||
binding.mainHashtagImage.setStoriesBorder();
|
||||
}
|
||||
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
|
||||
binding.btnFollowTag.setVisibility(View.VISIBLE);
|
||||
binding.btnFollowTag.setText(hashtagModel.getFollowing() ? R.string.unfollow : R.string.follow);
|
||||
ViewCompat.setBackgroundTintList(binding.btnFollowTag, ColorStateList.valueOf(
|
||||
ContextCompat.getColor(context, hashtagModel.getFollowing()
|
||||
? R.color.btn_purple_background
|
||||
: R.color.btn_pink_background)));
|
||||
binding.btnFollowTag.setChipIconResource(hashtagModel.getFollowing()
|
||||
? R.drawable.ic_outline_person_add_disabled_24
|
||||
: R.drawable.ic_outline_person_add_24);
|
||||
binding.btnFollowTag.setOnClickListener(v -> {
|
||||
final String cookie = settingsHelper.getString(Constants.COOKIE);
|
||||
final String csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie);
|
||||
binding.btnFollowTag.setClickable(false);
|
||||
if (!hashtagModel.getFollowing()) {
|
||||
tagsService.follow(hashtag.substring(1), csrfToken, new ServiceCallback<Boolean>() {
|
||||
@Override
|
||||
public void onSuccess(final Boolean result) {
|
||||
binding.btnFollowTag.setClickable(true);
|
||||
if (!result) {
|
||||
Log.e(TAG, "onSuccess: result is false");
|
||||
return;
|
||||
}
|
||||
onRefresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull final Throwable t) {
|
||||
binding.btnFollowTag.setClickable(true);
|
||||
Log.e(TAG, "onFailure: ", t);
|
||||
final String message = t.getMessage();
|
||||
Snackbar.make(root,
|
||||
message != null ? message
|
||||
: getString(R.string.downloader_unknown_error),
|
||||
BaseTransientBottomBar.LENGTH_LONG)
|
||||
.show();
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
tagsService.unfollow(hashtag.substring(1), csrfToken, new ServiceCallback<Boolean>() {
|
||||
@Override
|
||||
public void onSuccess(final Boolean result) {
|
||||
binding.btnFollowTag.setClickable(true);
|
||||
if (!result) {
|
||||
Log.e(TAG, "onSuccess: result is false");
|
||||
return;
|
||||
}
|
||||
onRefresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull final Throwable t) {
|
||||
binding.btnFollowTag.setClickable(true);
|
||||
Log.e(TAG, "onFailure: ", t);
|
||||
final String message = t.getMessage();
|
||||
Snackbar.make(root,
|
||||
message != null ? message
|
||||
: getString(R.string.downloader_unknown_error),
|
||||
BaseTransientBottomBar.LENGTH_LONG)
|
||||
.show();
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
binding.btnFollowTag.setText(Utils.dataBox.getFavorite(hashtag) != null
|
||||
? R.string.unfavorite_short
|
||||
: R.string.favorite_short);
|
||||
ViewCompat.setBackgroundTintList(binding.btnFollowTag, ColorStateList.valueOf(
|
||||
ContextCompat.getColor(context, Utils.dataBox.getFavorite(hashtag) != null
|
||||
? R.color.btn_purple_background
|
||||
: R.color.btn_pink_background)));
|
||||
binding.btnFollowTag.setVisibility(View.GONE);
|
||||
}
|
||||
final DataBox.FavoriteModel favorite = Utils.dataBox.getFavorite(hashtag.substring(1), FavoriteType.HASHTAG);
|
||||
final boolean isFav = favorite != null;
|
||||
binding.favChip.setVisibility(View.VISIBLE);
|
||||
binding.favChip.setChipIconResource(isFav ? R.drawable.ic_star_check_24
|
||||
: R.drawable.ic_outline_star_plus_24);
|
||||
binding.favChip.setText(isFav ? R.string.favorite_short : R.string.add_to_favorites);
|
||||
binding.favChip.setOnClickListener(v -> {
|
||||
final DataBox.FavoriteModel fav = Utils.dataBox.getFavorite(hashtag.substring(1), FavoriteType.HASHTAG);
|
||||
final boolean isFavorite = fav != null;
|
||||
final String message;
|
||||
if (isFavorite) {
|
||||
Utils.dataBox.deleteFavorite(hashtag.substring(1), FavoriteType.HASHTAG);
|
||||
binding.favChip.setText(R.string.add_to_favorites);
|
||||
binding.favChip.setChipIconResource(R.drawable.ic_outline_star_plus_24);
|
||||
message = getString(R.string.removed_from_favs);
|
||||
} else {
|
||||
Utils.dataBox.addFavorite(new DataBox.FavoriteModel(
|
||||
-1,
|
||||
hashtag.substring(1),
|
||||
FavoriteType.HASHTAG,
|
||||
hashtagModel.getName(),
|
||||
null,
|
||||
new Date()
|
||||
));
|
||||
binding.favChip.setText(R.string.favorite_short);
|
||||
binding.favChip.setChipIconResource(R.drawable.ic_star_check_24);
|
||||
message = getString(R.string.added_to_favs);
|
||||
}
|
||||
final Snackbar snackbar = Snackbar.make(root, message, BaseTransientBottomBar.LENGTH_LONG);
|
||||
snackbar.setAction(R.string.ok, v1 -> snackbar.dismiss())
|
||||
.setAnimationMode(BaseTransientBottomBar.ANIMATION_MODE_SLIDE)
|
||||
.setAnchorView(fragmentActivity.getBottomNavView())
|
||||
.show();
|
||||
});
|
||||
binding.mainHashtagImage.setImageURI(hashtagModel.getSdProfilePic());
|
||||
final String postCount = String.valueOf(hashtagModel.getPostCount());
|
||||
final SpannableStringBuilder span = new SpannableStringBuilder(getString(R.string.main_posts_count, postCount));
|
||||
final SpannableStringBuilder span = new SpannableStringBuilder(getString(R.string.main_posts_count_inline, postCount));
|
||||
span.setSpan(new RelativeSizeSpan(1.2f), 0, postCount.length(), 0);
|
||||
span.setSpan(new StyleSpan(Typeface.BOLD), 0, postCount.length(), 0);
|
||||
binding.mainTagPostCount.setText(span);
|
||||
@ -312,9 +413,7 @@ public class HashTagFragment extends Fragment {
|
||||
if (actionBar != null) {
|
||||
Log.d(TAG, "setting title: " + hashtag);
|
||||
final Handler handler = new Handler();
|
||||
handler.postDelayed(() -> {
|
||||
actionBar.setTitle(hashtag);
|
||||
}, 200);
|
||||
handler.postDelayed(() -> actionBar.setTitle(hashtag), 200);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,10 +27,14 @@ import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.navigation.NavDirections;
|
||||
import androidx.navigation.fragment.NavHostFragment;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import com.google.android.material.snackbar.BaseTransientBottomBar;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import awais.instagrabber.R;
|
||||
@ -48,11 +52,12 @@ import awais.instagrabber.databinding.FragmentLocationBinding;
|
||||
import awais.instagrabber.interfaces.FetchListener;
|
||||
import awais.instagrabber.models.LocationModel;
|
||||
import awais.instagrabber.models.PostModel;
|
||||
import awais.instagrabber.models.StoryModel;
|
||||
import awais.instagrabber.models.enums.DownloadMethod;
|
||||
import awais.instagrabber.models.enums.FavoriteType;
|
||||
import awais.instagrabber.models.enums.PostItemType;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.CookieUtils;
|
||||
import awais.instagrabber.utils.DataBox;
|
||||
import awais.instagrabber.utils.DownloadUtils;
|
||||
import awais.instagrabber.utils.TextUtils;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
@ -62,7 +67,7 @@ import awaisomereport.LogCollector;
|
||||
import static awais.instagrabber.utils.Utils.logCollector;
|
||||
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||
|
||||
public class LocationFragment extends Fragment {
|
||||
public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
|
||||
private static final String TAG = "LocationFragment";
|
||||
|
||||
private MainActivity fragmentActivity;
|
||||
@ -78,7 +83,7 @@ public class LocationFragment extends Fragment {
|
||||
private String endCursor;
|
||||
private AsyncTask<?, ?, ?> currentlyExecuting;
|
||||
private boolean isLoggedIn;
|
||||
private StoryModel[] storyModels;
|
||||
private boolean isPullToRefresh;
|
||||
|
||||
private final OnBackPressedCallback onBackPressedCallback = new OnBackPressedCallback(false) {
|
||||
@Override
|
||||
@ -119,20 +124,25 @@ public class LocationFragment extends Fragment {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
private final FetchListener<PostModel[]> postsFetchListener = new FetchListener<PostModel[]>() {
|
||||
private final FetchListener<List<PostModel>> postsFetchListener = new FetchListener<List<PostModel>>() {
|
||||
@Override
|
||||
public void onResult(final PostModel[] result) {
|
||||
public void onResult(final List<PostModel> result) {
|
||||
binding.swipeRefreshLayout.setRefreshing(false);
|
||||
if (result == null) return;
|
||||
binding.mainPosts.post(() -> binding.mainPosts.setVisibility(View.VISIBLE));
|
||||
final List<PostModel> postModels = postsViewModel.getList().getValue();
|
||||
final List<PostModel> finalList = postModels == null || postModels.isEmpty() ? new ArrayList<>()
|
||||
: new ArrayList<>(postModels);
|
||||
finalList.addAll(Arrays.asList(result));
|
||||
List<PostModel> finalList = postModels == null || postModels.isEmpty() ? new ArrayList<>()
|
||||
: new ArrayList<>(postModels);
|
||||
if (isPullToRefresh) {
|
||||
finalList = result;
|
||||
isPullToRefresh = false;
|
||||
} else {
|
||||
finalList.addAll(result);
|
||||
}
|
||||
postsViewModel.getList().postValue(finalList);
|
||||
PostModel model = null;
|
||||
if (result.length != 0) {
|
||||
model = result[result.length - 1];
|
||||
if (!result.isEmpty()) {
|
||||
model = result.get(result.size() - 1);
|
||||
}
|
||||
if (model == null) return;
|
||||
endCursor = model.getEndCursor();
|
||||
@ -164,10 +174,18 @@ public class LocationFragment extends Fragment {
|
||||
@Override
|
||||
public void onViewCreated(@NonNull final View view, @Nullable final Bundle savedInstanceState) {
|
||||
if (!shouldRefresh) return;
|
||||
binding.swipeRefreshLayout.setOnRefreshListener(this);
|
||||
init();
|
||||
shouldRefresh = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
isPullToRefresh = true;
|
||||
endCursor = null;
|
||||
fetchLocationModel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
@ -182,6 +200,8 @@ public class LocationFragment extends Fragment {
|
||||
isLoggedIn = !TextUtils.isEmpty(cookie) && CookieUtils.getUserIdFromCookie(cookie) != null;
|
||||
final LocationFragmentArgs fragmentArgs = LocationFragmentArgs.fromBundle(getArguments());
|
||||
locationId = fragmentArgs.getLocationId();
|
||||
binding.favChip.setVisibility(View.GONE);
|
||||
binding.btnMap.setVisibility(View.GONE);
|
||||
setTitle();
|
||||
setupPosts();
|
||||
fetchLocationModel();
|
||||
@ -275,7 +295,6 @@ public class LocationFragment extends Fragment {
|
||||
false,
|
||||
false,
|
||||
stories -> {
|
||||
storyModels = stories;
|
||||
if (stories != null && stories.length > 0) {
|
||||
binding.mainLocationImage.setStoriesBorder();
|
||||
}
|
||||
@ -283,7 +302,7 @@ public class LocationFragment extends Fragment {
|
||||
}
|
||||
binding.mainLocationImage.setImageURI(locationModel.getSdProfilePic());
|
||||
final String postCount = String.valueOf(locationModel.getPostCount());
|
||||
final SpannableStringBuilder span = new SpannableStringBuilder(getString(R.string.main_posts_count,
|
||||
final SpannableStringBuilder span = new SpannableStringBuilder(getString(R.string.main_posts_count_inline,
|
||||
postCount));
|
||||
span.setSpan(new RelativeSizeSpan(1.2f), 0, postCount.length(), 0);
|
||||
span.setSpan(new StyleSpan(Typeface.BOLD), 0, postCount.length(), 0);
|
||||
@ -329,6 +348,40 @@ public class LocationFragment extends Fragment {
|
||||
binding.locationUrl.setVisibility(View.VISIBLE);
|
||||
binding.locationUrl.setText(TextUtils.getSpannableUrl(url));
|
||||
}
|
||||
final DataBox.FavoriteModel favorite = Utils.dataBox.getFavorite(locationId, FavoriteType.LOCATION);
|
||||
final boolean isFav = favorite != null;
|
||||
binding.favChip.setVisibility(View.VISIBLE);
|
||||
binding.favChip.setChipIconResource(isFav ? R.drawable.ic_star_check_24
|
||||
: R.drawable.ic_outline_star_plus_24);
|
||||
binding.favChip.setText(isFav ? R.string.favorite_short : R.string.add_to_favorites);
|
||||
binding.favChip.setOnClickListener(v -> {
|
||||
final DataBox.FavoriteModel fav = Utils.dataBox.getFavorite(locationId, FavoriteType.LOCATION);
|
||||
final boolean isFavorite = fav != null;
|
||||
final String message;
|
||||
if (isFavorite) {
|
||||
Utils.dataBox.deleteFavorite(locationId, FavoriteType.LOCATION);
|
||||
binding.favChip.setText(R.string.add_to_favorites);
|
||||
binding.favChip.setChipIconResource(R.drawable.ic_outline_star_plus_24);
|
||||
message = getString(R.string.removed_from_favs);
|
||||
} else {
|
||||
Utils.dataBox.addFavorite(new DataBox.FavoriteModel(
|
||||
-1,
|
||||
locationId,
|
||||
FavoriteType.LOCATION,
|
||||
locationModel.getName(),
|
||||
locationModel.getSdProfilePic(),
|
||||
new Date()
|
||||
));
|
||||
binding.favChip.setText(R.string.favorite_short);
|
||||
binding.favChip.setChipIconResource(R.drawable.ic_star_check_24);
|
||||
message = getString(R.string.added_to_favs);
|
||||
}
|
||||
final Snackbar snackbar = Snackbar.make(root, message, BaseTransientBottomBar.LENGTH_LONG);
|
||||
snackbar.setAction(R.string.ok, v1 -> snackbar.dismiss())
|
||||
.setAnimationMode(BaseTransientBottomBar.ANIMATION_MODE_SLIDE)
|
||||
.setAnchorView(fragmentActivity.getBottomNavView())
|
||||
.show();
|
||||
});
|
||||
}
|
||||
|
||||
private void fetchPosts() {
|
||||
|
@ -27,7 +27,6 @@ import androidx.navigation.fragment.NavHostFragment;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@ -58,7 +57,6 @@ public final class SavedViewerFragment extends Fragment implements SwipeRefreshL
|
||||
private static AsyncTask<?, ?, ?> currentlyExecuting;
|
||||
private PostsAdapter postsAdapter;
|
||||
private boolean hasNextPage;
|
||||
private boolean autoloadPosts;
|
||||
private FragmentSavedBinding binding;
|
||||
private String username;
|
||||
private String endCursor;
|
||||
@ -107,17 +105,16 @@ public final class SavedViewerFragment extends Fragment implements SwipeRefreshL
|
||||
return false;
|
||||
}
|
||||
});
|
||||
private final FetchListener<PostModel[]> postsFetchListener = new FetchListener<PostModel[]>() {
|
||||
private final FetchListener<List<PostModel>> postsFetchListener = new FetchListener<List<PostModel>>() {
|
||||
@Override
|
||||
public void onResult(final PostModel[] result) {
|
||||
public void onResult(final List<PostModel> result) {
|
||||
final List<PostModel> current = postsViewModel.getList().getValue();
|
||||
if (result != null && result.length > 0) {
|
||||
final List<PostModel> resultList = Arrays.asList(result);
|
||||
if (result != null && !result.isEmpty()) {
|
||||
if (current == null) {
|
||||
postsViewModel.getList().postValue(resultList);
|
||||
postsViewModel.getList().postValue(result);
|
||||
} else {
|
||||
final List<PostModel> currentCopy = new ArrayList<>(current);
|
||||
currentCopy.addAll(resultList);
|
||||
currentCopy.addAll(result);
|
||||
postsViewModel.getList().postValue(currentCopy);
|
||||
}
|
||||
binding.mainPosts.post(() -> {
|
||||
@ -125,11 +122,11 @@ public final class SavedViewerFragment extends Fragment implements SwipeRefreshL
|
||||
binding.mainPosts.setVisibility(View.VISIBLE);
|
||||
});
|
||||
|
||||
final PostModel model = result.length > 0 ? result[result.length - 1] : null;
|
||||
final PostModel model = !result.isEmpty() ? result.get(result.size() - 1) : null;
|
||||
if (model != null) {
|
||||
endCursor = model.getEndCursor();
|
||||
hasNextPage = model.hasNextPage();
|
||||
if (autoloadPosts && hasNextPage) {
|
||||
if (hasNextPage) {
|
||||
fetchPosts();
|
||||
} else {
|
||||
binding.swipeRefreshLayout.setRefreshing(false);
|
||||
@ -246,7 +243,7 @@ public final class SavedViewerFragment extends Fragment implements SwipeRefreshL
|
||||
binding.swipeRefreshLayout.setRefreshing(true);
|
||||
|
||||
lazyLoader = new RecyclerLazyLoader(layoutManager, (page, totalItemsCount) -> {
|
||||
if (!autoloadPosts && hasNextPage) {
|
||||
if (hasNextPage) {
|
||||
binding.swipeRefreshLayout.setRefreshing(true);
|
||||
fetchPosts();
|
||||
endCursor = null;
|
||||
@ -258,7 +255,7 @@ public final class SavedViewerFragment extends Fragment implements SwipeRefreshL
|
||||
|
||||
private void fetchPosts() {
|
||||
stopCurrentExecutor();
|
||||
final AsyncTask<Void, Void, PostModel[]> asyncTask;
|
||||
final AsyncTask<Void, Void, List<PostModel>> asyncTask;
|
||||
switch (type) {
|
||||
case LIKED:
|
||||
asyncTask = new iLikedFetcher(endCursor, postsFetchListener);
|
||||
|
@ -2,7 +2,6 @@ package awais.instagrabber.fragments.main;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
@ -30,8 +29,6 @@ import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
@ -42,9 +39,12 @@ import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import com.google.android.material.snackbar.BaseTransientBottomBar;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import awais.instagrabber.ProfileNavGraphDirections;
|
||||
@ -71,6 +71,7 @@ import awais.instagrabber.models.PostModel;
|
||||
import awais.instagrabber.models.ProfileModel;
|
||||
import awais.instagrabber.models.StoryModel;
|
||||
import awais.instagrabber.models.enums.DownloadMethod;
|
||||
import awais.instagrabber.models.enums.FavoriteType;
|
||||
import awais.instagrabber.models.enums.PostItemType;
|
||||
import awais.instagrabber.models.enums.StoryViewerChoice;
|
||||
import awais.instagrabber.repositories.responses.FriendshipRepoChangeRootResponse;
|
||||
@ -111,11 +112,12 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
||||
private StoryModel[] storyModels;
|
||||
private boolean hasNextPage;
|
||||
private String endCursor;
|
||||
private AsyncTask<Void, Void, PostModel[]> currentlyExecuting;
|
||||
private MenuItem favMenuItem;
|
||||
private AsyncTask<Void, Void, List<PostModel>> currentlyExecuting;
|
||||
private boolean isPullToRefresh;
|
||||
private HighlightsAdapter highlightsAdapter;
|
||||
private HighlightsViewModel highlightsViewModel;
|
||||
private MenuItem blockMenuItem;
|
||||
private MenuItem restrictMenuItem;
|
||||
|
||||
private final Runnable usernameSettingRunnable = () -> {
|
||||
final ActionBar actionBar = fragmentActivity.getSupportActionBar();
|
||||
@ -161,11 +163,11 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
||||
return false;
|
||||
}
|
||||
});
|
||||
private final FetchListener<PostModel[]> postsFetchListener = new FetchListener<PostModel[]>() {
|
||||
private final FetchListener<List<PostModel>> postsFetchListener = new FetchListener<List<PostModel>>() {
|
||||
@Override
|
||||
public void onResult(final PostModel[] result) {
|
||||
public void onResult(final List<PostModel> result) {
|
||||
binding.swipeRefreshLayout.setRefreshing(false);
|
||||
if (result == null || result.length <= 0) {
|
||||
if (result == null || result.isEmpty()) {
|
||||
binding.privatePage1.setImageResource(R.drawable.ic_cancel);
|
||||
binding.privatePage2.setText(R.string.empty_acc);
|
||||
binding.privatePage.setVisibility(View.VISIBLE);
|
||||
@ -175,15 +177,14 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
||||
final List<PostModel> postModels = postsViewModel.getList().getValue();
|
||||
List<PostModel> finalList = postModels == null || postModels.isEmpty() ? new ArrayList<>()
|
||||
: new ArrayList<>(postModels);
|
||||
final List<PostModel> resultList = Arrays.asList(result);
|
||||
if (isPullToRefresh) {
|
||||
finalList = resultList;
|
||||
finalList = result;
|
||||
isPullToRefresh = false;
|
||||
} else {
|
||||
finalList.addAll(resultList);
|
||||
finalList.addAll(result);
|
||||
}
|
||||
postsViewModel.getList().postValue(finalList);
|
||||
final PostModel lastPostModel = result[result.length - 1];
|
||||
final PostModel lastPostModel = result.get(result.size() - 1);
|
||||
if (lastPostModel == null) return;
|
||||
endCursor = lastPostModel.getEndCursor();
|
||||
hasNextPage = lastPostModel.hasNextPage();
|
||||
@ -262,7 +263,81 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
||||
@Override
|
||||
public void onCreateOptionsMenu(@NonNull final Menu menu, @NonNull final MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.profile_menu, menu);
|
||||
favMenuItem = menu.findItem(R.id.favourites);
|
||||
// favMenuItem = menu.findItem(R.id.favourites);
|
||||
blockMenuItem = menu.findItem(R.id.block);
|
||||
if (blockMenuItem != null) {
|
||||
blockMenuItem.setVisible(false);
|
||||
}
|
||||
restrictMenuItem = menu.findItem(R.id.restrict);
|
||||
if (restrictMenuItem != null) {
|
||||
restrictMenuItem.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(@NonNull final MenuItem item) {
|
||||
if (item.getItemId() == R.id.restrict) {
|
||||
if (!isLoggedIn) return false;
|
||||
final String action = profileModel.getRestricted() ? "Unrestrict" : "Restrict";
|
||||
friendshipService.toggleRestrict(
|
||||
profileModel.getId(),
|
||||
!profileModel.getRestricted(),
|
||||
CookieUtils.getCsrfTokenFromCookie(cookie),
|
||||
new ServiceCallback<FriendshipRepoRestrictRootResponse>() {
|
||||
@Override
|
||||
public void onSuccess(final FriendshipRepoRestrictRootResponse result) {
|
||||
Log.d(TAG, action + " success: " + result);
|
||||
fetchProfileDetails();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(final Throwable t) {
|
||||
Log.e(TAG, "Error while performing " + action, t);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
if (item.getItemId() == R.id.block) {
|
||||
final String userIdFromCookie = CookieUtils.getUserIdFromCookie(cookie);
|
||||
if (!isLoggedIn) return false;
|
||||
if (profileModel.getBlocked()) {
|
||||
friendshipService.unblock(
|
||||
userIdFromCookie,
|
||||
profileModel.getId(),
|
||||
CookieUtils.getCsrfTokenFromCookie(cookie),
|
||||
new ServiceCallback<FriendshipRepoChangeRootResponse>() {
|
||||
@Override
|
||||
public void onSuccess(final FriendshipRepoChangeRootResponse result) {
|
||||
Log.d(TAG, "Unblock success: " + result);
|
||||
fetchProfileDetails();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(final Throwable t) {
|
||||
Log.e(TAG, "Error unblocking", t);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
friendshipService.block(
|
||||
userIdFromCookie,
|
||||
profileModel.getId(),
|
||||
CookieUtils.getCsrfTokenFromCookie(cookie),
|
||||
new ServiceCallback<FriendshipRepoChangeRootResponse>() {
|
||||
@Override
|
||||
public void onSuccess(final FriendshipRepoChangeRootResponse result) {
|
||||
Log.d(TAG, "Block success: " + result);
|
||||
fetchProfileDetails();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(final Throwable t) {
|
||||
Log.e(TAG, "Error blocking", t);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -340,14 +415,14 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
||||
new ProfileFetcher(username.substring(1), profileModel -> {
|
||||
if (getContext() == null) return;
|
||||
this.profileModel = profileModel;
|
||||
final String userIdFromCookie = CookieUtils.getUserIdFromCookie(cookie);
|
||||
final boolean isSelf = isLoggedIn
|
||||
&& profileModel != null
|
||||
&& userIdFromCookie != null
|
||||
&& userIdFromCookie.equals(profileModel.getId());
|
||||
if (favMenuItem != null) {
|
||||
favMenuItem.setVisible(isSelf);
|
||||
}
|
||||
// final String userIdFromCookie = CookieUtils.getUserIdFromCookie(cookie);
|
||||
// final boolean isSelf = isLoggedIn
|
||||
// && profileModel != null
|
||||
// && userIdFromCookie != null
|
||||
// && userIdFromCookie.equals(profileModel.getId());
|
||||
// if (favMenuItem != null) {
|
||||
// favMenuItem.setVisible(isSelf);
|
||||
// }
|
||||
setProfileDetails();
|
||||
|
||||
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
@ -385,7 +460,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
||||
} else binding.highlightsList.setVisibility(View.GONE);
|
||||
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
} else if (settingsHelper.getString(Constants.STORY_VIEWER).equals(StoryViewerChoice.ALOINSTAGRAM.getValue())) {
|
||||
Log.d("austin_debug", "alo triggered");
|
||||
// Log.d(TAG, "alo triggered");
|
||||
aloService.getUserStory(profileId, profileModel.getUsername(), false, new ServiceCallback<List<StoryModel>>() {
|
||||
@Override
|
||||
public void onSuccess(final List<StoryModel> result) {
|
||||
@ -402,15 +477,13 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
||||
});
|
||||
}
|
||||
|
||||
final String myId = CookieUtils.getUserIdFromCookie(cookie);
|
||||
if (isLoggedIn) {
|
||||
final String myId = CookieUtils.getUserIdFromCookie(cookie);
|
||||
if (profileId.equals(myId)) {
|
||||
binding.btnTagged.setVisibility(View.VISIBLE);
|
||||
binding.btnSaved.setVisibility(View.VISIBLE);
|
||||
binding.btnLiked.setVisibility(View.VISIBLE);
|
||||
binding.btnSaved.setText(R.string.saved);
|
||||
ViewCompat.setBackgroundTintList(binding.btnSaved,
|
||||
ColorStateList.valueOf(ContextCompat.getColor(context, R.color.btn_orange_background)));
|
||||
} else {
|
||||
binding.btnTagged.setVisibility(View.GONE);
|
||||
binding.btnSaved.setVisibility(View.GONE);
|
||||
@ -418,58 +491,50 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
||||
binding.btnFollow.setVisibility(View.VISIBLE);
|
||||
if (profileModel.getFollowing()) {
|
||||
binding.btnFollow.setText(R.string.unfollow);
|
||||
ViewCompat.setBackgroundTintList(binding.btnFollow,
|
||||
ColorStateList.valueOf(ContextCompat.getColor(context, R.color.btn_purple_background)));
|
||||
binding.btnFollow.setIconResource(R.drawable.ic_outline_person_add_disabled_24);
|
||||
} else if (profileModel.getRequested()) {
|
||||
binding.btnFollow.setText(R.string.cancel);
|
||||
ViewCompat.setBackgroundTintList(binding.btnFollow,
|
||||
ColorStateList.valueOf(ContextCompat.getColor(context, R.color.btn_purple_background)));
|
||||
binding.btnFollow.setIconResource(R.drawable.ic_outline_person_add_disabled_24);
|
||||
} else {
|
||||
binding.btnFollow.setText(R.string.follow);
|
||||
ViewCompat.setBackgroundTintList(binding.btnFollow,
|
||||
ColorStateList.valueOf(ContextCompat.getColor(context, R.color.btn_pink_background)));
|
||||
binding.btnFollow.setIconResource(R.drawable.ic_outline_person_add_24);
|
||||
}
|
||||
binding.btnRestrict.setVisibility(View.VISIBLE);
|
||||
if (profileModel.getRestricted()) {
|
||||
binding.btnRestrict.setText(R.string.unrestrict);
|
||||
ViewCompat.setBackgroundTintList(binding.btnRestrict,
|
||||
ColorStateList.valueOf(ContextCompat.getColor(context, R.color.btn_green_background)));
|
||||
} else {
|
||||
binding.btnRestrict.setText(R.string.restrict);
|
||||
ViewCompat.setBackgroundTintList(binding.btnRestrict,
|
||||
ColorStateList.valueOf(ContextCompat.getColor(context, R.color.btn_orange_background)));
|
||||
if (restrictMenuItem != null) {
|
||||
restrictMenuItem.setVisible(true);
|
||||
if (profileModel.getRestricted()) {
|
||||
restrictMenuItem.setTitle(R.string.unrestrict);
|
||||
} else {
|
||||
restrictMenuItem.setTitle(R.string.restrict);
|
||||
}
|
||||
}
|
||||
binding.btnBlock.setVisibility(View.VISIBLE);
|
||||
binding.btnTagged.setVisibility(View.VISIBLE);
|
||||
if (profileModel.getBlocked()) {
|
||||
binding.btnBlock.setText(R.string.unblock);
|
||||
ViewCompat.setBackgroundTintList(binding.btnBlock,
|
||||
ColorStateList.valueOf(ContextCompat.getColor(context, R.color.btn_green_background)));
|
||||
} else {
|
||||
binding.btnBlock.setText(R.string.block);
|
||||
ViewCompat.setBackgroundTintList(binding.btnBlock,
|
||||
ColorStateList.valueOf(ContextCompat.getColor(context, R.color.btn_red_background)));
|
||||
if (blockMenuItem != null) {
|
||||
blockMenuItem.setVisible(true);
|
||||
if (profileModel.getBlocked()) {
|
||||
blockMenuItem.setTitle(R.string.unblock);
|
||||
} else {
|
||||
blockMenuItem.setTitle(R.string.block);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (Utils.dataBox.getFavorite(username) != null) {
|
||||
binding.btnFollow.setText(R.string.unfavorite_short);
|
||||
ViewCompat.setBackgroundTintList(binding.btnFollow,
|
||||
ColorStateList.valueOf(ContextCompat.getColor(context, R.color.btn_purple_background)));
|
||||
} else {
|
||||
binding.btnFollow.setText(R.string.favorite_short);
|
||||
ViewCompat.setBackgroundTintList(binding.btnFollow,
|
||||
ColorStateList.valueOf(ContextCompat.getColor(context, R.color.btn_pink_background)));
|
||||
}
|
||||
binding.btnFollow.setVisibility(View.VISIBLE);
|
||||
if (!profileModel.isReallyPrivate()) {
|
||||
binding.btnRestrict.setVisibility(View.VISIBLE);
|
||||
binding.btnRestrict.setText(R.string.tagged);
|
||||
ViewCompat.setBackgroundTintList(binding.btnRestrict,
|
||||
ColorStateList.valueOf(ContextCompat.getColor(context, R.color.btn_blue_background)));
|
||||
if (!profileModel.isReallyPrivate() && restrictMenuItem != null) {
|
||||
restrictMenuItem.setVisible(true);
|
||||
if (profileModel.getRestricted()) {
|
||||
restrictMenuItem.setTitle(R.string.unrestrict);
|
||||
} else {
|
||||
restrictMenuItem.setTitle(R.string.restrict);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!profileId.equals(myId)) {
|
||||
binding.favCb.setVisibility(View.VISIBLE);
|
||||
final boolean isFav = Utils.dataBox.getFavorite(username.substring(1), FavoriteType.USER) != null;
|
||||
binding.favCb.setChecked(isFav);
|
||||
binding.favCb.setButtonDrawable(isFav ? R.drawable.ic_star_check_24 : R.drawable.ic_outline_star_plus_24);
|
||||
} else {
|
||||
binding.favCb.setVisibility(View.GONE);
|
||||
}
|
||||
binding.mainProfileImage.setImageURI(profileModel.getSdProfilePic());
|
||||
|
||||
final long followersCount = profileModel.getFollowersCount();
|
||||
@ -570,23 +635,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
||||
final String userIdFromCookie = CookieUtils.getUserIdFromCookie(cookie);
|
||||
// final boolean isSelf = isLoggedIn && profileModel != null && userIdFromCookie != null && userIdFromCookie
|
||||
// .equals(profileModel.getId());
|
||||
final String favorite = Utils.dataBox.getFavorite(username);
|
||||
binding.btnFollow.setOnClickListener(v -> {
|
||||
if (!isLoggedIn) {
|
||||
if (favorite != null && v == binding.btnFollow) {
|
||||
Utils.dataBox.delFavorite(new DataBox.FavoriteModel(
|
||||
username,
|
||||
Long.parseLong(favorite.split("/")[1]),
|
||||
username.replaceAll("^@", "")));
|
||||
} else if (v == binding.btnFollow) {
|
||||
Utils.dataBox.addFavorite(new DataBox.FavoriteModel(
|
||||
username,
|
||||
System.currentTimeMillis(),
|
||||
username.replaceAll("^@", "")));
|
||||
}
|
||||
fetchProfileDetails();
|
||||
return;
|
||||
}
|
||||
if (profileModel.getFollowing() || profileModel.getRequested()) {
|
||||
friendshipService.unfollow(
|
||||
userIdFromCookie,
|
||||
@ -623,64 +672,6 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
||||
});
|
||||
}
|
||||
});
|
||||
binding.btnRestrict.setOnClickListener(v -> {
|
||||
if (!isLoggedIn) return;
|
||||
final String action = profileModel.getRestricted() ? "Unrestrict" : "Restrict";
|
||||
friendshipService.toggleRestrict(
|
||||
profileModel.getId(),
|
||||
!profileModel.getRestricted(),
|
||||
CookieUtils.getCsrfTokenFromCookie(cookie),
|
||||
new ServiceCallback<FriendshipRepoRestrictRootResponse>() {
|
||||
@Override
|
||||
public void onSuccess(final FriendshipRepoRestrictRootResponse result) {
|
||||
Log.d(TAG, action + " success: " + result);
|
||||
fetchProfileDetails();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(final Throwable t) {
|
||||
Log.e(TAG, "Error while performing " + action, t);
|
||||
}
|
||||
});
|
||||
});
|
||||
binding.btnBlock.setOnClickListener(v -> {
|
||||
if (!isLoggedIn) return;
|
||||
if (profileModel.getBlocked()) {
|
||||
friendshipService.unblock(
|
||||
userIdFromCookie,
|
||||
profileModel.getId(),
|
||||
CookieUtils.getCsrfTokenFromCookie(cookie),
|
||||
new ServiceCallback<FriendshipRepoChangeRootResponse>() {
|
||||
@Override
|
||||
public void onSuccess(final FriendshipRepoChangeRootResponse result) {
|
||||
Log.d(TAG, "Unblock success: " + result);
|
||||
fetchProfileDetails();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(final Throwable t) {
|
||||
Log.e(TAG, "Error unblocking", t);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
friendshipService.block(
|
||||
userIdFromCookie,
|
||||
profileModel.getId(),
|
||||
CookieUtils.getCsrfTokenFromCookie(cookie),
|
||||
new ServiceCallback<FriendshipRepoChangeRootResponse>() {
|
||||
@Override
|
||||
public void onSuccess(final FriendshipRepoChangeRootResponse result) {
|
||||
Log.d(TAG, "Block success: " + result);
|
||||
fetchProfileDetails();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(final Throwable t) {
|
||||
Log.e(TAG, "Error blocking", t);
|
||||
}
|
||||
});
|
||||
});
|
||||
binding.btnSaved.setOnClickListener(v -> {
|
||||
final NavDirections action = ProfileFragmentDirections.actionProfileFragmentToSavedViewerFragment(profileModel.getUsername(),
|
||||
profileModel.getId(),
|
||||
@ -728,6 +719,41 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show();
|
||||
});
|
||||
binding.favCb.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
||||
// do not do anything if state matches the db, as listener is set before profile details are set
|
||||
final String finalUsername = username.startsWith("@") ? username.substring(1) : username;
|
||||
final DataBox.FavoriteModel favorite = Utils.dataBox.getFavorite(finalUsername, FavoriteType.USER);
|
||||
if ((isChecked && favorite != null) || (!isChecked && favorite == null)) {
|
||||
return;
|
||||
}
|
||||
buttonView.setVisibility(View.GONE);
|
||||
binding.favProgress.setVisibility(View.VISIBLE);
|
||||
final String message;
|
||||
if (isChecked) {
|
||||
final DataBox.FavoriteModel model = new DataBox.FavoriteModel(
|
||||
-1,
|
||||
finalUsername,
|
||||
FavoriteType.USER,
|
||||
profileModel.getName(),
|
||||
profileModel.getSdProfilePic(),
|
||||
new Date()
|
||||
);
|
||||
Utils.dataBox.addFavorite(model);
|
||||
binding.favCb.setButtonDrawable(R.drawable.ic_star_check_24);
|
||||
message = getString(R.string.added_to_favs);
|
||||
} else {
|
||||
Utils.dataBox.deleteFavorite(finalUsername, FavoriteType.USER);
|
||||
message = getString(R.string.removed_from_favs);
|
||||
binding.favCb.setButtonDrawable(R.drawable.ic_outline_star_plus_24);
|
||||
}
|
||||
final Snackbar snackbar = Snackbar.make(root, message, BaseTransientBottomBar.LENGTH_LONG);
|
||||
snackbar.setAction(R.string.ok, v -> snackbar.dismiss())
|
||||
.setAnimationMode(BaseTransientBottomBar.ANIMATION_MODE_SLIDE)
|
||||
.setAnchorView(fragmentActivity.getBottomNavView())
|
||||
.show();
|
||||
binding.favProgress.setVisibility(View.GONE);
|
||||
binding.favCb.setVisibility(View.VISIBLE);
|
||||
});
|
||||
}
|
||||
|
||||
private void showProfilePicDialog() {
|
||||
|
@ -107,6 +107,11 @@ public class MorePreferencesFragment extends BasePreferencesFragment {
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
generalCategory.addPreference(getPreference(R.string.title_favorites, R.drawable.ic_star_24, preference -> {
|
||||
final NavDirections navDirections = MorePreferencesFragmentDirections.actionMorePreferencesFragmentToFavoritesFragment();
|
||||
NavHostFragment.findNavController(this).navigate(navDirections);
|
||||
return true;
|
||||
}));
|
||||
generalCategory.addPreference(getPreference(R.string.action_settings, R.drawable.ic_outline_settings_24, preference -> {
|
||||
final NavDirections navDirections = MorePreferencesFragmentDirections.actionMorePreferencesFragmentToSettingsPreferencesFragment();
|
||||
NavHostFragment.findNavController(this).navigate(navDirections);
|
||||
|
@ -0,0 +1,7 @@
|
||||
package awais.instagrabber.models.enums;
|
||||
|
||||
public enum FavoriteType {
|
||||
USER,
|
||||
HASHTAG,
|
||||
LOCATION
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package awais.instagrabber.repositories;
|
||||
|
||||
import retrofit2.Call;
|
||||
import retrofit2.http.Header;
|
||||
import retrofit2.http.POST;
|
||||
import retrofit2.http.Path;
|
||||
|
||||
public interface TagsRepository {
|
||||
|
||||
@POST("/web/tags/follow/{tag}/")
|
||||
Call<String> follow(@Header("User-Agent") String userAgent,
|
||||
@Header("x-csrftoken") String csrfToken,
|
||||
@Path("tag") String tag);
|
||||
|
||||
@POST("/web/tags/unfollow/{tag}/")
|
||||
Call<String> unfollow(@Header("User-Agent") String userAgent,
|
||||
@Header("x-csrftoken") String csrfToken,
|
||||
@Path("tag") String tag);
|
||||
}
|
@ -81,4 +81,5 @@ public final class Constants {
|
||||
public static final String ACTION_SHOW_ACTIVITY = "show_activity";
|
||||
public static final String PREF_DARK_THEME = "dark_theme";
|
||||
public static final String PREF_LIGHT_THEME = "light_theme";
|
||||
public static final String DEFAULT_HASH_TAG_PIC = "https://www.instagram.com/static/images/hashtag/search-hashtag-default-avatar.png/1d8417c9a4f5.png";
|
||||
}
|
@ -6,15 +6,17 @@ import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.util.ObjectsCompat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import awais.instagrabber.BuildConfig;
|
||||
import awais.instagrabber.models.enums.FavoriteType;
|
||||
import awaisomereport.LogCollector;
|
||||
|
||||
import static awais.instagrabber.utils.Utils.logCollector;
|
||||
@ -24,12 +26,9 @@ public final class DataBox extends SQLiteOpenHelper {
|
||||
|
||||
private static DataBox sInstance;
|
||||
|
||||
private final static int VERSION = 2;
|
||||
private final static int VERSION = 3;
|
||||
private final static String TABLE_COOKIES = "cookies";
|
||||
private final static String TABLE_FAVORITES = "favorites";
|
||||
private final static String KEY_DATE_ADDED = "date_added";
|
||||
private final static String KEY_QUERY_TEXT = "query_text";
|
||||
private final static String KEY_QUERY_DISPLAY = "query_display";
|
||||
|
||||
private final static String KEY_ID = "id";
|
||||
private final static String KEY_USERNAME = Constants.EXTRAS_USERNAME;
|
||||
@ -38,7 +37,12 @@ public final class DataBox extends SQLiteOpenHelper {
|
||||
private final static String KEY_FULL_NAME = "full_name";
|
||||
private final static String KEY_PROFILE_PIC = "profile_pic";
|
||||
|
||||
private final Context c;
|
||||
private final static String FAV_COL_ID = "id";
|
||||
private final static String FAV_COL_QUERY = "query_text";
|
||||
private final static String FAV_COL_TYPE = "type";
|
||||
private final static String FAV_COL_DISPLAY_NAME = "display_name";
|
||||
private final static String FAV_COL_PIC_URL = "pic_url";
|
||||
private final static String FAV_COL_DATE_ADDED = "date_added";
|
||||
|
||||
public static synchronized DataBox getInstance(final Context context) {
|
||||
if (sInstance == null) sInstance = new DataBox(context.getApplicationContext());
|
||||
@ -47,7 +51,6 @@ public final class DataBox extends SQLiteOpenHelper {
|
||||
|
||||
private DataBox(@Nullable final Context context) {
|
||||
super(context, "cookiebox.db", null, VERSION);
|
||||
c = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -60,42 +63,128 @@ public final class DataBox extends SQLiteOpenHelper {
|
||||
+ KEY_COOKIE + " TEXT,"
|
||||
+ KEY_FULL_NAME + " TEXT,"
|
||||
+ KEY_PROFILE_PIC + " TEXT)");
|
||||
db.execSQL("CREATE TABLE favorites (id INTEGER PRIMARY KEY, query_text TEXT, date_added INTEGER, query_display TEXT)");
|
||||
// db.execSQL("CREATE TABLE favorites (id INTEGER PRIMARY KEY, query_text TEXT, date_added INTEGER, query_display TEXT)");
|
||||
db.execSQL("CREATE TABLE " + TABLE_FAVORITES + " ("
|
||||
+ FAV_COL_ID + " INTEGER PRIMARY KEY,"
|
||||
+ FAV_COL_QUERY + " TEXT,"
|
||||
+ FAV_COL_TYPE + " TEXT,"
|
||||
+ FAV_COL_DISPLAY_NAME + " TEXT,"
|
||||
+ FAV_COL_PIC_URL + " TEXT,"
|
||||
+ FAV_COL_DATE_ADDED + " INTEGER)");
|
||||
Log.i(TAG, "Tables created!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
|
||||
Log.i(TAG, String.format("Updating DB from v%d to v%d", oldVersion, newVersion));
|
||||
if (oldVersion == 1) {
|
||||
db.execSQL("ALTER TABLE " + TABLE_COOKIES + " ADD " + KEY_FULL_NAME + " TEXT");
|
||||
db.execSQL("ALTER TABLE " + TABLE_COOKIES + " ADD " + KEY_PROFILE_PIC + " TEXT");
|
||||
// switch without break, so that all migrations from a previous version to new are run
|
||||
switch (oldVersion) {
|
||||
case 1:
|
||||
db.execSQL("ALTER TABLE " + TABLE_COOKIES + " ADD " + KEY_FULL_NAME + " TEXT");
|
||||
db.execSQL("ALTER TABLE " + TABLE_COOKIES + " ADD " + KEY_PROFILE_PIC + " TEXT");
|
||||
case 2:
|
||||
final List<FavoriteModel> oldFavorites = backupOldFavorites(db);
|
||||
// recreate with new columns (as there will be no doubt about the `query_display` column being present or not in the future versions)
|
||||
db.execSQL("DROP TABLE " + TABLE_FAVORITES);
|
||||
db.execSQL("CREATE TABLE " + TABLE_FAVORITES + " ("
|
||||
+ FAV_COL_ID + " INTEGER PRIMARY KEY,"
|
||||
+ FAV_COL_QUERY + " TEXT,"
|
||||
+ FAV_COL_TYPE + " TEXT,"
|
||||
+ FAV_COL_DISPLAY_NAME + " TEXT,"
|
||||
+ FAV_COL_PIC_URL + " TEXT,"
|
||||
+ FAV_COL_DATE_ADDED + " INTEGER)");
|
||||
// add the old favorites back
|
||||
for (final FavoriteModel oldFavorite : oldFavorites) {
|
||||
addFavorite(db, oldFavorite);
|
||||
}
|
||||
}
|
||||
Log.i(TAG, String.format("DB update from v%d to v%d completed!", oldVersion, newVersion));
|
||||
}
|
||||
|
||||
public final void addFavorite(@NonNull final FavoriteModel favoriteModel) {
|
||||
final String query = favoriteModel.getQuery();
|
||||
final String display = favoriteModel.getDisplayName();
|
||||
@NonNull
|
||||
private List<FavoriteModel> backupOldFavorites(@NonNull final SQLiteDatabase db) {
|
||||
// check if old favorites table had the column query_display
|
||||
final boolean queryDisplayExists = checkColumnExists(db, TABLE_FAVORITES, "query_display");
|
||||
Log.d(TAG, "backupOldFavorites: queryDisplayExists: " + queryDisplayExists);
|
||||
final List<FavoriteModel> oldModels = new ArrayList<>();
|
||||
final String sql = "SELECT "
|
||||
+ "query_text,"
|
||||
+ "date_added"
|
||||
+ (queryDisplayExists ? ",query_display" : "")
|
||||
+ " FROM " + TABLE_FAVORITES;
|
||||
try (final Cursor cursor = db.rawQuery(sql, null)) {
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
do {
|
||||
try {
|
||||
final String queryText = cursor.getString(cursor.getColumnIndex("query_text"));
|
||||
FavoriteType type = null;
|
||||
String query = null;
|
||||
if (queryText.startsWith("@")) {
|
||||
type = FavoriteType.USER;
|
||||
query = queryText.substring(1);
|
||||
} else if (queryText.contains("/")) {
|
||||
type = FavoriteType.LOCATION;
|
||||
query = queryText.substring(0, queryText.indexOf("/"));
|
||||
} else if (queryText.startsWith("#")) {
|
||||
type = FavoriteType.HASHTAG;
|
||||
query = queryText.substring(1);
|
||||
}
|
||||
oldModels.add(new FavoriteModel(
|
||||
-1,
|
||||
query,
|
||||
type,
|
||||
queryDisplayExists ? cursor.getString(cursor.getColumnIndex("query_display"))
|
||||
: null,
|
||||
null,
|
||||
new Date(cursor.getLong(cursor.getColumnIndex("date_added")))
|
||||
));
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "onUpgrade", e);
|
||||
}
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "onUpgrade", e);
|
||||
}
|
||||
Log.d(TAG, "backupOldFavorites: oldModels:" + oldModels);
|
||||
return oldModels;
|
||||
}
|
||||
|
||||
public boolean checkColumnExists(@NonNull final SQLiteDatabase db,
|
||||
@NonNull final String tableName,
|
||||
@NonNull final String columnName) {
|
||||
boolean exists = false;
|
||||
try (Cursor cursor = db.rawQuery("PRAGMA table_info(" + tableName + ")", null)) {
|
||||
if (cursor.moveToFirst()) {
|
||||
do {
|
||||
final String currentColumn = cursor.getString(cursor.getColumnIndex("name"));
|
||||
if (currentColumn.equals(columnName)) {
|
||||
exists = true;
|
||||
}
|
||||
} while (cursor.moveToNext());
|
||||
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Log.e(TAG, "checkColumnExists", ex);
|
||||
}
|
||||
return exists;
|
||||
}
|
||||
|
||||
public final void addFavorite(@NonNull final FavoriteModel model) {
|
||||
final String query = model.getQuery();
|
||||
if (!TextUtils.isEmpty(query)) {
|
||||
try (final SQLiteDatabase db = getWritableDatabase()) {
|
||||
db.beginTransaction();
|
||||
try {
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(KEY_DATE_ADDED, favoriteModel.getDate());
|
||||
values.put(KEY_QUERY_TEXT, query);
|
||||
values.put(KEY_QUERY_DISPLAY, display);
|
||||
|
||||
final int rows = db.update(TABLE_FAVORITES, values, KEY_QUERY_TEXT + "=?", new String[]{query});
|
||||
|
||||
if (rows != 1)
|
||||
db.insertOrThrow(TABLE_FAVORITES, null, values);
|
||||
|
||||
addFavorite(db, model);
|
||||
db.setTransactionSuccessful();
|
||||
} catch (final Exception e) {
|
||||
if (logCollector != null)
|
||||
if (logCollector != null) {
|
||||
logCollector.appendException(e, LogCollector.LogFile.DATA_BOX_FAVORITES, "addFavorite");
|
||||
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
|
||||
}
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.e(TAG, "", e);
|
||||
}
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
}
|
||||
@ -103,23 +192,40 @@ public final class DataBox extends SQLiteOpenHelper {
|
||||
}
|
||||
}
|
||||
|
||||
public final synchronized void delFavorite(@NonNull final FavoriteModel favoriteModel) {
|
||||
final String query = favoriteModel.getQuery();
|
||||
private void addFavorite(@NonNull final SQLiteDatabase db, @NonNull final FavoriteModel model) {
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(FAV_COL_QUERY, model.getQuery());
|
||||
values.put(FAV_COL_TYPE, model.getType().toString());
|
||||
values.put(FAV_COL_DISPLAY_NAME, model.getDisplayName());
|
||||
values.put(FAV_COL_PIC_URL, model.getPicUrl());
|
||||
values.put(FAV_COL_DATE_ADDED, model.getDateAdded().getTime());
|
||||
int rows = 0;
|
||||
if (model.getId() >= 1) {
|
||||
rows = db.update(TABLE_FAVORITES, values, FAV_COL_ID + "=?", new String[]{String.valueOf(model.getId())});
|
||||
}
|
||||
if (rows != 1) {
|
||||
db.insertOrThrow(TABLE_FAVORITES, null, values);
|
||||
}
|
||||
}
|
||||
|
||||
public final synchronized void deleteFavorite(@NonNull final String query, @NonNull final FavoriteType type) {
|
||||
if (!TextUtils.isEmpty(query)) {
|
||||
try (final SQLiteDatabase db = getWritableDatabase()) {
|
||||
db.beginTransaction();
|
||||
try {
|
||||
final int rowsDeleted = db.delete(TABLE_FAVORITES, "query_text=? AND date_added=?",
|
||||
new String[]{query, Long.toString(favoriteModel.getDate())});
|
||||
final int rowsDeleted = db.delete(TABLE_FAVORITES,
|
||||
FAV_COL_QUERY + "=?" +
|
||||
" AND " + FAV_COL_TYPE + "=?",
|
||||
new String[]{query, type.toString()});
|
||||
|
||||
final int rowsDeletedTwo = db.delete(TABLE_FAVORITES, "query_text=? AND date_added=?",
|
||||
new String[]{query.replaceAll("@", ""), Long.toString(favoriteModel.getDate())});
|
||||
|
||||
if (rowsDeleted > 0 || rowsDeletedTwo > 0) db.setTransactionSuccessful();
|
||||
if (rowsDeleted > 0) db.setTransactionSuccessful();
|
||||
} catch (final Exception e) {
|
||||
if (logCollector != null)
|
||||
logCollector.appendException(e, LogCollector.LogFile.DATA_BOX_FAVORITES, "delFavorite");
|
||||
if (BuildConfig.DEBUG) Log.e(TAG, "Error", e);
|
||||
if (logCollector != null) {
|
||||
logCollector.appendException(e, LogCollector.LogFile.DATA_BOX_FAVORITES, "deleteFavorite");
|
||||
}
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.e(TAG, "Error", e);
|
||||
}
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
}
|
||||
@ -127,73 +233,74 @@ public final class DataBox extends SQLiteOpenHelper {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public final ArrayList<FavoriteModel> getAllFavorites() {
|
||||
ArrayList<FavoriteModel> favorites = null;
|
||||
FavoriteModel tempFav;
|
||||
@NonNull
|
||||
public final List<FavoriteModel> getAllFavorites() {
|
||||
final List<FavoriteModel> favorites = new ArrayList<>();
|
||||
final SQLiteDatabase db = getWritableDatabase();
|
||||
|
||||
try (final Cursor cursor = db.rawQuery("SELECT query_text, date_added, query_display FROM favorites ORDER BY date_added DESC", null)) {
|
||||
try (final Cursor cursor = db.rawQuery("SELECT "
|
||||
+ FAV_COL_ID + ","
|
||||
+ FAV_COL_QUERY + ","
|
||||
+ FAV_COL_TYPE + ","
|
||||
+ FAV_COL_DISPLAY_NAME + ","
|
||||
+ FAV_COL_PIC_URL + ","
|
||||
+ FAV_COL_DATE_ADDED
|
||||
+ " FROM " + TABLE_FAVORITES,
|
||||
null)) {
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
db.beginTransaction();
|
||||
favorites = new ArrayList<>();
|
||||
FavoriteModel tempFav;
|
||||
do {
|
||||
FavoriteType type = null;
|
||||
try {
|
||||
type = FavoriteType.valueOf(cursor.getString(cursor.getColumnIndex(FAV_COL_TYPE)));
|
||||
} catch (IllegalArgumentException ignored) {}
|
||||
tempFav = new FavoriteModel(
|
||||
(cursor.getString(0).charAt(0) == '@' || cursor.getString(0).charAt(0) == '#' || cursor.getString(0).contains("/"))
|
||||
? cursor.getString(0)
|
||||
: "@" + cursor.getString(0), // query text
|
||||
cursor.getLong(1), // date added
|
||||
cursor.getString(2) == null ? (cursor.getString(0).charAt(0) == '@' || cursor.getString(0).charAt(0) == '#' || cursor
|
||||
.getString(0).contains("/"))
|
||||
? cursor.getString(0)
|
||||
: "@" + cursor.getString(0) : cursor.getString(2) // display
|
||||
cursor.getInt(cursor.getColumnIndex(FAV_COL_ID)),
|
||||
cursor.getString(cursor.getColumnIndex(FAV_COL_QUERY)),
|
||||
type,
|
||||
cursor.getString(cursor.getColumnIndex(FAV_COL_DISPLAY_NAME)),
|
||||
cursor.getString(cursor.getColumnIndex(FAV_COL_PIC_URL)),
|
||||
new Date(cursor.getLong(cursor.getColumnIndex(FAV_COL_DATE_ADDED)))
|
||||
);
|
||||
if (cursor.getString(2) == null) {
|
||||
try {
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(KEY_DATE_ADDED, tempFav.getDate());
|
||||
values.put(KEY_QUERY_TEXT, tempFav.getQuery());
|
||||
values.put(KEY_QUERY_DISPLAY, tempFav.getDisplayName());
|
||||
|
||||
final int rows = db.update(TABLE_FAVORITES, values, KEY_QUERY_TEXT + "=?", new String[]{tempFav.getQuery()});
|
||||
|
||||
if (rows != 1)
|
||||
db.insertOrThrow(TABLE_FAVORITES, null, values);
|
||||
} catch (final Exception e) {
|
||||
if (logCollector != null)
|
||||
logCollector.appendException(e, LogCollector.LogFile.DATA_BOX_FAVORITES, "delFavorite");
|
||||
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
|
||||
}
|
||||
}
|
||||
favorites.add(tempFav);
|
||||
} while (cursor.moveToNext());
|
||||
db.endTransaction();
|
||||
}
|
||||
} catch (final Exception x) {
|
||||
Log.e("austin_debug", "", x);
|
||||
try {
|
||||
db.execSQL("ALTER TABLE favorites ADD query_display TEXT");
|
||||
Toast.makeText(c, "DB has migrated, launch quick access again.", Toast.LENGTH_SHORT).show();
|
||||
} catch (final Exception e) {
|
||||
if (logCollector != null)
|
||||
logCollector.appendException(e, LogCollector.LogFile.DATA_BOX_FAVORITES, "migrate");
|
||||
Toast.makeText(c, "DB migration failed, contact maintainer.", Toast.LENGTH_SHORT).show();
|
||||
if (BuildConfig.DEBUG) Log.e(TAG, "", e);
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
Log.e(TAG, "", e);
|
||||
}
|
||||
|
||||
return favorites;
|
||||
}
|
||||
|
||||
public final String getFavorite(@NonNull final String query) {
|
||||
@Nullable
|
||||
public final FavoriteModel getFavorite(@NonNull final String query, @NonNull final FavoriteType type) {
|
||||
try (final SQLiteDatabase db = getReadableDatabase();
|
||||
final Cursor cursor = db.rawQuery("SELECT query_text, date_added FROM favorites WHERE "
|
||||
+ KEY_QUERY_TEXT + "='" + query + "' ORDER BY date_added DESC", null)) {
|
||||
final Cursor cursor = db.rawQuery("SELECT "
|
||||
+ FAV_COL_ID + ","
|
||||
+ FAV_COL_QUERY + ","
|
||||
+ FAV_COL_TYPE + ","
|
||||
+ FAV_COL_DISPLAY_NAME + ","
|
||||
+ FAV_COL_PIC_URL + ","
|
||||
+ FAV_COL_DATE_ADDED
|
||||
+ " FROM " + TABLE_FAVORITES
|
||||
+ " WHERE " + FAV_COL_QUERY + "='" + query + "'"
|
||||
+ " AND " + FAV_COL_TYPE + "='" + type.toString() + "'",
|
||||
null)) {
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
return cursor.getString(0) + "/" + String.valueOf(cursor.getLong(1));
|
||||
FavoriteType favoriteType = null;
|
||||
try {
|
||||
favoriteType = FavoriteType.valueOf(cursor.getString(cursor.getColumnIndex(FAV_COL_TYPE)));
|
||||
} catch (IllegalArgumentException ignored) {}
|
||||
return new FavoriteModel(
|
||||
cursor.getInt(cursor.getColumnIndex(FAV_COL_ID)),
|
||||
cursor.getString(cursor.getColumnIndex(FAV_COL_QUERY)),
|
||||
favoriteType,
|
||||
cursor.getString(cursor.getColumnIndex(FAV_COL_DISPLAY_NAME)),
|
||||
cursor.getString(cursor.getColumnIndex(FAV_COL_PIC_URL)),
|
||||
new Date(cursor.getLong(cursor.getColumnIndex(FAV_COL_DATE_ADDED)))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -399,31 +506,80 @@ public final class DataBox extends SQLiteOpenHelper {
|
||||
}
|
||||
|
||||
public static class FavoriteModel {
|
||||
private final String query, displayName;
|
||||
private final long date;
|
||||
private final int id;
|
||||
private final String query;
|
||||
private final FavoriteType type;
|
||||
private final String displayName;
|
||||
private final String picUrl;
|
||||
private final Date dateAdded;
|
||||
|
||||
public FavoriteModel(final String query, final long date, final String displayName) {
|
||||
public FavoriteModel(final int id,
|
||||
final String query,
|
||||
final FavoriteType type,
|
||||
final String displayName,
|
||||
final String picUrl,
|
||||
final Date dateAdded) {
|
||||
this.id = id;
|
||||
this.query = query;
|
||||
this.date = date;
|
||||
this.type = type;
|
||||
this.displayName = displayName;
|
||||
this.picUrl = picUrl;
|
||||
this.dateAdded = dateAdded;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getQuery() {
|
||||
return query;
|
||||
}
|
||||
|
||||
public FavoriteType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public long getDate() {
|
||||
return date;
|
||||
public String getPicUrl() {
|
||||
return picUrl;
|
||||
}
|
||||
|
||||
public Date getDateAdded() {
|
||||
return dateAdded;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
final FavoriteModel that = (FavoriteModel) o;
|
||||
return id == that.id &&
|
||||
ObjectsCompat.equals(query, that.query) &&
|
||||
type == that.type &&
|
||||
ObjectsCompat.equals(displayName, that.displayName) &&
|
||||
ObjectsCompat.equals(picUrl, that.picUrl) &&
|
||||
ObjectsCompat.equals(dateAdded, that.dateAdded);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return ObjectsCompat.hash(id, query, type, displayName, picUrl, dateAdded);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return query;
|
||||
return "FavoriteModel{" +
|
||||
"id=" + id +
|
||||
", query='" + query + '\'' +
|
||||
", type=" + type +
|
||||
", displayName='" + displayName + '\'' +
|
||||
", picUrl='" + picUrl + '\'' +
|
||||
", dateAdded=" + dateAdded +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
}
|
@ -21,6 +21,7 @@ import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
@ -35,6 +36,8 @@ import static awais.instagrabber.utils.Utils.logCollector;
|
||||
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||
|
||||
public final class ExportImportUtils {
|
||||
private static final String TAG = "ExportImportUtils";
|
||||
|
||||
public static final int FLAG_COOKIES = 1;
|
||||
public static final int FLAG_FAVORITES = 1 << 1;
|
||||
public static final int FLAG_SETTINGS = 1 << 2;
|
||||
@ -60,7 +63,7 @@ public final class ExportImportUtils {
|
||||
if (fetchListener != null) fetchListener.onResult(false);
|
||||
if (logCollector != null)
|
||||
logCollector.appendException(e, LogFile.UTILS_EXPORT, "Export::isPass");
|
||||
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
|
||||
if (BuildConfig.DEBUG) Log.e(TAG, "", e);
|
||||
}
|
||||
} else {
|
||||
exportBytes = Base64.encode(exportString.getBytes(), Base64.DEFAULT | Base64.NO_WRAP | Base64.NO_PADDING);
|
||||
@ -75,7 +78,7 @@ public final class ExportImportUtils {
|
||||
if (fetchListener != null) fetchListener.onResult(false);
|
||||
if (logCollector != null)
|
||||
logCollector.appendException(e, LogFile.UTILS_EXPORT, "Export::notPass");
|
||||
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
|
||||
if (BuildConfig.DEBUG) Log.e(TAG, "", e);
|
||||
}
|
||||
} else if (fetchListener != null) fetchListener.onResult(false);
|
||||
}
|
||||
@ -111,7 +114,7 @@ public final class ExportImportUtils {
|
||||
if (fetchListener != null) fetchListener.onResult(false);
|
||||
if (logCollector != null)
|
||||
logCollector.appendException(e, LogFile.UTILS_IMPORT, "Import::pass");
|
||||
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
|
||||
if (BuildConfig.DEBUG) Log.e(TAG, "", e);
|
||||
}
|
||||
|
||||
} else
|
||||
@ -129,7 +132,7 @@ public final class ExportImportUtils {
|
||||
} catch (final Exception e) {
|
||||
if (fetchListener != null) fetchListener.onResult(false);
|
||||
if (logCollector != null) logCollector.appendException(e, LogFile.UTILS_IMPORT, "Import");
|
||||
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
|
||||
if (BuildConfig.DEBUG) Log.e(TAG, "", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -172,9 +175,9 @@ public final class ExportImportUtils {
|
||||
final int favsLen = favs.length();
|
||||
for (int i = 0; i < favsLen; ++i) {
|
||||
final JSONObject favsObject = favs.getJSONObject(i);
|
||||
Utils.dataBox.addFavorite(new DataBox.FavoriteModel(favsObject.getString("q"),
|
||||
favsObject.getLong("d"),
|
||||
favsObject.has("s") ? favsObject.getString("s") : favsObject.getString("q")));
|
||||
// Utils.dataBox.addFavorite(new DataBox.FavoriteModel(favsObject.getString("q"),
|
||||
// favsObject.getLong("d"),
|
||||
// favsObject.has("s") ? favsObject.getString("s") : favsObject.getString("q")));
|
||||
}
|
||||
}
|
||||
|
||||
@ -183,7 +186,7 @@ public final class ExportImportUtils {
|
||||
} catch (final Exception e) {
|
||||
if (fetchListener != null) fetchListener.onResult(false);
|
||||
if (logCollector != null) logCollector.appendException(e, LogFile.UTILS_IMPORT, "saveToSettings");
|
||||
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
|
||||
if (BuildConfig.DEBUG) Log.e(TAG, "", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -212,7 +215,7 @@ public final class ExportImportUtils {
|
||||
result = jsonObject.toString();
|
||||
} catch (final Exception e) {
|
||||
if (logCollector != null) logCollector.appendException(e, LogFile.UTILS_EXPORT, "getExportString");
|
||||
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
|
||||
if (BuildConfig.DEBUG) Log.e(TAG, "", e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -249,7 +252,7 @@ public final class ExportImportUtils {
|
||||
} catch (final Exception e) {
|
||||
result = null;
|
||||
if (logCollector != null) logCollector.appendException(e, LogFile.UTILS_EXPORT, "getSettings");
|
||||
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
|
||||
if (BuildConfig.DEBUG) Log.e(TAG, "", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -261,15 +264,15 @@ public final class ExportImportUtils {
|
||||
String result = null;
|
||||
if (Utils.dataBox != null) {
|
||||
try {
|
||||
final ArrayList<DataBox.FavoriteModel> allFavorites = Utils.dataBox.getAllFavorites();
|
||||
final List<DataBox.FavoriteModel> allFavorites = Utils.dataBox.getAllFavorites();
|
||||
final int allFavoritesSize;
|
||||
if (allFavorites != null && (allFavoritesSize = allFavorites.size()) > 0) {
|
||||
if ((allFavoritesSize = allFavorites.size()) > 0) {
|
||||
final JSONArray jsonArray = new JSONArray();
|
||||
for (int i = 0; i < allFavoritesSize; i++) {
|
||||
final DataBox.FavoriteModel favorite = allFavorites.get(i);
|
||||
final JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("q", favorite.getQuery());
|
||||
jsonObject.put("d", favorite.getDate());
|
||||
jsonObject.put("d", favorite.getDateAdded().getTime());
|
||||
jsonObject.put("s", favorite.getDisplayName());
|
||||
jsonArray.put(jsonObject);
|
||||
}
|
||||
@ -278,7 +281,7 @@ public final class ExportImportUtils {
|
||||
} catch (final Exception e) {
|
||||
result = null;
|
||||
if (logCollector != null) logCollector.appendException(e, LogFile.UTILS_EXPORT, "getFavorites");
|
||||
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
|
||||
if (BuildConfig.DEBUG) Log.e(TAG, "", e);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@ -305,7 +308,7 @@ public final class ExportImportUtils {
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
result = null;
|
||||
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
|
||||
if (BuildConfig.DEBUG) Log.e(TAG, "", e);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -57,7 +57,8 @@ public class NavigationExtensions {
|
||||
return false;
|
||||
}
|
||||
String newlySelectedItemTag = graphIdToTagMap.get(item.getItemId());
|
||||
if (!selectedItemTag[0].equals(newlySelectedItemTag)) {
|
||||
String tag = selectedItemTag[0];
|
||||
if (tag != null && !tag.equals(newlySelectedItemTag)) {
|
||||
fragmentManager.popBackStack(firstFragmentTag, FragmentManager.POP_BACK_STACK_INCLUSIVE);
|
||||
Fragment fragment = fragmentManager.findFragmentByTag(newlySelectedItemTag);
|
||||
if (fragment == null) {
|
||||
|
@ -6,7 +6,6 @@ import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
@ -21,7 +20,6 @@ import android.widget.Toast;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import com.google.android.exoplayer2.database.ExoDatabaseProvider;
|
||||
|
@ -0,0 +1,19 @@
|
||||
package awais.instagrabber.viewmodels;
|
||||
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import awais.instagrabber.utils.DataBox;
|
||||
|
||||
public class FavoritesViewModel extends ViewModel {
|
||||
private MutableLiveData<List<DataBox.FavoriteModel>> list;
|
||||
|
||||
public MutableLiveData<List<DataBox.FavoriteModel>> getList() {
|
||||
if (list == null) {
|
||||
list = new MutableLiveData<>();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
package awais.instagrabber.webservices;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import awais.instagrabber.repositories.TagsRepository;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
import retrofit2.Retrofit;
|
||||
|
||||
public class TagsService extends BaseService {
|
||||
|
||||
private static final String TAG = "TagsService";
|
||||
|
||||
// web for www.instagram.com
|
||||
private final TagsRepository webRepository;
|
||||
|
||||
private static TagsService instance;
|
||||
|
||||
private TagsService() {
|
||||
final Retrofit webRetrofit = getRetrofitBuilder()
|
||||
.baseUrl("https://www.instagram.com/")
|
||||
.build();
|
||||
webRepository = webRetrofit.create(TagsRepository.class);
|
||||
}
|
||||
|
||||
public static TagsService getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new TagsService();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void follow(@NonNull final String tag,
|
||||
@NonNull final String csrfToken,
|
||||
final ServiceCallback<Boolean> callback) {
|
||||
final Call<String> request = webRepository.follow(Constants.USER_AGENT,
|
||||
csrfToken,
|
||||
tag);
|
||||
request.enqueue(new Callback<String>() {
|
||||
@Override
|
||||
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) {
|
||||
final String body = response.body();
|
||||
if (body == null) {
|
||||
callback.onFailure(new RuntimeException("body is null"));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
final JSONObject jsonObject = new JSONObject(body);
|
||||
final String status = jsonObject.optString("status");
|
||||
callback.onSuccess(status.equals("ok"));
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "onResponse: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) {
|
||||
// Log.e(TAG, "onFailure: ", t);
|
||||
callback.onFailure(t);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void unfollow(@NonNull final String tag,
|
||||
@NonNull final String csrfToken,
|
||||
final ServiceCallback<Boolean> callback) {
|
||||
final Call<String> request = webRepository.unfollow(Constants.USER_AGENT,
|
||||
csrfToken,
|
||||
tag);
|
||||
request.enqueue(new Callback<String>() {
|
||||
@Override
|
||||
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) {
|
||||
final String body = response.body();
|
||||
if (body == null) {
|
||||
callback.onFailure(new RuntimeException("body is null"));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
final JSONObject jsonObject = new JSONObject(body);
|
||||
final String status = jsonObject.optString("status");
|
||||
callback.onSuccess(status.equals("ok"));
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "onResponse: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) {
|
||||
// Log.e(TAG, "onFailure: ", t);
|
||||
callback.onFailure(t);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
10
app/src/main/res/drawable/ic_block_24.xml
Normal file
10
app/src/main/res/drawable/ic_block_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,2zM4,12c0,-4.42 3.58,-8 8,-8 1.85,0 3.55,0.63 4.9,1.69L5.69,16.9C4.63,15.55 4,13.85 4,12zM12,20c-1.85,0 -3.55,-0.63 -4.9,-1.69L18.31,7.1C19.37,8.45 20,10.15 20,12c0,4.42 -3.58,8 -8,8z"/>
|
||||
</vector>
|
10
app/src/main/res/drawable/ic_highlight_off_24.xml
Normal file
10
app/src/main/res/drawable/ic_highlight_off_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="M14.59,8L12,10.59 9.41,8 8,9.41 10.59,12 8,14.59 9.41,16 12,13.41 14.59,16 16,14.59 13.41,12 16,9.41 14.59,8zM12,2C6.47,2 2,6.47 2,12s4.47,10 10,10 10,-4.47 10,-10S17.53,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z"/>
|
||||
</vector>
|
10
app/src/main/res/drawable/ic_outline_class_24.xml
Normal file
10
app/src/main/res/drawable/ic_outline_class_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="M18,2L6,2c-1.1,0 -2,0.9 -2,2v16c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,4c0,-1.1 -0.9,-2 -2,-2zM9,4h2v5l-1,-0.75L9,9L9,4zM18,20L6,20L6,4h1v9l3,-2.25L13,13L13,4h5v16z"/>
|
||||
</vector>
|
10
app/src/main/res/drawable/ic_outline_map_24.xml
Normal file
10
app/src/main/res/drawable/ic_outline_map_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.5,3l-0.16,0.03L15,5.1 9,3 3.36,4.9c-0.21,0.07 -0.36,0.25 -0.36,0.48L3,20.5c0,0.28 0.22,0.5 0.5,0.5l0.16,-0.03L9,18.9l6,2.1 5.64,-1.9c0.21,-0.07 0.36,-0.25 0.36,-0.48L21,3.5c0,-0.28 -0.22,-0.5 -0.5,-0.5zM10,5.47l4,1.4v11.66l-4,-1.4L10,5.47zM5,6.46l3,-1.01v11.7l-3,1.16L5,6.46zM19,17.54l-3,1.01L16,6.86l3,-1.16v11.84z"/>
|
||||
</vector>
|
10
app/src/main/res/drawable/ic_outline_person_add_24.xml
Normal file
10
app/src/main/res/drawable/ic_outline_person_add_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="M15,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM15,6c1.1,0 2,0.9 2,2s-0.9,2 -2,2 -2,-0.9 -2,-2 0.9,-2 2,-2zM15,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4zM9,18c0.22,-0.72 3.31,-2 6,-2 2.7,0 5.8,1.29 6,2L9,18zM6,15v-3h3v-2L6,10L6,7L4,7v3L1,10v2h3v3z"/>
|
||||
</vector>
|
@ -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="M15,6c1.1,0 2,0.9 2,2 0,0.99 -0.73,1.82 -1.67,1.97l-2.31,-2.31C13.19,6.72 14.01,6 15,6m0,-2c-2.21,0 -4,1.79 -4,4 0,0.18 0.03,0.35 0.05,0.52l3.43,3.43c0.17,0.02 0.34,0.05 0.52,0.05 2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4zM16.69,14.16L22.53,20L23,20v-2c0,-2.14 -3.56,-3.5 -6.31,-3.84zM13.01,16.13L14.88,18L9,18c0.08,-0.24 0.88,-1.01 2.91,-1.57l1.1,-0.3M1.41,1.71L0,3.12l4,4L4,10L1,10v2h3v3h2v-3h2.88l2.51,2.51C9.19,15.11 7,16.3 7,18v2h9.88l4,4 1.41,-1.41L1.41,1.71zM6,10v-0.88l0.88,0.88L6,10z"/>
|
||||
</vector>
|
10
app/src/main/res/drawable/ic_outline_person_pin_24.xml
Normal file
10
app/src/main/res/drawable/ic_outline_person_pin_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,2L5,2c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h4l3,3 3,-3h4c1.1,0 2,-0.9 2,-2L21,4c0,-1.1 -0.9,-2 -2,-2zM19,18h-4.83l-0.59,0.59L12,20.17l-1.59,-1.59 -0.58,-0.58L5,18L5,4h14v14zM12,11c1.65,0 3,-1.35 3,-3s-1.35,-3 -3,-3 -3,1.35 -3,3 1.35,3 3,3zM12,7c0.55,0 1,0.45 1,1s-0.45,1 -1,1 -1,-0.45 -1,-1 0.45,-1 1,-1zM18,15.58c0,-2.5 -3.97,-3.58 -6,-3.58s-6,1.08 -6,3.58L6,17h12v-1.42zM8.48,15c0.74,-0.51 2.23,-1 3.52,-1s2.78,0.49 3.52,1L8.48,15z"/>
|
||||
</vector>
|
10
app/src/main/res/drawable/ic_outline_star_24.xml
Normal file
10
app/src/main/res/drawable/ic_outline_star_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="M22,9.24l-7.19,-0.62L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21 12,17.27 18.18,21l-1.63,-7.03L22,9.24zM12,15.4l-3.76,2.27 1,-4.28 -3.32,-2.88 4.38,-0.38L12,6.1l1.71,4.04 4.38,0.38 -3.32,2.88 1,4.28L12,15.4z"/>
|
||||
</vector>
|
10
app/src/main/res/drawable/ic_outline_star_plus_24.xml
Normal file
10
app/src/main/res/drawable/ic_outline_star_plus_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:tint="?attr/colorControlNormal"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#000"
|
||||
android:pathData="M5.8 21L7.4 14L2 9.2L9.2 8.6L12 2L14.8 8.6L22 9.2L18.8 12H18C17.3 12 16.6 12.1 15.9 12.4L18.1 10.5L13.7 10.1L12 6.1L10.3 10.1L5.9 10.5L9.2 13.4L8.2 17.7L12 15.4L12.5 15.7C12.3 16.2 12.1 16.8 12.1 17.3L5.8 21M17 14V17H14V19H17V22H19V19H22V17H19V14H17Z" />
|
||||
</vector>
|
8
app/src/main/res/drawable/ic_star_check_24.xml
Normal file
8
app/src/main/res/drawable/ic_star_check_24.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<!-- drawable/star_check.xml -->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="24dp"
|
||||
android:width="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path android:fillColor="#000" android:pathData="M5.8 21L7.4 14L2 9.2L9.2 8.6L12 2L14.8 8.6L22 9.2L18.8 12H18C14.9 12 12.4 14.3 12 17.3L5.8 21M17.8 21.2L22.6 16.4L21.3 15L17.7 18.6L16.2 17L15 18.2L17.8 21.2" />
|
||||
</vector>
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<solid android:color="@color/semi_transparent_black" />
|
||||
<solid android:color="@color/black_a50" />
|
||||
<padding
|
||||
android:left="2dp"
|
||||
android:right="2dp"
|
||||
|
6
app/src/main/res/drawable/sl_favourite_24.xml
Normal file
6
app/src/main/res/drawable/sl_favourite_24.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/ic_outline_star_plus_24" android:state_checked="false" />
|
||||
<item android:drawable="@drawable/ic_star_check_24" android:state_checked="true" />
|
||||
<item android:drawable="@drawable/ic_outline_star_plus_24" />
|
||||
</selector>
|
@ -28,7 +28,6 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
app:layout_collapseMode="none"
|
||||
app:popupTheme="@style/Widget.AppTheme.Toolbar.PrimarySurface"
|
||||
app:title="@string/app_name"
|
||||
tools:menu="@menu/main_menu" />
|
||||
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||
|
@ -4,7 +4,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/semi_transparent_black">
|
||||
android:background="@color/black_a50">
|
||||
|
||||
<awais.instagrabber.customviews.drawee.ZoomableDraweeView
|
||||
android:id="@+id/imageViewer"
|
||||
|
7
app/src/main/res/layout/fragment_favorites.xml
Normal file
7
app/src/main/res/layout/fragment_favorites.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/favorite_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:listitem="@layout/item_suggestion" />
|
@ -17,47 +17,120 @@
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_scrollFlags="scroll">
|
||||
|
||||
<LinearLayout
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/tagInfoContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/profile_info_container_bottom_space"
|
||||
android:visibility="visible">
|
||||
android:padding="@dimen/profile_info_container_bottom_space">
|
||||
|
||||
<awais.instagrabber.customviews.CircularImageView
|
||||
android:id="@+id/mainHashtagImage"
|
||||
android:layout_width="@dimen/profile_picture_size"
|
||||
android:layout_height="@dimen/profile_picture_size"
|
||||
android:adjustViewBounds="true"
|
||||
android:background="?selectableItemBackgroundBorderless" />
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/mainTagPostCount"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:background="@mipmap/ic_launcher" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/mainTagPostCount"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginRight="12dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:gravity="center"
|
||||
android:padding="8dp"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat"
|
||||
android:textSize="15sp"
|
||||
tools:text="35\nPosts" />
|
||||
app:layout_constraintBottom_toTopOf="@id/btnFollowTag"
|
||||
app:layout_constraintStart_toEndOf="@id/mainHashtagImage"
|
||||
app:layout_constraintTop_toTopOf="@id/mainHashtagImage"
|
||||
tools:text="35 Posts" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/btnFollowTag"
|
||||
android:layout_width="0dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="2"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:text="@string/follow"
|
||||
android:textColor="@color/btn_pink_text_color"
|
||||
android:textSize="20sp"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/btn_pink_background" />
|
||||
</LinearLayout>
|
||||
app:chipBackgroundColor="@null"
|
||||
app:chipIcon="@drawable/ic_outline_person_add_24"
|
||||
app:chipIconTint="@color/deep_purple_800"
|
||||
app:layout_constraintBottom_toBottomOf="@id/mainHashtagImage"
|
||||
app:layout_constraintStart_toEndOf="@id/mainHashtagImage"
|
||||
app:layout_constraintTop_toBottomOf="@id/mainTagPostCount"
|
||||
app:rippleColor="@color/purple_200" />
|
||||
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/fav_chip"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:text="@string/add_to_favorites"
|
||||
android:visibility="gone"
|
||||
app:chipBackgroundColor="@null"
|
||||
app:chipIcon="@drawable/ic_outline_star_plus_24"
|
||||
app:chipIconTint="@color/yellow_800"
|
||||
app:layout_constraintBottom_toBottomOf="@id/mainHashtagImage"
|
||||
app:layout_constraintStart_toEndOf="@id/btnFollowTag"
|
||||
app:layout_constraintTop_toBottomOf="@id/mainTagPostCount"
|
||||
app:rippleColor="@color/yellow_400" />
|
||||
|
||||
<!--<com.google.android.material.chip.Chip-->
|
||||
<!-- android:layout_width="wrap_content"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- app:layout_constraintBottom_toBottomOf="@id/mainHashtagImage"-->
|
||||
<!-- app:layout_constraintStart_toEndOf="@id/mainHashtagImage"-->
|
||||
<!-- app:layout_constraintTop_toBottomOf="@id/mainTagPostCount" />-->
|
||||
|
||||
<!--<com.google.android.material.button.MaterialButton-->
|
||||
<!-- android:id="@+id/btnFollowTag"-->
|
||||
<!-- style="@style/Widget.MaterialComponents.Button.TextButton"-->
|
||||
<!-- android:layout_width="0dp"-->
|
||||
<!-- android:layout_height="0dp"-->
|
||||
<!-- android:text="@string/follow"-->
|
||||
<!-- android:textColor="@color/deep_purple_200"-->
|
||||
<!-- android:visibility="gone"-->
|
||||
<!-- app:icon="@drawable/ic_outline_person_add_24"-->
|
||||
<!-- app:iconGravity="top"-->
|
||||
<!-- app:iconTint="@color/deep_purple_200"-->
|
||||
<!-- app:layout_constraintBottom_toTopOf="@id/fav_cb"-->
|
||||
<!-- app:layout_constraintEnd_toEndOf="parent"-->
|
||||
<!-- app:layout_constraintStart_toEndOf="@id/mainTagPostCount"-->
|
||||
<!-- app:layout_constraintTop_toTopOf="@id/mainHashtagImage"-->
|
||||
<!-- tools:visibility="visible" />-->
|
||||
|
||||
<!--<CheckBox-->
|
||||
<!-- android:id="@+id/fav_cb"-->
|
||||
<!-- android:layout_width="0dp"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:button="@drawable/sl_favourite_24"-->
|
||||
<!-- android:paddingStart="8dp"-->
|
||||
<!-- android:paddingEnd="8dp"-->
|
||||
<!-- android:text="Add to favorites"-->
|
||||
<!-- android:visibility="gone"-->
|
||||
<!-- app:buttonTint="@color/yellow_800"-->
|
||||
<!-- app:layout_constraintBottom_toBottomOf="@id/mainHashtagImage"-->
|
||||
<!-- app:layout_constraintEnd_toEndOf="parent"-->
|
||||
<!-- app:layout_constraintStart_toEndOf="@id/mainHashtagImage"-->
|
||||
<!-- app:layout_constraintTop_toBottomOf="@id/btnFollowTag"-->
|
||||
<!-- tools:visibility="gone" />-->
|
||||
|
||||
<!--<ProgressBar-->
|
||||
<!-- android:id="@+id/fav_progress"-->
|
||||
<!-- style="@style/Widget.MaterialComponents.ProgressIndicator.Circular.Indeterminate"-->
|
||||
<!-- android:layout_width="24dp"-->
|
||||
<!-- android:layout_height="24dp"-->
|
||||
<!-- android:paddingStart="8dp"-->
|
||||
<!-- android:paddingEnd="8dp"-->
|
||||
<!-- android:visibility="gone"-->
|
||||
<!-- app:layout_constraintBottom_toBottomOf="@id/mainHashtagImage"-->
|
||||
<!-- app:layout_constraintStart_toStartOf="@id/fav_cb"-->
|
||||
<!-- app:layout_constraintTop_toBottomOf="@id/mainTagPostCount"-->
|
||||
<!-- tools:visibility="gone" />-->
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
|
@ -17,101 +17,128 @@
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_scrollFlags="scroll|exitUntilCollapsed">
|
||||
|
||||
<RelativeLayout
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/locInfoContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:animateLayoutChanges="true"
|
||||
android:background="@null"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="5dp">
|
||||
android:padding="8dp">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/locInfo"
|
||||
android:layout_width="match_parent"
|
||||
<awais.instagrabber.customviews.CircularImageView
|
||||
android:id="@+id/mainLocationImage"
|
||||
android:layout_width="@dimen/profile_picture_size"
|
||||
android:layout_height="@dimen/profile_picture_size"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
app:actualImageScaleType="centerCrop"
|
||||
app:layout_constraintEnd_toStartOf="@id/mainLocPostCount"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:background="@mipmap/ic_launcher" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/mainLocPostCount"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:gravity="center_vertical"
|
||||
android:maxLines="1"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat"
|
||||
app:layout_constraintBottom_toTopOf="@id/btnMap"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/mainLocationImage"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="35 Posts" />
|
||||
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/btnMap"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/profile_info_container_bottom_space">
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:text="@string/map"
|
||||
app:chipBackgroundColor="@null"
|
||||
app:chipIcon="@drawable/ic_outline_map_24"
|
||||
app:chipIconTint="@color/green_500"
|
||||
app:layout_constraintBottom_toTopOf="@id/locationFullName"
|
||||
app:layout_constraintStart_toEndOf="@id/mainLocationImage"
|
||||
app:layout_constraintTop_toBottomOf="@id/mainLocPostCount"
|
||||
app:rippleColor="@color/grey_500"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<awais.instagrabber.customviews.CircularImageView
|
||||
android:id="@+id/mainLocationImage"
|
||||
android:layout_width="@dimen/profile_picture_size"
|
||||
android:layout_height="@dimen/profile_picture_size"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
app:actualImageScaleType="fitCenter" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/mainLocPostCount"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginRight="12dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat"
|
||||
android:textSize="15sp"
|
||||
tools:text="35\nPosts" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/btnMap"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="2"
|
||||
android:text="@string/map"
|
||||
android:textColor="@color/btn_green_text_color"
|
||||
android:textSize="20sp"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/btn_green_background" />
|
||||
</LinearLayout>
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/fav_chip"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:text="@string/add_to_favorites"
|
||||
app:chipBackgroundColor="@null"
|
||||
app:chipIcon="@drawable/ic_outline_star_plus_24"
|
||||
app:chipIconTint="@color/yellow_800"
|
||||
app:layout_constraintBottom_toBottomOf="@id/mainLocationImage"
|
||||
app:layout_constraintStart_toEndOf="@id/btnMap"
|
||||
app:layout_constraintTop_toBottomOf="@id/mainLocPostCount"
|
||||
app:rippleColor="@color/yellow_400" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/locationFullName"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/locInfo"
|
||||
android:ellipsize="marquee"
|
||||
android:paddingStart="10dp"
|
||||
android:paddingLeft="10dp"
|
||||
android:paddingEnd="10dp"
|
||||
android:paddingRight="10dp"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingRight="8dp"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body2"
|
||||
android:textSize="16sp"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toTopOf="@id/locationBiography"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/mainLocationImage"
|
||||
tools:text="OUR HOUSE" />
|
||||
|
||||
<awais.instagrabber.customviews.RamboTextView
|
||||
android:id="@+id/locationBiography"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/locationFullName"
|
||||
android:background="?android:selectableItemBackground"
|
||||
android:paddingStart="10dp"
|
||||
android:paddingLeft="10dp"
|
||||
android:paddingEnd="10dp"
|
||||
android:paddingRight="10dp"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingRight="8dp"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone"
|
||||
tools:text="IN THE MIDDLE OF OUR STREET" />
|
||||
app:layout_constraintBottom_toTopOf="@id/locationUrl"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/locationFullName"
|
||||
tools:text="IN THE MIDDLE OF OUR STREET"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<awais.instagrabber.customviews.RamboTextView
|
||||
android:id="@+id/locationUrl"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/locationBiography"
|
||||
android:ellipsize="marquee"
|
||||
android:paddingStart="10dp"
|
||||
android:paddingLeft="10dp"
|
||||
android:paddingEnd="10dp"
|
||||
android:paddingRight="10dp"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingRight="8dp"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone"
|
||||
tools:text="https://austinhuang.me/" />
|
||||
</RelativeLayout>
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/locationBiography"
|
||||
tools:text="https://austinhuang.me/"
|
||||
tools:visibility="visible" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
|
@ -79,8 +79,10 @@
|
||||
android:ellipsize="marquee"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="4dp"
|
||||
android:paddingRight="4dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
android:textStyle="bold"
|
||||
@ -102,15 +104,34 @@
|
||||
app:srcCompat="@drawable/verified"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/fav_cb"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:button="@drawable/sl_favourite_24"
|
||||
android:visibility="gone"
|
||||
app:buttonTint="@color/yellow_800"
|
||||
app:layout_constraintBaseline_toBaselineOf="@id/mainFullName"
|
||||
app:layout_constraintBottom_toTopOf="@id/mainBiography"
|
||||
app:layout_constraintStart_toEndOf="@id/isVerified" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/fav_progress"
|
||||
style="@style/Widget.MaterialComponents.ProgressIndicator.Circular.Indeterminate"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="@id/mainFullName"
|
||||
app:layout_constraintStart_toEndOf="@id/isVerified"
|
||||
app:layout_constraintTop_toTopOf="@id/mainFullName"
|
||||
tools:visibility="gone" />
|
||||
|
||||
<awais.instagrabber.customviews.RamboTextView
|
||||
android:id="@+id/mainBiography"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:background="?android:selectableItemBackground"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingRight="8dp"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
app:layout_constraintBottom_toTopOf="@id/mainUrl"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
@ -124,10 +145,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/mainBiography"
|
||||
android:ellipsize="marquee"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingRight="8dp"
|
||||
android:padding="8dp"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
@ -135,97 +153,77 @@
|
||||
app:layout_constraintTop_toBottomOf="@id/mainBiography"
|
||||
tools:text="https://austinhuang.me/"
|
||||
tools:textColor="@android:color/holo_blue_dark"
|
||||
tools:visibility="visible" />
|
||||
tools:visibility="gone" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btnFollow"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/follow"
|
||||
android:textColor="@color/btn_pink_text_color"
|
||||
android:textColor="@color/deep_purple_200"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/btn_pink_background"
|
||||
app:layout_constraintBottom_toTopOf="@id/button_barrier"
|
||||
app:layout_constraintEnd_toStartOf="@id/btnRestrict"
|
||||
app:icon="@drawable/ic_outline_person_add_24"
|
||||
app:iconGravity="top"
|
||||
app:iconTint="@color/deep_purple_200"
|
||||
app:layout_constraintBottom_toTopOf="@id/highlights_barrier"
|
||||
app:layout_constraintEnd_toStartOf="@id/btnTagged"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/mainUrl"
|
||||
app:rippleColor="@color/purple_200"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/btnRestrict"
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btnTagged"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/restrict"
|
||||
android:textColor="@color/btn_orange_text_color"
|
||||
android:text="@string/tagged"
|
||||
android:textColor="@color/deep_orange_600"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/btn_orange_background"
|
||||
app:layout_constraintBottom_toTopOf="@id/button_barrier"
|
||||
app:layout_constraintEnd_toStartOf="@id/btnBlock"
|
||||
app:icon="@drawable/ic_outline_person_pin_24"
|
||||
app:iconGravity="top"
|
||||
app:iconTint="@color/deep_orange_600"
|
||||
app:layout_constraintBottom_toTopOf="@id/highlights_barrier"
|
||||
app:layout_constraintEnd_toStartOf="@id/btnSaved"
|
||||
app:layout_constraintStart_toEndOf="@id/btnFollow"
|
||||
app:layout_constraintTop_toBottomOf="@id/mainUrl"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/btnBlock"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/block"
|
||||
android:textColor="@color/btn_red_text_color"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/btn_red_background"
|
||||
app:layout_constraintBottom_toTopOf="@id/button_barrier"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/btnRestrict"
|
||||
app:layout_constraintTop_toBottomOf="@id/mainUrl"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/button_barrier"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:barrierDirection="bottom"
|
||||
app:constraint_referenced_ids="btnFollow, btnRestrict, btnBlock" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/btnTagged"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/tagged"
|
||||
android:textColor="@color/btn_blue_text_color"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/btn_blue_background"
|
||||
app:layout_constraintBottom_toTopOf="@id/highlights_barrier"
|
||||
app:layout_constraintEnd_toStartOf="@id/btnSaved"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/button_barrier"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btnSaved"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/saved"
|
||||
android:textColor="@color/btn_orange_text_color"
|
||||
android:textColor="@color/blue_700"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/btn_orange_background"
|
||||
app:icon="@drawable/ic_outline_class_24"
|
||||
app:iconGravity="top"
|
||||
app:iconTint="@color/blue_700"
|
||||
app:layout_constraintBottom_toTopOf="@id/highlights_barrier"
|
||||
app:layout_constraintEnd_toStartOf="@id/btnLiked"
|
||||
app:layout_constraintStart_toEndOf="@id/btnTagged"
|
||||
app:layout_constraintTop_toTopOf="@id/button_barrier"
|
||||
app:layout_constraintTop_toBottomOf="@id/mainUrl"
|
||||
app:rippleColor="@color/blue_A400"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btnLiked"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/liked"
|
||||
android:textColor="@color/btn_lightpink_text_color"
|
||||
android:textColor="@color/red_600"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/btn_lightpink_background"
|
||||
app:icon="@drawable/ic_like"
|
||||
app:iconGravity="top"
|
||||
app:iconTint="@color/red_600"
|
||||
app:layout_constraintBottom_toTopOf="@id/highlights_barrier"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/btnSaved"
|
||||
app:layout_constraintTop_toTopOf="@id/button_barrier"
|
||||
app:layout_constraintTop_toBottomOf="@id/mainUrl"
|
||||
app:rippleColor="@color/red_300"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
|
13
app/src/main/res/layout/item_fav_section_header.xml
Normal file
13
app/src/main/res/layout/item_fav_section_header.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.appcompat.widget.AppCompatTextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingRight="16dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
|
||||
android:textColor="?colorAccent"
|
||||
android:textStyle="bold"
|
||||
tools:text="HEADERS" />
|
@ -18,7 +18,7 @@
|
||||
android:id="@+id/media_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
tools:background="@color/semi_transparent_black" />
|
||||
tools:background="@color/black_a50" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:layout_width="24dp"
|
||||
|
@ -22,10 +22,10 @@
|
||||
android:layout_weight="1"
|
||||
android:animateLayoutChanges="true"
|
||||
android:background="@null"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingLeft="8dp"
|
||||
android:gravity="center"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingRight="8dp"
|
||||
android:weightSum="2">
|
||||
@ -36,7 +36,6 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
|
||||
android:textColor="@color/feed_text_primary_color"
|
||||
tools:text="username" />
|
||||
|
||||
<awais.instagrabber.customviews.RamboTextView
|
||||
@ -46,7 +45,6 @@
|
||||
android:layout_below="@+id/title"
|
||||
android:gravity="center_vertical"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
|
||||
android:textColor="@color/feed_text_primary_color"
|
||||
android:textSize="15sp"
|
||||
android:visibility="visible"
|
||||
tools:text="location" />
|
||||
|
@ -7,7 +7,10 @@
|
||||
android:background="?selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:padding="8dp">
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingRight="16dp"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<com.facebook.drawee.view.SimpleDraweeView
|
||||
android:id="@+id/ivProfilePic"
|
||||
@ -26,8 +29,8 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingEnd="4dp"
|
||||
android:paddingRight="4dp"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
@ -42,10 +45,10 @@
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingRight="8dp"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingEnd="0dp"
|
||||
android:paddingRight="0dp"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body2"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
|
@ -1,12 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
android:id="@+id/favourites"
|
||||
android:enabled="true"
|
||||
android:icon="@drawable/ic_star_24"
|
||||
android:title="@string/title_favorites"
|
||||
android:visible="false"
|
||||
app:showAsAction="ifRoom" />
|
||||
<!--<item-->
|
||||
<!-- android:id="@+id/favourites"-->
|
||||
<!-- android:enabled="true"-->
|
||||
<!-- android:icon="@drawable/ic_star_24"-->
|
||||
<!-- android:title="@string/title_favorites"-->
|
||||
<!-- android:visible="false"-->
|
||||
<!-- app:showAsAction="ifRoom" />-->
|
||||
|
||||
<item
|
||||
android:id="@+id/block"
|
||||
android:icon="@drawable/ic_block_24"
|
||||
android:title="@string/block"
|
||||
android:visible="false"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/restrict"
|
||||
android:icon="@drawable/ic_highlight_off_24"
|
||||
android:title="@string/restrict"
|
||||
android:visible="false"
|
||||
app:showAsAction="never" />
|
||||
</menu>
|
@ -34,6 +34,24 @@
|
||||
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="string"
|
||||
app:nullable="false" />
|
||||
</action>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/morePreferencesFragment"
|
||||
android:name="awais.instagrabber.fragments.settings.MorePreferencesFragment"
|
||||
@ -47,6 +65,9 @@
|
||||
<action
|
||||
android:id="@+id/action_morePreferencesFragment_to_notificationsViewer"
|
||||
app:destination="@id/notificationsViewer" />
|
||||
<action
|
||||
android:id="@+id/action_morePreferencesFragment_to_favoritesFragment"
|
||||
app:destination="@id/favoritesFragment" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/settingsPreferencesFragment"
|
||||
@ -69,4 +90,8 @@
|
||||
android:id="@+id/themePreferencesFragment"
|
||||
android:name="awais.instagrabber.fragments.settings.ThemePreferencesFragment"
|
||||
android:label="@string/theme_settings" />
|
||||
<fragment
|
||||
android:id="@+id/favoritesFragment"
|
||||
android:name="awais.instagrabber.fragments.FavoritesFragment"
|
||||
android:label="@string/title_favorites" />
|
||||
</navigation>
|
@ -28,15 +28,13 @@
|
||||
<color name="btn_lightorange_background">#FFBB00</color>
|
||||
<color name="btn_lightorange_text_color">#FF000000</color>
|
||||
|
||||
<color name="feed_text_primary_color">@color/text_color_light</color>
|
||||
|
||||
<color name="dm_profile_button_color">#efefef</color>
|
||||
<color name="semi_transparent_black">#80000000</color>
|
||||
|
||||
<color name="white">#FFFFFF</color>
|
||||
|
||||
<color name="black">#000000</color>
|
||||
<color name="black_800">#121212</color>
|
||||
<color name="black_a50">#80000000</color>
|
||||
|
||||
<color name="grey_50">#FAFAFA</color>
|
||||
<color name="grey_100">#F5F5F5</color>
|
||||
@ -83,7 +81,65 @@
|
||||
<color name="purple_200">#bb86fc</color>
|
||||
<color name="purple_600">#4b01d0</color>
|
||||
|
||||
<color name="red_200">#cf6679</color>
|
||||
<color name="deep_purple_50">#EDE7F6</color>
|
||||
<color name="deep_purple_100">#D1C4E9</color>
|
||||
<color name="deep_purple_200">#B39DDB</color>
|
||||
<color name="deep_purple_300">#9575CD</color>
|
||||
<color name="deep_purple_400">#7E57C2</color>
|
||||
<color name="deep_purple_500">#673AB7</color>
|
||||
<color name="deep_purple_600">#5E35B1</color>
|
||||
<color name="deep_purple_700">#512DA8</color>
|
||||
<color name="deep_purple_800">#4527A0</color>
|
||||
<color name="deep_purple_900">#311B92</color>
|
||||
<color name="deep_purple_A100">#B388FF</color>
|
||||
<color name="deep_purple_A200">#7C4DFF</color>
|
||||
<color name="deep_purple_A400">#651FFF</color>
|
||||
<color name="deep_purple_A700">#6200EA</color>
|
||||
|
||||
<color name="red_50">#FFEBEE</color>
|
||||
<color name="red_100">#FFCDD2</color>
|
||||
<color name="red_200">#EF9A9A</color>
|
||||
<color name="red_300">#E57373</color>
|
||||
<color name="red_400">#EF5350</color>
|
||||
<color name="red_500">#F44336</color>
|
||||
<color name="red_600">#E53935</color>
|
||||
<color name="red_700">#D32F2F</color>
|
||||
<color name="red_800">#C62828</color>
|
||||
<color name="red_900">#B71C1C</color>
|
||||
<color name="red_A100">#FF8A80</color>
|
||||
<color name="red_A200">#FF5252</color>
|
||||
<color name="red_A400">#FF1744</color>
|
||||
<color name="red_A700">#D50000</color>
|
||||
|
||||
<color name="deep_orange_50">#FBE9E7</color>
|
||||
<color name="deep_orange_100">#FFCCBC</color>
|
||||
<color name="deep_orange_200">#FFAB91</color>
|
||||
<color name="deep_orange_300">#FF8A65</color>
|
||||
<color name="deep_orange_400">#FF7043</color>
|
||||
<color name="deep_orange_500">#FF5722</color>
|
||||
<color name="deep_orange_600">#F4511E</color>
|
||||
<color name="deep_orange_700">#E64A19</color>
|
||||
<color name="deep_orange_800">#D84315</color>
|
||||
<color name="deep_orange_900">#BF360C</color>
|
||||
<color name="deep_orange_A100">#FF9E80</color>
|
||||
<color name="deep_orange_A200">#FF6E40</color>
|
||||
<color name="deep_orange_A400">#FF3D00</color>
|
||||
<color name="deep_orange_A700">#DD2C00</color>
|
||||
|
||||
<color name="yellow_50">#FFFDE7</color>
|
||||
<color name="yellow_100">#FFF9C4</color>
|
||||
<color name="yellow_200">#FFF59D</color>
|
||||
<color name="yellow_300">#FFF176</color>
|
||||
<color name="yellow_400">#FFEE58</color>
|
||||
<color name="yellow_500">#FFEB3B</color>
|
||||
<color name="yellow_600">#FDD835</color>
|
||||
<color name="yellow_700">#FBC02D</color>
|
||||
<color name="yellow_800">#F9A825</color>
|
||||
<color name="yellow_900">#F57F17</color>
|
||||
<color name="yellow_A100">#FFFF8D</color>
|
||||
<color name="yellow_A200">#FFFF00</color>
|
||||
<color name="yellow_A400">#FFEA00</color>
|
||||
<color name="yellow_A700">#FFD600</color>
|
||||
|
||||
<!-- Barinsta Theme colors -->
|
||||
<color name="barinstaColorPrimary">#a86735</color>
|
||||
|
@ -58,6 +58,7 @@
|
||||
<string name="select_language">Language</string>
|
||||
<string name="what_to_do_dialog">What to do?</string>
|
||||
<string name="main_posts_count">%s\nPosts</string>
|
||||
<string name="main_posts_count_inline">%s Posts</string>
|
||||
<string name="main_posts_followers">%s\nFollowers</string>
|
||||
<string name="main_posts_following">%s\nFollowing</string>
|
||||
<string name="post_viewer_video_post">Video post</string>
|
||||
@ -146,7 +147,7 @@
|
||||
<string name="time_settings_swap_time">Swap Time and Date positions</string>
|
||||
<string name="quick_access_info_dialog">Favorites panel is for adding your favorite hashtags and/or usernames.\n\nAnd the Quick Access panel is for quickly switching between accounts.\n\nNote 1: Make sure to Login into each account [Settings > Login] to add account to the list!\n\nNote 2: Log out of the current account and then log into the other account.</string>
|
||||
<string name="quick_access_cannot_delete_curr">Cannot delete currently in use account</string>
|
||||
<string name="quick_access_confirm_delete">Are you sure you want to delete %s?</string>
|
||||
<string name="quick_access_confirm_delete">Are you sure you want to delete \'%s\'?</string>
|
||||
<string name="profile_viewer_imageinfo">Width: %d\nHeight: %d</string>
|
||||
<string name="profile_viewer_colordepth_prefix">\nColor depth:</string>
|
||||
<string name="profile_endpoint">Select profile picture endpoint\n(Does not affect hashtags)</string>
|
||||
@ -283,4 +284,11 @@
|
||||
<string name="dark_theme_settings">Dark theme</string>
|
||||
<string name="light_barinsta_theme">Barinsta</string>
|
||||
<string name="dark_material_dark_theme">Material Dark</string>
|
||||
<string name="added_to_favs">Added to Favorites</string>
|
||||
<string name="add_to_favorites">Add to favorites</string>
|
||||
<string name="accounts">Accounts</string>
|
||||
<string name="hashtags">Hashtags</string>
|
||||
<string name="locations">Locations</string>
|
||||
<string name="unknown">Unknown</string>
|
||||
<string name="removed_from_favs">Removed from Favourites</string>
|
||||
</resources>
|
@ -108,4 +108,24 @@
|
||||
<item name="android:background">?colorSurface</item>
|
||||
<item name="android:windowBackground">?attr/colorSurface</item>
|
||||
</style>
|
||||
|
||||
<style name="ThemeOverlay.MaterialComponents.MaterialAlertDialog.Light" parent="ThemeOverlay.MaterialComponents.MaterialAlertDialog">
|
||||
<!--<item name="colorPrimary">?attr/colorPrimaryDark</item>-->
|
||||
<!--<item name="colorSecondary">?attr/colorSecondaryVariant</item>-->
|
||||
<!--<item name="colorSurface">@color/shrine_pink_light</item>-->
|
||||
<!--<item name="colorOnSurface">@color/shrine_pink_900</item>-->
|
||||
<!--<item name="materialAlertDialogTitleTextStyle">@style/MaterialAlertDialog.App.Title.Text</item>-->
|
||||
<!--<item name="colorPrimary">?attr/colorPrimaryDark</item>-->
|
||||
<item name="buttonBarPositiveButtonStyle">@style/Widget.MaterialComponents.Button.TextButton.Dialog.Light</item>
|
||||
<item name="buttonBarNeutralButtonStyle">@style/Widget.MaterialComponents.Button.TextButton.Dialog.Light</item>
|
||||
<item name="buttonBarNegativeButtonStyle">@style/Widget.MaterialComponents.Button.TextButton.Dialog.Light</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.MaterialComponents.Button.TextButton.Dialog.Light" parent="Widget.MaterialComponents.Button.TextButton.Dialog">
|
||||
<item name="materialThemeOverlay">@style/ThemeOverlay.MaterialComponents.Button.TextButton.Light</item>
|
||||
</style>
|
||||
|
||||
<style name="ThemeOverlay.MaterialComponents.Button.TextButton.Light" parent="">
|
||||
<item name="colorPrimary">?attr/colorPrimaryDark</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
@ -19,6 +19,7 @@
|
||||
<item name="android:windowLightNavigationBar" tools:ignore="NewApi">false</item>
|
||||
<item name="actionBarTheme">@style/ThemeOverlay.MaterialComponents.ActionBar</item>
|
||||
<!--<item name="toolbarStyle">@style/Widget.MaterialComponents.Toolbar.Primary</item>-->
|
||||
<item name="materialAlertDialogTheme">@style/ThemeOverlay.MaterialComponents.MaterialAlertDialog.Light</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.Light.White" parent="AppTheme.Light">
|
||||
|
Loading…
Reference in New Issue
Block a user