Skip to content
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

Closed
wants to merge 23 commits into from

Conversation

remi6397
Copy link
Contributor

@remi6397 remi6397 commented May 6, 2018

Fixes #558 #550

  1. web+mastodon:// test case: https://jsfiddle.net/pvyoof6L/11/
    For me it works with Chrome, but not with Firefox.
  2. QS tile and external application Share functionalities will now prompt for account selection.

Copy link
Collaborator

@charlag charlag left a 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>() {
Copy link
Collaborator

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;
Copy link
Collaborator

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)
Copy link
Collaborator

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)
Copy link
Collaborator

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

Copy link
Contributor Author

@remi6397 remi6397 May 6, 2018

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 :Þ

Copy link
Collaborator

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"
Copy link
Collaborator

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()))) {
Copy link
Collaborator

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);
Copy link
Collaborator

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?

@charlag
Copy link
Collaborator

charlag commented May 6, 2018

Now holder if fine, thank you!

@connyduck connyduck added this to the Tusky 1.9 milestone May 6, 2018
Copy link
Collaborator

@charlag charlag left a 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"
Copy link
Collaborator

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

Copy link
Collaborator

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>>,
Copy link
Collaborator

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
Copy link
Collaborator

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.


<!-- for day/night mode -->
Copy link
Collaborator

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()) {
Copy link
Collaborator

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 }
Copy link
Collaborator

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>,
Copy link
Collaborator

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);
Copy link
Collaborator

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)
Copy link
Collaborator

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?

Copy link
Collaborator

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...

Copy link
Contributor Author

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.

Copy link
Collaborator

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

Copy link
Collaborator

@charlag charlag left a 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)
Copy link
Collaborator

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
Copy link
Collaborator

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,
Copy link
Collaborator

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() })
Copy link
Collaborator

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"
Copy link
Collaborator

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>,
Copy link
Collaborator

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 ... ,
) {
....
}

@charlag
Copy link
Collaborator

charlag commented May 12, 2018

It overlaps the name. I would also align nickname and display name with each other. I think it's also important to show full username (with instance) but I'm not sure how to do that - maybe push things closer to edges, make margins and font smaller
screenshot_20180512-190623

@charlag
Copy link
Collaborator

charlag commented May 12, 2018

CI fails with:

:app:kaptGenerateStubsDebugUnitTestKotline: /home/circleci/code/app/src/test/java/com/keylesspalace/tusky/ComposeActivityTest.kt: (88, 24): Unresolved reference: customEmojis
e: /home/circleci/code/app/src/test/java/com/keylesspalace/tusky/ComposeActivityTest.kt: (110, 24): Unresolved reference: instance

@connyduck
Copy link
Collaborator

It overlaps the name. I would also align nickname and display name with each other. I think it's also important to show full username (with instance) but I'm not sure how to do that - maybe push things closer to edges, make margins and font smaller

Probably best to give it more lines. First line image+button, second line display name, third line full username including instance.

@connyduck connyduck removed this from the Tusky 1.9 milestone May 28, 2018
@connyduck
Copy link
Collaborator

Will you continue working on this or should somebody else take it over? @remi6397

@remi6397
Copy link
Contributor Author

@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…

@connyduck
Copy link
Collaborator

ok, no problem, thx for the info

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants