1
0
mirror of https://github.com/KokaKiwi/BarInsta synced 2024-11-22 22:57:29 +00:00

Merge branch 'master' into dm-notifications-enhancements

This commit is contained in:
Austin Huang 2021-01-06 13:25:06 -05:00 committed by GitHub
commit b2917e3d63
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 225 additions and 75 deletions

View File

@ -18,8 +18,8 @@ assignees: 'austinhuang0131'
## Answer honestly. Check accordingly to your situation. ## Answer honestly. Check accordingly to your situation.
- [ ] I had prior rule violations on Instagram, specifically: - [ ] I had prior rule violations on Instagram, specifically:
- [ ] I have admitted the use of InstaGrabber on Instagram. - [ ] I have admitted the use of Barinsta on Instagram.
- [ ] I have admitted the use of InstaGrabber to a friend who uses Instagram. - [ ] I have admitted the use of Barinsta to a friend who uses Instagram.
- [ ] I have modified the source code of the app that I use, other than what is present in this repo. Specifically: - [ ] I have modified the source code of the app that I use, other than what is present in this repo. Specifically:
## Describe your case, including your usage pattern, but without private information. ## Describe your case, including your usage pattern, but without private information.

View File

@ -6,10 +6,10 @@ labels: bug
assignees: '' assignees: ''
--- ---
<!-- FOLLOW THIS FORMAT --> <!-- If you choose not to follow this format, you should erase the entire body. -->
- [ ] My app is on the latest version. I understand that any other version is not supported. - [ ] My app is on the latest version. I understand that any other version is not supported.
- [ ] I have read [the FAQ](https://instagrabber.austinhuang.me/faq). - [ ] I have read [the FAQ](https://barinsta.austinhuang.me/en/latest/faq).
<!-- <!--
Describe the bug here. Don't stress too much, but do include the key points. Describe the bug here. Don't stress too much, but do include the key points.
@ -18,11 +18,9 @@ Describe the bug here. Don't stress too much, but do include the key points.
## Steps ## Steps
<!-- <!--
DETAILED Steps to reproduce the behaviour. 1. ...
1. Go to '...' 2. ...
2. Click on '....' 3. See error...
3. Scroll down to '....'
4. See error
--> -->
## Environment ## Environment

View File

@ -7,7 +7,13 @@ assignees: ''
--- ---
<!-- <!--
STOP!!!
General questions & feedback should be submitted to General questions & feedback should be submitted to
* one of our chatrooms (see README.md), or * one of our chatrooms (see README.md), or
* r/barinsta on reddit. * r/barinsta on reddit.
STOP!!!
--> -->

View File

@ -60,11 +60,13 @@ dependencies {
def appcompat_version = "1.2.0" def appcompat_version = "1.2.0"
def nav_version = '2.3.2' def nav_version = '2.3.2'
def exoplayer_version = '2.12.0'
implementation 'com.google.android.material:material:1.3.0-beta01' implementation 'com.google.android.material:material:1.3.0-beta01'
implementation 'com.google.android.exoplayer:exoplayer-core:2.12.0' implementation "com.google.android.exoplayer:exoplayer-core:$exoplayer_version"
implementation 'com.google.android.exoplayer:exoplayer-ui:2.12.0' implementation "com.google.android.exoplayer:exoplayer-dash:$exoplayer_version"
implementation "com.google.android.exoplayer:exoplayer-ui:$exoplayer_version"
implementation "androidx.appcompat:appcompat:$appcompat_version" implementation "androidx.appcompat:appcompat:$appcompat_version"
implementation "androidx.appcompat:appcompat-resources:$appcompat_version" implementation "androidx.appcompat:appcompat-resources:$appcompat_version"

View File

@ -25,6 +25,7 @@ import awais.instagrabber.databinding.ItemFeedVideoBinding;
import awais.instagrabber.models.FeedModel; import awais.instagrabber.models.FeedModel;
import awais.instagrabber.models.PostsLayoutPreferences; import awais.instagrabber.models.PostsLayoutPreferences;
import awais.instagrabber.models.enums.MediaItemType; import awais.instagrabber.models.enums.MediaItemType;
import awais.instagrabber.utils.TextUtils;
public final class FeedAdapterV2 extends ListAdapter<FeedModel, RecyclerView.ViewHolder> { public final class FeedAdapterV2 extends ListAdapter<FeedModel, RecyclerView.ViewHolder> {
private static final String TAG = "FeedAdapterV2"; private static final String TAG = "FeedAdapterV2";
@ -46,7 +47,13 @@ public final class FeedAdapterV2 extends ListAdapter<FeedModel, RecyclerView.Vie
@Override @Override
public boolean areContentsTheSame(@NonNull final FeedModel oldItem, @NonNull final FeedModel newItem) { public boolean areContentsTheSame(@NonNull final FeedModel oldItem, @NonNull final FeedModel newItem) {
return oldItem.getPostId().equals(newItem.getPostId()) && oldItem.getPostCaption().equals(newItem.getPostCaption()); boolean result = oldItem.getPostId().equals(newItem.getPostId());
if (TextUtils.isEmpty(oldItem.getPostCaption())) {
return result ? TextUtils.isEmpty(newItem.getPostCaption()) : false;
}
else {
return result ? oldItem.getPostCaption().equals(newItem.getPostCaption()) : false;
}
} }
}; };
private final AdapterSelectionCallback adapterSelectionCallback = new AdapterSelectionCallback() { private final AdapterSelectionCallback adapterSelectionCallback = new AdapterSelectionCallback() {

View File

@ -33,5 +33,9 @@ public final class FeedStoryViewHolder extends RecyclerView.ViewHolder {
binding.title.setAlpha(model.isFullyRead() ? 0.5F : 1.0F); binding.title.setAlpha(model.isFullyRead() ? 0.5F : 1.0F);
binding.icon.setImageURI(profileModel.getSdProfilePic()); binding.icon.setImageURI(profileModel.getSdProfilePic());
binding.icon.setAlpha(model.isFullyRead() ? 0.5F : 1.0F); binding.icon.setAlpha(model.isFullyRead() ? 0.5F : 1.0F);
if (model.isLive()) binding.icon.setStoriesBorder(2);
else if (model.isBestie()) binding.icon.setStoriesBorder(1);
else binding.icon.setStoriesBorder(0);
} }
} }

View File

@ -49,14 +49,15 @@ public class CircularImageView extends SimpleDraweeView {
setBackgroundResource(R.drawable.shape_oval_light); setBackgroundResource(R.drawable.shape_oval_light);
} }
public void setStoriesBorder() { /* types: 0 clear, 1 green (feed bestie / has story), 2 red (live) */
public void setStoriesBorder(final int type) {
// private final int borderSize = 8; // private final int borderSize = 8;
final int color = Color.GREEN; final int color = type == 2 ? Color.RED : Color.GREEN;
RoundingParams roundingParams = getHierarchy().getRoundingParams(); RoundingParams roundingParams = getHierarchy().getRoundingParams();
if (roundingParams == null) { if (roundingParams == null) {
roundingParams = RoundingParams.asCircle().setRoundingMethod(RoundingParams.RoundingMethod.BITMAP_ONLY); roundingParams = RoundingParams.asCircle().setRoundingMethod(RoundingParams.RoundingMethod.BITMAP_ONLY);
} }
roundingParams.setBorder(color, 5.0f); roundingParams.setBorder(color, type == 0 ? 0f : 5.0f);
getHierarchy().setRoundingParams(roundingParams); getHierarchy().setRoundingParams(roundingParams);
} }
} }

View File

@ -580,7 +580,7 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe
@Override @Override
public void onSuccess(final List<StoryModel> storyModels) { public void onSuccess(final List<StoryModel> storyModels) {
if (storyModels != null && !storyModels.isEmpty()) { if (storyModels != null && !storyModels.isEmpty()) {
hashtagDetailsBinding.mainHashtagImage.setStoriesBorder(); hashtagDetailsBinding.mainHashtagImage.setStoriesBorder(1);
hasStories = true; hasStories = true;
} else { } else {
hasStories = false; hasStories = false;

View File

@ -563,7 +563,7 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR
@Override @Override
public void onSuccess(final List<StoryModel> storyModels) { public void onSuccess(final List<StoryModel> storyModels) {
if (storyModels != null && !storyModels.isEmpty()) { if (storyModels != null && !storyModels.isEmpty()) {
locationDetailsBinding.mainLocationImage.setStoriesBorder(); locationDetailsBinding.mainLocationImage.setStoriesBorder(1);
hasStories = true; hasStories = true;
} }
storiesFetching = false; storiesFetching = false;

View File

@ -197,6 +197,7 @@ public final class StoryListViewerFragment extends Fragment implements SwipeRefr
@Override @Override
public void onSuccess(final List<FeedStoryModel> result) { public void onSuccess(final List<FeedStoryModel> result) {
feedStoriesViewModel.getList().postValue(result); feedStoriesViewModel.getList().postValue(result);
adapter.submitList(result);
binding.swipeRefreshLayout.setRefreshing(false); binding.swipeRefreshLayout.setRefreshing(false);
} }

View File

@ -50,6 +50,7 @@ import com.facebook.imagepipeline.request.ImageRequestBuilder;
import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.source.dash.DashMediaSource;
import com.google.android.exoplayer2.source.LoadEventInfo; import com.google.android.exoplayer2.source.LoadEventInfo;
import com.google.android.exoplayer2.source.MediaLoadData; import com.google.android.exoplayer2.source.MediaLoadData;
import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.MediaSource;
@ -134,7 +135,7 @@ public class StoryViewerFragment extends Fragment {
private MenuItem menuDm; private MenuItem menuDm;
private SimpleExoPlayer player; private SimpleExoPlayer player;
private boolean isHashtag, isLoc; private boolean isHashtag, isLoc;
private String highlight; private String highlight, actionBarTitle;
private boolean fetching = false, sticking = false, shouldRefresh = true; private boolean fetching = false, sticking = false, shouldRefresh = true;
private int currentFeedStoryIndex; private int currentFeedStoryIndex;
private double sliderValue; private double sliderValue;
@ -256,6 +257,15 @@ public class StoryViewerFragment extends Fragment {
releasePlayer(); releasePlayer();
} }
@Override
public void onResume() {
super.onResume();
final ActionBar actionBar = fragmentActivity.getSupportActionBar();
if (actionBar != null) {
actionBar.setTitle(actionBarTitle);
}
}
@Override @Override
public void onDestroy() { public void onDestroy() {
releasePlayer(); releasePlayer();
@ -646,6 +656,7 @@ public class StoryViewerFragment extends Fragment {
private void resetView() { private void resetView() {
final Context context = getContext(); final Context context = getContext();
StoryModel live = null;
slidePos = 0; slidePos = 0;
lastSlidePos = 0; lastSlidePos = 0;
if (menuDownload != null) menuDownload.setVisible(false); if (menuDownload != null) menuDownload.setVisible(false);
@ -681,6 +692,7 @@ public class StoryViewerFragment extends Fragment {
final FeedStoryModel model = models.get(currentFeedStoryIndex); final FeedStoryModel model = models.get(currentFeedStoryIndex);
currentStoryMediaId = model.getStoryMediaId(); currentStoryMediaId = model.getStoryMediaId();
currentStoryUsername = model.getProfileModel().getUsername(); currentStoryUsername = model.getProfileModel().getUsername();
if (model.isLive()) live = model.getFirstStoryModel();
} }
} else if (!TextUtils.isEmpty(fragmentArgs.getProfileId()) && !TextUtils.isEmpty(fragmentArgs.getUsername())) { } else if (!TextUtils.isEmpty(fragmentArgs.getProfileId()) && !TextUtils.isEmpty(fragmentArgs.getUsername())) {
currentStoryMediaId = fragmentArgs.getProfileId(); currentStoryMediaId = fragmentArgs.getProfileId();
@ -692,12 +704,14 @@ public class StoryViewerFragment extends Fragment {
if (isHighlight) { if (isHighlight) {
final ActionBar actionBar = fragmentActivity.getSupportActionBar(); final ActionBar actionBar = fragmentActivity.getSupportActionBar();
if (actionBar != null) { if (actionBar != null) {
actionBarTitle = highlight;
actionBar.setTitle(highlight); actionBar.setTitle(highlight);
} }
} else if (hasUsername) { } else if (hasUsername) {
currentStoryUsername = currentStoryUsername.replace("@", ""); currentStoryUsername = currentStoryUsername.replace("@", "");
final ActionBar actionBar = fragmentActivity.getSupportActionBar(); final ActionBar actionBar = fragmentActivity.getSupportActionBar();
if (actionBar != null) { if (actionBar != null) {
actionBarTitle = currentStoryUsername;
actionBar.setTitle(currentStoryUsername); actionBar.setTitle(currentStoryUsername);
} }
} }
@ -755,12 +769,14 @@ public class StoryViewerFragment extends Fragment {
Log.e(TAG, "Error", t); Log.e(TAG, "Error", t);
} }
}; };
storiesService.getUserStory(currentStoryMediaId, if (live != null) storyCallback.onSuccess(Collections.singletonList(live));
currentStoryUsername, else storiesService.getUserStory(currentStoryMediaId,
isLoc, currentStoryUsername,
isHashtag, isLoc,
isHighlight, isHashtag,
storyCallback); isHighlight,
storyCallback);
}
} }
private void refreshStory() { private void refreshStory() {
@ -784,51 +800,55 @@ public class StoryViewerFragment extends Fragment {
final MediaItemType itemType = currentStory.getItemType(); final MediaItemType itemType = currentStory.getItemType();
if (menuDownload != null) menuDownload.setVisible(false); if (menuDownload != null) menuDownload.setVisible(false);
url = itemType == MediaItemType.MEDIA_TYPE_VIDEO ? currentStory.getVideoUrl() : currentStory.getStoryUrl(); url = itemType == MediaItemType.MEDIA_TYPE_IMAGE ? currentStory.getStoryUrl() : currentStory.getVideoUrl();
final String shortCode = currentStory.getTappableShortCode(); if (itemType != MediaItemType.MEDIA_TYPE_LIVE) {
binding.viewStoryPost.setVisibility(shortCode != null ? View.VISIBLE : View.GONE); final String shortCode = currentStory.getTappableShortCode();
binding.viewStoryPost.setTag(shortCode); binding.viewStoryPost.setVisibility(shortCode != null ? View.VISIBLE : View.GONE);
binding.viewStoryPost.setTag(shortCode);
final String spotify = currentStory.getSpotify(); final String spotify = currentStory.getSpotify();
binding.spotify.setVisibility(spotify != null ? View.VISIBLE : View.GONE); binding.spotify.setVisibility(spotify != null ? View.VISIBLE : View.GONE);
binding.spotify.setTag(spotify); binding.spotify.setTag(spotify);
poll = currentStory.getPoll(); poll = currentStory.getPoll();
binding.poll.setVisibility(poll != null ? View.VISIBLE : View.GONE); binding.poll.setVisibility(poll != null ? View.VISIBLE : View.GONE);
binding.poll.setTag(poll); binding.poll.setTag(poll);
question = currentStory.getQuestion(); question = currentStory.getQuestion();
binding.answer.setVisibility((question != null && !TextUtils.isEmpty(cookie)) ? View.VISIBLE : View.GONE); binding.answer.setVisibility((question != null && !TextUtils.isEmpty(cookie)) ? View.VISIBLE : View.GONE);
binding.answer.setTag(question); binding.answer.setTag(question);
mentions = currentStory.getMentions(); mentions = currentStory.getMentions();
binding.mention.setVisibility((mentions != null && mentions.length > 0) ? View.VISIBLE : View.GONE); binding.mention.setVisibility((mentions != null && mentions.length > 0) ? View.VISIBLE : View.GONE);
binding.mention.setTag(mentions); binding.mention.setTag(mentions);
quiz = currentStory.getQuiz(); quiz = currentStory.getQuiz();
binding.quiz.setVisibility(quiz != null ? View.VISIBLE : View.GONE); binding.quiz.setVisibility(quiz != null ? View.VISIBLE : View.GONE);
binding.quiz.setTag(quiz); binding.quiz.setTag(quiz);
slider = currentStory.getSlider(); slider = currentStory.getSlider();
binding.slider.setVisibility(slider != null ? View.VISIBLE : View.GONE); binding.slider.setVisibility(slider != null ? View.VISIBLE : View.GONE);
binding.slider.setTag(slider); binding.slider.setTag(slider);
final SwipeUpModel swipeUp = currentStory.getSwipeUp(); final SwipeUpModel swipeUp = currentStory.getSwipeUp();
if (swipeUp != null) { if (swipeUp != null) {
binding.swipeUp.setVisibility(View.VISIBLE); binding.swipeUp.setVisibility(View.VISIBLE);
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);
} }
releasePlayer(); releasePlayer();
if (isHashtag || isLoc) { if (isHashtag || isLoc) {
final ActionBar actionBar = fragmentActivity.getSupportActionBar(); final ActionBar actionBar = fragmentActivity.getSupportActionBar();
if (actionBar != null) { if (actionBar != null) {
actionBarTitle = currentStory.getUsername();
actionBar.setTitle(currentStory.getUsername()); actionBar.setTitle(currentStory.getUsername());
} }
} }
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();
@ -954,6 +974,72 @@ public class StoryViewerFragment extends Fragment {
}); });
} }
private void setupLive() {
binding.playerView.setVisibility(View.VISIBLE);
binding.progressView.setVisibility(View.GONE);
binding.imageViewer.setVisibility(View.GONE);
binding.imageViewer.setController(null);
if (menuDownload != null) menuDownload.setVisible(false);
if (menuDm != null) menuDm.setVisible(false);
final Context context = getContext();
if (context == null) return;
player = new SimpleExoPlayer.Builder(context).build();
binding.playerView.setPlayer(player);
player.setPlayWhenReady(settingsHelper.getBoolean(Constants.AUTOPLAY_VIDEOS));
final Uri uri = Uri.parse(url);
final MediaItem mediaItem = MediaItem.fromUri(uri);
final DashMediaSource mediaSource = new DashMediaSource.Factory(new DefaultDataSourceFactory(context, "instagram"))
.createMediaSource(mediaItem);
mediaSource.addEventListener(new Handler(), new MediaSourceEventListener() {
@Override
public void onLoadCompleted(final int windowIndex,
@Nullable final MediaSource.MediaPeriodId mediaPeriodId,
final LoadEventInfo loadEventInfo,
final MediaLoadData mediaLoadData) {
binding.progressView.setVisibility(View.GONE);
}
@Override
public void onLoadStarted(final int windowIndex,
@Nullable final MediaSource.MediaPeriodId mediaPeriodId,
final LoadEventInfo loadEventInfo,
final MediaLoadData mediaLoadData) {
binding.progressView.setVisibility(View.VISIBLE);
}
@Override
public void onLoadCanceled(final int windowIndex,
@Nullable final MediaSource.MediaPeriodId mediaPeriodId,
final LoadEventInfo loadEventInfo,
final MediaLoadData mediaLoadData) {
binding.progressView.setVisibility(View.GONE);
}
@Override
public void onLoadError(final int windowIndex,
@Nullable final MediaSource.MediaPeriodId mediaPeriodId,
final LoadEventInfo loadEventInfo,
final MediaLoadData mediaLoadData,
final IOException error,
final boolean wasCanceled) {
binding.progressView.setVisibility(View.GONE);
}
});
player.setMediaSource(mediaSource);
player.prepare();
binding.playerView.setOnClickListener(v -> {
if (player != null) {
if (player.getPlaybackState() == Player.STATE_ENDED) player.seekTo(0);
player.setPlayWhenReady(player.getPlaybackState() == Player.STATE_ENDED || !player.isPlaying());
}
});
}
private void openProfile(final String username) { private void openProfile(final String username) {
final ActionBar actionBar = fragmentActivity.getSupportActionBar(); final ActionBar actionBar = fragmentActivity.getSupportActionBar();
if (actionBar != null) { if (actionBar != null) {

View File

@ -79,6 +79,21 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre
private RecyclerView storiesRecyclerView; private RecyclerView storiesRecyclerView;
private MenuItem storyListMenu; private MenuItem storyListMenu;
private final FeedStoriesAdapter feedStoriesAdapter = new FeedStoriesAdapter(
new FeedStoriesAdapter.OnFeedStoryClickListener() {
@Override
public void onFeedStoryClick(FeedStoryModel model, int position) {
final NavDirections action = FeedFragmentDirections.actionFeedFragmentToStoryViewerFragment(position, null, false, false, null, null, false, false);
NavHostFragment.findNavController(FeedFragment.this).navigate(action);
}
@Override
public void onFeedStoryLongClick(FeedStoryModel model, int position) {
navigateToProfile("@" + model.getProfileModel().getUsername());
}
}
);
private final FeedAdapterV2.FeedItemCallback feedItemCallback = new FeedAdapterV2.FeedItemCallback() { private final FeedAdapterV2.FeedItemCallback feedItemCallback = new FeedAdapterV2.FeedItemCallback() {
@Override @Override
public void onPostClick(final FeedModel feedModel, final View profilePicView, final View mainPostImage) { public void onPostClick(final FeedModel feedModel, final View profilePicView, final View mainPostImage) {
@ -353,20 +368,6 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre
private void setupFeedStories() { private void setupFeedStories() {
if (storyListMenu != null) storyListMenu.setVisible(false); if (storyListMenu != null) storyListMenu.setVisible(false);
feedStoriesViewModel = new ViewModelProvider(fragmentActivity).get(FeedStoriesViewModel.class); feedStoriesViewModel = new ViewModelProvider(fragmentActivity).get(FeedStoriesViewModel.class);
final FeedStoriesAdapter feedStoriesAdapter = new FeedStoriesAdapter(
new FeedStoriesAdapter.OnFeedStoryClickListener() {
@Override
public void onFeedStoryClick(FeedStoryModel model, int position) {
final NavDirections action = FeedFragmentDirections.actionFeedFragmentToStoryViewerFragment(position, null, false, false, null, null, false, false);
NavHostFragment.findNavController(FeedFragment.this).navigate(action);
}
@Override
public void onFeedStoryLongClick(FeedStoryModel model, int position) {
navigateToProfile("@" + model.getProfileModel().getUsername());
}
}
);
final Context context = getContext(); final Context context = getContext();
if (context == null) return; if (context == null) return;
storiesRecyclerView = new RecyclerView(context); storiesRecyclerView = new RecyclerView(context);
@ -390,6 +391,7 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre
@Override @Override
public void onSuccess(final List<FeedStoryModel> result) { public void onSuccess(final List<FeedStoryModel> result) {
feedStoriesViewModel.getList().postValue(result); feedStoriesViewModel.getList().postValue(result);
feedStoriesAdapter.submitList(result);
storiesFetching = false; storiesFetching = false;
if (storyListMenu != null) storyListMenu.setVisible(true); if (storyListMenu != null) storyListMenu.setVisible(true);
updateSwipeRefreshState(); updateSwipeRefreshState();

View File

@ -869,7 +869,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
@Override @Override
public void onSuccess(final List<StoryModel> storyModels) { public void onSuccess(final List<StoryModel> storyModels) {
if (storyModels != null && !storyModels.isEmpty()) { if (storyModels != null && !storyModels.isEmpty()) {
profileDetailsBinding.mainProfileImage.setStoriesBorder(); profileDetailsBinding.mainProfileImage.setStoriesBorder(1);
hasStories = true; hasStories = true;
} }
} }

View File

@ -14,17 +14,21 @@ public final class FeedStoryModel implements Serializable {
private final ProfileModel profileModel; private final ProfileModel profileModel;
private final StoryModel firstStoryModel; private final StoryModel firstStoryModel;
private Boolean fullyRead; private Boolean fullyRead;
private final boolean isLive, isBestie;
private final long timestamp; private final long timestamp;
private final int mediaCount; private final int mediaCount;
public FeedStoryModel(final String storyMediaId, final ProfileModel profileModel, final boolean fullyRead, public FeedStoryModel(final String storyMediaId, final ProfileModel profileModel, final boolean fullyRead,
final long timestamp, final StoryModel firstStoryModel, final int mediaCount) { final long timestamp, final StoryModel firstStoryModel, final int mediaCount,
final boolean isLive, final boolean isBestie) {
this.storyMediaId = storyMediaId; this.storyMediaId = storyMediaId;
this.profileModel = profileModel; this.profileModel = profileModel;
this.fullyRead = fullyRead; this.fullyRead = fullyRead;
this.timestamp = timestamp; this.timestamp = timestamp;
this.firstStoryModel = firstStoryModel; this.firstStoryModel = firstStoryModel;
this.mediaCount = mediaCount; this.mediaCount = mediaCount;
this.isLive = isLive;
this.isBestie = isBestie;
} }
public String getStoryMediaId() { public String getStoryMediaId() {
@ -63,4 +67,12 @@ public final class FeedStoryModel implements Serializable {
public void setFullyRead(final boolean fullyRead) { public void setFullyRead(final boolean fullyRead) {
this.fullyRead = fullyRead; this.fullyRead = fullyRead;
} }
public boolean isLive() {
return isLive;
}
public boolean isBestie() {
return isBestie;
}
} }

View File

@ -14,7 +14,10 @@ public enum MediaItemType implements Serializable {
@SerializedName("8") @SerializedName("8")
MEDIA_TYPE_SLIDER(8), MEDIA_TYPE_SLIDER(8),
@SerializedName("11") @SerializedName("11")
MEDIA_TYPE_VOICE(11); MEDIA_TYPE_VOICE(11),
// 5 is arbitrary
@SerializedName("5")
MEDIA_TYPE_LIVE(5);
private final int id; private final int id;
private static final Map<Integer, MediaItemType> map = new HashMap<>(); private static final Map<Integer, MediaItemType> map = new HashMap<>();

View File

@ -1034,4 +1034,17 @@ public final class ResponseBodyUtils {
} }
return read; return read;
} }
public static StoryModel parseBroadcastItem(final JSONObject data) throws JSONException {
final StoryModel model = new StoryModel(data.getString("id"),
data.getString("cover_frame_url"),
data.getString("cover_frame_url"),
MediaItemType.MEDIA_TYPE_LIVE,
data.optLong("published_time", 0),
data.getJSONObject("user").getString("username"),
data.getJSONObject("user").getString("pk"),
false);
model.setVideoUrl(data.getString("dash_playback_url"));
return model;
}
} }

View File

@ -140,11 +140,6 @@ public final class Utils {
return mimeType.toLowerCase(); return mimeType.toLowerCase();
} }
public static void errorFinish(@NonNull final Activity activity) {
Toast.makeText(activity, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
activity.finish();
}
public static SimpleCache getSimpleCacheInstance(final Context context) { public static SimpleCache getSimpleCacheInstance(final Context context) {
if (context == null) { if (context == null) {
return null; return null;

View File

@ -121,12 +121,32 @@ public class StoriesService extends BaseService {
final long timestamp = node.getLong("latest_reel_media"); final long timestamp = node.getLong("latest_reel_media");
final int mediaCount = node.getInt("media_count"); final int mediaCount = node.getInt("media_count");
final boolean fullyRead = !node.isNull("seen") && node.getLong("seen") == timestamp; final boolean fullyRead = !node.isNull("seen") && node.getLong("seen") == timestamp;
final JSONObject itemJson = node.has("items") ? node.getJSONArray("items").getJSONObject(0) : null; final JSONObject itemJson = node.has("items") ? node.getJSONArray("items").optJSONObject(0) : null;
final boolean isBestie = node.optBoolean("has_besties_media", false);
StoryModel firstStoryModel = null; StoryModel firstStoryModel = null;
if (itemJson != null) { if (itemJson != null) {
firstStoryModel = ResponseBodyUtils.parseStoryItem(itemJson, false, false, null); firstStoryModel = ResponseBodyUtils.parseStoryItem(itemJson, false, false, null);
} }
feedStoryModels.add(new FeedStoryModel(id, profileModel, fullyRead, timestamp, firstStoryModel, mediaCount)); feedStoryModels.add(new FeedStoryModel(id, profileModel, fullyRead, timestamp, firstStoryModel, mediaCount, false, isBestie));
}
final JSONArray broadcasts = new JSONObject(body).getJSONArray("broadcasts");
for (int i = 0; i < broadcasts.length(); ++i) {
final JSONObject node = broadcasts.getJSONObject(i);
final JSONObject user = node.getJSONObject("broadcast_owner");
final ProfileModel profileModel = new ProfileModel(false, false, false,
user.getString("pk"),
user.getString("username"),
null, null, null,
user.getString("profile_pic_url"),
null, 0, 0, 0, false, false, false, false, false);
final String id = node.getString("id");
final long timestamp = node.getLong("published_time");
final JSONObject itemJson = node.has("items") ? node.getJSONArray("items").getJSONObject(0) : null;
StoryModel firstStoryModel = null;
if (itemJson != null) {
firstStoryModel = ResponseBodyUtils.parseBroadcastItem(itemJson);
}
feedStoryModels.add(new FeedStoryModel(id, profileModel, false, timestamp, firstStoryModel, 1, true, false));
} }
callback.onSuccess(sort(feedStoryModels)); callback.onSuccess(sort(feedStoryModels));
} catch (JSONException e) { } catch (JSONException e) {