mirror of
				https://codeberg.org/tom79/Fedilab.git
				synced 2025-10-20 11:20:16 +03:00 
			
		
		
		
	Fix issue #60 - Allow to upload gif from keyboard
This commit is contained in:
		
							parent
							
								
									bb6e31c00a
								
							
						
					
					
						commit
						5f8685db32
					
				
					 4 changed files with 241 additions and 2 deletions
				
			
		|  | @ -0,0 +1,198 @@ | |||
| package app.fedilab.android.helper; | ||||
| 
 | ||||
| import static app.fedilab.android.ui.drawer.ComposeAdapter.autocomplete; | ||||
| 
 | ||||
| import android.content.Context; | ||||
| import android.content.SharedPreferences; | ||||
| import android.content.res.TypedArray; | ||||
| import android.graphics.Paint; | ||||
| import android.os.Build; | ||||
| import android.os.Bundle; | ||||
| import android.util.AttributeSet; | ||||
| import android.view.KeyEvent; | ||||
| import android.view.inputmethod.EditorInfo; | ||||
| import android.view.inputmethod.InputConnection; | ||||
| 
 | ||||
| import androidx.annotation.CallSuper; | ||||
| import androidx.annotation.DimenRes; | ||||
| import androidx.annotation.NonNull; | ||||
| import androidx.annotation.Px; | ||||
| import androidx.core.view.inputmethod.EditorInfoCompat; | ||||
| import androidx.core.view.inputmethod.InputConnectionCompat; | ||||
| import androidx.core.view.inputmethod.InputContentInfoCompat; | ||||
| import androidx.preference.PreferenceManager; | ||||
| 
 | ||||
| import com.google.android.material.textfield.MaterialAutoCompleteTextView; | ||||
| import com.vanniktech.emoji.EmojiManager; | ||||
| import com.vanniktech.emoji.emoji.Emoji; | ||||
| 
 | ||||
| import app.fedilab.android.R; | ||||
| import app.fedilab.android.interfaces.EmojiEditTextInterface; | ||||
| 
 | ||||
