mirror of
https://github.com/ArcaneChat/android.git
synced 2026-07-03 14:05:24 +02:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c52f4c908d | |||
| 896a36d40d | |||
| d83e37599c | |||
| e374f5f576 | |||
| bd97bc278b | |||
| 36c405122d | |||
| 5a06786d4c | |||
| c8eafa2e3a | |||
| b2131d61aa | |||
| 20c2af7097 | |||
| e8cf9b8dec | |||
| cf9a263b42 | |||
| 1c5d619edf |
@@ -33,5 +33,6 @@ public interface BindableConversationItem extends Unbindable {
|
||||
void onShowFullClicked(DcMsg messageRecord);
|
||||
void onDownloadClicked(DcMsg messageRecord);
|
||||
void onReactionClicked(DcMsg messageRecord);
|
||||
void onStickerClicked(DcMsg messageRecord);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1456,6 +1456,18 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
isEditing = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStickerPicked(Uri stickerUri) {
|
||||
if (isEditing) return;
|
||||
sendSticker(stickerUri, "image/png");
|
||||
}
|
||||
|
||||
public void refreshStickerPicker() {
|
||||
if (emojiPicker != null) {
|
||||
emojiPicker.refreshStickerPicker();
|
||||
}
|
||||
}
|
||||
|
||||
// media selected by the system keyboard
|
||||
@Override
|
||||
public void onMediaSelected(@NonNull Uri uri, String contentType) {
|
||||
|
||||
@@ -70,6 +70,7 @@ import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import org.thoughtcrime.securesms.util.views.ConversationAdaptiveActionsToolbar;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
@@ -401,6 +402,7 @@ public class ConversationFragment extends MessageSelectorFragment
|
||||
boolean showReplyPrivately = chat.isMultiUser() && !messageRecord.isOutgoing() && canReply;
|
||||
menu.findItem(R.id.menu_context_reply_privately).setVisible(showReplyPrivately);
|
||||
menu.findItem(R.id.menu_add_to_home_screen).setVisible(messageRecord.getType() == DcMsg.DC_MSG_WEBXDC);
|
||||
menu.findItem(R.id.menu_context_save_sticker).setVisible(false);
|
||||
|
||||
/*
|
||||
boolean saved = messageRecord.getSavedMsgId() != 0;
|
||||
@@ -554,6 +556,46 @@ public class ConversationFragment extends MessageSelectorFragment
|
||||
}
|
||||
}
|
||||
|
||||
private void handleSaveSticker(final DcMsg message) {
|
||||
if (message.getType() != DcMsg.DC_MSG_STICKER) {
|
||||
return;
|
||||
}
|
||||
|
||||
File stickerFile = message.getFileAsFile();
|
||||
if (stickerFile == null || !stickerFile.exists()) {
|
||||
Toast.makeText(getContext(), R.string.error, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
// Create stickers directory in internal storage
|
||||
File stickersDir = new File(getContext().getFilesDir(), "stickers");
|
||||
if (!stickersDir.exists()) {
|
||||
stickersDir.mkdirs();
|
||||
}
|
||||
|
||||
// Copy sticker to stickers directory
|
||||
String fileName = System.currentTimeMillis() + "_" + stickerFile.getName();
|
||||
File destFile = new File(stickersDir, fileName);
|
||||
|
||||
try (java.io.FileInputStream in = new java.io.FileInputStream(stickerFile);
|
||||
java.io.FileOutputStream out = new java.io.FileOutputStream(destFile)) {
|
||||
byte[] buffer = new byte[1024];
|
||||
int read;
|
||||
while ((read = in.read(buffer)) != -1) {
|
||||
out.write(buffer, 0, read);
|
||||
}
|
||||
Toast.makeText(getContext(), R.string.add_to_sticker_collection, Toast.LENGTH_SHORT).show();
|
||||
|
||||
// Refresh sticker picker to show the newly added sticker
|
||||
if (getActivity() instanceof ConversationActivity) {
|
||||
((ConversationActivity) getActivity()).refreshStickerPicker();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error saving sticker", e);
|
||||
Toast.makeText(getContext(), R.string.error, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
private void handleReplyMessage(final DcMsg message) {
|
||||
if (getActivity() != null) {
|
||||
@@ -947,6 +989,18 @@ public class ConversationFragment extends MessageSelectorFragment
|
||||
ReactionsDetailsFragment dialog = ReactionsDetailsFragment.newInstance(messageRecord.getId());
|
||||
dialog.show(getActivity().getSupportFragmentManager(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStickerClicked(DcMsg messageRecord) {
|
||||
new androidx.appcompat.app.AlertDialog.Builder(getContext())
|
||||
.setTitle(R.string.add_to_sticker_collection)
|
||||
.setMessage(R.string.ask_add_sticker_to_collection)
|
||||
.setPositiveButton(R.string.ok, (dialog, which) -> {
|
||||
handleSaveSticker(messageRecord);
|
||||
})
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -972,6 +972,8 @@ public class ConversationItem extends BaseConversationItem
|
||||
public void onClick(final View v, final Slide slide) {
|
||||
if (shouldInterceptClicks(messageRecord) || !batchSelected.isEmpty()) {
|
||||
performClick();
|
||||
} else if (eventListener != null) {
|
||||
eventListener.onStickerClicked(messageRecord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -353,6 +353,13 @@ public class InputPanel extends ConstraintLayout
|
||||
composeText.setSelection(start + emoji.length());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStickerPicked(Uri stickerUri) {
|
||||
if (listener != null) {
|
||||
listener.onStickerPicked(stickerUri);
|
||||
}
|
||||
}
|
||||
|
||||
public interface Listener {
|
||||
void onRecorderStarted();
|
||||
void onRecorderLocked();
|
||||
@@ -361,6 +368,7 @@ public class InputPanel extends ConstraintLayout
|
||||
void onRecorderPermissionRequired();
|
||||
void onEmojiToggle();
|
||||
void onQuoteDismissed();
|
||||
void onStickerPicked(Uri stickerUri);
|
||||
}
|
||||
|
||||
private static class SlideToCancel {
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
package org.thoughtcrime.securesms.components.emoji;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -12,15 +15,24 @@ import androidx.core.util.Consumer;
|
||||
import androidx.emoji2.emojipicker.EmojiPickerView;
|
||||
import androidx.emoji2.emojipicker.EmojiViewItem;
|
||||
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.components.InputAwareLayout.InputView;
|
||||
import org.thoughtcrime.securesms.util.ResUtil;
|
||||
|
||||
public class MediaKeyboard extends FrameLayout implements InputView, Consumer<EmojiViewItem> {
|
||||
import java.io.File;
|
||||
|
||||
public class MediaKeyboard extends LinearLayout implements InputView, Consumer<EmojiViewItem>, StickerPickerView.StickerPickerListener {
|
||||
|
||||
private static final String TAG = MediaKeyboard.class.getSimpleName();
|
||||
|
||||
@Nullable private MediaKeyboardListener keyboardListener;
|
||||
@Nullable private MediaKeyboardListener keyboardListener;
|
||||
private EmojiPickerView emojiPicker;
|
||||
private StickerPickerView stickerPicker;
|
||||
private View stickerPickerContainer;
|
||||
private View stickerPickerEmpty;
|
||||
private TabLayout tabLayout;
|
||||
|
||||
public MediaKeyboard(@NonNull Context context) {
|
||||
super(context);
|
||||
@@ -51,13 +63,90 @@ public class MediaKeyboard extends FrameLayout implements InputView, Consumer<Em
|
||||
|
||||
public void show() {
|
||||
if (emojiPicker == null) {
|
||||
emojiPicker = findViewById(R.id.emoji_picker);
|
||||
emojiPicker.setOnEmojiPickedListener(this);
|
||||
setupViews();
|
||||
}
|
||||
setVisibility(VISIBLE);
|
||||
if (keyboardListener != null) keyboardListener.onShown();
|
||||
}
|
||||
|
||||
private void setupViews() {
|
||||
emojiPicker = findViewById(R.id.emoji_picker);
|
||||
stickerPicker = findViewById(R.id.sticker_picker);
|
||||
stickerPickerContainer = findViewById(R.id.sticker_picker_container);
|
||||
stickerPickerEmpty = findViewById(R.id.sticker_picker_empty);
|
||||
tabLayout = findViewById(R.id.media_keyboard_tabs);
|
||||
|
||||
if (emojiPicker != null) {
|
||||
emojiPicker.setOnEmojiPickedListener(this);
|
||||
}
|
||||
|
||||
if (stickerPicker != null) {
|
||||
stickerPicker.setStickerPickerListener(this);
|
||||
}
|
||||
|
||||
if (tabLayout != null) {
|
||||
Drawable emojiIcon = ResUtil.getDrawable(getContext(), R.attr.conversation_emoji_toggle);
|
||||
|
||||
tabLayout.addTab(tabLayout.newTab().setIcon(emojiIcon));
|
||||
tabLayout.addTab(tabLayout.newTab().setIcon(R.drawable.ic_sticker_24));
|
||||
|
||||
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
|
||||
@Override
|
||||
public void onTabSelected(TabLayout.Tab tab) {
|
||||
if (tab.getPosition() == 0) {
|
||||
showEmojiPicker();
|
||||
} else {
|
||||
showStickerPicker();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabUnselected(TabLayout.Tab tab) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabReselected(TabLayout.Tab tab) {
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void showEmojiPicker() {
|
||||
if (emojiPicker != null) {
|
||||
emojiPicker.setVisibility(View.VISIBLE);
|
||||
}
|
||||
if (stickerPickerContainer != null) {
|
||||
stickerPickerContainer.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private void showStickerPicker() {
|
||||
if (emojiPicker != null) {
|
||||
emojiPicker.setVisibility(View.GONE);
|
||||
}
|
||||
if (stickerPickerContainer != null) {
|
||||
stickerPickerContainer.setVisibility(View.VISIBLE);
|
||||
}
|
||||
if (stickerPicker != null) {
|
||||
stickerPicker.loadStickers();
|
||||
updateStickerEmptyState();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateStickerEmptyState() {
|
||||
if (stickerPicker != null && stickerPickerEmpty != null) {
|
||||
boolean hasStickers = stickerPicker.getAdapter() != null && stickerPicker.getAdapter().getItemCount() > 0;
|
||||
stickerPickerEmpty.setVisibility(hasStickers ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
public void refreshStickerPicker() {
|
||||
if (stickerPicker != null) {
|
||||
stickerPicker.loadStickers();
|
||||
updateStickerEmptyState();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hide(boolean immediate) {
|
||||
setVisibility(GONE);
|
||||
@@ -70,9 +159,24 @@ public class MediaKeyboard extends FrameLayout implements InputView, Consumer<Em
|
||||
if (keyboardListener != null) keyboardListener.onEmojiPicked(emojiViewItem.getEmoji());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStickerSelected(@NonNull File stickerFile) {
|
||||
if (keyboardListener != null) {
|
||||
keyboardListener.onStickerPicked(Uri.fromFile(stickerFile));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStickerDeleted(@NonNull File stickerFile) {
|
||||
// Update empty state after deletion
|
||||
Log.i(TAG, "Sticker deleted: " + stickerFile.getName());
|
||||
updateStickerEmptyState();
|
||||
}
|
||||
|
||||
public interface MediaKeyboardListener {
|
||||
void onShown();
|
||||
void onHidden();
|
||||
void onEmojiPicked(String emoji);
|
||||
void onStickerPicked(Uri stickerUri);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
package org.thoughtcrime.securesms.components.emoji;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class StickerPickerView extends RecyclerView {
|
||||
|
||||
private static final String TAG = StickerPickerView.class.getSimpleName();
|
||||
private static final String STICKER_FOLDER = "stickers";
|
||||
|
||||
@Nullable private StickerPickerListener listener;
|
||||
private GlideRequests glideRequests;
|
||||
private File stickerDir;
|
||||
|
||||
public StickerPickerView(@NonNull Context context) {
|
||||
super(context);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public StickerPickerView(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context);
|
||||
}
|
||||
|
||||
private void init(Context context) {
|
||||
glideRequests = GlideApp.with(context);
|
||||
stickerDir = new File(context.getFilesDir(), STICKER_FOLDER);
|
||||
setLayoutManager(new GridLayoutManager(context, 4));
|
||||
loadStickers();
|
||||
}
|
||||
|
||||
public void setStickerPickerListener(@Nullable StickerPickerListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public void loadStickers() {
|
||||
List<File> stickerFiles = getSavedStickers();
|
||||
setAdapter(new StickerAdapter(getContext(), glideRequests, stickerFiles, listener));
|
||||
}
|
||||
|
||||
private List<File> getSavedStickers() {
|
||||
List<File> stickerFiles = new ArrayList<>();
|
||||
|
||||
if (!stickerDir.exists()) {
|
||||
return stickerFiles;
|
||||
}
|
||||
|
||||
File[] files = stickerDir.listFiles();
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
if (file.isFile()) {
|
||||
stickerFiles.add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort stickers by filename
|
||||
Collections.sort(stickerFiles, new Comparator<File>() {
|
||||
@Override
|
||||
public int compare(File f1, File f2) {
|
||||
return f1.getName().compareToIgnoreCase(f2.getName());
|
||||
}
|
||||
});
|
||||
|
||||
return stickerFiles;
|
||||
}
|
||||
|
||||
public interface StickerPickerListener {
|
||||
void onStickerSelected(@NonNull File stickerFile);
|
||||
void onStickerDeleted(@NonNull File stickerFile);
|
||||
}
|
||||
|
||||
static class StickerAdapter extends RecyclerView.Adapter<StickerAdapter.StickerViewHolder> {
|
||||
|
||||
private final Context context;
|
||||
private final GlideRequests glideRequests;
|
||||
private final List<File> stickerFiles;
|
||||
private final LayoutInflater layoutInflater;
|
||||
private final StickerPickerListener listener;
|
||||
|
||||
StickerAdapter(@NonNull Context context,
|
||||
@NonNull GlideRequests glideRequests,
|
||||
@NonNull List<File> stickerFiles,
|
||||
@Nullable StickerPickerListener listener) {
|
||||
this.context = context;
|
||||
this.glideRequests = glideRequests;
|
||||
this.stickerFiles = stickerFiles;
|
||||
this.layoutInflater = LayoutInflater.from(context);
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull StickerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = layoutInflater.inflate(R.layout.sticker_picker_item, parent, false);
|
||||
return new StickerViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull StickerViewHolder holder, int position) {
|
||||
File stickerFile = stickerFiles.get(position);
|
||||
holder.stickerFile = stickerFile;
|
||||
|
||||
glideRequests.load(stickerFile)
|
||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||
.into(holder.image);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return stickerFiles.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewRecycled(@NonNull StickerViewHolder holder) {
|
||||
super.onViewRecycled(holder);
|
||||
glideRequests.clear(holder.image);
|
||||
}
|
||||
|
||||
private void deleteSticker(File stickerFile) {
|
||||
if (stickerFile != null && stickerFile.exists()) {
|
||||
new androidx.appcompat.app.AlertDialog.Builder(context)
|
||||
.setTitle(R.string.delete)
|
||||
.setMessage(R.string.ask_delete_sticker)
|
||||
.setPositiveButton(R.string.delete, (dialog, which) -> {
|
||||
if (stickerFile.delete()) {
|
||||
int position = stickerFiles.indexOf(stickerFile);
|
||||
if (position >= 0) {
|
||||
stickerFiles.remove(position);
|
||||
notifyItemRemoved(position);
|
||||
}
|
||||
if (listener != null) {
|
||||
listener.onStickerDeleted(stickerFile);
|
||||
}
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
||||
class StickerViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
private File stickerFile;
|
||||
private final ImageView image;
|
||||
|
||||
StickerViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
image = itemView.findViewById(R.id.sticker_image);
|
||||
itemView.setOnClickListener(view -> {
|
||||
if (listener != null && stickerFile != null) {
|
||||
listener.onStickerSelected(stickerFile);
|
||||
}
|
||||
});
|
||||
itemView.setOnLongClickListener(view -> {
|
||||
if (stickerFile != null) {
|
||||
deleteSticker(stickerFile);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#FFFFFF" android:viewportHeight="960" android:viewportWidth="960" android:width="24dp">
|
||||
|
||||
<path android:fillColor="@android:color/white" android:pathData="M460,600Q529,600 580,555Q631,510 640,442L320,532Q346,564 382,582Q418,600 460,600ZM294,450L400,420Q404,392 386,371Q368,350 340,350Q315,350 297.5,367.5Q280,385 280,410Q280,421 284,431Q288,441 294,450ZM534,380L640,350Q645,322 626.5,301Q608,280 580,280Q555,280 537.5,297.5Q520,315 520,340Q520,351 524,361Q528,371 534,380ZM640,840L200,840Q167,840 143.5,816.5Q120,793 120,760L120,200Q120,167 143.5,143.5Q167,120 200,120L760,120Q793,120 816.5,143.5Q840,167 840,200L840,640L640,840ZM600,760L600,680Q600,647 623.5,623.5Q647,600 680,600L760,600L760,200Q760,200 760,200Q760,200 760,200L200,200Q200,200 200,200Q200,200 200,200L200,760Q200,760 200,760Q200,760 200,760L600,760ZM600,760L600,760L600,760Q600,760 600,760Q600,760 600,760ZM200,760L200,760Q200,760 200,760Q200,760 200,760L200,200Q200,200 200,200Q200,200 200,200L200,200Q200,200 200,200Q200,200 200,200L200,600L200,600Q200,600 200,623.5Q200,647 200,680L200,760Z"/>
|
||||
|
||||
</vector>
|
||||
@@ -1,18 +1,69 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<org.thoughtcrime.securesms.components.emoji.MediaKeyboard
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/emoji_drawer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<androidx.emoji2.emojipicker.EmojiPickerView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/emoji_picker"
|
||||
<FrameLayout
|
||||
android:id="@+id/media_keyboard_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:background="?emoji_drawer_background">
|
||||
|
||||
<androidx.emoji2.emojipicker.EmojiPickerView
|
||||
android:id="@+id/emoji_picker"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?emoji_drawer_background"
|
||||
app:emojiGridColumns="12"/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/sticker_picker_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone">
|
||||
|
||||
<org.thoughtcrime.securesms.components.emoji.StickerPickerView
|
||||
android:id="@+id/sticker_picker"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?emoji_drawer_background"
|
||||
android:paddingTop="4dp"
|
||||
android:clipToPadding="false"
|
||||
android:clipChildren="false"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/sticker_picker_empty"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:text="@string/sticker_picker_empty_hint"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone"/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/media_keyboard_tabs"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?emoji_drawer_background"
|
||||
app:emojiGridColumns="12"/>
|
||||
app:tabMode="fixed"
|
||||
app:tabGravity="center"
|
||||
app:tabIndicatorGravity="top"
|
||||
app:tabIconTint="?attr/colorControlNormal"
|
||||
app:tabPaddingStart="16dp"
|
||||
app:tabPaddingEnd="16dp"
|
||||
app:tabPaddingTop="10dp"
|
||||
app:tabPaddingBottom="10dp"
|
||||
/>
|
||||
|
||||
</org.thoughtcrime.securesms.components.emoji.MediaKeyboard>
|
||||
|
||||
@@ -2,18 +2,69 @@
|
||||
<!-- WARNING: on modifications also update the layout-land folder. -->
|
||||
<org.thoughtcrime.securesms.components.emoji.MediaKeyboard
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/emoji_drawer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<androidx.emoji2.emojipicker.EmojiPickerView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/emoji_picker"
|
||||
<FrameLayout
|
||||
android:id="@+id/media_keyboard_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:background="?emoji_drawer_background">
|
||||
|
||||
<androidx.emoji2.emojipicker.EmojiPickerView
|
||||
android:id="@+id/emoji_picker"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?emoji_drawer_background"
|
||||
app:emojiGridColumns="9"/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/sticker_picker_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone">
|
||||
|
||||
<org.thoughtcrime.securesms.components.emoji.StickerPickerView
|
||||
android:id="@+id/sticker_picker"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?emoji_drawer_background"
|
||||
android:paddingTop="4dp"
|
||||
android:clipToPadding="false"
|
||||
android:clipChildren="false"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/sticker_picker_empty"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:text="@string/sticker_picker_empty_hint"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone"/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/media_keyboard_tabs"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?emoji_drawer_background"
|
||||
app:emojiGridColumns="9"/>
|
||||
app:tabMode="fixed"
|
||||
app:tabGravity="center"
|
||||
app:tabIndicatorGravity="top"
|
||||
app:tabIconTint="?attr/colorControlNormal"
|
||||
app:tabPaddingStart="16dp"
|
||||
app:tabPaddingEnd="16dp"
|
||||
app:tabPaddingTop="10dp"
|
||||
app:tabPaddingBottom="10dp"
|
||||
/>
|
||||
|
||||
</org.thoughtcrime.securesms.components.emoji.MediaKeyboard>
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ImageView android:id="@+id/sticker_image"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="100dp"
|
||||
android:padding="8dp"
|
||||
android:scaleType="centerInside"/>
|
||||
@@ -40,6 +40,11 @@
|
||||
android:visible="false"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item android:title="@string/add_to_sticker_collection"
|
||||
android:id="@+id/menu_context_save_sticker"
|
||||
android:visible="false"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item android:title="@string/info"
|
||||
android:id="@+id/menu_context_details"
|
||||
app:showAsAction="never" />
|
||||
|
||||
@@ -178,6 +178,9 @@
|
||||
<string name="add_to_sticker_collection">Add to Sticker Collection</string>
|
||||
<string name="add_stickers_instructions">To add stickers, tap "Open Sticker Folder", create a subfolder for your sticker pack, and drag image and sticker files there</string>
|
||||
<string name="open_sticker_folder">Open Sticker Folder</string>
|
||||
<string name="ask_add_sticker_to_collection">Add this sticker to your collection?</string>
|
||||
<string name="ask_delete_sticker">Delete this sticker?</string>
|
||||
<string name="sticker_picker_empty_hint">Saved stickers will appear here.</string>
|
||||
<string name="images">Images</string>
|
||||
<string name="audio">Audio</string>
|
||||
<string name="voice_message">Voice Message</string>
|
||||
|
||||
Reference in New Issue
Block a user