fixing lint problems

This commit is contained in:
Mariotaku Lee 2017-08-28 00:37:40 +08:00
parent b69f89df8b
commit 4d13ec32e6
No known key found for this signature in database
GPG Key ID: 15C10F89D7C33535
28 changed files with 246 additions and 210 deletions

View File

@ -45,6 +45,12 @@ android {
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
aaptOptions {
additionalParameters "--no-version-vectors"
}
@ -61,6 +67,7 @@ android {
dimension 'channel'
}
}
buildTypes {
debug {
minifyEnabled false
@ -74,11 +81,13 @@ android {
resValue("bool", "debug", "false")
}
}
sourceSets.each {
it.res.srcDirs += project.files("src/${it.name}/res-localized")
it.res.srcDirs += project.files("src/${it.name}/res-svg2png")
it.java.srcDirs += "src/${it.name}/kotlin"
}
testOptions {
unitTests.returnDefaultValues = true
}

View File

@ -1 +1 @@
5b6ffb3701c112844efa7cb73251752db335471d
31b8532f317628f2c3b26b9770bbd6d4cb9209ec

View File

@ -0,0 +1,45 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2017 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.model;
import android.database.Cursor;
import java.io.Closeable;
import java.io.IOException;
public class CursorReference<C extends Cursor> implements Closeable {
private final C cursor;
public CursorReference(C cursor) {
this.cursor = cursor;
}
public C get() {
return cursor;
}
@Override
public void close() throws IOException {
if (cursor == null) return;
cursor.close();
}
}

View File

@ -51,6 +51,11 @@ import java.util.List;
import static org.mariotaku.twidere.TwidereConstants.LOGTAG;
/**
* @deprecated This will be removed soon, target language selection will be changed inside
* translation UI.
*/
@Deprecated
public class TranslationDestinationPreference extends Preference implements OnClickListener {
private String mSelectedLanguageCode = "en";

View File

@ -117,12 +117,7 @@ public final class ViewSupport {
}
public static void setForeground(View view, Drawable foreground) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
if (view instanceof IForegroundView) {
//noinspection RedundantCast
((IForegroundView) view).setForeground(foreground);
}
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
ViewAccessorICS.setForeground(view, foreground);
} else {
view.setForeground(foreground);
@ -146,7 +141,6 @@ public final class ViewSupport {
}
static void setForeground(final View view, final Drawable foreground) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) return;
if (view instanceof FrameLayout) {
//noinspection RedundantCast
((FrameLayout) view).setForeground(foreground);

View File

@ -0,0 +1,28 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2017 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.ktextension
import android.database.sqlite.SQLiteDatabase
import org.mariotaku.twidere.model.CursorReference
fun SQLiteDatabase.queryReference(table: String, columns: Array<String>? = null,
selection: String? = null, selectionArgs: Array<String>? = null, groupBy: String? = null,
having: String? = null, orderBy: String? = null) =
CursorReference(query(table, columns, selection, selectionArgs, groupBy, having, orderBy))

View File

@ -58,6 +58,7 @@ import org.mariotaku.twidere.receiver.ConnectivityStateReceiver
import org.mariotaku.twidere.service.StreamingService
import org.mariotaku.twidere.util.*
import org.mariotaku.twidere.util.content.TwidereSQLiteOpenHelper
import org.mariotaku.twidere.util.dagger.ApplicationModule
import org.mariotaku.twidere.util.dagger.GeneralComponent
import org.mariotaku.twidere.util.emoji.EmojioneTranslator
import org.mariotaku.twidere.util.kovenant.startKovenant
@ -116,6 +117,10 @@ class TwidereApplication : Application(), Constants, OnSharedPreferenceChangeLis
TwidereSQLiteOpenHelper(this, Constants.DATABASES_NAME, Constants.DATABASES_VERSION)
}
val applicationModule: ApplicationModule by lazy {
ApplicationModule(this)
}
private val sharedPreferences: SharedPreferences by lazy {
val prefs = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE)
prefs.registerOnSharedPreferenceChangeListener(this)

View File

@ -24,11 +24,17 @@ import android.content.ContentResolver
import android.database.Cursor
import android.net.Uri
import org.mariotaku.ktextension.map
import org.mariotaku.ktextension.useCursor
import org.mariotaku.library.objectcursor.ObjectCursor
import org.mariotaku.sqliteqb.library.SQLFunctions
import org.mariotaku.twidere.extension.model.component1
import org.mariotaku.twidere.model.CursorReference
import org.mariotaku.twidere.util.TwidereQueryBuilder
import org.mariotaku.twidere.util.content.ContentResolverUtils
fun ContentResolver.queryReference(uri: Uri, projection: Array<String>? = null,
selection: String? = null, selectionArgs: Array<String>? = null, sortOrder: String? = null) =
CursorReference(query(uri, projection, selection, selectionArgs, sortOrder))
@SuppressLint("Recycle")
fun ContentResolver.rawQuery(sql: String, selectionArgs: Array<String>?, notifyUri: Uri? = null): Cursor? {
val rawUri = TwidereQueryBuilder.rawQuery(sql, notifyUri)
@ -37,20 +43,27 @@ fun ContentResolver.rawQuery(sql: String, selectionArgs: Array<String>?, notifyU
fun <T> ContentResolver.queryOne(uri: Uri, projection: Array<String>?, selection: String?,
selectionArgs: Array<String>?, sortOrder: String? = null, cls: Class<T>): T? {
val cursor = this.query(uri, projection, selection, selectionArgs, sortOrder)
return cursor.useCursor { cur ->
if (!cur.moveToFirst()) return@useCursor null
return queryReference(uri, projection, selection, selectionArgs, sortOrder).use { (cur) ->
if (!cur.moveToFirst()) return@use null
val indices = ObjectCursor.indicesFrom(cur, cls)
return@useCursor indices.newObject(cur)
return@use indices.newObject(cur)
}
}
fun <T> ContentResolver.queryAll(uri: Uri, projection: Array<String>?, selection: String?,
selectionArgs: Array<String>?, sortOrder: String? = null, cls: Class<T>): List<T> {
val cursor = this.query(uri, projection, selection, selectionArgs, sortOrder)
return cursor.useCursor { cur ->
return@useCursor cur.map(ObjectCursor.indicesFrom(cur, cls))
return queryReference(uri, projection, selection, selectionArgs, sortOrder).use { (cur) ->
return@use cur.map(ObjectCursor.indicesFrom(cur, cls))
}
}
fun ContentResolver.queryCount(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int {
val projection = arrayOf(SQLFunctions.COUNT())
return queryReference(uri, projection, selection, selectionArgs, null).use { (cur) ->
if (cur.moveToFirst()) {
return@use cur.getInt(0)
}
return@use -1
}
}

View File

@ -24,8 +24,6 @@ import com.bumptech.glide.DrawableRequestBuilder
import com.bumptech.glide.DrawableTypeRequest
import com.bumptech.glide.RequestManager
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.request.target.ImageViewTarget
import com.bumptech.glide.request.target.Target
import jp.wasabeef.glide.transformations.CropCircleTransformation
import org.mariotaku.twidere.R
import org.mariotaku.twidere.annotation.ImageShapeStyle

View File

@ -0,0 +1,27 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2017 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.extension.model
import android.database.Cursor
import org.mariotaku.twidere.model.CursorReference
operator fun <C : Cursor> CursorReference<C>.component1(): C {
return get()
}

View File

@ -4,9 +4,9 @@ import android.content.ContentResolver
import android.net.Uri
import org.mariotaku.ktextension.addAllEnhanced
import org.mariotaku.ktextension.isNullOrEmpty
import org.mariotaku.ktextension.map
import org.mariotaku.library.objectcursor.ObjectCursor
import org.mariotaku.sqliteqb.library.Expression
import org.mariotaku.twidere.extension.queryAll
import org.mariotaku.twidere.model.FiltersData
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.provider.TwidereDataStore.Filters
@ -23,25 +23,13 @@ import java.util.*
fun FiltersData.read(cr: ContentResolver, loadSubscription: Boolean = false) {
fun readBaseItems(uri: Uri): List<FiltersData.BaseItem>? {
val where = if (loadSubscription) null else Expression.lesserThan(Filters.SOURCE, 0).sql
val c = cr.query(uri, Filters.COLUMNS, where, null, null) ?: return null
@Suppress("ConvertTryFinallyToUseCall")
try {
val indices = ObjectCursor.indicesFrom(c, FiltersData.BaseItem::class.java)
return c.map(indices)
} finally {
c.close()
}
return cr.queryAll(uri, Filters.COLUMNS, where, null, null,
FiltersData.BaseItem::class.java)
}
this.users = run {
val where = if (loadSubscription) null else Expression.lesserThan(Filters.Users.SOURCE, 0).sql
val c = cr.query(Filters.Users.CONTENT_URI, Filters.Users.COLUMNS, where, null, null) ?: return@run null
@Suppress("ConvertTryFinallyToUseCall")
try {
val indices = ObjectCursor.indicesFrom(c, FiltersData.UserItem::class.java)
return@run c.map(indices)
} finally {
c.close()
}
return@run cr.queryAll(Filters.Users.CONTENT_URI, Filters.Users.COLUMNS, where, null,
null, FiltersData.UserItem::class.java)
}
this.keywords = readBaseItems(Filters.Keywords.CONTENT_URI)
this.sources = readBaseItems(Filters.Sources.CONTENT_URI)
@ -183,7 +171,7 @@ fun FiltersData.addAll(data: FiltersData, ignoreDuplicates: Boolean = false): Bo
}
fun FiltersData.removeAll(data: FiltersData): Boolean {
var changed: Boolean = false
var changed = false
changed = changed or (data.users?.let { this.users?.removeAll(it) } ?: false)
changed = changed or (data.keywords?.let { this.keywords?.removeAll(it) } ?: false)
changed = changed or (data.sources?.let { this.sources?.removeAll(it) } ?: false)

View File

@ -25,6 +25,7 @@ import android.animation.Animator
import android.animation.Animator.AnimatorListener
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
@ -77,6 +78,7 @@ import org.mariotaku.twidere.constant.profileImageStyleKey
import org.mariotaku.twidere.extension.loadProfileBanner
import org.mariotaku.twidere.extension.loadProfileImage
import org.mariotaku.twidere.extension.model.setActivated
import org.mariotaku.twidere.extension.queryCount
import org.mariotaku.twidere.fragment.AccountsDashboardFragment.AccountsInfo
import org.mariotaku.twidere.graphic.BadgeDrawable
import org.mariotaku.twidere.menu.AccountToggleProvider
@ -119,6 +121,7 @@ class AccountsDashboardFragment : BaseFragment(), LoaderCallbacks<AccountsInfo>,
private var useStarsForLikes: Boolean = false
private var loaderInitialized: Boolean = false
@SuppressLint("RestrictedApi")
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
accountsAdapter = AccountSelectorAdapter(layoutInflater, preferences, Glide.with(this)).also {
@ -741,7 +744,7 @@ class AccountsDashboardFragment : BaseFragment(), LoaderCallbacks<AccountsInfo>,
private fun loadAccountsInfo(loadFromDb: Boolean): AccountsInfo {
val accounts = AccountUtils.getAllAccountDetails(AccountManager.get(context), true)
val draftsCount = if (loadFromDb) {
DataStoreUtils.queryCount(context.contentResolver, Drafts.CONTENT_URI_UNSENT, null,
context.contentResolver.queryCount(Drafts.CONTENT_URI_UNSENT, null,
null)
} else {
-1

View File

@ -94,15 +94,11 @@ class NetworkDiagnosticsFragment : BaseFragment() {
internal class DiagnosticsTask(fragment: NetworkDiagnosticsFragment) : AsyncTask<Any, LogText, Unit>() {
private val fragmentRef = WeakReference(fragment)
private val context = fragment.activity.applicationContext
private val connectivityManager: ConnectivityManager
init {
connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
}
private val contextRef = WeakReference(fragment.activity.applicationContext)
override fun doInBackground(vararg params: Any) {
val context = contextRef.get() ?: return
val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
logPrintln("**** NOTICE ****", LogText.State.WARNING)
logPrintln()
logPrintln("Text below may have personal information, BE CAREFUL TO MAKE IT PUBLIC",
@ -245,7 +241,7 @@ class NetworkDiagnosticsFragment : BaseFragment() {
logPrintln(context.resources.configuration.toString())
logPrintln()
logPrintln(("Active network info: "))
logPrintln((connectivityManager.activeNetworkInfo.toString()))
logPrintln((cm.activeNetworkInfo.toString()))
}
override fun onProgressUpdate(vararg values: LogText) {

View File

@ -263,7 +263,7 @@ abstract class BaseFiltersFragment : AbsContentListViewFragment<SimpleCursorAdap
if (id >= 0) {
val valueWhere = Expression.equalsArgs(Filters.VALUE).sql
val valueWhereArgs = arrayOf(text)
if (DataStoreUtils.queryCount(resolver, uri, valueWhere, valueWhereArgs) == 0) {
if (resolver.queryCount(uri, valueWhere, valueWhereArgs) == 0) {
val idWhere = Expression.equals(Filters._ID, id).sql
resolver.update(uri, values, idWhere, null)
} else {

View File

@ -27,7 +27,6 @@ import android.graphics.drawable.ColorDrawable
import android.media.AudioManager
import android.media.MediaPlayer
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.support.v4.app.Fragment
@ -384,7 +383,7 @@ class VideoPageFragment : CacheDownloadMediaViewerFragment(), IBaseFragment<Vide
const val EXTRA_DEFAULT_MUTE = "default_mute"
internal const val EXTRA_PAUSED_BY_USER = "paused_by_user"
internal const val EXTRA_PLAY_AUDIO = "play_audio"
internal val SUPPORTED_VIDEO_TYPES: Array<String>
internal val SUPPORTED_VIDEO_TYPES: Array<String> = arrayOf("video/webm", "video/mp4")
internal val FALLBACK_VIDEO_TYPES: Array<String> = arrayOf("video/mp4")
internal val MediaViewerFragment.isLoopEnabled: Boolean
@ -398,14 +397,6 @@ class VideoPageFragment : CacheDownloadMediaViewerFragment(), IBaseFragment<Vide
internal val MediaViewerFragment.accountKey: UserKey
get() = arguments.getParcelable<UserKey>(EXTRA_ACCOUNT_KEY)
init {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
SUPPORTED_VIDEO_TYPES = arrayOf("video/mp4")
} else {
SUPPORTED_VIDEO_TYPES = arrayOf("video/webm", "video/mp4")
}
}
@SuppressLint("SwitchIntDef")
internal fun getBestVideoUrlAndType(media: ParcelableMedia?, supportedTypes: Array<String>): Pair<String, String>? {

View File

@ -46,6 +46,7 @@ import org.mariotaku.twidere.adapter.SelectableUsersAdapter
import org.mariotaku.twidere.constant.IntentConstants.*
import org.mariotaku.twidere.constant.nameFirstKey
import org.mariotaku.twidere.extension.model.isOfficial
import org.mariotaku.twidere.extension.queryOne
import org.mariotaku.twidere.extension.text.appendCompat
import org.mariotaku.twidere.fragment.BaseFragment
import org.mariotaku.twidere.loader.CacheUserSearchLoader
@ -324,17 +325,8 @@ class MessageNewConversationFragment : BaseFragment(), LoaderCallbacks<List<Parc
val where = Expression.and(Expression.equalsArgs(Conversations.ACCOUNT_KEY),
Expression.equalsArgs(Conversations.PARTICIPANT_KEYS)).sql
val whereArgs = arrayOf(accountKey.toString(), participantKeys.sorted().joinToString(","))
val cur = resolver.query(Conversations.CONTENT_URI, Conversations.COLUMNS, where, whereArgs, null) ?: return null
@Suppress("ConvertTryFinallyToUseCall")
try {
if (cur.moveToFirst()) {
val indices = ObjectCursor.indicesFrom(cur, ParcelableMessageConversation::class.java)
return indices.newObject(cur)
}
} finally {
cur.close()
}
return null
return resolver.queryOne(Conversations.CONTENT_URI, Conversations.COLUMNS, where, whereArgs,
null, ParcelableMessageConversation::class.java)
}
internal class PerformSearchRequestRunnable(val query: String, fragment: MessageNewConversationFragment) : Runnable {

View File

@ -35,6 +35,7 @@ import org.mariotaku.twidere.extension.model.*
import org.mariotaku.twidere.extension.model.api.key
import org.mariotaku.twidere.extension.model.api.microblog.toParcelable
import org.mariotaku.twidere.extension.model.api.toParcelable
import org.mariotaku.twidere.extension.queryCount
import org.mariotaku.twidere.model.*
import org.mariotaku.twidere.model.notification.NotificationChannelSpec
import org.mariotaku.twidere.model.pagination.SinceMaxPagination
@ -389,7 +390,7 @@ class StreamingService : BaseService() {
Expression.equalsArgs(CachedRelationships.USER_KEY),
Expression.equals(CachedRelationships.NOTIFICATIONS_ENABLED, 1)).sql
val whereArgs = arrayOf(account.key.toString(), userKey.toString())
if (DataStoreUtils.queryCount(context.contentResolver, CachedRelationships.CONTENT_URI,
if (context.contentResolver.queryCount(CachedRelationships.CONTENT_URI,
where, whereArgs) <= 0) return
contentNotificationManager.showUserNotification(account.key, status, userKey)

View File

@ -11,8 +11,10 @@ import org.mariotaku.abstask.library.AbstractTask
import org.mariotaku.library.objectcursor.ObjectCursor
import org.mariotaku.sqliteqb.library.Expression
import org.mariotaku.twidere.TwidereConstants.ACCOUNT_TYPE
import org.mariotaku.twidere.extension.model.component1
import org.mariotaku.twidere.extension.model.setAccountKey
import org.mariotaku.twidere.extension.model.setAccountUser
import org.mariotaku.twidere.extension.queryReference
import org.mariotaku.twidere.model.AccountDetails
import org.mariotaku.twidere.model.ParcelableUser
import org.mariotaku.twidere.model.Tab
@ -58,33 +60,34 @@ class UpdateAccountInfoTask(
}
private fun updateTabs(resolver: ContentResolver, accountKey: UserKey) {
val tabsCursor = resolver.query(Tabs.CONTENT_URI, Tabs.COLUMNS, null, null, null) ?: return
try {
resolver.queryReference(Tabs.CONTENT_URI, Tabs.COLUMNS, null, null,
null).use { (tabsCursor) ->
if (tabsCursor == null) return
val indices = ObjectCursor.indicesFrom(tabsCursor, Tab::class.java)
val creator = ObjectCursor.valuesCreatorFrom(Tab::class.java)
tabsCursor.moveToFirst()
val values = LongSparseArray<ContentValues>()
while (!tabsCursor.isAfterLast) {
val tab = indices.newObject(tabsCursor)
val arguments = tab.arguments
if (arguments != null) {
val accountId = arguments.accountId
val keys = arguments.accountKeys
if (TextUtils.equals(accountKey.id, accountId) && keys == null) {
arguments.accountKeys = arrayOf(accountKey)
values.put(tab.id, creator.create(tab))
try {
while (!tabsCursor.isAfterLast) {
val tab = indices.newObject(tabsCursor)
val arguments = tab.arguments
if (arguments != null) {
val accountId = arguments.accountId
val keys = arguments.accountKeys
if (TextUtils.equals(accountKey.id, accountId) && keys == null) {
arguments.accountKeys = arrayOf(accountKey)
values.put(tab.id, creator.create(tab))
}
}
tabsCursor.moveToNext()
}
tabsCursor.moveToNext()
} catch (e: IOException) {
// Ignore
}
for (i in 0 until values.size()) {
val where = Expression.equals(Tabs._ID, values.keyAt(i)).sql
resolver.update(Tabs.CONTENT_URI, values.valueAt(i), where, null)
}
} catch (e: IOException) {
// Ignore
} finally {
tabsCursor.close()
}
}
}

View File

@ -40,6 +40,7 @@ import org.mariotaku.twidere.TwidereConstants.QUERY_PARAM_SHOW_NOTIFICATION
import org.mariotaku.twidere.annotation.AccountType
import org.mariotaku.twidere.extension.model.*
import org.mariotaku.twidere.extension.model.api.toParcelable
import org.mariotaku.twidere.extension.queryCount
import org.mariotaku.twidere.model.*
import org.mariotaku.twidere.model.ParcelableMessageConversation.ConversationType
import org.mariotaku.twidere.model.event.GetMessagesTaskEvent
@ -138,9 +139,8 @@ class GetMessagesTask(
val sincePagination = param.pagination?.get(accountsCount + index) as? SinceMaxPagination
val firstFetch by lazy {
val noConversationsBefore = DataStoreUtils.queryCount(context.contentResolver,
Conversations.CONTENT_URI, Expression.equalsArgs(Conversations.ACCOUNT_KEY).sql,
arrayOf(accountKey.toString())) <= 0
val noConversationsBefore = context.contentResolver.queryCount(Conversations.CONTENT_URI,
Expression.equalsArgs(Conversations.ACCOUNT_KEY).sql, arrayOf(accountKey.toString())) <= 0
return@lazy noConversationsBefore
}

View File

@ -20,11 +20,9 @@
package org.mariotaku.twidere.task.twitter.message
import android.accounts.AccountManager
import android.annotation.SuppressLint
import android.content.ContentResolver
import android.content.ContentValues
import android.content.Context
import org.mariotaku.library.objectcursor.ObjectCursor
import org.mariotaku.microblog.library.MicroBlog
import org.mariotaku.microblog.library.MicroBlogException
import org.mariotaku.sqliteqb.library.Expression
@ -33,6 +31,7 @@ import org.mariotaku.twidere.annotation.AccountType
import org.mariotaku.twidere.extension.model.isOfficial
import org.mariotaku.twidere.extension.model.newMicroBlogInstance
import org.mariotaku.twidere.extension.model.timestamp
import org.mariotaku.twidere.extension.queryOne
import org.mariotaku.twidere.model.AccountDetails
import org.mariotaku.twidere.model.ParcelableMessage
import org.mariotaku.twidere.model.ParcelableMessageConversation
@ -119,19 +118,8 @@ class MarkMessageReadTask(
val where = Expression.and(Expression.equalsArgs(Messages.ACCOUNT_KEY),
Expression.equalsArgs(Messages.CONVERSATION_ID)).sql
val whereArgs = arrayOf(accountKey.toString(), conversationId)
@SuppressLint("Recycle")
val cur = query(Messages.CONTENT_URI, Messages.COLUMNS,
where, whereArgs, OrderBy(Messages.LOCAL_TIMESTAMP, false).sql) ?: return null
@Suppress("ConvertTryFinallyToUseCall")
try {
if (cur.moveToFirst()) {
val indices = ObjectCursor.indicesFrom(cur, ParcelableMessage::class.java)
return indices.newObject(cur)
}
} finally {
cur.close()
}
return null
return queryOne(Messages.CONTENT_URI, Messages.COLUMNS, where, whereArgs,
OrderBy(Messages.LOCAL_TIMESTAMP, false).sql, ParcelableMessage::class.java)
}
private val TwitterOfficialConversationExtras.maxReadEvent: Pair<String, Long>?

View File

@ -2,7 +2,6 @@ package org.mariotaku.twidere.text
import android.graphics.Canvas
import android.graphics.Paint
import android.text.TextPaint
import android.text.style.ReplacementSpan
/**

View File

@ -4,10 +4,12 @@ import android.accounts.Account
import android.accounts.AccountManager
import android.database.sqlite.SQLiteDatabase
import org.mariotaku.ktextension.HexColorFormat
import org.mariotaku.ktextension.queryReference
import org.mariotaku.ktextension.toHexColor
import org.mariotaku.library.objectcursor.ObjectCursor
import org.mariotaku.twidere.TwidereConstants.*
import org.mariotaku.twidere.annotation.AuthTypeInt
import org.mariotaku.twidere.extension.model.component1
import org.mariotaku.twidere.model.ParcelableCredentials
import org.mariotaku.twidere.model.ParcelableUser
import org.mariotaku.twidere.model.UserKey
@ -24,10 +26,9 @@ import org.mariotaku.twidere.provider.TwidereDataStore.Accounts
*/
@Suppress("deprecation")
fun migrateAccounts(am: AccountManager, db: SQLiteDatabase) {
val cur = db.query(Accounts.TABLE_NAME, Accounts.COLUMNS, null, null,
null, null, null) ?: return
@Suppress("ConvertTryFinallyToUseCall")
try {
db.queryReference(Accounts.TABLE_NAME, Accounts.COLUMNS, null, null,
null, null, null).use { (cur) ->
if (cur == null) return
val indices = ObjectCursor.indicesFrom(cur, ParcelableCredentials::class.java)
cur.moveToFirst()
while (!cur.isAfterLast) {
@ -56,8 +57,6 @@ fun migrateAccounts(am: AccountManager, db: SQLiteDatabase) {
am.setAuthToken(account, ACCOUNT_AUTH_TOKEN_TYPE, JsonSerializer.serialize(credentials.toCredentials()))
cur.moveToNext()
}
} finally {
cur.close()
}
}

View File

@ -19,6 +19,8 @@ import org.mariotaku.sqliteqb.library.*
import org.mariotaku.sqliteqb.library.Columns.Column
import org.mariotaku.twidere.constant.filterPossibilitySensitiveStatusesKey
import org.mariotaku.twidere.constant.filterUnavailableQuoteStatusesKey
import org.mariotaku.twidere.extension.model.component1
import org.mariotaku.twidere.extension.queryReference
import org.mariotaku.twidere.extension.rawQuery
import org.mariotaku.twidere.model.Draft
import org.mariotaku.twidere.model.ParcelableActivity
@ -196,21 +198,23 @@ fun <T : ParcelableStatus> ContentResolver.updateStatusInfo(uris: Array<Uri>, co
@WorkerThread
fun <T> ContentResolver.updateItems(uri: Uri, columns: Array<String>?, where: String?,
whereArgs: Array<String>?, cls: Class<T>, action: (T) -> T) {
val c = query(uri, columns, where, whereArgs, null) ?: return
val values = LongSparseArray<ContentValues>()
try {
queryReference(uri, columns, where, whereArgs, null).use { (c) ->
if (c == null) return
val ci = ObjectCursor.indicesFrom(c, cls)
val vc = ObjectCursor.valuesCreatorFrom(cls)
c.moveToFirst()
while (!c.isAfterLast) {
val item = action(ci.newObject(c))
values.put(c.getLong(ci[BaseColumns._ID]), vc.create(item))
c.moveToNext()
try {
while (!c.isAfterLast) {
val item = action(ci.newObject(c))
values.put(c.getLong(ci[BaseColumns._ID]), vc.create(item))
c.moveToNext()
}
} catch (e: IOException) {
return
}
} catch (e: IOException) {
return
} finally {
c.close()
}
for (i in 0 until values.size()) {
val updateWhere = Expression.equals(BaseColumns._ID, values.keyAt(i)).sql

View File

@ -48,6 +48,9 @@ import org.mariotaku.twidere.constant.databaseItemLimitKey
import org.mariotaku.twidere.extension.model.*
import org.mariotaku.twidere.extension.model.api.mastodon.toParcelable
import org.mariotaku.twidere.extension.model.api.toParcelable
import org.mariotaku.twidere.extension.queryCount
import org.mariotaku.twidere.extension.queryOne
import org.mariotaku.twidere.extension.queryReference
import org.mariotaku.twidere.extension.rawQuery
import org.mariotaku.twidere.model.*
import org.mariotaku.twidere.model.tab.extra.HomeTabExtras
@ -267,27 +270,27 @@ object DataStoreUtils {
fun getStatusCount(context: Context, uri: Uri, accountKey: UserKey): Int {
val where = Expression.equalsArgs(AccountSupportColumns.ACCOUNT_KEY).sql
val whereArgs = arrayOf(accountKey.toString())
return queryCount(context.contentResolver, uri, where, whereArgs)
return context.contentResolver.queryCount(uri, where, whereArgs)
}
fun getActivitiesCount(context: Context, uri: Uri,
accountKey: UserKey): Int {
val where = Expression.equalsArgs(AccountSupportColumns.ACCOUNT_KEY).sql
return queryCount(context.contentResolver, uri, where, arrayOf(accountKey.toString()))
return context.contentResolver.queryCount(uri, where, arrayOf(accountKey.toString()))
}
@SuppressLint("Recycle")
fun getFilteredUserKeys(context: Context?): Array<UserKey> {
if (context == null) return emptyArray()
val resolver = context.contentResolver
val projection = arrayOf(Filters.Users.USER_KEY)
return resolver.query(Filters.Users.CONTENT_URI, projection, null, null, null)?.useCursor { cur ->
return@useCursor Array(cur.count) { i ->
return resolver.queryReference(Filters.Users.CONTENT_URI, projection, null,
null, null).use { (cur) ->
if (cur == null) return@use emptyArray()
return@use Array(cur.count) { i ->
cur.moveToPosition(i)
UserKey.valueOf(cur.getString(0))
}
} ?: emptyArray()
}
}
fun getAccountDisplayName(context: Context, accountKey: UserKey, nameFirst: Boolean): String? {
@ -353,7 +356,7 @@ object DataStoreUtils {
}
val selection = Expression.and(*expressions.toTypedArray())
return queryCount(context.contentResolver, uri, selection.sql, expressionArgs.toTypedArray())
return context.contentResolver.queryCount(uri, selection.sql, expressionArgs.toTypedArray())
}
fun getActivitiesCount(context: Context, uri: Uri, compareColumn: String,
@ -370,7 +373,7 @@ object DataStoreUtils {
)
val whereArgs = arrayListOf<String>()
keys.mapTo(whereArgs) { it.toString() }
return queryCount(context.contentResolver, uri, selection.sql, whereArgs.toTypedArray())
return context.contentResolver.queryCount(uri, selection.sql, whereArgs.toTypedArray())
}
fun getActivitiesCount(context: Context, uri: Uri,
@ -394,8 +397,8 @@ object DataStoreUtils {
val resolver = context.contentResolver
if (followingOnly) {
val projection = arrayOf(Activities.SOURCES)
val cur = resolver.query(uri, projection, selection.sql, selectionArgs, null) ?: return -1
cur.useCursor { cur ->
return resolver.queryReference(uri, projection, selection.sql, selectionArgs, null).use { (cur) ->
if (cur == null) return@use 0
var total = 0
cur.moveToFirst()
while (!cur.isAfterLast) {
@ -418,10 +421,10 @@ object DataStoreUtils {
}
cur.moveToNext()
}
return total
return@use total
}
}
return queryCount(resolver, uri, selection.sql, selectionArgs)
return resolver.queryCount(uri, selection.sql, selectionArgs)
}
fun getTableId(uri: Uri?): Int {
@ -558,7 +561,8 @@ object DataStoreUtils {
return AccountUtils.getAccounts(AccountManager.get(context)).isNotEmpty()
}
@Synchronized fun cleanDatabasesByItemLimit(context: Context) {
@Synchronized
fun cleanDatabasesByItemLimit(context: Context) {
val resolver = context.contentResolver
val preferences = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE)
val itemLimit = preferences[databaseItemLimitKey]
@ -619,17 +623,7 @@ object DataStoreUtils {
fun isFilteringUser(context: Context, userKey: String): Boolean {
val cr = context.contentResolver
val where = Expression.equalsArgs(Filters.Users.USER_KEY)
val c = cr.query(Filters.Users.CONTENT_URI, arrayOf(SQLFunctions.COUNT()),
where.sql, arrayOf(userKey), null) ?: return false
@Suppress("ConvertTryFinallyToUseCall")
try {
if (c.moveToFirst()) {
return c.getLong(0) > 0
}
} finally {
c.close()
}
return false
return cr.queryCount(Filters.Users.CONTENT_URI, where.sql, arrayOf(userKey)) > 0
}
private fun <T> getObjectFieldArray(context: Context, uri: Uri, keys: Array<UserKey?>,
@ -797,9 +791,10 @@ object DataStoreUtils {
fun prepareDatabase(context: Context) {
val cr = context.contentResolver
val cursor = cr.query(TwidereDataStore.CONTENT_URI_DATABASE_PREPARE, null, null,
null, null) ?: return
cursor.close()
cr.queryReference(TwidereDataStore.CONTENT_URI_DATABASE_PREPARE, null, null,
null, null).use {
// Just try to initialize database
}
}
internal interface FieldArrayCreator<T, I> {
@ -810,20 +805,6 @@ object DataStoreUtils {
fun assign(array: T, arrayIdx: Int, cur: Cursor, colIdx: I)
}
fun queryCount(cr: ContentResolver, uri: Uri, selection: String?, selectionArgs: Array<String>?): Int {
val projection = arrayOf(SQLFunctions.COUNT())
val cur = cr.query(uri, projection, selection, selectionArgs, null) ?: return -1
@Suppress("ConvertTryFinallyToUseCall")
try {
if (cur.moveToFirst()) {
return cur.getInt(0)
}
return -1
} finally {
cur.close()
}
}
fun getInteractionsCount(context: Context, extraArgs: Bundle?, accountKeys: Array<UserKey>,
since: Long, sinceColumn: String): Int {
var extraWhere: Expression? = null
@ -905,23 +886,15 @@ object DataStoreUtils {
accountKey: UserKey,
statusId: String): ParcelableStatus? {
val resolver = context.contentResolver
var status: ParcelableStatus? = null
val where = Expression.and(Expression.equalsArgs(Statuses.ACCOUNT_KEY),
Expression.equalsArgs(Statuses.ID)).sql
val whereArgs = arrayOf(accountKey.toString(), statusId)
for (uri in DataStoreUtils.STATUSES_URIS) {
val cur = resolver.query(uri, Statuses.COLUMNS, where, whereArgs, null) ?: continue
@Suppress("ConvertTryFinallyToUseCall")
try {
if (cur.moveToFirst()) {
val indices = ObjectCursor.indicesFrom(cur, ParcelableStatus::class.java)
status = indices.newObject(cur)
}
} finally {
cur.close()
}
val status = resolver.queryOne(uri, Statuses.COLUMNS, where, whereArgs, null,
ParcelableStatus::class.java)
if (status != null) return status
}
return status
return null
}
@ -958,17 +931,8 @@ object DataStoreUtils {
val where = Expression.and(Expression.equalsArgs(Conversations.ACCOUNT_KEY),
Expression.equalsArgs(Conversations.CONVERSATION_ID)).sql
val whereArgs = arrayOf(accountKey.toString(), conversationId)
val cur = resolver.query(Conversations.CONTENT_URI, Conversations.COLUMNS, where, whereArgs, null) ?: return null
@Suppress("ConvertTryFinallyToUseCall")
try {
if (cur.moveToFirst()) {
val indices = ObjectCursor.indicesFrom(cur, ParcelableMessageConversation::class.java)
return indices.newObject(cur)
}
} finally {
cur.close()
}
return null
return resolver.queryOne(Conversations.CONTENT_URI, Conversations.COLUMNS, where, whereArgs,
null, ParcelableMessageConversation::class.java)
}

View File

@ -19,7 +19,6 @@
package org.mariotaku.twidere.util.api
import android.os.Build
import org.mariotaku.ktextension.bcp47Tag
import org.mariotaku.restfu.http.MultiValueMap
import org.mariotaku.twidere.extension.restfu.contains

View File

@ -46,6 +46,7 @@ import org.mariotaku.mediaviewer.library.FileCache
import org.mariotaku.mediaviewer.library.MediaDownloader
import org.mariotaku.restfu.http.RestHttpClient
import org.mariotaku.twidere.Constants
import org.mariotaku.twidere.app.TwidereApplication
import org.mariotaku.twidere.constant.SharedPreferenceConstants.KEY_CACHE_SIZE_LIMIT
import org.mariotaku.twidere.constant.autoRefreshCompatibilityModeKey
import org.mariotaku.twidere.extension.model.load
@ -193,8 +194,7 @@ class ApplicationModule(private val context: Context) {
@Provides
@Singleton
fun mediaDownloader(preferences: SharedPreferences, client: RestHttpClient,
thumbor: ThumborWrapper): MediaDownloader {
fun mediaDownloader(client: RestHttpClient, thumbor: ThumborWrapper): MediaDownloader {
return TwidereMediaDownloader(context, client, thumbor)
}
@ -367,15 +367,12 @@ class ApplicationModule(private val context: Context) {
companion object {
private var instance: ApplicationModule? = null
fun get(context: Context): ApplicationModule {
return instance ?: run {
val module = ApplicationModule(context.applicationContext)
instance = module
return@run module
val appContext = context.applicationContext
if (appContext is TwidereApplication) {
return appContext.applicationModule
}
return ApplicationModule(appContext)
}
}
}

View File

@ -48,6 +48,7 @@ import org.mariotaku.twidere.constant.iWantMyStarsBackKey
import org.mariotaku.twidere.constant.nameFirstKey
import org.mariotaku.twidere.extension.model.*
import org.mariotaku.twidere.extension.model.api.formattedTextWithIndices
import org.mariotaku.twidere.extension.queryOne
import org.mariotaku.twidere.extension.rawQuery
import org.mariotaku.twidere.model.*
import org.mariotaku.twidere.model.notification.NotificationChannelSpec
@ -364,18 +365,8 @@ class ContentNotificationManager(
fun showDraft(draftUri: Uri): Long {
val draftId = draftUri.lastPathSegment.toLongOrNull() ?: return -1
val where = Expression.equals(Drafts._ID, draftId)
val c = context.contentResolver.query(Drafts.CONTENT_URI, Drafts.COLUMNS, where.sql,
null, null) ?: return -1
val i = ObjectCursor.indicesFrom(c, Draft::class.java)
val item: Draft
try {
if (!c.moveToFirst()) return -1
item = i.newObject(c)
} catch (e: IOException) {
return -1
} finally {
c.close()
}
val item = context.contentResolver.queryOne(Drafts.CONTENT_URI, Drafts.COLUMNS, where.sql,
null, null, Draft::class.java) ?: return -1
val title = context.getString(R.string.status_not_updated)
val message = context.getString(R.string.status_not_updated_summary)
val intent = Intent()

View File

@ -1,6 +1,5 @@
package org.mariotaku.twidere.view.holder
import android.graphics.Typeface
import android.support.v4.content.ContextCompat
import android.support.v4.widget.TextViewCompat
import android.support.v7.widget.RecyclerView
@ -8,9 +7,7 @@ import android.support.v7.widget.RecyclerView.ViewHolder
import android.text.SpannableString
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.style.ClickableSpan
import android.text.style.ForegroundColorSpan
import android.text.style.StyleSpan
import android.view.View
import android.view.View.OnClickListener
import android.view.View.OnLongClickListener