add ‘paste as quote’ for api >= 23
This commit is contained in:
		
							parent
							
								
									00281112b9
								
							
						
					
					
						commit
						e8066debf8
					
				| @ -85,6 +85,7 @@ import eu.siacs.conversations.ui.util.ActivityResult; | |||||||
| import eu.siacs.conversations.ui.util.AttachmentTool; | import eu.siacs.conversations.ui.util.AttachmentTool; | ||||||
| import eu.siacs.conversations.ui.util.ConversationMenuConfigurator; | import eu.siacs.conversations.ui.util.ConversationMenuConfigurator; | ||||||
| import eu.siacs.conversations.ui.util.DateSeparator; | import eu.siacs.conversations.ui.util.DateSeparator; | ||||||
|  | import eu.siacs.conversations.ui.util.EditMessageActionModeCallback; | ||||||
| import eu.siacs.conversations.ui.util.ListViewUtils; | import eu.siacs.conversations.ui.util.ListViewUtils; | ||||||
| import eu.siacs.conversations.ui.util.MenuDoubleTabUtil; | import eu.siacs.conversations.ui.util.MenuDoubleTabUtil; | ||||||
| import eu.siacs.conversations.ui.util.PendingItem; | import eu.siacs.conversations.ui.util.PendingItem; | ||||||
| @ -991,25 +992,16 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke | |||||||
| 
 | 
 | ||||||
| 		registerForContextMenu(binding.messagesView); | 		registerForContextMenu(binding.messagesView); | ||||||
| 
 | 
 | ||||||
