updated ObjectCursor

This commit is contained in:
Mariotaku Lee 2017-03-05 16:08:09 +08:00
parent 7310f10cc5
commit a59035ed55
No known key found for this signature in database
GPG Key ID: 15C10F89D7C33535
42 changed files with 332 additions and 243 deletions

5
.gitignore vendored
View File

@ -28,4 +28,7 @@ Thumbs.db
/private
# Local files
/captures
/captures
# JRE error dumps
hs_err_*.log

View File

@ -37,7 +37,7 @@ subprojects {
SupportLib : '25.2.0',
MariotakuCommons: '0.9.11',
RestFu : '0.9.35',
ObjectCursor : '0.9.13',
ObjectCursor : '0.9.16',
PlayServices : '10.2.0',
MapsUtils : '0.4.4',
Crashlyrics : '2.6.6',

View File

@ -20,6 +20,7 @@
package org.mariotaku.twidere.extension
import android.support.test.runner.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
/**
@ -28,4 +29,9 @@ import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class ViewExtensionsKtTest {
@Test
fun testEmpty() {
}
}

View File

@ -0,0 +1,47 @@
/*
* 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.util
import android.database.MatrixCursor
import android.support.test.runner.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.mariotaku.library.objectcursor.ObjectCursor
import org.mariotaku.twidere.model.FiltersData
import org.mariotaku.twidere.model.ParcelableStatus
/**
* Created by mariotaku on 2017/3/5.
*/
@RunWith(AndroidJUnit4::class)
class ObjectCursorTest {
@Test
fun testSimple() {
val cur = MatrixCursor(emptyArray(), 0)
ObjectCursor.indicesFrom(cur, ParcelableStatus::class.java)
}
@Test
fun testMemberClass() {
val cur = MatrixCursor(emptyArray(), 0)
ObjectCursor.indicesFrom(cur, FiltersData.BaseItem::class.java)
}
}

View File

@ -22,7 +22,6 @@ package org.mariotaku.twidere.loader;
import android.content.Context;
import android.net.Uri;
import org.mariotaku.library.objectcursor.ObjectCursor;
import org.mariotaku.twidere.loader.iface.IExtendedLoader;
/**
@ -30,9 +29,8 @@ import org.mariotaku.twidere.loader.iface.IExtendedLoader;
*/
public class ExtendedObjectCursorLoader<E> extends ObjectCursorLoader<E> implements IExtendedLoader {
public ExtendedObjectCursorLoader(Context context, Class<? extends ObjectCursor.CursorIndices<E>> indicesClass,
Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder, boolean fromUser) {
public ExtendedObjectCursorLoader(Context context, Class<E> indicesClass, Uri uri,
String[] projection, String selection, String[] selectionArgs, String sortOrder, boolean fromUser) {
super(context, indicesClass, uri, projection, selection, selectionArgs, sortOrder);
setFromUser(fromUser);
}

View File

@ -30,7 +30,6 @@ import org.mariotaku.library.objectcursor.ObjectCursor;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.List;
@ -40,7 +39,7 @@ import java.util.List;
public class ObjectCursorLoader<T> extends FixedAsyncTaskLoader<List<T>> {
final ForceLoadContentObserver mObserver;
final Class<? extends ObjectCursor.CursorIndices<T>> mIndicesClass;
final Class<T> mObjectClass;
Uri mUri;
String[] mProjection;
@ -71,17 +70,7 @@ public class ObjectCursorLoader<T> extends FixedAsyncTaskLoader<List<T>> {
@SuppressWarnings("TryWithIdenticalCatches")
@NonNull
private ObjectCursor.CursorIndices<T> createIndices(final Cursor cursor) {
try {
return mIndicesClass.getConstructor(Cursor.class).newInstance(cursor);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
return ObjectCursor.indicesFrom(cursor, mObjectClass);
}
/* Runs on the UI thread */
@ -112,9 +101,9 @@ public class ObjectCursorLoader<T> extends FixedAsyncTaskLoader<List<T>> {
* calls to {@link #setUri(Uri)}, {@link #setSelection(String)}, etc
* to specify the query to perform.
*/
public ObjectCursorLoader(Context context, Class<? extends ObjectCursor.CursorIndices<T>> indicesClass) {
public ObjectCursorLoader(Context context, Class<T> objectClass) {
super(context);
mIndicesClass = indicesClass;
mObjectClass = objectClass;
mObserver = new ForceLoadContentObserver();
}
@ -124,11 +113,10 @@ public class ObjectCursorLoader<T> extends FixedAsyncTaskLoader<List<T>> {
* ContentResolver.query()} for documentation on the meaning of the
* parameters. These will be passed as-is to that call.
*/
public ObjectCursorLoader(Context context, Class<? extends ObjectCursor.CursorIndices<T>> indicesClass,
Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
public ObjectCursorLoader(Context context, Class<T> objectClass, Uri uri, String[] projection,
String selection, String[] selectionArgs, String sortOrder) {
super(context);
mIndicesClass = indicesClass;
mObjectClass = objectClass;
mObserver = new ForceLoadContentObserver();
mUri = uri;
mProjection = projection;

View File

@ -43,13 +43,7 @@ import org.mariotaku.twidere.annotation.Preference;
import org.mariotaku.twidere.annotation.PreferenceType;
import org.mariotaku.twidere.constant.SharedPreferenceConstants;
import org.mariotaku.twidere.model.FiltersData;
import org.mariotaku.twidere.model.FiltersData$BaseItemCursorIndices;
import org.mariotaku.twidere.model.FiltersData$BaseItemValuesCreator;
import org.mariotaku.twidere.model.FiltersData$UserItemCursorIndices;
import org.mariotaku.twidere.model.FiltersData$UserItemValuesCreator;
import org.mariotaku.twidere.model.Tab;
import org.mariotaku.twidere.model.TabCursorIndices;
import org.mariotaku.twidere.model.TabValuesCreator;
import org.mariotaku.twidere.provider.TwidereDataStore.Filters;
import org.mariotaku.twidere.provider.TwidereDataStore.Tabs;
import org.mariotaku.twidere.util.content.ContentResolverUtils;
@ -115,13 +109,13 @@ public class DataImportExportUtils implements Constants {
final ContentResolver cr = context.getContentResolver();
data.setUsers(queryAll(cr, Filters.Users.CONTENT_URI, Filters.Users.COLUMNS,
FiltersData$UserItemCursorIndices.class));
FiltersData.UserItem.class));
data.setKeywords(queryAll(cr, Filters.Keywords.CONTENT_URI, Filters.Keywords.COLUMNS,
FiltersData$BaseItemCursorIndices.class));
FiltersData.BaseItem.class));
data.setSources(queryAll(cr, Filters.Sources.CONTENT_URI, Filters.Sources.COLUMNS,
FiltersData$BaseItemCursorIndices.class));
FiltersData.BaseItem.class));
data.setLinks(queryAll(cr, Filters.Links.CONTENT_URI, Filters.Links.COLUMNS,
FiltersData$BaseItemCursorIndices.class));
FiltersData.BaseItem.class));
exportItem(zos, ENTRY_FILTERS, FiltersData.class, data);
}
if (hasFlag(flags, FLAG_TABS)) {
@ -131,7 +125,7 @@ public class DataImportExportUtils implements Constants {
if (c != null) {
final List<Tab> tabs = new ArrayList<>(c.getCount());
try {
TabCursorIndices ci = new TabCursorIndices(c);
final ObjectCursor.CursorIndices<Tab> ci = ObjectCursor.indicesFrom(c, Tab.class);
c.moveToFirst();
while (!c.isAfterLast()) {
tabs.add(ci.newObject(c));
@ -152,16 +146,11 @@ public class DataImportExportUtils implements Constants {
}
private static <T> List<T> queryAll(ContentResolver cr, Uri uri, String[] projection,
Class<? extends ObjectCursor.CursorIndices<T>> cls) throws IOException {
Class<T> cls) throws IOException {
Cursor c = cr.query(uri, projection, null, null, null);
if (c == null) return null;
try {
final ObjectCursor.CursorIndices<T> ci;
try {
ci = cls.getConstructor(Cursor.class).newInstance(c);
} catch (Exception e) {
throw new RuntimeException(e);
}
final ObjectCursor.CursorIndices<T> ci = ObjectCursor.indicesFrom(c, cls);
List<T> items = new ArrayList<>(c.getCount());
c.moveToFirst();
while (!c.isAfterLast()) {
@ -252,31 +241,36 @@ public class DataImportExportUtils implements Constants {
void insertBase(ContentResolver cr, Uri uri, List<FiltersData.BaseItem> items) throws IOException {
if (items == null) return;
final ObjectCursor.ValuesCreator<FiltersData.BaseItem> baseItemCreator =
ObjectCursor.valuesCreatorFrom(FiltersData.BaseItem.class);
List<ContentValues> values = new ArrayList<>(items.size());
for (FiltersData.BaseItem item : items) {
values.add(FiltersData$BaseItemValuesCreator.create(item));
values.add(baseItemCreator.create(item));
}
ContentResolverUtils.bulkInsert(cr, uri, values);
}
void insertUser(ContentResolver cr, Uri uri, List<FiltersData.UserItem> items) throws IOException {
if (items == null) return;
final ObjectCursor.ValuesCreator<FiltersData.UserItem> userItemCreator =
ObjectCursor.valuesCreatorFrom(FiltersData.UserItem.class);
List<ContentValues> values = new ArrayList<>(items.size());
for (FiltersData.UserItem item : items) {
values.add(FiltersData$UserItemValuesCreator.create(item));
values.add(userItemCreator.create(item));
}
ContentResolverUtils.bulkInsert(cr, uri, values);
}
});
}
if (hasFlag(flags, FLAG_TABS)) {
final ObjectCursor.ValuesCreator<Tab> creator = ObjectCursor.valuesCreatorFrom(Tab.class);
importItemsList(context, zipFile, ENTRY_TABS, Tab.class, new ContentResolverProcessStrategy<List<Tab>>() {
@Override
public boolean importItem(ContentResolver cr, List<Tab> items) throws IOException {
if (items == null) return false;
List<ContentValues> values = new ArrayList<>(items.size());
for (Tab item : items) {
values.add(TabValuesCreator.create(item));
values.add(creator.create(item));
}
cr.delete(Tabs.CONTENT_URI, null, null);
ContentResolverUtils.bulkInsert(cr, Tabs.CONTENT_URI, values);
@ -292,8 +286,8 @@ public class DataImportExportUtils implements Constants {
}
private static void importSharedPreferencesData(@NonNull final ZipFile zipFile, @NonNull final Context context,
@NonNull final String preferencesName, @NonNull final String entryName,
@NonNull final SharedPreferencesProcessStrategy strategy) throws IOException {
@NonNull final String preferencesName, @NonNull final String entryName,
@NonNull final SharedPreferencesProcessStrategy strategy) throws IOException {
final ZipEntry entry = zipFile.getEntry(entryName);
if (entry == null) return;
final JsonParser jsonParser = LoganSquare.JSON_FACTORY.createParser(zipFile.getInputStream(entry));
@ -314,8 +308,8 @@ public class DataImportExportUtils implements Constants {
}
private static void exportSharedPreferencesData(@NonNull final ZipOutputStream zos, final Context context,
@NonNull final String preferencesName, @NonNull final String entryName,
@NonNull final SharedPreferencesProcessStrategy strategy) throws IOException {
@NonNull final String preferencesName, @NonNull final String entryName,
@NonNull final SharedPreferencesProcessStrategy strategy) throws IOException {
final SharedPreferences preferences = context.getSharedPreferences(preferencesName, Context.MODE_PRIVATE);
final Map<String, ?> map = preferences.getAll();
zos.putNextEntry(new ZipEntry(entryName));
@ -330,10 +324,10 @@ public class DataImportExportUtils implements Constants {
}
private static <T> void importItemsList(@NonNull final Context context,
@NonNull final ZipFile zipFile,
@NonNull final String entryName,
@NonNull final Class<T> itemCls,
@NonNull final ContentResolverProcessStrategy<List<T>> strategy)
@NonNull final ZipFile zipFile,
@NonNull final String entryName,
@NonNull final Class<T> itemCls,
@NonNull final ContentResolverProcessStrategy<List<T>> strategy)
throws IOException {
final ZipEntry entry = zipFile.getEntry(entryName);
if (entry == null) return;
@ -344,9 +338,9 @@ public class DataImportExportUtils implements Constants {
private static <T> void exportItemsList(@NonNull final ZipOutputStream zos,
@NonNull final String entryName,
@NonNull final Class<T> itemCls,
@NonNull final List<T> itemList) throws IOException {
@NonNull final String entryName,
@NonNull final Class<T> itemCls,
@NonNull final List<T> itemList) throws IOException {
zos.putNextEntry(new ZipEntry(entryName));
final JsonGenerator jsonGenerator = LoganSquare.JSON_FACTORY.createGenerator(zos);
LoganSquareMapperFinder.mapperFor(itemCls).serialize(itemList, jsonGenerator);
@ -355,10 +349,10 @@ public class DataImportExportUtils implements Constants {
}
private static <T> void importItem(@NonNull final Context context,
@NonNull final ZipFile zipFile,
@NonNull final String entryName,
@NonNull final Class<T> itemCls,
@NonNull final ContentResolverProcessStrategy<T> strategy)
@NonNull final ZipFile zipFile,
@NonNull final String entryName,
@NonNull final Class<T> itemCls,
@NonNull final ContentResolverProcessStrategy<T> strategy)
throws IOException {
final ZipEntry entry = zipFile.getEntry(entryName);
if (entry == null) return;
@ -369,9 +363,9 @@ public class DataImportExportUtils implements Constants {
private static <T> void exportItem(@NonNull final ZipOutputStream zos,
@NonNull final String entryName,
@NonNull final Class<T> itemCls,
@NonNull final T item) throws IOException {
@NonNull final String entryName,
@NonNull final Class<T> itemCls,
@NonNull final T item) throws IOException {
zos.putNextEntry(new ZipEntry(entryName));
final JsonGenerator jsonGenerator = LoganSquare.JSON_FACTORY.createGenerator(zos);
LoganSquareMapperFinder.mapperFor(itemCls).serialize(item, jsonGenerator, true);

View File

@ -64,6 +64,7 @@ import org.mariotaku.abstask.library.AbstractTask
import org.mariotaku.abstask.library.TaskStarter
import org.mariotaku.kpreferences.get
import org.mariotaku.ktextension.*
import org.mariotaku.library.objectcursor.ObjectCursor
import org.mariotaku.pickncrop.library.MediaPickerActivity
import org.mariotaku.twidere.Constants.*
import org.mariotaku.twidere.R
@ -452,7 +453,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
this.inReplyToStatus = this@ComposeActivity.inReplyToStatus
this.isPossiblySensitive = this@ComposeActivity.possiblySensitive
}
val values = DraftValuesCreator.create(draft)
val values = ObjectCursor.valuesCreatorFrom(Draft::class.java).create(draft)
val draftUri = contentResolver.insert(Drafts.CONTENT_URI, values)
displayNewDraftNotification(text, draftUri)
return draftUri

View File

@ -82,16 +82,20 @@ class DataExportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
}
}
internal class ExportSettingsTask(private val activity: DataExportActivity, private val mPath: String?, private val mFlags: Int) : AsyncTask<Any, Any, Boolean>() {
internal class ExportSettingsTask(
private val activity: DataExportActivity,
private val path: String?,
private val flags: Int
) : AsyncTask<Any, Any, Boolean>() {
override fun doInBackground(vararg params: Any): Boolean? {
if (mPath == null) return false
if (path == null) return false
val sdf = SimpleDateFormat("yyyy-MM-dd_HH-mm-ss", Locale.US)
val fileName = String.format("Twidere_Settings_%s.zip", sdf.format(Date()))
val file = File(mPath, fileName)
val file = File(path, fileName)
file.delete()
try {
DataImportExportUtils.exportData(activity, file, mFlags)
DataImportExportUtils.exportData(activity, file, flags)
return true
} catch (e: IOException) {
Log.w(LOGTAG, e)

View File

@ -26,14 +26,16 @@ import android.view.View
import android.view.ViewGroup
import com.bumptech.glide.RequestManager
import org.mariotaku.kpreferences.get
import org.mariotaku.library.objectcursor.ObjectCursor
import org.mariotaku.twidere.R
import org.mariotaku.twidere.constant.mediaPreviewStyleKey
import org.mariotaku.twidere.extension.model.getActionName
import org.mariotaku.twidere.model.Draft
import org.mariotaku.twidere.model.DraftCursorIndices
import org.mariotaku.twidere.model.draft.StatusObjectExtras
import org.mariotaku.twidere.model.util.ParcelableMediaUtils
import org.mariotaku.twidere.util.*
import org.mariotaku.twidere.util.DataStoreUtils
import org.mariotaku.twidere.util.SharedPreferencesWrapper
import org.mariotaku.twidere.util.Utils
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
import org.mariotaku.twidere.view.holder.DraftViewHolder
import javax.inject.Inject
@ -53,7 +55,7 @@ class DraftsAdapter(
field = value
notifyDataSetChanged()
}
private var indices: DraftCursorIndices? = null
private var indices: ObjectCursor.CursorIndices<Draft>? = null
init {
GeneralComponentHelper.build(context).inject(this)
@ -122,9 +124,7 @@ class DraftsAdapter(
override fun swapCursor(c: Cursor?): Cursor? {
val old = super.swapCursor(c)
if (c != null) {
indices = DraftCursorIndices(c)
}
indices = c?.let { ObjectCursor.indicesFrom(it, Draft::class.java) }
return old
}

View File

@ -29,6 +29,7 @@ import android.view.View
import android.widget.TextView
import com.bumptech.glide.RequestManager
import org.mariotaku.kpreferences.get
import org.mariotaku.library.objectcursor.ObjectCursor
import org.mariotaku.sqliteqb.library.Columns
import org.mariotaku.sqliteqb.library.Expression
import org.mariotaku.sqliteqb.library.OrderBy
@ -36,10 +37,9 @@ import org.mariotaku.twidere.R
import org.mariotaku.twidere.constant.displayProfileImageKey
import org.mariotaku.twidere.constant.profileImageStyleKey
import org.mariotaku.twidere.extension.loadProfileImage
import org.mariotaku.twidere.model.ParcelableUserCursorIndices
import org.mariotaku.twidere.model.ParcelableUser
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.provider.TwidereDataStore.CachedUsers
import org.mariotaku.twidere.util.MediaLoaderWrapper
import org.mariotaku.twidere.util.SharedPreferencesWrapper
import org.mariotaku.twidere.util.UserColorNameManager
import org.mariotaku.twidere.util.Utils
@ -61,7 +61,7 @@ class UserAutoCompleteAdapter(
private val displayProfileImage: Boolean
private var profileImageStyle: Int
private var indices: ParcelableUserCursorIndices? = null
private var indices: ObjectCursor.CursorIndices<ParcelableUser>? = null
var accountKey: UserKey? = null
@ -79,11 +79,11 @@ class UserAutoCompleteAdapter(
icon.style = profileImageStyle
text1.text = userColorNameManager.getUserNickname(cursor.getString(indices.key), cursor.getString(indices.name))
text1.text = userColorNameManager.getUserNickname(cursor.getString(indices[CachedUsers.USER_KEY]), cursor.getString(indices[CachedUsers.NAME]))
@SuppressLint("SetTextI18n")
text2.text = "@${cursor.getString(indices.screen_name)}"
text2.text = "@${cursor.getString(indices[CachedUsers.SCREEN_NAME])}"
if (displayProfileImage) {
val profileImageUrl = cursor.getString(indices.profile_image_url)
val profileImageUrl = cursor.getString(indices[CachedUsers.PROFILE_IMAGE_URL])
requestManager.loadProfileImage(context, profileImageUrl, profileImageStyle).into(icon)
} else {
//TODO cancel image load
@ -101,7 +101,7 @@ class UserAutoCompleteAdapter(
}
override fun convertToString(cursor: Cursor?): CharSequence {
return cursor!!.getString(indices!!.screen_name)
return cursor!!.getString(indices!![CachedUsers.SCREEN_NAME])
}
override fun runQueryOnBackgroundThread(constraint: CharSequence): Cursor? {
@ -127,9 +127,7 @@ class UserAutoCompleteAdapter(
}
override fun swapCursor(cursor: Cursor?): Cursor? {
if (cursor != null) {
indices = ParcelableUserCursorIndices(cursor)
}
indices = cursor?.let { ObjectCursor.indicesFrom(it, ParcelableUser::class.java) }
return super.swapCursor(cursor)
}

View File

@ -5,8 +5,10 @@ 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.model.*
import org.mariotaku.twidere.model.FiltersData
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.provider.TwidereDataStore.Filters
import org.mariotaku.twidere.util.content.ContentResolverUtils
import org.xmlpull.v1.XmlPullParser
@ -24,7 +26,8 @@ fun FiltersData.read(cr: ContentResolver, loadSubscription: Boolean = false) {
val c = cr.query(uri, Filters.COLUMNS, where, null, null) ?: return null
@Suppress("ConvertTryFinallyToUseCall")
try {
return c.map(`FiltersData$BaseItemCursorIndices`(c))
val indices = ObjectCursor.indicesFrom(c, FiltersData.BaseItem::class.java)
return c.map(indices)
} finally {
c.close()
}
@ -34,7 +37,8 @@ fun FiltersData.read(cr: ContentResolver, loadSubscription: Boolean = false) {
val c = cr.query(Filters.Users.CONTENT_URI, Filters.Users.COLUMNS, where, null, null) ?: return@run null
@Suppress("ConvertTryFinallyToUseCall")
try {
return@run c.map(`FiltersData$UserItemCursorIndices`(c))
val indices = ObjectCursor.indicesFrom(c, FiltersData.UserItem::class.java)
return@run c.map(indices)
} finally {
c.close()
}
@ -45,33 +49,31 @@ fun FiltersData.read(cr: ContentResolver, loadSubscription: Boolean = false) {
}
fun FiltersData.write(cr: ContentResolver, deleteOld: Boolean = true) {
val baseCreator = ObjectCursor.valuesCreatorFrom(FiltersData.BaseItem::class.java)
val userCreator = ObjectCursor.valuesCreatorFrom(FiltersData.UserItem::class.java)
if (users != null) {
if (deleteOld) {
cr.delete(Filters.Users.CONTENT_URI, null, null)
}
ContentResolverUtils.bulkInsert(cr, Filters.Users.CONTENT_URI,
users.map(`FiltersData$UserItemValuesCreator`::create))
ContentResolverUtils.bulkInsert(cr, Filters.Users.CONTENT_URI, users.map(userCreator::create))
}
if (keywords != null) {
if (deleteOld) {
cr.delete(Filters.Keywords.CONTENT_URI, null, null)
}
ContentResolverUtils.bulkInsert(cr, Filters.Keywords.CONTENT_URI,
keywords.map(`FiltersData$BaseItemValuesCreator`::create))
ContentResolverUtils.bulkInsert(cr, Filters.Keywords.CONTENT_URI, keywords.map(baseCreator::create))
}
if (sources != null) {
if (deleteOld) {
cr.delete(Filters.Sources.CONTENT_URI, null, null)
}
ContentResolverUtils.bulkInsert(cr, Filters.Sources.CONTENT_URI,
sources.map(`FiltersData$BaseItemValuesCreator`::create))
ContentResolverUtils.bulkInsert(cr, Filters.Sources.CONTENT_URI, sources.map(baseCreator::create))
}
if (links != null) {
if (deleteOld) {
cr.delete(Filters.Links.CONTENT_URI, null, null)
}
ContentResolverUtils.bulkInsert(cr, Filters.Links.CONTENT_URI,
links.map(`FiltersData$BaseItemValuesCreator`::create))
ContentResolverUtils.bulkInsert(cr, Filters.Links.CONTENT_URI, links.map(baseCreator::create))
}
}

View File

@ -339,7 +339,9 @@ abstract class CursorActivitiesFragment : AbsActivitiesFragment() {
class CursorActivitiesLoader(context: Context, uri: Uri, projection: Array<String>,
selection: String, selectionArgs: Array<String>,
sortOrder: String, fromUser: Boolean) : ExtendedObjectCursorLoader<ParcelableActivity>(context, ParcelableActivityCursorIndices::class.java, uri, projection, selection, selectionArgs, sortOrder, fromUser) {
sortOrder: String, fromUser: Boolean
) : ExtendedObjectCursorLoader<ParcelableActivity>(context, ParcelableActivity::class.java, uri,
projection, selection, selectionArgs, sortOrder, fromUser) {
override fun createObjectCursor(cursor: Cursor, indices: ObjectCursor.CursorIndices<ParcelableActivity>): ObjectCursor<ParcelableActivity> {
val filteredUserIds = DataStoreUtils.getFilteredUserIds(context)

View File

@ -43,7 +43,10 @@ import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter
import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter.IndicatorPosition
import org.mariotaku.twidere.constant.IntentConstants.EXTRA_FROM_USER
import org.mariotaku.twidere.loader.ExtendedObjectCursorLoader
import org.mariotaku.twidere.model.*
import org.mariotaku.twidere.model.ParameterizedExpression
import org.mariotaku.twidere.model.ParcelableStatus
import org.mariotaku.twidere.model.SimpleRefreshTaskParam
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.model.event.*
import org.mariotaku.twidere.provider.TwidereDataStore.Filters
import org.mariotaku.twidere.provider.TwidereDataStore.Statuses
@ -98,8 +101,8 @@ abstract class CursorStatusesFragment : AbsStatusesFragment() {
accountKeys[it].toString()
}
val expression = processWhere(where, selectionArgs)
return ExtendedObjectCursorLoader(context, ParcelableStatusCursorIndices::class.java, uri,
projection, expression.sql, expression.parameters, sortOrder, fromUser)
return ExtendedObjectCursorLoader(context, ParcelableStatus::class.java, uri, projection,
expression.sql, expression.parameters, sortOrder, fromUser)
}
override fun createMessageBusCallback(): Any {

View File

@ -47,6 +47,7 @@ import org.mariotaku.chameleon.Chameleon
import org.mariotaku.ktextension.Bundle
import org.mariotaku.ktextension.contains
import org.mariotaku.ktextension.set
import org.mariotaku.library.objectcursor.ObjectCursor
import org.mariotaku.sqliteqb.library.Columns.Column
import org.mariotaku.sqliteqb.library.Expression
import org.mariotaku.sqliteqb.library.RawItemArray
@ -60,8 +61,6 @@ import org.mariotaku.twidere.extension.applyTheme
import org.mariotaku.twidere.extension.model.isOfficial
import org.mariotaku.twidere.model.AccountDetails
import org.mariotaku.twidere.model.Tab
import org.mariotaku.twidere.model.TabCursorIndices
import org.mariotaku.twidere.model.TabValuesCreator
import org.mariotaku.twidere.model.tab.DrawableHolder
import org.mariotaku.twidere.model.tab.TabConfiguration
import org.mariotaku.twidere.model.tab.iface.AccountCallback
@ -378,14 +377,15 @@ class CustomTabsFragment : BaseFragment(), LoaderCallbacks<Cursor?>, MultiChoice
return@setOnClickListener
}
}
val valuesCreator = ObjectCursor.valuesCreatorFrom(Tab::class.java)
when (tag) {
TAG_EDIT_TAB -> {
val where = Expression.equalsArgs(Tabs._ID).sql
val whereArgs = arrayOf(tab.id.toString())
context.contentResolver.update(Tabs.CONTENT_URI, TabValuesCreator.create(tab), where, whereArgs)
context.contentResolver.update(Tabs.CONTENT_URI, valuesCreator.create(tab), where, whereArgs)
}
TAG_ADD_TAB -> {
context.contentResolver.insert(Tabs.CONTENT_URI, TabValuesCreator.create(tab))
context.contentResolver.insert(Tabs.CONTENT_URI, valuesCreator.create(tab))
}
}
SettingsActivity.setShouldRestart(activity)
@ -473,7 +473,7 @@ class CustomTabsFragment : BaseFragment(), LoaderCallbacks<Cursor?>, MultiChoice
private val iconColor: Int = ThemeUtils.getThemeForegroundColor(context)
private val tempTab: Tab = Tab()
private var indices: TabCursorIndices? = null
private var indices: ObjectCursor.CursorIndices<Tab>? = null
override fun bindView(view: View, context: Context?, cursor: Cursor) {
super.bindView(view, context, cursor)
@ -504,9 +504,7 @@ class CustomTabsFragment : BaseFragment(), LoaderCallbacks<Cursor?>, MultiChoice
}
override fun changeCursor(cursor: Cursor?) {
if (cursor != null) {
indices = TabCursorIndices(cursor)
}
indices = cursor?.let { ObjectCursor.indicesFrom(it, Tab::class.java) }
super.changeCursor(cursor)
}

View File

@ -72,6 +72,7 @@ import org.mariotaku.kpreferences.get
import org.mariotaku.ktextension.applyFontFamily
import org.mariotaku.ktextension.contains
import org.mariotaku.ktextension.findPositionByItemId
import org.mariotaku.library.objectcursor.ObjectCursor
import org.mariotaku.microblog.library.MicroBlogException
import org.mariotaku.microblog.library.twitter.model.Paging
import org.mariotaku.microblog.library.twitter.model.TranslationResult
@ -2134,13 +2135,14 @@ class StatusFragment : BaseFragment(), LoaderCallbacks<SingleResponse<Parcelable
val pStatus = ParcelableStatusUtils.fromStatus(status,
accountKey, false)
cr.insert(CachedStatuses.CONTENT_URI, ParcelableStatusValuesCreator.create(pStatus))
cr.insert(CachedStatuses.CONTENT_URI, ObjectCursor.valuesCreatorFrom(ParcelableStatus::class.java).create(pStatus))
val activityCursor = cr.query(Activities.AboutMe.CONTENT_URI,
Activities.COLUMNS, activityWhere.sql, statusWhereArgs, null)!!
try {
activityCursor.moveToFirst()
val ci = ParcelableActivityCursorIndices(activityCursor)
val ci = ObjectCursor.indicesFrom(activityCursor, ParcelableActivity::class.java)
val vc = ObjectCursor.valuesCreatorFrom(ParcelableActivity::class.java)
while (!activityCursor.isAfterLast) {
val activity = ci.newObject(activityCursor)
val activityStatus = activity.getActivityStatus()
@ -2149,7 +2151,7 @@ class StatusFragment : BaseFragment(), LoaderCallbacks<SingleResponse<Parcelable
activityStatus.reply_count = activitySummary.replyCount
activityStatus.retweet_count = activitySummary.retweetCount
}
cr.update(Activities.AboutMe.CONTENT_URI, ParcelableActivityValuesCreator.create(activity),
cr.update(Activities.AboutMe.CONTENT_URI, vc.create(activity),
Expression.equals(Activities._ID, activity._id).sql, null)
activityCursor.moveToNext()
}

View File

@ -83,6 +83,7 @@ import org.mariotaku.chameleon.Chameleon
import org.mariotaku.chameleon.ChameleonUtils
import org.mariotaku.kpreferences.get
import org.mariotaku.ktextension.*
import org.mariotaku.library.objectcursor.ObjectCursor
import org.mariotaku.microblog.library.MicroBlog
import org.mariotaku.microblog.library.MicroBlogException
import org.mariotaku.microblog.library.twitter.model.FriendshipUpdate
@ -325,8 +326,8 @@ class UserFragment : BaseFragment(), OnClickListener, OnLinkClickListener,
val resolver = context.applicationContext.contentResolver
task {
resolver.insert(CachedUsers.CONTENT_URI, ParcelableUserValuesCreator.create(user))
resolver.insert(CachedRelationships.CONTENT_URI, ParcelableRelationshipValuesCreator.create(userRelationship))
resolver.insert(CachedUsers.CONTENT_URI, ObjectCursor.valuesCreatorFrom(ParcelableUser::class.java).create(user))
resolver.insert(CachedRelationships.CONTENT_URI, ObjectCursor.valuesCreatorFrom(ParcelableRelationship::class.java).create(userRelationship))
}
followContainer.follow.visibility = View.VISIBLE
}
@ -1599,7 +1600,7 @@ class UserFragment : BaseFragment(), OnClickListener, OnLinkClickListener,
val data = ParcelableRelationshipUtils.create(accountKey, userKey, relationship,
isFiltering)
val resolver = context.contentResolver
val values = ParcelableRelationshipValuesCreator.create(data)
val values = ObjectCursor.valuesCreatorFrom(ParcelableRelationship::class.java).create(data)
resolver.insert(CachedRelationships.CONTENT_URI, values)
return SingleResponse.getInstance(data)
} catch (e: MicroBlogException) {

View File

@ -44,6 +44,7 @@ import android.widget.AbsListView.MultiChoiceModeListener
import com.bumptech.glide.Glide
import kotlinx.android.synthetic.main.fragment_content_listview.*
import org.mariotaku.ktextension.setGroupAvailability
import org.mariotaku.library.objectcursor.ObjectCursor
import org.mariotaku.sqliteqb.library.Columns
import org.mariotaku.sqliteqb.library.Expression
import org.mariotaku.twidere.R
@ -56,7 +57,6 @@ import org.mariotaku.twidere.extension.*
import org.mariotaku.twidere.fragment.AbsContentListViewFragment
import org.mariotaku.twidere.fragment.BaseDialogFragment
import org.mariotaku.twidere.model.FiltersData
import org.mariotaku.twidere.model.`FiltersData$BaseItemCursorIndices`
import org.mariotaku.twidere.provider.TwidereDataStore.Filters
import org.mariotaku.twidere.text.style.EmojiSpan
import org.mariotaku.twidere.util.DataStoreUtils
@ -331,15 +331,12 @@ abstract class BaseFiltersFragment : AbsContentListViewFragment<SimpleCursorAdap
) : SimpleCursorAdapter(context, R.layout.simple_list_item_activated_1, null,
emptyArray(), intArrayOf(), 0), SelectableItemAdapter {
private var indices: `FiltersData$BaseItemCursorIndices`? = null
private var indices: ObjectCursor.CursorIndices<FiltersData.BaseItem>? = null
private val secondaryTextColor = ThemeUtils.getTextColorSecondary(context)
override fun swapCursor(c: Cursor?): Cursor? {
val old = super.swapCursor(c)
if (c != null) {
indices = `FiltersData$BaseItemCursorIndices`(c)
}
return old
indices = c?.let { ObjectCursor.indicesFrom(it, FiltersData.BaseItem::class.java) }
return super.swapCursor(c)
}
override fun bindView(view: View, context: Context, cursor: Cursor) {
@ -347,8 +344,8 @@ abstract class BaseFiltersFragment : AbsContentListViewFragment<SimpleCursorAdap
val indices = this.indices!!
val text1 = view.findViewById(android.R.id.text1) as TextView
val ssb = SpannableStringBuilder(cursor.getString(indices.value))
if (cursor.getLong(indices.source) >= 0) {
val ssb = SpannableStringBuilder(cursor.getString(indices[Filters.VALUE]))
if (cursor.getLong(indices[Filters.SOURCE]) >= 0) {
val start = ssb.length
ssb.append("*")
val end = start + 1
@ -363,7 +360,7 @@ abstract class BaseFiltersFragment : AbsContentListViewFragment<SimpleCursorAdap
override fun isSelectable(position: Int): Boolean {
val cursor = this.cursor ?: return false
if (cursor.moveToPosition(position)) {
return cursor.getLong(indices!!.source) < 0
return cursor.getLong(indices!![Filters.SOURCE]) < 0
}
return false
}

View File

@ -20,6 +20,7 @@ import android.widget.TextView
import kotlinx.android.synthetic.main.fragment_content_listview.*
import org.mariotaku.kpreferences.KPreferences
import org.mariotaku.ktextension.setItemAvailability
import org.mariotaku.library.objectcursor.ObjectCursor
import org.mariotaku.twidere.R
import org.mariotaku.twidere.TwidereConstants.*
import org.mariotaku.twidere.activity.AccountSelectorActivity
@ -29,9 +30,9 @@ import org.mariotaku.twidere.constant.IntentConstants.EXTRA_ACCOUNT_HOST
import org.mariotaku.twidere.constant.nameFirstKey
import org.mariotaku.twidere.fragment.AddUserFilterDialogFragment
import org.mariotaku.twidere.fragment.ExtraFeaturesIntroductionDialogFragment
import org.mariotaku.twidere.model.FiltersData
import org.mariotaku.twidere.model.ParcelableUser
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.model.`FiltersData$UserItemCursorIndices`
import org.mariotaku.twidere.model.analyzer.PurchaseFinished
import org.mariotaku.twidere.provider.TwidereDataStore.Filters
import org.mariotaku.twidere.text.style.EmojiSpan
@ -165,7 +166,7 @@ class FilteredUsersFragment : BaseFiltersFragment() {
private val nameFirst: Boolean
private var indices: `FiltersData$UserItemCursorIndices`? = null
private var indices: ObjectCursor.CursorIndices<FiltersData.UserItem>? = null
private val secondaryTextColor = ThemeUtils.getTextColorSecondary(context)
init {
@ -182,15 +183,15 @@ class FilteredUsersFragment : BaseFiltersFragment() {
icon.visibility = View.GONE
val userId = UserKey.valueOf(cursor.getString(indices.userKey))
val name = cursor.getString(indices.name)
val screenName = cursor.getString(indices.screenName)
val userId = UserKey.valueOf(cursor.getString(indices[Filters.Users.USER_KEY]))
val name = cursor.getString(indices[Filters.Users.NAME])
val screenName = cursor.getString(indices[Filters.Users.SCREEN_NAME])
val displayName = userColorNameManager.getDisplayName(userId, name, screenName,
nameFirst)
text1.text = displayName
val ssb = SpannableStringBuilder(displayName)
if (cursor.getLong(indices.source) >= 0) {
if (cursor.getLong(indices[Filters.Users.SOURCE]) >= 0) {
val start = ssb.length
ssb.append("*")
val end = start + 1
@ -203,17 +204,14 @@ class FilteredUsersFragment : BaseFiltersFragment() {
}
override fun swapCursor(c: Cursor?): Cursor? {
val old = super.swapCursor(c)
if (c != null) {
indices = `FiltersData$UserItemCursorIndices`(c)
}
return old
indices = c?.let { ObjectCursor.indicesFrom(it, FiltersData.UserItem::class.java) }
return super.swapCursor(c)
}
override fun isSelectable(position: Int): Boolean {
val cursor = this.cursor ?: return false
if (cursor.moveToPosition(position)) {
return cursor.getLong(indices!!.source) < 0
return cursor.getLong(indices!![Filters.Users.SOURCE]) < 0
}
return false
}
@ -221,7 +219,7 @@ class FilteredUsersFragment : BaseFiltersFragment() {
fun getUserKeyString(position: Int): String? {
val cursor = this.cursor ?: return null
if (cursor.moveToPosition(position)) {
return cursor.getString(indices!!.userKey)
return cursor.getString(indices!![Filters.Users.USER_KEY])
}
return null
}

View File

@ -23,6 +23,7 @@ import kotlinx.android.synthetic.main.layout_list_with_empty_view.*
import okhttp3.HttpUrl
import org.mariotaku.abstask.library.TaskStarter
import org.mariotaku.ktextension.*
import org.mariotaku.library.objectcursor.ObjectCursor
import org.mariotaku.sqliteqb.library.Expression
import org.mariotaku.twidere.R
import org.mariotaku.twidere.TwidereConstants.REQUEST_PURCHASE_EXTRA_FEATURES
@ -37,8 +38,6 @@ import org.mariotaku.twidere.fragment.BaseFragment
import org.mariotaku.twidere.fragment.ExtraFeaturesIntroductionDialogFragment
import org.mariotaku.twidere.fragment.ProgressDialogFragment
import org.mariotaku.twidere.model.FiltersSubscription
import org.mariotaku.twidere.model.FiltersSubscriptionCursorIndices
import org.mariotaku.twidere.model.FiltersSubscriptionValuesCreator
import org.mariotaku.twidere.model.analyzer.PurchaseFinished
import org.mariotaku.twidere.provider.TwidereDataStore.Filters
import org.mariotaku.twidere.task.filter.RefreshFiltersSubscriptionsTask
@ -229,7 +228,7 @@ class FiltersSubscriptionsFragment : BaseFragment(), LoaderManager.LoaderCallbac
val whereArgs = ids.toStringArray()
resolver.query(Filters.Subscriptions.CONTENT_URI, Filters.Subscriptions.COLUMNS, where,
whereArgs, null)?.useCursor { cursor ->
val indices = FiltersSubscriptionCursorIndices(cursor)
val indices = ObjectCursor.indicesFrom(cursor, FiltersSubscription::class.java)
cursor.moveToFirst()
while (!cursor.isAfterLast) {
val subscription = indices.newObject(cursor)
@ -261,11 +260,11 @@ class FiltersSubscriptionsFragment : BaseFragment(), LoaderManager.LoaderCallbac
class FilterSubscriptionsAdapter(context: Context) : SimpleCursorAdapter(context,
R.layout.list_item_two_line, null, arrayOf(Filters.Subscriptions.NAME),
intArrayOf(android.R.id.text1), 0) {
private var indices: FiltersSubscriptionCursorIndices? = null
private var indices: ObjectCursor.CursorIndices<FiltersSubscription>? = null
private var tempObject: FiltersSubscription = FiltersSubscription()
override fun swapCursor(c: Cursor?): Cursor? {
indices = if (c != null) FiltersSubscriptionCursorIndices(c) else null
indices = c?.let { ObjectCursor.indicesFrom(it, FiltersSubscription::class.java) }
return super.swapCursor(c)
}
@ -295,7 +294,8 @@ class FiltersSubscriptionsFragment : BaseFragment(), LoaderManager.LoaderCallbac
subscription.setupUrl(editUrl.text.toString())
val component = subscription.instantiateComponent(context) ?: return@setPositiveButton
component.firstAdded()
context.contentResolver.insert(Filters.Subscriptions.CONTENT_URI, FiltersSubscriptionValuesCreator.create(subscription))
val vc = ObjectCursor.valuesCreatorFrom(FiltersSubscription::class.java)
context.contentResolver.insert(Filters.Subscriptions.CONTENT_URI, vc.create(subscription))
}
builder.setNegativeButton(android.R.string.cancel, null)
val dialog = builder.create()

View File

@ -57,6 +57,7 @@ import org.mariotaku.chameleon.ChameleonUtils
import org.mariotaku.kpreferences.get
import org.mariotaku.ktextension.setItemAvailability
import org.mariotaku.ktextension.useCursor
import org.mariotaku.library.objectcursor.ObjectCursor
import org.mariotaku.microblog.library.MicroBlog
import org.mariotaku.microblog.library.MicroBlogException
import org.mariotaku.microblog.library.twitter.TwitterUpload
@ -455,7 +456,8 @@ class MessageConversationInfoFragment : BaseFragment(), IToolBarSupportFragment,
context.contentResolver.query(Conversations.CONTENT_URI, Conversations.COLUMNS, where,
whereArgs, null).useCursor { cur ->
if (cur.moveToFirst()) {
return ParcelableMessageConversationCursorIndices.fromCursor(cur)
val indices = ObjectCursor.indicesFrom(cur, ParcelableMessageConversation::class.java)
return indices.newObject(cur)
}
}
return null

View File

@ -40,6 +40,7 @@ import org.mariotaku.kpreferences.get
import org.mariotaku.ktextension.Bundle
import org.mariotaku.ktextension.set
import org.mariotaku.ktextension.setItemAvailability
import org.mariotaku.library.objectcursor.ObjectCursor
import org.mariotaku.sqliteqb.library.Expression
import org.mariotaku.twidere.R
import org.mariotaku.twidere.adapter.SelectableUsersAdapter
@ -48,8 +49,10 @@ import org.mariotaku.twidere.constant.nameFirstKey
import org.mariotaku.twidere.extension.model.isOfficial
import org.mariotaku.twidere.fragment.BaseFragment
import org.mariotaku.twidere.loader.CacheUserSearchLoader
import org.mariotaku.twidere.model.*
import org.mariotaku.twidere.model.ParcelableMessageConversation
import org.mariotaku.twidere.model.ParcelableMessageConversation.ConversationType
import org.mariotaku.twidere.model.ParcelableUser
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.model.util.AccountUtils
import org.mariotaku.twidere.provider.TwidereDataStore.Messages.Conversations
import org.mariotaku.twidere.task.twitter.message.SendMessageTask
@ -247,7 +250,7 @@ class MessageNewConversationFragment : BaseFragment(), LoaderCallbacks<List<Parc
}
}
val values = ParcelableMessageConversationValuesCreator.create(conversation)
val values = ObjectCursor.valuesCreatorFrom(ParcelableMessageConversation::class.java).create(conversation)
context.contentResolver.insert(Conversations.CONTENT_URI, values)
activity.startActivity(IntentUtils.messageConversation(accountKey, conversation.id))
activity.finish()
@ -301,7 +304,8 @@ class MessageNewConversationFragment : BaseFragment(), LoaderCallbacks<List<Parc
val cur = resolver.query(Conversations.CONTENT_URI, Conversations.COLUMNS, where, whereArgs, null) ?: return null
try {
if (cur.moveToFirst()) {
return ParcelableMessageConversationCursorIndices.fromCursor(cur)
val indices = ObjectCursor.indicesFrom(cur, ParcelableMessageConversation::class.java)
return indices.newObject(cur)
}
} finally {
cur.close()

View File

@ -535,7 +535,7 @@ class MessagesConversationFragment : AbsContentListRecyclerViewFragment<Messages
context: Context,
val accountKey: UserKey,
val conversationId: String
) : ObjectCursorLoader<ParcelableMessage>(context, ParcelableMessageCursorIndices::class.java) {
) : ObjectCursorLoader<ParcelableMessage>(context, ParcelableMessage::class.java) {
private val atomicConversation = AtomicReference<ParcelableMessageConversation?>()
val conversation: ParcelableMessageConversation? get() = atomicConversation.get()

View File

@ -44,7 +44,6 @@ import org.mariotaku.twidere.fragment.iface.IFloatingActionButtonFragment
import org.mariotaku.twidere.fragment.iface.IFloatingActionButtonFragment.ActionInfo
import org.mariotaku.twidere.loader.ObjectCursorLoader
import org.mariotaku.twidere.model.ParcelableMessageConversation
import org.mariotaku.twidere.model.ParcelableMessageConversationCursorIndices
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.model.event.GetMessagesTaskEvent
import org.mariotaku.twidere.provider.TwidereDataStore.Messages
@ -84,7 +83,7 @@ class MessagesEntriesFragment : AbsContentListRecyclerViewFragment<MessagesEntri
}
override fun onCreateLoader(id: Int, args: Bundle?): Loader<List<ParcelableMessageConversation>?> {
val loader = ObjectCursorLoader(context, ParcelableMessageConversationCursorIndices::class.java)
val loader = ObjectCursorLoader(context, ParcelableMessageConversation::class.java)
val projection = (Conversations.COLUMNS + Conversations.UNREAD_COUNT).map {
TwidereQueryBuilder.mapConversationsProjection(it)
}.toTypedArray()

View File

@ -1,13 +1,13 @@
package org.mariotaku.twidere.loader
import android.content.Context
import org.mariotaku.library.objectcursor.ObjectCursor
import org.mariotaku.microblog.library.MicroBlog
import org.mariotaku.microblog.library.twitter.model.User
import org.mariotaku.sqliteqb.library.Columns
import org.mariotaku.sqliteqb.library.Expression
import org.mariotaku.twidere.model.AccountDetails
import org.mariotaku.twidere.model.ParcelableUser
import org.mariotaku.twidere.model.ParcelableUserCursorIndices
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.provider.TwidereDataStore.CachedUsers
import org.mariotaku.twidere.util.UserColorNameManager
@ -47,10 +47,10 @@ class CacheUserSearchLoader(
val selectionArgs = arrayOf(queryEscaped, queryEscaped, *nicknameKeys)
val c = context.contentResolver.query(CachedUsers.CONTENT_URI, CachedUsers.BASIC_COLUMNS,
selection.sql, selectionArgs, null)!!
val i = ParcelableUserCursorIndices(c)
val i = ObjectCursor.indicesFrom(c, ParcelableUser::class.java)
c.moveToFirst()
while (!c.isAfterLast) {
if (list.none { it.key.toString() == c.getString(i.key) }) {
if (list.none { it.key.toString() == c.getString(i[CachedUsers.USER_KEY]) }) {
list.add(i.newObject(c))
}
c.moveToNext()

View File

@ -27,6 +27,7 @@ import android.text.TextUtils
import android.util.Log
import org.mariotaku.abstask.library.TaskStarter
import org.mariotaku.ktextension.set
import org.mariotaku.library.objectcursor.ObjectCursor
import org.mariotaku.microblog.library.MicroBlog
import org.mariotaku.microblog.library.MicroBlogException
import org.mariotaku.microblog.library.twitter.model.User
@ -38,13 +39,16 @@ import org.mariotaku.twidere.TwidereConstants.*
import org.mariotaku.twidere.annotation.AccountType
import org.mariotaku.twidere.annotation.Referral
import org.mariotaku.twidere.extension.model.newMicroBlogInstance
import org.mariotaku.twidere.model.*
import org.mariotaku.twidere.model.AccountDetails
import org.mariotaku.twidere.model.ParcelableUser
import org.mariotaku.twidere.model.SingleResponse
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.model.util.AccountUtils
import org.mariotaku.twidere.model.util.ParcelableUserUtils
import org.mariotaku.twidere.model.util.UserKeyUtils
import org.mariotaku.twidere.provider.TwidereDataStore.CachedUsers
import org.mariotaku.twidere.task.UpdateAccountInfoTask
import org.mariotaku.twidere.util.ContentValuesCreator.createCachedUser
import org.mariotaku.twidere.util.ContentValuesCreator
import org.mariotaku.twidere.util.TwitterWrapper
import org.mariotaku.twidere.util.UserColorNameManager
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
@ -85,7 +89,7 @@ class ParcelableUserLoader(
if (!omitIntentExtra && extras != null) {
val user = extras.getParcelable<ParcelableUser>(EXTRA_USER)
if (user != null) {
val values = ParcelableUserValuesCreator.create(user)
val values = ObjectCursor.valuesCreatorFrom(ParcelableUser::class.java).create(user)
resolver.insert(CachedUsers.CONTENT_URI, values)
ParcelableUserUtils.updateExtraInformation(user, details, userColorNameManager)
return SingleResponse(user).apply {
@ -118,7 +122,7 @@ class ParcelableUserLoader(
whereArgs, null)?.let { cur ->
try {
cur.moveToFirst()
val indices = ParcelableUserCursorIndices(cur)
val indices = ObjectCursor.indicesFrom(cur, ParcelableUser::class.java)
while (!cur.isAfterLast) {
val user = indices.newObject(cur)
if (TextUtils.equals(UserKeyUtils.getUserHost(user), user.key.host)) {
@ -152,7 +156,7 @@ class ParcelableUserLoader(
twitterUser = TwitterWrapper.tryShowUser(twitter, id, screenName, details.type)
}
}
val cachedUserValues = createCachedUser(twitterUser, profileImageSize)
val cachedUserValues = ContentValuesCreator.createCachedUser(twitterUser, profileImageSize)
resolver.insert(CachedUsers.CONTENT_URI, cachedUserValues)
val user = ParcelableUserUtils.fromUser(twitterUser, accountKey,
profileImageSize = profileImageSize)

View File

@ -41,6 +41,7 @@ import okhttp3.Dns
import org.apache.commons.lang3.ArrayUtils
import org.mariotaku.ktextension.isNullOrEmpty
import org.mariotaku.ktextension.toNulls
import org.mariotaku.library.objectcursor.ObjectCursor
import org.mariotaku.sqliteqb.library.Columns.Column
import org.mariotaku.sqliteqb.library.Expression
import org.mariotaku.sqliteqb.library.RawItemArray
@ -52,7 +53,6 @@ import org.mariotaku.twidere.annotation.ReadPositionTag
import org.mariotaku.twidere.app.TwidereApplication
import org.mariotaku.twidere.model.AccountPreferences
import org.mariotaku.twidere.model.Draft
import org.mariotaku.twidere.model.DraftCursorIndices
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.model.event.UnreadCountUpdatedEvent
import org.mariotaku.twidere.provider.TwidereDataStore.*
@ -360,7 +360,7 @@ class TwidereDataProvider : ContentProvider(), LazyLoadCallback {
val draftId = values.getAsLong(BaseColumns._ID) ?: 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 = DraftCursorIndices(c)
val i = ObjectCursor.indicesFrom(c, Draft::class.java)
val item: Draft
try {
if (!c.moveToFirst()) return -1

View File

@ -47,6 +47,7 @@ import org.mariotaku.ktextension.configure
import org.mariotaku.ktextension.toLong
import org.mariotaku.ktextension.toTypedArray
import org.mariotaku.ktextension.useCursor
import org.mariotaku.library.objectcursor.ObjectCursor
import org.mariotaku.microblog.library.MicroBlogException
import org.mariotaku.microblog.library.twitter.TwitterUpload
import org.mariotaku.microblog.library.twitter.model.MediaUploadResponse
@ -121,7 +122,7 @@ class LengthyOperationsService : BaseIntentService("lengthy_operations") {
val where = Expression.equals(Drafts._ID, draftId)
@SuppressLint("Recycle")
val draft: Draft = contentResolver.query(Drafts.CONTENT_URI, Drafts.COLUMNS, where.sql, null, null)?.useCursor {
val i = DraftCursorIndices(it)
val i = ObjectCursor.indicesFrom(it, Draft::class.java)
if (!it.moveToFirst()) return@useCursor null
return@useCursor i.newObject(it)
} ?: return

View File

@ -8,11 +8,15 @@ import android.content.Context
import android.support.v4.util.LongSparseArray
import android.text.TextUtils
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.setAccountKey
import org.mariotaku.twidere.extension.model.setAccountUser
import org.mariotaku.twidere.model.*
import org.mariotaku.twidere.model.AccountDetails
import org.mariotaku.twidere.model.ParcelableUser
import org.mariotaku.twidere.model.Tab
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.provider.TwidereDataStore.*
import java.io.IOException
@ -57,7 +61,8 @@ class UpdateAccountInfoTask(
private fun updateTabs(resolver: ContentResolver, accountKey: UserKey) {
val tabsCursor = resolver.query(Tabs.CONTENT_URI, Tabs.COLUMNS, null, null, null) ?: return
try {
val indices = TabCursorIndices(tabsCursor)
val indices = ObjectCursor.indicesFrom(tabsCursor, Tab::class.java)
val creator = ObjectCursor.valuesCreatorFrom(Tab::class.java)
tabsCursor.moveToFirst()
val values = LongSparseArray<ContentValues>()
while (!tabsCursor.isAfterLast) {
@ -68,7 +73,7 @@ class UpdateAccountInfoTask(
val keys = arguments.accountKeys
if (TextUtils.equals(accountKey.id, accountId) && keys == null) {
arguments.accountKeys = arrayOf(accountKey)
values.put(tab.id, TabValuesCreator.create(tab))
values.put(tab.id, creator.create(tab))
}
}
tabsCursor.moveToNext()

View File

@ -6,12 +6,11 @@ import android.content.Context
import android.net.Uri
import org.mariotaku.abstask.library.AbstractTask
import org.mariotaku.ktextension.useCursor
import org.mariotaku.library.objectcursor.ObjectCursor
import org.mariotaku.sqliteqb.library.Expression
import org.mariotaku.twidere.extension.model.instantiateComponent
import org.mariotaku.twidere.model.FiltersData
import org.mariotaku.twidere.model.FiltersSubscriptionCursorIndices
import org.mariotaku.twidere.model.`FiltersData$BaseItemValuesCreator`
import org.mariotaku.twidere.model.`FiltersData$UserItemValuesCreator`
import org.mariotaku.twidere.model.FiltersSubscription
import org.mariotaku.twidere.provider.TwidereDataStore.Filters
import org.mariotaku.twidere.util.DebugLog
import org.mariotaku.twidere.util.content.ContentResolverUtils
@ -26,7 +25,7 @@ class RefreshFiltersSubscriptionsTask(val context: Context) : AbstractTask<Unit?
val resolver = context.contentResolver
val sourceIds = ArrayList<Long>()
resolver.query(Filters.Subscriptions.CONTENT_URI, Filters.Subscriptions.COLUMNS, null, null, null)?.useCursor { cursor ->
val indices = FiltersSubscriptionCursorIndices(cursor)
val indices = ObjectCursor.indicesFrom(cursor, FiltersSubscription::class.java)
cursor.moveToFirst()
while (!cursor.isAfterLast) {
val subscription = indices.newObject(cursor)
@ -72,9 +71,10 @@ class RefreshFiltersSubscriptionsTask(val context: Context) : AbstractTask<Unit?
private fun updateUserItems(resolver: ContentResolver, items: List<FiltersData.UserItem>?, sourceId: Long) {
resolver.delete(Filters.Users.CONTENT_URI, Expression.equalsArgs(Filters.Users.SOURCE).sql,
arrayOf(sourceId.toString()))
val creator = ObjectCursor.valuesCreatorFrom(FiltersData.UserItem::class.java)
items?.map { item ->
item.source = sourceId
return@map `FiltersData$UserItemValuesCreator`.create(item)
return@map creator.create(item)
}?.let { items ->
ContentResolverUtils.bulkInsert(resolver, Filters.Users.CONTENT_URI, items)
}
@ -83,9 +83,10 @@ class RefreshFiltersSubscriptionsTask(val context: Context) : AbstractTask<Unit?
private fun updateBaseItems(resolver: ContentResolver, items: List<FiltersData.BaseItem>?, uri: Uri, sourceId: Long) {
resolver.delete(uri, Expression.equalsArgs(Filters.SOURCE).sql,
arrayOf(sourceId.toString()))
val creator = ObjectCursor.valuesCreatorFrom(FiltersData.BaseItem::class.java)
items?.map { item ->
item.source = sourceId
return@map `FiltersData$BaseItemValuesCreator`.create(item)
return@map creator.create(item)
}?.let { items ->
ContentResolverUtils.bulkInsert(resolver, uri, items)
}

View File

@ -10,6 +10,7 @@ import org.apache.commons.lang3.ArrayUtils
import org.apache.commons.lang3.math.NumberUtils
import org.mariotaku.abstask.library.TaskStarter
import org.mariotaku.kpreferences.get
import org.mariotaku.library.objectcursor.ObjectCursor
import org.mariotaku.microblog.library.MicroBlog
import org.mariotaku.microblog.library.MicroBlogException
import org.mariotaku.microblog.library.twitter.model.Paging
@ -23,7 +24,7 @@ import org.mariotaku.twidere.TwidereConstants.QUERY_PARAM_NOTIFY_CHANGE
import org.mariotaku.twidere.constant.loadItemLimitKey
import org.mariotaku.twidere.extension.model.newMicroBlogInstance
import org.mariotaku.twidere.model.AccountDetails
import org.mariotaku.twidere.model.ParcelableStatusValuesCreator
import org.mariotaku.twidere.model.ParcelableStatus
import org.mariotaku.twidere.model.RefreshTaskParam
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.model.event.GetStatusesTaskEvent
@ -165,6 +166,7 @@ abstract class GetStatusesTask(
// Get id diff of first and last item
val sortDiff = firstSortId - lastSortId
val creator = ObjectCursor.valuesCreatorFrom(ParcelableStatus::class.java)
for (i in 0 until statuses.size) {
val item = statuses[i]
val status = ParcelableStatusUtils.fromStatus(item, accountKey, false, profileImageSize)
@ -173,7 +175,7 @@ abstract class GetStatusesTask(
sortDiff, i, statuses.size)
status.inserted_date = System.currentTimeMillis()
mediaLoader.preloadStatus(status)
values[i] = ParcelableStatusValuesCreator.create(status)
values[i] = creator.create(status)
if (minIdx == -1 || item < statuses[minIdx]) {
minIdx = i
minPositionKey = status.position_key

View File

@ -25,64 +25,66 @@ import android.content.ContentValues
import android.content.Context
import android.net.Uri
import android.support.v4.util.ArraySet
import org.mariotaku.library.objectcursor.ObjectCursor
import org.mariotaku.microblog.library.MicroBlog
import org.mariotaku.microblog.library.MicroBlogException
import org.mariotaku.microblog.library.twitter.model.Trends
import org.mariotaku.sqliteqb.library.Expression
import org.mariotaku.sqliteqb.library.Expression.and
import org.mariotaku.sqliteqb.library.Expression.equalsArgs
import org.mariotaku.twidere.TwidereConstants.LOGTAG
import org.mariotaku.twidere.annotation.AccountType
import org.mariotaku.twidere.annotation.AccountType.FANFOU
import org.mariotaku.twidere.extension.model.newMicroBlogInstance
import org.mariotaku.twidere.model.ParcelableTrend
import org.mariotaku.twidere.model.ParcelableTrendValuesCreator
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.model.event.TrendsRefreshedEvent
import org.mariotaku.twidere.model.util.AccountUtils
import org.mariotaku.twidere.model.util.AccountUtils.getAccountDetails
import org.mariotaku.twidere.provider.TwidereDataStore.CachedHashtags
import org.mariotaku.twidere.provider.TwidereDataStore.CachedTrends
import org.mariotaku.twidere.util.DebugLog
import org.mariotaku.twidere.task.BaseAbstractTask
import org.mariotaku.twidere.util.DebugLog.w
import org.mariotaku.twidere.util.content.ContentResolverUtils
import org.mariotaku.twidere.util.content.ContentResolverUtils.bulkInsert
import java.util.*
/**
* Created by mariotaku on 16/2/24.
*/
class GetTrendsTask(
context: android.content.Context,
private val accountKey: org.mariotaku.twidere.model.UserKey,
context: Context,
private val accountKey: UserKey,
private val woeId: Int
) : org.mariotaku.twidere.task.BaseAbstractTask<Any?, Unit, Any?>(context) {
) : BaseAbstractTask<Any?, Unit, Any?>(context) {
override fun doLongOperation(param: Any?) {
val details = org.mariotaku.twidere.model.util.AccountUtils.getAccountDetails(android.accounts.AccountManager.get(context), accountKey, true) ?: return
val twitter = details.newMicroBlogInstance(context, cls = org.mariotaku.microblog.library.MicroBlog::class.java)
val details = getAccountDetails(AccountManager.get(context), accountKey, true) ?: return
val twitter = details.newMicroBlogInstance(context, cls = MicroBlog::class.java)
try {
val trends = when {
details.type == org.mariotaku.twidere.annotation.AccountType.FANFOU -> twitter.fanfouTrends
details.type == FANFOU -> twitter.fanfouTrends
else -> twitter.getLocationTrends(woeId).firstOrNull()
} ?: return
storeTrends(context.contentResolver, org.mariotaku.twidere.provider.TwidereDataStore.CachedTrends.Local.CONTENT_URI, trends)
} catch (e: org.mariotaku.microblog.library.MicroBlogException) {
org.mariotaku.twidere.util.DebugLog.w(LOGTAG, tr = e)
storeTrends(context.contentResolver, CachedTrends.Local.CONTENT_URI, trends)
} catch (e: MicroBlogException) {
w(LOGTAG, tr = e)
}
}
override fun afterExecute(handler: Any?, result: Unit) {
bus.post(org.mariotaku.twidere.model.event.TrendsRefreshedEvent())
bus.post(TrendsRefreshedEvent())
}
private fun storeTrends(cr: android.content.ContentResolver, uri: android.net.Uri, trends: org.mariotaku.microblog.library.twitter.model.Trends) {
val hashtags = android.support.v4.util.ArraySet<String>()
val deleteWhere = org.mariotaku.sqliteqb.library.Expression.and(org.mariotaku.sqliteqb.library.Expression.equalsArgs(org.mariotaku.twidere.provider.TwidereDataStore.CachedTrends.ACCOUNT_KEY),
org.mariotaku.sqliteqb.library.Expression.equalsArgs(org.mariotaku.twidere.provider.TwidereDataStore.CachedTrends.WOEID)).sql
private fun storeTrends(cr: ContentResolver, uri: Uri, trends: Trends) {
val hashtags = ArraySet<String>()
val deleteWhere = and(equalsArgs(CachedTrends.ACCOUNT_KEY), equalsArgs(CachedTrends.WOEID)).sql
val deleteWhereArgs = arrayOf(accountKey.toString(), woeId.toString())
cr.delete(org.mariotaku.twidere.provider.TwidereDataStore.CachedTrends.Local.CONTENT_URI, deleteWhere, deleteWhereArgs)
cr.delete(CachedTrends.Local.CONTENT_URI, deleteWhere, deleteWhereArgs)
val allTrends = java.util.ArrayList<org.mariotaku.twidere.model.ParcelableTrend>()
val allTrends = ArrayList<ParcelableTrend>()
trends.trends.forEachIndexed { idx, trend ->
val hashtag = trend.name.replaceFirst("#", "")
hashtags.add(hashtag)
allTrends.add(org.mariotaku.twidere.model.ParcelableTrend().apply {
allTrends.add(ParcelableTrend().apply {
this.account_key = accountKey
this.woe_id = woeId
this.name = trend.name
@ -90,10 +92,11 @@ class GetTrendsTask(
this.trend_order = idx
})
}
org.mariotaku.twidere.util.content.ContentResolverUtils.bulkInsert(cr, uri, allTrends.map(org.mariotaku.twidere.model.ParcelableTrendValuesCreator::create))
val creator = ObjectCursor.valuesCreatorFrom(ParcelableTrend::class.java)
bulkInsert(cr, uri, allTrends.map(creator::create))
ContentResolverUtils.bulkDelete(cr, CachedHashtags.CONTENT_URI, CachedHashtags.NAME, false,
hashtags, null, null)
ContentResolverUtils.bulkInsert(cr, CachedHashtags.CONTENT_URI, hashtags.map {
bulkInsert(cr, CachedHashtags.CONTENT_URI, hashtags.map {
val values = ContentValues()
values.put(CachedHashtags.NAME, it)
return@map values

View File

@ -21,6 +21,7 @@ import net.ypresto.androidtranscoder.format.MediaFormatStrategyPresets
import org.apache.commons.lang3.ArrayUtils
import org.apache.commons.lang3.math.NumberUtils
import org.mariotaku.ktextension.*
import org.mariotaku.library.objectcursor.ObjectCursor
import org.mariotaku.microblog.library.MicroBlog
import org.mariotaku.microblog.library.MicroBlogException
import org.mariotaku.microblog.library.fanfou.model.PhotoStatusUpdate
@ -646,8 +647,8 @@ class UpdateStatusTask(
val sizeLimit = account.mediaSizeLimit
body = getBodyFromMedia(context, media, sizeLimit, chucked,
ContentLengthInputStream.ReadListener { length, position ->
callback?.onUploadingProgressChanged(index, position, length)
})
callback?.onUploadingProgressChanged(index, position, length)
})
val mediaUploadEvent = MediaUploadEvent.create(context, media)
mediaUploadEvent.setFileSize(body.body.length())
body.geometry?.let { geometry ->
@ -927,7 +928,8 @@ class UpdateStatusTask(
draft.timestamp = System.currentTimeMillis()
config(draft)
val resolver = context.contentResolver
val draftUri = resolver.insert(Drafts.CONTENT_URI, DraftValuesCreator.create(draft)) ?: return -1
val creator = ObjectCursor.valuesCreatorFrom(Draft::class.java)
val draftUri = resolver.insert(Drafts.CONTENT_URI, creator.create(draft)) ?: return -1
return NumberUtils.toLong(draftUri.lastPathSegment, -1)
}

View File

@ -25,6 +25,7 @@ import android.content.Context
import org.mariotaku.ktextension.toInt
import org.mariotaku.ktextension.toLong
import org.mariotaku.ktextension.useCursor
import org.mariotaku.library.objectcursor.ObjectCursor
import org.mariotaku.microblog.library.MicroBlog
import org.mariotaku.microblog.library.MicroBlogException
import org.mariotaku.microblog.library.twitter.model.DMResponse
@ -429,18 +430,20 @@ class GetMessagesTask(
fun storeMessages(context: Context, data: DatabaseUpdateData, details: AccountDetails,
showNotification: Boolean = false) {
val resolver = context.contentResolver
val conversationCreator = ObjectCursor.valuesCreatorFrom(ParcelableMessageConversation::class.java)
val conversationsValues = data.conversations.filterNot {
it.id in data.deleteConversations
}.map {
val values = ParcelableMessageConversationValuesCreator.create(it)
val values = conversationCreator.create(it)
if (it._id > 0) {
values.put(Conversations._ID, it._id)
}
return@map values
}
val messageCreator = ObjectCursor.valuesCreatorFrom(ParcelableMessage::class.java)
val messagesValues = data.messages.filterNot {
data.deleteMessages[it.conversation_id]?.contains(it.id) ?: false
}.map(ParcelableMessageValuesCreator::create)
}.map(messageCreator::create)
for ((conversationId, messageIds) in data.deleteMessages) {
val where = Expression.and(Expression.equalsArgs(Messages.ACCOUNT_KEY),
@ -480,11 +483,11 @@ class GetMessagesTask(
val whereArgs = newIds.toTypedArray() + accountKey.toString()
return context.contentResolver.query(Conversations.CONTENT_URI, Conversations.COLUMNS,
where, whereArgs, null).useCursor { cur ->
val indices = ParcelableMessageConversationCursorIndices(cur)
val indices = ObjectCursor.indicesFrom(cur, ParcelableMessageConversation::class.java)
cur.moveToFirst()
while (!cur.isAfterLast) {
val conversationId = cur.getString(indices.id)
val timestamp = cur.getLong(indices.local_timestamp)
val conversationId = cur.getString(indices[Conversations.CONVERSATION_ID])
val timestamp = cur.getLong(indices[Conversations.LOCAL_TIMESTAMP])
val conversation = this[conversationId] ?: run {
val obj = indices.newObject(cur)
this[conversationId] = obj

View File

@ -23,6 +23,7 @@ import android.accounts.AccountManager
import android.annotation.SuppressLint
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
@ -31,7 +32,10 @@ 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.model.*
import org.mariotaku.twidere.model.AccountDetails
import org.mariotaku.twidere.model.ParcelableMessage
import org.mariotaku.twidere.model.ParcelableMessageConversation
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.model.message.conversation.TwitterOfficialConversationExtras
import org.mariotaku.twidere.model.util.AccountUtils
import org.mariotaku.twidere.provider.TwidereDataStore.Messages
@ -103,7 +107,8 @@ class MarkMessageReadTask(
where, whereArgs, OrderBy(Messages.LOCAL_TIMESTAMP, false).sql) ?: return null
try {
if (cur.moveToFirst()) {
return ParcelableMessageCursorIndices.fromCursor(cur)
val indices = ObjectCursor.indicesFrom(cur, ParcelableMessage::class.java)
return indices.newObject(cur)
}
} finally {
cur.close()

View File

@ -6,10 +6,10 @@ import android.database.sqlite.SQLiteDatabase
import com.bluelinelabs.logansquare.LoganSquare
import org.mariotaku.ktextension.HexColorFormat
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.model.ParcelableCredentials
import org.mariotaku.twidere.model.ParcelableCredentialsCursorIndices
import org.mariotaku.twidere.model.ParcelableUser
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.model.account.cred.BasicCredentials
@ -27,7 +27,7 @@ import org.mariotaku.twidere.provider.TwidereDataStore.Accounts
fun migrateAccounts(am: AccountManager, db: SQLiteDatabase) {
val cur = db.query(Accounts.TABLE_NAME, Accounts.COLUMNS, null, null, null, null, null) ?: return
try {
val indices = ParcelableCredentialsCursorIndices(cur)
val indices = ObjectCursor.indicesFrom(cur, ParcelableCredentials::class.java)
cur.moveToFirst()
while (!cur.isAfterLast) {
val credentials = indices.newObject(cur)

View File

@ -30,6 +30,7 @@ import android.net.Uri
import android.support.v4.app.NotificationCompat
import org.mariotaku.kpreferences.get
import org.mariotaku.ktextension.isEmpty
import org.mariotaku.library.objectcursor.ObjectCursor
import org.mariotaku.microblog.library.twitter.model.Activity
import org.mariotaku.sqliteqb.library.*
import org.mariotaku.sqliteqb.library.Columns.Column
@ -99,22 +100,22 @@ class ContentNotificationManager(
val usersCount = userCursor.count
val statusesCount = statusCursor.count
if (statusesCount == 0 || usersCount == 0) return
val statusIndices = ParcelableStatusCursorIndices(statusCursor)
val userIndices = ParcelableStatusCursorIndices(userCursor)
val positionKey = if (statusCursor.moveToFirst()) statusCursor.getLong(statusIndices.position_key) else -1L
val statusIndices = ObjectCursor.indicesFrom(statusCursor, ParcelableStatus::class.java)
val userIndices = ObjectCursor.indicesFrom(userCursor, ParcelableStatus::class.java)
val positionKey = if (statusCursor.moveToFirst()) statusCursor.getLong(statusIndices[Statuses.POSITION_KEY]) else -1L
val notificationTitle = resources.getQuantityString(R.plurals.N_new_statuses,
statusesCount, statusesCount)
val notificationContent: String
userCursor.moveToFirst()
val displayName = userColorNameManager.getDisplayName(userCursor.getString(userIndices.user_key),
userCursor.getString(userIndices.user_name), userCursor.getString(userIndices.user_screen_name),
val displayName = userColorNameManager.getDisplayName(userCursor.getString(userIndices[Statuses.USER_KEY]),
userCursor.getString(userIndices[Statuses.USER_NAME]), userCursor.getString(userIndices[Statuses.USER_SCREEN_NAME]),
nameFirst)
if (usersCount == 1) {
notificationContent = context.getString(R.string.from_name, displayName)
} else if (usersCount == 2) {
userCursor.moveToPosition(1)
val othersName = userColorNameManager.getDisplayName(userCursor.getString(userIndices.user_key),
userCursor.getString(userIndices.user_name), userCursor.getString(userIndices.user_screen_name),
val othersName = userColorNameManager.getDisplayName(userCursor.getString(userIndices[Statuses.USER_KEY]),
userCursor.getString(userIndices[Statuses.USER_NAME]), userCursor.getString(userIndices[Statuses.USER_SCREEN_NAME]),
nameFirst)
notificationContent = resources.getString(R.string.from_name_and_name, displayName, othersName)
} else {
@ -178,7 +179,7 @@ class ContentNotificationManager(
builder.setStyle(style)
builder.setAutoCancel(true)
style.setSummaryText(accountName)
val ci = ParcelableActivityCursorIndices(c)
val ci = ObjectCursor.indicesFrom(c, ParcelableActivity::class.java)
var timestamp: Long = -1
val filteredUserIds = DataStoreUtils.getFilteredUserIds(context)
@ -276,11 +277,11 @@ class ContentNotificationManager(
try {
if (cur.isEmpty) return
val indices = ParcelableMessageConversationCursorIndices(cur)
val indices = ObjectCursor.indicesFrom(cur, ParcelableMessageConversation::class.java)
var messageSum: Int = 0
cur.forEachRow { cur, pos ->
messageSum += cur.getInt(indices.unread_count)
messageSum += cur.getInt(indices[Conversations.UNREAD_COUNT])
return@forEachRow true
}

View File

@ -20,6 +20,7 @@
package org.mariotaku.twidere.util
import android.content.ContentValues
import org.mariotaku.library.objectcursor.ObjectCursor
import org.mariotaku.microblog.library.twitter.model.SavedSearch
import org.mariotaku.microblog.library.twitter.model.Status
import org.mariotaku.microblog.library.twitter.model.User
@ -34,7 +35,7 @@ object ContentValuesCreator {
fun createCachedUser(user: User, profileImageSize: String = "normal"): ContentValues {
val values = ContentValues()
ParcelableUserValuesCreator.writeTo(ParcelableUserUtils.fromUser(user, null,
ObjectCursor.valuesCreatorFrom(ParcelableUser::class.java).writeTo(ParcelableUserUtils.fromUser(user, null,
profileImageSize = profileImageSize), values)
return values
}
@ -78,8 +79,8 @@ object ContentValuesCreator {
}
fun createStatus(orig: Status, accountKey: UserKey, profileImageSize: String): ContentValues {
return ParcelableStatusValuesCreator.create(ParcelableStatusUtils.fromStatus(orig,
accountKey, false, profileImageSize))
return ObjectCursor.valuesCreatorFrom(ParcelableStatus::class.java)
.create(ParcelableStatusUtils.fromStatus(orig, accountKey, false, profileImageSize))
}
fun createActivity(activity: ParcelableActivity, details: AccountDetails): ContentValues {
@ -109,7 +110,7 @@ object ContentValuesCreator {
activity.status_text_plain = status.text_plain
activity.status_source = status.source
}
ParcelableActivityValuesCreator.writeTo(activity, values)
ObjectCursor.valuesCreatorFrom(ParcelableActivity::class.java).writeTo(activity, values)
return values
}

View File

@ -10,11 +10,15 @@ import android.support.annotation.WorkerThread
import android.support.v4.util.LongSparseArray
import org.mariotaku.kpreferences.get
import org.mariotaku.ktextension.useCursor
import org.mariotaku.library.objectcursor.ObjectCursor
import org.mariotaku.sqliteqb.library.*
import org.mariotaku.twidere.constant.filterPossibilitySensitiveStatusesKey
import org.mariotaku.twidere.constant.filterUnavailableQuoteStatusesKey
import org.mariotaku.twidere.model.*
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.util.DataStoreUtils.ACTIVITIES_URIS
import java.io.IOException
@ -94,7 +98,7 @@ fun deleteDrafts(context: Context, draftIds: LongArray): Int {
context.contentResolver.query(Drafts.CONTENT_URI, Drafts.COLUMNS, where, whereArgs,
null).useCursor { cursor ->
val indices = DraftCursorIndices(cursor)
val indices = ObjectCursor.indicesFrom(cursor, Draft::class.java)
cursor.moveToFirst()
while (!cursor.isAfterLast) {
val draft = indices.newObject(cursor)
@ -194,12 +198,13 @@ fun updateActivity(cr: ContentResolver, uri: Uri,
val c = cr.query(uri, Activities.COLUMNS, where, whereArgs, null) ?: return
val values = LongSparseArray<ContentValues>()
try {
val ci = ParcelableActivityCursorIndices(c)
val ci = ObjectCursor.indicesFrom(c, ParcelableActivity::class.java)
val vc = ObjectCursor.valuesCreatorFrom(ParcelableActivity::class.java)
c.moveToFirst()
while (!c.isAfterLast) {
val activity = ci.newObject(c)
action(activity)
values.put(activity._id, ParcelableActivityValuesCreator.create(activity))
values.put(activity._id, vc.create(activity))
c.moveToNext()
}
} catch (e: IOException) {

View File

@ -159,7 +159,8 @@ object DataStoreUtils {
if (accountKeys.all { it == null }) return arrayOfNulls(accountKeys.size)
return getObjectFieldArray(context, uri, accountKeys, Conversations.ACCOUNT_KEY, Conversations.COLUMNS,
OrderBy(SQLFunctions.MIN(Messages.LOCAL_TIMESTAMP)), null, null,
::ParcelableMessageConversationCursorIndices, { arrayOfNulls<ParcelableMessageConversation>(it) })
{ ObjectCursor.indicesFrom(it, ParcelableMessageConversation::class.java) },
{ arrayOfNulls<ParcelableMessageConversation>(it) })
}
fun getNewestConversations(context: Context, uri: Uri, accountKeys: Array<UserKey?>,
@ -167,7 +168,8 @@ object DataStoreUtils {
if (accountKeys.all { it == null }) return arrayOfNulls(accountKeys.size)
return getObjectFieldArray(context, uri, accountKeys, Conversations.ACCOUNT_KEY, Conversations.COLUMNS,
OrderBy(SQLFunctions.MAX(Messages.LOCAL_TIMESTAMP)), extraWhere, extraWhereArgs,
::ParcelableMessageConversationCursorIndices, { arrayOfNulls<ParcelableMessageConversation>(it) })
{ ObjectCursor.indicesFrom(it, ParcelableMessageConversation::class.java) },
{ arrayOfNulls<ParcelableMessageConversation>(it) })
}
fun getNewestStatusSortIds(context: Context, uri: Uri, accountKeys: Array<UserKey?>): LongArray {
@ -800,6 +802,8 @@ object DataStoreUtils {
val cr = context.contentResolver
try {
val baseCreator = ObjectCursor.valuesCreatorFrom(FiltersData.BaseItem::class.java)
val userCreator = ObjectCursor.valuesCreatorFrom(FiltersData.UserItem::class.java)
val userValues = ArrayList<ContentValues>()
val keywordValues = ArrayList<ContentValues>()
val linkValues = ArrayList<ContentValues>()
@ -808,12 +812,12 @@ object DataStoreUtils {
userItem.userKey = user.key
userItem.screenName = user.screen_name
userItem.name = user.name
userValues.add(`FiltersData$UserItemValuesCreator`.create(userItem))
userValues.add(userCreator.create(userItem))
val keywordItem = FiltersData.BaseItem()
keywordItem.value = "@" + user.screen_name
keywordItem.userKey = user.key
keywordValues.add(`FiltersData$BaseItemValuesCreator`.create(keywordItem))
keywordValues.add(baseCreator.create(keywordItem))
// Insert user link (without scheme) to links
val linkItem = FiltersData.BaseItem()
@ -821,7 +825,7 @@ object DataStoreUtils {
val linkWithoutScheme = userLink.toString().substringAfter("://")
linkItem.value = linkWithoutScheme
linkItem.userKey = user.key
linkValues.add(`FiltersData$BaseItemValuesCreator`.create(linkItem))
linkValues.add(baseCreator.create(linkItem))
}
ContentResolverUtils.bulkInsert(cr, Filters.Users.CONTENT_URI, userValues)
@ -861,8 +865,9 @@ object DataStoreUtils {
for (uri in DataStoreUtils.STATUSES_URIS) {
val cur = resolver.query(uri, Statuses.COLUMNS, where, whereArgs, null) ?: continue
try {
if (cur.count > 0 && cur.moveToFirst()) {
status = ParcelableStatusCursorIndices.fromCursor(cur)
if (cur.moveToFirst()) {
val indices = ObjectCursor.indicesFrom(cur, ParcelableStatus::class.java)
status = indices.newObject(cur)
}
} finally {
cur.close()
@ -885,7 +890,7 @@ object DataStoreUtils {
val resolver = context.contentResolver
val status = ParcelableStatusUtils.fromStatus(result, accountKey, false)
resolver.delete(CachedStatuses.CONTENT_URI, where, whereArgs)
resolver.insert(CachedStatuses.CONTENT_URI, ParcelableStatusValuesCreator.create(status))
resolver.insert(CachedStatuses.CONTENT_URI, ObjectCursor.valuesCreatorFrom(ParcelableStatus::class.java).create(status))
return status
}
@ -898,7 +903,8 @@ object DataStoreUtils {
val cur = resolver.query(Conversations.CONTENT_URI, Conversations.COLUMNS, where, whereArgs, null) ?: return null
try {
if (cur.moveToFirst()) {
return ParcelableMessageConversationCursorIndices.fromCursor(cur)
val indices = ObjectCursor.indicesFrom(cur, ParcelableMessageConversation::class.java)
return indices.newObject(cur)
}
} finally {
cur.close()

View File

@ -26,6 +26,7 @@ import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
import android.os.Build
import org.mariotaku.kpreferences.get
import org.mariotaku.library.objectcursor.ObjectCursor
import org.mariotaku.sqliteqb.library.*
import org.mariotaku.sqliteqb.library.Columns.Column
import org.mariotaku.sqliteqb.library.query.SQLCreateTriggerQuery.Event
@ -34,7 +35,6 @@ import org.mariotaku.twidere.TwidereConstants.SHARED_PREFERENCES_NAME
import org.mariotaku.twidere.annotation.CustomTabType
import org.mariotaku.twidere.constant.defaultAPIConfigKey
import org.mariotaku.twidere.model.Tab
import org.mariotaku.twidere.model.TabValuesCreator
import org.mariotaku.twidere.model.tab.TabConfiguration
import org.mariotaku.twidere.provider.TwidereDataStore.*
import org.mariotaku.twidere.provider.TwidereDataStore.Messages.Conversations
@ -104,6 +104,7 @@ class TwidereSQLiteOpenHelper(
private fun setupDefaultTabs(db: SQLiteDatabase) {
val creator = ObjectCursor.valuesCreatorFrom(Tab::class.java)
db.beginTransaction()
@CustomTabType
val tabTypes = arrayOf(CustomTabType.HOME_TIMELINE, CustomTabType.NOTIFICATIONS_TIMELINE,
@ -117,7 +118,7 @@ class TwidereSQLiteOpenHelper(
this.icon = conf!!.icon.persistentKey
this.position = i
}
db.insert(Tabs.TABLE_NAME, null, TabValuesCreator.create(tab))
db.insert(Tabs.TABLE_NAME, null, creator.create(tab))
}
db.setTransactionSuccessful()
db.endTransaction()

View File

@ -4,12 +4,11 @@ import android.content.Context
import android.support.v4.util.LongSparseArray
import org.mariotaku.ktextension.map
import org.mariotaku.ktextension.set
import org.mariotaku.library.objectcursor.ObjectCursor
import org.mariotaku.sqliteqb.library.Expression
import org.mariotaku.twidere.extension.model.filename
import org.mariotaku.twidere.extension.model.unique_id_non_null
import org.mariotaku.twidere.model.Draft
import org.mariotaku.twidere.model.DraftCursorIndices
import org.mariotaku.twidere.model.DraftValuesCreator
import org.mariotaku.twidere.provider.TwidereDataStore.Drafts
import org.mariotaku.twidere.util.DebugLog
import org.mariotaku.twidere.util.content.ContentResolverUtils
@ -45,7 +44,8 @@ abstract class FileBasedDraftsSyncAction<RemoteFileInfo>(val context: Context) :
val localDrafts = run {
val cur = context.contentResolver.query(Drafts.CONTENT_URI, Drafts.COLUMNS, null, null, null)!!
try {
return@run cur.map(DraftCursorIndices(cur))
val indices = ObjectCursor.indicesFrom(cur, Draft::class.java)
return@run cur.map(indices)
} finally {
cur.close()
}
@ -121,19 +121,20 @@ abstract class FileBasedDraftsSyncAction<RemoteFileInfo>(val context: Context) :
val fileList = downloadRemoteInfoList.joinToString(",") { it.draftFileName }
DebugLog.d(LOGTAG_SYNC, "Downloading remote drafts $fileList")
ContentResolverUtils.bulkInsert(context.contentResolver, Drafts.CONTENT_URI,
downloadDrafts(downloadRemoteInfoList).map { DraftValuesCreator.create(it) })
downloadDrafts(downloadRemoteInfoList).map { ObjectCursor.valuesCreatorFrom(Draft::class.java).create(it) })
}
// Update local items
if (updateLocalInfoList.size() > 0) {
val fileList = (0 until updateLocalInfoList.size()).joinToString(",") { updateLocalInfoList.valueAt(it).draftFileName }
DebugLog.d(LOGTAG_SYNC, "Updating local drafts $fileList")
val creator = ObjectCursor.valuesCreatorFrom(Draft::class.java)
for (index in 0 until updateLocalInfoList.size()) {
val draft = Draft()
if (draft.loadFromRemote(updateLocalInfoList.valueAt(index))) {
val where = Expression.equalsArgs(Drafts._ID).sql
val whereArgs = arrayOf(updateLocalInfoList.keyAt(index).toString())
context.contentResolver.update(Drafts.CONTENT_URI, DraftValuesCreator.create(draft), where, whereArgs)
context.contentResolver.update(Drafts.CONTENT_URI, creator.create(draft), where, whereArgs)
}
}
}
@ -156,7 +157,8 @@ abstract class FileBasedDraftsSyncAction<RemoteFileInfo>(val context: Context) :
snapshotsListFile.writer().use { writer ->
val cur = context.contentResolver.query(Drafts.CONTENT_URI, Drafts.COLUMNS, null, null, null)!!
try {
cur.map(DraftCursorIndices(cur)).map { it.unique_id_non_null }.forEach { line ->
val indices = ObjectCursor.indicesFrom(cur, Draft::class.java)
cur.map(indices).map { it.unique_id_non_null }.forEach { line ->
writer.write(line)
writer.write("\n")
}