diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/TwidereConstants.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/TwidereConstants.java
index eb56565f3..2a48921b3 100644
--- a/twidere.component.common/src/main/java/org/mariotaku/twidere/TwidereConstants.java
+++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/TwidereConstants.java
@@ -73,6 +73,7 @@ public interface TwidereConstants extends SharedPreferenceConstants, IntentConst
String SCHEME_HTTPS = "https";
String SCHEME_CONTENT = ContentResolver.SCHEME_CONTENT;
String SCHEME_TWIDERE = "twidere";
+ String SCHEME_TWIDERE_SETTINGS = "twidere.settings";
String SCHEME_DATA = "data";
String PROTOCOL_HTTP = SCHEME_HTTP + "://";
diff --git a/twidere/build.gradle b/twidere/build.gradle
index 0c6604f64..7d8fd39c1 100644
--- a/twidere/build.gradle
+++ b/twidere/build.gradle
@@ -176,7 +176,7 @@ dependencies {
compile 'com.github.mariotaku.MediaViewerLibrary:base:0.9.23'
compile 'com.github.mariotaku.MediaViewerLibrary:subsample-image-view:0.9.23'
- compile 'com.github.mariotaku:SQLiteQB:0.9.10'
+ compile 'com.github.mariotaku:SQLiteQB:0.9.12'
compile "com.github.mariotaku.ObjectCursor:core:${libVersions['ObjectCursor']}"
compile 'com.github.mariotaku:MultiValueSwitch:0.9.7'
compile 'com.github.mariotaku:AbstractTask:0.9.4'
diff --git a/twidere/src/main/AndroidManifest.xml b/twidere/src/main/AndroidManifest.xml
index e17c98c5d..7d58c7195 100644
--- a/twidere/src/main/AndroidManifest.xml
+++ b/twidere/src/main/AndroidManifest.xml
@@ -296,10 +296,17 @@
android:windowSoftInputMode="adjustResize">
-
+
+
+
+
+
+
+
+
{
- val intent = Intent(this, SettingsActivity::class.java)
- intent.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT, CustomTabsFragment::class.java.name)
- intent.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT_TITLE, R.string.tabs)
- startActivityForResult(intent, REQUEST_SETTINGS)
+ startActivityForResult(IntentUtils.settings("tabs"), REQUEST_SETTINGS)
}
drawerToggleButton -> {
if (homeMenu.isDrawerOpen(GravityCompat.START) || homeMenu.isDrawerOpen(GravityCompat.END)) {
@@ -933,6 +929,18 @@ class HomeActivity : BaseActivity(), OnClickListener, OnPageChangeListener, Supp
publishProgress(TabBadge(i, count))
result.put(i, count)
}
+ CustomTabType.DIRECT_MESSAGES -> {
+ val accountKeys = Utils.getAccountKeys(context, spec.args) ?: activatedKeys
+ val projection = (Conversations.COLUMNS + Conversations.UNREAD_COUNT).map {
+ TwidereQueryBuilder.mapConversationsProjection(it)
+ }.toTypedArray()
+ val count = context.contentResolver.getUnreadMessagesEntriesCursor(projection,
+ accountKeys)?.useCursor { cur ->
+ return@useCursor cur.count
+ } ?: -1
+ publishProgress(TabBadge(i, count))
+ result.put(i, count)
+ }
else -> {
publishProgress(TabBadge(i, -1))
}
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 867559076..ccd9f7421 100644
--- a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/SettingsActivity.kt
+++ b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/SettingsActivity.kt
@@ -32,7 +32,6 @@ import android.support.v7.app.AlertDialog
import android.support.v7.preference.Preference
import android.support.v7.preference.PreferenceFragmentCompat
import android.support.v7.preference.PreferenceFragmentCompat.OnPreferenceStartFragmentCallback
-import android.text.TextUtils
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.View
@@ -90,7 +89,7 @@ class SettingsActivity : BaseActivity(), OnItemClickListener, OnPreferenceStartF
entriesList.onItemClickListener = this
if (savedInstanceState == null) {
- val initialTag = intent.getStringExtra(EXTRA_INITIAL_TAG)
+ val initialTag = intent.data?.path
var initialItem = -1
var firstEntry = -1
for (i in 0 until entriesAdapter.count) {
@@ -99,7 +98,7 @@ class SettingsActivity : BaseActivity(), OnItemClickListener, OnPreferenceStartF
if (firstEntry == -1) {
firstEntry = i
}
- if (TextUtils.equals(initialTag, entry.tag)) {
+ if (initialTag == entry.tag) {
initialItem = i
break
}
@@ -415,8 +414,6 @@ class SettingsActivity : BaseActivity(), OnItemClickListener, OnPreferenceStartF
companion object {
- val EXTRA_INITIAL_TAG = "initial_tag"
-
private val RESULT_SETTINGS_CHANGED = 10
fun setShouldRecreate(activity: Activity) {
diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/SignInActivity.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/SignInActivity.kt
index abde1ac1b..41e170635 100644
--- a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/SignInActivity.kt
+++ b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/SignInActivity.kt
@@ -254,8 +254,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher, APIEditorDi
R.id.settings -> {
if (signInTask != null && signInTask!!.status == AsyncTask.Status.RUNNING)
return false
- val intent = Intent(this, SettingsActivity::class.java)
- startActivity(intent)
+ startActivity(IntentUtils.settings())
}
R.id.edit_api -> {
if (signInTask != null && signInTask!!.status == AsyncTask.Status.RUNNING)
diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AccountsDashboardFragment.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AccountsDashboardFragment.kt
index 47ec06e1a..7275e4b1a 100644
--- a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AccountsDashboardFragment.kt
+++ b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AccountsDashboardFragment.kt
@@ -581,7 +581,7 @@ class AccountsDashboardFragment : BaseFragment(), LoaderCallbacks,
closeAccountsDrawer()
}
R.id.settings -> {
- val intent = Intent(activity, SettingsActivity::class.java)
+ val intent = IntentUtils.settings()
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
startActivityForResult(intent, REQUEST_SETTINGS)
closeAccountsDrawer()
diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/service/StreamingService.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/service/StreamingService.kt
index b6a94b27d..4b7069830 100644
--- a/twidere/src/main/kotlin/org/mariotaku/twidere/service/StreamingService.kt
+++ b/twidere/src/main/kotlin/org/mariotaku/twidere/service/StreamingService.kt
@@ -23,7 +23,6 @@ import org.mariotaku.microblog.library.twitter.model.DirectMessage
import org.mariotaku.microblog.library.twitter.model.Status
import org.mariotaku.twidere.R
import org.mariotaku.twidere.TwidereConstants.LOGTAG
-import org.mariotaku.twidere.activity.SettingsActivity
import org.mariotaku.twidere.annotation.AccountType
import org.mariotaku.twidere.constant.streamingNonMeteredNetworkKey
import org.mariotaku.twidere.constant.streamingPowerSavingKey
@@ -40,6 +39,7 @@ import org.mariotaku.twidere.task.twitter.GetActivitiesAboutMeTask
import org.mariotaku.twidere.task.twitter.message.GetMessagesTask
import org.mariotaku.twidere.util.DataStoreUtils
import org.mariotaku.twidere.util.DebugLog
+import org.mariotaku.twidere.util.IntentUtils
import org.mariotaku.twidere.util.Utils
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
import org.mariotaku.twidere.util.streaming.TwitterTimelineStreamCallback
@@ -140,7 +140,7 @@ class StreamingService : BaseService() {
}
private fun showNotification() {
- val intent = Intent(this, SettingsActivity::class.java)
+ val intent = IntentUtils.settings("streaming")
val contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
val contentTitle = getString(R.string.app_name)
val contentText = getString(R.string.timeline_streaming_running)
diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/util/ContentNotificationManager.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/util/ContentNotificationManager.kt
index bc715cd9e..862322233 100644
--- a/twidere/src/main/kotlin/org/mariotaku/twidere/util/ContentNotificationManager.kt
+++ b/twidere/src/main/kotlin/org/mariotaku/twidere/util/ContentNotificationManager.kt
@@ -48,8 +48,9 @@ import org.mariotaku.twidere.extension.model.notificationDisabled
import org.mariotaku.twidere.extension.rawQuery
import org.mariotaku.twidere.model.*
import org.mariotaku.twidere.model.util.ParcelableActivityUtils
-import org.mariotaku.twidere.provider.TwidereDataStore.*
+import org.mariotaku.twidere.provider.TwidereDataStore.Activities
import org.mariotaku.twidere.provider.TwidereDataStore.Messages.Conversations
+import org.mariotaku.twidere.provider.TwidereDataStore.Statuses
import org.mariotaku.twidere.receiver.NotificationReceiver
import org.mariotaku.twidere.util.database.FilterQueryBuilder
import org.oshkimaadziig.george.androidutils.SpanFormatter
@@ -257,30 +258,14 @@ class ContentNotificationManager(
val projection = (Conversations.COLUMNS + Conversations.UNREAD_COUNT).map {
TwidereQueryBuilder.mapConversationsProjection(it)
}.toTypedArray()
- val qb = SQLQueryBuilder.select(Columns(*projection))
- qb.from(Table(Conversations.TABLE_NAME))
- qb.join(Join(false, Join.Operation.LEFT_OUTER, Table(Messages.TABLE_NAME),
- Expression.equals(
- Column(Table(Conversations.TABLE_NAME), Conversations.CONVERSATION_ID),
- Column(Table(Messages.TABLE_NAME), Messages.CONVERSATION_ID)
- )
- ))
- qb.where(Expression.and(
- Expression.equalsArgs(Column(Table(Conversations.TABLE_NAME), Conversations.ACCOUNT_KEY)),
- Expression.lesserThan(Column(Table(Conversations.TABLE_NAME), Conversations.LAST_READ_TIMESTAMP),
- Column(Table(Conversations.TABLE_NAME), Conversations.LOCAL_TIMESTAMP))
- ))
- qb.groupBy(Column(Table(Messages.TABLE_NAME), Messages.CONVERSATION_ID))
- qb.orderBy(OrderBy(arrayOf(Conversations.LOCAL_TIMESTAMP, Conversations.SORT_ID), booleanArrayOf(false, false)))
- val selectionArgs = arrayOf(accountKey.toString())
- val cur = cr.rawQuery(qb.buildSQL(), selectionArgs) ?: return
+ val cur = cr.getUnreadMessagesEntriesCursor(projection, arrayOf(accountKey)) ?: return
try {
if (cur.isEmpty) return
val indices = ObjectCursor.indicesFrom(cur, ParcelableMessageConversation::class.java)
var messageSum: Int = 0
- cur.forEachRow { cur, pos ->
+ cur.forEachRow { cur, _ ->
messageSum += cur.getInt(indices[Conversations.UNREAD_COUNT])
return@forEachRow true
}
@@ -321,6 +306,7 @@ class ContentNotificationManager(
}
}
+
/**
* @param limit -1 for no limit
* @return Remaining count, -1 if no rows present
diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/util/DataStoreFunctions.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/util/DataStoreFunctions.kt
index 4d1440428..44bc048b3 100644
--- a/twidere/src/main/kotlin/org/mariotaku/twidere/util/DataStoreFunctions.kt
+++ b/twidere/src/main/kotlin/org/mariotaku/twidere/util/DataStoreFunctions.kt
@@ -5,21 +5,26 @@ import android.content.ContentResolver
import android.content.ContentValues
import android.content.Context
import android.content.SharedPreferences
+import android.database.Cursor
import android.net.Uri
import android.support.annotation.WorkerThread
import android.support.v4.util.LongSparseArray
import org.mariotaku.kpreferences.get
+import org.mariotaku.ktextension.toStringArray
import org.mariotaku.ktextension.useCursor
import org.mariotaku.library.objectcursor.ObjectCursor
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.rawQuery
import org.mariotaku.twidere.model.Draft
import org.mariotaku.twidere.model.ParcelableActivity
import org.mariotaku.twidere.model.ParcelableStatus
import org.mariotaku.twidere.model.ParcelableStatus.FilterFlags
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.provider.TwidereDataStore.*
+import org.mariotaku.twidere.provider.TwidereDataStore.Messages.Conversations
import org.mariotaku.twidere.util.DataStoreUtils.ACTIVITIES_URIS
import java.io.IOException
@@ -31,43 +36,43 @@ fun buildStatusFilterWhereClause(preferences: SharedPreferences,
table: String,
extraSelection: Expression?): Expression {
val filteredUsersQuery = SQLQueryBuilder
- .select(Columns.Column(Table(Filters.Users.TABLE_NAME), Filters.Users.USER_KEY))
+ .select(Column(Table(Filters.Users.TABLE_NAME), Filters.Users.USER_KEY))
.from(Tables(Filters.Users.TABLE_NAME))
.build()
val filteredUsersWhere = Expression.or(
- Expression.`in`(Columns.Column(Table(table), Statuses.USER_KEY), filteredUsersQuery),
- Expression.`in`(Columns.Column(Table(table), Statuses.RETWEETED_BY_USER_KEY), filteredUsersQuery),
- Expression.`in`(Columns.Column(Table(table), Statuses.QUOTED_USER_KEY), filteredUsersQuery)
+ Expression.`in`(Column(Table(table), Statuses.USER_KEY), filteredUsersQuery),
+ Expression.`in`(Column(Table(table), Statuses.RETWEETED_BY_USER_KEY), filteredUsersQuery),
+ Expression.`in`(Column(Table(table), Statuses.QUOTED_USER_KEY), filteredUsersQuery)
)
val filteredIdsQueryBuilder = SQLQueryBuilder
- .select(Columns.Column(Table(table), Statuses._ID))
+ .select(Column(Table(table), Statuses._ID))
.from(Tables(table))
.where(filteredUsersWhere)
.union()
- .select(Columns(Columns.Column(Table(table), Statuses._ID)))
+ .select(Columns(Column(Table(table), Statuses._ID)))
.from(Tables(table, Filters.Sources.TABLE_NAME))
.where(Expression.or(
- Expression.likeRaw(Columns.Column(Table(table), Statuses.SOURCE),
+ Expression.likeRaw(Column(Table(table), Statuses.SOURCE),
"'%>'||" + Filters.Sources.TABLE_NAME + "." + Filters.Sources.VALUE + "||'%'"),
- Expression.likeRaw(Columns.Column(Table(table), Statuses.QUOTED_SOURCE),
+ Expression.likeRaw(Column(Table(table), Statuses.QUOTED_SOURCE),
"'%>'||" + Filters.Sources.TABLE_NAME + "." + Filters.Sources.VALUE + "||'%'")
))
.union()
- .select(Columns(Columns.Column(Table(table), Statuses._ID)))
+ .select(Columns(Column(Table(table), Statuses._ID)))
.from(Tables(table, Filters.Keywords.TABLE_NAME))
.where(Expression.or(
- Expression.likeRaw(Columns.Column(Table(table), Statuses.TEXT_PLAIN),
+ Expression.likeRaw(Column(Table(table), Statuses.TEXT_PLAIN),
"'%'||" + Filters.Keywords.TABLE_NAME + "." + Filters.Keywords.VALUE + "||'%'"),
- Expression.likeRaw(Columns.Column(Table(table), Statuses.QUOTED_TEXT_PLAIN),
+ Expression.likeRaw(Column(Table(table), Statuses.QUOTED_TEXT_PLAIN),
"'%'||" + Filters.Keywords.TABLE_NAME + "." + Filters.Keywords.VALUE + "||'%'")
))
.union()
- .select(Columns(Columns.Column(Table(table), Statuses._ID)))
+ .select(Columns(Column(Table(table), Statuses._ID)))
.from(Tables(table, Filters.Links.TABLE_NAME))
.where(Expression.or(
- Expression.likeRaw(Columns.Column(Table(table), Statuses.SPANS),
+ Expression.likeRaw(Column(Table(table), Statuses.SPANS),
"'%'||" + Filters.Links.TABLE_NAME + "." + Filters.Links.VALUE + "||'%'"),
- Expression.likeRaw(Columns.Column(Table(table), Statuses.QUOTED_SPANS),
+ Expression.likeRaw(Column(Table(table), Statuses.QUOTED_SPANS),
"'%'||" + Filters.Links.TABLE_NAME + "." + Filters.Links.VALUE + "||'%'")
))
var filterFlags: Long = 0
@@ -81,9 +86,9 @@ fun buildStatusFilterWhereClause(preferences: SharedPreferences,
val filterExpression = Expression.or(
Expression.and(
Expression("(" + Statuses.FILTER_FLAGS + " & " + filterFlags + ") == 0"),
- Expression.notIn(Columns.Column(Table(table), Statuses._ID), filteredIdsQueryBuilder.build())
+ Expression.notIn(Column(Table(table), Statuses._ID), filteredIdsQueryBuilder.build())
),
- Expression.equals(Columns.Column(Table(table), Statuses.IS_GAP), 1)
+ Expression.equals(Column(Table(table), Statuses.IS_GAP), 1)
)
if (extraSelection != null) {
return Expression.and(filterExpression, extraSelection)
@@ -133,14 +138,14 @@ fun deleteActivityStatus(cr: ContentResolver, accountKey: UserKey,
val updateWhereArgs: Array
if (host != null) {
deleteWhere = Expression.and(
- Expression.likeRaw(Columns.Column(Activities.ACCOUNT_KEY), "'%@'||?"),
+ Expression.likeRaw(Column(Activities.ACCOUNT_KEY), "'%@'||?"),
Expression.or(
Expression.equalsArgs(Activities.STATUS_ID),
Expression.equalsArgs(Activities.STATUS_RETWEET_ID)
)).sql
deleteWhereArgs = arrayOf(host, statusId, statusId)
updateWhere = Expression.and(
- Expression.likeRaw(Columns.Column(Activities.ACCOUNT_KEY), "'%@'||?"),
+ Expression.likeRaw(Column(Activities.ACCOUNT_KEY), "'%@'||?"),
Expression.equalsArgs(Activities.STATUS_MY_RETWEET_ID)
).sql
updateWhereArgs = arrayOf(host, statusId)
@@ -219,3 +224,25 @@ fun updateActivity(cr: ContentResolver, uri: Uri,
cr.update(uri, values.valueAt(i), updateWhere, updateWhereArgs)
}
}
+
+fun ContentResolver.getUnreadMessagesEntriesCursor(projection: Array, accountKeys: Array): Cursor? {
+ val qb = SQLQueryBuilder.select(Columns(*projection))
+ qb.from(Table(Conversations.TABLE_NAME))
+ qb.join(Join(false, Join.Operation.LEFT_OUTER, Table(Messages.TABLE_NAME),
+ Expression.equals(
+ Column(Table(Conversations.TABLE_NAME), Conversations.CONVERSATION_ID),
+ Column(Table(Messages.TABLE_NAME), Messages.CONVERSATION_ID)
+ )
+ ))
+ qb.where(Expression.and(
+ Expression.inArgs(Column(Table(Conversations.TABLE_NAME), Conversations.ACCOUNT_KEY),
+ accountKeys.size),
+ Expression.lesserThan(Column(Table(Conversations.TABLE_NAME), Conversations.LAST_READ_TIMESTAMP),
+ Column(Table(Conversations.TABLE_NAME), Conversations.LOCAL_TIMESTAMP))
+ ))
+ qb.groupBy(Column(Table(Messages.TABLE_NAME), Messages.CONVERSATION_ID))
+ qb.orderBy(OrderBy(arrayOf(Column(Table(Conversations.TABLE_NAME), Conversations.LOCAL_TIMESTAMP),
+ Column(Table(Conversations.TABLE_NAME), Conversations.SORT_ID)), booleanArrayOf(false, false)))
+ val selectionArgs = accountKeys.toStringArray()
+ return rawQuery(qb.buildSQL(), selectionArgs)
+}
\ No newline at end of file
diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/util/DataStoreUtils.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/util/DataStoreUtils.kt
index addf17ca2..02eeaa66e 100644
--- a/twidere/src/main/kotlin/org/mariotaku/twidere/util/DataStoreUtils.kt
+++ b/twidere/src/main/kotlin/org/mariotaku/twidere/util/DataStoreUtils.kt
@@ -912,4 +912,6 @@ object DataStoreUtils {
return null
}
+
+
}
diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/util/IntentUtils.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/util/IntentUtils.kt
index 13730b5cd..674cdcfe9 100644
--- a/twidere/src/main/kotlin/org/mariotaku/twidere/util/IntentUtils.kt
+++ b/twidere/src/main/kotlin/org/mariotaku/twidere/util/IntentUtils.kt
@@ -634,6 +634,16 @@ object IntentUtils {
context.startActivity(intent)
}
+ fun settings(initialTag: String? = null): Intent {
+ val intent = Intent()
+ val builder = Uri.Builder()
+ builder.scheme(SCHEME_TWIDERE_SETTINGS)
+ builder.authority(initialTag.orEmpty())
+ intent.data = builder.build()
+ intent.`package` = BuildConfig.APPLICATION_ID
+ return intent
+ }
+
fun openProfileEditor(context: Context, accountId: UserKey?) {
val intent = Intent()
val builder = Uri.Builder()