1
0
mirror of https://github.com/TwidereProject/Twidere-Android synced 2025-02-10 00:30:51 +01:00

code cleanup

This commit is contained in:
Mariotaku Lee 2016-12-15 13:11:32 +08:00
parent 76ee626068
commit 44ac6750b0
61 changed files with 391 additions and 268 deletions

View File

@ -32,7 +32,7 @@ allprojects {
subprojects { subprojects {
buildscript { buildscript {
ext.kotlin_version = '1.0.5-2' ext.kotlin_version = '1.0.5-2'
ext.android_support_lib_version = '25.0.1' ext.android_support_lib_version = '25.1.0'
ext.mariotaku_commons_library_version = '0.9.11' ext.mariotaku_commons_library_version = '0.9.11'
ext.mariotaku_restfu_version = '0.9.34' ext.mariotaku_restfu_version = '0.9.34'
} }

View File

@ -1,56 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.util;
import android.app.Application;
import android.support.annotation.NonNull;
/**
* Created by mariotaku on 15/7/8.
*/
public abstract class BugReporter {
private static BugReporter sImplementation;
public static void setImplementation(BugReporter impl) {
sImplementation = impl;
}
public static void init(Application application) {
if (sImplementation == null) return;
sImplementation.initImpl(application);
}
public static void log(int priority, String tag, String msg) {
if (sImplementation == null) return;
sImplementation.logImpl(priority, tag, msg);
}
public static void logException(@NonNull Throwable throwable) {
if (sImplementation == null) return;
sImplementation.logExceptionImpl(throwable);
}
protected abstract void logImpl(int priority, String tag, String msg);
protected abstract void logExceptionImpl(@NonNull Throwable throwable);
protected abstract void initImpl(Application application);
}

View File

@ -65,6 +65,10 @@
<init>(android.content.Context); <init>(android.content.Context);
} }
-keep class * extends org.mariotaku.twidere.util.MapFragmentFactory
-keep class * extends org.mariotaku.twidere.util.TwitterCardFragmentFactory
-keep class * extends org.mariotaku.twidere.util.BugReporter
-keepclassmembers class * { -keepclassmembers class * {
private <fields>; private <fields>;
} }

View File

@ -0,0 +1,20 @@
package org.mariotaku.twidere.util
import android.support.test.runner.AndroidJUnit4
import org.junit.Assert
import org.junit.Test
import org.junit.runner.RunWith
import org.mariotaku.twidere.BuildConfig
/**
* Created by mariotaku on 2016/12/15.
*/
@RunWith(AndroidJUnit4::class)
class AnalyzerTest {
@Test
fun testGetInstance() {
if (BuildConfig.FLAVOR.contains("google")) {
Assert.assertNotNull(Analyzer.implementation)
}
}
}

View File

@ -0,0 +1,18 @@
package org.mariotaku.twidere.util
import android.support.test.InstrumentationRegistry
import android.support.test.runner.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
/**
* Created by mariotaku on 2016/12/15.
*/
@RunWith(AndroidJUnit4::class)
class MapFragmentFactoryTest {
@Test
fun testGetInstance() {
val context = InstrumentationRegistry.getTargetContext()
MapFragmentFactory.instance.createMapFragment(context = context)
}
}

View File

@ -0,0 +1,16 @@
package org.mariotaku.twidere.util
import android.support.test.runner.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
/**
* Created by mariotaku on 2016/12/15.
*/
@RunWith(AndroidJUnit4::class)
class TwitterCardFragmentFactoryTest {
@Test
fun testGetInstance() {
TwitterCardFragmentFactory.instance
}
}

View File

@ -1,42 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.util;
import android.app.Application;
import android.support.annotation.NonNull;
/**
* Created by mariotaku on 15/7/8.
*/
public class TwidereBugReporter extends BugReporter {
@Override
protected void logImpl(int priority, String tag, String msg) {
}
@Override
protected void logExceptionImpl(@NonNull final Throwable throwable) {
}
@Override
protected void initImpl(final Application application) {
}
}

View File

@ -17,20 +17,18 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.mariotaku.twidere.util; package org.mariotaku.twidere.util
import android.content.Context; import android.content.Context
import android.support.annotation.NonNull; import android.support.v4.app.Fragment
import android.support.v4.app.Fragment;
import org.mariotaku.twidere.fragment.OpenStreetMapViewerFragment; import org.mariotaku.twidere.fragment.OpenStreetMapViewerFragment
/** /**
* Created by mariotaku on 15/4/27. * Created by mariotaku on 15/4/27.
*/ */
public class MapFragmentFactoryImpl extends MapFragmentFactory { class OSMMapFragmentFactory : MapFragmentFactory() {
@Override override fun createMapFragment(context: Context): Fragment {
public Fragment createMapFragment(@NonNull Context context) { return OpenStreetMapViewerFragment()
return new OpenStreetMapViewerFragment();
} }
} }

View File

@ -0,0 +1 @@
org.mariotaku.twidere.util.OSMMapFragmentFactory

View File

@ -0,0 +1 @@
org.mariotaku.twidere.util.TwitterCardFragmentFactoryImpl

View File

@ -25,25 +25,52 @@ import android.accounts.OnAccountsUpdateListener
import android.app.Application import android.app.Application
import android.os.Build import android.os.Build
import com.crashlytics.android.Crashlytics import com.crashlytics.android.Crashlytics
import com.crashlytics.android.answers.Answers
import com.crashlytics.android.answers.AnswersEvent
import com.crashlytics.android.answers.LoginEvent
import com.crashlytics.android.answers.SearchEvent
import io.fabric.sdk.android.Fabric import io.fabric.sdk.android.Fabric
import org.mariotaku.ktextension.addOnAccountsUpdatedListenerSafe import org.mariotaku.ktextension.addOnAccountsUpdatedListenerSafe
import org.mariotaku.ktextension.configure
import org.mariotaku.twidere.BuildConfig import org.mariotaku.twidere.BuildConfig
import org.mariotaku.twidere.Constants import org.mariotaku.twidere.Constants
import org.mariotaku.twidere.TwidereConstants.ACCOUNT_TYPE
import org.mariotaku.twidere.model.analyzer.Search
import org.mariotaku.twidere.model.analyzer.SignIn
/** /**
* Created by mariotaku on 15/7/8. * Created by mariotaku on 15/7/8.
*/ */
class TwidereBugReporter : BugReporter(), Constants { class FabricAnalyzer : Analyzer(), Constants {
override fun logImpl(priority: Int, tag: String, msg: String) { override fun log(priority: Int, tag: String, msg: String) {
Crashlytics.log(priority, tag, msg) Crashlytics.log(priority, tag, msg)
} }
override fun logExceptionImpl(throwable: Throwable) { override fun logException(throwable: Throwable) {
Crashlytics.logException(throwable) Crashlytics.logException(throwable)
} }
override fun initImpl(application: Application) { override fun log(event: Event) {
val answers = Answers.getInstance()
when (event) {
is SignIn -> {
answers.logLogin(configure(LoginEvent()) {
putMethod(event.type)
putSuccess(event.success)
putAttributes(event)
})
}
is Search -> {
answers.logSearch(configure(SearchEvent()) {
putQuery(event.query)
putAttributes(event)
})
}
}
}
override fun init(application: Application) {
Fabric.with(application, Crashlytics()) Fabric.with(application, Crashlytics())
Crashlytics.setBool("debug", BuildConfig.DEBUG) Crashlytics.setBool("debug", BuildConfig.DEBUG)
Crashlytics.setString("build.brand", Build.BRAND) Crashlytics.setString("build.brand", Build.BRAND)
@ -55,8 +82,14 @@ class TwidereBugReporter : BugReporter(), Constants {
Crashlytics.setString("build.product", Build.PRODUCT) Crashlytics.setString("build.product", Build.PRODUCT)
val am = AccountManager.get(application) val am = AccountManager.get(application)
am.addOnAccountsUpdatedListenerSafe(OnAccountsUpdateListener { accounts -> am.addOnAccountsUpdatedListenerSafe(OnAccountsUpdateListener { accounts ->
Crashlytics.setString("twidere.accounts", accounts.joinToString(transform = Account::name)) Crashlytics.setString("twidere.accounts", accounts.filter { it.type == ACCOUNT_TYPE }
.joinToString(transform = Account::name))
}, updateImmediately = true) }, updateImmediately = true)
} }
private fun AnswersEvent<*>.putAttributes(event: Analyzer.Event) {
if (event.account != null) {
putCustomAttribute("account", event.account)
}
}
} }

View File

@ -31,7 +31,7 @@ import org.mariotaku.twidere.fragment.WebMapFragment
/** /**
* Created by mariotaku on 15/4/27. * Created by mariotaku on 15/4/27.
*/ */
class MapFragmentFactoryImpl : MapFragmentFactory() { class GoogleMapFragmentFactory : MapFragmentFactory() {
override fun createMapFragment(context: Context): Fragment { override fun createMapFragment(context: Context): Fragment {
if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context) == ConnectionResult.SUCCESS) { if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context) == ConnectionResult.SUCCESS) {

View File

@ -0,0 +1 @@
org.mariotaku.twidere.util.FabricAnalyzer

View File

@ -0,0 +1 @@
org.mariotaku.twidere.util.GoogleMapFragmentFactory

View File

@ -0,0 +1 @@
org.mariotaku.twidere.util.TwitterCardFragmentFactoryImpl

View File

@ -1,12 +0,0 @@
package android.support.v4.app;
public class BackStackEntryAccessor {
private BackStackEntryAccessor() {
}
public static Fragment getFragmentInBackStackRecord(final FragmentManager.BackStackEntry entry) {
if (entry instanceof BackStackRecord) return ((BackStackRecord) entry).mHead.fragment;
return null;
}
}

View File

@ -167,7 +167,7 @@ public class NetworkDiagnosticsFragment extends BaseSupportFragment {
publishProgress(LogText.LINEBREAK, LogText.LINEBREAK); publishProgress(LogText.LINEBREAK, LogText.LINEBREAK);
for (UserKey accountKey : DataStoreUtils.getAccountKeys(mContext)) { for (UserKey accountKey : DataStoreUtils.getAccountKeys(mContext)) {
final AccountDetails details = AccountUtils.getAccountDetails(AccountManager.get(mContext), accountKey); final AccountDetails details = AccountUtils.getAccountDetails(AccountManager.get(mContext), accountKey, true);
final MicroBlog twitter = MicroBlogAPIFactory.getInstance(mContext, accountKey); final MicroBlog twitter = MicroBlogAPIFactory.getInstance(mContext, accountKey);
if (details == null || twitter == null) continue; if (details == null || twitter == null) continue;
publishProgress(new LogText("Testing connection for account " + accountKey)); publishProgress(new LogText("Testing connection for account " + accountKey));

View File

@ -50,7 +50,7 @@ public class AccountPreferences implements Constants {
} }
public int getDefaultNotificationLightColor() { public int getDefaultNotificationLightColor() {
final AccountDetails a = AccountUtils.getAccountDetails(AccountManager.get(mContext), mAccountKey); final AccountDetails a = AccountUtils.getAccountDetails(AccountManager.get(mContext), mAccountKey, true);
if (a != null) { if (a != null) {
return a.color; return a.color;
} else { } else {

View File

@ -41,49 +41,52 @@ public class AccountUtils {
return am.getAccountsByType(ACCOUNT_TYPE); return am.getAccountsByType(ACCOUNT_TYPE);
} }
public static AccountDetails[] getAllAccountDetails(@NonNull AccountManager am, @NonNull Account[] accounts) { public static AccountDetails[] getAllAccountDetails(@NonNull AccountManager am, @NonNull Account[] accounts, boolean getCredentials) {
AccountDetails[] details = new AccountDetails[accounts.length]; AccountDetails[] details = new AccountDetails[accounts.length];
for (int i = 0; i < accounts.length; i++) { for (int i = 0; i < accounts.length; i++) {
details[i] = getAccountDetails(am, accounts[i]); details[i] = getAccountDetails(am, accounts[i], getCredentials);
} }
Arrays.sort(details); Arrays.sort(details);
return details; return details;
} }
public static AccountDetails[] getAllAccountDetails(@NonNull AccountManager am, @NonNull UserKey[] accountKeys) { public static AccountDetails[] getAllAccountDetails(@NonNull AccountManager am, @NonNull UserKey[] accountKeys, boolean getCredentials) {
AccountDetails[] details = new AccountDetails[accountKeys.length]; AccountDetails[] details = new AccountDetails[accountKeys.length];
for (int i = 0; i < accountKeys.length; i++) { for (int i = 0; i < accountKeys.length; i++) {
details[i] = getAccountDetails(am, accountKeys[i]); details[i] = getAccountDetails(am, accountKeys[i], getCredentials);
} }
Arrays.sort(details); Arrays.sort(details);
return details; return details;
} }
public static AccountDetails[] getAllAccountDetails(@NonNull AccountManager am) { public static AccountDetails[] getAllAccountDetails(@NonNull AccountManager am, boolean getCredentials) {
return getAllAccountDetails(am, getAccounts(am)); return getAllAccountDetails(am, getAccounts(am), getCredentials);
} }
@Nullable @Nullable
public static AccountDetails getAccountDetails(@NonNull AccountManager am, @NonNull UserKey accountKey) { public static AccountDetails getAccountDetails(@NonNull AccountManager am, @NonNull UserKey accountKey, boolean getCredentials) {
final Account account = findByAccountKey(am, accountKey); final Account account = findByAccountKey(am, accountKey);
if (account == null) return null; if (account == null) return null;
return getAccountDetails(am, account); return getAccountDetails(am, account, getCredentials);
} }
public static AccountDetails getAccountDetails(@NonNull AccountManager am, @NonNull Account account) { public static AccountDetails getAccountDetails(@NonNull AccountManager am, @NonNull Account account, boolean getCredentials) {
AccountDetails details = new AccountDetails(); AccountDetails details = new AccountDetails();
details.key = AccountExtensionsKt.getAccountKey(account, am); details.key = AccountExtensionsKt.getAccountKey(account, am);
details.account = account; details.account = account;
details.color = AccountExtensionsKt.getColor(account, am); details.color = AccountExtensionsKt.getColor(account, am);
details.position = AccountExtensionsKt.getPosition(account, am); details.position = AccountExtensionsKt.getPosition(account, am);
details.credentials = AccountExtensionsKt.getCredentials(account, am);
details.user = AccountExtensionsKt.getAccountUser(account, am);
details.activated = AccountExtensionsKt.isActivated(account, am); details.activated = AccountExtensionsKt.isActivated(account, am);
details.type = AccountExtensionsKt.getAccountType(account, am); details.type = AccountExtensionsKt.getAccountType(account, am);
details.credentials_type = AccountExtensionsKt.getCredentialsType(account, am); details.credentials_type = AccountExtensionsKt.getCredentialsType(account, am);
details.user = AccountExtensionsKt.getAccountUser(account, am);
details.user.color = details.color;
details.extras = AccountExtensionsKt.getAccountExtras(account, am); details.extras = AccountExtensionsKt.getAccountExtras(account, am);
details.user.color = details.color; if (getCredentials) {
details.credentials = AccountExtensionsKt.getCredentials(account, am);
}
return details; return details;
} }
@ -97,7 +100,7 @@ public class AccountUtils {
} }
public static boolean hasOfficialKeyAccount(Context context) { public static boolean hasOfficialKeyAccount(Context context) {
for (AccountDetails details : getAllAccountDetails(AccountManager.get(context))) { for (AccountDetails details : getAllAccountDetails(AccountManager.get(context), true)) {
if (AccountDetailsExtensionsKt.isOfficial(details, context)) { if (AccountDetailsExtensionsKt.isOfficial(details, context)) {
return true; return true;
} }

View File

@ -18,7 +18,7 @@ public class ParcelableStatusUpdateUtils {
public static ParcelableStatusUpdate fromDraftItem(final Context context, final Draft draft) { public static ParcelableStatusUpdate fromDraftItem(final Context context, final Draft draft) {
ParcelableStatusUpdate statusUpdate = new ParcelableStatusUpdate(); ParcelableStatusUpdate statusUpdate = new ParcelableStatusUpdate();
if (draft.account_keys != null) { if (draft.account_keys != null) {
statusUpdate.accounts = AccountUtils.getAllAccountDetails(AccountManager.get(context), draft.account_keys); statusUpdate.accounts = AccountUtils.getAllAccountDetails(AccountManager.get(context), draft.account_keys, true);
} else { } else {
statusUpdate.accounts = new AccountDetails[0]; statusUpdate.accounts = new AccountDetails[0];
} }

View File

@ -92,7 +92,7 @@ public abstract class AccountsListPreference extends PreferenceCategory implemen
protected void onAttachedToHierarchy(@NonNull final PreferenceManager preferenceManager) { protected void onAttachedToHierarchy(@NonNull final PreferenceManager preferenceManager) {
super.onAttachedToHierarchy(preferenceManager); super.onAttachedToHierarchy(preferenceManager);
if (getPreferenceCount() > 0) return; if (getPreferenceCount() > 0) return;
setAccountsData(AccountUtils.getAllAccountDetails(AccountManager.get(getContext()))); setAccountsData(AccountUtils.getAllAccountDetails(AccountManager.get(getContext()), true));
} }
protected abstract void setupPreference(AccountItemPreference preference, AccountDetails account); protected abstract void setupPreference(AccountItemPreference preference, AccountDetails account);

View File

@ -628,7 +628,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
@Override @Override
protected SingleResponse<ParcelableStatus> doInBackground(final Object... params) { protected SingleResponse<ParcelableStatus> doInBackground(final Object... params) {
final ContentResolver resolver = getContext().getContentResolver(); final ContentResolver resolver = getContext().getContentResolver();
final AccountDetails details = AccountUtils.getAccountDetails(AccountManager.get(getContext()), mAccountKey); final AccountDetails details = AccountUtils.getAccountDetails(AccountManager.get(getContext()), mAccountKey, true);
if (details == null) return SingleResponse.Companion.getInstance(); if (details == null) return SingleResponse.Companion.getInstance();
final MicroBlog microBlog = AccountDetailsExtensionsKt.newMicroBlogInstance(details, final MicroBlog microBlog = AccountDetailsExtensionsKt.newMicroBlogInstance(details,
getContext(), MicroBlog.class); getContext(), MicroBlog.class);
@ -1114,7 +1114,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
@Override @Override
protected SingleResponse<ParcelableStatus> doInBackground(final Object... params) { protected SingleResponse<ParcelableStatus> doInBackground(final Object... params) {
final AccountDetails details = AccountUtils.getAccountDetails(AccountManager.get(context), mAccountKey); final AccountDetails details = AccountUtils.getAccountDetails(AccountManager.get(context), mAccountKey, true);
if (details == null) return SingleResponse.Companion.getInstance(); if (details == null) return SingleResponse.Companion.getInstance();
final MicroBlog microBlog = AccountDetailsExtensionsKt.newMicroBlogInstance(details, final MicroBlog microBlog = AccountDetailsExtensionsKt.newMicroBlogInstance(details,
getContext(), MicroBlog.class); getContext(), MicroBlog.class);
@ -1359,7 +1359,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
protected SingleResponse<ParcelableStatus> doInBackground(final Object... params) { protected SingleResponse<ParcelableStatus> doInBackground(final Object... params) {
final ContentResolver resolver = getContext().getContentResolver(); final ContentResolver resolver = getContext().getContentResolver();
final AccountDetails details = AccountUtils.getAccountDetails(AccountManager.get(getContext()), final AccountDetails details = AccountUtils.getAccountDetails(AccountManager.get(getContext()),
mAccountKey); mAccountKey, true);
if (details == null) return SingleResponse.Companion.getInstance(); if (details == null) return SingleResponse.Companion.getInstance();
final MicroBlog microBlog = AccountDetailsExtensionsKt.newMicroBlogInstance(details, final MicroBlog microBlog = AccountDetailsExtensionsKt.newMicroBlogInstance(details,
getContext(), MicroBlog.class); getContext(), MicroBlog.class);

View File

@ -93,8 +93,8 @@ public class MicroBlogAPIFactory implements TwidereConstants {
@WorkerThread @WorkerThread
public static MicroBlog getInstance(@NonNull final Context context, public static MicroBlog getInstance(@NonNull final Context context,
@NonNull final UserKey accountKey) { @NonNull final UserKey accountKey) {
AccountManager am = AccountManager.get(context); final AccountManager am = AccountManager.get(context);
Account account = AccountUtils.findByAccountKey(am, accountKey); final Account account = AccountUtils.findByAccountKey(am, accountKey);
if (account == null) return null; if (account == null) return null;
final Credentials credentials = AccountExtensionsKt.getCredentials(account, am); final Credentials credentials = AccountExtensionsKt.getCredentials(account, am);
final String accountType = AccountExtensionsKt.getAccountType(account, am); final String accountType = AccountExtensionsKt.getAccountType(account, am);

View File

@ -508,7 +508,7 @@ public final class Utils implements Constants {
} }
public static boolean isOfficialCredentials(@NonNull final Context context, final UserKey accountKey) { public static boolean isOfficialCredentials(@NonNull final Context context, final UserKey accountKey) {
final AccountDetails details = AccountUtils.getAccountDetails(AccountManager.get(context), accountKey); final AccountDetails details = AccountUtils.getAccountDetails(AccountManager.get(context), accountKey, true);
if (details == null) return false; if (details == null) return false;
return AccountDetailsExtensionsKt.isOfficial(details, context); return AccountDetailsExtensionsKt.isOfficial(details, context);
} }
@ -599,14 +599,14 @@ public final class Utils implements Constants {
if (t instanceof MicroBlogException) if (t instanceof MicroBlogException)
return getTwitterErrorMessage(context, action, (MicroBlogException) t); return getTwitterErrorMessage(context, action, (MicroBlogException) t);
else if (t != null) return getErrorMessage(context, trimLineBreak(t.getMessage())); else if (t != null) return getErrorMessage(context, trimLineBreak(t.getMessage()));
TwidereBugReporter.logException(new IllegalStateException()); Analyzer.Companion.logException(new IllegalStateException());
return context.getString(R.string.error_unknown_error); return context.getString(R.string.error_unknown_error);
} }
@Nullable @Nullable
public static String getErrorMessage(@NonNull final Context context, final Throwable t) { public static String getErrorMessage(@NonNull final Context context, final Throwable t) {
if (t == null) { if (t == null) {
TwidereBugReporter.logException(new IllegalStateException()); Analyzer.Companion.logException(new IllegalStateException());
return context.getString(R.string.error_unknown_error); return context.getString(R.string.error_unknown_error);
} }
if (t instanceof MicroBlogException) if (t instanceof MicroBlogException)
@ -1189,10 +1189,10 @@ public final class Utils implements Constants {
if (appContext == null) return; if (appContext == null) return;
if (!appContext.getResources().getBoolean(R.bool.use_legacy_refresh_service)) return; if (!appContext.getResources().getBoolean(R.bool.use_legacy_refresh_service)) return;
final Intent refreshServiceIntent = new Intent(appContext, RefreshService.class); final Intent refreshServiceIntent = new Intent(appContext, RefreshService.class);
DataStoreUtils.prepareDatabase(context);
AsyncTask.execute(new Runnable() { AsyncTask.execute(new Runnable() {
@Override @Override
public void run() { public void run() {
DataStoreUtils.prepareDatabase(context);
if (isNetworkAvailable(appContext) && hasAutoRefreshAccounts(appContext)) { if (isNetworkAvailable(appContext) && hasAutoRefreshAccounts(appContext)) {
if (BuildConfig.DEBUG) { if (BuildConfig.DEBUG) {
Log.d(LOGTAG, "Start background refresh service"); Log.d(LOGTAG, "Start background refresh service");
@ -1471,7 +1471,7 @@ public final class Utils implements Constants {
try { try {
Menu.class.isAssignableFrom(MenuBuilder.class); Menu.class.isAssignableFrom(MenuBuilder.class);
} catch (Error e) { } catch (Error e) {
TwidereBugReporter.logException(e); Analyzer.Companion.logException(e);
return false; return false;
} }
return true; return true;

View File

@ -124,7 +124,7 @@ public class TwidereMediaDownloader implements MediaDownloader, Constants {
useThumbor = ((MediaExtra) extra).isUseThumbor(); useThumbor = ((MediaExtra) extra).isUseThumbor();
UserKey accountKey = ((MediaExtra) extra).getAccountKey(); UserKey accountKey = ((MediaExtra) extra).getAccountKey();
if (accountKey != null) { if (accountKey != null) {
account = AccountUtils.getAccountDetails(AccountManager.get(mContext), accountKey); account = AccountUtils.getAccountDetails(AccountManager.get(mContext), accountKey, true);
if (account != null) { if (account != null) {
auth = CredentialsExtensionsKt.getAuthorization(account.credentials); auth = CredentialsExtensionsKt.getAuthorization(account.credentials);
} }

View File

@ -39,6 +39,7 @@ import org.mariotaku.twidere.app.TwidereApplication
import org.mariotaku.twidere.extension.model.is_oauth import org.mariotaku.twidere.extension.model.is_oauth
import org.mariotaku.twidere.model.UserKey import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.model.util.AccountUtils import org.mariotaku.twidere.model.util.AccountUtils
import org.mariotaku.twidere.util.DataStoreUtils
class AccountSelectorActivity : BaseActivity(), OnClickListener, OnItemClickListener { class AccountSelectorActivity : BaseActivity(), OnClickListener, OnItemClickListener {
@ -83,12 +84,13 @@ class AccountSelectorActivity : BaseActivity(), OnClickListener, OnItemClickList
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
firstCreated = savedInstanceState == null firstCreated = savedInstanceState == null
setContentView(R.layout.activity_account_selector) setContentView(R.layout.activity_account_selector)
DataStoreUtils.prepareDatabase(this)
adapter = AccountDetailsAdapter(this).apply { adapter = AccountDetailsAdapter(this).apply {
setSwitchEnabled(!isSingleSelection) setSwitchEnabled(!isSingleSelection)
setSortEnabled(false) setSortEnabled(false)
isProfileImageDisplayed = preferences.getBoolean(KEY_DISPLAY_PROFILE_IMAGE, true) isProfileImageDisplayed = preferences.getBoolean(KEY_DISPLAY_PROFILE_IMAGE, true)
val am = AccountManager.get(context) val am = AccountManager.get(context)
val allAccountDetails = AccountUtils.getAllAccountDetails(am, AccountUtils.getAccounts(am)) val allAccountDetails = AccountUtils.getAllAccountDetails(am, AccountUtils.getAccounts(am), false)
val extraKeys = keysWhiteList val extraKeys = keysWhiteList
val oAuthOnly = isOAuthOnly val oAuthOnly = isOAuthOnly
val accountHost = accountHost val accountHost = accountHost

View File

@ -71,6 +71,7 @@ import org.mariotaku.twidere.R
import org.mariotaku.twidere.adapter.ArrayRecyclerAdapter import org.mariotaku.twidere.adapter.ArrayRecyclerAdapter
import org.mariotaku.twidere.adapter.BaseRecyclerViewAdapter import org.mariotaku.twidere.adapter.BaseRecyclerViewAdapter
import org.mariotaku.twidere.constant.* import org.mariotaku.twidere.constant.*
import org.mariotaku.twidere.extension.getAccountUser
import org.mariotaku.twidere.fragment.BaseDialogFragment import org.mariotaku.twidere.fragment.BaseDialogFragment
import org.mariotaku.twidere.fragment.PermissionRequestDialog import org.mariotaku.twidere.fragment.PermissionRequestDialog
import org.mariotaku.twidere.fragment.PermissionRequestDialog.PermissionRequestCancelCallback import org.mariotaku.twidere.fragment.PermissionRequestDialog.PermissionRequestCancelCallback
@ -491,7 +492,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
finish() finish()
return return
} }
val accountDetails = AccountUtils.getAllAccountDetails(am, accounts) val accountDetails = AccountUtils.getAllAccountDetails(am, accounts, true)
val defaultAccountIds = accountDetails.map(AccountDetails::key).toTypedArray() val defaultAccountIds = accountDetails.map(AccountDetails::key).toTypedArray()
menuBar.setOnMenuItemClickListener(this) menuBar.setOnMenuItemClickListener(this)
setupEditText() setupEditText()
@ -994,7 +995,8 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
private fun handleReplyIntent(status: ParcelableStatus?): Boolean { private fun handleReplyIntent(status: ParcelableStatus?): Boolean {
if (status == null) return false if (status == null) return false
val account = AccountUtils.getAccountDetails(AccountManager.get(this), status.account_key) ?: return false val am = AccountManager.get(this)
val accountUser = AccountUtils.findByAccountKey(am, status.account_key)?.getAccountUser(am) ?: return false
var selectionStart = 0 var selectionStart = 0
val mentions = TreeSet(String.CASE_INSENSITIVE_ORDER) val mentions = TreeSet(String.CASE_INSENSITIVE_ORDER)
editText.append("@" + status.user_screen_name + " ") editText.append("@" + status.user_screen_name + " ")
@ -1025,7 +1027,8 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
} }
} }
mentions.filterNot { it.equals(status.user_screen_name, ignoreCase = true) || it.equals(account.user.screen_name, ignoreCase = true) } mentions.filterNot { it.equals(status.user_screen_name, ignoreCase = true)
|| it.equals(accountUser.screen_name, ignoreCase = true) }
.forEach { editText.append("@$it ") } .forEach { editText.append("@$it ") }
val selectionEnd = editText.length() val selectionEnd = editText.length()
editText.setSelection(selectionStart, selectionEnd) editText.setSelection(selectionStart, selectionEnd)
@ -1292,7 +1295,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
val isPossiblySensitive = hasMedia && possiblySensitive val isPossiblySensitive = hasMedia && possiblySensitive
val update = ParcelableStatusUpdate() val update = ParcelableStatusUpdate()
@Draft.Action val action = draft?.action_type ?: getDraftAction(intent.action) @Draft.Action val action = draft?.action_type ?: getDraftAction(intent.action)
update.accounts = AccountUtils.getAllAccountDetails(AccountManager.get(this), accountKeys) update.accounts = AccountUtils.getAllAccountDetails(AccountManager.get(this), accountKeys, true)
update.text = text update.text = text
if (attachLocation) { if (attachLocation) {
update.location = recentLocation update.location = recentLocation

View File

@ -58,12 +58,12 @@ import org.mariotaku.twidere.util.Utils.matchLinkId
class LinkHandlerActivity : BaseActivity(), SystemWindowsInsetsCallback, IControlBarActivity, SupportFragmentCallback { class LinkHandlerActivity : BaseActivity(), SystemWindowsInsetsCallback, IControlBarActivity, SupportFragmentCallback {
private val mControlBarShowHideHelper = ControlBarShowHideHelper(this) private lateinit var multiSelectHandler: MultiSelectEventHandler
private var mMultiSelectHandler: MultiSelectEventHandler? = null private lateinit var controlBarShowHideHelper: ControlBarShowHideHelper
private var mFinishOnly: Boolean = false private var finishOnly: Boolean = false
private var mActionBarHeight: Int = 0 private var actionBarHeight: Int = 0
private var mSubtitle: CharSequence? = null private var subtitle: CharSequence? = null
private var mHideOffsetNotSupported: Boolean = false private var hideOffsetNotSupported: Boolean = false
override val currentVisibleFragment: Fragment? override val currentVisibleFragment: Fragment?
@ -90,7 +90,7 @@ class LinkHandlerActivity : BaseActivity(), SystemWindowsInsetsCallback, IContro
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) { when (item.itemId) {
android.R.id.home -> { android.R.id.home -> {
if (mFinishOnly) { if (finishOnly) {
finish() finish()
} else { } else {
NavUtils.navigateUpFromSameTask(this) NavUtils.navigateUpFromSameTask(this)
@ -142,17 +142,20 @@ class LinkHandlerActivity : BaseActivity(), SystemWindowsInsetsCallback, IContro
} }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
mMultiSelectHandler = MultiSelectEventHandler(this) super.onCreate(savedInstanceState)
mMultiSelectHandler!!.dispatchOnCreate() multiSelectHandler = MultiSelectEventHandler(this)
val intent = intent controlBarShowHideHelper = ControlBarShowHideHelper(this)
multiSelectHandler.dispatchOnCreate()
val uri = intent.data val uri = intent.data
val linkId = matchLinkId(uri) val linkId = matchLinkId(uri)
intent.setExtrasClassLoader(classLoader) intent.setExtrasClassLoader(classLoader)
val fragment: Fragment? val fragment: Fragment
try { try {
fragment = createFragmentForIntent(this, linkId, intent) fragment = createFragmentForIntent(this, linkId, intent) ?: run {
finish()
return
}
} catch (e: Utils.NoAccountException) { } catch (e: Utils.NoAccountException) {
super.onCreate(savedInstanceState)
val selectIntent = Intent(this, AccountSelectorActivity::class.java) val selectIntent = Intent(this, AccountSelectorActivity::class.java)
val accountHost: String? = intent.getStringExtra(EXTRA_ACCOUNT_HOST) ?: val accountHost: String? = intent.getStringExtra(EXTRA_ACCOUNT_HOST) ?:
uri.getQueryParameter(QUERY_PARAM_ACCOUNT_HOST) ?: e.accountHost uri.getQueryParameter(QUERY_PARAM_ACCOUNT_HOST) ?: e.accountHost
@ -172,20 +175,13 @@ class LinkHandlerActivity : BaseActivity(), SystemWindowsInsetsCallback, IContro
} }
} }
super.onCreate(savedInstanceState)
if (fragment == null) {
finish()
return
}
setupActionBarOption() setupActionBarOption()
Utils.logOpenNotificationFromUri(this, uri) Utils.logOpenNotificationFromUri(this, uri)
val ft = supportFragmentManager.beginTransaction() val ft = supportFragmentManager.beginTransaction()
ft.replace(android.R.id.content, fragment) ft.replace(android.R.id.content, fragment)
ft.commit() ft.commit()
setTitle(linkId, uri) setTitle(linkId, uri)
mFinishOnly = java.lang.Boolean.parseBoolean(uri.getQueryParameter(QUERY_PARAM_FINISH_ONLY)) finishOnly = java.lang.Boolean.parseBoolean(uri.getQueryParameter(QUERY_PARAM_FINISH_ONLY))
if (fragment is IToolBarSupportFragment) { if (fragment is IToolBarSupportFragment) {
ThemeUtils.setCompatContentViewOverlay(window, EmptyDrawable()) ThemeUtils.setCompatContentViewOverlay(window, EmptyDrawable())
@ -194,12 +190,12 @@ class LinkHandlerActivity : BaseActivity(), SystemWindowsInsetsCallback, IContro
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
mMultiSelectHandler!!.dispatchOnStart() multiSelectHandler.dispatchOnStart()
} }
override fun onStop() { override fun onStop() {
mMultiSelectHandler!!.dispatchOnStop() multiSelectHandler.dispatchOnStop()
super.onStop() super.onStop()
} }
@ -209,20 +205,20 @@ class LinkHandlerActivity : BaseActivity(), SystemWindowsInsetsCallback, IContro
} }
fun setSubtitle(subtitle: CharSequence?) { fun setSubtitle(subtitle: CharSequence?) {
mSubtitle = subtitle this.subtitle = subtitle
setupActionBarOption() setupActionBarOption()
} }
override fun setControlBarVisibleAnimate(visible: Boolean) { override fun setControlBarVisibleAnimate(visible: Boolean) {
// Currently only search page needs this pattern, so we only enable this feature for it. // Currently only search page needs this pattern, so we only enable this feature for it.
if (currentVisibleFragment !is HideUiOnScroll) return if (currentVisibleFragment !is HideUiOnScroll) return
mControlBarShowHideHelper.setControlBarVisibleAnimate(visible) controlBarShowHideHelper.setControlBarVisibleAnimate(visible)
} }
override fun setControlBarVisibleAnimate(visible: Boolean, listener: ControlBarShowHideHelper.ControlBarAnimationListener) { override fun setControlBarVisibleAnimate(visible: Boolean, listener: ControlBarShowHideHelper.ControlBarAnimationListener) {
// Currently only search page needs this pattern, so we only enable this feature for it. // Currently only search page needs this pattern, so we only enable this feature for it.
if (currentVisibleFragment !is HideUiOnScroll) return if (currentVisibleFragment !is HideUiOnScroll) return
mControlBarShowHideHelper.setControlBarVisibleAnimate(visible, listener) controlBarShowHideHelper.setControlBarVisibleAnimate(visible, listener)
} }
override fun getControlBarOffset(): Float { override fun getControlBarOffset(): Float {
@ -241,12 +237,12 @@ class LinkHandlerActivity : BaseActivity(), SystemWindowsInsetsCallback, IContro
val actionBar = supportActionBar val actionBar = supportActionBar
if (fragment is IToolBarSupportFragment) { if (fragment is IToolBarSupportFragment) {
fragment.controlBarOffset = offset fragment.controlBarOffset = offset
} else if (actionBar != null && !mHideOffsetNotSupported) { } else if (actionBar != null && !hideOffsetNotSupported) {
try { try {
actionBar.hideOffset = (controlBarHeight * offset).toInt() actionBar.hideOffset = (controlBarHeight * offset).toInt()
} catch (e: UnsupportedOperationException) { } catch (e: UnsupportedOperationException) {
// Some device will throw this exception // Some device will throw this exception
mHideOffsetNotSupported = true hideOffsetNotSupported = true
} }
} }
@ -261,9 +257,9 @@ class LinkHandlerActivity : BaseActivity(), SystemWindowsInsetsCallback, IContro
} else if (actionBar != null) { } else if (actionBar != null) {
return actionBar.height return actionBar.height
} }
if (mActionBarHeight != 0) return mActionBarHeight if (actionBarHeight != 0) return actionBarHeight
mActionBarHeight = ThemeUtils.getActionBarHeight(this) actionBarHeight = ThemeUtils.getActionBarHeight(this)
return mActionBarHeight return actionBarHeight
} }
private fun setTitle(linkId: Int, uri: Uri): Boolean { private fun setTitle(linkId: Int, uri: Uri): Boolean {
@ -408,7 +404,7 @@ class LinkHandlerActivity : BaseActivity(), SystemWindowsInsetsCallback, IContro
val actionBar = supportActionBar val actionBar = supportActionBar
if (actionBar != null) { if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true) actionBar.setDisplayHomeAsUpEnabled(true)
actionBar.subtitle = mSubtitle actionBar.subtitle = subtitle
} }
} }
@ -459,7 +455,7 @@ class LinkHandlerActivity : BaseActivity(), SystemWindowsInsetsCallback, IContro
args.putDouble(EXTRA_LATITUDE, lat) args.putDouble(EXTRA_LATITUDE, lat)
args.putDouble(EXTRA_LONGITUDE, lng) args.putDouble(EXTRA_LONGITUDE, lng)
} }
fragment = MapFragmentFactory.getInstance().createMapFragment(context) fragment = MapFragmentFactory.instance.createMapFragment(context)
} }
LINK_ID_STATUS -> { LINK_ID_STATUS -> {
fragment = StatusFragment() fragment = StatusFragment()
@ -721,6 +717,7 @@ class LinkHandlerActivity : BaseActivity(), SystemWindowsInsetsCallback, IContro
if (accountKey == null) { if (accountKey == null) {
val accountId = uri.getQueryParameter(CompatibilityConstants.QUERY_PARAM_ACCOUNT_ID) val accountId = uri.getQueryParameter(CompatibilityConstants.QUERY_PARAM_ACCOUNT_ID)
val paramAccountName = uri.getQueryParameter(QUERY_PARAM_ACCOUNT_NAME) val paramAccountName = uri.getQueryParameter(QUERY_PARAM_ACCOUNT_NAME)
DataStoreUtils.prepareDatabase(context)
if (accountId != null) { if (accountId != null) {
accountKey = DataStoreUtils.findAccountKey(context, accountId) accountKey = DataStoreUtils.findAccountKey(context, accountId)
args.putParcelable(EXTRA_ACCOUNT_KEY, accountKey) args.putParcelable(EXTRA_ACCOUNT_KEY, accountKey)

View File

@ -39,6 +39,7 @@ import android.widget.AdapterView.OnItemClickListener
import android.widget.AdapterView.OnItemSelectedListener import android.widget.AdapterView.OnItemSelectedListener
import jopt.csp.util.SortableIntList import jopt.csp.util.SortableIntList
import kotlinx.android.synthetic.main.activity_quick_search_bar.* import kotlinx.android.synthetic.main.activity_quick_search_bar.*
import org.mariotaku.kpreferences.get
import org.mariotaku.twidere.R import org.mariotaku.twidere.R
import org.mariotaku.twidere.TwidereConstants.QUERY_PARAM_ACCOUNT_KEY import org.mariotaku.twidere.TwidereConstants.QUERY_PARAM_ACCOUNT_KEY
import org.mariotaku.twidere.TwidereConstants.QUERY_PARAM_QUERY import org.mariotaku.twidere.TwidereConstants.QUERY_PARAM_QUERY
@ -47,7 +48,7 @@ import org.mariotaku.twidere.annotation.Referral
import org.mariotaku.twidere.constant.IntentConstants.EXTRA_ACCOUNT_KEY import org.mariotaku.twidere.constant.IntentConstants.EXTRA_ACCOUNT_KEY
import org.mariotaku.twidere.constant.KeyboardShortcutConstants.ACTION_NAVIGATION_BACK import org.mariotaku.twidere.constant.KeyboardShortcutConstants.ACTION_NAVIGATION_BACK
import org.mariotaku.twidere.constant.KeyboardShortcutConstants.CONTEXT_TAG_NAVIGATION import org.mariotaku.twidere.constant.KeyboardShortcutConstants.CONTEXT_TAG_NAVIGATION
import org.mariotaku.twidere.constant.SharedPreferenceConstants.KEY_NEW_DOCUMENT_API import org.mariotaku.twidere.constant.newDocumentApiKey
import org.mariotaku.twidere.model.AccountDetails import org.mariotaku.twidere.model.AccountDetails
import org.mariotaku.twidere.model.UserKey import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.model.util.AccountUtils import org.mariotaku.twidere.model.util.AccountUtils
@ -96,7 +97,7 @@ class QuickSearchBarActivity : BaseActivity(), OnClickListener, LoaderCallbacks<
} }
override fun onCreateLoader(id: Int, args: Bundle?): Loader<Cursor?> { override fun onCreateLoader(id: Int, args: Bundle?): Loader<Cursor?> {
val accountId = selectedAccountKey val accountId = selectedAccountDetails?.key
val builder = Suggestions.Search.CONTENT_URI.buildUpon() val builder = Suggestions.Search.CONTENT_URI.buildUpon()
builder.appendQueryParameter(QUERY_PARAM_QUERY, ParseUtils.parseString(searchQuery.text)) builder.appendQueryParameter(QUERY_PARAM_QUERY, ParseUtils.parseString(searchQuery.text))
if (accountId != null) { if (accountId != null) {
@ -125,19 +126,19 @@ class QuickSearchBarActivity : BaseActivity(), OnClickListener, LoaderCallbacks<
val item = adapter.getSuggestionItem(position)!! val item = adapter.getSuggestionItem(position)!!
when (adapter.getItemViewType(position)) { when (adapter.getItemViewType(position)) {
SuggestionsAdapter.VIEW_TYPE_USER_SUGGESTION_ITEM -> { SuggestionsAdapter.VIEW_TYPE_USER_SUGGESTION_ITEM -> {
IntentUtils.openUserProfile(this, selectedAccountKey, IntentUtils.openUserProfile(this, selectedAccountDetails?.key,
UserKey.valueOf(item.extra_id!!), item.summary, null, UserKey.valueOf(item.extra_id!!), item.summary, null,
preferences.getBoolean(KEY_NEW_DOCUMENT_API), preferences[newDocumentApiKey],
Referral.DIRECT) Referral.DIRECT)
finish() finish()
} }
SuggestionsAdapter.VIEW_TYPE_USER_SCREEN_NAME -> { SuggestionsAdapter.VIEW_TYPE_USER_SCREEN_NAME -> {
IntentUtils.openUserProfile(this, selectedAccountKey, null, item.title, null, IntentUtils.openUserProfile(this, selectedAccountDetails?.key, null, item.title,
preferences.getBoolean(KEY_NEW_DOCUMENT_API), Referral.DIRECT) null, preferences[newDocumentApiKey], Referral.DIRECT)
finish() finish()
} }
SuggestionsAdapter.VIEW_TYPE_SAVED_SEARCH, SuggestionsAdapter.VIEW_TYPE_SEARCH_HISTORY -> { SuggestionsAdapter.VIEW_TYPE_SAVED_SEARCH, SuggestionsAdapter.VIEW_TYPE_SEARCH_HISTORY -> {
IntentUtils.openSearch(this, selectedAccountKey, item.title) IntentUtils.openSearch(this, selectedAccountDetails?.key, item.title)
finish() finish()
} }
} }
@ -168,7 +169,7 @@ class QuickSearchBarActivity : BaseActivity(), OnClickListener, LoaderCallbacks<
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_quick_search_bar) setContentView(R.layout.activity_quick_search_bar)
val am = AccountManager.get(this) val am = AccountManager.get(this)
val accounts = AccountUtils.getAllAccountDetails(am, AccountUtils.getAccounts(am)).toList() val accounts = AccountUtils.getAllAccountDetails(am, AccountUtils.getAccounts(am), true).toList()
val accountsSpinnerAdapter = AccountsSpinnerAdapter(this, R.layout.spinner_item_account_icon) val accountsSpinnerAdapter = AccountsSpinnerAdapter(this, R.layout.spinner_item_account_icon)
accountsSpinnerAdapter.setDropDownViewResource(R.layout.list_item_simple_user) accountsSpinnerAdapter.setDropDownViewResource(R.layout.list_item_simple_user)
accountsSpinnerAdapter.addAll(accounts) accountsSpinnerAdapter.addAll(accounts)
@ -231,14 +232,14 @@ class QuickSearchBarActivity : BaseActivity(), OnClickListener, LoaderCallbacks<
if (isFinishing) return if (isFinishing) return
val query = ParseUtils.parseString(searchQuery.text) val query = ParseUtils.parseString(searchQuery.text)
if (TextUtils.isEmpty(query)) return if (TextUtils.isEmpty(query)) return
IntentUtils.openSearch(this, selectedAccountKey, query) val details = selectedAccountDetails ?: return
IntentUtils.openSearch(this, details.key, query)
finish() finish()
} }
private val selectedAccountKey: UserKey? private val selectedAccountDetails: AccountDetails?
get() { get() {
val account = accountSpinner.selectedItem as AccountDetails return accountSpinner.selectedItem as? AccountDetails
return account.key
} }
private fun updateWindowAttributes() { private fun updateWindowAttributes() {

View File

@ -52,6 +52,7 @@ import com.bluelinelabs.logansquare.LoganSquare
import com.rengwuxian.materialedittext.MaterialEditText import com.rengwuxian.materialedittext.MaterialEditText
import kotlinx.android.synthetic.main.activity_sign_in.* import kotlinx.android.synthetic.main.activity_sign_in.*
import org.mariotaku.ktextension.Bundle import org.mariotaku.ktextension.Bundle
import org.mariotaku.ktextension.convert
import org.mariotaku.ktextension.set import org.mariotaku.ktextension.set
import org.mariotaku.microblog.library.MicroBlog import org.mariotaku.microblog.library.MicroBlog
import org.mariotaku.microblog.library.MicroBlogException import org.mariotaku.microblog.library.MicroBlogException
@ -71,6 +72,8 @@ import org.mariotaku.twidere.annotation.AccountType
import org.mariotaku.twidere.constant.IntentConstants.EXTRA_API_CONFIG import org.mariotaku.twidere.constant.IntentConstants.EXTRA_API_CONFIG
import org.mariotaku.twidere.constant.SharedPreferenceConstants.KEY_CREDENTIALS_TYPE import org.mariotaku.twidere.constant.SharedPreferenceConstants.KEY_CREDENTIALS_TYPE
import org.mariotaku.twidere.constant.defaultAPIConfigKey import org.mariotaku.twidere.constant.defaultAPIConfigKey
import org.mariotaku.twidere.extension.getColor
import org.mariotaku.twidere.extension.model.official
import org.mariotaku.twidere.extension.newMicroBlogInstance import org.mariotaku.twidere.extension.newMicroBlogInstance
import org.mariotaku.twidere.fragment.BaseDialogFragment import org.mariotaku.twidere.fragment.BaseDialogFragment
import org.mariotaku.twidere.fragment.ProgressDialogFragment import org.mariotaku.twidere.fragment.ProgressDialogFragment
@ -78,12 +81,14 @@ import org.mariotaku.twidere.model.CustomAPIConfig
import org.mariotaku.twidere.model.ParcelableUser import org.mariotaku.twidere.model.ParcelableUser
import org.mariotaku.twidere.model.SingleResponse import org.mariotaku.twidere.model.SingleResponse
import org.mariotaku.twidere.model.UserKey import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.model.account.AccountExtras
import org.mariotaku.twidere.model.account.StatusNetAccountExtras import org.mariotaku.twidere.model.account.StatusNetAccountExtras
import org.mariotaku.twidere.model.account.TwitterAccountExtras import org.mariotaku.twidere.model.account.TwitterAccountExtras
import org.mariotaku.twidere.model.account.cred.BasicCredentials import org.mariotaku.twidere.model.account.cred.BasicCredentials
import org.mariotaku.twidere.model.account.cred.Credentials import org.mariotaku.twidere.model.account.cred.Credentials
import org.mariotaku.twidere.model.account.cred.EmptyCredentials import org.mariotaku.twidere.model.account.cred.EmptyCredentials
import org.mariotaku.twidere.model.account.cred.OAuthCredentials import org.mariotaku.twidere.model.account.cred.OAuthCredentials
import org.mariotaku.twidere.model.analyzer.SignIn
import org.mariotaku.twidere.model.util.AccountUtils import org.mariotaku.twidere.model.util.AccountUtils
import org.mariotaku.twidere.model.util.ParcelableUserUtils import org.mariotaku.twidere.model.util.ParcelableUserUtils
import org.mariotaku.twidere.model.util.UserKeyUtils import org.mariotaku.twidere.model.util.UserKeyUtils
@ -383,7 +388,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher {
result.updateAccount(am) result.updateAccount(am)
Toast.makeText(this, R.string.error_already_logged_in, Toast.LENGTH_SHORT).show() Toast.makeText(this, R.string.error_already_logged_in, Toast.LENGTH_SHORT).show()
} else { } else {
result.addAccount(am) val account = result.addAccount(am)
if (accountAuthenticatorResponse != null) { if (accountAuthenticatorResponse != null) {
accountAuthenticatorResult = Bundle { accountAuthenticatorResult = Bundle {
this[AccountManager.KEY_BOOLEAN_RESULT] = true this[AccountManager.KEY_BOOLEAN_RESULT] = true
@ -394,6 +399,8 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher {
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
startActivity(intent) startActivity(intent)
} }
Analyzer.log(SignIn(true, type = result.accountType.first, account = account.name,
officialKey = result.accountType.second?.official ?: false))
finish() finish()
} }
} }
@ -402,21 +409,29 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher {
if (BuildConfig.DEBUG) { if (BuildConfig.DEBUG) {
Log.w(LOGTAG, exception) Log.w(LOGTAG, exception)
} }
var errorReason: String? = null
if (exception is AuthenticityTokenException) { if (exception is AuthenticityTokenException) {
Toast.makeText(this, R.string.wrong_api_key, Toast.LENGTH_SHORT).show() Toast.makeText(this, R.string.wrong_api_key, Toast.LENGTH_SHORT).show()
errorReason = "wrong_api_key"
} else if (exception is WrongUserPassException) { } else if (exception is WrongUserPassException) {
Toast.makeText(this, R.string.wrong_username_password, Toast.LENGTH_SHORT).show() Toast.makeText(this, R.string.wrong_username_password, Toast.LENGTH_SHORT).show()
errorReason = "wrong_username_password"
} else if (exception is SignInTask.WrongBasicCredentialException) { } else if (exception is SignInTask.WrongBasicCredentialException) {
Toast.makeText(this, R.string.wrong_username_password, Toast.LENGTH_SHORT).show() Toast.makeText(this, R.string.wrong_username_password, Toast.LENGTH_SHORT).show()
errorReason = "wrong_username_password"
} else if (exception is SignInTask.WrongAPIURLFormatException) { } else if (exception is SignInTask.WrongAPIURLFormatException) {
Toast.makeText(this, R.string.wrong_api_key, Toast.LENGTH_SHORT).show() Toast.makeText(this, R.string.wrong_api_key, Toast.LENGTH_SHORT).show()
errorReason = "wrong_api_key"
} else if (exception is LoginVerificationException) { } else if (exception is LoginVerificationException) {
Toast.makeText(this, R.string.login_verification_failed, Toast.LENGTH_SHORT).show() Toast.makeText(this, R.string.login_verification_failed, Toast.LENGTH_SHORT).show()
errorReason = "login_verification_failed"
} else if (exception is AuthenticationException) { } else if (exception is AuthenticationException) {
Utils.showErrorMessage(this, getString(R.string.action_signing_in), exception.cause, true) Utils.showErrorMessage(this, getString(R.string.action_signing_in), exception.cause, true)
} else { } else {
Utils.showErrorMessage(this, getString(R.string.action_signing_in), exception, true) Utils.showErrorMessage(this, getString(R.string.action_signing_in), exception, true)
} }
Analyzer.log(SignIn(false, type = "unknown", authType = apiConfig.credentialsType,
errorReason = errorReason))
} }
internal fun dismissDialogFragment(tag: String) { internal fun dismissDialogFragment(tag: String) {
@ -543,9 +558,10 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher {
val userId = apiUser.id!! val userId = apiUser.id!!
val accountKey = UserKey(userId, UserKeyUtils.getUserHost(apiUser)) val accountKey = UserKey(userId, UserKeyUtils.getUserHost(apiUser))
val user = ParcelableUserUtils.fromUser(apiUser, accountKey) val user = ParcelableUserUtils.fromUser(apiUser, accountKey)
val account = AccountUtils.getAccountDetails(AccountManager.get(context), accountKey) val am = AccountManager.get(context)
val account = AccountUtils.findByAccountKey(am, accountKey)
if (account != null) { if (account != null) {
color = account.color color = account.getColor(am)
} }
val credentials = OAuthCredentials() val credentials = OAuthCredentials()
credentials.api_url_format = apiUrlFormat credentials.api_url_format = apiUrlFormat
@ -717,7 +733,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher {
val credentials: Credentials, val credentials: Credentials,
val user: ParcelableUser, val user: ParcelableUser,
val color: Int = 0, val color: Int = 0,
val accountType: Pair<String, String?> val accountType: Pair<String, AccountExtras?>
) { ) {
private fun writeAccountInfo(action: (k: String, v: String?) -> Unit) { private fun writeAccountInfo(action: (k: String, v: String?) -> Unit) {
@ -729,7 +745,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher {
action(ACCOUNT_USER_DATA_COLOR, toHexColor(color)) action(ACCOUNT_USER_DATA_COLOR, toHexColor(color))
action(ACCOUNT_USER_DATA_USER, LoganSquare.serialize(user)) action(ACCOUNT_USER_DATA_USER, LoganSquare.serialize(user))
action(ACCOUNT_USER_DATA_EXTRAS, accountType.second) action(ACCOUNT_USER_DATA_EXTRAS, accountType.second?.convert { LoganSquare.serialize(it) })
} }
private fun writeAuthToken(am: AccountManager, account: Account) { private fun writeAuthToken(am: AccountManager, account: Account) {
@ -856,9 +872,10 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher {
val accountType = SignInActivity.detectAccountType(twitter, apiUser) val accountType = SignInActivity.detectAccountType(twitter, apiUser)
val accountKey = UserKey(userId, UserKeyUtils.getUserHost(apiUser)) val accountKey = UserKey(userId, UserKeyUtils.getUserHost(apiUser))
val user = ParcelableUserUtils.fromUser(apiUser, accountKey) val user = ParcelableUserUtils.fromUser(apiUser, accountKey)
val account = AccountUtils.getAccountDetails(AccountManager.get(activity), accountKey) val am = AccountManager.get(activity)
val account = AccountUtils.findByAccountKey(am, accountKey)
if (account != null) { if (account != null) {
color = account.color color = account.getColor(am)
} }
val credentials = BasicCredentials() val credentials = BasicCredentials()
credentials.api_url_format = apiUrlFormat credentials.api_url_format = apiUrlFormat
@ -885,9 +902,10 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher {
val accountType = SignInActivity.detectAccountType(twitter, apiUser) val accountType = SignInActivity.detectAccountType(twitter, apiUser)
val accountKey = UserKey(userId, UserKeyUtils.getUserHost(apiUser)) val accountKey = UserKey(userId, UserKeyUtils.getUserHost(apiUser))
val user = ParcelableUserUtils.fromUser(apiUser, accountKey) val user = ParcelableUserUtils.fromUser(apiUser, accountKey)
val account = AccountUtils.getAccountDetails(AccountManager.get(activity), accountKey) val am = AccountManager.get(activity)
val account = AccountUtils.findByAccountKey(am, accountKey)
if (account != null) { if (account != null) {
color = account.color color = account.getColor(am)
} }
val credentials = EmptyCredentials() val credentials = EmptyCredentials()
credentials.api_url_format = apiUrlFormat credentials.api_url_format = apiUrlFormat
@ -912,9 +930,10 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher {
val accountType = SignInActivity.detectAccountType(twitter, apiUser) val accountType = SignInActivity.detectAccountType(twitter, apiUser)
val accountKey = UserKey(userId, UserKeyUtils.getUserHost(apiUser)) val accountKey = UserKey(userId, UserKeyUtils.getUserHost(apiUser))
val user = ParcelableUserUtils.fromUser(apiUser, accountKey) val user = ParcelableUserUtils.fromUser(apiUser, accountKey)
val account = AccountUtils.getAccountDetails(AccountManager.get(activity), accountKey) val am = AccountManager.get(activity)
val account = AccountUtils.findByAccountKey(am, accountKey)
if (account != null) { if (account != null) {
color = account.color color = account.getColor(am)
} }
val credentials = OAuthCredentials() val credentials = OAuthCredentials()
credentials.api_url_format = apiUrlFormat credentials.api_url_format = apiUrlFormat
@ -992,17 +1011,16 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher {
private val EXTRA_API_LAST_CHANGE = "api_last_change" private val EXTRA_API_LAST_CHANGE = "api_last_change"
private val DEFAULT_TWITTER_API_URL_FORMAT = "https://[DOMAIN.]twitter.com/" private val DEFAULT_TWITTER_API_URL_FORMAT = "https://[DOMAIN.]twitter.com/"
internal fun detectAccountType(twitter: MicroBlog, user: User): Pair<String, String?> { internal fun detectAccountType(twitter: MicroBlog, user: User): Pair<String, AccountExtras?> {
try { try {
// Get StatusNet specific resource // Get StatusNet specific resource
val config = twitter.statusNetConfig val config = twitter.statusNetConfig
val extra = StatusNetAccountExtras() val extras = StatusNetAccountExtras()
val site = config.site val site = config.site
if (site != null) { if (site != null) {
extra.textLimit = site.textLimit extras.textLimit = site.textLimit
} }
return Pair(AccountType.STATUSNET, JsonSerializer.serialize(extra, return Pair(AccountType.STATUSNET, extras)
StatusNetAccountExtras::class.java))
} catch (e: MicroBlogException) { } catch (e: MicroBlogException) {
// Ignore // Ignore
} }
@ -1012,10 +1030,9 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher {
val paging = Paging() val paging = Paging()
paging.count(1) paging.count(1)
twitter.getActivitiesAboutMe(paging) twitter.getActivitiesAboutMe(paging)
val extra = TwitterAccountExtras() val extras = TwitterAccountExtras()
extra.setIsOfficialCredentials(true) extras.setIsOfficialCredentials(true)
return Pair(AccountType.TWITTER, JsonSerializer.serialize(extra, return Pair(AccountType.TWITTER, extras)
TwitterAccountExtras::class.java))
} catch (e: MicroBlogException) { } catch (e: MicroBlogException) {
// Ignore // Ignore
} }

View File

@ -13,7 +13,7 @@ import org.mariotaku.twidere.R
import org.mariotaku.twidere.TwidereConstants.* import org.mariotaku.twidere.TwidereConstants.*
import org.mariotaku.twidere.app.TwidereApplication import org.mariotaku.twidere.app.TwidereApplication
import org.mariotaku.twidere.model.UserKey import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.util.BugReporter import org.mariotaku.twidere.util.Analyzer
import org.mariotaku.twidere.util.IntentUtils import org.mariotaku.twidere.util.IntentUtils
import org.mariotaku.twidere.util.Utils import org.mariotaku.twidere.util.Utils
@ -46,7 +46,7 @@ class WebLinkHandlerActivity : Activity(), Constants {
startActivity(handled.first) startActivity(handled.first)
} else { } else {
if (!handled.second) { if (!handled.second) {
BugReporter.logException(TwitterLinkException("Unable to handle twitter uri " + uri)) Analyzer.logException(TwitterLinkException("Unable to handle twitter uri " + uri))
} }
val fallbackIntent = Intent(Intent.ACTION_VIEW, uri) val fallbackIntent = Intent(Intent.ACTION_VIEW, uri)
fallbackIntent.addCategory(Intent.CATEGORY_BROWSABLE) fallbackIntent.addCategory(Intent.CATEGORY_BROWSABLE)

View File

@ -52,6 +52,7 @@ import org.mariotaku.mediaviewer.library.MediaDownloader
import org.mariotaku.restfu.http.RestHttpClient import org.mariotaku.restfu.http.RestHttpClient
import org.mariotaku.twidere.BuildConfig import org.mariotaku.twidere.BuildConfig
import org.mariotaku.twidere.Constants import org.mariotaku.twidere.Constants
import org.mariotaku.twidere.Constants.KEY_USAGE_STATISTICS
import org.mariotaku.twidere.R import org.mariotaku.twidere.R
import org.mariotaku.twidere.TwidereConstants.* import org.mariotaku.twidere.TwidereConstants.*
import org.mariotaku.twidere.activity.AssistLauncherActivity import org.mariotaku.twidere.activity.AssistLauncherActivity
@ -72,6 +73,7 @@ import org.mariotaku.twidere.view.ProfileImageView
import org.mariotaku.twidere.view.TabPagerIndicator import org.mariotaku.twidere.view.TabPagerIndicator
import org.mariotaku.twidere.view.ThemedMultiValueSwitch import org.mariotaku.twidere.view.ThemedMultiValueSwitch
import org.mariotaku.twidere.view.TimelineContentTextView import org.mariotaku.twidere.view.TimelineContentTextView
import java.util.*
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import javax.inject.Inject import javax.inject.Inject
@ -251,18 +253,18 @@ class TwidereApplication : Application(), Constants, OnSharedPreferenceChangeLis
private fun initBugReport() { private fun initBugReport() {
if (!sharedPreferences[bugReportsKey]) return if (!sharedPreferences[bugReportsKey]) return
BugReporter.setImplementation(TwidereBugReporter()) Analyzer.implementation = ServiceLoader.load(Analyzer::class.java).firstOrNull()
BugReporter.init(this) Analyzer.init(this)
} }
private fun migrateUsageStatisticsPreferences() { private fun migrateUsageStatisticsPreferences() {
val preferences = sharedPreferences val preferences = sharedPreferences
val hasUsageStatistics = preferences.contains(Constants.KEY_USAGE_STATISTICS) val hasUsageStatistics = preferences.contains(KEY_USAGE_STATISTICS)
if (hasUsageStatistics) return if (hasUsageStatistics) return
if (preferences.contains(KEY_UCD_DATA_PROFILING) || preferences.contains(KEY_SPICE_DATA_PROFILING)) { if (preferences.contains(KEY_UCD_DATA_PROFILING) || preferences.contains(KEY_SPICE_DATA_PROFILING)) {
val prevUsageEnabled = preferences.getBoolean(KEY_UCD_DATA_PROFILING, false) || preferences.getBoolean(KEY_SPICE_DATA_PROFILING, false) val prevUsageEnabled = preferences.getBoolean(KEY_UCD_DATA_PROFILING, false) || preferences.getBoolean(KEY_SPICE_DATA_PROFILING, false)
val editor = preferences.edit() val editor = preferences.edit()
editor.putBoolean(Constants.KEY_USAGE_STATISTICS, prevUsageEnabled) editor.putBoolean(KEY_USAGE_STATISTICS, prevUsageEnabled)
editor.remove(KEY_UCD_DATA_PROFILING) editor.remove(KEY_UCD_DATA_PROFILING)
editor.remove(KEY_SPICE_DATA_PROFILING) editor.remove(KEY_SPICE_DATA_PROFILING)
editor.apply() editor.apply()

View File

@ -21,9 +21,10 @@ import org.mariotaku.twidere.util.toHexColor
fun Account.getCredentials(am: AccountManager): Credentials { fun Account.getCredentials(am: AccountManager): Credentials {
val credentialsType: String = getCredentialsType(am) val authToken = am.peekAuthToken(this, ACCOUNT_AUTH_TOKEN_TYPE) ?: run {
val creds: Credentials = parseCredentials(am.peekAuthToken(this, ACCOUNT_AUTH_TOKEN_TYPE), credentialsType) throw IllegalStateException("AuthToken is null for ${this}")
return creds }
return parseCredentials(authToken, getCredentialsType(am))
} }
@Credentials.Type @Credentials.Type
@ -32,7 +33,10 @@ fun Account.getCredentialsType(am: AccountManager): String {
} }
fun Account.getAccountKey(am: AccountManager): UserKey { fun Account.getAccountKey(am: AccountManager): UserKey {
return UserKey.valueOf(am.getUserData(this, ACCOUNT_USER_DATA_KEY)) val accountKeyString = am.getUserData(this, ACCOUNT_USER_DATA_KEY) ?: run {
throw IllegalStateException("UserKey is null for ${this}")
}
return UserKey.valueOf(accountKeyString)
} }
fun Account.setAccountKey(am: AccountManager, accountKey: UserKey) { fun Account.setAccountKey(am: AccountManager, accountKey: UserKey) {

View File

@ -4,6 +4,7 @@ import android.content.Context
import org.mariotaku.twidere.annotation.AccountType import org.mariotaku.twidere.annotation.AccountType
import org.mariotaku.twidere.extension.newMicroBlogInstance import org.mariotaku.twidere.extension.newMicroBlogInstance
import org.mariotaku.twidere.model.AccountDetails import org.mariotaku.twidere.model.AccountDetails
import org.mariotaku.twidere.model.account.AccountExtras
import org.mariotaku.twidere.model.account.TwitterAccountExtras import org.mariotaku.twidere.model.account.TwitterAccountExtras
import org.mariotaku.twidere.model.account.cred.Credentials import org.mariotaku.twidere.model.account.cred.Credentials
import org.mariotaku.twidere.model.account.cred.OAuthCredentials import org.mariotaku.twidere.model.account.cred.OAuthCredentials
@ -23,6 +24,14 @@ fun AccountDetails.isOfficial(context: Context): Boolean {
return false return false
} }
val AccountExtras.official: Boolean
get() {
if (this is TwitterAccountExtras) {
return isOfficialCredentials
}
return false
}
@JvmOverloads @JvmOverloads
fun <T> AccountDetails.newMicroBlogInstance(context: Context, includeEntities: Boolean = true, includeRetweets: Boolean = true, fun <T> AccountDetails.newMicroBlogInstance(context: Context, includeEntities: Boolean = true, includeRetweets: Boolean = true,

View File

@ -727,7 +727,7 @@ class AccountsDashboardFragment : BaseSupportFragment(), LoaderCallbacks<Account
} }
override fun loadInBackground(): AccountsInfo { override fun loadInBackground(): AccountsInfo {
val accounts = AccountUtils.getAllAccountDetails(AccountManager.get(context)) val accounts = AccountUtils.getAllAccountDetails(AccountManager.get(context), true)
val draftsCount = DataStoreUtils.queryCount(context, Drafts.CONTENT_URI_UNSENT, null, null) val draftsCount = DataStoreUtils.queryCount(context, Drafts.CONTENT_URI_UNSENT, null, null)
return AccountsInfo(accounts, draftsCount) return AccountsInfo(accounts, draftsCount)
} }

View File

@ -287,7 +287,7 @@ class CustomTabsFragment : BaseSupportFragment(), LoaderCallbacks<Cursor?>, Mult
accountsAdapter.add(AccountDetails.dummy()) accountsAdapter.add(AccountDetails.dummy())
} }
val officialKeyOnly = arguments.getBoolean(EXTRA_OFFICIAL_KEY_ONLY, false) val officialKeyOnly = arguments.getBoolean(EXTRA_OFFICIAL_KEY_ONLY, false)
accountsAdapter.addAll(AccountUtils.getAllAccountDetails(AccountManager.get(context)).filter { accountsAdapter.addAll(AccountUtils.getAllAccountDetails(AccountManager.get(context), true).filter {
if (officialKeyOnly && !it.isOfficial(context)) { if (officialKeyOnly && !it.isOfficial(context)) {
return@filter false return@filter false
} }

View File

@ -171,7 +171,7 @@ class MessagesConversationFragment : BaseSupportFragment(), LoaderCallbacks<Curs
ActionBar.DISPLAY_SHOW_TITLE or ActionBar.DISPLAY_SHOW_CUSTOM) ActionBar.DISPLAY_SHOW_TITLE or ActionBar.DISPLAY_SHOW_CUSTOM)
actionBar.setCustomView(R.layout.layout_actionbar_message_user_picker) actionBar.setCustomView(R.layout.layout_actionbar_message_user_picker)
val am = AccountManager.get(context) val am = AccountManager.get(context)
val accounts = AccountUtils.getAllAccountDetails(am, AccountUtils.getAccounts(am)).asList() val accounts = AccountUtils.getAllAccountDetails(am, AccountUtils.getAccounts(am), true).asList()
val accountsSpinnerAdapter = AccountsSpinnerAdapter( val accountsSpinnerAdapter = AccountsSpinnerAdapter(
actionBar.themedContext, R.layout.spinner_item_account_icon) actionBar.themedContext, R.layout.spinner_item_account_icon)
accountsSpinnerAdapter.setDropDownViewResource(R.layout.list_item_simple_user) accountsSpinnerAdapter.setDropDownViewResource(R.layout.list_item_simple_user)
@ -244,7 +244,7 @@ class MessagesConversationFragment : BaseSupportFragment(), LoaderCallbacks<Curs
if (accountPos >= 0) { if (accountPos >= 0) {
account = accountsSpinnerAdapter.getItem(accountPos) account = accountsSpinnerAdapter.getItem(accountPos)
} else { } else {
account = AccountUtils.getAccountDetails(AccountManager.get(activity), accountKey) account = AccountUtils.getAccountDetails(AccountManager.get(activity), accountKey, true)
} }
if (userId != null) { if (userId != null) {
recipient = Utils.getUserForConversation(activity, accountKey, userId) recipient = Utils.getUserForConversation(activity, accountKey, userId)

View File

@ -47,7 +47,7 @@ import org.mariotaku.twidere.model.ParcelableStatus
import org.mariotaku.twidere.model.ParcelableStatusUpdate import org.mariotaku.twidere.model.ParcelableStatusUpdate
import org.mariotaku.twidere.model.util.AccountUtils import org.mariotaku.twidere.model.util.AccountUtils
import org.mariotaku.twidere.service.BackgroundOperationService import org.mariotaku.twidere.service.BackgroundOperationService
import org.mariotaku.twidere.util.BugReporter import org.mariotaku.twidere.util.Analyzer
import org.mariotaku.twidere.util.EditTextEnterHandler import org.mariotaku.twidere.util.EditTextEnterHandler
import org.mariotaku.twidere.util.LinkCreator import org.mariotaku.twidere.util.LinkCreator
import org.mariotaku.twidere.util.TwidereValidator import org.mariotaku.twidere.util.TwidereValidator
@ -63,7 +63,7 @@ class RetweetQuoteDialogFragment : BaseDialogFragment() {
val builder = AlertDialog.Builder(context) val builder = AlertDialog.Builder(context)
val context = builder.context val context = builder.context
val status = status!! val status = status!!
val details = AccountUtils.getAccountDetails(AccountManager.get(context), status.account_key)!! val details = AccountUtils.getAccountDetails(AccountManager.get(context), status.account_key, true)!!
builder.setView(R.layout.dialog_status_quote_retweet) builder.setView(R.layout.dialog_status_quote_retweet)
builder.setTitle(R.string.retweet_quote_confirm_title) builder.setTitle(R.string.retweet_quote_confirm_title)
@ -159,7 +159,7 @@ class RetweetQuoteDialogFragment : BaseDialogFragment() {
} else if (useQuote(!status.user_is_protected, details)) { } else if (useQuote(!status.user_is_protected, details)) {
dismissDialog = retweetOrQuote(details, status, SHOW_PROTECTED_CONFIRM) dismissDialog = retweetOrQuote(details, status, SHOW_PROTECTED_CONFIRM)
} else { } else {
BugReporter.logException(IllegalStateException(status.toString())) Analyzer.logException(IllegalStateException(status.toString()))
} }
if (dismissDialog) { if (dismissDialog) {
dismiss() dismiss()

View File

@ -19,6 +19,7 @@
package org.mariotaku.twidere.fragment package org.mariotaku.twidere.fragment
import android.accounts.AccountManager
import android.content.ContentValues import android.content.ContentValues
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
@ -28,6 +29,7 @@ import android.text.TextUtils
import android.view.Menu import android.view.Menu
import android.view.MenuInflater import android.view.MenuInflater
import android.view.MenuItem import android.view.MenuItem
import org.mariotaku.ktextension.convert
import org.mariotaku.twidere.Constants.* import org.mariotaku.twidere.Constants.*
import org.mariotaku.twidere.R import org.mariotaku.twidere.R
import org.mariotaku.twidere.activity.ComposeActivity import org.mariotaku.twidere.activity.ComposeActivity
@ -38,9 +40,12 @@ import org.mariotaku.twidere.fragment.iface.IBaseFragment.SystemWindowsInsetsCal
import org.mariotaku.twidere.fragment.iface.RefreshScrollTopInterface import org.mariotaku.twidere.fragment.iface.RefreshScrollTopInterface
import org.mariotaku.twidere.fragment.iface.SupportFragmentCallback import org.mariotaku.twidere.fragment.iface.SupportFragmentCallback
import org.mariotaku.twidere.model.UserKey import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.model.analyzer.Search
import org.mariotaku.twidere.model.tab.DrawableHolder import org.mariotaku.twidere.model.tab.DrawableHolder
import org.mariotaku.twidere.model.util.AccountUtils
import org.mariotaku.twidere.provider.RecentSearchProvider import org.mariotaku.twidere.provider.RecentSearchProvider
import org.mariotaku.twidere.provider.TwidereDataStore.SearchHistory import org.mariotaku.twidere.provider.TwidereDataStore.SearchHistory
import org.mariotaku.twidere.util.Analyzer
class SearchFragment : AbsToolbarTabPagesFragment(), RefreshScrollTopInterface, SupportFragmentCallback, SystemWindowsInsetsCallback, ControlBarOffsetListener, OnPageChangeListener, LinkHandlerActivity.HideUiOnScroll { class SearchFragment : AbsToolbarTabPagesFragment(), RefreshScrollTopInterface, SupportFragmentCallback, SystemWindowsInsetsCallback, ControlBarOffsetListener, OnPageChangeListener, LinkHandlerActivity.HideUiOnScroll {
@ -55,16 +60,20 @@ class SearchFragment : AbsToolbarTabPagesFragment(), RefreshScrollTopInterface,
val values = ContentValues() val values = ContentValues()
values.put(SearchHistory.QUERY, query) values.put(SearchHistory.QUERY, query)
context.contentResolver.insert(SearchHistory.CONTENT_URI, values) context.contentResolver.insert(SearchHistory.CONTENT_URI, values)
Analyzer.log(Search(query, accountKey.convert {
AccountUtils.findByAccountKey(AccountManager.get(context), it)
}?.name))
} }
} }
override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater!!.inflate(R.menu.menu_search, menu) inflater.inflate(R.menu.menu_search, menu)
} }
override fun onPrepareOptionsMenu(menu: Menu?) { override fun onPrepareOptionsMenu(menu: Menu) {
if (isDetached || activity == null) return if (isDetached || activity == null) return
val item = menu!!.findItem(R.id.compose) val item = menu.findItem(R.id.compose)
item.title = getString(R.string.tweet_hashtag, query) item.title = getString(R.string.tweet_hashtag, query)
} }

View File

@ -2058,7 +2058,7 @@ class StatusFragment : BaseSupportFragment(), LoaderCallbacks<SingleResponse<Par
override fun loadInBackground(): StatusActivity? { override fun loadInBackground(): StatusActivity? {
val context = context val context = context
val details = AccountUtils.getAccountDetails(AccountManager.get(context), mAccountKey) ?: return null val details = AccountUtils.getAccountDetails(AccountManager.get(context), mAccountKey, true) ?: return null
if (AccountType.TWITTER != details.type) { if (AccountType.TWITTER != details.type) {
return null return null
} }

View File

@ -884,7 +884,7 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
builder.appendQueryParameter(QUERY_PARAM_ACCOUNT_KEY, user.account_key.toString()) builder.appendQueryParameter(QUERY_PARAM_ACCOUNT_KEY, user.account_key.toString())
builder.appendQueryParameter(QUERY_PARAM_USER_KEY, user.key.toString()) builder.appendQueryParameter(QUERY_PARAM_USER_KEY, user.key.toString())
val intent = Intent(Intent.ACTION_VIEW, builder.build()) val intent = Intent(Intent.ACTION_VIEW, builder.build())
intent.putExtra(EXTRA_ACCOUNT, AccountUtils.getAccountDetails(AccountManager.get(activity), user.account_key)) intent.putExtra(EXTRA_ACCOUNT, AccountUtils.getAccountDetails(AccountManager.get(activity), user.account_key, true))
intent.putExtra(EXTRA_USER, user) intent.putExtra(EXTRA_USER, user)
startActivity(intent) startActivity(intent)
} }
@ -1529,7 +1529,7 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
null, isFiltering)) null, isFiltering))
} }
val details = AccountUtils.getAccountDetails(AccountManager.get(context), val details = AccountUtils.getAccountDetails(AccountManager.get(context),
accountKey) ?: return SingleResponse.getInstance<ParcelableRelationship>(MicroBlogException("No Account")) accountKey, true) ?: return SingleResponse.getInstance<ParcelableRelationship>(MicroBlogException("No Account"))
if (details.type == AccountType.TWITTER) { if (details.type == AccountType.TWITTER) {
if (!UserKeyUtils.isSameHost(accountKey, user.key)) { if (!UserKeyUtils.isSameHost(accountKey, user.key)) {
return SingleResponse.getInstance(ParcelableRelationshipUtils.create(user, isFiltering)) return SingleResponse.getInstance(ParcelableRelationshipUtils.create(user, isFiltering))

View File

@ -348,7 +348,7 @@ class UserProfileEditorFragment : BaseSupportFragment(), OnSizeChangedListener,
) : AbstractTask<Context, SingleResponse<ParcelableUser>, UserProfileEditorFragment>() { ) : AbstractTask<Context, SingleResponse<ParcelableUser>, UserProfileEditorFragment>() {
override fun doLongOperation(context: Context): SingleResponse<ParcelableUser> { override fun doLongOperation(context: Context): SingleResponse<ParcelableUser> {
val details = AccountUtils.getAccountDetails(AccountManager.get(context), accountKey) ?: return SingleResponse.getInstance() val details = AccountUtils.getAccountDetails(AccountManager.get(context), accountKey, true) ?: return SingleResponse.getInstance()
val microBlog = details.newMicroBlogInstance(context = context, cls = MicroBlog::class.java) val microBlog = details.newMicroBlogInstance(context = context, cls = MicroBlog::class.java)
try { try {
var user: User? = null var user: User? = null

View File

@ -140,7 +140,7 @@ class CardPollFragment : BaseSupportFragment(), LoaderManager.LoaderCallbacks<Pa
public override fun doLongOperation(cardDataMap: CardDataMap): ParcelableCardEntity? { public override fun doLongOperation(cardDataMap: CardDataMap): ParcelableCardEntity? {
val details = AccountUtils.getAccountDetails(AccountManager.get(context), val details = AccountUtils.getAccountDetails(AccountManager.get(context),
card.account_key) ?: return null card.account_key, true) ?: return null
val caps = details.newMicroBlogInstance(context, cls = TwitterCaps::class.java) val caps = details.newMicroBlogInstance(context, cls = TwitterCaps::class.java)
try { try {
val cardEntity = caps.sendPassThrough(cardDataMap).card val cardEntity = caps.sendPassThrough(cardDataMap).card
@ -233,7 +233,7 @@ class CardPollFragment : BaseSupportFragment(), LoaderManager.LoaderCallbacks<Pa
override fun onCreateLoader(id: Int, args: Bundle?): Loader<ParcelableCardEntity?> { override fun onCreateLoader(id: Int, args: Bundle?): Loader<ParcelableCardEntity?> {
val card = card val card = card
val details = AccountUtils.getAccountDetails(AccountManager.get(context), card.account_key)!! val details = AccountUtils.getAccountDetails(AccountManager.get(context), card.account_key, true)!!
return ParcelableCardEntityLoader(context, details, card.url, card.name) return ParcelableCardEntityLoader(context, details, card.url, card.name)
} }

View File

@ -26,7 +26,7 @@ class AccountDetailsLoader(
} }
override fun loadInBackground(): List<AccountDetails> { override fun loadInBackground(): List<AccountDetails> {
return AccountUtils.getAllAccountDetails(am).filter { return AccountUtils.getAllAccountDetails(am, true).filter {
filter?.invoke(it) ?: true filter?.invoke(it) ?: true
}.sortedBy(AccountDetails::position) }.sortedBy(AccountDetails::position)
} }

View File

@ -91,7 +91,7 @@ abstract class MicroBlogAPIStatusesLoader(
override fun loadInBackground(): ListResponse<ParcelableStatus> { override fun loadInBackground(): ListResponse<ParcelableStatus> {
val context = context val context = context
val accountKey = accountKey ?: return ListResponse.getListInstance<ParcelableStatus>(MicroBlogException("No Account")) val accountKey = accountKey ?: return ListResponse.getListInstance<ParcelableStatus>(MicroBlogException("No Account"))
val details = AccountUtils.getAccountDetails(AccountManager.get(context), accountKey) ?: val details = AccountUtils.getAccountDetails(AccountManager.get(context), accountKey, true) ?:
return ListResponse.getListInstance<ParcelableStatus>(MicroBlogException("No Account")) return ListResponse.getListInstance<ParcelableStatus>(MicroBlogException("No Account"))
var data: MutableList<ParcelableStatus>? = data var data: MutableList<ParcelableStatus>? = data

View File

@ -44,11 +44,11 @@ abstract class MicroBlogAPIUsersLoader(
override fun loadInBackground(): List<ParcelableUser> { override fun loadInBackground(): List<ParcelableUser> {
if (accountKey == null) { if (accountKey == null) {
return ListResponse.getListInstance<ParcelableUser>(MicroBlogException("No Account")) return ListResponse.getListInstance(MicroBlogException("No Account"))
} }
val am = AccountManager.get(context) val am = AccountManager.get(context)
val details = AccountUtils.getAccountDetails(am, accountKey) ?: val details = AccountUtils.getAccountDetails(am, accountKey, true) ?:
return ListResponse.getListInstance<ParcelableUser>(MicroBlogException("No Account")) return ListResponse.getListInstance(MicroBlogException("No Account"))
val twitter: MicroBlog = details.newMicroBlogInstance(context = context, cls = MicroBlog::class.java) val twitter: MicroBlog = details.newMicroBlogInstance(context = context, cls = MicroBlog::class.java)
val data = data val data = data
val users: List<User> val users: List<User>

View File

@ -58,7 +58,7 @@ class ParcelableStatusLoader(
override fun loadInBackground(): SingleResponse<ParcelableStatus> { override fun loadInBackground(): SingleResponse<ParcelableStatus> {
if (accountKey == null || statusId == null) return SingleResponse.getInstance<ParcelableStatus>() if (accountKey == null || statusId == null) return SingleResponse.getInstance<ParcelableStatus>()
val details = AccountUtils.getAccountDetails(AccountManager.get(context), accountKey) val details = AccountUtils.getAccountDetails(AccountManager.get(context), accountKey, true)
if (!omitIntentExtra && extras != null) { if (!omitIntentExtra && extras != null) {
val cache = extras.getParcelable<ParcelableStatus>(IntentConstants.EXTRA_STATUS) val cache = extras.getParcelable<ParcelableStatus>(IntentConstants.EXTRA_STATUS)
if (cache != null) { if (cache != null) {

View File

@ -70,7 +70,7 @@ class ParcelableUserLoader(
val resolver = context.contentResolver val resolver = context.contentResolver
val accountKey = accountKey val accountKey = accountKey
val am = AccountManager.get(context) val am = AccountManager.get(context)
val details = AccountUtils.getAllAccountDetails(am, AccountUtils.getAccounts(am)).firstOrNull { val details = AccountUtils.getAllAccountDetails(am, AccountUtils.getAccounts(am), true).firstOrNull {
if (it.key == accountKey) { if (it.key == accountKey) {
return@firstOrNull true return@firstOrNull true
} else if (it.user.account_key == accountKey) { } else if (it.user.account_key == accountKey) {

View File

@ -15,7 +15,7 @@ import org.mariotaku.twidere.model.util.AccountUtils
class AccountActionProvider( class AccountActionProvider(
context: Context, context: Context,
var accounts: Array<AccountDetails>? = AccountUtils.getAllAccountDetails(AccountManager.get(context)) var accounts: Array<AccountDetails>? = AccountUtils.getAllAccountDetails(AccountManager.get(context), false)
) : ActionProvider(context), TwidereConstants { ) : ActionProvider(context), TwidereConstants {
var selectedAccountIds: Array<UserKey>? = null var selectedAccountIds: Array<UserKey>? = null

View File

@ -0,0 +1,12 @@
package org.mariotaku.twidere.model.analyzer
import org.mariotaku.twidere.util.Analyzer
/**
* Created by mariotaku on 2016/12/15.
*/
data class Search(
val query: String,
override val account: String?
) : Analyzer.Event

View File

@ -0,0 +1,16 @@
package org.mariotaku.twidere.model.analyzer
import org.mariotaku.twidere.annotation.AccountType
import org.mariotaku.twidere.util.Analyzer
/**
* Created by mariotaku on 2016/12/15.
*/
data class SignIn(
val success: Boolean,
@AccountType val type: String,
override val account: String? = null,
val officialKey: Boolean = false,
val authType: String? = null,
val errorReason: String? = null
) : Analyzer.Event

View File

@ -350,7 +350,7 @@ class BackgroundOperationService : IntentService("background_operation"), Consta
text: String, text: String,
imageUri: String?): SingleResponse<ParcelableDirectMessage> { imageUri: String?): SingleResponse<ParcelableDirectMessage> {
val details = AccountUtils.getAccountDetails(AccountManager.get(this), val details = AccountUtils.getAccountDetails(AccountManager.get(this),
accountKey) ?: return SingleResponse.getInstance<ParcelableDirectMessage>() accountKey, true) ?: return SingleResponse.getInstance()
val twitter = details.newMicroBlogInstance(context = this, cls = MicroBlog::class.java) val twitter = details.newMicroBlogInstance(context = this, cls = MicroBlog::class.java)
val twitterUpload = details.newMicroBlogInstance(context = this, cls = TwitterUpload::class.java) val twitterUpload = details.newMicroBlogInstance(context = this, cls = TwitterUpload::class.java)
try { try {

View File

@ -94,7 +94,7 @@ class StreamingService : Service() {
} }
private fun setTwitterInstances(): Boolean { private fun setTwitterInstances(): Boolean {
val accountsList = AccountUtils.getAllAccountDetails(AccountManager.get(this)).filter { it.credentials is OAuthCredentials } val accountsList = AccountUtils.getAllAccountDetails(AccountManager.get(this), true).filter { it.credentials is OAuthCredentials }
val accountKeys = accountsList.map { it.key }.toTypedArray() val accountKeys = accountsList.map { it.key }.toTypedArray()
val activatedPreferences = AccountPreferences.getAccountPreferences(this, accountKeys) val activatedPreferences = AccountPreferences.getAccountPreferences(this, accountKeys)
if (BuildConfig.DEBUG) { if (BuildConfig.DEBUG) {

View File

@ -71,7 +71,7 @@ abstract class AbsFriendshipOperationTask(
} }
public override fun doLongOperation(args: Arguments): SingleResponse<ParcelableUser> { public override fun doLongOperation(args: Arguments): SingleResponse<ParcelableUser> {
val details = AccountUtils.getAccountDetails(AccountManager.get(context), args.accountKey) ?: return SingleResponse.getInstance<ParcelableUser>() val details = AccountUtils.getAccountDetails(AccountManager.get(context), args.accountKey, true) ?: return SingleResponse.getInstance()
val twitter = details.newMicroBlogInstance(context, cls = MicroBlog::class.java) val twitter = details.newMicroBlogInstance(context, cls = MicroBlog::class.java)
try { try {
val user = perform(twitter, details, args) val user = perform(twitter, details, args)

View File

@ -28,7 +28,7 @@ class DestroyStatusTask(
) : ManagedAsyncTask<Any, Any, SingleResponse<ParcelableStatus>>(context) { ) : ManagedAsyncTask<Any, Any, SingleResponse<ParcelableStatus>>(context) {
override fun doInBackground(vararg params: Any): SingleResponse<ParcelableStatus> { override fun doInBackground(vararg params: Any): SingleResponse<ParcelableStatus> {
val details = AccountUtils.getAccountDetails(AccountManager.get(context), accountKey) val details = AccountUtils.getAccountDetails(AccountManager.get(context), accountKey, true)
?: return SingleResponse() ?: return SingleResponse()
val microBlog = details.newMicroBlogInstance(context, cls = MicroBlog::class.java) val microBlog = details.newMicroBlogInstance(context, cls = MicroBlog::class.java)
var status: ParcelableStatus? = null var status: ParcelableStatus? = null

View File

@ -67,7 +67,7 @@ abstract class GetActivitiesTask(
for (i in accountIds.indices) { for (i in accountIds.indices) {
val accountKey = accountIds[i] val accountKey = accountIds[i]
val noItemsBefore = DataStoreUtils.getActivitiesCount(context, contentUri, accountKey) <= 0 val noItemsBefore = DataStoreUtils.getActivitiesCount(context, contentUri, accountKey) <= 0
val credentials = AccountUtils.getAccountDetails(AccountManager.get(context), accountKey) ?: continue val credentials = AccountUtils.getAccountDetails(AccountManager.get(context), accountKey, true) ?: continue
val microBlog = credentials.newMicroBlogInstance(context = context, cls = MicroBlog::class.java) val microBlog = credentials.newMicroBlogInstance(context = context, cls = MicroBlog::class.java)
val paging = Paging() val paging = Paging()
paging.count(loadItemLimit) paging.count(loadItemLimit)

View File

@ -93,7 +93,7 @@ abstract class GetStatusesTask(
for (i in 0 until accountKeys.size) { for (i in 0 until accountKeys.size) {
val accountKey = accountKeys[i] val accountKey = accountKeys[i]
val details = AccountUtils.getAccountDetails(AccountManager.get(context), val details = AccountUtils.getAccountDetails(AccountManager.get(context),
accountKey) ?: continue accountKey, true) ?: continue
val microBlog = details.newMicroBlogInstance(context = context, cls = MicroBlog::class.java) val microBlog = details.newMicroBlogInstance(context = context, cls = MicroBlog::class.java)
try { try {
val paging = Paging() val paging = Paging()

View File

@ -0,0 +1,61 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.util
import android.app.Application
/**
* Created by mariotaku on 15/7/8.
*/
abstract class Analyzer {
protected abstract fun log(priority: Int, tag: String, msg: String)
protected abstract fun log(event: Event)
protected abstract fun logException(throwable: Throwable)
protected abstract fun init(application: Application)
interface Event {
val account: String?
}
companion object {
var implementation: Analyzer? = null
fun init(application: Application) {
implementation?.init(application)
}
fun log(event: Event) {
implementation?.log(event)
}
fun log(priority: Int, tag: String, msg: String) {
implementation?.log(priority, tag, msg)
}
fun logException(throwable: Throwable) {
implementation?.logException(throwable)
}
}
}

View File

@ -21,6 +21,7 @@ package org.mariotaku.twidere.util
import android.content.Context import android.content.Context
import android.support.v4.app.Fragment import android.support.v4.app.Fragment
import java.util.*
/** /**
* Created by mariotaku on 15/4/27. * Created by mariotaku on 15/4/27.
@ -31,7 +32,8 @@ abstract class MapFragmentFactory {
companion object { companion object {
fun getInstance(): MapFragmentFactory = MapFragmentFactoryImpl() val instance: MapFragmentFactory
get() = ServiceLoader.load(MapFragmentFactory::class.java).first()
} }
} }

View File

@ -115,7 +115,7 @@ object MenuUtils {
status: ParcelableStatus, status: ParcelableStatus,
twitter: AsyncTwitterWrapper) { twitter: AsyncTwitterWrapper) {
val account = AccountUtils.getAccountDetails(AccountManager.get(context), val account = AccountUtils.getAccountDetails(AccountManager.get(context),
status.account_key) ?: return status.account_key, true) ?: return
setupForStatus(context, preferences, menu, status, account, twitter) setupForStatus(context, preferences, menu, status, account, twitter)
} }

View File

@ -27,6 +27,7 @@ import org.mariotaku.twidere.fragment.card.CardPollFragment
import org.mariotaku.twidere.model.ParcelableCardEntity import org.mariotaku.twidere.model.ParcelableCardEntity
import org.mariotaku.twidere.model.ParcelableStatus import org.mariotaku.twidere.model.ParcelableStatus
import org.mariotaku.twidere.model.util.ParcelableCardEntityUtils import org.mariotaku.twidere.model.util.ParcelableCardEntityUtils
import java.util.*
/** /**
* Created by mariotaku on 15/1/1. * Created by mariotaku on 15/1/1.
@ -42,7 +43,7 @@ abstract class TwitterCardFragmentFactory {
companion object { companion object {
val instance: TwitterCardFragmentFactory val instance: TwitterCardFragmentFactory
get() = TwitterCardFragmentFactoryImpl() get() = ServiceLoader.load(TwitterCardFragmentFactory::class.java).first()
fun createGenericPlayerFragment(card: ParcelableCardEntity?, args: Bundle?): Fragment? { fun createGenericPlayerFragment(card: ParcelableCardEntity?, args: Bundle?): Fragment? {
if (card == null) return null if (card == null) return null