Repository: tuskyapp/Tusky (language: kotlin)

Issue:
Link lookup ends up with wrong link
I have been using Tusky for a good week now and noticed that every now and then clicking on links in posts take me to the wrong internet address.

E.g.:
1. Click a link in a post, which should go to www.patrion.com/…
2. Land on the Mastodon profile of the European Commision?
A bit like chat roulette I guess :-)

Here's a link to a raw video: https://cloud.zell-mbc.com/s/QbQ2xFzY2TajKgZ
Most links work, some don't.

Edit: Forgot to mention that when I click that same link from a different client (browser, FediLab, etc.) the correct page opens.

* * * *
- Tusky Version: 19.0
- Android Version: 10
- Android Device: Stoneage Samsung tablet, SM-T830
- Mastodon instance (if applicable): Doesn't matter

- [x ] I searched or browsed the repo’s other issues to ensure this is not a duplicate.
 



Discussion hints:
Is the account of the European commission involved or mentioned in this thread? Does it happen only in thread view or also in other places?
Also, which instance are you on? 
> Is the account of the European commission involved or mentioned in this thread? Does it happen only in thread view or also in other places?

Need to lookup this thread again to confirm, but would be surprised because it's been about a completely different subject.

> Does it happen only in thread view or also in other places?

Don't know either, will test next time this happens

> Also, which instance are you on?

My personal instance, Pleroma based

I have now installed Tusky on my mobile phone as well, so I can compare when this happens next time. 

What happens if you throw the link into the search of your instance? Thats what Tusky is doing do determine if it is a fedi link or not
> What happens if you throw the link into the search of your instance?

You mean the search at the top of the Tusky screen, the magnifier? If so, nothing is found, which is correct (?) because it's a URL and not a post/account/hashtag
![image](https://user-images.githubusercontent.com/29018767/201396559-b38fcc4e-ebde-406c-b704-b3cf2c2be6e8.png)


> Does it happen only in thread view or also in other places?

It's happening on the main timeline  as well as the thread view

> Is the account of the European commission involved or mentioned in this thread?

No

> Tusky on my mobile phone

Shows the same behaviour
OnePlus 8 Pro, Android 12

And as far as my instance as potential reason for the failure is concerned, I am running [Fedilab](https://fedilab.app/) on that device as well, and there the link in that post works fine.

Yes the post in question and the link are fine, that is definitely not the problem.
I can think of two things that could cause such behavior
1) search returns wrong results when looking up the link
2) View recycling is wrongly implemented and the click listener of another link is invoked

But it looks like it is neither of those 🤔 
I'll "click a bit more" going forward, maybe I can identify a pattern.
I know I had another post with the same issue but can't remember where this one took me to...
I got another one, same effect. I klick on a link and end up with someone's profile. I can provide a video if it helps.
https://cloud.zell-mbc.com/s/fBkTnfnXDnwJaPM
This happens to me frequently as well (server runs Akkoma.)

It seems to usually go to a link that has similar words in it?

