diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 27d129af..68419415 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -48,11 +48,6 @@
-
-
@@ -78,6 +73,15 @@
+
+
+
+
+
+
+
+
accounts = accountManager.getAllAccountsOrderedByActive();
+ AccountEntity activeAccount = accountManager.getActiveAccount();
+
+ switch(accounts.size()) {
+ case 1:
+ listener.onAccountSelected(activeAccount);
+ return;
+ case 2:
+ if (!showActiveAccount) {
+ for (AccountEntity account : accounts) {
+ if (activeAccount != account) {
+ listener.onAccountSelected(account);
+ return;
+ }
+ }
+ }
+ break;
+ }
+
+ if (!showActiveAccount && activeAccount != null) {
+ accounts.remove(activeAccount);
+ }
+ AccountSelectionAdapter adapter = new AccountSelectionAdapter(this);
+ adapter.addAll(accounts);
+
+ new AlertDialog.Builder(this)
+ .setTitle(dialogTitle)
+ .setAdapter(adapter, (dialogInterface, index) -> listener.onAccountSelected(accounts.get(index)))
+ .show();
+ }
}
diff --git a/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java b/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java
index 8fb3cff6..30fcdf71 100644
--- a/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java
+++ b/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java
@@ -1615,6 +1615,11 @@ public final class ComposeActivity
return maximumTootCharacters;
}
+ static boolean canHandleMimeType(@Nullable String mimeType) {
+ return (mimeType != null &&
+ (mimeType.startsWith("image/") || mimeType.startsWith("video/") || mimeType.equals("text/plain")));
+ }
+
public static final class QueuedMedia {
Type type;
ProgressImageView preview;
diff --git a/app/src/main/java/com/keylesspalace/tusky/MainActivity.java b/app/src/main/java/com/keylesspalace/tusky/MainActivity.java
index 19ef6023..e2110c8c 100644
--- a/app/src/main/java/com/keylesspalace/tusky/MainActivity.java
+++ b/app/src/main/java/com/keylesspalace/tusky/MainActivity.java
@@ -108,6 +108,14 @@ public final class MainActivity extends BottomSheetActivity implements ActionBut
private Drawer drawer;
private ViewPager viewPager;
+ private void forwardShare(Intent intent) {
+ Intent composeIntent = new Intent(this, ComposeActivity.class);
+ composeIntent.setAction(intent.getAction());
+ composeIntent.setType(intent.getType());
+ composeIntent.putExtras(intent);
+ startActivity(composeIntent);
+ }
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -117,18 +125,40 @@ public final class MainActivity extends BottomSheetActivity implements ActionBut
if (intent != null) {
long accountId = intent.getLongExtra(NotificationHelper.ACCOUNT_ID, -1);
+ boolean accountRequested = (accountId != -1);
- if (accountId != -1) {
- // user clicked a notification, show notification tab and switch user if necessary
- tabPosition = 1;
+ if (accountRequested) {
AccountEntity account = accountManager.getActiveAccount();
-
if (account == null || accountId != account.getId()) {
accountManager.setActiveAccount(accountId);
}
}
- }
+ if (ComposeActivity.canHandleMimeType(intent.getType())) {
+ // Sharing to Tusky from an external app
+ if (accountRequested) {
+ // The correct account is already active
+ forwardShare(intent);
+ } else {
+ // No account was provided, show the chooser
+ showAccountChooserDialog(getString(R.string.action_share_as), true, account -> {
+ long requestedId = account.getId();
+ AccountEntity activeAccount = accountManager.getActiveAccount();
+ if (activeAccount != null && requestedId == activeAccount.getId()) {
+ // The correct account is already active
+ forwardShare(intent);
+ } else {
+ // A different account was requested, restart the activity
+ intent.putExtra(NotificationHelper.ACCOUNT_ID, requestedId);
+ changeAccount(requestedId, intent);
+ }
+ });
+ }
+ } else if (accountRequested) {
+ // user clicked a notification, show notification tab and switch user if necessary
+ tabPosition = 1;
+ }
+ }
setContentView(R.layout.activity_main);
composeButton = findViewById(R.id.floating_btn);
@@ -420,17 +450,22 @@ public final class MainActivity extends BottomSheetActivity implements ActionBut
return true;
}
//change Account
- changeAccount(profile.getIdentifier());
+ changeAccount(profile.getIdentifier(), null);
return false;
}
- private void changeAccount(long newSelectedId) {
+ private void changeAccount(long newSelectedId, @Nullable Intent forward) {
cacheUpdater.stop();
accountManager.setActiveAccount(newSelectedId);
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ if (forward != null) {
+ intent.setType(forward.getType());
+ intent.setAction(forward.getAction());
+ intent.putExtras(forward);
+ }
startActivity(intent);
finishWithoutSlideOutAnimation();
diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/AccountSelectionAdapter.kt b/app/src/main/java/com/keylesspalace/tusky/adapter/AccountSelectionAdapter.kt
new file mode 100644
index 00000000..7db9a643
--- /dev/null
+++ b/app/src/main/java/com/keylesspalace/tusky/adapter/AccountSelectionAdapter.kt
@@ -0,0 +1,58 @@
+/* Copyright 2019 Levi Bard
+ *
+ * This file is a part of Tusky.
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with Tusky; if not,
+ * see . */
+
+package com.keylesspalace.tusky.adapter
+
+import android.content.Context
+import android.text.TextUtils
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ArrayAdapter
+import com.keylesspalace.tusky.R
+import com.keylesspalace.tusky.db.AccountEntity
+import com.keylesspalace.tusky.util.CustomEmojiHelper
+import com.squareup.picasso.Picasso
+
+import kotlinx.android.synthetic.main.item_autocomplete_account.view.*
+
+class AccountSelectionAdapter(context: Context): ArrayAdapter(context, R.layout.item_autocomplete_account) {
+ override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
+ var view = convertView
+
+ if (convertView == null) {
+ val layoutInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
+ view = layoutInflater.inflate(R.layout.item_autocomplete_account, parent, false)
+ }
+ view!!
+
+ val account = getItem(position)
+ if (account != null) {
+ val username = view.username
+ val displayName = view.display_name
+ val avatar = view.avatar
+ username.text = account.fullName
+ displayName.text = CustomEmojiHelper.emojifyString(account.displayName, account.emojis, displayName)
+ if (!TextUtils.isEmpty(account.profilePictureUrl)) {
+ Picasso.with(context)
+ .load(account.profilePictureUrl)
+ .placeholder(R.drawable.avatar_default)
+ .into(avatar)
+ }
+ }
+
+ return view
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/keylesspalace/tusky/di/ServicesModule.kt b/app/src/main/java/com/keylesspalace/tusky/di/ServicesModule.kt
index 9015b5f2..327ef284 100644
--- a/app/src/main/java/com/keylesspalace/tusky/di/ServicesModule.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/di/ServicesModule.kt
@@ -15,6 +15,7 @@
package com.keylesspalace.tusky.di
+import com.keylesspalace.tusky.service.AccountChooserService
import com.keylesspalace.tusky.service.SendTootService
import dagger.Module
import dagger.android.ContributesAndroidInjector
@@ -23,4 +24,6 @@ import dagger.android.ContributesAndroidInjector
abstract class ServicesModule {
@ContributesAndroidInjector
abstract fun contributesSendTootService(): SendTootService
+ @ContributesAndroidInjector
+ abstract fun contributesAccountChooserService(): AccountChooserService
}
\ No newline at end of file
diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/SFragment.java b/app/src/main/java/com/keylesspalace/tusky/fragment/SFragment.java
index ea144cfb..f14abd73 100644
--- a/app/src/main/java/com/keylesspalace/tusky/fragment/SFragment.java
+++ b/app/src/main/java/com/keylesspalace/tusky/fragment/SFragment.java
@@ -337,26 +337,7 @@ public abstract class SFragment extends BaseFragment {
}
private void showOpenAsDialog(String statusUrl, CharSequence dialogTitle) {
- List accounts = accountManager.getAllAccountsOrderedByActive();
- AccountEntity activeAccount = accountManager.getActiveAccount();
-
- if (accounts.size() == 2) {
- for (AccountEntity account : accounts) {
- if (activeAccount != account) {
- openAsAccount(statusUrl, account);
- break;
- }
- }
- } else {
- accounts.remove(activeAccount);
- CharSequence[] accountNames = new CharSequence[accounts.size()];
- for (int i = 0; i < accounts.size(); ++i) {
- accountNames[i] = accounts.get(i).getFullName();
- }
- new AlertDialog.Builder(getActivity())
- .setTitle(dialogTitle)
- .setItems(accountNames, (dialogInterface, index) -> openAsAccount(statusUrl, accounts.get(index)))
- .show();
- }
+ BaseActivity activity = (BaseActivity)getActivity();
+ activity.showAccountChooserDialog(dialogTitle, false, account -> openAsAccount(statusUrl, account));
}
}
diff --git a/app/src/main/java/com/keylesspalace/tusky/interfaces/AccountSelectionListener.kt b/app/src/main/java/com/keylesspalace/tusky/interfaces/AccountSelectionListener.kt
new file mode 100644
index 00000000..04b1ebd2
--- /dev/null
+++ b/app/src/main/java/com/keylesspalace/tusky/interfaces/AccountSelectionListener.kt
@@ -0,0 +1,22 @@
+/* Copyright 2019 Levi Bard
+ *
+ * This file is a part of Tusky.
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with Tusky; if not,
+ * see . */
+
+package com.keylesspalace.tusky.interfaces
+
+import com.keylesspalace.tusky.db.AccountEntity
+
+interface AccountSelectionListener {
+ fun onAccountSelected(account: AccountEntity)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/keylesspalace/tusky/service/AccountChooserService.kt b/app/src/main/java/com/keylesspalace/tusky/service/AccountChooserService.kt
new file mode 100644
index 00000000..dd39160d
--- /dev/null
+++ b/app/src/main/java/com/keylesspalace/tusky/service/AccountChooserService.kt
@@ -0,0 +1,61 @@
+/* Copyright 2019 Levi Bard
+ *
+ * This file is a part of Tusky.
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with Tusky; if not,
+ * see . */
+
+package com.keylesspalace.tusky.service
+
+import android.annotation.TargetApi
+import android.content.ComponentName
+import android.content.IntentFilter
+import android.graphics.drawable.Icon
+import android.os.Bundle
+import android.service.chooser.ChooserTarget
+import android.service.chooser.ChooserTargetService
+import android.text.TextUtils
+import com.keylesspalace.tusky.R
+import com.keylesspalace.tusky.db.AccountManager
+import com.keylesspalace.tusky.di.Injectable
+import com.keylesspalace.tusky.util.NotificationHelper
+import com.squareup.picasso.Picasso
+import dagger.android.AndroidInjection
+import javax.inject.Inject
+
+@TargetApi(23)
+class AccountChooserService : ChooserTargetService(), Injectable {
+ @Inject
+ lateinit var accountManager: AccountManager
+
+ override fun onCreate() {
+ super.onCreate()
+ AndroidInjection.inject(this)
+ }
+
+ override fun onGetChooserTargets(targetActivityName: ComponentName?, intentFilter: IntentFilter?): MutableList {
+ val targets = mutableListOf()
+ for (account in accountManager.getAllAccountsOrderedByActive()) {
+ val icon: Icon = if (TextUtils.isEmpty(account.profilePictureUrl)) {
+ Icon.createWithResource(applicationContext, R.drawable.avatar_default)
+ } else {
+ Icon.createWithBitmap(Picasso.with(this).load(account.profilePictureUrl)
+ .error(R.drawable.avatar_default)
+ .placeholder(R.drawable.avatar_default)
+ .get())
+ }
+ val bundle = Bundle()
+ bundle.putLong(NotificationHelper.ACCOUNT_ID, account.id)
+ targets.add(ChooserTarget(account.displayName, icon, 1.0f, targetActivityName, bundle))
+ }
+ return targets
+ }
+}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index eef63087..7bdb52da 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -116,6 +116,7 @@
Copy the link
Open as %s
+ Share as …
Share toot URL to…
Share toot to…