-
-
Notifications
You must be signed in to change notification settings - Fork 390
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add "web+mastodon" protocol handler; prompt for selecting account when action is triggered by external application. #633
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for doing this, it is a cool feature!
Tbh, I didn't build it yet but I have some questions.
My biggest concern is replies. You see, different servers have different IDs for the same statuses (or maybe the same IDs for different statuses). So when replying we risk to reply to wrong account/status.
I think we should either disallow such things when replying or handle it gracefully.
Maybe I've missed something but this PR doesn't handle this?
import com.pkmmte.view.CircularImageView | ||
import com.squareup.picasso.Picasso | ||
|
||
class AccountListAdapter(private val accountList: List<AccountEntity>, private val onAccountSelectedListener : OnAccountSelectedListener) : RecyclerView.Adapter<AccountListAdapter.AccountListViewHolder>() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please format it as per guidelines
@@ -22,6 +23,7 @@ | |||
import android.graphics.Color; | |||
import android.graphics.drawable.Drawable; | |||
import android.os.Bundle; | |||
import android.os.StrictMode; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need that ;)
} | ||
} | ||
|
||
class AccountListViewHolder(val accountItem: RelativeLayout) : RecyclerView.ViewHolder(accountItem) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it doesn't care which layout it's passed, you can remove redundant info
override fun onBindViewHolder(holder: AccountListViewHolder, position: Int) { | ||
val account = accountList[position] | ||
|
||
val avatar = holder.accountItem.findViewById<CircularImageView>(R.id.account_avatar) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm sorry, but that's not how ViewHolder
pattern works. The whole point of holders is to avoid expensive view search on every item bind. Look it up, but in general you find views in ViewHolder
constructor and just fill in data in onBindViewHolder
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It always has the same elements anyway, so… ¯_(ツ)_/¯
Anyway, I'm changing this :Þ
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, ofc they're the same, what's the point of traversing the view hierarchy every time then?
@@ -0,0 +1,9 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could it be FrameLayout
? Maybe just RecyclerView
?
if (inReplyToId == null) { | ||
composeAvatar.setOnClickListener(v -> showAccountSwitchDialog(true)); | ||
|
||
if (!intent.hasExtra(ACCOUNT_PRESET) && !intent.hasExtra(SAVED_TOOT_UID_EXTRA) && (getCallingActivity() == null || !getCallingActivity().getClassName().equals(MainActivity.class.getName()))) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super long line 😅
If you are to to check calling activity, maybe you should check that the caller is not ComposeActivity
?
|
||
AlertDialog dialog = builder.create(); | ||
AccountListAdapter adapter = new AccountListAdapter(accountManager.getAllAccountsOrderedByActive(), account -> { | ||
accountManager.setActiveAccount(account); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe I'm missing the point, but why do we have to restart activity? What happens after you return from it - all other screens are still for the old account (or flags handle this)?
Maybe we can avoid doing setActiveAccount()
by using InstanceSwitchAuthInterceptor
? Need to fix search too in this case...
I would ask input of others on how we should do it.
Are you in the Matrix room?
Now holder if fine, thank you! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you're moving in the right direction, I'm not sure yet how you want to implement dialog but using pairs is okay imo - maybe if it becomes too long you need to import class names or make a typealias but it's details
@@ -0,0 +1,56 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use ConstraintLayout instead of RelativeLayout whenever you can
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You certainly can deal with just one ConstraintLayout instead of all these containers, ask me if you need help
import com.pkmmte.view.CircularImageView | ||
import com.squareup.picasso.Picasso | ||
|
||
class FollowingAccountListAdapter(private val accountList: List<Pair<AccountEntity, FollowState>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please format fields by guidelines afterwards
} | ||
|
||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FollowingAccountListViewHolder { | ||
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_following_account, parent, false) as RelativeLayout |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid mentioning concrete layout whenever you can. Holder doesn't care.
app/src/main/AndroidManifest.xml
Outdated
|
||
<!-- for day/night mode --> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
put it back ;)
} | ||
|
||
private fun loadAccounts() { | ||
for (account in accountManager.getAllAccountsOrderedByActive()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
excuse me, I don't understand what's happening here
} | ||
} | ||
|
||
followingAccounts.map { if (it.first == account) Pair(account, followState) else it } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think using to
operator is more idiomatic than "Pair()"
import com.pkmmte.view.CircularImageView | ||
import com.squareup.picasso.Picasso | ||
|
||
class AccountListAdapter(private val accountList: List<AccountEntity>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please format fields by guidelines afterwards
@@ -49,8 +49,13 @@ public Response intercept(@NonNull Chain chain) throws IOException { | |||
|
|||
Request.Builder builder = originalRequest.newBuilder(); | |||
|
|||
String authorizationHeader = originalRequest.header(MastodonApi.TOKEN_HEADER); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As we expect for #517 it is going to be a common case to use another account and because interceptor already knows about accounts maybe it's a good idea to pass account ID instead of token header for every request? We should think about priority it needs to have but I think it should be lower than instance but should override active account
private fun broadcast(action: String, id: String) { | ||
val intent = Intent(action) | ||
intent.putExtra("id", id) | ||
LocalBroadcastManager.getInstance(applicationContext).sendBroadcast(intent) | ||
} | ||
|
||
override fun onFollowingAccountSelected(account: AccountEntity, position: Int) { | ||
override fun onFollowingAccountSelected(authorizeFollow: AuthorizeFollow) { | ||
(recyclerView.adapter as FollowingAccountListAdapter).updateAccount(authorizeFollow.accountEntity, authorizeFollow.followState, anyPendingTransaction = true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You've got a field with adapter, why do you fetch it this (unholy) way?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And in a lot of places as well...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you mean by unholy there? It's definitely awful, but I'm not sure what to change it to.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In your class you already have field named adapter
- no need to fetch it through recycler
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My previous comments still hold (especially about headers).
It's working but need some more love
private fun broadcast(action: String, id: String) { | ||
val intent = Intent(action) | ||
intent.putExtra("id", id) | ||
LocalBroadcastManager.getInstance(applicationContext).sendBroadcast(intent) | ||
} | ||
|
||
override fun onFollowingAccountSelected(account: AccountEntity, position: Int) { | ||
override fun onFollowingAccountSelected(authorizeFollow: AuthorizeFollow) { | ||
(recyclerView.adapter as FollowingAccountListAdapter).updateAccount(authorizeFollow.accountEntity, authorizeFollow.followState, anyPendingTransaction = true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And in a lot of places as well...
override fun onResponse(call: Call<Relationship>, response: Response<Relationship>) { | ||
if (!response.isSuccessful || response.body() == null) { | ||
onNetworkError() | ||
authorizeFollow.followState |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line is just hanging? You wanted to change it maybe
import com.keylesspalace.tusky.adapter.FollowingAccountListAdapter.FollowState | ||
import com.keylesspalace.tusky.db.AccountEntity | ||
|
||
data class AuthorizeFollow(val accountEntity: AccountEntity, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
data class AuthorizeFollow(
val accountEntity: AccountEntity,
val subjectAccount: Account,
var followState: FollowState,
var anyPendingTransaction: Boolean
)
adapter = FollowingAccountListAdapter(mutableListOf(), this) | ||
recyclerView.adapter = adapter | ||
|
||
cancelButton.setOnClickListener({ finish() }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
someMethod({ ... }) ----> someMethod { }
@@ -0,0 +1,56 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You certainly can deal with just one ConstraintLayout instead of all these containers, ask me if you need help
import com.pkmmte.view.CircularImageView | ||
import com.squareup.picasso.Picasso | ||
|
||
class FollowingAccountListAdapter(private val authorizeFollowList: MutableList<AuthorizeFollow>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
class Blahblah (
private val ... ,
private val ... ,
) {
....
}
CI fails with:
|
Probably best to give it more lines. First line image+button, second line display name, third line full username including instance. |
Will you continue working on this or should somebody else take it over? @remi6397 |
@connyduck Hi! I'm sorry, but I don't think that I can do that. :( It would be better if someone more experienced would take that over… |
ok, no problem, thx for the info |
Fixes #558 #550
web+mastodon://
test case: https://jsfiddle.net/pvyoof6L/11/For me it works with Chrome, but not with Firefox.