mirror of
https://github.com/KokaKiwi/BarInsta
synced 2024-11-08 07:57:28 +00:00
Send stickers and gifs in DM
This commit is contained in:
parent
4bb77abb33
commit
6d73528387
@ -0,0 +1,107 @@
|
||||
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.drawee.drawable.ScalingUtils;
|
||||
import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder;
|
||||
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.util.Objects;
|
||||
|
||||
import awais.instagrabber.databinding.ItemMediaBinding;
|
||||
import awais.instagrabber.repositories.responses.giphy.GiphyGif;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
|
||||
public class GifItemsAdapter extends ListAdapter<GiphyGif, GifItemsAdapter.GifViewHolder> {
|
||||
|
||||
private static final DiffUtil.ItemCallback<GiphyGif> diffCallback = new DiffUtil.ItemCallback<GiphyGif>() {
|
||||
@Override
|
||||
public boolean areItemsTheSame(@NonNull final GiphyGif oldItem, @NonNull final GiphyGif newItem) {
|
||||
return Objects.equals(oldItem.getId(), newItem.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areContentsTheSame(@NonNull final GiphyGif oldItem, @NonNull final GiphyGif newItem) {
|
||||
return Objects.equals(oldItem.getId(), newItem.getId());
|
||||
}
|
||||
};
|
||||
|
||||
private final OnItemClickListener onItemClickListener;
|
||||
|
||||
public GifItemsAdapter(final OnItemClickListener onItemClickListener) {
|
||||
super(diffCallback);
|
||||
this.onItemClickListener = onItemClickListener;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public GifViewHolder 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 GifViewHolder(binding, onItemClickListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull final GifViewHolder holder, final int position) {
|
||||
holder.bind(getItem(position));
|
||||
}
|
||||
|
||||
public static class GifViewHolder extends RecyclerView.ViewHolder {
|
||||
private static final String TAG = GifViewHolder.class.getSimpleName();
|
||||
private static final int size = Utils.displayMetrics.widthPixels / 3;
|
||||
|
||||
private final ItemMediaBinding binding;
|
||||
private final OnItemClickListener onItemClickListener;
|
||||
|
||||
public GifViewHolder(@NonNull final ItemMediaBinding binding,
|
||||
final OnItemClickListener onItemClickListener) {
|
||||
super(binding.getRoot());
|
||||
this.binding = binding;
|
||||
this.onItemClickListener = onItemClickListener;
|
||||
binding.duration.setVisibility(View.GONE);
|
||||
final GenericDraweeHierarchyBuilder builder = new GenericDraweeHierarchyBuilder(itemView.getResources());
|
||||
builder.setActualImageScaleType(ScalingUtils.ScaleType.FIT_CENTER);
|
||||
binding.item.setHierarchy(builder.build());
|
||||
}
|
||||
|
||||
public void bind(final GiphyGif item) {
|
||||
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.parse(item.getImages().getFixedHeight().getWebp()))
|
||||
.setResizeOptions(ResizeOptions.forDimensions(size, size))
|
||||
.build();
|
||||
final PipelineDraweeControllerBuilder builder = Fresco.newDraweeControllerBuilder()
|
||||
.setImageRequest(request)
|
||||
.setAutoPlayAnimations(true)
|
||||
.setControllerListener(controllerListener);
|
||||
binding.item.setController(builder.build());
|
||||
}
|
||||
}
|
||||
|
||||
public interface OnItemClickListener {
|
||||
void onItemClick(GiphyGif giphyGif);
|
||||
}
|
||||
}
|
@ -0,0 +1,150 @@
|
||||
package awais.instagrabber.dialogs;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.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 com.google.android.material.snackbar.Snackbar;
|
||||
|
||||
import awais.instagrabber.R;
|
||||
import awais.instagrabber.adapters.GifItemsAdapter;
|
||||
import awais.instagrabber.customviews.helpers.TextWatcherAdapter;
|
||||
import awais.instagrabber.databinding.LayoutGifPickerBinding;
|
||||
import awais.instagrabber.repositories.responses.giphy.GiphyGif;
|
||||
import awais.instagrabber.utils.Debouncer;
|
||||
import awais.instagrabber.utils.TextUtils;
|
||||
import awais.instagrabber.viewmodels.GifPickerViewModel;
|
||||
|
||||
public class GifPickerBottomDialogFragment extends BottomSheetDialogFragment {
|
||||
private static final String TAG = GifPickerBottomDialogFragment.class.getSimpleName();
|
||||
private static final int INPUT_DEBOUNCE_INTERVAL = 500;
|
||||
private static final String INPUT_KEY = "gif_search_input";
|
||||
|
||||
private LayoutGifPickerBinding binding;
|
||||
private GifPickerViewModel viewModel;
|
||||
private GifItemsAdapter gifItemsAdapter;
|
||||
private OnSelectListener onSelectListener;
|
||||
private Debouncer<String> inputDebouncer;
|
||||
|
||||
public static GifPickerBottomDialogFragment newInstance() {
|
||||
final Bundle args = new Bundle();
|
||||
final GifPickerBottomDialogFragment fragment = new GifPickerBottomDialogFragment();
|
||||
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);
|
||||
final Debouncer.Callback<String> callback = new Debouncer.Callback<String>() {
|
||||
@Override
|
||||
public void call(final String key) {
|
||||
final Editable text = binding.input.getText();
|
||||
if (TextUtils.isEmpty(text)) {
|
||||
viewModel.search(null);
|
||||
return;
|
||||
}
|
||||
viewModel.search(text.toString().trim());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(final Throwable t) {
|
||||
Log.e(TAG, "onError: ", t);
|
||||
}
|
||||
};
|
||||
inputDebouncer = new Debouncer<>(callback, INPUT_DEBOUNCE_INTERVAL);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) {
|
||||
binding = LayoutGifPickerBinding.inflate(inflater, container, false);
|
||||
viewModel = new ViewModelProvider(this).get(GifPickerViewModel.class);
|
||||
return binding.getRoot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull final View view, @Nullable final Bundle savedInstanceState) {
|
||||
init();
|
||||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
setupList();
|
||||
setupInput();
|
||||
setupObservers();
|
||||
}
|
||||
|
||||
private void setupList() {
|
||||
final Context context = getContext();
|
||||
if (context == null) return;
|
||||
binding.gifList.setLayoutManager(new GridLayoutManager(context, 3));
|
||||
binding.gifList.setHasFixedSize(true);
|
||||
gifItemsAdapter = new GifItemsAdapter(entry -> {
|
||||
if (onSelectListener == null) return;
|
||||
onSelectListener.onSelect(entry);
|
||||
});
|
||||
binding.gifList.setAdapter(gifItemsAdapter);
|
||||
}
|
||||
|
||||
private void setupInput() {
|
||||
binding.input.addTextChangedListener(new TextWatcherAdapter() {
|
||||
@Override
|
||||
public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
|
||||
inputDebouncer.call(INPUT_KEY);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setupObservers() {
|
||||
viewModel.getImages().observe(getViewLifecycleOwner(), imagesResource -> {
|
||||
if (imagesResource == null) return;
|
||||
switch (imagesResource.status) {
|
||||
case SUCCESS:
|
||||
gifItemsAdapter.submitList(imagesResource.data);
|
||||
break;
|
||||
case ERROR:
|
||||
final Context context = getContext();
|
||||
if (context != null && imagesResource.message != null) {
|
||||
Snackbar.make(context, binding.getRoot(), imagesResource.message, Snackbar.LENGTH_LONG);
|
||||
}
|
||||
break;
|
||||
case LOADING:
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setOnSelectListener(final OnSelectListener onSelectListener) {
|
||||
this.onSelectListener = onSelectListener;
|
||||
}
|
||||
|
||||
public interface OnSelectListener {
|
||||
void onSelect(GiphyGif giphyGif);
|
||||
}
|
||||
}
|
@ -81,6 +81,7 @@ import awais.instagrabber.customviews.helpers.SwipeAndRestoreItemTouchHelperCall
|
||||
import awais.instagrabber.customviews.helpers.TextWatcherAdapter;
|
||||
import awais.instagrabber.databinding.FragmentDirectMessagesThreadBinding;
|
||||
import awais.instagrabber.dialogs.DirectItemReactionDialogFragment;
|
||||
import awais.instagrabber.dialogs.GifPickerBottomDialogFragment;
|
||||
import awais.instagrabber.dialogs.MediaPickerBottomDialogFragment;
|
||||
import awais.instagrabber.fragments.PostViewV2Fragment;
|
||||
import awais.instagrabber.fragments.UserSearchFragment;
|
||||
@ -737,6 +738,7 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
||||
|
||||
private void hideInput() {
|
||||
binding.emojiToggle.setVisibility(View.GONE);
|
||||
binding.gif.setVisibility(View.GONE);
|
||||
binding.camera.setVisibility(View.GONE);
|
||||
binding.gallery.setVisibility(View.GONE);
|
||||
binding.input.setVisibility(View.GONE);
|
||||
@ -750,6 +752,7 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
||||
|
||||
private void showInput() {
|
||||
binding.emojiToggle.setVisibility(View.VISIBLE);
|
||||
binding.gif.setVisibility(View.VISIBLE);
|
||||
binding.camera.setVisibility(View.VISIBLE);
|
||||
binding.gallery.setVisibility(View.VISIBLE);
|
||||
binding.input.setVisibility(View.VISIBLE);
|
||||
@ -788,16 +791,18 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
||||
binding.send.setListenForRecord(true);
|
||||
startIconAnimation();
|
||||
}
|
||||
binding.gallery.setVisibility(View.VISIBLE);
|
||||
binding.gif.setVisibility(View.VISIBLE);
|
||||
binding.camera.setVisibility(View.VISIBLE);
|
||||
binding.gallery.setVisibility(View.VISIBLE);
|
||||
return;
|
||||
}
|
||||
if (binding.send.isListenForRecord()) {
|
||||
binding.send.setListenForRecord(false);
|
||||
startIconAnimation();
|
||||
}
|
||||
binding.gallery.setVisibility(View.GONE);
|
||||
binding.gif.setVisibility(View.GONE);
|
||||
binding.camera.setVisibility(View.GONE);
|
||||
binding.gallery.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
private String getDirectItemPreviewText(final DirectItem item) {
|
||||
@ -937,8 +942,9 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
||||
public void onStart() {
|
||||
isRecording = true;
|
||||
binding.input.setHint(null);
|
||||
binding.gallery.setVisibility(View.GONE);
|
||||
binding.gif.setVisibility(View.GONE);
|
||||
binding.camera.setVisibility(View.GONE);
|
||||
binding.gallery.setVisibility(View.GONE);
|
||||
if (PermissionUtils.hasAudioRecordPerms(context)) {
|
||||
viewModel.startRecording();
|
||||
return;
|
||||
@ -958,8 +964,9 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
||||
public void onFinish(final long recordTime) {
|
||||
Log.d(TAG, "onFinish");
|
||||
binding.input.setHint("Message");
|
||||
binding.gallery.setVisibility(View.VISIBLE);
|
||||
binding.gif.setVisibility(View.VISIBLE);
|
||||
binding.camera.setVisibility(View.VISIBLE);
|
||||
binding.gallery.setVisibility(View.VISIBLE);
|
||||
viewModel.stopRecording(false);
|
||||
isRecording = false;
|
||||
}
|
||||
@ -971,16 +978,18 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
||||
if (PermissionUtils.hasAudioRecordPerms(context)) {
|
||||
tooltip.show(binding.send);
|
||||
}
|
||||
binding.gallery.setVisibility(View.VISIBLE);
|
||||
binding.gif.setVisibility(View.VISIBLE);
|
||||
binding.camera.setVisibility(View.VISIBLE);
|
||||
binding.gallery.setVisibility(View.VISIBLE);
|
||||
viewModel.stopRecording(true);
|
||||
isRecording = false;
|
||||
}
|
||||
});
|
||||
binding.recordView.setOnBasketAnimationEndListener(() -> {
|
||||
binding.input.setHint(R.string.dms_thread_message_hint);
|
||||
binding.gallery.setVisibility(View.VISIBLE);
|
||||
binding.gif.setVisibility(View.VISIBLE);
|
||||
binding.camera.setVisibility(View.VISIBLE);
|
||||
binding.gallery.setVisibility(View.VISIBLE);
|
||||
});
|
||||
binding.input.addTextChangedListener(new TextWatcherAdapter() {
|
||||
// int prevLength = 0;
|
||||
@ -1057,6 +1066,16 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
|
||||
mediaPicker.show(getChildFragmentManager(), "MediaPicker");
|
||||
hideKeyboard(true);
|
||||
});
|
||||
binding.gif.setOnClickListener(v -> {
|
||||
final GifPickerBottomDialogFragment gifPicker = GifPickerBottomDialogFragment.newInstance();
|
||||
gifPicker.setOnSelectListener(giphyGif -> {
|
||||
gifPicker.dismiss();
|
||||
if (giphyGif == null) return;
|
||||
handleSentMessage(viewModel.sendAnimatedMedia(giphyGif));
|
||||
});
|
||||
gifPicker.show(getChildFragmentManager(), "GifPicker");
|
||||
hideKeyboard(true);
|
||||
});
|
||||
binding.camera.setOnClickListener(v -> {
|
||||
final Intent intent = new Intent(context, CameraActivity.class);
|
||||
startActivityForResult(intent, CAMERA_REQUEST_CODE);
|
||||
|
@ -53,6 +53,7 @@ import awais.instagrabber.repositories.responses.directmessages.DirectThreadDeta
|
||||
import awais.instagrabber.repositories.responses.directmessages.DirectThreadFeedResponse;
|
||||
import awais.instagrabber.repositories.responses.directmessages.DirectThreadParticipantRequestsResponse;
|
||||
import awais.instagrabber.repositories.responses.directmessages.RankedRecipient;
|
||||
import awais.instagrabber.repositories.responses.giphy.GiphyGif;
|
||||
import awais.instagrabber.utils.BitmapUtils;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.CookieUtils;
|
||||
@ -641,6 +642,24 @@ public final class ThreadManager {
|
||||
return data;
|
||||
}
|
||||
|
||||
public LiveData<Resource<Object>> sendAnimatedMedia(@NonNull final GiphyGif giphyGif) {
|
||||
final MutableLiveData<Resource<Object>> data = new MutableLiveData<>();
|
||||
final Long userId = getCurrentUserId(data);
|
||||
if (userId == null) return data;
|
||||
final String clientContext = UUID.randomUUID().toString();
|
||||
final DirectItem directItem = DirectItemFactory.createAnimatedMedia(userId, clientContext, giphyGif);
|
||||
directItem.setPending(true);
|
||||
addItems(0, Collections.singletonList(directItem));
|
||||
data.postValue(Resource.loading(directItem));
|
||||
final Call<DirectThreadBroadcastResponse> request = service.broadcastAnimatedMedia(
|
||||
clientContext,
|
||||
threadIdOrUserIds,
|
||||
giphyGif
|
||||
);
|
||||
enqueueRequest(request, data, directItem);
|
||||
return data;
|
||||
}
|
||||
|
||||
public void sendVoice(@NonNull final MutableLiveData<Resource<Object>> data,
|
||||
@NonNull final Uri uri,
|
||||
@NonNull final List<Float> waveform,
|
||||
|
@ -7,7 +7,8 @@ public enum BroadcastItemType {
|
||||
IMAGE("configure_photo"),
|
||||
LINK("link"),
|
||||
VIDEO("configure_video"),
|
||||
VOICE("share_voice");
|
||||
VOICE("share_voice"),
|
||||
ANIMATED_MEDIA("animated_media");
|
||||
|
||||
private final String value;
|
||||
|
||||
|
@ -0,0 +1,14 @@
|
||||
package awais.instagrabber.repositories;
|
||||
|
||||
import awais.instagrabber.repositories.responses.giphy.GiphyGifResponse;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.http.GET;
|
||||
import retrofit2.http.Query;
|
||||
|
||||
public interface GifRepository {
|
||||
|
||||
@GET("/api/v1/creatives/story_media_search_keyed_format/")
|
||||
Call<GiphyGifResponse> searchGiphyGifs(@Query("request_surface") final String requestSurface,
|
||||
@Query("q") final String query,
|
||||
@Query("media_types") final String mediaTypes);
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package awais.instagrabber.repositories.requests.directmessages;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import awais.instagrabber.models.enums.BroadcastItemType;
|
||||
import awais.instagrabber.repositories.responses.giphy.GiphyGif;
|
||||
|
||||
public class AnimatedMediaBroadcastOptions extends BroadcastOptions {
|
||||
|
||||
private final GiphyGif giphyGif;
|
||||
|
||||
public AnimatedMediaBroadcastOptions(final String clientContext,
|
||||
final ThreadIdOrUserIds threadIdOrUserIds,
|
||||
final GiphyGif giphyGif) {
|
||||
super(clientContext, threadIdOrUserIds, BroadcastItemType.ANIMATED_MEDIA);
|
||||
this.giphyGif = giphyGif;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getFormMap() {
|
||||
final Map<String, String> form = new HashMap<>();
|
||||
form.put("is_sticker", String.valueOf(giphyGif.isSticker()));
|
||||
form.put("id", giphyGif.getId());
|
||||
return form;
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
package awais.instagrabber.repositories.responses.giphy;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class GiphyGif {
|
||||
private final String type;
|
||||
private final String id;
|
||||
private final String title;
|
||||
private final int isSticker;
|
||||
private final GiphyGifImages images;
|
||||
|
||||
public GiphyGif(final String type, final String id, final String title, final int isSticker, final GiphyGifImages images) {
|
||||
this.type = type;
|
||||
this.id = id;
|
||||
this.title = title;
|
||||
this.isSticker = isSticker;
|
||||
this.images = images;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public boolean isSticker() {
|
||||
return isSticker == 1;
|
||||
}
|
||||
|
||||
public GiphyGifImages getImages() {
|
||||
return images;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
final GiphyGif giphyGif = (GiphyGif) o;
|
||||
return isSticker == giphyGif.isSticker &&
|
||||
Objects.equals(type, giphyGif.type) &&
|
||||
Objects.equals(id, giphyGif.id) &&
|
||||
Objects.equals(title, giphyGif.title) &&
|
||||
Objects.equals(images, giphyGif.images);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(type, id, title, isSticker, images);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GiphyGif{" +
|
||||
"type='" + type + '\'' +
|
||||
", id='" + id + '\'' +
|
||||
", title='" + title + '\'' +
|
||||
", isSticker=" + isSticker() +
|
||||
", images=" + images +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package awais.instagrabber.repositories.responses.giphy;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class GiphyGifImage {
|
||||
private final int height;
|
||||
private final int width;
|
||||
private final long webpSize;
|
||||
private final String webp;
|
||||
|
||||
public GiphyGifImage(final int height, final int width, final long webpSize, final String webp) {
|
||||
this.height = height;
|
||||
this.width = width;
|
||||
this.webpSize = webpSize;
|
||||
this.webp = webp;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public long getWebpSize() {
|
||||
return webpSize;
|
||||
}
|
||||
|
||||
public String getWebp() {
|
||||
return webp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
final GiphyGifImage that = (GiphyGifImage) o;
|
||||
return height == that.height &&
|
||||
width == that.width &&
|
||||
webpSize == that.webpSize &&
|
||||
Objects.equals(webp, that.webp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(height, width, webpSize, webp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GiphyGifImage{" +
|
||||
"height=" + height +
|
||||
", width=" + width +
|
||||
", webpSize=" + webpSize +
|
||||
", webp='" + webp + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package awais.instagrabber.repositories.responses.giphy;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import awais.instagrabber.repositories.responses.AnimatedMediaFixedHeight;
|
||||
|
||||
public class GiphyGifImages {
|
||||
private final AnimatedMediaFixedHeight fixedHeight;
|
||||
|
||||
public GiphyGifImages(final AnimatedMediaFixedHeight fixedHeight) {
|
||||
this.fixedHeight = fixedHeight;
|
||||
}
|
||||
|
||||
public AnimatedMediaFixedHeight getFixedHeight() {
|
||||
return fixedHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
final GiphyGifImages that = (GiphyGifImages) o;
|
||||
return Objects.equals(fixedHeight, that.fixedHeight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(fixedHeight);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GiphyGifImages{" +
|
||||
"fixedHeight=" + fixedHeight +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package awais.instagrabber.repositories.responses.giphy;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class GiphyGifResponse {
|
||||
private final GiphyGifResults results;
|
||||
private final String status;
|
||||
|
||||
public GiphyGifResponse(final GiphyGifResults results, final String status) {
|
||||
this.results = results;
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public GiphyGifResults getResults() {
|
||||
return results;
|
||||
}
|
||||
|
||||
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 GiphyGifResponse that = (GiphyGifResponse) o;
|
||||
return Objects.equals(results, that.results) &&
|
||||
Objects.equals(status, that.status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(results, status);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GiphyGifResponse{" +
|
||||
"results=" + results +
|
||||
", status='" + status + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package awais.instagrabber.repositories.responses.giphy;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class GiphyGifResults {
|
||||
private final List<GiphyGif> giphyGifs;
|
||||
private final List<GiphyGif> giphy;
|
||||
|
||||
public GiphyGifResults(final List<GiphyGif> giphyGifs, final List<GiphyGif> giphy) {
|
||||
this.giphyGifs = giphyGifs;
|
||||
this.giphy = giphy;
|
||||
}
|
||||
|
||||
public List<GiphyGif> getGiphyGifs() {
|
||||
return giphyGifs;
|
||||
}
|
||||
|
||||
public List<GiphyGif> getGiphy() {
|
||||
return giphy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
final GiphyGifResults that = (GiphyGifResults) o;
|
||||
return Objects.equals(giphyGifs, that.giphyGifs) &&
|
||||
Objects.equals(giphy, that.giphy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(giphyGifs, giphy);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GiphyGifResults{" +
|
||||
"giphyGifs=" + giphyGifs +
|
||||
", giphy=" + giphy +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -15,6 +15,7 @@ import awais.instagrabber.models.enums.DirectItemType;
|
||||
import awais.instagrabber.models.enums.MediaItemType;
|
||||
import awais.instagrabber.repositories.responses.User;
|
||||
import awais.instagrabber.repositories.responses.directmessages.DirectItem;
|
||||
import awais.instagrabber.repositories.responses.directmessages.DirectItemAnimatedMedia;
|
||||
import awais.instagrabber.repositories.responses.directmessages.DirectItemReelShare;
|
||||
import awais.instagrabber.repositories.responses.directmessages.DirectItemVisualMedia;
|
||||
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
|
||||
@ -84,11 +85,16 @@ public final class DMUtils {
|
||||
message = item.getPlaceholder().getMessage();
|
||||
break;
|
||||
case MEDIA_SHARE:
|
||||
subtitle = resources.getString(R.string.dms_inbox_shared_post, username != null ? username : "",
|
||||
item.getMediaShare().getUser().getUsername());
|
||||
final User mediaShareUser = item.getMediaShare().getUser();
|
||||
subtitle = resources.getString(R.string.dms_inbox_shared_post,
|
||||
username != null ? username : "",
|
||||
mediaShareUser == null ? "" : mediaShareUser.getUsername());
|
||||
break;
|
||||
case ANIMATED_MEDIA:
|
||||
subtitle = resources.getString(R.string.dms_inbox_shared_gif, username != null ? username : "");
|
||||
final DirectItemAnimatedMedia animatedMedia = item.getAnimatedMedia();
|
||||
subtitle = resources.getString(animatedMedia.isSticker() ? R.string.dms_inbox_shared_sticker
|
||||
: R.string.dms_inbox_shared_gif,
|
||||
username != null ? username : "");
|
||||
break;
|
||||
case PROFILE:
|
||||
subtitle = resources
|
||||
@ -111,8 +117,10 @@ public final class DMUtils {
|
||||
final int format = reelType.equals("highlight_reel")
|
||||
? R.string.dms_inbox_shared_highlight
|
||||
: R.string.dms_inbox_shared_story;
|
||||
subtitle = resources.getString(format, username != null ? username : "",
|
||||
item.getStoryShare().getMedia().getUser().getUsername());
|
||||
final User storyShareMediaUser = item.getStoryShare().getMedia().getUser();
|
||||
subtitle = resources.getString(format,
|
||||
username != null ? username : "",
|
||||
storyShareMediaUser == null ? "" : storyShareMediaUser.getUsername());
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -126,12 +134,16 @@ public final class DMUtils {
|
||||
subtitle = item.getVideoCallEvent().getDescription();
|
||||
break;
|
||||
case CLIP:
|
||||
subtitle = resources.getString(R.string.dms_inbox_shared_clip, username != null ? username : "",
|
||||
item.getClip().getClip().getUser().getUsername());
|
||||
final User clipUser = item.getClip().getClip().getUser();
|
||||
subtitle = resources.getString(R.string.dms_inbox_shared_clip,
|
||||
username != null ? username : "",
|
||||
clipUser == null ? "" : clipUser.getUsername());
|
||||
break;
|
||||
case FELIX_SHARE:
|
||||
subtitle = resources.getString(R.string.dms_inbox_shared_igtv, username != null ? username : "",
|
||||
item.getFelixShare().getVideo().getUser().getUsername());
|
||||
final User felixShareVideoUser = item.getFelixShare().getVideo().getUser();
|
||||
subtitle = resources.getString(R.string.dms_inbox_shared_igtv,
|
||||
username != null ? username : "",
|
||||
felixShareVideoUser == null ? "" : felixShareVideoUser.getUsername());
|
||||
break;
|
||||
case RAVEN_MEDIA:
|
||||
subtitle = getRavenMediaSubtitle(item, resources, username);
|
||||
|
@ -8,13 +8,16 @@ import java.util.UUID;
|
||||
|
||||
import awais.instagrabber.models.enums.DirectItemType;
|
||||
import awais.instagrabber.models.enums.MediaItemType;
|
||||
import awais.instagrabber.repositories.responses.AnimatedMediaImages;
|
||||
import awais.instagrabber.repositories.responses.Audio;
|
||||
import awais.instagrabber.repositories.responses.ImageVersions2;
|
||||
import awais.instagrabber.repositories.responses.Media;
|
||||
import awais.instagrabber.repositories.responses.MediaCandidate;
|
||||
import awais.instagrabber.repositories.responses.VideoVersion;
|
||||
import awais.instagrabber.repositories.responses.directmessages.DirectItem;
|
||||
import awais.instagrabber.repositories.responses.directmessages.DirectItemAnimatedMedia;
|
||||
import awais.instagrabber.repositories.responses.directmessages.DirectItemVoiceMedia;
|
||||
import awais.instagrabber.repositories.responses.giphy.GiphyGif;
|
||||
|
||||
public final class DirectItemFactory {
|
||||
|
||||
@ -213,4 +216,45 @@ public final class DirectItemFactory {
|
||||
0,
|
||||
false);
|
||||
}
|
||||
|
||||
public static DirectItem createAnimatedMedia(final long userId,
|
||||
final String clientContext,
|
||||
final GiphyGif giphyGif) {
|
||||
final AnimatedMediaImages animatedImages = new AnimatedMediaImages(giphyGif.getImages().getFixedHeight());
|
||||
final DirectItemAnimatedMedia animateMedia = new DirectItemAnimatedMedia(
|
||||
giphyGif.getId(),
|
||||
animatedImages,
|
||||
false,
|
||||
giphyGif.isSticker()
|
||||
);
|
||||
return new DirectItem(
|
||||
UUID.randomUUID().toString(),
|
||||
userId,
|
||||
System.currentTimeMillis() * 1000,
|
||||
DirectItemType.ANIMATED_MEDIA,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
clientContext,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
animateMedia,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
0,
|
||||
false
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import awais.instagrabber.repositories.responses.User;
|
||||
import awais.instagrabber.repositories.responses.directmessages.DirectItem;
|
||||
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
|
||||
import awais.instagrabber.repositories.responses.directmessages.RankedRecipient;
|
||||
import awais.instagrabber.repositories.responses.giphy.GiphyGif;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.CookieUtils;
|
||||
import awais.instagrabber.utils.DirectoryUtils;
|
||||
@ -219,6 +220,10 @@ public class DirectThreadViewModel extends AndroidViewModel {
|
||||
return threadManager.unsend(item);
|
||||
}
|
||||
|
||||
public LiveData<Resource<Object>> sendAnimatedMedia(@NonNull final GiphyGif giphyGif) {
|
||||
return threadManager.sendAnimatedMedia(giphyGif);
|
||||
}
|
||||
|
||||
public User getCurrentUser() {
|
||||
return currentUser;
|
||||
}
|
||||
|
@ -0,0 +1,121 @@
|
||||
package awais.instagrabber.viewmodels;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import awais.instagrabber.models.Resource;
|
||||
import awais.instagrabber.repositories.responses.giphy.GiphyGif;
|
||||
import awais.instagrabber.repositories.responses.giphy.GiphyGifResponse;
|
||||
import awais.instagrabber.repositories.responses.giphy.GiphyGifResults;
|
||||
import awais.instagrabber.webservices.GifService;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
|
||||
public class GifPickerViewModel extends ViewModel {
|
||||
private static final String TAG = GifPickerViewModel.class.getSimpleName();
|
||||
|
||||
private final MutableLiveData<Resource<List<GiphyGif>>> images = new MutableLiveData<>(Resource.success(Collections.emptyList()));
|
||||
private final GifService gifService;
|
||||
|
||||
private Call<GiphyGifResponse> searchRequest;
|
||||
|
||||
public GifPickerViewModel() {
|
||||
gifService = GifService.getInstance();
|
||||
search(null);
|
||||
}
|
||||
|
||||
public LiveData<Resource<List<GiphyGif>>> getImages() {
|
||||
return images;
|
||||
}
|
||||
|
||||
public void search(final String query) {
|
||||
final Resource<List<GiphyGif>> currentValue = images.getValue();
|
||||
if (currentValue != null && currentValue.status == Resource.Status.LOADING) {
|
||||
cancelSearchRequest();
|
||||
}
|
||||
images.postValue(Resource.loading(getCurrentImages()));
|
||||
searchRequest = gifService.searchGiphyGifs(query, query != null);
|
||||
searchRequest.enqueue(new Callback<GiphyGifResponse>() {
|
||||
@Override
|
||||
public void onResponse(@NonNull final Call<GiphyGifResponse> call,
|
||||
@NonNull final Response<GiphyGifResponse> response) {
|
||||
if (response.isSuccessful()) {
|
||||
parseResponse(response);
|
||||
return;
|
||||
}
|
||||
if (response.errorBody() != null) {
|
||||
try {
|
||||
final String string = response.errorBody().string();
|
||||
final String msg = String.format(Locale.US,
|
||||
"onResponse: url: %s, responseCode: %d, errorBody: %s",
|
||||
call.request().url().toString(),
|
||||
response.code(),
|
||||
string);
|
||||
images.postValue(Resource.error(msg, getCurrentImages()));
|
||||
Log.e(TAG, msg);
|
||||
} catch (IOException e) {
|
||||
images.postValue(Resource.error(e.getMessage(), getCurrentImages()));
|
||||
Log.e(TAG, "onResponse: ", e);
|
||||
}
|
||||
}
|
||||
images.postValue(Resource.error("request was not successful and response error body was null", getCurrentImages()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull final Call<GiphyGifResponse> call,
|
||||
@NonNull final Throwable t) {
|
||||
images.postValue(Resource.error(t.getMessage(), getCurrentImages()));
|
||||
Log.e(TAG, "enqueueRequest: onFailure: ", t);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void parseResponse(final Response<GiphyGifResponse> response) {
|
||||
final GiphyGifResponse giphyGifResponse = response.body();
|
||||
if (giphyGifResponse == null) {
|
||||
images.postValue(Resource.error("Response body was null", getCurrentImages()));
|
||||
return;
|
||||
}
|
||||
final GiphyGifResults results = giphyGifResponse.getResults();
|
||||
images.postValue(Resource.success(
|
||||
ImmutableList.<GiphyGif>builder()
|
||||
.addAll(results.getGiphy() == null ? Collections.emptyList() : results.getGiphy())
|
||||
.addAll(results.getGiphyGifs() == null ? Collections.emptyList() : results.getGiphyGifs())
|
||||
.build()
|
||||
));
|
||||
}
|
||||
|
||||
// @NonNull
|
||||
// private List<GiphyGifImage> getGiphyGifImages(@NonNull final List<GiphyGif> giphy) {
|
||||
// return giphy.stream()
|
||||
// .map(giphyGif -> {
|
||||
// final GiphyGifImages images = giphyGif.getImages();
|
||||
// if (images == null) return null;
|
||||
// return images.getOriginal();
|
||||
// })
|
||||
// .filter(Objects::nonNull)
|
||||
// .collect(Collectors.toList());
|
||||
// }
|
||||
|
||||
private List<GiphyGif> getCurrentImages() {
|
||||
final Resource<List<GiphyGif>> value = images.getValue();
|
||||
return value == null ? Collections.emptyList() : value.data;
|
||||
}
|
||||
|
||||
public void cancelSearchRequest() {
|
||||
if (searchRequest == null) return;
|
||||
searchRequest.cancel();
|
||||
}
|
||||
}
|
@ -17,6 +17,7 @@ import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import awais.instagrabber.repositories.DirectMessagesRepository;
|
||||
import awais.instagrabber.repositories.requests.directmessages.AnimatedMediaBroadcastOptions;
|
||||
import awais.instagrabber.repositories.requests.directmessages.BroadcastOptions;
|
||||
import awais.instagrabber.repositories.requests.directmessages.BroadcastOptions.ThreadIdOrUserIds;
|
||||
import awais.instagrabber.repositories.requests.directmessages.LinkBroadcastOptions;
|
||||
@ -34,6 +35,7 @@ import awais.instagrabber.repositories.responses.directmessages.DirectThreadDeta
|
||||
import awais.instagrabber.repositories.responses.directmessages.DirectThreadFeedResponse;
|
||||
import awais.instagrabber.repositories.responses.directmessages.DirectThreadParticipantRequestsResponse;
|
||||
import awais.instagrabber.repositories.responses.directmessages.RankedRecipientsResponse;
|
||||
import awais.instagrabber.repositories.responses.giphy.GiphyGif;
|
||||
import awais.instagrabber.utils.TextUtils;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
import retrofit2.Call;
|
||||
@ -182,6 +184,11 @@ public class DirectMessagesService extends BaseService {
|
||||
return broadcast(new ReactionBroadcastOptions(clientContext, threadIdOrUserIds, itemId, emoji, delete));
|
||||
}
|
||||
|
||||
public Call<DirectThreadBroadcastResponse> broadcastAnimatedMedia(final String clientContext,
|
||||
final ThreadIdOrUserIds threadIdOrUserIds,
|
||||
final GiphyGif giphyGif) {
|
||||
return broadcast(new AnimatedMediaBroadcastOptions(clientContext, threadIdOrUserIds, giphyGif));
|
||||
}
|
||||
|
||||
private Call<DirectThreadBroadcastResponse> broadcast(@NonNull final BroadcastOptions broadcastOptions) {
|
||||
if (TextUtils.isEmpty(broadcastOptions.getClientContext())) {
|
||||
|
@ -0,0 +1,33 @@
|
||||
package awais.instagrabber.webservices;
|
||||
|
||||
import awais.instagrabber.repositories.GifRepository;
|
||||
import awais.instagrabber.repositories.responses.giphy.GiphyGifResponse;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Retrofit;
|
||||
|
||||
public class GifService extends BaseService {
|
||||
|
||||
private final GifRepository repository;
|
||||
|
||||
private static GifService instance;
|
||||
|
||||
private GifService() {
|
||||
final Retrofit retrofit = getRetrofitBuilder()
|
||||
.baseUrl("https://i.instagram.com")
|
||||
.build();
|
||||
repository = retrofit.create(GifRepository.class);
|
||||
}
|
||||
|
||||
public static GifService getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new GifService();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public Call<GiphyGifResponse> searchGiphyGifs(final String query,
|
||||
final boolean includeGifs) {
|
||||
final String mediaTypes = includeGifs ? "[\"giphy_gifs\",\"giphy\"]" : "[\"giphy\"]";
|
||||
return repository.searchGiphyGifs("direct", query, mediaTypes);
|
||||
}
|
||||
}
|
10
app/src/main/res/drawable/ic_round_gif_24.xml
Normal file
10
app/src/main/res/drawable/ic_round_gif_24.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M12.25,9c0.41,0 0.75,0.34 0.75,0.75v4.5c0,0.41 -0.34,0.75 -0.75,0.75s-0.75,-0.34 -0.75,-0.75v-4.5c0,-0.41 0.34,-0.75 0.75,-0.75zM10,9.75c0,-0.41 -0.34,-0.75 -0.75,-0.75L6,9c-0.6,0 -1,0.5 -1,1v4c0,0.5 0.4,1 1,1h3c0.6,0 1,-0.5 1,-1v-1.25c0,-0.41 -0.34,-0.75 -0.75,-0.75s-0.75,0.34 -0.75,0.75v0.75h-2v-3h2.75c0.41,0 0.75,-0.34 0.75,-0.75zM19,9.75c0,-0.41 -0.34,-0.75 -0.75,-0.75L15.5,9c-0.55,0 -1,0.45 -1,1v4.25c0,0.41 0.34,0.75 0.75,0.75s0.75,-0.34 0.75,-0.75L16,13h1.25c0.41,0 0.75,-0.34 0.75,-0.75s-0.34,-0.75 -0.75,-0.75L16,11.5v-1h2.25c0.41,0 0.75,-0.34 0.75,-0.75z"/>
|
||||
</vector>
|
@ -120,7 +120,8 @@
|
||||
app:layout_constraintBottom_toBottomOf="@id/input"
|
||||
app:layout_constraintEnd_toStartOf="@id/send"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/input" />
|
||||
app:layout_constraintTop_toTopOf="@id/input"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/emoji_toggle"
|
||||
@ -143,7 +144,8 @@
|
||||
app:rippleColor="@color/grey_500"
|
||||
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.App.Button.Circle"
|
||||
app:strokeColor="@color/black"
|
||||
app:strokeWidth="1dp" />
|
||||
app:strokeWidth="1dp"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<awais.instagrabber.customviews.KeyNotifyingEmojiEditText
|
||||
android:id="@+id/input"
|
||||
@ -158,16 +160,32 @@
|
||||
android:textColorHint="@color/grey_500"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/camera"
|
||||
app:layout_constraintEnd_toStartOf="@id/gif"
|
||||
app:layout_constraintStart_toEndOf="@id/emoji_toggle"
|
||||
app:layout_constraintTop_toBottomOf="@id/reply_preview_text"
|
||||
app:layout_goneMarginBottom="4dp"
|
||||
app:layout_goneMarginEnd="24dp" />
|
||||
app:layout_goneMarginEnd="24dp"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageButton
|
||||
android:id="@+id/gif"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:scaleType="fitCenter"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="@id/input_bg"
|
||||
app:layout_constraintEnd_toStartOf="@id/camera"
|
||||
app:layout_constraintStart_toEndOf="@id/input"
|
||||
app:layout_constraintTop_toTopOf="@id/input"
|
||||
app:srcCompat="@drawable/ic_round_gif_24"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageButton
|
||||
android:id="@+id/camera"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginStart="4dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:paddingStart="4dp"
|
||||
android:paddingEnd="4dp"
|
||||
@ -175,10 +193,10 @@
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="@id/input_bg"
|
||||
app:layout_constraintEnd_toStartOf="@id/gallery"
|
||||
app:layout_constraintStart_toEndOf="@id/input"
|
||||
app:layout_constraintStart_toEndOf="@id/gif"
|
||||
app:layout_constraintTop_toTopOf="@id/input"
|
||||
app:srcCompat="@drawable/ic_camera_24"
|
||||
tools:visibility="gone" />
|
||||
tools:visibility="visible" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageButton
|
||||
android:id="@+id/gallery"
|
||||
@ -196,7 +214,7 @@
|
||||
app:layout_constraintEnd_toStartOf="@id/send"
|
||||
app:layout_constraintStart_toEndOf="@id/camera"
|
||||
app:layout_constraintTop_toTopOf="@id/input"
|
||||
tools:visibility="gone" />
|
||||
tools:visibility="visible" />
|
||||
|
||||
<awais.instagrabber.customviews.RecordView
|
||||
android:id="@+id/record_view"
|
||||
@ -214,7 +232,7 @@
|
||||
app:slide_to_cancel_margin_right="16dp"
|
||||
app:slide_to_cancel_text="Slide To Cancel"
|
||||
app:slide_to_cancel_text_color="@color/white"
|
||||
tools:visibility="gone" />
|
||||
tools:visibility="visible" />
|
||||
|
||||
<awais.instagrabber.customviews.RecordButton
|
||||
android:id="@+id/send"
|
||||
@ -231,7 +249,8 @@
|
||||
app:layout_constraintBottom_toBottomOf="@id/input_bg"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/input_bg"
|
||||
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.App.Button.Circle" />
|
||||
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.App.Button.Circle"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<awais.instagrabber.customviews.emoji.EmojiPicker
|
||||
android:id="@+id/emoji_picker"
|
||||
@ -241,7 +260,8 @@
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/accept_pending_request_question"
|
||||
@ -255,7 +275,7 @@
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toTopOf="@id/decline"
|
||||
app:layout_constraintTop_toBottomOf="@id/chats_barrier"
|
||||
tools:visibility="visible" />
|
||||
tools:visibility="gone" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/decline"
|
||||
@ -272,7 +292,7 @@
|
||||
app:layout_constraintEnd_toStartOf="@id/accept"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/accept_pending_request_question"
|
||||
tools:visibility="visible" />
|
||||
tools:visibility="gone" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/accept"
|
||||
@ -288,5 +308,5 @@
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/decline"
|
||||
app:layout_constraintTop_toBottomOf="@id/accept_pending_request_question"
|
||||
tools:visibility="visible" />
|
||||
tools:visibility="gone" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
70
app/src/main/res/layout/layout_gif_picker.xml
Normal file
70
app/src/main/res/layout/layout_gif_picker.xml
Normal file
@ -0,0 +1,70 @@
|
||||
<?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">
|
||||
|
||||
<View
|
||||
android:id="@+id/input_bg"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:background="@drawable/bg_input"
|
||||
app:layout_constraintBottom_toBottomOf="@id/input"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/input" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/search_icon"
|
||||
style="@style/Widget.MaterialComponents.Button.Icon.NoInsets"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="2dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:clickable="false"
|
||||
android:scrollbars="none"
|
||||
app:icon="@drawable/ic_search_24"
|
||||
app:iconGravity="textStart"
|
||||
app:iconSize="24dp"
|
||||
app:iconTint="@color/grey_700"
|
||||
app:layout_constraintBottom_toBottomOf="@id/input_bg"
|
||||
app:layout_constraintEnd_toStartOf="@id/input"
|
||||
app:layout_constraintStart_toStartOf="@id/input_bg"
|
||||
app:layout_constraintTop_toTopOf="@id/input"
|
||||
app:rippleColor="@color/grey_500"
|
||||
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.App.Button.Circle"
|
||||
app:strokeColor="@color/black"
|
||||
app:strokeWidth="1dp" />
|
||||
|
||||
<androidx.emoji.widget.EmojiAppCompatEditText
|
||||
android:id="@+id/input"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:hint="@string/search_giphy"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingBottom="12dp"
|
||||
android:textColor="@color/white"
|
||||
android:textColorHint="@color/grey_500"
|
||||
app:layout_constraintBottom_toTopOf="@id/gif_list"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/search_icon"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/gif_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/input" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -185,6 +185,7 @@
|
||||
<string name="dms_inbox_shared_video">%s shared a video</string>
|
||||
<string name="dms_inbox_shared_message">%s sent a message</string>
|
||||
<string name="dms_inbox_shared_gif">%s shared a gif</string>
|
||||
<string name="dms_inbox_shared_sticker">%s shared a sticker</string>
|
||||
<string name="dms_inbox_shared_profile">%s shared a profile: @%s</string>
|
||||
<string name="dms_inbox_shared_location">%s shared a location: %s</string>
|
||||
<string name="dms_inbox_shared_highlight">%s shared a story highlight by @%s</string>
|
||||
@ -490,4 +491,5 @@
|
||||
<string name="auto_refresh_every">Auto refresh every</string>
|
||||
<string name="secs">secs</string>
|
||||
<string name="mins">mins</string>
|
||||
<string name="search_giphy">Search GIPHY</string>
|
||||
</resources>
|
||||
|
Loading…
Reference in New Issue
Block a user