Tusky icon indicating copy to clipboard operation
Tusky copied to clipboard

copy and paste of a toot containing link adds garbage to links

Open novadeviator opened this issue 6 years ago • 8 comments

When copying the whole toot that contains a link and pasting the text into new toot, Tusky adds "%E2%80%8B" at the end of the actual link. The text in the published toot is the same and looks ok, but actual link points to original URL with added garbage which then prevents from visiting that link (usually 404).

STEPS TO REPRODUCE:

  • find any public toot with link in it
  • tap on it to open it as separate toot
  • long press on it to copy to clipboard
  • compose new toot
  • long press into it and choose paste, and send
  • tap the link in the new sent toot
  • it will end up in 404 or not where original links was pointing

an example of link with added characters: http://scholar.harvard.edu/files/mickens/files/towashitallaway.pdf%E2%80%8B


  • Tusky Version: 9.1

  • Android Version: 7.0

  • Android Device: HUAWEI VNS-L21

  • [x] I searched or browsed the repo’s other issues to ensure this is not a duplicate.

novadeviator avatar Nov 21 '19 04:11 novadeviator

Seems related to HTML sanitization.

JuanjoSalvador avatar Nov 21 '19 19:11 JuanjoSalvador

https://github.com/tuskyapp/Tusky/blob/78b5aa8baf0c34fb5ed00742ec3174dc5bb33fa3/app/src/main/java/com/keylesspalace/tusky/util/LinkHelper.java#L121-L127

connyduck avatar Nov 21 '19 19:11 connyduck

Maybe we should copy original text somehow? Or it will be HTML and not very nice?

charlag avatar Jan 17 '20 22:01 charlag

@connyduck did we fix this?

charlag avatar May 10 '22 20:05 charlag

https://github.com/tuskyapp/Tusky/blob/ad001d044d9f6b354c948758abe9d6fb2e8036f1/app/src/main/java/com/keylesspalace/tusky/util/LinkHelper.kt#L92-L97

Still an issue in the app too

modelmat avatar May 11 '22 05:05 modelmat

Thanks for checking. I wonder if we can fix it outside of the span while keeping the hitbox, probably not. Maybe we need to override what is copied for the link then

charlag avatar May 11 '22 15:05 charlag

Maybe there is another way to prevent the large link hitboxes than to add this special character?

connyduck avatar May 11 '22 15:05 connyduck

That would be the best

charlag avatar May 15 '22 16:05 charlag

A full reproduction recipe is:

  1. Bookmark https://chaos.social/@netzpolitik_feed/109365395616419194 (so it's easy to get back to if you're testing fixes)
  2. Open the status
  3. Long-pressed the link at the bottom of the status (which displays as https://netpolitik.org/2022/twitter-exodus-wie-behoerden-medien-und-ngos-mastodon-fuer-sich-entdecken/)
  4. Copy the link
  5. Click back twice to go Bookmarks -> Timeline
  6. Click the compose FAB
  7. Paste the link in to the new status
  8. Set the status visibility to "Direct" so it doesn't show up in my public timeline
  9. Click "Toot"
  10. Open my profile
  11. See the status from (9) which includes the link (which looks correct)
  12. Click the link

Then it breaks.

nikclayton avatar Nov 25 '22 10:11 nikclayton

I thought adding SPAN_EXCLUSIVE_EXCLUSIVE might fix this, per https://developer.android.com/reference/kotlin/android/text/Spanned#SPAN_EXCLUSIVE_EXCLUSIVE:kotlin.Int

Spans of type SPAN_EXCLUSIVE_EXCLUSIVE do not expand to include text inserted at either their starting or ending point. They can never have a length of 0 and are automatically removed from the buffer if all the text they cover is removed.

The "... do not expand ..." bit in particular. But this doesn't seem to work (in LinkHelper.kt:setClickableText())

    removeSpan(span)
    flags = (flags and 0xffffff00.toInt()) or SPAN_EXCLUSIVE_EXCLUSIVE  // <-- new code
    setSpan(customSpan, start, end, flags)

nikclayton avatar Nov 25 '22 10:11 nikclayton

Changing the unicode space from \u200B (zero width space) to \u200C (zero-width non-joiner) doesn't work.

nikclayton avatar Nov 25 '22 10:11 nikclayton

This is a difference between how the span of the link is treated by Android and how the span of the text selection is treated.

The easiest way to see this is to change the inserted character to something visible, like "x". If you launch Tusky with that change you will see the "x" at the end of every link, but it's not part of the clickable link (i.e., it's a different colour) and it's not part of the URL that's opened.

But if you long-press to select the link, the "x" is included in the text selection.

nikclayton avatar Nov 25 '22 11:11 nikclayton

The official Mastodon Android app doesn't have the link hitbox problem, and links copied from there are correct, so it would be worth looking at what that code does.

nikclayton avatar Nov 26 '22 11:11 nikclayton

That bug is here forever and it is super annoying, it really should be fixed. Thanks for the help, I will look into it.

connyduck avatar Nov 26 '22 11:11 connyduck

Just looked at this a bit more.

The fix in the official Mastodon app is to:

  1. Subclass TextView as LinkedTextView
  2. Introduce an empty class, DeleteWhenCopiedSpan
  3. When text that shouldn't be copied (e.g., the "..." if a URL is truncated, or the unicode to stop the hitbox from extending) it's tagged with DeleteWhenCopiedSpan
  4. Override LinkedTextView.onTextContextMenuItem, and if the action is id.copy then delete any spans matching DeleteWhenCopiedSpan before copying the content to the clipboard.

The basic TextView doesn't provide functionality to hook in to onTextContextMenuItem (there's no "setTextContextMenuListener" or similar), so subclassing appears to be the way to go.

But... it doesn't need add anything to URLs, because LinkedTextView also overrides onTouchEvent, and ignores touch events that are outside of a clickable span. You can override onTouchEvent in a TextView with setOnTouchListener.

But... if my reading of the platform code for TextView is correct, setOnTouchListener is ignored when links are clicked on.

So a TextView subclass is probably the way to go.

nikclayton avatar Dec 07 '22 12:12 nikclayton