![An example of the error happening](https://user-images.githubusercontent.com/82258270/218444063-2cfb9f9d-b890-4725-b81e-0888906cc877.gif)

o_0 Which post, which server is this?
> o_0 Which post, which server is this?

I posted a link to an archived version of someone's blog post which was 404'ing (https://archive.is/x9nzZ) onto my sever (moth.zone) and Tusky decided to send me to @anarchist_archive@kolektiva.social (https://kolektiva.social/@anarchist_archive) for some reason. Aside from both having the word "archive" there's no connection to either account. No clue why it happens, but it happens with a lot of other URLs too.
Ok, so it is case 1) from above. Search on some non-Mastodon servers returns accounts when searching for urls and Tusky opens the first one. I can reproduce it with one of my test accounts.
The solution is to check if the url of the found accounts matches the search before opening it. The relevant code is on BottomSheetActivity if someone wants to fix it.

Pull request: When looking up fediverse urls, verify that account results returned match the input query
Fixes #2804

Test command: ./gradlew :app:testBlueDebugUnitTest --tests "com.keylesspalace.tusky.BottomSheetActivityTest"

Fix patch:
diff --git a/app/src/main/java/com/keylesspalace/tusky/BottomSheetActivity.kt b/app/src/main/java/com/keylesspalace/tusky/BottomSheetActivity.kt
index 60d1966d1c..8df0c66171 100644
--- a/app/src/main/java/com/keylesspalace/tusky/BottomSheetActivity.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/BottomSheetActivity.kt
@@ -86,8 +86,11 @@ abstract class BottomSheetActivity : BaseActivity() {
                     if (statuses.isNotEmpty()) {
                         viewThread(statuses[0].id, statuses[0].url)
                         return@subscribe
-                    } else if (accounts.isNotEmpty()) {
-                        viewAccount(accounts[0].id)
+                    }
+                    accounts.firstOrNull { it.url == url }?.let { account ->
+                        // Some servers return (unrelated) accounts for url searches (#2804)
+                        // Verify that the account's url matches the query
+                        viewAccount(account.id)
                         return@subscribe
                     }
 


Test patch:
diff --git a/app/src/test/java/com/keylesspalace/tusky/BottomSheetActivityTest.kt b/app/src/test/java/com/keylesspalace/tusky/BottomSheetActivityTest.kt
index 66b922bd5a..f4b12a61f0 100644
--- a/app/src/test/java/com/keylesspalace/tusky/BottomSheetActivityTest.kt
+++ b/app/src/test/java/com/keylesspalace/tusky/BottomSheetActivityTest.kt
@@ -46,6 +46,7 @@ class BottomSheetActivityTest {
     private lateinit var apiMock: MastodonApi
     private val accountQuery = "http://mastodon.foo.bar/@User"
     private val statusQuery = "http://mastodon.foo.bar/@User/345678"
+    private val nonexistentStatusQuery = "http://mastodon.foo.bar/@User/345678000"
     private val nonMastodonQuery = "http://medium.com/@correspondent/345678"
     private val emptyCallback = Single.just(SearchResult(emptyList(), emptyList(), emptyList()))
     private val testScheduler = TestScheduler()
@@ -55,7 +56,7 @@ class BottomSheetActivityTest {
         localUsername = "admin",
         username = "admin",
         displayName = "Ad Min",
-        url = "http://mastodon.foo.bar",
+        url = "http://mastodon.foo.bar/@User",
         avatar = ""
     )
     private val accountSingle = Single.just(SearchResult(listOf(account), emptyList(), emptyList()))
@@ -101,6 +102,7 @@ class BottomSheetActivityTest {
         apiMock = mock {
             on { searchObservable(eq(accountQuery), eq(null), anyBoolean(), eq(null), eq(null), eq(null)) } doReturn accountSingle
             on { searchObservable(eq(statusQuery), eq(null), anyBoolean(), eq(null), eq(null), eq(null)) } doReturn statusSingle
+            on { searchObservable(eq(nonexistentStatusQuery), eq(null), anyBoolean(), eq(null), eq(null), eq(null)) } doReturn accountSingle
             on { searchObservable(eq(nonMastodonQuery), eq(null), anyBoolean(), eq(null), eq(null), eq(null)) } doReturn emptyCallback
         }
 
@@ -184,6 +186,14 @@ class BottomSheetActivityTest {
         }
     }
 
+    @Test
+    fun search_doesNotRespectUnrelatedResult() {
+        activity.viewUrl(nonexistentStatusQuery)
+        testScheduler.advanceTimeBy(100, TimeUnit.MILLISECONDS)
+        assertEquals(nonexistentStatusQuery, activity.link)
+        assertEquals(null, activity.accountId)
+    }
+
     @Test
     fun search_withCancellation_doesNotLoadUrl_forAccount() {
         activity.viewUrl(accountQuery)