mirror of
https://github.com/KokaKiwi/BarInsta
synced 2024-12-04 12:27:29 +00:00
Merge branch 'master' of https://github.com/austinhuang0131/instagrabber
This commit is contained in:
commit
16f0a34f55
@ -57,7 +57,7 @@ android {
|
|||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
debug {
|
debug {
|
||||||
minifyEnabled true
|
minifyEnabled false
|
||||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,13 +166,13 @@ dependencies {
|
|||||||
def nav_version = '2.3.5'
|
def nav_version = '2.3.5'
|
||||||
def exoplayer_version = '2.14.1'
|
def exoplayer_version = '2.14.1'
|
||||||
|
|
||||||
implementation 'com.google.android.material:material:1.4.0-beta01'
|
implementation 'com.google.android.material:material:1.4.0-rc01'
|
||||||
|
|
||||||
implementation "com.google.android.exoplayer:exoplayer-core:$exoplayer_version"
|
implementation "com.google.android.exoplayer:exoplayer-core:$exoplayer_version"
|
||||||
implementation "com.google.android.exoplayer:exoplayer-dash:$exoplayer_version"
|
implementation "com.google.android.exoplayer:exoplayer-dash:$exoplayer_version"
|
||||||
implementation "com.google.android.exoplayer:exoplayer-ui:$exoplayer_version"
|
implementation "com.google.android.exoplayer:exoplayer-ui:$exoplayer_version"
|
||||||
|
|
||||||
implementation "androidx.recyclerview:recyclerview:1.2.0"
|
implementation "androidx.recyclerview:recyclerview:1.2.1"
|
||||||
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
|
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
|
||||||
implementation "androidx.viewpager2:viewpager2:1.0.0"
|
implementation "androidx.viewpager2:viewpager2:1.0.0"
|
||||||
implementation "androidx.navigation:navigation-fragment:$nav_version"
|
implementation "androidx.navigation:navigation-fragment:$nav_version"
|
||||||
@ -183,11 +183,11 @@ dependencies {
|
|||||||
|
|
||||||
implementation 'com.google.guava:guava:27.0.1-android'
|
implementation 'com.google.guava:guava:27.0.1-android'
|
||||||
|
|
||||||
def core_version = "1.6.0-beta01"
|
def core_version = "1.6.0-rc01"
|
||||||
implementation "androidx.core:core:$core_version"
|
implementation "androidx.core:core:$core_version"
|
||||||
|
|
||||||
// Fragment
|
// Fragment
|
||||||
implementation "androidx.fragment:fragment-ktx:1.3.4"
|
implementation "androidx.fragment:fragment-ktx:1.3.5"
|
||||||
|
|
||||||
// Lifecycle
|
// Lifecycle
|
||||||
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
|
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
|
||||||
@ -203,10 +203,10 @@ dependencies {
|
|||||||
annotationProcessor "androidx.room:room-compiler:$room_version"
|
annotationProcessor "androidx.room:room-compiler:$room_version"
|
||||||
|
|
||||||
// CameraX
|
// CameraX
|
||||||
def camerax_version = "1.1.0-alpha04"
|
def camerax_version = "1.1.0-alpha05"
|
||||||
implementation "androidx.camera:camera-camera2:$camerax_version"
|
implementation "androidx.camera:camera-camera2:$camerax_version"
|
||||||
implementation "androidx.camera:camera-lifecycle:$camerax_version"
|
implementation "androidx.camera:camera-lifecycle:$camerax_version"
|
||||||
implementation "androidx.camera:camera-view:1.0.0-alpha24"
|
implementation "androidx.camera:camera-view:1.0.0-alpha25"
|
||||||
|
|
||||||
// EmojiCompat
|
// EmojiCompat
|
||||||
def emoji_compat_version = "1.1.0"
|
def emoji_compat_version = "1.1.0"
|
||||||
@ -238,7 +238,7 @@ dependencies {
|
|||||||
|
|
||||||
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.7'
|
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.7'
|
||||||
|
|
||||||
githubImplementation 'io.sentry:sentry-android:4.3.0'
|
githubImplementation 'io.sentry:sentry-android:5.0.1'
|
||||||
|
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter:5.7.2'
|
testImplementation 'org.junit.jupiter:junit-jupiter:5.7.2'
|
||||||
testImplementation "androidx.test.ext:junit-ktx:1.1.2"
|
testImplementation "androidx.test.ext:junit-ktx:1.1.2"
|
||||||
|
@ -82,7 +82,7 @@ public class DirectorySelectActivity extends BaseLanguageActivity {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!"com.android.externalstorage.documents".equals(data.getData().getAuthority())) {
|
if (!"com.android.externalstorage.documents".equals(data.getData().getAuthority())) {
|
||||||
showErrorDialog(getString(R.string.dir_select_no_download_folder));
|
showErrorDialog(getString(R.string.dir_select_no_download_folder, data.getData().getAuthority()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
AppExecutors.INSTANCE.getMainThread().execute(() -> {
|
AppExecutors.INSTANCE.getMainThread().execute(() -> {
|
||||||
|
@ -171,7 +171,7 @@ public final class DirectItemsAdapter extends RecyclerView.Adapter<RecyclerView.
|
|||||||
return new DirectItemVideoCallEventViewHolder(baseBinding, binding, currentUser, thread, callback);
|
return new DirectItemVideoCallEventViewHolder(baseBinding, binding, currentUser, thread, callback);
|
||||||
}
|
}
|
||||||
case PLACEHOLDER: {
|
case PLACEHOLDER: {
|
||||||
final LayoutDmTextBinding binding = LayoutDmTextBinding.inflate(layoutInflater, baseBinding.message, false);
|
final LayoutDmStoryShareBinding binding = LayoutDmStoryShareBinding.inflate(layoutInflater, baseBinding.message, false);
|
||||||
return new DirectItemPlaceholderViewHolder(baseBinding, binding, currentUser, thread, callback);
|
return new DirectItemPlaceholderViewHolder(baseBinding, binding, currentUser, thread, callback);
|
||||||
}
|
}
|
||||||
case ANIMATED_MEDIA: {
|
case ANIMATED_MEDIA: {
|
||||||
@ -401,7 +401,7 @@ public final class DirectItemsAdapter extends RecyclerView.Adapter<RecyclerView.
|
|||||||
|
|
||||||
void onEmailClick(String email);
|
void onEmailClick(String email);
|
||||||
|
|
||||||
void onMediaClick(Media media);
|
void onMediaClick(Media media, int index);
|
||||||
|
|
||||||
void onStoryClick(DirectItemStoryShare storyShare);
|
void onStoryClick(DirectItemStoryShare storyShare);
|
||||||
|
|
||||||
|
@ -9,20 +9,20 @@ import androidx.recyclerview.widget.ListAdapter;
|
|||||||
|
|
||||||
import awais.instagrabber.adapters.viewholder.FeedStoryViewHolder;
|
import awais.instagrabber.adapters.viewholder.FeedStoryViewHolder;
|
||||||
import awais.instagrabber.databinding.ItemHighlightBinding;
|
import awais.instagrabber.databinding.ItemHighlightBinding;
|
||||||
import awais.instagrabber.models.FeedStoryModel;
|
import awais.instagrabber.repositories.responses.stories.Story;
|
||||||
|
|
||||||
public final class FeedStoriesAdapter extends ListAdapter<FeedStoryModel, FeedStoryViewHolder> {
|
public final class FeedStoriesAdapter extends ListAdapter<Story, FeedStoryViewHolder> {
|
||||||
private final OnFeedStoryClickListener listener;
|
private final OnFeedStoryClickListener listener;
|
||||||
|
|
||||||
private static final DiffUtil.ItemCallback<FeedStoryModel> diffCallback = new DiffUtil.ItemCallback<FeedStoryModel>() {
|
private static final DiffUtil.ItemCallback<Story> diffCallback = new DiffUtil.ItemCallback<Story>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean areItemsTheSame(@NonNull final FeedStoryModel oldItem, @NonNull final FeedStoryModel newItem) {
|
public boolean areItemsTheSame(@NonNull final Story oldItem, @NonNull final Story newItem) {
|
||||||
return oldItem.getStoryMediaId().equals(newItem.getStoryMediaId());
|
return oldItem.getId().equals(newItem.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean areContentsTheSame(@NonNull final FeedStoryModel oldItem, @NonNull final FeedStoryModel newItem) {
|
public boolean areContentsTheSame(@NonNull final Story oldItem, @NonNull final Story newItem) {
|
||||||
return oldItem.getStoryMediaId().equals(newItem.getStoryMediaId()) && oldItem.isFullyRead() == newItem.isFullyRead();
|
return oldItem.getId().equals(newItem.getId()) && oldItem.getSeen() == newItem.getSeen();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -41,13 +41,13 @@ public final class FeedStoriesAdapter extends ListAdapter<FeedStoryModel, FeedSt
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull final FeedStoryViewHolder holder, final int position) {
|
public void onBindViewHolder(@NonNull final FeedStoryViewHolder holder, final int position) {
|
||||||
final FeedStoryModel model = getItem(position);
|
final Story model = getItem(position);
|
||||||
holder.bind(model, position, listener);
|
holder.bind(model, position, listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface OnFeedStoryClickListener {
|
public interface OnFeedStoryClickListener {
|
||||||
void onFeedStoryClick(FeedStoryModel model, int position);
|
void onFeedStoryClick(Story model, int position);
|
||||||
|
|
||||||
void onFeedStoryLongClick(FeedStoryModel model, int position);
|
void onFeedStoryLongClick(Story model, int position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,22 +15,22 @@ import java.util.stream.Collectors;
|
|||||||
|
|
||||||
import awais.instagrabber.adapters.viewholder.StoryListViewHolder;
|
import awais.instagrabber.adapters.viewholder.StoryListViewHolder;
|
||||||
import awais.instagrabber.databinding.ItemNotificationBinding;
|
import awais.instagrabber.databinding.ItemNotificationBinding;
|
||||||
import awais.instagrabber.models.FeedStoryModel;
|
import awais.instagrabber.repositories.responses.stories.Story;
|
||||||
import awais.instagrabber.utils.TextUtils;
|
import awais.instagrabber.utils.TextUtils;
|
||||||
|
|
||||||
public final class FeedStoriesListAdapter extends ListAdapter<FeedStoryModel, StoryListViewHolder> implements Filterable {
|
public final class FeedStoriesListAdapter extends ListAdapter<Story, StoryListViewHolder> implements Filterable {
|
||||||
private final OnFeedStoryClickListener listener;
|
private final OnFeedStoryClickListener listener;
|
||||||
private List<FeedStoryModel> list;
|
private List<Story> list;
|
||||||
|
|
||||||
private final Filter filter = new Filter() {
|
private final Filter filter = new Filter() {
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
protected FilterResults performFiltering(final CharSequence filter) {
|
protected FilterResults performFiltering(final CharSequence filter) {
|
||||||
final String query = TextUtils.isEmpty(filter) ? null : filter.toString().toLowerCase();
|
final String query = TextUtils.isEmpty(filter) ? null : filter.toString().toLowerCase();
|
||||||
List<FeedStoryModel> filteredList = list;
|
List<Story> filteredList = list;
|
||||||
if (list != null && query != null) {
|
if (list != null && query != null) {
|
||||||
filteredList = list.stream()
|
filteredList = list.stream()
|
||||||
.filter(feedStoryModel -> feedStoryModel.getProfileModel()
|
.filter(feedStoryModel -> feedStoryModel.getUser()
|
||||||
.getUsername()
|
.getUsername()
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.contains(query))
|
.contains(query))
|
||||||
@ -45,19 +45,19 @@ public final class FeedStoriesListAdapter extends ListAdapter<FeedStoryModel, St
|
|||||||
@Override
|
@Override
|
||||||
protected void publishResults(final CharSequence constraint, final FilterResults results) {
|
protected void publishResults(final CharSequence constraint, final FilterResults results) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
submitList((List<FeedStoryModel>) results.values, true);
|
submitList((List<Story>) results.values, true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final DiffUtil.ItemCallback<FeedStoryModel> diffCallback = new DiffUtil.ItemCallback<FeedStoryModel>() {
|
private static final DiffUtil.ItemCallback<Story> diffCallback = new DiffUtil.ItemCallback<Story>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean areItemsTheSame(@NonNull final FeedStoryModel oldItem, @NonNull final FeedStoryModel newItem) {
|
public boolean areItemsTheSame(@NonNull final Story oldItem, @NonNull final Story newItem) {
|
||||||
return oldItem.getStoryMediaId().equals(newItem.getStoryMediaId());
|
return oldItem.getId().equals(newItem.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean areContentsTheSame(@NonNull final FeedStoryModel oldItem, @NonNull final FeedStoryModel newItem) {
|
public boolean areContentsTheSame(@NonNull final Story oldItem, @NonNull final Story newItem) {
|
||||||
return oldItem.getStoryMediaId().equals(newItem.getStoryMediaId()) && oldItem.isFullyRead() == newItem.isFullyRead();
|
return oldItem.getId().equals(newItem.getId()) && oldItem.getSeen() == newItem.getSeen();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ public final class FeedStoriesListAdapter extends ListAdapter<FeedStoryModel, St
|
|||||||
return filter;
|
return filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void submitList(@Nullable final List<FeedStoryModel> list, final boolean isFiltered) {
|
private void submitList(@Nullable final List<Story> list, final boolean isFiltered) {
|
||||||
if (!isFiltered) {
|
if (!isFiltered) {
|
||||||
this.list = list;
|
this.list = list;
|
||||||
}
|
}
|
||||||
@ -79,7 +79,7 @@ public final class FeedStoriesListAdapter extends ListAdapter<FeedStoryModel, St
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void submitList(final List<FeedStoryModel> list) {
|
public void submitList(final List<Story> list) {
|
||||||
submitList(list, false);
|
submitList(list, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,12 +93,12 @@ public final class FeedStoriesListAdapter extends ListAdapter<FeedStoryModel, St
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull final StoryListViewHolder holder, final int position) {
|
public void onBindViewHolder(@NonNull final StoryListViewHolder holder, final int position) {
|
||||||
final FeedStoryModel model = getItem(position);
|
final Story model = getItem(position);
|
||||||
holder.bind(model, listener);
|
holder.bind(model, listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface OnFeedStoryClickListener {
|
public interface OnFeedStoryClickListener {
|
||||||
void onFeedStoryClick(final FeedStoryModel model);
|
void onFeedStoryClick(final Story model);
|
||||||
|
|
||||||
void onProfileClick(final String username);
|
void onProfileClick(final String username);
|
||||||
}
|
}
|
||||||
|
@ -9,19 +9,19 @@ import androidx.recyclerview.widget.ListAdapter;
|
|||||||
|
|
||||||
import awais.instagrabber.adapters.viewholder.StoryListViewHolder;
|
import awais.instagrabber.adapters.viewholder.StoryListViewHolder;
|
||||||
import awais.instagrabber.databinding.ItemNotificationBinding;
|
import awais.instagrabber.databinding.ItemNotificationBinding;
|
||||||
import awais.instagrabber.models.HighlightModel;
|
import awais.instagrabber.repositories.responses.stories.Story;
|
||||||
|
|
||||||
public final class HighlightStoriesListAdapter extends ListAdapter<HighlightModel, StoryListViewHolder> {
|
public final class HighlightStoriesListAdapter extends ListAdapter<Story, StoryListViewHolder> {
|
||||||
private final OnHighlightStoryClickListener listener;
|
private final OnHighlightStoryClickListener listener;
|
||||||
|
|
||||||
private static final DiffUtil.ItemCallback<HighlightModel> diffCallback = new DiffUtil.ItemCallback<HighlightModel>() {
|
private static final DiffUtil.ItemCallback<Story> diffCallback = new DiffUtil.ItemCallback<Story>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean areItemsTheSame(@NonNull final HighlightModel oldItem, @NonNull final HighlightModel newItem) {
|
public boolean areItemsTheSame(@NonNull final Story oldItem, @NonNull final Story newItem) {
|
||||||
return oldItem.getId().equals(newItem.getId());
|
return oldItem.getId().equals(newItem.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean areContentsTheSame(@NonNull final HighlightModel oldItem, @NonNull final HighlightModel newItem) {
|
public boolean areContentsTheSame(@NonNull final Story oldItem, @NonNull final Story newItem) {
|
||||||
return oldItem.getId().equals(newItem.getId());
|
return oldItem.getId().equals(newItem.getId());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -41,12 +41,12 @@ public final class HighlightStoriesListAdapter extends ListAdapter<HighlightMode
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull final StoryListViewHolder holder, final int position) {
|
public void onBindViewHolder(@NonNull final StoryListViewHolder holder, final int position) {
|
||||||
final HighlightModel model = getItem(position);
|
final Story model = getItem(position);
|
||||||
holder.bind(model, position, listener);
|
holder.bind(model, position, listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface OnHighlightStoryClickListener {
|
public interface OnHighlightStoryClickListener {
|
||||||
void onHighlightClick(final HighlightModel model, final int position);
|
void onHighlightClick(final Story model, final int position);
|
||||||
|
|
||||||
void onProfileClick(final String username);
|
void onProfileClick(final String username);
|
||||||
}
|
}
|
||||||
|
@ -9,20 +9,20 @@ import androidx.recyclerview.widget.ListAdapter;
|
|||||||
|
|
||||||
import awais.instagrabber.adapters.viewholder.HighlightViewHolder;
|
import awais.instagrabber.adapters.viewholder.HighlightViewHolder;
|
||||||
import awais.instagrabber.databinding.ItemHighlightBinding;
|
import awais.instagrabber.databinding.ItemHighlightBinding;
|
||||||
import awais.instagrabber.models.HighlightModel;
|
import awais.instagrabber.repositories.responses.stories.Story;
|
||||||
|
|
||||||
public final class HighlightsAdapter extends ListAdapter<HighlightModel, HighlightViewHolder> {
|
public final class HighlightsAdapter extends ListAdapter<Story, HighlightViewHolder> {
|
||||||
|
|
||||||
private final OnHighlightClickListener clickListener;
|
private final OnHighlightClickListener clickListener;
|
||||||
|
|
||||||
private static final DiffUtil.ItemCallback<HighlightModel> diffCallback = new DiffUtil.ItemCallback<HighlightModel>() {
|
private static final DiffUtil.ItemCallback<Story> diffCallback = new DiffUtil.ItemCallback<Story>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean areItemsTheSame(@NonNull final HighlightModel oldItem, @NonNull final HighlightModel newItem) {
|
public boolean areItemsTheSame(@NonNull final Story oldItem, @NonNull final Story newItem) {
|
||||||
return oldItem.getId().equals(newItem.getId());
|
return oldItem.getId().equals(newItem.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean areContentsTheSame(@NonNull final HighlightModel oldItem, @NonNull final HighlightModel newItem) {
|
public boolean areContentsTheSame(@NonNull final Story oldItem, @NonNull final Story newItem) {
|
||||||
return oldItem.getId().equals(newItem.getId());
|
return oldItem.getId().equals(newItem.getId());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -42,7 +42,7 @@ public final class HighlightsAdapter extends ListAdapter<HighlightModel, Highlig
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull final HighlightViewHolder holder, final int position) {
|
public void onBindViewHolder(@NonNull final HighlightViewHolder holder, final int position) {
|
||||||
final HighlightModel highlightModel = getItem(position);
|
final Story highlightModel = getItem(position);
|
||||||
if (clickListener != null) {
|
if (clickListener != null) {
|
||||||
holder.itemView.setOnClickListener(v -> clickListener.onHighlightClick(highlightModel, position));
|
holder.itemView.setOnClickListener(v -> clickListener.onHighlightClick(highlightModel, position));
|
||||||
}
|
}
|
||||||
@ -50,6 +50,6 @@ public final class HighlightsAdapter extends ListAdapter<HighlightModel, Highlig
|
|||||||
}
|
}
|
||||||
|
|
||||||
public interface OnHighlightClickListener {
|
public interface OnHighlightClickListener {
|
||||||
void onHighlightClick(final HighlightModel model, final int position);
|
void onHighlightClick(final Story model, final int position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,111 +0,0 @@
|
|||||||
package awais.instagrabber.adapters;
|
|
||||||
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.recyclerview.widget.DiffUtil;
|
|
||||||
import androidx.recyclerview.widget.ListAdapter;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
|
|
||||||
import com.facebook.drawee.backends.pipeline.Fresco;
|
|
||||||
import com.facebook.drawee.backends.pipeline.PipelineDraweeControllerBuilder;
|
|
||||||
import com.facebook.drawee.controller.BaseControllerListener;
|
|
||||||
import com.facebook.imagepipeline.common.ResizeOptions;
|
|
||||||
import com.facebook.imagepipeline.image.ImageInfo;
|
|
||||||
import com.facebook.imagepipeline.request.ImageRequest;
|
|
||||||
import com.facebook.imagepipeline.request.ImageRequestBuilder;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
import awais.instagrabber.databinding.ItemMediaBinding;
|
|
||||||
import awais.instagrabber.utils.MediaController.MediaEntry;
|
|
||||||
import awais.instagrabber.utils.TextUtils;
|
|
||||||
import awais.instagrabber.utils.Utils;
|
|
||||||
|
|
||||||
public class MediaItemsAdapter extends ListAdapter<MediaEntry, MediaItemsAdapter.MediaItemViewHolder> {
|
|
||||||
|
|
||||||
private static final DiffUtil.ItemCallback<MediaEntry> diffCallback = new DiffUtil.ItemCallback<MediaEntry>() {
|
|
||||||
@Override
|
|
||||||
public boolean areItemsTheSame(@NonNull final MediaEntry oldItem, @NonNull final MediaEntry newItem) {
|
|
||||||
return oldItem.imageId == newItem.imageId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean areContentsTheSame(@NonNull final MediaEntry oldItem, @NonNull final MediaEntry newItem) {
|
|
||||||
return oldItem.imageId == newItem.imageId;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private final OnItemClickListener onItemClickListener;
|
|
||||||
|
|
||||||
public MediaItemsAdapter(final OnItemClickListener onItemClickListener) {
|
|
||||||
super(diffCallback);
|
|
||||||
this.onItemClickListener = onItemClickListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public MediaItemViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) {
|
|
||||||
final LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
|
|
||||||
final ItemMediaBinding binding = ItemMediaBinding.inflate(layoutInflater, parent, false);
|
|
||||||
return new MediaItemViewHolder(binding, onItemClickListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBindViewHolder(@NonNull final MediaItemViewHolder holder, final int position) {
|
|
||||||
holder.bind(getItem(position));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class MediaItemViewHolder extends RecyclerView.ViewHolder {
|
|
||||||
private static final String TAG = MediaItemViewHolder.class.getSimpleName();
|
|
||||||
private static final int size = Utils.displayMetrics.widthPixels / 3;
|
|
||||||
|
|
||||||
private final ItemMediaBinding binding;
|
|
||||||
private final OnItemClickListener onItemClickListener;
|
|
||||||
|
|
||||||
public MediaItemViewHolder(@NonNull final ItemMediaBinding binding,
|
|
||||||
final OnItemClickListener onItemClickListener) {
|
|
||||||
super(binding.getRoot());
|
|
||||||
this.binding = binding;
|
|
||||||
this.onItemClickListener = onItemClickListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void bind(final MediaEntry item) {
|
|
||||||
final Uri uri = Uri.fromFile(new File(item.path));
|
|
||||||
if (onItemClickListener != null) {
|
|
||||||
itemView.setOnClickListener(v -> onItemClickListener.onItemClick(item));
|
|
||||||
}
|
|
||||||
final BaseControllerListener<ImageInfo> controllerListener = new BaseControllerListener<ImageInfo>() {
|
|
||||||
@Override
|
|
||||||
public void onFailure(final String id, final Throwable throwable) {
|
|
||||||
Log.e(TAG, "onFailure: ", throwable);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
final ImageRequest request = ImageRequestBuilder
|
|
||||||
.newBuilderWithSource(uri)
|
|
||||||
.setLocalThumbnailPreviewsEnabled(true)
|
|
||||||
.setProgressiveRenderingEnabled(false)
|
|
||||||
.setResizeOptions(ResizeOptions.forDimensions(size, size))
|
|
||||||
.build();
|
|
||||||
final PipelineDraweeControllerBuilder builder = Fresco.newDraweeControllerBuilder()
|
|
||||||
.setImageRequest(request)
|
|
||||||
.setControllerListener(controllerListener);
|
|
||||||
binding.item.setController(builder.build());
|
|
||||||
if (item.isVideo && item.duration >= 0) {
|
|
||||||
final String timeString = TextUtils.millisToTimeString(item.duration);
|
|
||||||
binding.duration.setVisibility(View.VISIBLE);
|
|
||||||
binding.duration.setText(timeString);
|
|
||||||
} else {
|
|
||||||
binding.duration.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface OnItemClickListener {
|
|
||||||
void onItemClick(MediaEntry entry);
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,8 +4,8 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||||||
|
|
||||||
import awais.instagrabber.adapters.FeedStoriesAdapter;
|
import awais.instagrabber.adapters.FeedStoriesAdapter;
|
||||||
import awais.instagrabber.databinding.ItemHighlightBinding;
|
import awais.instagrabber.databinding.ItemHighlightBinding;
|
||||||
import awais.instagrabber.models.FeedStoryModel;
|
|
||||||
import awais.instagrabber.repositories.responses.User;
|
import awais.instagrabber.repositories.responses.User;
|
||||||
|
import awais.instagrabber.repositories.responses.stories.Story;
|
||||||
|
|
||||||
public final class FeedStoryViewHolder extends RecyclerView.ViewHolder {
|
public final class FeedStoryViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ public final class FeedStoryViewHolder extends RecyclerView.ViewHolder {
|
|||||||
this.binding = binding;
|
this.binding = binding;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void bind(final FeedStoryModel model,
|
public void bind(final Story model,
|
||||||
final int position,
|
final int position,
|
||||||
final FeedStoriesAdapter.OnFeedStoryClickListener listener) {
|
final FeedStoriesAdapter.OnFeedStoryClickListener listener) {
|
||||||
if (model == null) return;
|
if (model == null) return;
|
||||||
@ -28,14 +28,17 @@ public final class FeedStoryViewHolder extends RecyclerView.ViewHolder {
|
|||||||
if (listener != null) listener.onFeedStoryLongClick(model, position);
|
if (listener != null) listener.onFeedStoryLongClick(model, position);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
final User profileModel = model.getProfileModel();
|
final User profileModel = model.getUser();
|
||||||
binding.title.setText(profileModel.getUsername());
|
binding.title.setText(profileModel.getUsername());
|
||||||
binding.title.setAlpha(model.isFullyRead() ? 0.5F : 1.0F);
|
final boolean isFullyRead =
|
||||||
|
model.getSeen() != null &&
|
||||||
|
model.getSeen().equals(model.getLatestReelMedia());
|
||||||
|
binding.title.setAlpha(isFullyRead ? 0.5F : 1.0F);
|
||||||
binding.icon.setImageURI(profileModel.getProfilePicUrl());
|
binding.icon.setImageURI(profileModel.getProfilePicUrl());
|
||||||
binding.icon.setAlpha(model.isFullyRead() ? 0.5F : 1.0F);
|
binding.icon.setAlpha(isFullyRead ? 0.5F : 1.0F);
|
||||||
|
|
||||||
if (model.isLive()) binding.icon.setStoriesBorder(2);
|
if (model.getBroadcast() != null) binding.icon.setStoriesBorder(2);
|
||||||
else if (model.isBestie()) binding.icon.setStoriesBorder(1);
|
else if (model.getHasBestiesMedia()) binding.icon.setStoriesBorder(1);
|
||||||
else binding.icon.setStoriesBorder(0);
|
else binding.icon.setStoriesBorder(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,7 +3,7 @@ package awais.instagrabber.adapters.viewholder;
|
|||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import awais.instagrabber.databinding.ItemHighlightBinding;
|
import awais.instagrabber.databinding.ItemHighlightBinding;
|
||||||
import awais.instagrabber.models.HighlightModel;
|
import awais.instagrabber.repositories.responses.stories.Story;
|
||||||
|
|
||||||
public final class HighlightViewHolder extends RecyclerView.ViewHolder {
|
public final class HighlightViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
@ -14,10 +14,10 @@ public final class HighlightViewHolder extends RecyclerView.ViewHolder {
|
|||||||
this.binding = binding;
|
this.binding = binding;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void bind(final HighlightModel model) {
|
public void bind(final Story model) {
|
||||||
if (model == null) return;
|
if (model == null) return;
|
||||||
binding.title.setText(model.getTitle());
|
binding.title.setText(model.getTitle());
|
||||||
binding.icon.setImageURI(model.getThumbnailUrl());
|
binding.icon.setImageURI(model.getCoverMedia().getCroppedImageVersion().getUrl());
|
||||||
// binding.getRoot().setOnClickListener(v -> {
|
// binding.getRoot().setOnClickListener(v -> {
|
||||||
// if (listener == null) return;
|
// if (listener == null) return;
|
||||||
// listener.onFeedStoryClick(model, position);
|
// listener.onFeedStoryClick(model, position);
|
||||||
|
@ -8,8 +8,8 @@ import awais.instagrabber.R;
|
|||||||
import awais.instagrabber.adapters.FeedStoriesListAdapter.OnFeedStoryClickListener;
|
import awais.instagrabber.adapters.FeedStoriesListAdapter.OnFeedStoryClickListener;
|
||||||
import awais.instagrabber.adapters.HighlightStoriesListAdapter.OnHighlightStoryClickListener;
|
import awais.instagrabber.adapters.HighlightStoriesListAdapter.OnHighlightStoryClickListener;
|
||||||
import awais.instagrabber.databinding.ItemNotificationBinding;
|
import awais.instagrabber.databinding.ItemNotificationBinding;
|
||||||
import awais.instagrabber.models.FeedStoryModel;
|
import awais.instagrabber.repositories.responses.stories.Story;
|
||||||
import awais.instagrabber.models.HighlightModel;
|
import awais.instagrabber.utils.ResponseBodyUtils;
|
||||||
|
|
||||||
public final class StoryListViewHolder extends RecyclerView.ViewHolder {
|
public final class StoryListViewHolder extends RecyclerView.ViewHolder {
|
||||||
private final ItemNotificationBinding binding;
|
private final ItemNotificationBinding binding;
|
||||||
@ -19,7 +19,7 @@ public final class StoryListViewHolder extends RecyclerView.ViewHolder {
|
|||||||
this.binding = binding;
|
this.binding = binding;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void bind(final FeedStoryModel model,
|
public void bind(final Story model,
|
||||||
final OnFeedStoryClickListener notificationClickListener) {
|
final OnFeedStoryClickListener notificationClickListener) {
|
||||||
if (model == null) return;
|
if (model == null) return;
|
||||||
|
|
||||||
@ -31,19 +31,20 @@ public final class StoryListViewHolder extends RecyclerView.ViewHolder {
|
|||||||
|
|
||||||
binding.tvDate.setText(model.getDateTime());
|
binding.tvDate.setText(model.getDateTime());
|
||||||
|
|
||||||
binding.tvUsername.setText(model.getProfileModel().getUsername());
|
binding.tvUsername.setText(model.getUser().getUsername());
|
||||||
binding.ivProfilePic.setImageURI(model.getProfileModel().getProfilePicUrl());
|
binding.ivProfilePic.setImageURI(model.getUser().getProfilePicUrl());
|
||||||
binding.ivProfilePic.setOnClickListener(v -> {
|
binding.ivProfilePic.setOnClickListener(v -> {
|
||||||
if (notificationClickListener == null) return;
|
if (notificationClickListener == null) return;
|
||||||
notificationClickListener.onProfileClick(model.getProfileModel().getUsername());
|
notificationClickListener.onProfileClick(model.getUser().getUsername());
|
||||||
});
|
});
|
||||||
|
|
||||||
if (model.getFirstStoryModel() != null) {
|
if (model.getItems() != null && model.getItems().size() > 0) {
|
||||||
binding.ivPreviewPic.setVisibility(View.VISIBLE);
|
binding.ivPreviewPic.setVisibility(View.VISIBLE);
|
||||||
binding.ivPreviewPic.setImageURI(model.getFirstStoryModel().getThumbnail());
|
binding.ivPreviewPic.setImageURI(ResponseBodyUtils.getThumbUrl(model.getItems().get(0)));
|
||||||
} else binding.ivPreviewPic.setVisibility(View.INVISIBLE);
|
} else binding.ivPreviewPic.setVisibility(View.INVISIBLE);
|
||||||
|
|
||||||
float alpha = model.isFullyRead() ? 0.5F : 1.0F;
|
float alpha = model.getSeen() != null && model.getSeen().equals(model.getLatestReelMedia())
|
||||||
|
? 0.5F : 1.0F;
|
||||||
binding.ivProfilePic.setAlpha(alpha);
|
binding.ivProfilePic.setAlpha(alpha);
|
||||||
binding.ivPreviewPic.setAlpha(alpha);
|
binding.ivPreviewPic.setAlpha(alpha);
|
||||||
binding.tvUsername.setAlpha(alpha);
|
binding.tvUsername.setAlpha(alpha);
|
||||||
@ -56,7 +57,7 @@ public final class StoryListViewHolder extends RecyclerView.ViewHolder {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void bind(final HighlightModel model,
|
public void bind(final Story model,
|
||||||
final int position,
|
final int position,
|
||||||
final OnHighlightStoryClickListener notificationClickListener) {
|
final OnHighlightStoryClickListener notificationClickListener) {
|
||||||
if (model == null) return;
|
if (model == null) return;
|
||||||
@ -72,7 +73,7 @@ public final class StoryListViewHolder extends RecyclerView.ViewHolder {
|
|||||||
binding.ivProfilePic.setVisibility(View.GONE);
|
binding.ivProfilePic.setVisibility(View.GONE);
|
||||||
|
|
||||||
binding.ivPreviewPic.setVisibility(View.VISIBLE);
|
binding.ivPreviewPic.setVisibility(View.VISIBLE);
|
||||||
binding.ivPreviewPic.setImageURI(model.getThumbnailUrl());
|
binding.ivPreviewPic.setImageURI(model.getCoverImageVersion().getUrl());
|
||||||
|
|
||||||
itemView.setOnClickListener(v -> {
|
itemView.setOnClickListener(v -> {
|
||||||
if (notificationClickListener == null) return;
|
if (notificationClickListener == null) return;
|
||||||
|
@ -65,19 +65,29 @@ public class DirectItemMediaShareViewHolder extends DirectItemViewHolder {
|
|||||||
if (media == null) return;
|
if (media == null) return;
|
||||||
itemView.post(() -> {
|
itemView.post(() -> {
|
||||||
setupUser(media);
|
setupUser(media);
|
||||||
setupTitle(media);
|
|
||||||
setupCaption(media);
|
setupCaption(media);
|
||||||
});
|
});
|
||||||
itemView.post(() -> {
|
final int index;
|
||||||
|
final Media toDisplay;
|
||||||
final MediaItemType mediaType = media.getMediaType();
|
final MediaItemType mediaType = media.getMediaType();
|
||||||
setupTypeIndicator(mediaType);
|
switch (mediaType) {
|
||||||
if (mediaType == MediaItemType.MEDIA_TYPE_SLIDER) {
|
case MEDIA_TYPE_SLIDER:
|
||||||
setupPreview(media.getCarouselMedia().get(0), messageDirection);
|
toDisplay = media.getCarouselMedia().stream()
|
||||||
return;
|
.filter(m -> media.getCarouselShareChildMediaId() != null &&
|
||||||
|
media.getCarouselShareChildMediaId().equals(m.getId()))
|
||||||
|
.findAny()
|
||||||
|
.orElse(media.getCarouselMedia().get(0));
|
||||||
|
index = media.getCarouselMedia().indexOf(toDisplay);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
toDisplay = media;
|
||||||
|
index = 0;
|
||||||
}
|
}
|
||||||
setupPreview(media, messageDirection);
|
itemView.post(() -> {
|
||||||
|
setupTypeIndicator(mediaType);
|
||||||
|
setupPreview(toDisplay, messageDirection);
|
||||||
});
|
});
|
||||||
itemView.setOnClickListener(v -> openMedia(media));
|
itemView.setOnClickListener(v -> openMedia(media, index));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupTypeIndicator(final MediaItemType mediaType) {
|
private void setupTypeIndicator(final MediaItemType mediaType) {
|
||||||
@ -129,16 +139,6 @@ public class DirectItemMediaShareViewHolder extends DirectItemViewHolder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupTitle(@NonNull final Media media) {
|
|
||||||
final String title = media.getTitle();
|
|
||||||
if (!TextUtils.isEmpty(title)) {
|
|
||||||
binding.title.setVisibility(View.VISIBLE);
|
|
||||||
binding.title.setText(title);
|
|
||||||
} else {
|
|
||||||
binding.title.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupUser(@NonNull final Media media) {
|
private void setupUser(@NonNull final Media media) {
|
||||||
final User user = media.getUser();
|
final User user = media.getUser();
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
|
@ -47,7 +47,7 @@ public class DirectItemMediaViewHolder extends DirectItemViewHolder {
|
|||||||
.setActualImageScaleType(ScalingUtils.ScaleType.CENTER_CROP)
|
.setActualImageScaleType(ScalingUtils.ScaleType.CENTER_CROP)
|
||||||
.build());
|
.build());
|
||||||
final Media media = directItemModel.getMedia();
|
final Media media = directItemModel.getMedia();
|
||||||
itemView.setOnClickListener(v -> openMedia(media));
|
itemView.setOnClickListener(v -> openMedia(media, -1));
|
||||||
final MediaItemType modelMediaType = media.getMediaType();
|
final MediaItemType modelMediaType = media.getMediaType();
|
||||||
binding.typeIcon.setVisibility(modelMediaType == MediaItemType.MEDIA_TYPE_VIDEO || modelMediaType == MediaItemType.MEDIA_TYPE_SLIDER
|
binding.typeIcon.setVisibility(modelMediaType == MediaItemType.MEDIA_TYPE_VIDEO || modelMediaType == MediaItemType.MEDIA_TYPE_SLIDER
|
||||||
? View.VISIBLE
|
? View.VISIBLE
|
||||||
|
@ -1,21 +1,23 @@
|
|||||||
package awais.instagrabber.adapters.viewholder.directmessages;
|
package awais.instagrabber.adapters.viewholder.directmessages;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper;
|
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||||
|
|
||||||
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
|
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
|
||||||
import awais.instagrabber.databinding.LayoutDmBaseBinding;
|
import awais.instagrabber.databinding.LayoutDmBaseBinding;
|
||||||
import awais.instagrabber.databinding.LayoutDmTextBinding;
|
import awais.instagrabber.databinding.LayoutDmStoryShareBinding;
|
||||||
import awais.instagrabber.repositories.responses.User;
|
import awais.instagrabber.repositories.responses.User;
|
||||||
import awais.instagrabber.repositories.responses.directmessages.DirectItem;
|
import awais.instagrabber.repositories.responses.directmessages.DirectItem;
|
||||||
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
|
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
|
||||||
|
|
||||||
public class DirectItemPlaceholderViewHolder extends DirectItemViewHolder {
|
public class DirectItemPlaceholderViewHolder extends DirectItemViewHolder {
|
||||||
|
|
||||||
private final LayoutDmTextBinding binding;
|
private final LayoutDmStoryShareBinding binding;
|
||||||
|
|
||||||
public DirectItemPlaceholderViewHolder(@NonNull final LayoutDmBaseBinding baseBinding,
|
public DirectItemPlaceholderViewHolder(@NonNull final LayoutDmBaseBinding baseBinding,
|
||||||
final LayoutDmTextBinding binding,
|
final LayoutDmStoryShareBinding binding,
|
||||||
final User currentUser,
|
final User currentUser,
|
||||||
final DirectThread thread,
|
final DirectThread thread,
|
||||||
final DirectItemCallback callback) {
|
final DirectItemCallback callback) {
|
||||||
@ -26,13 +28,11 @@ public class DirectItemPlaceholderViewHolder extends DirectItemViewHolder {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void bindItem(final DirectItem directItemModel, final MessageDirection messageDirection) {
|
public void bindItem(final DirectItem directItemModel, final MessageDirection messageDirection) {
|
||||||
final String text = String.format("%s: %s", directItemModel.getPlaceholder().getTitle(), directItemModel.getPlaceholder().getMessage());
|
binding.shareInfo.setText(directItemModel.getPlaceholder().getTitle());
|
||||||
binding.tvMessage.setText(text);
|
binding.text.setVisibility(View.VISIBLE);
|
||||||
}
|
binding.text.setText(directItemModel.getPlaceholder().getMessage());
|
||||||
|
binding.ivMediaPreview.setVisibility(View.GONE);
|
||||||
@Override
|
binding.typeIcon.setVisibility(View.GONE);
|
||||||
protected boolean showBackground() {
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -50,7 +50,7 @@ public class DirectItemRavenMediaViewHolder extends DirectItemViewHolder {
|
|||||||
setPreview(visualMedia, messageDirection);
|
setPreview(visualMedia, messageDirection);
|
||||||
final boolean expired = TextUtils.isEmpty(media.getId());
|
final boolean expired = TextUtils.isEmpty(media.getId());
|
||||||
if (expired) return;
|
if (expired) return;
|
||||||
itemView.setOnClickListener(v -> openMedia(media));
|
itemView.setOnClickListener(v -> openMedia(media, -1));
|
||||||
/*final boolean isExpired = visualMedia == null || (mediaModel = visualMedia.getMedia()) == null ||
|
/*final boolean isExpired = visualMedia == null || (mediaModel = visualMedia.getMedia()) == null ||
|
||||||
TextUtils.isEmpty(mediaModel.getThumbUrl()) && mediaModel.getPk() < 1;
|
TextUtils.isEmpty(mediaModel.getThumbUrl()) && mediaModel.getPk() < 1;
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ public class DirectItemReelShareViewHolder extends DirectItemViewHolder {
|
|||||||
}
|
}
|
||||||
if (!expired) {
|
if (!expired) {
|
||||||
setPreview(media);
|
setPreview(media);
|
||||||
itemView.setOnClickListener(v -> openMedia(media));
|
itemView.setOnClickListener(v -> openMedia(media, -1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -501,8 +501,8 @@ public abstract class DirectItemViewHolder extends RecyclerView.ViewHolder imple
|
|||||||
callback.onURLClick(url);
|
callback.onURLClick(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void openMedia(final Media media) {
|
protected void openMedia(final Media media, final int index) {
|
||||||
callback.onMediaClick(media);
|
callback.onMediaClick(media, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void openStory(final DirectItemStoryShare storyShare) {
|
protected void openStory(final DirectItemStoryShare storyShare) {
|
||||||
|
@ -39,7 +39,7 @@ public class FeedPostFetchService implements PostFetcher.PostFetchService {
|
|||||||
return;
|
return;
|
||||||
} else if (result == null) return;
|
} else if (result == null) return;
|
||||||
nextCursor = result.getNextCursor();
|
nextCursor = result.getNextCursor();
|
||||||
hasNextPage = result.hasNextPage();
|
hasNextPage = result.getHasNextPage();
|
||||||
|
|
||||||
final List<Media> mediaResults = result.getFeedModels();
|
final List<Media> mediaResults = result.getFeedModels();
|
||||||
feedModels.addAll(mediaResults);
|
feedModels.addAll(mediaResults);
|
||||||
|
@ -35,7 +35,7 @@ public class HashtagPostFetchService implements PostFetcher.PostFetchService {
|
|||||||
public void onSuccess(final PostsFetchResponse result) {
|
public void onSuccess(final PostsFetchResponse result) {
|
||||||
if (result == null) return;
|
if (result == null) return;
|
||||||
nextMaxId = result.getNextCursor();
|
nextMaxId = result.getNextCursor();
|
||||||
moreAvailable = result.hasNextPage();
|
moreAvailable = result.getHasNextPage();
|
||||||
if (fetchListener != null) {
|
if (fetchListener != null) {
|
||||||
fetchListener.onResult(result.getFeedModels());
|
fetchListener.onResult(result.getFeedModels());
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ public class LocationPostFetchService implements PostFetcher.PostFetchService {
|
|||||||
public void onSuccess(final PostsFetchResponse result) {
|
public void onSuccess(final PostsFetchResponse result) {
|
||||||
if (result == null) return;
|
if (result == null) return;
|
||||||
nextMaxId = result.getNextCursor();
|
nextMaxId = result.getNextCursor();
|
||||||
moreAvailable = result.hasNextPage();
|
moreAvailable = result.getHasNextPage();
|
||||||
if (fetchListener != null) {
|
if (fetchListener != null) {
|
||||||
fetchListener.onResult(result.getFeedModels());
|
fetchListener.onResult(result.getFeedModels());
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ public class ProfilePostFetchService implements PostFetcher.PostFetchService {
|
|||||||
public void onSuccess(final PostsFetchResponse result) {
|
public void onSuccess(final PostsFetchResponse result) {
|
||||||
if (result == null) return;
|
if (result == null) return;
|
||||||
nextMaxId = result.getNextCursor();
|
nextMaxId = result.getNextCursor();
|
||||||
moreAvailable = result.hasNextPage();
|
moreAvailable = result.getHasNextPage();
|
||||||
if (fetchListener != null) {
|
if (fetchListener != null) {
|
||||||
fetchListener.onResult(result.getFeedModels());
|
fetchListener.onResult(result.getFeedModels());
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ public class SavedPostFetchService implements PostFetcher.PostFetchService {
|
|||||||
public void onSuccess(final PostsFetchResponse result) {
|
public void onSuccess(final PostsFetchResponse result) {
|
||||||
if (result == null) return;
|
if (result == null) return;
|
||||||
nextMaxId = result.getNextCursor();
|
nextMaxId = result.getNextCursor();
|
||||||
moreAvailable = result.hasNextPage();
|
moreAvailable = result.getHasNextPage();
|
||||||
if (fetchListener != null) {
|
if (fetchListener != null) {
|
||||||
fetchListener.onResult(result.getFeedModels());
|
fetchListener.onResult(result.getFeedModels());
|
||||||
}
|
}
|
||||||
|
@ -1,194 +0,0 @@
|
|||||||
package awais.instagrabber.dialogs;
|
|
||||||
|
|
||||||
import android.app.Dialog;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.AdapterView;
|
|
||||||
import android.widget.ArrayAdapter;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.fragment.app.DialogFragment;
|
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
|
||||||
import androidx.recyclerview.widget.GridLayoutManager;
|
|
||||||
|
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialog;
|
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import awais.instagrabber.R;
|
|
||||||
import awais.instagrabber.adapters.MediaItemsAdapter;
|
|
||||||
import awais.instagrabber.databinding.LayoutMediaPickerBinding;
|
|
||||||
import awais.instagrabber.utils.MediaController;
|
|
||||||
import awais.instagrabber.utils.PermissionUtils;
|
|
||||||
import awais.instagrabber.utils.TextUtils;
|
|
||||||
import awais.instagrabber.viewmodels.MediaPickerViewModel;
|
|
||||||
|
|
||||||
public class MediaPickerBottomDialogFragment extends BottomSheetDialogFragment {
|
|
||||||
private static final String TAG = MediaPickerBottomDialogFragment.class.getSimpleName();
|
|
||||||
private static final int ATTACH_MEDIA_REQUEST_CODE = 100;
|
|
||||||
// private static final int HEIGHT_PIXELS = Utils.displayMetrics.heightPixels;
|
|
||||||
|
|
||||||
private LayoutMediaPickerBinding binding;
|
|
||||||
private MediaPickerViewModel viewModel;
|
|
||||||
private MediaItemsAdapter mediaItemsAdapter;
|
|
||||||
private OnSelectListener onSelectListener;
|
|
||||||
// private int actionBarHeight;
|
|
||||||
// private int statusBarHeight;
|
|
||||||
|
|
||||||
// private final BottomSheetBehavior.BottomSheetCallback bottomSheetCallback = new BottomSheetBehavior.BottomSheetCallback() {
|
|
||||||
// @Override
|
|
||||||
// public void onStateChanged(@NonNull final View bottomSheet, final int newState) {
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void onSlide(@NonNull final View bottomSheet, final float slideOffset) {
|
|
||||||
// // Log.d(TAG, "onSlide: " + slideOffset);
|
|
||||||
// final float sheetHeight = HEIGHT_PIXELS * slideOffset;
|
|
||||||
// final Context context = getContext();
|
|
||||||
// if (context == null) return;
|
|
||||||
// final float remaining = HEIGHT_PIXELS - sheetHeight - statusBarHeight;
|
|
||||||
// if (remaining <= actionBarHeight) {
|
|
||||||
// final ViewGroup.LayoutParams layoutParams = binding.toolbar.getLayoutParams();
|
|
||||||
// layoutParams.height = (int) (actionBarHeight - remaining);
|
|
||||||
// binding.toolbar.requestLayout();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
public static MediaPickerBottomDialogFragment newInstance() {
|
|
||||||
final Bundle args = new Bundle();
|
|
||||||
final MediaPickerBottomDialogFragment fragment = new MediaPickerBottomDialogFragment();
|
|
||||||
fragment.setArguments(args);
|
|
||||||
return fragment;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
setStyle(DialogFragment.STYLE_NORMAL, R.style.ThemeOverlay_Rounded_BottomSheetDialog);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) {
|
|
||||||
binding = LayoutMediaPickerBinding.inflate(inflater, container, false);
|
|
||||||
viewModel = new ViewModelProvider(this).get(MediaPickerViewModel.class);
|
|
||||||
// final Context context = getContext();
|
|
||||||
// if (context == null) return binding.getRoot();
|
|
||||||
// actionBarHeight = Utils.getActionBarHeight(context);
|
|
||||||
// statusBarHeight = Utils.getStatusBarHeight(context);
|
|
||||||
return binding.getRoot();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onViewCreated(@NonNull final View view, @Nullable final Bundle savedInstanceState) {
|
|
||||||
init();
|
|
||||||
// final Dialog dialog = getDialog();
|
|
||||||
// if (dialog == null) return;
|
|
||||||
// dialog.setOnShowListener(dialog1 -> {
|
|
||||||
// final BottomSheetDialog bottomSheetDialog = (BottomSheetDialog) dialog;
|
|
||||||
// final View bottomSheetInternal = bottomSheetDialog.findViewById(com.google.android.material.R.id.design_bottom_sheet);
|
|
||||||
// if (bottomSheetInternal == null) return;
|
|
||||||
// final BottomSheetBehavior<View> behavior = BottomSheetBehavior.from(bottomSheetInternal);
|
|
||||||
// behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
|
|
||||||
// });
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStart() {
|
|
||||||
super.onStart();
|
|
||||||
final Dialog dialog = getDialog();
|
|
||||||
if (dialog == null) return;
|
|
||||||
final BottomSheetDialog bottomSheetDialog = (BottomSheetDialog) dialog;
|
|
||||||
final View bottomSheetInternal = bottomSheetDialog.findViewById(com.google.android.material.R.id.design_bottom_sheet);
|
|
||||||
if (bottomSheetInternal == null) return;
|
|
||||||
bottomSheetInternal.getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
|
|
||||||
bottomSheetInternal.requestLayout();
|
|
||||||
// final BottomSheetBehavior<View> behavior = BottomSheetBehavior.from(bottomSheetInternal);
|
|
||||||
// behavior.addBottomSheetCallback(bottomSheetCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRequestPermissionsResult(final int requestCode, @NonNull final String[] permissions, @NonNull final int[] grantResults) {
|
|
||||||
if (requestCode == ATTACH_MEDIA_REQUEST_CODE) {
|
|
||||||
final Context context = getContext();
|
|
||||||
if (context == null) return;
|
|
||||||
final boolean hasAttachMediaPerms = PermissionUtils.hasAttachMediaPerms(context);
|
|
||||||
if (hasAttachMediaPerms) {
|
|
||||||
viewModel.loadMedia(context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void init() {
|
|
||||||
setupList();
|
|
||||||
setupAlbumPicker();
|
|
||||||
final Context context = getContext();
|
|
||||||
if (context == null) return;
|
|
||||||
if (!PermissionUtils.hasAttachMediaPerms(context)) {
|
|
||||||
PermissionUtils.requestAttachMediaPerms(this, ATTACH_MEDIA_REQUEST_CODE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
viewModel.loadMedia(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupList() {
|
|
||||||
final Context context = getContext();
|
|
||||||
if (context == null) return;
|
|
||||||
binding.mediaList.setLayoutManager(new GridLayoutManager(context, 3));
|
|
||||||
binding.mediaList.setHasFixedSize(true);
|
|
||||||
mediaItemsAdapter = new MediaItemsAdapter(entry -> {
|
|
||||||
if (onSelectListener == null) return;
|
|
||||||
onSelectListener.onSelect(entry);
|
|
||||||
});
|
|
||||||
binding.mediaList.setAdapter(mediaItemsAdapter);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupAlbumPicker() {
|
|
||||||
final Context context = getContext();
|
|
||||||
if (context == null) return;
|
|
||||||
final ArrayAdapter<String> albumPickerAdapter = new ArrayAdapter<>(context, android.R.layout.simple_spinner_item);
|
|
||||||
albumPickerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
|
||||||
binding.albumPicker.setAdapter(albumPickerAdapter);
|
|
||||||
binding.albumPicker.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
|
||||||
@Override
|
|
||||||
public void onItemSelected(final AdapterView<?> parent, final View view, final int position, final long id) {
|
|
||||||
final List<MediaController.AlbumEntry> albumEntries = viewModel.getAllAlbums().getValue();
|
|
||||||
if (albumEntries == null) return;
|
|
||||||
final MediaController.AlbumEntry albumEntry = albumEntries.get(position);
|
|
||||||
mediaItemsAdapter.submitList(albumEntry.photos, () -> binding.mediaList.scrollToPosition(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNothingSelected(final AdapterView<?> parent) {
|
|
||||||
mediaItemsAdapter.submitList(Collections.emptyList());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
viewModel.getAllAlbums().observe(getViewLifecycleOwner(), albums -> {
|
|
||||||
albumPickerAdapter.clear();
|
|
||||||
albumPickerAdapter.addAll(albums.stream()
|
|
||||||
.map(albumEntry -> albumEntry.bucketName)
|
|
||||||
.filter(name -> !TextUtils.isEmpty(name))
|
|
||||||
.collect(Collectors.toList()));
|
|
||||||
albumPickerAdapter.notifyDataSetChanged();
|
|
||||||
if (albums.isEmpty()) return;
|
|
||||||
mediaItemsAdapter.submitList(albums.get(0).photos);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOnSelectListener(final OnSelectListener onSelectListener) {
|
|
||||||
this.onSelectListener = onSelectListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface OnSelectListener {
|
|
||||||
void onSelect(MediaController.MediaEntry entry);
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,7 +2,6 @@ package awais.instagrabber.fragments;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.content.res.ColorStateList;
|
import android.content.res.ColorStateList;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
@ -93,8 +92,8 @@ import awais.instagrabber.models.enums.MediaItemType;
|
|||||||
import awais.instagrabber.repositories.responses.Caption;
|
import awais.instagrabber.repositories.responses.Caption;
|
||||||
import awais.instagrabber.repositories.responses.Location;
|
import awais.instagrabber.repositories.responses.Location;
|
||||||
import awais.instagrabber.repositories.responses.Media;
|
import awais.instagrabber.repositories.responses.Media;
|
||||||
import awais.instagrabber.repositories.responses.User;
|
|
||||||
import awais.instagrabber.repositories.responses.MediaCandidate;
|
import awais.instagrabber.repositories.responses.MediaCandidate;
|
||||||
|
import awais.instagrabber.repositories.responses.User;
|
||||||
import awais.instagrabber.repositories.responses.directmessages.RankedRecipient;
|
import awais.instagrabber.repositories.responses.directmessages.RankedRecipient;
|
||||||
import awais.instagrabber.utils.DownloadUtils;
|
import awais.instagrabber.utils.DownloadUtils;
|
||||||
import awais.instagrabber.utils.NullSafePair;
|
import awais.instagrabber.utils.NullSafePair;
|
||||||
@ -152,7 +151,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
|
|||||||
if (context != null) {
|
if (context != null) {
|
||||||
Toast.makeText(context, R.string.sending, Toast.LENGTH_SHORT).show();
|
Toast.makeText(context, R.string.sending, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
viewModel.shareDm((RankedRecipient) result);
|
viewModel.shareDm((RankedRecipient) result, sliderPosition);
|
||||||
} else if ((result instanceof Set)) {
|
} else if ((result instanceof Set)) {
|
||||||
try {
|
try {
|
||||||
// Log.d(TAG, "result: " + result);
|
// Log.d(TAG, "result: " + result);
|
||||||
@ -161,7 +160,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
|
|||||||
Toast.makeText(context, R.string.sending, Toast.LENGTH_SHORT).show();
|
Toast.makeText(context, R.string.sending, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
viewModel.shareDm((Set<RankedRecipient>) result);
|
viewModel.shareDm((Set<RankedRecipient>) result, sliderPosition);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(TAG, "share: ", e);
|
Log.e(TAG, "share: ", e);
|
||||||
}
|
}
|
||||||
@ -294,7 +293,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final Media media = (Media) feedModelSerializable;
|
final Media media = (Media) feedModelSerializable;
|
||||||
if (media.getMediaType() == MediaItemType.MEDIA_TYPE_SLIDER) {
|
if (media.getMediaType() == MediaItemType.MEDIA_TYPE_SLIDER && sliderPosition == -1) {
|
||||||
sliderPosition = arguments.getInt(ARG_SLIDER_POSITION, 0);
|
sliderPosition = arguments.getInt(ARG_SLIDER_POSITION, 0);
|
||||||
}
|
}
|
||||||
viewModel.setMedia(media);
|
viewModel.setMedia(media);
|
||||||
@ -1039,6 +1038,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
|
|||||||
final String text = "1/" + carouselMedia.size();
|
final String text = "1/" + carouselMedia.size();
|
||||||
binding.mediaCounter.setText(text);
|
binding.mediaCounter.setText(text);
|
||||||
sliderItemsAdapter.submitList(media.getCarouselMedia());
|
sliderItemsAdapter.submitList(media.getCarouselMedia());
|
||||||
|
sliderParent.setCurrentItem(sliderPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void pauseSliderPlayer() {
|
private void pauseSliderPlayer() {
|
||||||
|
@ -38,9 +38,9 @@ import awais.instagrabber.adapters.HighlightStoriesListAdapter.OnHighlightStoryC
|
|||||||
import awais.instagrabber.customviews.helpers.RecyclerLazyLoader;
|
import awais.instagrabber.customviews.helpers.RecyclerLazyLoader;
|
||||||
import awais.instagrabber.databinding.FragmentStoryListViewerBinding;
|
import awais.instagrabber.databinding.FragmentStoryListViewerBinding;
|
||||||
import awais.instagrabber.fragments.settings.MorePreferencesFragmentDirections;
|
import awais.instagrabber.fragments.settings.MorePreferencesFragmentDirections;
|
||||||
import awais.instagrabber.models.FeedStoryModel;
|
|
||||||
import awais.instagrabber.models.HighlightModel;
|
|
||||||
import awais.instagrabber.repositories.requests.StoryViewerOptions;
|
import awais.instagrabber.repositories.requests.StoryViewerOptions;
|
||||||
|
import awais.instagrabber.repositories.responses.stories.ArchiveResponse;
|
||||||
|
import awais.instagrabber.repositories.responses.stories.Story;
|
||||||
import awais.instagrabber.utils.AppExecutors;
|
import awais.instagrabber.utils.AppExecutors;
|
||||||
import awais.instagrabber.utils.CoroutineUtilsKt;
|
import awais.instagrabber.utils.CoroutineUtilsKt;
|
||||||
import awais.instagrabber.utils.TextUtils;
|
import awais.instagrabber.utils.TextUtils;
|
||||||
@ -48,7 +48,6 @@ import awais.instagrabber.viewmodels.ArchivesViewModel;
|
|||||||
import awais.instagrabber.viewmodels.FeedStoriesViewModel;
|
import awais.instagrabber.viewmodels.FeedStoriesViewModel;
|
||||||
import awais.instagrabber.webservices.ServiceCallback;
|
import awais.instagrabber.webservices.ServiceCallback;
|
||||||
import awais.instagrabber.webservices.StoriesRepository;
|
import awais.instagrabber.webservices.StoriesRepository;
|
||||||
import awais.instagrabber.webservices.StoriesRepository.ArchiveFetchResponse;
|
|
||||||
import kotlinx.coroutines.Dispatchers;
|
import kotlinx.coroutines.Dispatchers;
|
||||||
|
|
||||||
public final class StoryListViewerFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
|
public final class StoryListViewerFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
|
||||||
@ -69,12 +68,12 @@ public final class StoryListViewerFragment extends Fragment implements SwipeRefr
|
|||||||
|
|
||||||
private final OnFeedStoryClickListener clickListener = new OnFeedStoryClickListener() {
|
private final OnFeedStoryClickListener clickListener = new OnFeedStoryClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onFeedStoryClick(final FeedStoryModel model) {
|
public void onFeedStoryClick(final Story model) {
|
||||||
if (model == null) return;
|
if (model == null) return;
|
||||||
final List<FeedStoryModel> feedStoryModels = feedStoriesViewModel.getList().getValue();
|
final List<Story> feedStoryModels = feedStoriesViewModel.getList().getValue();
|
||||||
if (feedStoryModels == null) return;
|
if (feedStoryModels == null) return;
|
||||||
final int position = Iterables.indexOf(feedStoryModels, feedStoryModel -> feedStoryModel != null
|
final int position = Iterables.indexOf(feedStoryModels, feedStoryModel -> feedStoryModel != null
|
||||||
&& Objects.equals(feedStoryModel.getStoryMediaId(), model.getStoryMediaId()));
|
&& Objects.equals(feedStoryModel.getId(), model.getId()));
|
||||||
final NavDirections action = StoryListViewerFragmentDirections
|
final NavDirections action = StoryListViewerFragmentDirections
|
||||||
.actionStoryListFragmentToStoryViewerFragment(StoryViewerOptions.forFeedStoryPosition(position));
|
.actionStoryListFragmentToStoryViewerFragment(StoryViewerOptions.forFeedStoryPosition(position));
|
||||||
NavHostFragment.findNavController(StoryListViewerFragment.this).navigate(action);
|
NavHostFragment.findNavController(StoryListViewerFragment.this).navigate(action);
|
||||||
@ -88,7 +87,7 @@ public final class StoryListViewerFragment extends Fragment implements SwipeRefr
|
|||||||
|
|
||||||
private final OnHighlightStoryClickListener archiveClickListener = new OnHighlightStoryClickListener() {
|
private final OnHighlightStoryClickListener archiveClickListener = new OnHighlightStoryClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onHighlightClick(final HighlightModel model, final int position) {
|
public void onHighlightClick(final Story model, final int position) {
|
||||||
if (model == null) return;
|
if (model == null) return;
|
||||||
final NavDirections action = StoryListViewerFragmentDirections
|
final NavDirections action = StoryListViewerFragmentDirections
|
||||||
.actionStoryListFragmentToStoryViewerFragment(StoryViewerOptions.forStoryArchive(position));
|
.actionStoryListFragmentToStoryViewerFragment(StoryViewerOptions.forStoryArchive(position));
|
||||||
@ -101,9 +100,9 @@ public final class StoryListViewerFragment extends Fragment implements SwipeRefr
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private final ServiceCallback<ArchiveFetchResponse> cb = new ServiceCallback<ArchiveFetchResponse>() {
|
private final ServiceCallback<ArchiveResponse> cb = new ServiceCallback<ArchiveResponse>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(final ArchiveFetchResponse result) {
|
public void onSuccess(final ArchiveResponse result) {
|
||||||
binding.swipeRefreshLayout.setRefreshing(false);
|
binding.swipeRefreshLayout.setRefreshing(false);
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
try {
|
try {
|
||||||
@ -111,10 +110,10 @@ public final class StoryListViewerFragment extends Fragment implements SwipeRefr
|
|||||||
Toast.makeText(context, R.string.empty_list, Toast.LENGTH_SHORT).show();
|
Toast.makeText(context, R.string.empty_list, Toast.LENGTH_SHORT).show();
|
||||||
} catch (Exception ignored) {}
|
} catch (Exception ignored) {}
|
||||||
} else {
|
} else {
|
||||||
endCursor = result.getNextCursor();
|
endCursor = result.getMaxId();
|
||||||
final List<HighlightModel> models = archivesViewModel.getList().getValue();
|
final List<Story> models = archivesViewModel.getList().getValue();
|
||||||
final List<HighlightModel> modelsCopy = models == null ? new ArrayList<>() : new ArrayList<>(models);
|
final List<Story> modelsCopy = models == null ? new ArrayList<>() : new ArrayList<>(models);
|
||||||
modelsCopy.addAll(result.getResult());
|
modelsCopy.addAll(result.getItems());
|
||||||
archivesViewModel.getList().postValue(modelsCopy);
|
archivesViewModel.getList().postValue(modelsCopy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -236,7 +235,7 @@ public final class StoryListViewerFragment extends Fragment implements SwipeRefr
|
|||||||
binding.swipeRefreshLayout.setRefreshing(true);
|
binding.swipeRefreshLayout.setRefreshing(true);
|
||||||
if (type.equals("feed") && firstRefresh) {
|
if (type.equals("feed") && firstRefresh) {
|
||||||
binding.swipeRefreshLayout.setRefreshing(false);
|
binding.swipeRefreshLayout.setRefreshing(false);
|
||||||
final List<FeedStoryModel> value = feedStoriesViewModel.getList().getValue();
|
final List<Story> value = feedStoriesViewModel.getList().getValue();
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
adapter.submitList(value);
|
adapter.submitList(value);
|
||||||
}
|
}
|
||||||
@ -250,9 +249,9 @@ public final class StoryListViewerFragment extends Fragment implements SwipeRefr
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
feedStoriesViewModel.getList().postValue((List<FeedStoryModel>) feedStoryModels);
|
feedStoriesViewModel.getList().postValue((List<Story>) feedStoryModels);
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
adapter.submitList((List<FeedStoryModel>) feedStoryModels);
|
adapter.submitList((List<Story>) feedStoryModels);
|
||||||
binding.swipeRefreshLayout.setRefreshing(false);
|
binding.swipeRefreshLayout.setRefreshing(false);
|
||||||
}), Dispatchers.getIO())
|
}), Dispatchers.getIO())
|
||||||
);
|
);
|
||||||
|
@ -72,8 +72,6 @@ import awais.instagrabber.databinding.FragmentStoryViewerBinding;
|
|||||||
import awais.instagrabber.fragments.main.ProfileFragmentDirections;
|
import awais.instagrabber.fragments.main.ProfileFragmentDirections;
|
||||||
import awais.instagrabber.fragments.settings.PreferenceKeys;
|
import awais.instagrabber.fragments.settings.PreferenceKeys;
|
||||||
import awais.instagrabber.interfaces.SwipeEvent;
|
import awais.instagrabber.interfaces.SwipeEvent;
|
||||||
import awais.instagrabber.models.FeedStoryModel;
|
|
||||||
import awais.instagrabber.models.HighlightModel;
|
|
||||||
import awais.instagrabber.models.StoryModel;
|
import awais.instagrabber.models.StoryModel;
|
||||||
import awais.instagrabber.models.enums.MediaItemType;
|
import awais.instagrabber.models.enums.MediaItemType;
|
||||||
import awais.instagrabber.models.stickers.PollModel;
|
import awais.instagrabber.models.stickers.PollModel;
|
||||||
@ -84,6 +82,8 @@ import awais.instagrabber.models.stickers.SwipeUpModel;
|
|||||||
import awais.instagrabber.repositories.requests.StoryViewerOptions;
|
import awais.instagrabber.repositories.requests.StoryViewerOptions;
|
||||||
import awais.instagrabber.repositories.requests.StoryViewerOptions.Type;
|
import awais.instagrabber.repositories.requests.StoryViewerOptions.Type;
|
||||||
import awais.instagrabber.repositories.requests.directmessages.ThreadIdsOrUserIds;
|
import awais.instagrabber.repositories.requests.directmessages.ThreadIdsOrUserIds;
|
||||||
|
import awais.instagrabber.repositories.responses.stories.Broadcast;
|
||||||
|
import awais.instagrabber.repositories.responses.stories.Story;
|
||||||
import awais.instagrabber.utils.AppExecutors;
|
import awais.instagrabber.utils.AppExecutors;
|
||||||
import awais.instagrabber.utils.Constants;
|
import awais.instagrabber.utils.Constants;
|
||||||
import awais.instagrabber.utils.CookieUtils;
|
import awais.instagrabber.utils.CookieUtils;
|
||||||
@ -122,6 +122,7 @@ public class StoryViewerFragment extends Fragment {
|
|||||||
private StoriesRepository storiesRepository;
|
private StoriesRepository storiesRepository;
|
||||||
private MediaRepository mediaRepository;
|
private MediaRepository mediaRepository;
|
||||||
private StoryModel currentStory;
|
private StoryModel currentStory;
|
||||||
|
private Broadcast live;
|
||||||
private int slidePos;
|
private int slidePos;
|
||||||
private int lastSlidePos;
|
private int lastSlidePos;
|
||||||
private String url;
|
private String url;
|
||||||
@ -714,7 +715,7 @@ public class StoryViewerFragment extends Fragment {
|
|||||||
private void resetView() {
|
private void resetView() {
|
||||||
final Context context = getContext();
|
final Context context = getContext();
|
||||||
if (context == null) return;
|
if (context == null) return;
|
||||||
StoryModel live = null;
|
live = null;
|
||||||
slidePos = 0;
|
slidePos = 0;
|
||||||
lastSlidePos = 0;
|
lastSlidePos = 0;
|
||||||
if (menuDownload != null) menuDownload.setVisible(false);
|
if (menuDownload != null) menuDownload.setVisible(false);
|
||||||
@ -731,12 +732,12 @@ public class StoryViewerFragment extends Fragment {
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case HIGHLIGHT: {
|
case HIGHLIGHT: {
|
||||||
final HighlightsViewModel highlightsViewModel = (HighlightsViewModel) viewModel;
|
final HighlightsViewModel highlightsViewModel = (HighlightsViewModel) viewModel;
|
||||||
final List<HighlightModel> models = highlightsViewModel.getList().getValue();
|
final List<Story> models = highlightsViewModel.getList().getValue();
|
||||||
if (models == null || models.isEmpty() || currentFeedStoryIndex >= models.size() || currentFeedStoryIndex < 0) {
|
if (models == null || models.isEmpty() || currentFeedStoryIndex >= models.size() || currentFeedStoryIndex < 0) {
|
||||||
Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final HighlightModel model = models.get(currentFeedStoryIndex);
|
final Story model = models.get(currentFeedStoryIndex);
|
||||||
currentStoryMediaId = model.getId();
|
currentStoryMediaId = model.getId();
|
||||||
fetchOptions = StoryViewerOptions.forHighlight(model.getId());
|
fetchOptions = StoryViewerOptions.forHighlight(model.getId());
|
||||||
highlightTitle = model.getTitle();
|
highlightTitle = model.getTitle();
|
||||||
@ -744,25 +745,23 @@ public class StoryViewerFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
case FEED_STORY_POSITION: {
|
case FEED_STORY_POSITION: {
|
||||||
final FeedStoriesViewModel feedStoriesViewModel = (FeedStoriesViewModel) viewModel;
|
final FeedStoriesViewModel feedStoriesViewModel = (FeedStoriesViewModel) viewModel;
|
||||||
final List<FeedStoryModel> models = feedStoriesViewModel.getList().getValue();
|
final List<Story> models = feedStoriesViewModel.getList().getValue();
|
||||||
if (models == null || currentFeedStoryIndex >= models.size() || currentFeedStoryIndex < 0) return;
|
if (models == null || currentFeedStoryIndex >= models.size() || currentFeedStoryIndex < 0) return;
|
||||||
final FeedStoryModel model = models.get(currentFeedStoryIndex);
|
final Story model = models.get(currentFeedStoryIndex);
|
||||||
currentStoryMediaId = model.getStoryMediaId();
|
currentStoryMediaId = model.getId();
|
||||||
currentStoryUsername = model.getProfileModel().getUsername();
|
currentStoryUsername = model.getUser().getUsername();
|
||||||
fetchOptions = StoryViewerOptions.forUser(Long.parseLong(currentStoryMediaId), currentStoryUsername);
|
fetchOptions = StoryViewerOptions.forUser(Long.parseLong(currentStoryMediaId), currentStoryUsername);
|
||||||
if (model.isLive()) {
|
live = model.getBroadcast();
|
||||||
live = model.getFirstStoryModel();
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case STORY_ARCHIVE: {
|
case STORY_ARCHIVE: {
|
||||||
final ArchivesViewModel archivesViewModel = (ArchivesViewModel) viewModel;
|
final ArchivesViewModel archivesViewModel = (ArchivesViewModel) viewModel;
|
||||||
final List<HighlightModel> models = archivesViewModel.getList().getValue();
|
final List<Story> models = archivesViewModel.getList().getValue();
|
||||||
if (models == null || models.isEmpty() || currentFeedStoryIndex >= models.size() || currentFeedStoryIndex < 0) {
|
if (models == null || models.isEmpty() || currentFeedStoryIndex >= models.size() || currentFeedStoryIndex < 0) {
|
||||||
Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final HighlightModel model = models.get(currentFeedStoryIndex);
|
final Story model = models.get(currentFeedStoryIndex);
|
||||||
currentStoryMediaId = parseStoryMediaId(model.getId());
|
currentStoryMediaId = parseStoryMediaId(model.getId());
|
||||||
currentStoryUsername = model.getTitle();
|
currentStoryUsername = model.getTitle();
|
||||||
fetchOptions = StoryViewerOptions.forStoryArchive(model.getId());
|
fetchOptions = StoryViewerOptions.forStoryArchive(model.getId());
|
||||||
@ -800,6 +799,11 @@ public class StoryViewerFragment extends Fragment {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (currentStoryMediaId == null) return;
|
if (currentStoryMediaId == null) return;
|
||||||
|
if (live != null) {
|
||||||
|
currentStory = null;
|
||||||
|
refreshLive();
|
||||||
|
return;
|
||||||
|
}
|
||||||
final ServiceCallback<List<StoryModel>> storyCallback = new ServiceCallback<List<StoryModel>>() {
|
final ServiceCallback<List<StoryModel>> storyCallback = new ServiceCallback<List<StoryModel>>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(final List<StoryModel> storyModels) {
|
public void onSuccess(final List<StoryModel> storyModels) {
|
||||||
@ -826,10 +830,6 @@ public class StoryViewerFragment extends Fragment {
|
|||||||
Log.e(TAG, "Error", t);
|
Log.e(TAG, "Error", t);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (live != null) {
|
|
||||||
storyCallback.onSuccess(Collections.singletonList(live));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
storiesRepository.getUserStory(
|
storiesRepository.getUserStory(
|
||||||
fetchOptions,
|
fetchOptions,
|
||||||
CoroutineUtilsKt.getContinuation((storyModels, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
|
CoroutineUtilsKt.getContinuation((storyModels, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
|
||||||
@ -861,6 +861,30 @@ public class StoryViewerFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private synchronized void refreshLive() {
|
||||||
|
binding.storiesList.setVisibility(View.INVISIBLE);
|
||||||
|
binding.viewStoryPost.setVisibility(View.GONE);
|
||||||
|
binding.spotify.setVisibility(View.GONE);
|
||||||
|
binding.poll.setVisibility(View.GONE);
|
||||||
|
binding.answer.setVisibility(View.GONE);
|
||||||
|
binding.mention.setVisibility(View.GONE);
|
||||||
|
binding.quiz.setVisibility(View.GONE);
|
||||||
|
binding.slider.setVisibility(View.GONE);
|
||||||
|
lastSlidePos = slidePos;
|
||||||
|
releasePlayer();
|
||||||
|
url = live.getDashPlaybackUrl();
|
||||||
|
setupLive();
|
||||||
|
final ActionBar actionBar = fragmentActivity.getSupportActionBar();
|
||||||
|
actionBarSubtitle = TextUtils.epochSecondToString(live.getPublishedTime());
|
||||||
|
if (actionBar != null) {
|
||||||
|
try {
|
||||||
|
actionBar.setSubtitle(actionBarSubtitle);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "refreshLive: ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private synchronized void refreshStory() {
|
private synchronized void refreshStory() {
|
||||||
if (binding.storiesList.getVisibility() == View.VISIBLE) {
|
if (binding.storiesList.getVisibility() == View.VISIBLE) {
|
||||||
final List<StoryModel> storyModels = storiesViewModel.getList().getValue();
|
final List<StoryModel> storyModels = storiesViewModel.getList().getValue();
|
||||||
@ -883,7 +907,6 @@ public class StoryViewerFragment extends Fragment {
|
|||||||
|
|
||||||
url = itemType == MediaItemType.MEDIA_TYPE_IMAGE ? currentStory.getStoryUrl() : currentStory.getVideoUrl();
|
url = itemType == MediaItemType.MEDIA_TYPE_IMAGE ? currentStory.getStoryUrl() : currentStory.getVideoUrl();
|
||||||
|
|
||||||
if (itemType != MediaItemType.MEDIA_TYPE_LIVE) {
|
|
||||||
final String shortCode = currentStory.getTappableShortCode();
|
final String shortCode = currentStory.getTappableShortCode();
|
||||||
binding.viewStoryPost.setVisibility(shortCode != null ? View.VISIBLE : View.GONE);
|
binding.viewStoryPost.setVisibility(shortCode != null ? View.VISIBLE : View.GONE);
|
||||||
binding.viewStoryPost.setTag(shortCode);
|
binding.viewStoryPost.setTag(shortCode);
|
||||||
@ -918,7 +941,6 @@ public class StoryViewerFragment extends Fragment {
|
|||||||
binding.swipeUp.setText(swipeUp.getText());
|
binding.swipeUp.setText(swipeUp.getText());
|
||||||
binding.swipeUp.setTag(swipeUp.getUrl());
|
binding.swipeUp.setTag(swipeUp.getUrl());
|
||||||
} else binding.swipeUp.setVisibility(View.GONE);
|
} else binding.swipeUp.setVisibility(View.GONE);
|
||||||
}
|
|
||||||
|
|
||||||
releasePlayer();
|
releasePlayer();
|
||||||
final Type type = options.getType();
|
final Type type = options.getType();
|
||||||
@ -930,7 +952,6 @@ public class StoryViewerFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (itemType == MediaItemType.MEDIA_TYPE_VIDEO) setupVideo();
|
if (itemType == MediaItemType.MEDIA_TYPE_VIDEO) setupVideo();
|
||||||
else if (itemType == MediaItemType.MEDIA_TYPE_LIVE) setupLive();
|
|
||||||
else setupImage();
|
else setupImage();
|
||||||
|
|
||||||
final ActionBar actionBar = fragmentActivity.getSupportActionBar();
|
final ActionBar actionBar = fragmentActivity.getSupportActionBar();
|
||||||
@ -1202,14 +1223,14 @@ public class StoryViewerFragment extends Fragment {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (settingsHelper.getBoolean(MARK_AS_SEEN)
|
if (settingsHelper.getBoolean(MARK_AS_SEEN)
|
||||||
&& oldFeedStory instanceof FeedStoryModel
|
&& oldFeedStory instanceof Story
|
||||||
&& viewModel instanceof FeedStoriesViewModel) {
|
&& viewModel instanceof FeedStoriesViewModel) {
|
||||||
final FeedStoriesViewModel feedStoriesViewModel = (FeedStoriesViewModel) viewModel;
|
final FeedStoriesViewModel feedStoriesViewModel = (FeedStoriesViewModel) viewModel;
|
||||||
final FeedStoryModel oldFeedStoryModel = (FeedStoryModel) oldFeedStory;
|
final Story oldFeedStoryModel = (Story) oldFeedStory;
|
||||||
if (!oldFeedStoryModel.isFullyRead()) {
|
if (oldFeedStoryModel.getSeen() == null || !oldFeedStoryModel.getSeen().equals(oldFeedStoryModel.getLatestReelMedia())) {
|
||||||
oldFeedStoryModel.setFullyRead(true);
|
oldFeedStoryModel.setSeen(oldFeedStoryModel.getLatestReelMedia());
|
||||||
final List<FeedStoryModel> models = feedStoriesViewModel.getList().getValue();
|
final List<Story> models = feedStoriesViewModel.getList().getValue();
|
||||||
final List<FeedStoryModel> modelsCopy = models == null ? new ArrayList<>() : new ArrayList<>(models);
|
final List<Story> modelsCopy = models == null ? new ArrayList<>() : new ArrayList<>(models);
|
||||||
modelsCopy.set(currentFeedStoryIndex, oldFeedStoryModel);
|
modelsCopy.set(currentFeedStoryIndex, oldFeedStoryModel);
|
||||||
feedStoriesViewModel.getList().postValue(models);
|
feedStoriesViewModel.getList().postValue(models);
|
||||||
}
|
}
|
||||||
|
@ -174,7 +174,7 @@ public class RepliesFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setupToolbar() {
|
private void setupToolbar() {
|
||||||
binding.toolbar.setTitle("Replies");
|
binding.toolbar.setTitle(R.string.title_replies);
|
||||||
binding.toolbar.setNavigationIcon(R.drawable.ic_round_arrow_back_24);
|
binding.toolbar.setNavigationIcon(R.drawable.ic_round_arrow_back_24);
|
||||||
binding.toolbar.setNavigationOnClickListener(v -> {
|
binding.toolbar.setNavigationOnClickListener(v -> {
|
||||||
final FragmentManager fragmentManager = getParentFragmentManager();
|
final FragmentManager fragmentManager = getParentFragmentManager();
|
||||||
@ -187,7 +187,16 @@ public class RepliesFragment extends Fragment {
|
|||||||
if (context == null) return;
|
if (context == null) return;
|
||||||
commentsAdapter = new CommentsAdapter(currentUserId,
|
commentsAdapter = new CommentsAdapter(currentUserId,
|
||||||
true,
|
true,
|
||||||
Helper.getCommentCallback(context, getViewLifecycleOwner(), getNavController(), viewModel, null));
|
Helper.getCommentCallback(context,
|
||||||
|
getViewLifecycleOwner(),
|
||||||
|
getNavController(),
|
||||||
|
viewModel,
|
||||||
|
(comment, focusInput) -> {
|
||||||
|
viewModel.setReplyTo(comment);
|
||||||
|
binding.commentText.setText(String.format("@%s ", comment.getUser().getUsername()));
|
||||||
|
if (focusInput) Utils.showKeyboard(binding.commentText);
|
||||||
|
return null;
|
||||||
|
}));
|
||||||
binding.comments.setAdapter(commentsAdapter);
|
binding.comments.setAdapter(commentsAdapter);
|
||||||
final Resource<List<Comment>> listResource = viewModel.getReplyList().getValue();
|
final Resource<List<Comment>> listResource = viewModel.getReplyList().getValue();
|
||||||
commentsAdapter.submitList(listResource != null ? listResource.data : Collections.emptyList());
|
commentsAdapter.submitList(listResource != null ? listResource.data : Collections.emptyList());
|
||||||
|
@ -8,7 +8,6 @@ import android.annotation.SuppressLint;
|
|||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.graphics.drawable.Animatable;
|
import android.graphics.drawable.Animatable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
@ -32,7 +31,6 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.ActionBar;
|
import androidx.appcompat.app.ActionBar;
|
||||||
import androidx.appcompat.view.menu.ActionMenuItemView;
|
import androidx.appcompat.view.menu.ActionMenuItemView;
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import androidx.core.view.ViewCompat;
|
import androidx.core.view.ViewCompat;
|
||||||
import androidx.core.view.WindowInsetsAnimationCompat;
|
import androidx.core.view.WindowInsetsAnimationCompat;
|
||||||
import androidx.core.view.WindowInsetsAnimationControlListenerCompat;
|
import androidx.core.view.WindowInsetsAnimationControlListenerCompat;
|
||||||
@ -97,7 +95,6 @@ import awais.instagrabber.customviews.helpers.TranslateDeferringInsetsAnimationC
|
|||||||
import awais.instagrabber.databinding.FragmentDirectMessagesThreadBinding;
|
import awais.instagrabber.databinding.FragmentDirectMessagesThreadBinding;
|
||||||
import awais.instagrabber.dialogs.DirectItemReactionDialogFragment;
|
import awais.instagrabber.dialogs.DirectItemReactionDialogFragment;
|
||||||
import awais.instagrabber.dialogs.GifPickerBottomDialogFragment;
|
import awais.instagrabber.dialogs.GifPickerBottomDialogFragment;
|
||||||
import awais.instagrabber.dialogs.MediaPickerBottomDialogFragment;
|
|
||||||
import awais.instagrabber.fragments.PostViewV2Fragment;
|
import awais.instagrabber.fragments.PostViewV2Fragment;
|
||||||
import awais.instagrabber.fragments.UserSearchFragment;
|
import awais.instagrabber.fragments.UserSearchFragment;
|
||||||
import awais.instagrabber.fragments.UserSearchFragmentDirections;
|
import awais.instagrabber.fragments.UserSearchFragmentDirections;
|
||||||
@ -130,6 +127,7 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
private static final String TAG = DirectMessageThreadFragment.class.getSimpleName();
|
private static final String TAG = DirectMessageThreadFragment.class.getSimpleName();
|
||||||
private static final int AUDIO_RECORD_PERM_REQUEST_CODE = 1000;
|
private static final int AUDIO_RECORD_PERM_REQUEST_CODE = 1000;
|
||||||
private static final int CAMERA_REQUEST_CODE = 200;
|
private static final int CAMERA_REQUEST_CODE = 200;
|
||||||
|
private static final int FILE_PICKER_REQUEST_CODE = 500;
|
||||||
private static final String TRANSLATION_Y = "translationY";
|
private static final String TRANSLATION_Y = "translationY";
|
||||||
|
|
||||||
private DirectItemsAdapter itemsAdapter;
|
private DirectItemsAdapter itemsAdapter;
|
||||||
@ -221,7 +219,7 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMediaClick(final Media media) {
|
public void onMediaClick(final Media media, final int index) {
|
||||||
if (media.isReelMedia()) {
|
if (media.isReelMedia()) {
|
||||||
final String pk = media.getPk();
|
final String pk = media.getPk();
|
||||||
try {
|
try {
|
||||||
@ -240,6 +238,7 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
final NavController navController = NavHostFragment.findNavController(DirectMessageThreadFragment.this);
|
final NavController navController = NavHostFragment.findNavController(DirectMessageThreadFragment.this);
|
||||||
final Bundle bundle = new Bundle();
|
final Bundle bundle = new Bundle();
|
||||||
bundle.putSerializable(PostViewV2Fragment.ARG_MEDIA, media);
|
bundle.putSerializable(PostViewV2Fragment.ARG_MEDIA, media);
|
||||||
|
bundle.putInt(PostViewV2Fragment.ARG_SLIDER_POSITION, index);
|
||||||
try {
|
try {
|
||||||
navController.navigate(R.id.action_global_post_view, bundle);
|
navController.navigate(R.id.action_global_post_view, bundle);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -474,6 +473,24 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
@Override
|
@Override
|
||||||
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
||||||
super.onActivityResult(requestCode, resultCode, data);
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
if (requestCode == FILE_PICKER_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
|
||||||
|
if (data == null || data.getData() == null) {
|
||||||
|
Log.w(TAG, "data is null!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final Context context = getContext();
|
||||||
|
if (context == null) {
|
||||||
|
Log.w(TAG, "conetxt is null!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final Uri uri = data.getData();
|
||||||
|
final String mimeType = Utils.getMimeType(uri, context.getContentResolver());
|
||||||
|
if (mimeType.startsWith("image")) {
|
||||||
|
navigateToImageEditFragment(uri);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
handleSentMessage(viewModel.sendUri(uri));
|
||||||
|
}
|
||||||
if (requestCode == CAMERA_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
|
if (requestCode == CAMERA_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
|
||||||
if (data == null || data.getData() == null) {
|
if (data == null || data.getData() == null) {
|
||||||
Log.w(TAG, "data is null!");
|
Log.w(TAG, "data is null!");
|
||||||
@ -1109,17 +1126,15 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
|||||||
setupInsetsCallback();
|
setupInsetsCallback();
|
||||||
setupEmojiPicker();
|
setupEmojiPicker();
|
||||||
binding.gallery.setOnClickListener(v -> {
|
binding.gallery.setOnClickListener(v -> {
|
||||||
final MediaPickerBottomDialogFragment mediaPicker = MediaPickerBottomDialogFragment.newInstance();
|
final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
|
||||||
mediaPicker.setOnSelectListener(entry -> {
|
intent.setType("*/*");
|
||||||
mediaPicker.dismiss();
|
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||||
if (!isAdded()) return;
|
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
if (!entry.isVideo) {
|
intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[]{
|
||||||
navigateToImageEditFragment(entry.path);
|
"image/*",
|
||||||
return;
|
"video/mp4"
|
||||||
}
|
|
||||||
handleSentMessage(viewModel.sendUri(entry));
|
|
||||||
});
|
});
|
||||||
mediaPicker.show(getChildFragmentManager(), "MediaPicker");
|
startActivityForResult(intent, FILE_PICKER_REQUEST_CODE);
|
||||||
});
|
});
|
||||||
binding.gif.setOnClickListener(v -> {
|
binding.gif.setOnClickListener(v -> {
|
||||||
final GifPickerBottomDialogFragment gifPicker = GifPickerBottomDialogFragment.newInstance();
|
final GifPickerBottomDialogFragment gifPicker = GifPickerBottomDialogFragment.newInstance();
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package awais.instagrabber.fragments.main;
|
package awais.instagrabber.fragments.main;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@ -12,7 +11,6 @@ import android.view.MenuInflater;
|
|||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import androidx.activity.OnBackPressedCallback;
|
import androidx.activity.OnBackPressedCallback;
|
||||||
import androidx.activity.OnBackPressedDispatcher;
|
import androidx.activity.OnBackPressedDispatcher;
|
||||||
@ -43,10 +41,10 @@ import awais.instagrabber.customviews.PrimaryActionModeCallback;
|
|||||||
import awais.instagrabber.databinding.FragmentFeedBinding;
|
import awais.instagrabber.databinding.FragmentFeedBinding;
|
||||||
import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment;
|
import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment;
|
||||||
import awais.instagrabber.fragments.PostViewV2Fragment;
|
import awais.instagrabber.fragments.PostViewV2Fragment;
|
||||||
import awais.instagrabber.models.FeedStoryModel;
|
|
||||||
import awais.instagrabber.models.PostsLayoutPreferences;
|
import awais.instagrabber.models.PostsLayoutPreferences;
|
||||||
import awais.instagrabber.repositories.requests.StoryViewerOptions;
|
import awais.instagrabber.repositories.requests.StoryViewerOptions;
|
||||||
import awais.instagrabber.repositories.responses.Media;
|
import awais.instagrabber.repositories.responses.Media;
|
||||||
|
import awais.instagrabber.repositories.responses.stories.Story;
|
||||||
import awais.instagrabber.utils.AppExecutors;
|
import awais.instagrabber.utils.AppExecutors;
|
||||||
import awais.instagrabber.utils.Constants;
|
import awais.instagrabber.utils.Constants;
|
||||||
import awais.instagrabber.utils.CoroutineUtilsKt;
|
import awais.instagrabber.utils.CoroutineUtilsKt;
|
||||||
@ -76,7 +74,7 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre
|
|||||||
private final FeedStoriesAdapter feedStoriesAdapter = new FeedStoriesAdapter(
|
private final FeedStoriesAdapter feedStoriesAdapter = new FeedStoriesAdapter(
|
||||||
new FeedStoriesAdapter.OnFeedStoryClickListener() {
|
new FeedStoriesAdapter.OnFeedStoryClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onFeedStoryClick(FeedStoryModel model, int position) {
|
public void onFeedStoryClick(Story model, int position) {
|
||||||
final NavController navController = NavHostFragment.findNavController(FeedFragment.this);
|
final NavController navController = NavHostFragment.findNavController(FeedFragment.this);
|
||||||
if (isSafeToNavigate(navController)) {
|
if (isSafeToNavigate(navController)) {
|
||||||
final NavDirections action = FeedFragmentDirections
|
final NavDirections action = FeedFragmentDirections
|
||||||
@ -86,8 +84,8 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFeedStoryLongClick(FeedStoryModel model, int position) {
|
public void onFeedStoryLongClick(Story model, int position) {
|
||||||
navigateToProfile("@" + model.getProfileModel().getUsername());
|
navigateToProfile("@" + model.getUser().getUsername());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -399,9 +397,9 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre
|
|||||||
}
|
}
|
||||||
storiesFetching = false;
|
storiesFetching = false;
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
feedStoriesViewModel.getList().postValue((List<FeedStoryModel>) feedStoryModels);
|
feedStoriesViewModel.getList().postValue((List<Story>) feedStoryModels);
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
feedStoriesAdapter.submitList((List<FeedStoryModel>) feedStoryModels);
|
feedStoriesAdapter.submitList((List<Story>) feedStoryModels);
|
||||||
if (storyListMenu != null) storyListMenu.setVisible(true);
|
if (storyListMenu != null) storyListMenu.setVisible(true);
|
||||||
updateSwipeRefreshState();
|
updateSwipeRefreshState();
|
||||||
}), Dispatchers.getIO())
|
}), Dispatchers.getIO())
|
||||||
|
@ -23,7 +23,6 @@ import java.nio.charset.StandardCharsets;
|
|||||||
import awais.instagrabber.R;
|
import awais.instagrabber.R;
|
||||||
import awais.instagrabber.dialogs.ConfirmDialogFragment;
|
import awais.instagrabber.dialogs.ConfirmDialogFragment;
|
||||||
import awais.instagrabber.utils.AppExecutors;
|
import awais.instagrabber.utils.AppExecutors;
|
||||||
import awais.instagrabber.utils.Constants;
|
|
||||||
import awais.instagrabber.utils.DownloadUtils;
|
import awais.instagrabber.utils.DownloadUtils;
|
||||||
import awais.instagrabber.utils.TextUtils;
|
import awais.instagrabber.utils.TextUtils;
|
||||||
import awais.instagrabber.utils.Utils;
|
import awais.instagrabber.utils.Utils;
|
||||||
@ -111,7 +110,7 @@ public class DownloadsPreferencesFragment extends BasePreferencesFragment {
|
|||||||
R.string.error,
|
R.string.error,
|
||||||
"com.android.externalstorage.documents".equals(data.getData().getAuthority())
|
"com.android.externalstorage.documents".equals(data.getData().getAuthority())
|
||||||
? "Please report this error to the developers:\n\n" + sw.toString()
|
? "Please report this error to the developers:\n\n" + sw.toString()
|
||||||
: getString(R.string.dir_select_no_download_folder),
|
: getString(R.string.dir_select_no_download_folder, data.getData().getAuthority()),
|
||||||
R.string.ok,
|
R.string.ok,
|
||||||
0,
|
0,
|
||||||
0
|
0
|
||||||
|
@ -70,20 +70,21 @@ object DirectMessagesManager {
|
|||||||
suspend fun createThread(userPk: Long): DirectThread =
|
suspend fun createThread(userPk: Long): DirectThread =
|
||||||
directMessagesRepository.createThread(csrfToken, viewerId, deviceUuid, listOf(userPk), null)
|
directMessagesRepository.createThread(csrfToken, viewerId, deviceUuid, listOf(userPk), null)
|
||||||
|
|
||||||
fun sendMedia(recipient: RankedRecipient, mediaId: String, itemType: BroadcastItemType, scope: CoroutineScope) {
|
fun sendMedia(recipient: RankedRecipient, mediaId: String, secondId: String?, itemType: BroadcastItemType, scope: CoroutineScope) {
|
||||||
sendMedia(setOf(recipient), mediaId, itemType, scope)
|
sendMedia(setOf(recipient), mediaId, secondId, itemType, scope)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sendMedia(
|
fun sendMedia(
|
||||||
recipients: Set<RankedRecipient>,
|
recipients: Set<RankedRecipient>,
|
||||||
mediaId: String,
|
mediaId: String,
|
||||||
|
secondId: String?,
|
||||||
itemType: BroadcastItemType,
|
itemType: BroadcastItemType,
|
||||||
scope: CoroutineScope,
|
scope: CoroutineScope,
|
||||||
) {
|
) {
|
||||||
val threadIds = recipients.mapNotNull { it.thread?.threadId }
|
val threadIds = recipients.mapNotNull { it.thread?.threadId }
|
||||||
val userIdsTemp = recipients.mapNotNull { it.user?.pk }
|
val userIdsTemp = recipients.mapNotNull { it.user?.pk }
|
||||||
val userIds = userIdsTemp.map { listOf(it.toString(10)) }
|
val userIds = userIdsTemp.map { listOf(it.toString(10)) }
|
||||||
sendMedia(threadIds, userIds, mediaId, itemType, scope) {
|
sendMedia(threadIds, userIds, mediaId, secondId, itemType, scope) {
|
||||||
inboxManager.refresh(scope)
|
inboxManager.refresh(scope)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -92,6 +93,7 @@ object DirectMessagesManager {
|
|||||||
threadIds: List<String>,
|
threadIds: List<String>,
|
||||||
userIds: List<List<String>>,
|
userIds: List<List<String>>,
|
||||||
mediaId: String,
|
mediaId: String,
|
||||||
|
secondId: String?,
|
||||||
itemType: BroadcastItemType,
|
itemType: BroadcastItemType,
|
||||||
scope: CoroutineScope,
|
scope: CoroutineScope,
|
||||||
callback: (() -> Unit)?,
|
callback: (() -> Unit)?,
|
||||||
@ -107,7 +109,8 @@ object DirectMessagesManager {
|
|||||||
deviceUuid,
|
deviceUuid,
|
||||||
UUID.randomUUID().toString(),
|
UUID.randomUUID().toString(),
|
||||||
ThreadIdsOrUserIds(threadIds, userIds),
|
ThreadIdsOrUserIds(threadIds, userIds),
|
||||||
mediaId
|
mediaId,
|
||||||
|
secondId
|
||||||
)
|
)
|
||||||
if (itemType == BroadcastItemType.PROFILE)
|
if (itemType == BroadcastItemType.PROFILE)
|
||||||
directMessagesRepository.broadcastProfile(
|
directMessagesRepository.broadcastProfile(
|
||||||
|
@ -39,7 +39,6 @@ import kotlinx.coroutines.CoroutineScope
|
|||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import retrofit2.Call
|
import retrofit2.Call
|
||||||
import java.io.File
|
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.net.HttpURLConnection
|
import java.net.HttpURLConnection
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -368,17 +367,6 @@ class ThreadManager(
|
|||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sendUri(entry: MediaController.MediaEntry, scope: CoroutineScope): LiveData<Resource<Any?>> {
|
|
||||||
val data = MutableLiveData<Resource<Any?>>()
|
|
||||||
val uri = Uri.fromFile(File(entry.path))
|
|
||||||
if (!entry.isVideo) {
|
|
||||||
sendPhoto(data, uri, entry.width, entry.height, scope)
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
sendVideo(data, uri, entry.size, entry.duration, entry.width, entry.height, scope)
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
fun sendUri(uri: Uri, scope: CoroutineScope): LiveData<Resource<Any?>> {
|
fun sendUri(uri: Uri, scope: CoroutineScope): LiveData<Resource<Any?>> {
|
||||||
val data = MutableLiveData<Resource<Any?>>()
|
val data = MutableLiveData<Resource<Any?>>()
|
||||||
val mimeType = Utils.getMimeType(uri, contentResolver)
|
val mimeType = Utils.getMimeType(uri, contentResolver)
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
package awais.instagrabber.models
|
|
||||||
|
|
||||||
import awais.instagrabber.repositories.responses.User
|
|
||||||
import awais.instagrabber.utils.TextUtils
|
|
||||||
import java.io.Serializable
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
data class FeedStoryModel(
|
|
||||||
val storyMediaId: String,
|
|
||||||
val profileModel: User,
|
|
||||||
var isFullyRead: Boolean,
|
|
||||||
val timestamp: Long,
|
|
||||||
val firstStoryModel: StoryModel?,
|
|
||||||
val mediaCount: Int,
|
|
||||||
val isLive: Boolean,
|
|
||||||
val isBestie: Boolean
|
|
||||||
) : Serializable {
|
|
||||||
val dateTime: String
|
|
||||||
get() = TextUtils.epochSecondToString(timestamp)
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
package awais.instagrabber.models
|
|
||||||
|
|
||||||
import awais.instagrabber.utils.TextUtils
|
|
||||||
|
|
||||||
data class HighlightModel(
|
|
||||||
val title: String? = null,
|
|
||||||
val id: String = "",
|
|
||||||
val thumbnailUrl: String = "",
|
|
||||||
val timestamp: Long = 0,
|
|
||||||
val mediaCount: Int = 0,
|
|
||||||
) {
|
|
||||||
val dateTime: String
|
|
||||||
get() = TextUtils.epochSecondToString(timestamp)
|
|
||||||
}
|
|
@ -1,6 +1,8 @@
|
|||||||
package awais.instagrabber.repositories
|
package awais.instagrabber.repositories
|
||||||
|
|
||||||
import awais.instagrabber.repositories.responses.StoryStickerResponse
|
import awais.instagrabber.repositories.responses.stories.ArchiveResponse
|
||||||
|
import awais.instagrabber.repositories.responses.stories.ReelsTrayResponse
|
||||||
|
import awais.instagrabber.repositories.responses.stories.StoryStickerResponse
|
||||||
import retrofit2.http.*
|
import retrofit2.http.*
|
||||||
|
|
||||||
interface StoriesService {
|
interface StoriesService {
|
||||||
@ -9,13 +11,13 @@ interface StoriesService {
|
|||||||
suspend fun fetch(@Path("mediaId") mediaId: Long): String
|
suspend fun fetch(@Path("mediaId") mediaId: Long): String
|
||||||
|
|
||||||
@GET("/api/v1/feed/reels_tray/")
|
@GET("/api/v1/feed/reels_tray/")
|
||||||
suspend fun getFeedStories(): String
|
suspend fun getFeedStories(): ReelsTrayResponse?
|
||||||
|
|
||||||
@GET("/api/v1/highlights/{uid}/highlights_tray/")
|
@GET("/api/v1/highlights/{uid}/highlights_tray/")
|
||||||
suspend fun fetchHighlights(@Path("uid") uid: Long): String
|
suspend fun fetchHighlights(@Path("uid") uid: Long): ReelsTrayResponse?
|
||||||
|
|
||||||
@GET("/api/v1/archive/reel/day_shells/")
|
@GET("/api/v1/archive/reel/day_shells/")
|
||||||
suspend fun fetchArchive(@QueryMap queryParams: Map<String, String>): String
|
suspend fun fetchArchive(@QueryMap queryParams: Map<String, String>): ArchiveResponse?
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
suspend fun getUserStory(@Url url: String): String
|
suspend fun getUserStory(@Url url: String): String
|
||||||
|
@ -5,12 +5,16 @@ import awais.instagrabber.models.enums.BroadcastItemType
|
|||||||
class MediaShareBroadcastOptions(
|
class MediaShareBroadcastOptions(
|
||||||
clientContext: String,
|
clientContext: String,
|
||||||
threadIdsOrUserIds: ThreadIdsOrUserIds,
|
threadIdsOrUserIds: ThreadIdsOrUserIds,
|
||||||
val mediaId: String
|
val mediaId: String,
|
||||||
|
val childId: String?
|
||||||
) : BroadcastOptions(
|
) : BroadcastOptions(
|
||||||
clientContext,
|
clientContext,
|
||||||
threadIdsOrUserIds,
|
threadIdsOrUserIds,
|
||||||
BroadcastItemType.MEDIA_SHARE
|
BroadcastItemType.MEDIA_SHARE
|
||||||
) {
|
) {
|
||||||
override val formMap: Map<String, String>
|
override val formMap: Map<String, String>
|
||||||
get() = mapOf("media_id" to mediaId)
|
get() = listOfNotNull(
|
||||||
|
"media_id" to mediaId,
|
||||||
|
if (childId != null) "carousel_share_child_media_id" to childId else null
|
||||||
|
).toMap()
|
||||||
}
|
}
|
@ -1,16 +0,0 @@
|
|||||||
package awais.instagrabber.repositories.responses;
|
|
||||||
|
|
||||||
public class HdProfilePicUrlInfo {
|
|
||||||
private final String url;
|
|
||||||
private final int width, height;
|
|
||||||
|
|
||||||
public HdProfilePicUrlInfo(final String url, final int width, final int height) {
|
|
||||||
this.url = url;
|
|
||||||
this.width = width;
|
|
||||||
this.height = height;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUrl() {
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,5 @@
|
|||||||
|
package awais.instagrabber.repositories.responses
|
||||||
|
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
|
data class ImageUrl(val url: String, private val width: Int, private val height: Int) : Serializable
|
@ -1,30 +0,0 @@
|
|||||||
package awais.instagrabber.repositories.responses;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public class ImageVersions2 implements Serializable {
|
|
||||||
private final List<MediaCandidate> candidates;
|
|
||||||
|
|
||||||
public ImageVersions2(final List<MediaCandidate> candidates) {
|
|
||||||
this.candidates = candidates;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<MediaCandidate> getCandidates() {
|
|
||||||
return candidates;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(final Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
final ImageVersions2 that = (ImageVersions2) o;
|
|
||||||
return Objects.equals(candidates, that.candidates);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(candidates);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,5 @@
|
|||||||
|
package awais.instagrabber.repositories.responses
|
||||||
|
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
|
data class ImageVersions2(val candidates: List<MediaCandidate>) : Serializable
|
@ -1,27 +0,0 @@
|
|||||||
package awais.instagrabber.repositories.responses;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class LikersResponse {
|
|
||||||
private final List<User> users;
|
|
||||||
private final long userCount;
|
|
||||||
private final String status;
|
|
||||||
|
|
||||||
public LikersResponse(final List<User> users, final long userCount, final String status) {
|
|
||||||
this.users = users;
|
|
||||||
this.userCount = userCount;
|
|
||||||
this.status = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<User> getUsers() {
|
|
||||||
return users;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getUserCount() {
|
|
||||||
return userCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getStatus() {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,3 @@
|
|||||||
|
package awais.instagrabber.repositories.responses
|
||||||
|
|
||||||
|
data class LikersResponse(val users: List<User>, val userCount: Long, val status: String)
|
@ -4,7 +4,6 @@ import awais.instagrabber.models.enums.MediaItemType
|
|||||||
import awais.instagrabber.repositories.responses.feed.EndOfFeedDemarcator
|
import awais.instagrabber.repositories.responses.feed.EndOfFeedDemarcator
|
||||||
import awais.instagrabber.utils.TextUtils
|
import awais.instagrabber.utils.TextUtils
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
data class Media(
|
data class Media(
|
||||||
val pk: String? = null,
|
val pk: String? = null,
|
||||||
@ -38,7 +37,8 @@ data class Media(
|
|||||||
var isSidecarChild: Boolean = false,
|
var isSidecarChild: Boolean = false,
|
||||||
var hasViewerSaved: Boolean = false,
|
var hasViewerSaved: Boolean = false,
|
||||||
private val injected: Map<String, Any>? = null,
|
private val injected: Map<String, Any>? = null,
|
||||||
val endOfFeedDemarcator: EndOfFeedDemarcator? = null
|
val endOfFeedDemarcator: EndOfFeedDemarcator? = null,
|
||||||
|
val carouselShareChildMediaId: String? = null // which specific child should dm show first
|
||||||
) : Serializable {
|
) : Serializable {
|
||||||
private var dateString: String? = null
|
private var dateString: String? = null
|
||||||
|
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
package awais.instagrabber.repositories.responses;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public class MediaCandidate implements Serializable {
|
|
||||||
private final int width;
|
|
||||||
private final int height;
|
|
||||||
private final String url;
|
|
||||||
|
|
||||||
public MediaCandidate(final int width, final int height, final String url) {
|
|
||||||
this.width = width;
|
|
||||||
this.height = height;
|
|
||||||
this.url = url;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getWidth() {
|
|
||||||
return width;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getHeight() {
|
|
||||||
return height;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUrl() {
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(final Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
final MediaCandidate that = (MediaCandidate) o;
|
|
||||||
return width == that.width &&
|
|
||||||
height == that.height &&
|
|
||||||
Objects.equals(url, that.url);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(width, height, url);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,5 @@
|
|||||||
|
package awais.instagrabber.repositories.responses
|
||||||
|
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
|
data class MediaCandidate(val width: Int, val height: Int, val url: String) : Serializable
|
@ -1,15 +0,0 @@
|
|||||||
package awais.instagrabber.repositories.responses;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class MediaInfoResponse {
|
|
||||||
private final List<Media> items;
|
|
||||||
|
|
||||||
public MediaInfoResponse(final List<Media> items) {
|
|
||||||
this.items = items;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Media> getItems() {
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,3 @@
|
|||||||
|
package awais.instagrabber.repositories.responses
|
||||||
|
|
||||||
|
data class MediaInfoResponse(val items: List<Media>)
|
@ -1,32 +0,0 @@
|
|||||||
package awais.instagrabber.repositories.responses;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import awais.instagrabber.repositories.responses.notification.Notification;
|
|
||||||
import awais.instagrabber.repositories.responses.notification.NotificationCounts;
|
|
||||||
|
|
||||||
public class NewsInboxResponse {
|
|
||||||
private final NotificationCounts counts;
|
|
||||||
private final List<Notification> newStories;
|
|
||||||
private final List<Notification> oldStories;
|
|
||||||
|
|
||||||
public NewsInboxResponse(final NotificationCounts counts,
|
|
||||||
final List<Notification> newStories,
|
|
||||||
final List<Notification> oldStories) {
|
|
||||||
this.counts = counts;
|
|
||||||
this.newStories = newStories;
|
|
||||||
this.oldStories = oldStories;
|
|
||||||
}
|
|
||||||
|
|
||||||
public NotificationCounts getCounts() {
|
|
||||||
return counts;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Notification> getNewStories() {
|
|
||||||
return newStories;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Notification> getOldStories() {
|
|
||||||
return oldStories;
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,10 @@
|
|||||||
|
package awais.instagrabber.repositories.responses
|
||||||
|
|
||||||
|
import awais.instagrabber.repositories.responses.notification.Notification
|
||||||
|
import awais.instagrabber.repositories.responses.notification.NotificationCounts
|
||||||
|
|
||||||
|
data class NewsInboxResponse(
|
||||||
|
val counts: NotificationCounts,
|
||||||
|
val newStories: List<Notification>,
|
||||||
|
val oldStories: List<Notification>
|
||||||
|
)
|
@ -1,62 +0,0 @@
|
|||||||
package awais.instagrabber.repositories.responses;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public class Place {
|
|
||||||
private final Location location;
|
|
||||||
// for search
|
|
||||||
private final String title; // those are repeated within location
|
|
||||||
private final String subtitle; // address
|
|
||||||
private final String slug; // browser only; for end of address
|
|
||||||
// for location info
|
|
||||||
private final String status;
|
|
||||||
|
|
||||||
public Place(final Location location,
|
|
||||||
final String title,
|
|
||||||
final String subtitle,
|
|
||||||
final String slug,
|
|
||||||
final String status) {
|
|
||||||
this.location = location;
|
|
||||||
this.title = title;
|
|
||||||
this.subtitle = subtitle;
|
|
||||||
this.slug = slug;
|
|
||||||
this.status = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Location getLocation() {
|
|
||||||
return location;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTitle() {
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSubtitle() {
|
|
||||||
return subtitle;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSlug() {
|
|
||||||
return slug;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getStatus() {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(final Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
final Place place = (Place) o;
|
|
||||||
return Objects.equals(location, place.location) &&
|
|
||||||
Objects.equals(title, place.title) &&
|
|
||||||
Objects.equals(subtitle, place.subtitle) &&
|
|
||||||
Objects.equals(slug, place.slug) &&
|
|
||||||
Objects.equals(status, place.status);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(location, title, subtitle, slug, status);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,12 @@
|
|||||||
|
package awais.instagrabber.repositories.responses
|
||||||
|
|
||||||
|
data class Place(
|
||||||
|
val location: Location,
|
||||||
|
// for search
|
||||||
|
val title: String, // those are repeated within location
|
||||||
|
val subtitle: String?, // address
|
||||||
|
// browser only; for end of address
|
||||||
|
val slug: String?,
|
||||||
|
// for location info
|
||||||
|
val status: String?
|
||||||
|
)
|
@ -1,27 +0,0 @@
|
|||||||
package awais.instagrabber.repositories.responses;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class PostsFetchResponse {
|
|
||||||
private final List<Media> feedModels;
|
|
||||||
private final boolean hasNextPage;
|
|
||||||
private final String nextCursor;
|
|
||||||
|
|
||||||
public PostsFetchResponse(final List<Media> feedModels, final boolean hasNextPage, final String nextCursor) {
|
|
||||||
this.feedModels = feedModels;
|
|
||||||
this.hasNextPage = hasNextPage;
|
|
||||||
this.nextCursor = nextCursor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Media> getFeedModels() {
|
|
||||||
return feedModels;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasNextPage() {
|
|
||||||
return hasNextPage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getNextCursor() {
|
|
||||||
return nextCursor;
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,7 @@
|
|||||||
|
package awais.instagrabber.repositories.responses
|
||||||
|
|
||||||
|
class PostsFetchResponse(
|
||||||
|
val feedModels: List<Media>,
|
||||||
|
val hasNextPage: Boolean,
|
||||||
|
val nextCursor: String?
|
||||||
|
)
|
@ -1,20 +0,0 @@
|
|||||||
package awais.instagrabber.repositories.responses;
|
|
||||||
|
|
||||||
public class StoryStickerResponse {
|
|
||||||
private final String status;
|
|
||||||
|
|
||||||
public StoryStickerResponse(final String status) {
|
|
||||||
this.status = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getStatus() {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "StoryStickerResponse{" +
|
|
||||||
"status='" + status + '\'' +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
package awais.instagrabber.repositories.responses;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class TagFeedResponse {
|
|
||||||
private final int numResults;
|
|
||||||
private final String nextMaxId;
|
|
||||||
private final boolean moreAvailable;
|
|
||||||
private final String status;
|
|
||||||
private final List<Media> items;
|
|
||||||
|
|
||||||
public TagFeedResponse(final int numResults,
|
|
||||||
final String nextMaxId,
|
|
||||||
final boolean moreAvailable,
|
|
||||||
final String status,
|
|
||||||
final List<Media> items) {
|
|
||||||
this.numResults = numResults;
|
|
||||||
this.nextMaxId = nextMaxId;
|
|
||||||
this.moreAvailable = moreAvailable;
|
|
||||||
this.status = status;
|
|
||||||
this.items = items;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getNumResults() {
|
|
||||||
return numResults;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getNextMaxId() {
|
|
||||||
return nextMaxId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isMoreAvailable() {
|
|
||||||
return moreAvailable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getStatus() {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Media> getItems() {
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,9 @@
|
|||||||
|
package awais.instagrabber.repositories.responses
|
||||||
|
|
||||||
|
class TagFeedResponse(
|
||||||
|
val numResults: Int,
|
||||||
|
val nextMaxId: String?,
|
||||||
|
val moreAvailable: Boolean,
|
||||||
|
val status: String,
|
||||||
|
val items: List<Media>
|
||||||
|
)
|
@ -27,7 +27,7 @@ data class User @JvmOverloads constructor(
|
|||||||
val externalUrl: String? = null,
|
val externalUrl: String? = null,
|
||||||
val usertagsCount: Long = 0,
|
val usertagsCount: Long = 0,
|
||||||
val publicEmail: String? = null,
|
val publicEmail: String? = null,
|
||||||
val hdProfilePicUrlInfo: HdProfilePicUrlInfo? = null,
|
val hdProfilePicUrlInfo: ImageUrl? = null,
|
||||||
val profileContext: String? = null, // "also followed by" your friends
|
val profileContext: String? = null, // "also followed by" your friends
|
||||||
val profileContextLinksWithUserIds: List<UserProfileContextLink>? = null, // ^
|
val profileContextLinksWithUserIds: List<UserProfileContextLink>? = null, // ^
|
||||||
val socialContext: String? = null, // AYML
|
val socialContext: String? = null, // AYML
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
package awais.instagrabber.repositories.responses;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class UserFeedResponse {
|
|
||||||
private final int numResults;
|
|
||||||
private final String nextMaxId;
|
|
||||||
private final boolean moreAvailable;
|
|
||||||
private final String status;
|
|
||||||
private final List<Media> items;
|
|
||||||
|
|
||||||
public UserFeedResponse(final int numResults,
|
|
||||||
final String nextMaxId,
|
|
||||||
final boolean moreAvailable,
|
|
||||||
final String status,
|
|
||||||
final List<Media> items) {
|
|
||||||
this.numResults = numResults;
|
|
||||||
this.nextMaxId = nextMaxId;
|
|
||||||
this.moreAvailable = moreAvailable;
|
|
||||||
this.status = status;
|
|
||||||
this.items = items;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getNumResults() {
|
|
||||||
return numResults;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getNextMaxId() {
|
|
||||||
return nextMaxId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isMoreAvailable() {
|
|
||||||
return moreAvailable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getStatus() {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Media> getItems() {
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,9 @@
|
|||||||
|
package awais.instagrabber.repositories.responses
|
||||||
|
|
||||||
|
class UserFeedResponse(
|
||||||
|
val numResults: Int,
|
||||||
|
val nextMaxId: String?,
|
||||||
|
val moreAvailable: Boolean,
|
||||||
|
val status: String,
|
||||||
|
val items: List<Media>
|
||||||
|
)
|
@ -1,13 +0,0 @@
|
|||||||
package awais.instagrabber.repositories.responses;
|
|
||||||
|
|
||||||
public class WrappedMedia {
|
|
||||||
private final Media media;
|
|
||||||
|
|
||||||
public WrappedMedia(final Media media) {
|
|
||||||
this.media = media;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Media getMedia() {
|
|
||||||
return media;
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,3 @@
|
|||||||
|
package awais.instagrabber.repositories.responses
|
||||||
|
|
||||||
|
class WrappedMedia(val media: Media)
|
@ -0,0 +1,9 @@
|
|||||||
|
package awais.instagrabber.repositories.responses.stories
|
||||||
|
|
||||||
|
data class ArchiveResponse(
|
||||||
|
val numResults: Int,
|
||||||
|
val maxId: String?,
|
||||||
|
val moreAvailable: Boolean,
|
||||||
|
val status: String,
|
||||||
|
val items: List<Story>
|
||||||
|
)
|
@ -1,10 +1,10 @@
|
|||||||
package awais.instagrabber.repositories.responses.stories
|
package awais.instagrabber.repositories.responses.stories
|
||||||
|
|
||||||
import java.io.Serializable
|
|
||||||
import awais.instagrabber.repositories.responses.User
|
import awais.instagrabber.repositories.responses.User
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
data class Broadcast(
|
data class Broadcast(
|
||||||
val id: Long?,
|
val id: String?,
|
||||||
val dashPlaybackUrl: String?,
|
val dashPlaybackUrl: String?,
|
||||||
val dashAbrPlaybackUrl: String?, // adaptive quality
|
val dashAbrPlaybackUrl: String?, // adaptive quality
|
||||||
val viewerCount: Double?, // always .0
|
val viewerCount: Double?, // always .0
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
package awais.instagrabber.repositories.responses.stories
|
||||||
|
|
||||||
|
import awais.instagrabber.repositories.responses.ImageUrl
|
||||||
|
|
||||||
|
data class CoverMedia(val croppedImageVersion: ImageUrl)
|
@ -1,16 +1,31 @@
|
|||||||
package awais.instagrabber.repositories.responses.stories
|
package awais.instagrabber.repositories.responses.stories
|
||||||
|
|
||||||
import java.io.Serializable
|
import awais.instagrabber.repositories.responses.ImageUrl
|
||||||
import awais.instagrabber.repositories.responses.Media
|
|
||||||
import awais.instagrabber.repositories.responses.User
|
import awais.instagrabber.repositories.responses.User
|
||||||
|
import awais.instagrabber.utils.TextUtils
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
data class Story(
|
data class Story(
|
||||||
val id: Long?,
|
// universal
|
||||||
val latestReelMedia: Long?, // = timestamp
|
val id: String? = null,
|
||||||
val seen: Long?,
|
val latestReelMedia: Long? = null, // = timestamp
|
||||||
val user: User?,
|
val mediaCount: Int? = null,
|
||||||
val muted: Boolean?,
|
// for stories and highlights
|
||||||
val hasBestiesMedia: Boolean?,
|
var seen: Long? = null,
|
||||||
val mediaCount: Int?,
|
val user: User? = null,
|
||||||
val items: List<Media>? // may be null
|
// for stories
|
||||||
) : Serializable
|
val muted: Boolean? = null,
|
||||||
|
val hasBestiesMedia: Boolean? = null,
|
||||||
|
val items: List<StoryMedia>? = null, // may be null
|
||||||
|
// for highlights
|
||||||
|
val coverMedia: CoverMedia? = null,
|
||||||
|
val title: String? = null,
|
||||||
|
// for archives
|
||||||
|
val coverImageVersion: ImageUrl? = null,
|
||||||
|
// invented fields
|
||||||
|
val broadcast: Broadcast? = null, // does not naturally occur
|
||||||
|
) : Serializable {
|
||||||
|
val dateTime: String
|
||||||
|
get() = if (latestReelMedia != null) TextUtils.epochSecondToString(latestReelMedia) else ""
|
||||||
|
// note that archives have property "timestamp" but is ignored
|
||||||
|
}
|
@ -1,12 +1,11 @@
|
|||||||
package awais.instagrabber.repositories.responses.stories
|
package awais.instagrabber.repositories.responses.stories
|
||||||
|
|
||||||
import awais.instagrabber.models.enums.MediaItemType
|
import awais.instagrabber.models.enums.MediaItemType
|
||||||
import awais.instagrabber.utils.TextUtils
|
|
||||||
import awais.instagrabber.repositories.responses.ImageVersions2
|
import awais.instagrabber.repositories.responses.ImageVersions2
|
||||||
import awais.instagrabber.repositories.responses.User
|
|
||||||
import awais.instagrabber.repositories.responses.MediaCandidate
|
import awais.instagrabber.repositories.responses.MediaCandidate
|
||||||
|
import awais.instagrabber.repositories.responses.User
|
||||||
|
import awais.instagrabber.utils.TextUtils
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
data class StoryMedia(
|
data class StoryMedia(
|
||||||
// inherited from Media
|
// inherited from Media
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
package awais.instagrabber.repositories.responses.stories
|
||||||
|
|
||||||
|
data class StoryStickerResponse(val status: String?)
|
@ -1,6 +1,5 @@
|
|||||||
package awais.instagrabber.utils
|
package awais.instagrabber.utils
|
||||||
|
|
||||||
import android.Manifest
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
import android.content.UriPermission
|
import android.content.UriPermission
|
||||||
@ -38,8 +37,6 @@ object DownloadUtils {
|
|||||||
private const val DIR_TEMP = "Temp"
|
private const val DIR_TEMP = "Temp"
|
||||||
private const val DIR_BACKUPS = "Backups"
|
private const val DIR_BACKUPS = "Backups"
|
||||||
private var root: DocumentFile? = null
|
private var root: DocumentFile? = null
|
||||||
const val WRITE_PERMISSION = Manifest.permission.WRITE_EXTERNAL_STORAGE
|
|
||||||
val PERMS = arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@Throws(ReselectDocumentTreeException::class)
|
@Throws(ReselectDocumentTreeException::class)
|
||||||
fun init(
|
fun init(
|
||||||
@ -49,11 +46,11 @@ object DownloadUtils {
|
|||||||
if (isEmpty(barinstaDirUri)) {
|
if (isEmpty(barinstaDirUri)) {
|
||||||
throw ReselectDocumentTreeException("folder path is null or empty")
|
throw ReselectDocumentTreeException("folder path is null or empty")
|
||||||
}
|
}
|
||||||
|
val uri = Uri.parse(barinstaDirUri)
|
||||||
if (!barinstaDirUri!!.startsWith("content://com.android.externalstorage.documents")) {
|
if (!barinstaDirUri!!.startsWith("content://com.android.externalstorage.documents")) {
|
||||||
// reselect the folder in selector view
|
// reselect the folder in selector view
|
||||||
throw ReselectDocumentTreeException(Uri.parse(barinstaDirUri))
|
throw ReselectDocumentTreeException(uri)
|
||||||
}
|
}
|
||||||
val uri = Uri.parse(barinstaDirUri)
|
|
||||||
val existingPermissions = context.contentResolver.persistedUriPermissions
|
val existingPermissions = context.contentResolver.persistedUriPermissions
|
||||||
if (existingPermissions.isEmpty()) {
|
if (existingPermissions.isEmpty()) {
|
||||||
// reselect the folder in selector view
|
// reselect the folder in selector view
|
||||||
@ -150,7 +147,7 @@ object DownloadUtils {
|
|||||||
list.add(DIR_DOWNLOADS)
|
list.add(DIR_DOWNLOADS)
|
||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
val finalUsername = if (username!!.startsWith("@")) username.substring(1) else username
|
val finalUsername = if (username.startsWith("@")) username.substring(1) else username
|
||||||
list.add(DIR_DOWNLOADS)
|
list.add(DIR_DOWNLOADS)
|
||||||
list.add(finalUsername)
|
list.add(finalUsername)
|
||||||
return list
|
return list
|
||||||
@ -337,7 +334,7 @@ object DownloadUtils {
|
|||||||
|
|
||||||
private fun checkPathExists(paths: List<String>, context: Context): Boolean {
|
private fun checkPathExists(paths: List<String>, context: Context): Boolean {
|
||||||
if (root == null) return false
|
if (root == null) return false
|
||||||
val uri = root!!.getUri()
|
val uri = root!!.uri
|
||||||
var found = false
|
var found = false
|
||||||
var docId = DocumentsContract.getTreeDocumentId(uri)
|
var docId = DocumentsContract.getTreeDocumentId(uri)
|
||||||
for (path in paths) {
|
for (path in paths) {
|
||||||
@ -349,7 +346,7 @@ object DownloadUtils {
|
|||||||
), null, null, null
|
), null, null, null
|
||||||
)
|
)
|
||||||
if (docCursor == null) return false
|
if (docCursor == null) return false
|
||||||
while (docCursor!!.moveToNext() && !found) {
|
while (docCursor.moveToNext() && !found) {
|
||||||
if (path.equals(docCursor.getString(0))) {
|
if (path.equals(docCursor.getString(0))) {
|
||||||
docId = docCursor.getString(1)
|
docId = docCursor.getString(1)
|
||||||
found = true
|
found = true
|
||||||
|
@ -1,386 +0,0 @@
|
|||||||
package awais.instagrabber.utils;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.database.Cursor;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Environment;
|
|
||||||
import android.provider.MediaStore;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.util.SparseArray;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
import awais.instagrabber.R;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is the source code of Telegram for Android v. 1.3.x.
|
|
||||||
* It is licensed under GNU GPL v. 2 or later.
|
|
||||||
* You should have received a copy of the license in this archive (see LICENSE).
|
|
||||||
*
|
|
||||||
* Copyright Nikolai Kudashov, 2013-2018.
|
|
||||||
*/
|
|
||||||
public class MediaController {
|
|
||||||
private static final String TAG = MediaController.class.getSimpleName();
|
|
||||||
private static final String[] PROJECTION_PHOTOS = {
|
|
||||||
MediaStore.Images.Media._ID,
|
|
||||||
MediaStore.Images.Media.BUCKET_ID,
|
|
||||||
MediaStore.Images.Media.BUCKET_DISPLAY_NAME,
|
|
||||||
MediaStore.Images.Media.DATA,
|
|
||||||
Build.VERSION.SDK_INT > 28 ? MediaStore.Images.Media.DATE_TAKEN : MediaStore.Images.Media.DATE_MODIFIED,
|
|
||||||
MediaStore.Images.Media.ORIENTATION,
|
|
||||||
MediaStore.Images.Media.WIDTH,
|
|
||||||
MediaStore.Images.Media.HEIGHT,
|
|
||||||
MediaStore.Images.Media.SIZE
|
|
||||||
};
|
|
||||||
private static final String[] PROJECTION_VIDEO = {
|
|
||||||
MediaStore.Video.Media._ID,
|
|
||||||
MediaStore.Video.Media.BUCKET_ID,
|
|
||||||
MediaStore.Video.Media.BUCKET_DISPLAY_NAME,
|
|
||||||
MediaStore.Video.Media.DATA,
|
|
||||||
Build.VERSION.SDK_INT > 28 ? MediaStore.Video.Media.DATE_TAKEN : MediaStore.Images.Media.DATE_MODIFIED,
|
|
||||||
MediaStore.Video.Media.DURATION,
|
|
||||||
MediaStore.Video.Media.WIDTH,
|
|
||||||
MediaStore.Video.Media.HEIGHT,
|
|
||||||
MediaStore.Video.Media.SIZE
|
|
||||||
};
|
|
||||||
|
|
||||||
private final Context context;
|
|
||||||
private final OnLoadListener onLoadListener;
|
|
||||||
private final AppExecutors appExecutors;
|
|
||||||
|
|
||||||
private static Runnable broadcastPhotosRunnable;
|
|
||||||
|
|
||||||
private ArrayList<AlbumEntry> allMediaAlbums;
|
|
||||||
private ArrayList<AlbumEntry> allPhotoAlbums;
|
|
||||||
private AlbumEntry allPhotosAlbumEntry;
|
|
||||||
private AlbumEntry allMediaAlbumEntry;
|
|
||||||
private AlbumEntry allVideosAlbumEntry;
|
|
||||||
|
|
||||||
public MediaController(final Context context, final OnLoadListener onLoadListener) {
|
|
||||||
this.context = context;
|
|
||||||
this.onLoadListener = onLoadListener;
|
|
||||||
appExecutors = AppExecutors.INSTANCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void load() {
|
|
||||||
loadGalleryAlbums();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadGalleryAlbums() {
|
|
||||||
final Thread thread = new Thread(() -> {
|
|
||||||
final ArrayList<AlbumEntry> mediaAlbumsSorted = new ArrayList<>();
|
|
||||||
final ArrayList<AlbumEntry> photoAlbumsSorted = new ArrayList<>();
|
|
||||||
SparseArray<AlbumEntry> mediaAlbums = new SparseArray<>();
|
|
||||||
SparseArray<AlbumEntry> photoAlbums = new SparseArray<>();
|
|
||||||
AlbumEntry allPhotosAlbum = null;
|
|
||||||
AlbumEntry allVideosAlbum = null;
|
|
||||||
AlbumEntry allMediaAlbum = null;
|
|
||||||
String cameraFolder = null;
|
|
||||||
try {
|
|
||||||
cameraFolder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getAbsolutePath() + "/" + "Camera/";
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, "loadGalleryAlbums: ", e);
|
|
||||||
}
|
|
||||||
Integer mediaCameraAlbumId = null;
|
|
||||||
Integer photoCameraAlbumId = null;
|
|
||||||
|
|
||||||
Cursor cursor = null;
|
|
||||||
try {
|
|
||||||
if (PermissionUtils.hasAttachMediaPerms(context)) {
|
|
||||||
cursor = MediaStore.Images.Media.query(context.getContentResolver(),
|
|
||||||
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
|
|
||||||
PROJECTION_PHOTOS,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
(Build.VERSION.SDK_INT > 28
|
|
||||||
? MediaStore.Images.Media.DATE_TAKEN
|
|
||||||
: MediaStore.Images.Media.DATE_MODIFIED) + " DESC");
|
|
||||||
if (cursor != null) {
|
|
||||||
int imageIdColumn = cursor.getColumnIndex(MediaStore.Images.Media._ID);
|
|
||||||
int bucketIdColumn = cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_ID);
|
|
||||||
int bucketNameColumn = cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_DISPLAY_NAME);
|
|
||||||
int dataColumn = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
|
|
||||||
int dateColumn = cursor.getColumnIndex(Build.VERSION.SDK_INT > 28 ? MediaStore.Images.Media.DATE_TAKEN
|
|
||||||
: MediaStore.Images.Media.DATE_MODIFIED);
|
|
||||||
int orientationColumn = cursor.getColumnIndex(MediaStore.Images.Media.ORIENTATION);
|
|
||||||
int widthColumn = cursor.getColumnIndex(MediaStore.Images.Media.WIDTH);
|
|
||||||
int heightColumn = cursor.getColumnIndex(MediaStore.Images.Media.HEIGHT);
|
|
||||||
int sizeColumn = cursor.getColumnIndex(MediaStore.Images.Media.SIZE);
|
|
||||||
|
|
||||||
while (cursor.moveToNext()) {
|
|
||||||
String path = cursor.getString(dataColumn);
|
|
||||||
if (TextUtils.isEmpty(path)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int imageId = cursor.getInt(imageIdColumn);
|
|
||||||
int bucketId = cursor.getInt(bucketIdColumn);
|
|
||||||
String bucketName = cursor.getString(bucketNameColumn);
|
|
||||||
long dateTaken = cursor.getLong(dateColumn);
|
|
||||||
int orientation = cursor.getInt(orientationColumn);
|
|
||||||
int width = cursor.getInt(widthColumn);
|
|
||||||
int height = cursor.getInt(heightColumn);
|
|
||||||
long size = cursor.getLong(sizeColumn);
|
|
||||||
|
|
||||||
MediaEntry mediaEntry = new MediaEntry(bucketId, imageId, dateTaken, path, orientation, -1, false, width, height, size);
|
|
||||||
|
|
||||||
if (allPhotosAlbum == null) {
|
|
||||||
allPhotosAlbum = new AlbumEntry(0, context.getString(R.string.all_photos), mediaEntry);
|
|
||||||
photoAlbumsSorted.add(0, allPhotosAlbum);
|
|
||||||
}
|
|
||||||
if (allMediaAlbum == null) {
|
|
||||||
allMediaAlbum = new AlbumEntry(0, context.getString(R.string.all_media), mediaEntry);
|
|
||||||
mediaAlbumsSorted.add(0, allMediaAlbum);
|
|
||||||
}
|
|
||||||
allPhotosAlbum.addPhoto(mediaEntry);
|
|
||||||
allMediaAlbum.addPhoto(mediaEntry);
|
|
||||||
|
|
||||||
AlbumEntry albumEntry = mediaAlbums.get(bucketId);
|
|
||||||
if (albumEntry == null) {
|
|
||||||
albumEntry = new AlbumEntry(bucketId, bucketName, mediaEntry);
|
|
||||||
mediaAlbums.put(bucketId, albumEntry);
|
|
||||||
if (mediaCameraAlbumId == null && cameraFolder != null && path.startsWith(cameraFolder)) {
|
|
||||||
mediaAlbumsSorted.add(0, albumEntry);
|
|
||||||
mediaCameraAlbumId = bucketId;
|
|
||||||
} else {
|
|
||||||
mediaAlbumsSorted.add(albumEntry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
albumEntry.addPhoto(mediaEntry);
|
|
||||||
|
|
||||||
albumEntry = photoAlbums.get(bucketId);
|
|
||||||
if (albumEntry == null) {
|
|
||||||
albumEntry = new AlbumEntry(bucketId, bucketName, mediaEntry);
|
|
||||||
photoAlbums.put(bucketId, albumEntry);
|
|
||||||
if (photoCameraAlbumId == null && cameraFolder != null && path.startsWith(cameraFolder)) {
|
|
||||||
photoAlbumsSorted.add(0, albumEntry);
|
|
||||||
photoCameraAlbumId = bucketId;
|
|
||||||
} else {
|
|
||||||
photoAlbumsSorted.add(albumEntry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
albumEntry.addPhoto(mediaEntry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
|
||||||
Log.e(TAG, "loadGalleryAlbums: ", e);
|
|
||||||
} finally {
|
|
||||||
if (cursor != null) {
|
|
||||||
try {
|
|
||||||
cursor.close();
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, "loadGalleryAlbums: ", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (PermissionUtils.hasAttachMediaPerms(context)) {
|
|
||||||
cursor = MediaStore.Images.Media.query(context.getContentResolver(),
|
|
||||||
MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
|
|
||||||
PROJECTION_VIDEO,
|
|
||||||
MediaStore.Video.Media.MIME_TYPE + "=?",
|
|
||||||
new String[]{"video/mp4"},
|
|
||||||
(Build.VERSION.SDK_INT > 28
|
|
||||||
? MediaStore.Video.Media.DATE_TAKEN
|
|
||||||
: MediaStore.Video.Media.DATE_MODIFIED) + " DESC");
|
|
||||||
if (cursor != null) {
|
|
||||||
int imageIdColumn = cursor.getColumnIndex(MediaStore.Video.Media._ID);
|
|
||||||
int bucketIdColumn = cursor.getColumnIndex(MediaStore.Video.Media.BUCKET_ID);
|
|
||||||
int bucketNameColumn = cursor.getColumnIndex(MediaStore.Video.Media.BUCKET_DISPLAY_NAME);
|
|
||||||
int dataColumn = cursor.getColumnIndex(MediaStore.Video.Media.DATA);
|
|
||||||
int dateColumn = cursor.getColumnIndex(Build.VERSION.SDK_INT > 28 ? MediaStore.Video.Media.DATE_TAKEN
|
|
||||||
: MediaStore.Video.Media.DATE_MODIFIED);
|
|
||||||
int durationColumn = cursor.getColumnIndex(MediaStore.Video.Media.DURATION);
|
|
||||||
int widthColumn = cursor.getColumnIndex(MediaStore.Video.Media.WIDTH);
|
|
||||||
int heightColumn = cursor.getColumnIndex(MediaStore.Video.Media.HEIGHT);
|
|
||||||
int sizeColumn = cursor.getColumnIndex(MediaStore.Video.Media.SIZE);
|
|
||||||
|
|
||||||
while (cursor.moveToNext()) {
|
|
||||||
String path = cursor.getString(dataColumn);
|
|
||||||
if (TextUtils.isEmpty(path)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int imageId = cursor.getInt(imageIdColumn);
|
|
||||||
int bucketId = cursor.getInt(bucketIdColumn);
|
|
||||||
String bucketName = cursor.getString(bucketNameColumn);
|
|
||||||
long dateTaken = cursor.getLong(dateColumn);
|
|
||||||
long duration = cursor.getLong(durationColumn);
|
|
||||||
int width = cursor.getInt(widthColumn);
|
|
||||||
int height = cursor.getInt(heightColumn);
|
|
||||||
long size = cursor.getLong(sizeColumn);
|
|
||||||
|
|
||||||
MediaEntry mediaEntry = new MediaEntry(bucketId, imageId, dateTaken, path, -1, duration, true, width, height, size);
|
|
||||||
|
|
||||||
if (allVideosAlbum == null) {
|
|
||||||
allVideosAlbum = new AlbumEntry(0, context.getString(R.string.all_videos), mediaEntry);
|
|
||||||
allVideosAlbum.videoOnly = true;
|
|
||||||
int index = 0;
|
|
||||||
if (allMediaAlbum != null) {
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
if (allPhotosAlbum != null) {
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
mediaAlbumsSorted.add(index, allVideosAlbum);
|
|
||||||
}
|
|
||||||
if (allMediaAlbum == null) {
|
|
||||||
allMediaAlbum = new AlbumEntry(0, context.getString(R.string.all_media), mediaEntry);
|
|
||||||
mediaAlbumsSorted.add(0, allMediaAlbum);
|
|
||||||
}
|
|
||||||
allVideosAlbum.addPhoto(mediaEntry);
|
|
||||||
allMediaAlbum.addPhoto(mediaEntry);
|
|
||||||
|
|
||||||
AlbumEntry albumEntry = mediaAlbums.get(bucketId);
|
|
||||||
if (albumEntry == null) {
|
|
||||||
albumEntry = new AlbumEntry(bucketId, bucketName, mediaEntry);
|
|
||||||
mediaAlbums.put(bucketId, albumEntry);
|
|
||||||
if (mediaCameraAlbumId == null && cameraFolder != null && path.startsWith(cameraFolder)) {
|
|
||||||
mediaAlbumsSorted.add(0, albumEntry);
|
|
||||||
mediaCameraAlbumId = bucketId;
|
|
||||||
} else {
|
|
||||||
mediaAlbumsSorted.add(albumEntry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
albumEntry.addPhoto(mediaEntry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
|
||||||
Log.e(TAG, "loadGalleryAlbums: ", e);
|
|
||||||
} finally {
|
|
||||||
if (cursor != null) {
|
|
||||||
try {
|
|
||||||
cursor.close();
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, "loadGalleryAlbums: ", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int a = 0; a < mediaAlbumsSorted.size(); a++) {
|
|
||||||
Collections.sort(mediaAlbumsSorted.get(a).photos, (o1, o2) -> {
|
|
||||||
if (o1.dateTaken < o2.dateTaken) {
|
|
||||||
return 1;
|
|
||||||
} else if (o1.dateTaken > o2.dateTaken) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
broadcastNewPhotos(mediaAlbumsSorted, photoAlbumsSorted, mediaCameraAlbumId, allMediaAlbum, allPhotosAlbum, allVideosAlbum, 0);
|
|
||||||
});
|
|
||||||
thread.setPriority(Thread.MIN_PRIORITY);
|
|
||||||
thread.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void broadcastNewPhotos(final ArrayList<AlbumEntry> mediaAlbumsSorted,
|
|
||||||
final ArrayList<AlbumEntry> photoAlbumsSorted,
|
|
||||||
final Integer cameraAlbumIdFinal,
|
|
||||||
final AlbumEntry allMediaAlbumFinal,
|
|
||||||
final AlbumEntry allPhotosAlbumFinal,
|
|
||||||
final AlbumEntry allVideosAlbumFinal,
|
|
||||||
int delay) {
|
|
||||||
if (broadcastPhotosRunnable != null) {
|
|
||||||
appExecutors.getMainThread().cancel(broadcastPhotosRunnable);
|
|
||||||
}
|
|
||||||
appExecutors.getMainThread().execute(broadcastPhotosRunnable = () -> {
|
|
||||||
allMediaAlbums = mediaAlbumsSorted;
|
|
||||||
allPhotoAlbums = photoAlbumsSorted;
|
|
||||||
broadcastPhotosRunnable = null;
|
|
||||||
allPhotosAlbumEntry = allPhotosAlbumFinal;
|
|
||||||
allMediaAlbumEntry = allMediaAlbumFinal;
|
|
||||||
allVideosAlbumEntry = allVideosAlbumFinal;
|
|
||||||
if (onLoadListener != null) {
|
|
||||||
onLoadListener.onLoad();
|
|
||||||
}
|
|
||||||
}, delay);
|
|
||||||
}
|
|
||||||
|
|
||||||
public AlbumEntry getAllMediaAlbumEntry() {
|
|
||||||
return allMediaAlbumEntry;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AlbumEntry getAllPhotosAlbumEntry() {
|
|
||||||
return allPhotosAlbumEntry;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AlbumEntry getAllVideosAlbumEntry() {
|
|
||||||
return allVideosAlbumEntry;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArrayList<AlbumEntry> getAllMediaAlbums() {
|
|
||||||
return allMediaAlbums;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArrayList<AlbumEntry> getAllPhotoAlbums() {
|
|
||||||
return allPhotoAlbums;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class AlbumEntry {
|
|
||||||
public int bucketId;
|
|
||||||
public boolean videoOnly;
|
|
||||||
public String bucketName;
|
|
||||||
public MediaEntry coverPhoto;
|
|
||||||
public ArrayList<MediaEntry> photos = new ArrayList<>();
|
|
||||||
public SparseArray<MediaEntry> photosByIds = new SparseArray<>();
|
|
||||||
|
|
||||||
public AlbumEntry(int bucketId, String bucketName, MediaEntry coverPhoto) {
|
|
||||||
this.bucketId = bucketId;
|
|
||||||
this.bucketName = bucketName;
|
|
||||||
this.coverPhoto = coverPhoto;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addPhoto(MediaEntry mediaEntry) {
|
|
||||||
photos.add(mediaEntry);
|
|
||||||
photosByIds.put(mediaEntry.imageId, mediaEntry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class MediaEntry {
|
|
||||||
public int bucketId;
|
|
||||||
public int imageId;
|
|
||||||
public long dateTaken;
|
|
||||||
public long duration;
|
|
||||||
public int width;
|
|
||||||
public int height;
|
|
||||||
public long size;
|
|
||||||
public String path;
|
|
||||||
public int orientation;
|
|
||||||
public boolean isVideo;
|
|
||||||
public boolean isMuted;
|
|
||||||
public boolean canDeleteAfter;
|
|
||||||
|
|
||||||
public MediaEntry(int bucketId,
|
|
||||||
int imageId,
|
|
||||||
long dateTaken,
|
|
||||||
String path,
|
|
||||||
int orientation,
|
|
||||||
long duration,
|
|
||||||
boolean isVideo,
|
|
||||||
int width,
|
|
||||||
int height,
|
|
||||||
long size) {
|
|
||||||
this.bucketId = bucketId;
|
|
||||||
this.imageId = imageId;
|
|
||||||
this.dateTaken = dateTaken;
|
|
||||||
this.path = path;
|
|
||||||
this.width = width;
|
|
||||||
this.height = height;
|
|
||||||
this.size = size;
|
|
||||||
if (isVideo) {
|
|
||||||
this.duration = duration;
|
|
||||||
} else {
|
|
||||||
this.orientation = orientation;
|
|
||||||
}
|
|
||||||
this.isVideo = isVideo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface OnLoadListener {
|
|
||||||
void onLoad();
|
|
||||||
}
|
|
||||||
}
|
|
@ -28,7 +28,7 @@ import awais.instagrabber.repositories.responses.Location;
|
|||||||
import awais.instagrabber.repositories.responses.Media;
|
import awais.instagrabber.repositories.responses.Media;
|
||||||
import awais.instagrabber.repositories.responses.MediaCandidate;
|
import awais.instagrabber.repositories.responses.MediaCandidate;
|
||||||
import awais.instagrabber.repositories.responses.User;
|
import awais.instagrabber.repositories.responses.User;
|
||||||
import awais.instagrabber.repositories.responses.MediaCandidate;
|
import awais.instagrabber.repositories.responses.stories.StoryMedia;
|
||||||
|
|
||||||
public final class ResponseBodyUtils {
|
public final class ResponseBodyUtils {
|
||||||
private static final String TAG = "ResponseBodyUtils";
|
private static final String TAG = "ResponseBodyUtils";
|
||||||
@ -271,6 +271,7 @@ public final class ResponseBodyUtils {
|
|||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
null,
|
null,
|
||||||
|
null,
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -405,27 +406,38 @@ public final class ResponseBodyUtils {
|
|||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getThumbUrl(final Media media) {
|
public static String getThumbUrl(final Object media) {
|
||||||
return getImageCandidate(media, CandidateType.THUMBNAIL);
|
return getImageCandidate(media, CandidateType.THUMBNAIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getImageUrl(final Media media) {
|
public static String getImageUrl(final Object media) {
|
||||||
return getImageCandidate(media, CandidateType.DOWNLOAD);
|
return getImageCandidate(media, CandidateType.DOWNLOAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getImageCandidate(final Media media, final CandidateType type) {
|
private static String getImageCandidate(final Object rawMedia, final CandidateType type) {
|
||||||
if (media == null) return null;
|
final ImageVersions2 imageVersions2;
|
||||||
final ImageVersions2 imageVersions2 = media.getImageVersions2();
|
final int originalWidth, originalHeight;
|
||||||
|
if (rawMedia instanceof StoryMedia) {
|
||||||
|
imageVersions2 = ((StoryMedia) rawMedia).getImageVersions2();
|
||||||
|
originalWidth = ((StoryMedia) rawMedia).getOriginalWidth();
|
||||||
|
originalHeight = ((StoryMedia) rawMedia).getOriginalHeight();
|
||||||
|
}
|
||||||
|
else if (rawMedia instanceof Media) {
|
||||||
|
imageVersions2 = ((Media) rawMedia).getImageVersions2();
|
||||||
|
originalWidth = ((Media) rawMedia).getOriginalWidth();
|
||||||
|
originalHeight = ((Media) rawMedia).getOriginalHeight();
|
||||||
|
}
|
||||||
|
else return null;
|
||||||
if (imageVersions2 == null) return null;
|
if (imageVersions2 == null) return null;
|
||||||
final List<MediaCandidate> candidates = imageVersions2.getCandidates();
|
final List<MediaCandidate> candidates = imageVersions2.getCandidates();
|
||||||
if (candidates == null || candidates.isEmpty()) return null;
|
if (candidates == null || candidates.isEmpty()) return null;
|
||||||
final boolean isSquare = Integer.compare(media.getOriginalWidth(), media.getOriginalHeight()) == 0;
|
final boolean isSquare = Integer.compare(originalWidth, originalHeight) == 0;
|
||||||
final List<MediaCandidate> sortedCandidates = candidates.stream()
|
final List<MediaCandidate> sortedCandidates = candidates.stream()
|
||||||
.sorted((c1, c2) -> Integer.compare(c2.getWidth(), c1.getWidth()))
|
.sorted((c1, c2) -> Integer.compare(c2.getWidth(), c1.getWidth()))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
final List<MediaCandidate> filteredCandidates = sortedCandidates.stream()
|
final List<MediaCandidate> filteredCandidates = sortedCandidates.stream()
|
||||||
.filter(c ->
|
.filter(c ->
|
||||||
c.getWidth() <= media.getOriginalWidth()
|
c.getWidth() <= originalWidth
|
||||||
&& c.getWidth() <= type.getValue()
|
&& c.getWidth() <= type.getValue()
|
||||||
&& (isSquare || Integer
|
&& (isSquare || Integer
|
||||||
.compare(c.getWidth(), c.getHeight()) != 0)
|
.compare(c.getWidth(), c.getHeight()) != 0)
|
||||||
|
@ -5,12 +5,12 @@ import androidx.lifecycle.ViewModel;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import awais.instagrabber.models.HighlightModel;
|
import awais.instagrabber.repositories.responses.stories.Story;
|
||||||
|
|
||||||
public class ArchivesViewModel extends ViewModel {
|
public class ArchivesViewModel extends ViewModel {
|
||||||
private MutableLiveData<List<HighlightModel>> list;
|
private MutableLiveData<List<Story>> list;
|
||||||
|
|
||||||
public MutableLiveData<List<HighlightModel>> getList() {
|
public MutableLiveData<List<Story>> getList() {
|
||||||
if (list == null) {
|
if (list == null) {
|
||||||
list = new MutableLiveData<>();
|
list = new MutableLiveData<>();
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ public class CommentsViewerViewModel extends ViewModel {
|
|||||||
private String postId;
|
private String postId;
|
||||||
private String rootCursor;
|
private String rootCursor;
|
||||||
private boolean rootHasNext = true;
|
private boolean rootHasNext = true;
|
||||||
private Comment repliesParent;
|
private Comment repliesParent, replyTo;
|
||||||
private String repliesCursor;
|
private String repliesCursor;
|
||||||
private boolean repliesHasNext = true;
|
private boolean repliesHasNext = true;
|
||||||
private final CommentService commentService;
|
private final CommentService commentService;
|
||||||
@ -153,6 +153,11 @@ public class CommentsViewerViewModel extends ViewModel {
|
|||||||
return repliesParent;
|
return repliesParent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public void setReplyTo(final Comment replyTo) {
|
||||||
|
this.replyTo = replyTo;
|
||||||
|
}
|
||||||
|
|
||||||
public LiveData<Resource<List<Comment>>> getRootList() {
|
public LiveData<Resource<List<Comment>>> getRootList() {
|
||||||
return rootList;
|
return rootList;
|
||||||
}
|
}
|
||||||
@ -297,6 +302,7 @@ public class CommentsViewerViewModel extends ViewModel {
|
|||||||
if (comment == null) return;
|
if (comment == null) return;
|
||||||
if (repliesParent == null || !Objects.equals(repliesParent.getPk(), comment.getPk())) {
|
if (repliesParent == null || !Objects.equals(repliesParent.getPk(), comment.getPk())) {
|
||||||
repliesParent = comment;
|
repliesParent = comment;
|
||||||
|
replyTo = comment;
|
||||||
prevReplies = null;
|
prevReplies = null;
|
||||||
prevRepliesCursor = null;
|
prevRepliesCursor = null;
|
||||||
prevRepliesHasNext = true;
|
prevRepliesHasNext = true;
|
||||||
@ -368,8 +374,8 @@ public class CommentsViewerViewModel extends ViewModel {
|
|||||||
final boolean isReply) {
|
final boolean isReply) {
|
||||||
final MutableLiveData<Resource<Object>> data = new MutableLiveData<>(Resource.loading(null));
|
final MutableLiveData<Resource<Object>> data = new MutableLiveData<>(Resource.loading(null));
|
||||||
String replyToId = null;
|
String replyToId = null;
|
||||||
if (isReply && repliesParent != null) {
|
if (isReply && replyTo != null) {
|
||||||
replyToId = repliesParent.getPk();
|
replyToId = replyTo.getPk();
|
||||||
}
|
}
|
||||||
if (isReply && replyToId == null) {
|
if (isReply && replyToId == null) {
|
||||||
data.postValue(Resource.error(null, null));
|
data.postValue(Resource.error(null, null));
|
||||||
@ -399,10 +405,9 @@ public class CommentsViewerViewModel extends ViewModel {
|
|||||||
final List<Comment> list = getPrevList(isReply ? replyList : rootList);
|
final List<Comment> list = getPrevList(isReply ? replyList : rootList);
|
||||||
final ImmutableList.Builder<Comment> builder = ImmutableList.builder();
|
final ImmutableList.Builder<Comment> builder = ImmutableList.builder();
|
||||||
if (isReply) {
|
if (isReply) {
|
||||||
// in a reply list the first comment is the parent comment
|
// replies are added to the bottom of the list to preserve chronological order
|
||||||
builder.add(list.get(0))
|
builder.addAll(list)
|
||||||
.add(comment)
|
.add(comment);
|
||||||
.addAll(list.subList(1, list.size()));
|
|
||||||
} else {
|
} else {
|
||||||
builder.add(comment)
|
builder.add(comment)
|
||||||
.addAll(list);
|
.addAll(list);
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package awais.instagrabber.viewmodels
|
package awais.instagrabber.viewmodels
|
||||||
|
|
||||||
import android.R.attr
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.content.ContentResolver
|
import android.content.ContentResolver
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
@ -23,7 +22,6 @@ import awais.instagrabber.utils.MediaUtils.OnInfoLoadListener
|
|||||||
import awais.instagrabber.utils.MediaUtils.VideoInfo
|
import awais.instagrabber.utils.MediaUtils.VideoInfo
|
||||||
import awais.instagrabber.utils.VoiceRecorder.VoiceRecorderCallback
|
import awais.instagrabber.utils.VoiceRecorder.VoiceRecorderCallback
|
||||||
import awais.instagrabber.utils.VoiceRecorder.VoiceRecordingResult
|
import awais.instagrabber.utils.VoiceRecorder.VoiceRecordingResult
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
|
|
||||||
class DirectThreadViewModel(
|
class DirectThreadViewModel(
|
||||||
@ -76,10 +74,6 @@ class DirectThreadViewModel(
|
|||||||
return threadManager.sendText(text, viewModelScope)
|
return threadManager.sendText(text, viewModelScope)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sendUri(entry: MediaController.MediaEntry): LiveData<Resource<Any?>> {
|
|
||||||
return threadManager.sendUri(entry, viewModelScope)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun sendUri(uri: Uri): LiveData<Resource<Any?>> {
|
fun sendUri(uri: Uri): LiveData<Resource<Any?>> {
|
||||||
return threadManager.sendUri(uri, viewModelScope)
|
return threadManager.sendUri(uri, viewModelScope)
|
||||||
}
|
}
|
||||||
|
@ -3,15 +3,14 @@ package awais.instagrabber.viewmodels;
|
|||||||
import androidx.lifecycle.MutableLiveData;
|
import androidx.lifecycle.MutableLiveData;
|
||||||
import androidx.lifecycle.ViewModel;
|
import androidx.lifecycle.ViewModel;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import awais.instagrabber.models.FeedStoryModel;
|
import awais.instagrabber.repositories.responses.stories.Story;
|
||||||
|
|
||||||
public class FeedStoriesViewModel extends ViewModel {
|
public class FeedStoriesViewModel extends ViewModel {
|
||||||
private MutableLiveData<List<FeedStoryModel>> list;
|
private MutableLiveData<List<Story>> list;
|
||||||
|
|
||||||
public MutableLiveData<List<FeedStoryModel>> getList() {
|
public MutableLiveData<List<Story>> getList() {
|
||||||
if (list == null) {
|
if (list == null) {
|
||||||
list = new MutableLiveData<>();
|
list = new MutableLiveData<>();
|
||||||
}
|
}
|
||||||
|
@ -5,12 +5,12 @@ import androidx.lifecycle.ViewModel;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import awais.instagrabber.models.HighlightModel;
|
import awais.instagrabber.repositories.responses.stories.Story;
|
||||||
|
|
||||||
public class HighlightsViewModel extends ViewModel {
|
public class HighlightsViewModel extends ViewModel {
|
||||||
private MutableLiveData<List<HighlightModel>> list;
|
private MutableLiveData<List<Story>> list;
|
||||||
|
|
||||||
public MutableLiveData<List<HighlightModel>> getList() {
|
public MutableLiveData<List<Story>> getList() {
|
||||||
if (list == null) {
|
if (list == null) {
|
||||||
list = new MutableLiveData<>();
|
list = new MutableLiveData<>();
|
||||||
}
|
}
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
package awais.instagrabber.viewmodels;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData;
|
|
||||||
import androidx.lifecycle.MutableLiveData;
|
|
||||||
import androidx.lifecycle.ViewModel;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import awais.instagrabber.utils.MediaController;
|
|
||||||
import awais.instagrabber.utils.MediaController.AlbumEntry;
|
|
||||||
|
|
||||||
public class MediaPickerViewModel extends ViewModel implements MediaController.OnLoadListener {
|
|
||||||
private final MutableLiveData<List<AlbumEntry>> allAlbums = new MutableLiveData<>(Collections.emptyList());
|
|
||||||
|
|
||||||
private MediaController mediaController;
|
|
||||||
|
|
||||||
public MediaPickerViewModel() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void loadMedia(final Context context) {
|
|
||||||
mediaController = new MediaController(context, this);
|
|
||||||
mediaController.load();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLoad() {
|
|
||||||
if (mediaController == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final List<AlbumEntry> allPhotoAlbums = mediaController.getAllMediaAlbums();
|
|
||||||
this.allAlbums.postValue(allPhotoAlbums);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LiveData<List<AlbumEntry>> getAllAlbums() {
|
|
||||||
return allAlbums;
|
|
||||||
}
|
|
||||||
}
|
|
@ -331,19 +331,21 @@ class PostViewV2ViewModel : ViewModel() {
|
|||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
fun shareDm(result: RankedRecipient) {
|
fun shareDm(result: RankedRecipient, child: Int) {
|
||||||
if (messageManager == null) {
|
if (messageManager == null) {
|
||||||
messageManager = DirectMessagesManager
|
messageManager = DirectMessagesManager
|
||||||
}
|
}
|
||||||
val mediaId = media.id ?: return
|
val mediaId = media.id ?: return
|
||||||
messageManager?.sendMedia(result, mediaId, BroadcastItemType.MEDIA_SHARE, viewModelScope)
|
val childId = if (child == -1) null else media.carouselMedia?.get(child)?.id
|
||||||
|
messageManager?.sendMedia(result, mediaId, childId, BroadcastItemType.MEDIA_SHARE, viewModelScope)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun shareDm(recipients: Set<RankedRecipient>) {
|
fun shareDm(recipients: Set<RankedRecipient>, child: Int) {
|
||||||
if (messageManager == null) {
|
if (messageManager == null) {
|
||||||
messageManager = DirectMessagesManager
|
messageManager = DirectMessagesManager
|
||||||
}
|
}
|
||||||
val mediaId = media.id ?: return
|
val mediaId = media.id ?: return
|
||||||
messageManager?.sendMedia(recipients, mediaId, BroadcastItemType.MEDIA_SHARE, viewModelScope)
|
val childId = if (child == -1) null else media.carouselMedia?.get(child)?.id
|
||||||
|
messageManager?.sendMedia(recipients, mediaId, childId, BroadcastItemType.MEDIA_SHARE, viewModelScope)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -8,7 +8,6 @@ import awais.instagrabber.db.entities.Favorite
|
|||||||
import awais.instagrabber.db.repositories.AccountRepository
|
import awais.instagrabber.db.repositories.AccountRepository
|
||||||
import awais.instagrabber.db.repositories.FavoriteRepository
|
import awais.instagrabber.db.repositories.FavoriteRepository
|
||||||
import awais.instagrabber.managers.DirectMessagesManager
|
import awais.instagrabber.managers.DirectMessagesManager
|
||||||
import awais.instagrabber.models.HighlightModel
|
|
||||||
import awais.instagrabber.models.Resource
|
import awais.instagrabber.models.Resource
|
||||||
import awais.instagrabber.models.StoryModel
|
import awais.instagrabber.models.StoryModel
|
||||||
import awais.instagrabber.models.enums.BroadcastItemType
|
import awais.instagrabber.models.enums.BroadcastItemType
|
||||||
@ -18,6 +17,7 @@ import awais.instagrabber.repositories.responses.FriendshipStatus
|
|||||||
import awais.instagrabber.repositories.responses.User
|
import awais.instagrabber.repositories.responses.User
|
||||||
import awais.instagrabber.repositories.responses.UserProfileContextLink
|
import awais.instagrabber.repositories.responses.UserProfileContextLink
|
||||||
import awais.instagrabber.repositories.responses.directmessages.RankedRecipient
|
import awais.instagrabber.repositories.responses.directmessages.RankedRecipient
|
||||||
|
import awais.instagrabber.repositories.responses.stories.Story
|
||||||
import awais.instagrabber.utils.ControlledRunner
|
import awais.instagrabber.utils.ControlledRunner
|
||||||
import awais.instagrabber.utils.Event
|
import awais.instagrabber.utils.Event
|
||||||
import awais.instagrabber.utils.SingleRunner
|
import awais.instagrabber.utils.SingleRunner
|
||||||
@ -185,9 +185,9 @@ class ProfileFragmentViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val highlightsFetchControlledRunner = ControlledRunner<List<HighlightModel>?>()
|
private val highlightsFetchControlledRunner = ControlledRunner<List<Story>?>()
|
||||||
val userHighlights: LiveData<Resource<List<HighlightModel>?>> = currentUserProfileActionLiveData.switchMap { currentUserAndProfilePair ->
|
val userHighlights: LiveData<Resource<List<Story>?>> = currentUserProfileActionLiveData.switchMap { currentUserAndProfilePair ->
|
||||||
liveData<Resource<List<HighlightModel>?>>(context = viewModelScope.coroutineContext + ioDispatcher) {
|
liveData<Resource<List<Story>?>>(context = viewModelScope.coroutineContext + ioDispatcher) {
|
||||||
val (currentUserResource, profileResource, action) = currentUserAndProfilePair
|
val (currentUserResource, profileResource, action) = currentUserAndProfilePair
|
||||||
if (action != INIT && action != REFRESH) {
|
if (action != INIT && action != REFRESH) {
|
||||||
return@liveData
|
return@liveData
|
||||||
@ -236,7 +236,7 @@ class ProfileFragmentViewModel(
|
|||||||
StoryViewerOptions.forUser(fetchedUser.pk, fetchedUser.fullName)
|
StoryViewerOptions.forUser(fetchedUser.pk, fetchedUser.fullName)
|
||||||
)
|
)
|
||||||
|
|
||||||
private suspend fun fetchUserHighlights(fetchedUser: User): List<HighlightModel> = storiesRepository.fetchHighlights(fetchedUser.pk)
|
private suspend fun fetchUserHighlights(fetchedUser: User): List<Story> = storiesRepository.fetchHighlights(fetchedUser.pk)
|
||||||
|
|
||||||
private suspend fun checkAndUpdateFavorite(fetchedUser: User) {
|
private suspend fun checkAndUpdateFavorite(fetchedUser: User) {
|
||||||
try {
|
try {
|
||||||
@ -268,12 +268,12 @@ class ProfileFragmentViewModel(
|
|||||||
|
|
||||||
fun shareDm(result: RankedRecipient) {
|
fun shareDm(result: RankedRecipient) {
|
||||||
val mediaId = profile.value?.data?.pk ?: return
|
val mediaId = profile.value?.data?.pk ?: return
|
||||||
messageManager?.sendMedia(result, mediaId.toString(10), BroadcastItemType.PROFILE, viewModelScope)
|
messageManager?.sendMedia(result, mediaId.toString(10), null, BroadcastItemType.PROFILE, viewModelScope)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun shareDm(recipients: Set<RankedRecipient>) {
|
fun shareDm(recipients: Set<RankedRecipient>) {
|
||||||
val mediaId = profile.value?.data?.pk ?: return
|
val mediaId = profile.value?.data?.pk ?: return
|
||||||
messageManager?.sendMedia(recipients, mediaId.toString(10), BroadcastItemType.PROFILE, viewModelScope)
|
messageManager?.sendMedia(recipients, mediaId.toString(10), null, BroadcastItemType.PROFILE, viewModelScope)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun refresh() {
|
fun refresh() {
|
||||||
|
@ -173,8 +173,9 @@ open class DirectMessagesRepository(private val service: DirectMessagesService)
|
|||||||
clientContext: String,
|
clientContext: String,
|
||||||
threadIdsOrUserIds: ThreadIdsOrUserIds,
|
threadIdsOrUserIds: ThreadIdsOrUserIds,
|
||||||
mediaId: String,
|
mediaId: String,
|
||||||
|
childId: String?,
|
||||||
): DirectThreadBroadcastResponse =
|
): DirectThreadBroadcastResponse =
|
||||||
broadcast(csrfToken, userId, deviceUuid, MediaShareBroadcastOptions(clientContext, threadIdsOrUserIds, mediaId))
|
broadcast(csrfToken, userId, deviceUuid, MediaShareBroadcastOptions(clientContext, threadIdsOrUserIds, mediaId, childId))
|
||||||
|
|
||||||
suspend fun broadcastProfile(
|
suspend fun broadcastProfile(
|
||||||
csrfToken: String,
|
csrfToken: String,
|
||||||
|
@ -63,7 +63,7 @@ public class ProfileService {
|
|||||||
}
|
}
|
||||||
callback.onSuccess(new PostsFetchResponse(
|
callback.onSuccess(new PostsFetchResponse(
|
||||||
body.getItems(),
|
body.getItems(),
|
||||||
body.isMoreAvailable(),
|
body.getMoreAvailable(),
|
||||||
body.getNextMaxId()
|
body.getNextMaxId()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -204,7 +204,7 @@ public class ProfileService {
|
|||||||
}
|
}
|
||||||
callback.onSuccess(new PostsFetchResponse(
|
callback.onSuccess(new PostsFetchResponse(
|
||||||
userFeedResponse.getItems(),
|
userFeedResponse.getItems(),
|
||||||
userFeedResponse.isMoreAvailable(),
|
userFeedResponse.getMoreAvailable(),
|
||||||
userFeedResponse.getNextMaxId()
|
userFeedResponse.getNextMaxId()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -237,7 +237,7 @@ public class ProfileService {
|
|||||||
}
|
}
|
||||||
callback.onSuccess(new PostsFetchResponse(
|
callback.onSuccess(new PostsFetchResponse(
|
||||||
userFeedResponse.getItems(),
|
userFeedResponse.getItems(),
|
||||||
userFeedResponse.isMoreAvailable(),
|
userFeedResponse.getMoreAvailable(),
|
||||||
userFeedResponse.getNextMaxId()
|
userFeedResponse.getNextMaxId()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,15 @@
|
|||||||
package awais.instagrabber.webservices
|
package awais.instagrabber.webservices
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import awais.instagrabber.fragments.settings.PreferenceKeys
|
import awais.instagrabber.fragments.settings.PreferenceKeys
|
||||||
import awais.instagrabber.models.FeedStoryModel
|
|
||||||
import awais.instagrabber.models.HighlightModel
|
|
||||||
import awais.instagrabber.models.StoryModel
|
import awais.instagrabber.models.StoryModel
|
||||||
import awais.instagrabber.repositories.StoriesService
|
import awais.instagrabber.repositories.StoriesService
|
||||||
import awais.instagrabber.repositories.requests.StoryViewerOptions
|
import awais.instagrabber.repositories.requests.StoryViewerOptions
|
||||||
import awais.instagrabber.repositories.responses.StoryStickerResponse
|
import awais.instagrabber.repositories.responses.stories.ArchiveResponse
|
||||||
import awais.instagrabber.repositories.responses.User
|
import awais.instagrabber.repositories.responses.stories.Story
|
||||||
import awais.instagrabber.utils.Constants
|
import awais.instagrabber.repositories.responses.stories.StoryStickerResponse
|
||||||
import awais.instagrabber.utils.ResponseBodyUtils
|
import awais.instagrabber.utils.ResponseBodyUtils
|
||||||
import awais.instagrabber.utils.TextUtils.isEmpty
|
import awais.instagrabber.utils.TextUtils.isEmpty
|
||||||
import awais.instagrabber.utils.Utils
|
import awais.instagrabber.utils.Utils
|
||||||
import awais.instagrabber.utils.extensions.TAG
|
|
||||||
import awais.instagrabber.webservices.RetrofitFactory.retrofit
|
import awais.instagrabber.webservices.RetrofitFactory.retrofit
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
@ -27,101 +23,42 @@ open class StoriesRepository(private val service: StoriesService) {
|
|||||||
return ResponseBodyUtils.parseStoryItem(itemJson, false, null)
|
return ResponseBodyUtils.parseStoryItem(itemJson, false, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getFeedStories(): List<FeedStoryModel> {
|
suspend fun getFeedStories(): List<Story> {
|
||||||
val response = service.getFeedStories()
|
val response = service.getFeedStories()
|
||||||
return parseStoriesBody(response)
|
val result: MutableList<Story> = mutableListOf()
|
||||||
}
|
if (response?.broadcasts != null) {
|
||||||
|
val length = response.broadcasts.size
|
||||||
private fun parseStoriesBody(body: String): List<FeedStoryModel> {
|
|
||||||
val feedStoryModels: MutableList<FeedStoryModel> = ArrayList()
|
|
||||||
val feedStoriesReel = JSONObject(body).getJSONArray("tray")
|
|
||||||
for (i in 0 until feedStoriesReel.length()) {
|
|
||||||
val node = feedStoriesReel.getJSONObject(i)
|
|
||||||
if (node.optBoolean("hide_from_feed_unit") && Utils.settingsHelper.getBoolean(PreferenceKeys.HIDE_MUTED_REELS)) continue
|
|
||||||
val userJson = node.getJSONObject(if (node.has("user")) "user" else "owner")
|
|
||||||
try {
|
|
||||||
val user = User(
|
|
||||||
userJson.getLong("pk"),
|
|
||||||
userJson.getString("username"),
|
|
||||||
userJson.optString("full_name"),
|
|
||||||
userJson.optBoolean("is_private"),
|
|
||||||
userJson.getString("profile_pic_url"),
|
|
||||||
userJson.optBoolean("is_verified")
|
|
||||||
)
|
|
||||||
val timestamp = node.getLong("latest_reel_media")
|
|
||||||
val fullyRead = !node.isNull("seen") && node.getLong("seen") == timestamp
|
|
||||||
val itemJson = if (node.has("items")) node.getJSONArray("items").optJSONObject(0) else null
|
|
||||||
var firstStoryModel: StoryModel? = null
|
|
||||||
if (itemJson != null) {
|
|
||||||
firstStoryModel = ResponseBodyUtils.parseStoryItem(itemJson, false, null)
|
|
||||||
}
|
|
||||||
feedStoryModels.add(
|
|
||||||
FeedStoryModel(
|
|
||||||
node.getString("id"),
|
|
||||||
user,
|
|
||||||
fullyRead,
|
|
||||||
timestamp,
|
|
||||||
firstStoryModel,
|
|
||||||
node.getInt("media_count"),
|
|
||||||
false,
|
|
||||||
node.optBoolean("has_besties_media")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.e(TAG, "parseStoriesBody: ", e)
|
|
||||||
} // to cover promotional reels with non-long user pk's
|
|
||||||
}
|
|
||||||
val broadcasts = JSONObject(body).getJSONArray("broadcasts")
|
|
||||||
for (i in 0 until broadcasts.length()) {
|
|
||||||
val node = broadcasts.getJSONObject(i)
|
|
||||||
val userJson = node.getJSONObject("broadcast_owner")
|
|
||||||
val user = User(
|
|
||||||
userJson.getLong("pk"),
|
|
||||||
userJson.getString("username"),
|
|
||||||
userJson.optString("full_name"),
|
|
||||||
userJson.optBoolean("is_private"),
|
|
||||||
userJson.getString("profile_pic_url"),
|
|
||||||
userJson.optBoolean("is_verified")
|
|
||||||
)
|
|
||||||
feedStoryModels.add(
|
|
||||||
FeedStoryModel(
|
|
||||||
node.getString("id"),
|
|
||||||
user,
|
|
||||||
false,
|
|
||||||
node.getLong("published_time"),
|
|
||||||
ResponseBodyUtils.parseBroadcastItem(node),
|
|
||||||
1,
|
|
||||||
isLive = true,
|
|
||||||
isBestie = false
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return sort(feedStoryModels)
|
|
||||||
}
|
|
||||||
|
|
||||||
open suspend fun fetchHighlights(profileId: Long): List<HighlightModel> {
|
|
||||||
val response = service.fetchHighlights(profileId)
|
|
||||||
val highlightsReel = JSONObject(response).getJSONArray("tray")
|
|
||||||
val length = highlightsReel.length()
|
|
||||||
val highlightModels: MutableList<HighlightModel> = ArrayList()
|
|
||||||
for (i in 0 until length) {
|
for (i in 0 until length) {
|
||||||
val highlightNode = highlightsReel.getJSONObject(i)
|
val broadcast = response.broadcasts.get(i)
|
||||||
highlightModels.add(
|
result.add(
|
||||||
HighlightModel(
|
Story(
|
||||||
highlightNode.getString("title"),
|
broadcast.id,
|
||||||
highlightNode.getString(Constants.EXTRAS_ID),
|
broadcast.publishedTime,
|
||||||
highlightNode.getJSONObject("cover_media")
|
1,
|
||||||
.getJSONObject("cropped_image_version")
|
0L,
|
||||||
.getString("url"),
|
broadcast.broadcastOwner,
|
||||||
highlightNode.getLong("latest_reel_media"),
|
broadcast.muted,
|
||||||
highlightNode.getInt("media_count")
|
false, // unclear
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
broadcast
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (response?.tray != null) result.addAll(response.tray)
|
||||||
|
return sort(result.toList())
|
||||||
|
}
|
||||||
|
|
||||||
|
open suspend fun fetchHighlights(profileId: Long): List<Story> {
|
||||||
|
val response = service.fetchHighlights(profileId)
|
||||||
|
val highlightModels = response?.tray ?: listOf()
|
||||||
return highlightModels
|
return highlightModels
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun fetchArchive(maxId: String): ArchiveFetchResponse {
|
suspend fun fetchArchive(maxId: String): ArchiveResponse? {
|
||||||
val form = mutableMapOf(
|
val form = mutableMapOf(
|
||||||
"include_suggested_highlights" to "false",
|
"include_suggested_highlights" to "false",
|
||||||
"is_in_archive_home" to "true",
|
"is_in_archive_home" to "true",
|
||||||
@ -130,24 +67,7 @@ open class StoriesRepository(private val service: StoriesService) {
|
|||||||
if (!isEmpty(maxId)) {
|
if (!isEmpty(maxId)) {
|
||||||
form["max_id"] = maxId // NOT TESTED
|
form["max_id"] = maxId // NOT TESTED
|
||||||
}
|
}
|
||||||
val response = service.fetchArchive(form)
|
return service.fetchArchive(form)
|
||||||
val data = JSONObject(response)
|
|
||||||
val highlightsReel = data.getJSONArray("items")
|
|
||||||
val length = highlightsReel.length()
|
|
||||||
val highlightModels: MutableList<HighlightModel> = ArrayList()
|
|
||||||
for (i in 0 until length) {
|
|
||||||
val highlightNode = highlightsReel.getJSONObject(i)
|
|
||||||
highlightModels.add(
|
|
||||||
HighlightModel(
|
|
||||||
null,
|
|
||||||
highlightNode.getString(Constants.EXTRAS_ID),
|
|
||||||
highlightNode.getJSONObject("cover_image_version").getString("url"),
|
|
||||||
highlightNode.getLong("latest_reel_media"),
|
|
||||||
highlightNode.getInt("media_count")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return ArchiveFetchResponse(highlightModels, data.getBoolean("more_available"), data.getString("max_id"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
open suspend fun getUserStory(options: StoryViewerOptions): List<StoryModel> {
|
open suspend fun getUserStory(options: StoryViewerOptions): List<StoryModel> {
|
||||||
@ -299,24 +219,19 @@ open class StoriesRepository(private val service: StoriesService) {
|
|||||||
return builder.toString()
|
return builder.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun sort(list: List<FeedStoryModel>): List<FeedStoryModel> {
|
private fun sort(list: List<Story>): List<Story> {
|
||||||
val listCopy = ArrayList(list)
|
val listCopy = ArrayList(list)
|
||||||
listCopy.sortWith { o1, o2 ->
|
listCopy.sortWith { o1, o2 ->
|
||||||
when (Utils.settingsHelper.getString(PreferenceKeys.STORY_SORT)) {
|
if (o1.latestReelMedia == null || o2.latestReelMedia == null) return@sortWith 0
|
||||||
"1" -> return@sortWith o2.timestamp.compareTo(o1.timestamp)
|
else when (Utils.settingsHelper.getString(PreferenceKeys.STORY_SORT)) {
|
||||||
"2" -> return@sortWith o1.timestamp.compareTo(o2.timestamp)
|
"1" -> return@sortWith o2.latestReelMedia.compareTo(o1.latestReelMedia)
|
||||||
|
"2" -> return@sortWith o1.latestReelMedia.compareTo(o2.latestReelMedia)
|
||||||
else -> return@sortWith 0
|
else -> return@sortWith 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return listCopy
|
return listCopy
|
||||||
}
|
}
|
||||||
|
|
||||||
class ArchiveFetchResponse(val result: List<HighlightModel>, val hasNextPage: Boolean, val nextCursor: String) {
|
|
||||||
fun hasNextPage(): Boolean {
|
|
||||||
return hasNextPage
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@Volatile
|
@Volatile
|
||||||
private var INSTANCE: StoriesRepository? = null
|
private var INSTANCE: StoriesRepository? = null
|
||||||
|
@ -122,7 +122,7 @@ public class TagsService {
|
|||||||
}
|
}
|
||||||
callback.onSuccess(new PostsFetchResponse(
|
callback.onSuccess(new PostsFetchResponse(
|
||||||
body.getItems(),
|
body.getItems(),
|
||||||
body.isMoreAvailable(),
|
body.getMoreAvailable(),
|
||||||
body.getNextMaxId()
|
body.getNextMaxId()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
5
app/src/main/res/color/ic_read_button_tint.xml
Normal file
5
app/src/main/res/color/ic_read_button_tint.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:color="@color/grey_600" android:state_enabled="false" />
|
||||||
|
<item android:color="?colorControlNormal" />
|
||||||
|
</selector>
|
@ -3,7 +3,7 @@
|
|||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="24"
|
||||||
android:viewportHeight="24"
|
android:viewportHeight="24"
|
||||||
android:tint="?attr/colorControlNormal">
|
android:tint="@color/ic_read_button_tint">
|
||||||
<path
|
<path
|
||||||
android:fillColor="@android:color/white"
|
android:fillColor="@android:color/white"
|
||||||
android:pathData="M18,7l-1.41,-1.41 -6.34,6.34 1.41,1.41L18,7zM22.24,5.59L11.66,16.17 7.48,12l-1.41,1.41L11.66,19l12,-12 -1.42,-1.41zM0.41,13.41L6,19l1.41,-1.41L1.83,12 0.41,13.41z"/>
|
android:pathData="M18,7l-1.41,-1.41 -6.34,6.34 1.41,1.41L18,7zM22.24,5.59L11.66,16.17 7.48,12l-1.41,1.41L11.66,19l12,-12 -1.42,-1.41zM0.41,13.41L6,19l1.41,-1.41L1.83,12 0.41,13.41z"/>
|
||||||
|
@ -133,7 +133,7 @@
|
|||||||
android:id="@+id/btnBackward"
|
android:id="@+id/btnBackward"
|
||||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||||
android:layout_width="40dp"
|
android:layout_width="40dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="@dimen/story_item_height"
|
||||||
android:visibility="visible"
|
android:visibility="visible"
|
||||||
app:icon="@drawable/exo_ic_skip_previous"
|
app:icon="@drawable/exo_ic_skip_previous"
|
||||||
app:iconGravity="textStart"
|
app:iconGravity="textStart"
|
||||||
@ -157,7 +157,7 @@
|
|||||||
android:id="@+id/btnForward"
|
android:id="@+id/btnForward"
|
||||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||||
android:layout_width="40dp"
|
android:layout_width="40dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="@dimen/story_item_height"
|
||||||
android:visibility="visible"
|
android:visibility="visible"
|
||||||
app:icon="@drawable/exo_ic_skip_next"
|
app:icon="@drawable/exo_ic_skip_next"
|
||||||
app:iconGravity="textStart"
|
app:iconGravity="textStart"
|
||||||
|
@ -76,26 +76,7 @@
|
|||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="@id/title" />
|
app:layout_constraintTop_toTopOf="@id/caption" />
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
|
||||||
android:id="@+id/title"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:paddingStart="8dp"
|
|
||||||
android:paddingTop="8dp"
|
|
||||||
android:paddingEnd="8dp"
|
|
||||||
android:paddingBottom="0dp"
|
|
||||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
|
|
||||||
android:textColor="@color/white"
|
|
||||||
android:textStyle="bold"
|
|
||||||
app:layout_constraintBottom_toTopOf="@id/caption"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintVertical_bias="1"
|
|
||||||
app:layout_constraintVertical_chainStyle="packed"
|
|
||||||
tools:text="Title" />
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
android:id="@+id/caption"
|
android:id="@+id/caption"
|
||||||
@ -107,6 +88,5 @@
|
|||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/title"
|
|
||||||
tools:text="Caption Caption Caption Caption Caption Caption " />
|
tools:text="Caption Caption Caption Caption Caption Caption " />
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -1,30 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.Toolbar
|
|
||||||
android:id="@+id/toolbar"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="?actionBarSize"
|
|
||||||
app:layout_constraintBottom_toTopOf="@id/media_list"
|
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
|
||||||
|
|
||||||
<Spinner
|
|
||||||
android:id="@+id/album_picker"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="match_parent" />
|
|
||||||
|
|
||||||
</androidx.appcompat.widget.Toolbar>
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
android:id="@+id/media_list"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/toolbar" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -22,6 +22,7 @@
|
|||||||
<string name="title_favorites">Favorites</string>
|
<string name="title_favorites">Favorites</string>
|
||||||
<string name="title_discover">Discover</string>
|
<string name="title_discover">Discover</string>
|
||||||
<string name="title_comments">Comments</string>
|
<string name="title_comments">Comments</string>
|
||||||
|
<string name="title_replies">Replies</string>
|
||||||
<string name="title_notifications">Activity</string>
|
<string name="title_notifications">Activity</string>
|
||||||
<string name="update_check">Check for updates at startup</string>
|
<string name="update_check">Check for updates at startup</string>
|
||||||
<string name="flag_secure">Block screenshots & app preview</string>
|
<string name="flag_secure">Block screenshots & app preview</string>
|
||||||
@ -513,7 +514,7 @@
|
|||||||
<string name="dir_select_folder_not_exist">The previously selected folder does not exist now:</string>
|
<string name="dir_select_folder_not_exist">The previously selected folder does not exist now:</string>
|
||||||
<string name="dir_select_message2">Re-select the directory or select a new directory by clicking the button below.</string>
|
<string name="dir_select_message2">Re-select the directory or select a new directory by clicking the button below.</string>
|
||||||
<string name="select_a_folder">No folder selected!</string>
|
<string name="select_a_folder">No folder selected!</string>
|
||||||
<string name="dir_select_no_download_folder">Please choose a directory from your storage, not a category on the sidebar.</string>
|
<string name="dir_select_no_download_folder">Please choose a directory from your storage, not a category on the sidebar.\n(%s)</string>
|
||||||
<string name="dir_select_success_message">Success! Please wait. Starting app…</string>
|
<string name="dir_select_success_message">Success! Please wait. Starting app…</string>
|
||||||
<string name="barinsta_folder">Barinsta folder</string>
|
<string name="barinsta_folder">Barinsta folder</string>
|
||||||
<string name="top">Top</string>
|
<string name="top">Top</string>
|
||||||
|
@ -8,6 +8,9 @@ import awais.instagrabber.models.enums.FavoriteType
|
|||||||
import awais.instagrabber.repositories.*
|
import awais.instagrabber.repositories.*
|
||||||
import awais.instagrabber.repositories.responses.*
|
import awais.instagrabber.repositories.responses.*
|
||||||
import awais.instagrabber.repositories.responses.directmessages.*
|
import awais.instagrabber.repositories.responses.directmessages.*
|
||||||
|
import awais.instagrabber.repositories.responses.stories.ArchiveResponse
|
||||||
|
import awais.instagrabber.repositories.responses.stories.ReelsTrayResponse
|
||||||
|
import awais.instagrabber.repositories.responses.stories.StoryStickerResponse
|
||||||
|
|
||||||
open class UserServiceAdapter : UserService {
|
open class UserServiceAdapter : UserService {
|
||||||
override suspend fun getUserInfo(uid: Long): WrappedUser {
|
override suspend fun getUserInfo(uid: Long): WrappedUser {
|
||||||
@ -48,15 +51,15 @@ open class StoriesServiceAdapter : StoriesService {
|
|||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getFeedStories(): String {
|
override suspend fun getFeedStories(): ReelsTrayResponse? {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun fetchHighlights(uid: Long): String {
|
override suspend fun fetchHighlights(uid: Long): ReelsTrayResponse? {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun fetchArchive(queryParams: Map<String, String>): String {
|
override suspend fun fetchArchive(queryParams: Map<String, String>): ArchiveResponse? {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,13 +9,13 @@ import awais.instagrabber.db.datasources.FavoriteDataSource
|
|||||||
import awais.instagrabber.db.entities.Favorite
|
import awais.instagrabber.db.entities.Favorite
|
||||||
import awais.instagrabber.db.repositories.FavoriteRepository
|
import awais.instagrabber.db.repositories.FavoriteRepository
|
||||||
import awais.instagrabber.getOrAwaitValue
|
import awais.instagrabber.getOrAwaitValue
|
||||||
import awais.instagrabber.models.HighlightModel
|
|
||||||
import awais.instagrabber.models.Resource
|
import awais.instagrabber.models.Resource
|
||||||
import awais.instagrabber.models.StoryModel
|
import awais.instagrabber.models.StoryModel
|
||||||
import awais.instagrabber.models.enums.FavoriteType
|
import awais.instagrabber.models.enums.FavoriteType
|
||||||
import awais.instagrabber.repositories.requests.StoryViewerOptions
|
import awais.instagrabber.repositories.requests.StoryViewerOptions
|
||||||
import awais.instagrabber.repositories.responses.FriendshipStatus
|
import awais.instagrabber.repositories.responses.FriendshipStatus
|
||||||
import awais.instagrabber.repositories.responses.User
|
import awais.instagrabber.repositories.responses.User
|
||||||
|
import awais.instagrabber.repositories.responses.stories.Story
|
||||||
import awais.instagrabber.webservices.*
|
import awais.instagrabber.webservices.*
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import org.json.JSONException
|
import org.json.JSONException
|
||||||
@ -321,13 +321,13 @@ internal class ProfileFragmentViewModelTest {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
val testUserStories = listOf(StoryModel())
|
val testUserStories = listOf(StoryModel())
|
||||||
val testUserHighlights = listOf(HighlightModel())
|
val testUserHighlights = listOf(Story())
|
||||||
val userRepository = object : UserRepository(UserServiceAdapter()) {
|
val userRepository = object : UserRepository(UserServiceAdapter()) {
|
||||||
override suspend fun getUsernameInfo(username: String): User = testPublicUser
|
override suspend fun getUsernameInfo(username: String): User = testPublicUser
|
||||||
}
|
}
|
||||||
val storiesRepository = object : StoriesRepository(StoriesServiceAdapter()) {
|
val storiesRepository = object : StoriesRepository(StoriesServiceAdapter()) {
|
||||||
override suspend fun getUserStory(options: StoryViewerOptions): List<StoryModel> = testUserStories
|
override suspend fun getUserStory(options: StoryViewerOptions): List<StoryModel> = testUserStories
|
||||||
override suspend fun fetchHighlights(profileId: Long): List<HighlightModel> = testUserHighlights
|
override suspend fun fetchHighlights(profileId: Long): List<Story> = testUserHighlights
|
||||||
}
|
}
|
||||||
val viewModel = ProfileFragmentViewModel(
|
val viewModel = ProfileFragmentViewModel(
|
||||||
state,
|
state,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.5.0'
|
ext.kotlin_version = '1.5.20'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
# This option should only be used with decoupled projects. More details, visit
|
# This option should only be used with decoupled projects. More details, visit
|
||||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||||
# org.gradle.parallel=true
|
# org.gradle.parallel=true
|
||||||
#Tue May 04 02:33:38 JST 2021
|
#Wed Jun 30 00:40:18 JST 2021
|
||||||
|
org.gradle.jvmargs=-Xmx2048M -Dkotlin.daemon.jvm.options\="-Xmx2048M" -XX:+UseParallelGC
|
||||||
android.enableJetifier=true
|
android.enableJetifier=true
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
org.gradle.jvmargs=-Xmx2048M -Dkotlin.daemon.jvm.options\="-Xmx1536M"
|
|
||||||
|
Loading…
Reference in New Issue
Block a user