| public class FedilabAutoCompleteTextView extends MaterialAutoCompleteTextView implements EmojiEditTextInterface { | ||||
| 
 | ||||
|     private float emojiSize; | ||||
|     private boolean emoji; | ||||
|     private String[] imgTypeString; | ||||
|     private KeyBoardInputCallbackListener keyBoardInputCallbackListener; | ||||
|     final InputConnectionCompat.OnCommitContentListener callback = | ||||
|             new InputConnectionCompat.OnCommitContentListener() { | ||||
|                 @Override | ||||
|                 public boolean onCommitContent(@NonNull InputContentInfoCompat inputContentInfo, | ||||
|                                                int flags, Bundle opts) { | ||||
| 
 | ||||
|                     // read and display inputContentInfo asynchronously | ||||
|                     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1 && (flags & | ||||
|                             InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0) { | ||||
|                         try { | ||||
|                             inputContentInfo.requestPermission(); | ||||
|                         } catch (Exception e) { | ||||
|                             return false; // return false if failed | ||||
|                         } | ||||
|                     } | ||||
|                     boolean supported = false; | ||||
|                     for (final String mimeType : imgTypeString) { | ||||
|                         if (inputContentInfo.getDescription().hasMimeType(mimeType)) { | ||||
|                             supported = true; | ||||
|                             break; | ||||
|                         } | ||||
|                     } | ||||
|                     if (!supported) { | ||||
|                         return false; | ||||
|                     } | ||||
| 
 | ||||
|                     if (keyBoardInputCallbackListener != null) { | ||||
|                         keyBoardInputCallbackListener.onCommitContent(inputContentInfo, flags, opts); | ||||
|                     } | ||||
|                     return true;  // return true if succeeded | ||||
|                 } | ||||
|             }; | ||||
| 
 | ||||
| 
 | ||||
|     public FedilabAutoCompleteTextView(Context context) { | ||||
|         super(context); | ||||
|         initView(); | ||||
|     } | ||||
| 
 | ||||
|     public FedilabAutoCompleteTextView(Context context, AttributeSet attrs) { | ||||
|         super(context, attrs); | ||||
| 
 | ||||
|         final Paint.FontMetrics fontMetrics = getPaint().getFontMetrics(); | ||||
|         final float defaultEmojiSize = fontMetrics.descent - fontMetrics.ascent; | ||||
|         final SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(context); | ||||
|         emoji = sharedpreferences.getBoolean(context.getString(R.string.SET_DISPLAY_EMOJI), false); | ||||
|         if (attrs == null) { | ||||
|             emojiSize = defaultEmojiSize; | ||||
|         } else { | ||||
|             final TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.EmojiMultiAutoCompleteTextView); | ||||
| 
 | ||||
|             try { | ||||
|                 emojiSize = a.getDimension(R.styleable.EmojiMultiAutoCompleteTextView_emojiSize, defaultEmojiSize); | ||||
|             } finally { | ||||
|                 a.recycle(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         setText(getText()); | ||||
|         initView(); | ||||
|     } | ||||
| 
 | ||||
|     public FedilabAutoCompleteTextView(Context context, AttributeSet attrs, int defStyleAttr) { | ||||
|         super(context, attrs, defStyleAttr); | ||||
|         initView(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public InputConnection onCreateInputConnection(EditorInfo outAttrs) { | ||||
|         final InputConnection ic = super.onCreateInputConnection(outAttrs); | ||||
|         EditorInfoCompat.setContentMimeTypes(outAttrs, | ||||
|                 imgTypeString); | ||||
|         return InputConnectionCompat.createWrapper(ic, outAttrs, callback); | ||||
|     } | ||||
| 
 | ||||
|     private void initView() { | ||||
|         imgTypeString = new String[]{"image/png", | ||||
|                 "image/gif", | ||||
|                 "image/jpeg", | ||||
|                 "image/webp"}; | ||||
|     } | ||||
| 
 | ||||
|     public void setKeyBoardInputCallbackListener(KeyBoardInputCallbackListener keyBoardInputCallbackListener) { | ||||
|         this.keyBoardInputCallbackListener = keyBoardInputCallbackListener; | ||||
|     } | ||||
| 
 | ||||
|     @SuppressWarnings("unused") | ||||
|     public String[] getImgTypeString() { | ||||
|         return imgTypeString; | ||||
|     } | ||||
| 
 | ||||
|     @SuppressWarnings("unused") | ||||
|     public void setImgTypeString(String[] imgTypeString) { | ||||
|         this.imgTypeString = imgTypeString; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     @CallSuper | ||||
|     protected void onTextChanged(final CharSequence text, final int start, final int lengthBefore, final int lengthAfter) { | ||||
|         final Paint.FontMetrics fontMetrics = getPaint().getFontMetrics(); | ||||
|         final float defaultEmojiSize = fontMetrics.descent - fontMetrics.ascent; | ||||
|         if (emoji && !autocomplete) { | ||||
|             EmojiManager.getInstance().replaceWithImages(getContext(), getText(), emojiSize, defaultEmojiSize); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void backspace() { | ||||
|         final KeyEvent event = new KeyEvent(0, 0, 0, KeyEvent.KEYCODE_DEL, 0, 0, 0, 0, KeyEvent.KEYCODE_ENDCALL); | ||||
|         dispatchKeyEvent(event); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public float getEmojiSize() { | ||||
|         return emojiSize; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public final void setEmojiSize(@Px final int pixels) { | ||||
|         setEmojiSize(pixels, true); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     @CallSuper | ||||
|     public void input(final Emoji emoji) { | ||||
|         if (emoji != null && !autocomplete) { | ||||
|             final int start = getSelectionStart(); | ||||
|             final int end = getSelectionEnd(); | ||||
| 
 | ||||
|             if (start < 0) { | ||||
|                 append(emoji.getUnicode()); | ||||
|             } else { | ||||
|                 getText().replace(Math.min(start, end), Math.max(start, end), emoji.getUnicode(), 0, emoji.getUnicode().length()); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public final void setEmojiSize(@Px final int pixels, final boolean shouldInvalidate) { | ||||
|         emojiSize = pixels; | ||||
| 
 | ||||
|         if (shouldInvalidate && !autocomplete) { | ||||
|             setText(getText()); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public final void setEmojiSizeRes(@DimenRes final int res) { | ||||
|         setEmojiSizeRes(res, true); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public final void setEmojiSizeRes(@DimenRes final int res, final boolean shouldInvalidate) { | ||||
|         setEmojiSize(getResources().getDimensionPixelSize(res), shouldInvalidate); | ||||
|     } | ||||
| 
 | ||||
|     public interface KeyBoardInputCallbackListener { | ||||
|         void onCommitContent(InputContentInfoCompat inputContentInfo, | ||||
|                              int flags, Bundle opts); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,34 @@ | |||
| package app.fedilab.android.interfaces; | ||||
| 
 | ||||
| import androidx.annotation.DimenRes; | ||||
| import androidx.annotation.Px; | ||||
| 
 | ||||
| import com.vanniktech.emoji.emoji.Emoji; | ||||
| 
 | ||||
| public interface EmojiEditTextInterface { | ||||
|     void backspace(); | ||||
| 
 | ||||
|     void input(Emoji emoji); | ||||
| 
 | ||||
|     float getEmojiSize(); | ||||
| 
 | ||||
|     /** | ||||
|      * sets the emoji size in pixels and automatically invalidates the text and renders it with the new size | ||||
|      */ | ||||
|     void setEmojiSize(@Px int pixels); | ||||
| 
 | ||||
|     /** | ||||
|      * sets the emoji size in pixels and automatically invalidates the text and renders it with the new size when {@code shouldInvalidate} is true | ||||
|      */ | ||||
|     void setEmojiSize(@Px int pixels, boolean shouldInvalidate); | ||||
| 
 | ||||
|     /** | ||||
|      * sets the emoji size in pixels with the provided resource and automatically invalidates the text and renders it with the new size | ||||
|      */ | ||||
|     void setEmojiSizeRes(@DimenRes int res); | ||||
| 
 | ||||
|     /** | ||||
|      * sets the emoji size in pixels with the provided resource and invalidates the text and renders it with the new size when {@code shouldInvalidate} is true | ||||
|      */ | ||||
|     void setEmojiSizeRes(@DimenRes int res, boolean shouldInvalidate); | ||||
| } | ||||
|  | @ -1135,7 +1135,14 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder | |||
|                     statusDraft.text = new SpannableString(Html.fromHtml(statusDraft.content)).toString(); | ||||
|             } | ||||
|             holder.binding.content.setText(statusDraft.text); | ||||
| 
 | ||||
|             holder.binding.content.setKeyBoardInputCallbackListener((inputContentInfo, flags, opts) -> { | ||||
|                 if (inputContentInfo != null) { | ||||
|                     Uri uri = inputContentInfo.getContentUri(); | ||||
|                     List<Uri> uris = new ArrayList<>(); | ||||
|                     uris.add(uri); | ||||
|                     addAttachment(position, uris); | ||||
|                 } | ||||
|             }); | ||||
|             holder.binding.content.setSelection(statusDraft.cursorPosition); | ||||
|             if (statusDraft.setCursorToEnd) { | ||||
|                 statusDraft.setCursorToEnd = false; | ||||
|  |  | |||
|  | @ -55,7 +55,7 @@ | |||
|             android:visibility="gone" | ||||
|             app:layout_constraintTop_toBottomOf="@id/add_remove_status" /> | ||||
| 
 | ||||
|         <com.google.android.material.textfield.MaterialAutoCompleteTextView | ||||
|         <app.fedilab.android.helper.FedilabAutoCompleteTextView | ||||
|             android:id="@+id/content" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content" | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue