Allow text selection with multiple links in message
This commit is contained in:
		
							parent
							
								
									7b52e6984c
								
							
						
					
					
						commit
						8ca5eb4429
					
				|  | @ -15,6 +15,7 @@ import android.os.Build; | ||||||
| import android.support.v4.content.FileProvider; | import android.support.v4.content.FileProvider; | ||||||
| import android.text.Spannable; | import android.text.Spannable; | ||||||
| import android.text.SpannableString; | import android.text.SpannableString; | ||||||
|  | import android.text.SpannableStringBuilder; | ||||||
| import android.text.Spanned; | import android.text.Spanned; | ||||||
| import android.text.style.ForegroundColorSpan; | import android.text.style.ForegroundColorSpan; | ||||||
| import android.text.style.RelativeSizeSpan; | import android.text.style.RelativeSizeSpan; | ||||||
|  | @ -51,6 +52,7 @@ import eu.siacs.conversations.entities.Message; | ||||||
| import eu.siacs.conversations.entities.Message.FileParams; | import eu.siacs.conversations.entities.Message.FileParams; | ||||||
| import eu.siacs.conversations.entities.Transferable; | import eu.siacs.conversations.entities.Transferable; | ||||||
| import eu.siacs.conversations.ui.ConversationActivity; | import eu.siacs.conversations.ui.ConversationActivity; | ||||||
|  | import eu.siacs.conversations.ui.widget.ClickableMovementMethod; | ||||||
| import eu.siacs.conversations.utils.CryptoHelper; | import eu.siacs.conversations.utils.CryptoHelper; | ||||||
| import eu.siacs.conversations.utils.GeoHelper; | import eu.siacs.conversations.utils.GeoHelper; | ||||||
| import eu.siacs.conversations.utils.UIHelper; | import eu.siacs.conversations.utils.UIHelper; | ||||||
|  | @ -314,7 +316,7 @@ public class MessageAdapter extends ArrayAdapter<Message> { | ||||||
| 			if (body.length() > Config.MAX_DISPLAY_MESSAGE_CHARS) { | 			if (body.length() > Config.MAX_DISPLAY_MESSAGE_CHARS) { | ||||||
| 				body = body.substring(0, Config.MAX_DISPLAY_MESSAGE_CHARS)+"\u2026"; | 				body = body.substring(0, Config.MAX_DISPLAY_MESSAGE_CHARS)+"\u2026"; | ||||||
| 			} | 			} | ||||||
| 			final SpannableString formattedBody = new SpannableString(body); | 			Spannable formattedBody = new SpannableString(body); | ||||||
| 			int i = body.indexOf(Message.MERGE_SEPARATOR); | 			int i = body.indexOf(Message.MERGE_SEPARATOR); | ||||||
| 			while(i >= 0) { | 			while(i >= 0) { | ||||||
| 				final int end = i + Message.MERGE_SEPARATOR.length(); | 				final int end = i + Message.MERGE_SEPARATOR.length(); | ||||||
|  | @ -323,12 +325,8 @@ public class MessageAdapter extends ArrayAdapter<Message> { | ||||||
| 			} | 			} | ||||||
| 			if (message.getType() != Message.TYPE_PRIVATE) { | 			if (message.getType() != Message.TYPE_PRIVATE) { | ||||||
| 				if (message.hasMeCommand()) { | 				if (message.hasMeCommand()) { | ||||||
| 					final Spannable span = new SpannableString(formattedBody); | 					formattedBody.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), 0, nick.length(), | ||||||
| 					span.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), 0, nick.length(), |  | ||||||
| 							Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); | 							Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); | ||||||
| 					viewHolder.messageBody.setText(span); |  | ||||||
| 				} else { |  | ||||||
| 					viewHolder.messageBody.setText(formattedBody); |  | ||||||
| 				} | 				} | ||||||
| 			} else { | 			} else { | ||||||
| 				String privateMarker; | 				String privateMarker; | ||||||
|  | @ -344,46 +342,25 @@ public class MessageAdapter extends ArrayAdapter<Message> { | ||||||
| 					} | 					} | ||||||
| 					privateMarker = activity.getString(R.string.private_message_to, to); | 					privateMarker = activity.getString(R.string.private_message_to, to); | ||||||
| 				} | 				} | ||||||
| 				final Spannable span = new SpannableString(privateMarker + " " | 				formattedBody = new SpannableStringBuilder().append(privateMarker).append(' ').append(formattedBody); | ||||||
| 						+ formattedBody); | 				formattedBody.setSpan(new ForegroundColorSpan(getMessageTextColor(darkBackground,false)), 0, privateMarker | ||||||
| 				span.setSpan(new ForegroundColorSpan(getMessageTextColor(darkBackground,false)), 0, privateMarker |  | ||||||
| 						.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); | 						.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); | ||||||
| 				span.setSpan(new StyleSpan(Typeface.BOLD), 0, | 				formattedBody.setSpan(new StyleSpan(Typeface.BOLD), 0, | ||||||
| 						privateMarker.length(), | 						privateMarker.length(), | ||||||
| 						Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); | 						Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); | ||||||
| 				if (message.hasMeCommand()) { | 				if (message.hasMeCommand()) { | ||||||
| 					span.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), privateMarker.length() + 1, | 					formattedBody.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), privateMarker.length() + 1, | ||||||
| 							privateMarker.length() + 1 + nick.length(), | 							privateMarker.length() + 1 + nick.length(), | ||||||
| 							Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); | 							Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); | ||||||
| 				} | 				} | ||||||
| 				viewHolder.messageBody.setText(span); |  | ||||||
| 			} | 			} | ||||||
| 			int urlCount = 0; | 			Linkify.addLinks(formattedBody, Linkify.WEB_URLS); | ||||||
| 			final Matcher matcher = Patterns.WEB_URL.matcher(body); | 			Linkify.addLinks(formattedBody, XMPP_PATTERN, "xmpp"); | ||||||
| 			int beginWebURL = Integer.MAX_VALUE; | 			Linkify.addLinks(formattedBody, GeoHelper.GEO_URI, "geo"); | ||||||
| 			int endWebURL = 0; |  | ||||||
| 			while (matcher.find()) { |  | ||||||
| 				MatchResult result = matcher.toMatchResult(); |  | ||||||
| 				beginWebURL = result.start(); |  | ||||||
| 				endWebURL = result.end(); |  | ||||||
| 				urlCount++; |  | ||||||
| 			} |  | ||||||
| 			final Matcher geoMatcher = GeoHelper.GEO_URI.matcher(body); |  | ||||||
| 			while (geoMatcher.find()) { |  | ||||||
| 				urlCount++; |  | ||||||
| 			} |  | ||||||
| 			final Matcher xmppMatcher = XMPP_PATTERN.matcher(body); |  | ||||||
| 			while (xmppMatcher.find()) { |  | ||||||
| 				MatchResult result = xmppMatcher.toMatchResult(); |  | ||||||
| 				if (beginWebURL < result.start() || endWebURL > result.end()) { |  | ||||||
| 					urlCount++; |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 			viewHolder.messageBody.setTextIsSelectable(urlCount <= 1); |  | ||||||
| 			viewHolder.messageBody.setAutoLinkMask(0); | 			viewHolder.messageBody.setAutoLinkMask(0); | ||||||
| 			Linkify.addLinks(viewHolder.messageBody, Linkify.WEB_URLS); | 			viewHolder.messageBody.setText(formattedBody); | ||||||
| 			Linkify.addLinks(viewHolder.messageBody, XMPP_PATTERN, "xmpp"); | 			viewHolder.messageBody.setTextIsSelectable(true); | ||||||
| 			Linkify.addLinks(viewHolder.messageBody, GeoHelper.GEO_URI, "geo"); | 			viewHolder.messageBody.setMovementMethod(ClickableMovementMethod.getInstance()); | ||||||
| 		} else { | 		} else { | ||||||
| 			viewHolder.messageBody.setText(""); | 			viewHolder.messageBody.setText(""); | ||||||
| 			viewHolder.messageBody.setTextIsSelectable(false); | 			viewHolder.messageBody.setTextIsSelectable(false); | ||||||
|  |  | ||||||
|  | @ -0,0 +1,42 @@ | ||||||
|  | package eu.siacs.conversations.ui.widget; | ||||||
|  | 
 | ||||||
|  | import android.text.Layout; | ||||||
|  | import android.text.Spannable; | ||||||
|  | import android.text.method.ArrowKeyMovementMethod; | ||||||
|  | import android.text.style.ClickableSpan; | ||||||
|  | import android.view.MotionEvent; | ||||||
|  | import android.widget.TextView; | ||||||
|  | 
 | ||||||
|  | public class ClickableMovementMethod extends ArrowKeyMovementMethod { | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) { | ||||||
|  | 		// Just copied from android.text.method.LinkMovementMethod | ||||||
|  | 		if (event.getAction() == MotionEvent.ACTION_UP) { | ||||||
|  | 			int x = (int) event.getX(); | ||||||
|  | 			int y = (int) event.getY(); | ||||||
|  | 			x -= widget.getTotalPaddingLeft(); | ||||||
|  | 			y -= widget.getTotalPaddingTop(); | ||||||
|  | 			x += widget.getScrollX(); | ||||||
|  | 			y += widget.getScrollY(); | ||||||
|  | 			Layout layout = widget.getLayout(); | ||||||
|  | 			int line = layout.getLineForVertical(y); | ||||||
|  | 			int off = layout.getOffsetForHorizontal(line, x); | ||||||
|  | 			ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class); | ||||||
|  | 			if (link.length != 0) { | ||||||
|  | 				link[0].onClick(widget); | ||||||
|  | 				return true; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return super.onTouchEvent(widget, buffer, event); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public static ClickableMovementMethod getInstance() { | ||||||
|  | 		if (sInstance == null) { | ||||||
|  | 			sInstance = new ClickableMovementMethod(); | ||||||
|  | 		} | ||||||
|  | 		return sInstance; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private static ClickableMovementMethod sInstance; | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue
	
	 Mishiranu
						Mishiranu