|  | 		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { | ||||||
|  | 			this.binding.textinput.setCustomInsertionActionModeCallback(new EditMessageActionModeCallback(this.binding.textinput)); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		return binding.getRoot(); | 		return binding.getRoot(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private void quoteText(String text) { | 	private void quoteText(String text) { | ||||||
| 		if (binding.textinput.isEnabled()) { | 		if (binding.textinput.isEnabled()) { | ||||||
| 			text = text.replaceAll("(\n *){2,}", "\n").replaceAll("(^|\n)", "$1> ").replaceAll("\n$", ""); | 			binding.textinput.insertAsQuote(text); | ||||||
| 			Editable editable = binding.textinput.getEditableText(); |  | ||||||
| 			int position = binding.textinput.getSelectionEnd(); |  | ||||||
| 			if (position == -1) position = editable.length(); |  | ||||||
| 			if (position > 0 && editable.charAt(position - 1) != '\n') { |  | ||||||
| 				editable.insert(position++, "\n"); |  | ||||||
| 			} |  | ||||||
| 			editable.insert(position, text); |  | ||||||
| 			position += text.length(); |  | ||||||
| 			editable.insert(position++, "\n"); |  | ||||||
| 			if (position < editable.length() && editable.charAt(position) != '\n') { |  | ||||||
| 				editable.insert(position, "\n"); |  | ||||||
| 			} |  | ||||||
| 			binding.textinput.setSelection(position); |  | ||||||
| 			binding.textinput.requestFocus(); | 			binding.textinput.requestFocus(); | ||||||
| 			InputMethodManager inputMethodManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); | 			InputMethodManager inputMethodManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); | ||||||
| 			if (inputMethodManager != null) { | 			if (inputMethodManager != null) { | ||||||
|  | |||||||
| @ -0,0 +1,83 @@ | |||||||
|  | /* | ||||||
|  |  * Copyright (c) 2018, Daniel Gultsch All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without modification, | ||||||
|  |  * are permitted provided that the following conditions are met: | ||||||
|  |  * | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright notice, this | ||||||
|  |  * list of conditions and the following disclaimer. | ||||||
|  |  * | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright notice, | ||||||
|  |  * this list of conditions and the following disclaimer in the documentation and/or | ||||||
|  |  * other materials provided with the distribution. | ||||||
|  |  * | ||||||
|  |  * 3. Neither the name of the copyright holder nor the names of its contributors | ||||||
|  |  * may be used to endorse or promote products derived from this software without | ||||||
|  |  * specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||||||
|  |  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||||
|  |  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||||
|  |  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR | ||||||
|  |  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||||
|  |  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||||
|  |  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||||||
|  |  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||||
|  |  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||||
|  |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | package eu.siacs.conversations.ui.util; | ||||||
|  | 
 | ||||||
|  | import android.content.ClipData; | ||||||
|  | import android.content.ClipboardManager; | ||||||
|  | import android.content.Context; | ||||||
|  | import android.view.ActionMode; | ||||||
|  | import android.view.Menu; | ||||||
|  | import android.view.MenuInflater; | ||||||
|  | import android.view.MenuItem; | ||||||
|  | 
 | ||||||
|  | import eu.siacs.conversations.R; | ||||||
|  | import eu.siacs.conversations.ui.widget.EditMessage; | ||||||
|  | 
 | ||||||
|  | public class EditMessageActionModeCallback implements ActionMode.Callback { | ||||||
|  | 
 | ||||||
|  | 	private final EditMessage editMessage; | ||||||
|  | 	private final ClipboardManager clipboardManager; | ||||||
|  | 
 | ||||||
|  | 	public EditMessageActionModeCallback(EditMessage editMessage) { | ||||||
|  | 		this.editMessage = editMessage; | ||||||
|  | 		this.clipboardManager = (ClipboardManager) editMessage.getContext().getSystemService(Context.CLIPBOARD_SERVICE); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public boolean onCreateActionMode(ActionMode mode, Menu menu) { | ||||||
|  | 		MenuInflater inflater = mode.getMenuInflater(); | ||||||
|  | 		inflater.inflate(R.menu.edit_message_actions, menu); | ||||||
|  | 		MenuItem pasteAsQuote = menu.findItem(R.id.paste_as_quote); | ||||||
|  | 		pasteAsQuote.setVisible(clipboardManager.hasPrimaryClip() && clipboardManager.getPrimaryClipDescription().hasMimeType("text/plain")); | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public boolean onPrepareActionMode(ActionMode mode, Menu menu) { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public boolean onActionItemClicked(ActionMode mode, MenuItem item) { | ||||||
|  | 		if (item.getItemId() == R.id.paste_as_quote) { | ||||||
|  | 			ClipData primaryClip = clipboardManager.getPrimaryClip(); | ||||||
|  | 			if (primaryClip.getItemCount() >= 1) { | ||||||
|  | 				editMessage.insertAsQuote(primaryClip.getItemAt(0).getText().toString()); | ||||||
|  | 				return true; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public void onDestroyActionMode(ActionMode mode) { | ||||||
|  | 
 | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @ -129,6 +129,23 @@ public class EditMessage extends EmojiAppCompatEditText { | |||||||
| 		this.mCommitContentListener = listener; | 		this.mCommitContentListener = listener; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	public void insertAsQuote(String text) { | ||||||
|  | 		text = text.replaceAll("(\n *){2,}", "\n").replaceAll("(^|\n)", "$1> ").replaceAll("\n$", ""); | ||||||
|  | 		Editable editable = getEditableText(); | ||||||
|  | 		int position = getSelectionEnd(); | ||||||
|  | 		if (position == -1) position = editable.length(); | ||||||
|  | 		if (position > 0 && editable.charAt(position - 1) != '\n') { | ||||||
|  | 			editable.insert(position++, "\n"); | ||||||
|  | 		} | ||||||
|  | 		editable.insert(position, text); | ||||||
|  | 		position += text.length(); | ||||||
|  | 		editable.insert(position++, "\n"); | ||||||
|  | 		if (position < editable.length() && editable.charAt(position) != '\n') { | ||||||
|  | 			editable.insert(position, "\n"); | ||||||
|  | 		} | ||||||
|  | 		setSelection(position); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	@Override | 	@Override | ||||||
| 	public InputConnection onCreateInputConnection(EditorInfo editorInfo) { | 	public InputConnection onCreateInputConnection(EditorInfo editorInfo) { | ||||||
| 		final InputConnection ic = super.onCreateInputConnection(editorInfo); | 		final InputConnection ic = super.onCreateInputConnection(editorInfo); | ||||||
|  | |||||||
							
								
								
									
										38
									
								
								src/main/res/menu/edit_message_actions.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/main/res/menu/edit_message_actions.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,38 @@ | |||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <!-- | ||||||
|  |   ~ Copyright (c) 2018, Daniel Gultsch All rights reserved. | ||||||
|  |   ~ | ||||||
|  |   ~ Redistribution and use in source and binary forms, with or without modification, | ||||||
|  |   ~ are permitted provided that the following conditions are met: | ||||||
|  |   ~ | ||||||
|  |   ~ 1. Redistributions of source code must retain the above copyright notice, this | ||||||
|  |   ~ list of conditions and the following disclaimer. | ||||||
|  |   ~ | ||||||
|  |   ~ 2. Redistributions in binary form must reproduce the above copyright notice, | ||||||
|  |   ~ this list of conditions and the following disclaimer in the documentation and/or | ||||||
|  |   ~ other materials provided with the distribution. | ||||||
|  |   ~ | ||||||
|  |   ~ 3. Neither the name of the copyright holder nor the names of its contributors | ||||||
|  |   ~ may be used to endorse or promote products derived from this software without | ||||||
|  |   ~ specific prior written permission. | ||||||
|  |   ~ | ||||||
|  |   ~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||||||
|  |   ~ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||||
|  |   ~ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||||
|  |   ~ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR | ||||||
|  |   ~ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||||
|  |   ~ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||||
|  |   ~ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||||||
|  |   ~ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||||
|  |   ~ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||||
|  |   ~ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |   --> | ||||||
|  | 
 | ||||||
|  | <menu xmlns:android="http://schemas.android.com/apk/res/android"> | ||||||
|  | 
 | ||||||
|  |     <item | ||||||
|  |         android:id="@+id/paste_as_quote" | ||||||
|  |         android:title="Paste as quote" | ||||||
|  |         android:orderInCategory="99"/> | ||||||
|  | 
 | ||||||
|  | </menu> | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Daniel Gultsch
						Daniel Gultsch