diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/BitmapUtils.java b/twidere/src/main/java/org/mariotaku/twidere/util/BitmapUtils.java index 5d9e62a73..4ce0b76ee 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/BitmapUtils.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/BitmapUtils.java @@ -54,4 +54,11 @@ public class BitmapUtils { BitmapFactory.decodeFile(image.getPath(), o); return o.outMimeType; } + + public static int calculateInSampleSize(final int width, final int height, final int preferredWidth, + final int preferredHeight) { + if (preferredHeight > height && preferredWidth > width) return 1; + final int result = Math.round(Math.max(width, height) / (float) Math.max(preferredWidth, preferredHeight)); + return Math.max(1, result); + } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java b/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java index 85e72b440..0df2509be 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java @@ -55,20 +55,15 @@ import android.support.v4.net.ConnectivityManagerCompat; import android.support.v4.view.GravityCompat; import android.support.v4.view.accessibility.AccessibilityEventCompat; import android.support.v7.app.AppCompatActivity; -import android.support.v7.view.menu.MenuBuilder; import android.text.TextUtils; import android.text.format.DateFormat; import android.text.format.DateUtils; -import android.util.DisplayMetrics; import android.util.Log; import android.util.TypedValue; -import android.view.Display; import android.view.Gravity; import android.view.KeyCharacterMap; import android.view.KeyEvent; -import android.view.Menu; import android.view.View; -import android.view.WindowManager; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.widget.Toast; @@ -99,7 +94,6 @@ import org.mariotaku.twidere.view.TabPagerIndicator; import java.io.Closeable; import java.io.File; import java.io.IOException; -import java.lang.reflect.Field; import java.text.NumberFormat; import java.util.ArrayList; import java.util.List; @@ -159,13 +153,6 @@ public final class Utils implements Constants { accessibilityManager.sendAccessibilityEvent(event); } - public static int calculateInSampleSize(final int width, final int height, final int preferredWidth, - final int preferredHeight) { - if (preferredHeight > height && preferredWidth > width) return 1; - final int result = Math.round(Math.max(width, height) / (float) Math.max(preferredWidth, preferredHeight)); - return Math.max(1, result); - } - public static boolean closeSilently(final Closeable c) { if (c == null) return false; try { @@ -800,18 +787,6 @@ public final class Utils implements Constants { showErrorMessage(context, message, long_message); } - public static void startStatusShareChooser(final Context context, final ParcelableStatus status) { - final Intent intent = new Intent(Intent.ACTION_SEND); - intent.setType("text/plain"); - final String name = status.user_name, screenName = status.user_screen_name; - final String timeString = formatToLongTimeString(context, status.timestamp); - final String subject = context.getString(R.string.status_share_subject_format_with_time, name, screenName, timeString); - intent.putExtra(Intent.EXTRA_SUBJECT, subject); - intent.putExtra(Intent.EXTRA_TEXT, status.text_plain); - intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - context.startActivity(Intent.createChooser(intent, context.getString(R.string.action_share))); - } - public static String trimLineBreak(final String orig) { if (orig == null) return null; return orig.replaceAll("\\n+", "\n"); @@ -863,28 +838,6 @@ public final class Utils implements Constants { return 0; } - - public static Object findFieldOfTypes(T obj, Class cls, Class... checkTypes) { - labelField: - for (Field field : cls.getDeclaredFields()) { - field.setAccessible(true); - final Object fieldObj; - try { - fieldObj = field.get(obj); - } catch (Exception ignore) { - continue; - } - if (fieldObj != null) { - final Class type = fieldObj.getClass(); - for (Class checkType : checkTypes) { - if (!checkType.isAssignableFrom(type)) continue labelField; - } - return fieldObj; - } - } - return null; - } - public static int getNotificationId(int baseId, @Nullable UserKey accountKey) { int result = baseId; result = 31 * result + (accountKey != null ? accountKey.hashCode() : 0); @@ -962,38 +915,4 @@ public final class Utils implements Constants { return location; } - public static boolean checkDeviceCompatible() { - try { - Menu.class.isAssignableFrom(MenuBuilder.class); - } catch (Error e) { - Analyzer.Companion.logException(e); - return false; - } - return true; - } - - /** - * Detect whether screen minimum width is not smaller than 600dp, regardless split screen mode - */ - public static boolean isDeviceTablet(@NonNull Context context) { - DisplayMetrics metrics = new DisplayMetrics(); - WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); - final Display defaultDisplay = wm.getDefaultDisplay(); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { - defaultDisplay.getMetrics(metrics); - } else { - defaultDisplay.getRealMetrics(metrics); - } - final float mw = Math.min(metrics.widthPixels / metrics.density, metrics.heightPixels / metrics.density); - return mw >= 600; - } - - /* - * May return false on tablets when using split window - */ - public static boolean isScreenTablet(@NonNull Context context) { - DisplayMetrics metrics = context.getResources().getDisplayMetrics(); - return metrics.widthPixels / metrics.density >= 600; - } - } diff --git a/twidere/src/main/kotlin/android/support/v7/widget/TwidereToolbar.kt b/twidere/src/main/kotlin/android/support/v7/widget/TwidereToolbar.kt index 9d7ea03a1..3931eefd4 100644 --- a/twidere/src/main/kotlin/android/support/v7/widget/TwidereToolbar.kt +++ b/twidere/src/main/kotlin/android/support/v7/widget/TwidereToolbar.kt @@ -26,8 +26,9 @@ import android.util.AttributeSet import android.view.Menu import android.view.View import android.widget.ImageView +import org.mariotaku.twidere.extension.findFieldByTypes +import org.mariotaku.twidere.extension.get import org.mariotaku.twidere.util.ThemeUtils -import org.mariotaku.twidere.util.Utils /** * Created by mariotaku on 15/1/16. @@ -39,10 +40,18 @@ class TwidereToolbar(context: Context, attrs: AttributeSet?) : Toolbar(context, override fun getMenu(): Menu { val menu = super.getMenu() ThemeUtils.setActionBarOverflowColor(this, itemColor) - val menuView = Utils.findFieldOfTypes(this, Toolbar::class.java, - ActionMenuView::class.java) as? ActionMenuView ?: return menu - val presenter = Utils.findFieldOfTypes(menuView, ActionMenuView::class.java, - ActionMenuPresenter::class.java) as? ActionMenuPresenter ?: return menu + val menuViewField = try { + Toolbar::class.java.findFieldByTypes(ActionMenuView::class.java) + } catch (e: Exception) { + null + } ?: return menu + val menuView = this[menuViewField] as? ActionMenuView ?: return menu + val presenterField = try { + ActionMenuView::class.java.findFieldByTypes(ActionMenuPresenter::class.java) + } catch (e: Exception) { + null + } ?: return menu + val presenter = menuView[presenterField] as? ActionMenuPresenter ?: return menu setActionBarOverflowColor(presenter, itemColor) return menu } @@ -62,8 +71,12 @@ class TwidereToolbar(context: Context, attrs: AttributeSet?) : Toolbar(context, companion object { private fun setActionBarOverflowColor(presenter: ActionMenuPresenter, itemColor: Int) { - val view = Utils.findFieldOfTypes(presenter, ActionMenuPresenter::class.java, - ActionMenuView.ActionMenuChildView::class.java, View::class.java) as? ImageView ?: return + val viewField = try { + ActionMenuPresenter::class.java.findFieldByTypes(ActionMenuView.ActionMenuChildView::class.java, View::class.java) + } catch (e: Exception) { + null + } ?: return + val view = presenter[viewField] as? ImageView ?: return view.setColorFilter(itemColor, PorterDuff.Mode.SRC_ATOP) } } diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/HomeActivity.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/HomeActivity.kt index d81fc8de7..7f36ccb4b 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/HomeActivity.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/HomeActivity.kt @@ -868,7 +868,7 @@ class HomeActivity : BaseActivity(), OnClickListener, OnPageChangeListener, Supp fun hasMultiColumns(): Boolean { - if (!Utils.isDeviceTablet(this) || !Utils.isScreenTablet(this)) return false + if (!DeviceUtils.isDeviceTablet(this) || !DeviceUtils.isScreenTablet(this)) return false if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) { return preferences.getBoolean("multi_column_tabs_landscape", resources.getBoolean(R.bool.default_multi_column_tabs_land)) } diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/MainActivity.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/MainActivity.kt index 64eb2a7fa..9907a704e 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/MainActivity.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/MainActivity.kt @@ -28,6 +28,7 @@ import org.mariotaku.twidere.R import org.mariotaku.twidere.constant.IntentConstants.EXTRA_INTENT import org.mariotaku.twidere.extension.model.hasInvalidAccount import org.mariotaku.twidere.model.util.AccountUtils +import org.mariotaku.twidere.util.DeviceUtils import org.mariotaku.twidere.util.StrictModeUtils import org.mariotaku.twidere.util.Utils @@ -40,7 +41,7 @@ open class MainActivity : BaseActivity() { } super.onCreate(savedInstanceState) val am = AccountManager.get(this) - if (!Utils.checkDeviceCompatible()) { + if (!DeviceUtils.checkCompatibility()) { startActivity(Intent(this, IncompatibleAlertActivity::class.java)) } else if (!AccountUtils.hasAccountPermission(am)) { Toast.makeText(this, R.string.message_toast_no_account_permission, Toast.LENGTH_SHORT).show() diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/SettingsActivity.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/SettingsActivity.kt index 13ea6b485..b6f4b4eeb 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/SettingsActivity.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/SettingsActivity.kt @@ -48,9 +48,9 @@ import org.mariotaku.twidere.constant.KeyboardShortcutConstants.ACTION_NAVIGATIO import org.mariotaku.twidere.constant.KeyboardShortcutConstants.CONTEXT_TAG_NAVIGATION import org.mariotaku.twidere.extension.applyTheme import org.mariotaku.twidere.fragment.* +import org.mariotaku.twidere.util.DeviceUtils import org.mariotaku.twidere.util.KeyboardShortcutsHandler import org.mariotaku.twidere.util.ThemeUtils -import org.mariotaku.twidere.util.Utils import java.util.* class SettingsActivity : BaseActivity(), OnItemClickListener, OnPreferenceStartFragmentCallback { @@ -199,7 +199,7 @@ class SettingsActivity : BaseActivity(), OnItemClickListener, OnPreferenceStartF R.xml.preferences_theme) entriesAdapter.addPreference("cards", R.drawable.ic_action_card, getString(R.string.cards), R.xml.preferences_cards) - if (Utils.isDeviceTablet(this)) { + if (DeviceUtils.isDeviceTablet(this)) { entriesAdapter.addPreference("tablet_mode", R.drawable.ic_action_tablet, getString(R.string.preference_title_tablet_mode), R.xml.preferences_tablet_mode) } diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/extension/ClassExtensions.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/extension/ClassExtensions.kt new file mode 100644 index 000000000..02bff526e --- /dev/null +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/extension/ClassExtensions.kt @@ -0,0 +1,32 @@ +/* + * Twidere - Twitter client for Android + * + * Copyright (C) 2012-2017 Mariotaku Lee + * + * 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 . + */ + +package org.mariotaku.twidere.extension + +import java.lang.reflect.Field + +/** + * Created by mariotaku on 2017/4/17. + */ + +fun Class<*>.findFieldByTypes(vararg checkTypes: Class<*>): Field? { + return declaredFields.firstOrNull { field -> + checkTypes.all { it.isAssignableFrom(field.type) } + } +} \ No newline at end of file diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/extension/ReflectionExtensions.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/extension/ReflectionExtensions.kt new file mode 100644 index 000000000..d31a264a2 --- /dev/null +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/extension/ReflectionExtensions.kt @@ -0,0 +1,36 @@ +/* + * Twidere - Twitter client for Android + * + * Copyright (C) 2012-2017 Mariotaku Lee + * + * 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 . + */ + +package org.mariotaku.twidere.extension + +import java.lang.reflect.Field + +/** + * Created by mariotaku on 2017/4/17. + */ + +operator fun Any.get(field: Field): Any? { + val accessible = field.isAccessible + try { + field.isAccessible = true + return field[this] + } finally { + field.isAccessible = accessible + } +} \ No newline at end of file diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/extension/model/ParcelableMediaUpdateExtensions.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/extension/model/ParcelableMediaUpdateExtensions.kt index 19a46ba1b..dea89fd49 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/extension/model/ParcelableMediaUpdateExtensions.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/extension/model/ParcelableMediaUpdateExtensions.kt @@ -16,7 +16,7 @@ fun ParcelableMediaUpdate.getMimeType(resolver: ContentResolver): String? { ParcelableMedia.Type.IMAGE -> { val o = BitmapFactory.Options() o.inJustDecodeBounds = true - BitmapFactoryUtils.decodeUri(resolver, uri, null, o) + BitmapFactoryUtils.decodeUri(resolver, uri, opts = o) return o.outMimeType } else -> return null diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/task/twitter/UpdateStatusTask.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/task/twitter/UpdateStatusTask.kt index c5bfeca55..61704c682 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/task/twitter/UpdateStatusTask.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/task/twitter/UpdateStatusTask.kt @@ -688,7 +688,7 @@ class UpdateStatusTask( this.deleteAlways = deleteAlways } } finally { - Utils.closeSilently(body) + body?.close() } body?.deleteOnSuccess?.addAllTo(deleteOnSuccess) body?.deleteAlways?.addAllTo(deleteAlways) @@ -811,7 +811,7 @@ class UpdateStatusTask( var mediaType = defaultType val o = BitmapFactory.Options() o.inJustDecodeBounds = true - BitmapFactoryUtils.decodeUri(resolver, mediaUri, null, o) + BitmapFactoryUtils.decodeUri(resolver, mediaUri, opts = o) // Try to use decoded media type if (o.outMimeType != null) { mediaType = o.outMimeType @@ -823,7 +823,7 @@ class UpdateStatusTask( if (imageLimit != null) { if (imageLimit.checkGeomentry(o.outWidth, o.outHeight)) return null - o.inSampleSize = Utils.calculateInSampleSize(o.outWidth, o.outHeight, + o.inSampleSize = BitmapUtils.calculateInSampleSize(o.outWidth, o.outHeight, imageLimit.maxWidth, imageLimit.maxHeight) } o.inJustDecodeBounds = false diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/util/BitmapFactoryUtils.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/util/BitmapFactoryUtils.kt index cfb03abda..8e9cd7f44 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/util/BitmapFactoryUtils.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/util/BitmapFactoryUtils.kt @@ -6,7 +6,6 @@ import android.graphics.BitmapFactory import android.graphics.Rect import android.net.Uri import java.io.IOException -import java.io.InputStream /** * Created by mariotaku on 16/7/31. @@ -14,16 +13,10 @@ import java.io.InputStream object BitmapFactoryUtils { @Throws(IOException::class) - fun decodeUri(contentResolver: ContentResolver, uri: Uri, outPadding: Rect?, - opts: BitmapFactory.Options?, close: Boolean = true): Bitmap? { - var st: InputStream? = null - try { - st = contentResolver.openInputStream(uri) - return BitmapFactory.decodeStream(st, outPadding, opts) - } finally { - if (close) { - Utils.closeSilently(st) - } + fun decodeUri(contentResolver: ContentResolver, uri: Uri, outPadding: Rect? = null, + opts: BitmapFactory.Options? = null): Bitmap? { + return contentResolver.openInputStream(uri).use { + BitmapFactory.decodeStream(it, outPadding, opts) } } diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/util/DeviceUtils.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/util/DeviceUtils.kt new file mode 100644 index 000000000..700838051 --- /dev/null +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/util/DeviceUtils.kt @@ -0,0 +1,69 @@ +/* + * Twidere - Twitter client for Android + * + * Copyright (C) 2012-2017 Mariotaku Lee + * + * 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 . + */ + +package org.mariotaku.twidere.util + +import android.content.Context +import android.os.Build +import android.support.v7.view.menu.MenuBuilder +import android.util.DisplayMetrics +import android.view.Menu +import android.view.WindowManager + +/** + * Created by mariotaku on 2017/4/17. + */ + +object DeviceUtils { + + fun checkCompatibility(): Boolean { + try { + Menu::class.java.isAssignableFrom(MenuBuilder::class.java) + } catch (e: Error) { + Analyzer.logException(e) + return false + } + + return true + } + + /** + * Detect whether screen minimum width is not smaller than 600dp, regardless split screen mode + */ + fun isDeviceTablet(context: Context): Boolean { + val metrics = DisplayMetrics() + val wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager + val defaultDisplay = wm.defaultDisplay + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { + defaultDisplay.getMetrics(metrics) + } else { + defaultDisplay.getRealMetrics(metrics) + } + val mw = Math.min(metrics.widthPixels / metrics.density, metrics.heightPixels / metrics.density) + return mw >= 600 + } + + /* + * May return false on tablets when using split window + */ + fun isScreenTablet(context: Context): Boolean { + val metrics = context.resources.displayMetrics + return metrics.widthPixels / metrics.density >= 600 + } +} diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/util/OAuthPasswordAuthenticator.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/util/OAuthPasswordAuthenticator.kt index 1cfe5b55d..e603a85a3 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/util/OAuthPasswordAuthenticator.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/util/OAuthPasswordAuthenticator.kt @@ -108,9 +108,7 @@ class OAuthPasswordAuthenticator( @Throws(IOException::class, LoginVerificationException::class) private fun getVerificationData(authorizeResponseData: AuthorizeResponseData, challengeResponse: String?): AuthorizeRequestData { - var response: HttpResponse? = null try { - val data = AuthorizeRequestData() val params = MultiValueMap() val verification = authorizeResponseData.challenge!! params.add("authenticity_token", verification.authenticityToken) @@ -132,16 +130,16 @@ class OAuthPasswordAuthenticator( authorizeResultBuilder.url(endpoint.construct("/account/login_verification")) authorizeResultBuilder.headers(requestHeaders) authorizeResultBuilder.body(authorizationResultBody) - response = client.newCall(authorizeResultBuilder.build()).execute() - parseAuthorizeRequestData(response, data) - if (TextUtils.isEmpty(data.authenticityToken)) { - throw LoginVerificationException() + return client.newCall(authorizeResultBuilder.build()).execute().use { + val data = AuthorizeRequestData() + parseAuthorizeRequestData(it, data) + if (data.authenticityToken.isNullOrEmpty()) { + throw LoginVerificationException() + } + return@use data } - return data } catch (e: ParseException) { throw LoginVerificationException("Login verification challenge failed", e) - } finally { - Utils.closeSilently(response) } } @@ -188,7 +186,6 @@ class OAuthPasswordAuthenticator( private fun getAuthorizeResponseData(requestToken: OAuthToken, authorizeRequestData: AuthorizeRequestData, username: String, password: String): AuthorizeResponseData { - var response: HttpResponse? = null try { val data = AuthorizeResponseData() val params = MultiValueMap() @@ -209,7 +206,6 @@ class OAuthPasswordAuthenticator( authorizeResultBuilder.url(endpoint.construct("/oauth/authorize")) authorizeResultBuilder.headers(requestHeaders) authorizeResultBuilder.body(authorizationResultBody) - response = client.newCall(authorizeResultBuilder.build()).execute() val handler = object : AbstractSimpleMarkupHandler() { internal var isOAuthPinDivOpened: Boolean = false internal var isChallengeFormOpened: Boolean = false @@ -297,18 +293,17 @@ class OAuthPasswordAuthenticator( } } } - PARSER.parse(SimpleBody.reader(response!!.body), handler) + client.newCall(authorizeResultBuilder.build()).execute().use { + PARSER.parse(SimpleBody.reader(it.body), handler) + } return data } catch (e: ParseException) { throw AuthenticationException("Malformed HTML", e) - } finally { - Utils.closeSilently(response) } } @Throws(IOException::class, AuthenticationException::class) private fun getAuthorizeRequestData(requestToken: OAuthToken): AuthorizeRequestData { - var response: HttpResponse? = null try { val data = AuthorizeRequestData() val authorizePageBuilder = HttpRequest.Builder() @@ -321,16 +316,15 @@ class OAuthPasswordAuthenticator( requestHeaders.add("User-Agent", userAgent) authorizePageBuilder.headers(requestHeaders) val authorizePageRequest = authorizePageBuilder.build() - response = client.newCall(authorizePageRequest).execute() - parseAuthorizeRequestData(response, data) - if (TextUtils.isEmpty(data.authenticityToken)) { + client.newCall(authorizePageRequest).execute().use { + parseAuthorizeRequestData(it, data) + } + if (data.authenticityToken.isNullOrEmpty()) { throw AuthenticationException() } return data } catch (e: ParseException) { throw AuthenticationException("Malformed HTML", e) - } finally { - Utils.closeSilently(response) } } diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/util/sync/TimelineSyncManager.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/util/sync/TimelineSyncManager.kt index e5adef114..139958973 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/util/sync/TimelineSyncManager.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/util/sync/TimelineSyncManager.kt @@ -49,12 +49,27 @@ abstract class TimelineSyncManager(val context: Context) { } + fun blockingGetPosition(@ReadPositionTag positionTag: String, currentTag: String?): Long { + val position = fetchPosition(positionTag, currentTag) + synchronized(cachedPositions) { + cachedPositions[TimelineKey(positionTag, currentTag)] = position + } + return position + } + + fun peekPosition(@ReadPositionTag positionTag: String, currentTag: String?): Long { + synchronized(cachedPositions) { + return cachedPositions[TimelineKey(positionTag, currentTag)] ?: -1 + } + } + + @UiThread protected abstract fun performSync(data: Array) @WorkerThread @Throws(IOException::class) - abstract fun blockingGetPosition(@ReadPositionTag positionTag: String, currentTag: String?): Long + protected abstract fun fetchPosition(@ReadPositionTag positionTag: String, currentTag: String?): Long data class TimelineKey(val positionTag: String, val currentTag: String?) data class PositionData(val positionTag: String, val currentTag: String?, val positionKey: Long) @@ -80,4 +95,5 @@ abstract class TimelineSyncManager(val context: Context) { fun newFactory(): Factory = ServiceLoader.load(Factory::class.java).firstOrNull() ?: DummyFactory } + }