1
0
mirror of https://github.com/TwidereProject/Twidere-Android synced 2025-02-17 04:00:48 +01:00

added universal search api

This commit is contained in:
Mariotaku Lee 2016-08-18 21:02:49 +08:00
parent 533d8ad26b
commit 86758eb1d0
10 changed files with 225 additions and 72 deletions

View File

@ -3,6 +3,7 @@ package org.mariotaku.microblog.library.twitter;
import org.mariotaku.microblog.library.twitter.api.PrivateActivityResources;
import org.mariotaku.microblog.library.twitter.api.PrivateDirectMessagesResources;
import org.mariotaku.microblog.library.twitter.api.PrivateFriendsFollowersResources;
import org.mariotaku.microblog.library.twitter.api.PrivateSearchResources;
import org.mariotaku.microblog.library.twitter.api.PrivateTimelineResources;
import org.mariotaku.microblog.library.twitter.api.PrivateTweetResources;
@ -10,5 +11,6 @@ import org.mariotaku.microblog.library.twitter.api.PrivateTweetResources;
* Created by mariotaku on 16/3/4.
*/
public interface TwitterPrivate extends PrivateActivityResources, PrivateTweetResources,
PrivateTimelineResources, PrivateFriendsFollowersResources, PrivateDirectMessagesResources {
PrivateTimelineResources, PrivateFriendsFollowersResources, PrivateDirectMessagesResources,
PrivateSearchResources {
}

View File

@ -19,17 +19,21 @@
package org.mariotaku.microblog.library.twitter.api;
import org.mariotaku.restfu.annotation.method.GET;
import org.mariotaku.microblog.library.MicroBlogException;
import org.mariotaku.microblog.library.twitter.model.PrivateSearchQuery;
import org.mariotaku.microblog.library.twitter.model.PrivateSearchResult;
import org.mariotaku.microblog.library.twitter.model.UniversalSearchQuery;
import org.mariotaku.microblog.library.twitter.model.UniversalSearchResult;
import org.mariotaku.microblog.library.twitter.template.StatusAnnotationTemplate;
import org.mariotaku.restfu.annotation.method.GET;
import org.mariotaku.restfu.annotation.param.Queries;
import org.mariotaku.restfu.annotation.param.Query;
/**
* Created by mariotaku on 15/10/21.
*/
public interface PrivateSearchResources {
public interface PrivateSearchResources extends PrivateResources {
@GET("/search/universal.json")
PrivateSearchResult searchTweets(PrivateSearchQuery query) throws MicroBlogException;
@Queries(template = StatusAnnotationTemplate.class)
UniversalSearchResult universalSearch(@Query UniversalSearchQuery query) throws MicroBlogException;
}

View File

@ -1,26 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.microblog.library.twitter.model;
/**
* Created by mariotaku on 15/10/21.
*/
public class PrivateSearchResult {
}

View File

@ -24,8 +24,21 @@ import org.mariotaku.restfu.http.SimpleValueMap;
/**
* Created by mariotaku on 15/10/21.
*/
public class PrivateSearchQuery extends SimpleValueMap {
public class UniversalSearchQuery extends SimpleValueMap {
public void setCursor(String cursor) {
put("cursor", cursor);
}
public void setQuery(String query) {
put("q", query);
}
public void setCount(int count) {
put("count", count);
}
public void setModules(String[] modules) {
put("modules", modules);
}
}

View File

@ -0,0 +1,160 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.microblog.library.twitter.model;
import com.bluelinelabs.logansquare.annotation.JsonField;
import com.bluelinelabs.logansquare.annotation.JsonObject;
/**
* Created by mariotaku on 15/10/21.
*/
@JsonObject
public class UniversalSearchResult {
@JsonField(name = "metadata")
Metadata metadata;
@JsonField(name = "modules")
Module[] modules;
public Metadata getMetadata() {
return metadata;
}
public Module[] getModules() {
return modules;
}
@JsonObject
public static class Module {
@JsonField(name = "status")
StatusModule status;
@JsonField(name = "user_gallery")
UserGalleryModule userGallery;
}
@JsonObject
public static class StatusModule {
@JsonField(name = "metadata")
Metadata metadata;
@JsonField(name = "data")
Status data;
public Metadata getMetadata() {
return metadata;
}
public Status getData() {
return data;
}
@JsonObject
public static class Metadata {
@JsonField(name = "social_context")
SocialContext socialContext;
@JsonField(name = "result_type")
String resultType;
@JsonField(name = "auto_expand")
boolean autoExpand;
public SocialContext getSocialContext() {
return socialContext;
}
public String getResultType() {
return resultType;
}
public boolean isAutoExpand() {
return autoExpand;
}
@JsonObject
public static class SocialContext {
@JsonField(name = "following")
boolean following;
@JsonField(name = "followed_by")
boolean followedBy;
public boolean isFollowing() {
return following;
}
public boolean isFollowedBy() {
return followedBy;
}
}
}
}
@JsonObject
public static class UserGalleryModule {
@JsonField(name = "metadata")
Metadata metadata;
@JsonField(name = "data")
UserModule[] data;
public Metadata getMetadata() {
return metadata;
}
public UserModule[] getData() {
return data;
}
@JsonObject
public static class Metadata {
@JsonField(name = "result_type")
String resultType;
}
}
@JsonObject
public static class UserModule {
@JsonField(name = "metadata")
Object metadata;
@JsonField(name = "data")
User data;
public Object getMetadata() {
return metadata;
}
public User getData() {
return data;
}
@JsonObject
public static class Metadata {
@JsonField(name = "result_type")
String resultType;
}
}
@JsonObject
public static class Metadata {
@JsonField(name = "cursor")
String cursor;
public String getCursor() {
return cursor;
}
}
}

View File

@ -112,6 +112,7 @@ dependencies {
debugCompile 'com.facebook.stetho:stetho:1.3.1'
debugCompile 'com.facebook.stetho:stetho-okhttp3:1.3.1'
debugCompile 'com.facebook.stetho:stetho-js-rhino:1.3.1'
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.4-beta2'
provided 'javax.annotation:jsr250-api:1.0'

View File

@ -28,7 +28,6 @@ import android.view.Menu
import android.view.MenuItem
import android.widget.Toast
import com.twitter.Extractor
import org.mariotaku.twidere.Constants
import org.mariotaku.twidere.R
import org.mariotaku.twidere.activity.BaseActivity
import org.mariotaku.twidere.constant.IntentConstants.*
@ -44,7 +43,9 @@ import java.util.*
import javax.inject.Inject
@SuppressLint("Registered")
class MultiSelectEventHandler(private val activity: BaseActivity) : Constants, ActionMode.Callback, MultiSelectManager.Callback {
class MultiSelectEventHandler(
private val activity: BaseActivity
) : ActionMode.Callback, MultiSelectManager.Callback {
@Inject
lateinit var twitterWrapper: AsyncTwitterWrapper
@ -52,9 +53,9 @@ class MultiSelectEventHandler(private val activity: BaseActivity) : Constants, A
@Inject
lateinit var multiSelectManager: MultiSelectManager
private var mActionMode: ActionMode? = null
private var actionMode: ActionMode? = null
private var mAccountActionProvider: AccountActionProvider? = null
private var accountActionProvider: AccountActionProvider? = null
init {
GeneralComponentHelper.build(activity).inject(this)
@ -108,11 +109,11 @@ class MultiSelectEventHandler(private val activity: BaseActivity) : Constants, A
bundle.putStringArray(EXTRA_SCREEN_NAMES, allMentions.toTypedArray())
intent.putExtras(bundle)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
activity!!.startActivity(intent)
activity.startActivity(intent)
mode.finish()
}
R.id.mute_user -> {
val resolver = activity!!.contentResolver
val resolver = activity.contentResolver
val valuesList = ArrayList<ContentValues>()
val userIds = HashSet<UserKey>()
for (`object` in selectedItems) {
@ -152,9 +153,7 @@ class MultiSelectEventHandler(private val activity: BaseActivity) : Constants, A
if (intent == null || !intent.hasExtra(EXTRA_ACCOUNT)) return false
val account = intent.getParcelableExtra<ParcelableAccount>(EXTRA_ACCOUNT)
multiSelectManager.accountKey = account.account_key
if (mAccountActionProvider != null) {
mAccountActionProvider!!.selectedAccountIds = arrayOf(account.account_key)
}
accountActionProvider?.selectedAccountIds = arrayOf(account.account_key)
mode.invalidate()
}
return true
@ -162,8 +161,8 @@ class MultiSelectEventHandler(private val activity: BaseActivity) : Constants, A
override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
mode.menuInflater.inflate(R.menu.action_multi_select_contents, menu)
mAccountActionProvider = menu.findItem(R.id.select_account).actionProvider as AccountActionProvider
mAccountActionProvider!!.selectedAccountIds = arrayOf(multiSelectManager.firstSelectAccountKey)
accountActionProvider = menu.findItem(R.id.select_account).actionProvider as AccountActionProvider
accountActionProvider?.selectedAccountIds = arrayOf(multiSelectManager.firstSelectAccountKey)
return true
}
@ -171,8 +170,8 @@ class MultiSelectEventHandler(private val activity: BaseActivity) : Constants, A
if (multiSelectManager.count != 0) {
multiSelectManager.clearSelectedItems()
}
mAccountActionProvider = null
mActionMode = null
accountActionProvider = null
actionMode = null
}
override fun onItemsCleared() {
@ -194,20 +193,18 @@ class MultiSelectEventHandler(private val activity: BaseActivity) : Constants, A
private fun updateMultiSelectState() {
if (multiSelectManager.isActive) {
if (mActionMode == null) {
mActionMode = activity!!.startActionMode(this)
if (actionMode == null) {
actionMode = activity.startActionMode(this)
}
updateSelectedCount(mActionMode)
updateSelectedCount(actionMode)
} else {
if (mActionMode != null) {
mActionMode!!.finish()
mActionMode = null
}
actionMode?.finish()
actionMode = null
}
}
private fun updateSelectedCount(mode: ActionMode?) {
if (mode == null || activity == null || multiSelectManager == null) return
if (mode == null) return
val count = multiSelectManager.count
mode.title = activity.resources.getQuantityString(R.plurals.Nitems_selected, count, count)
}

View File

@ -31,7 +31,7 @@ import org.mariotaku.twidere.R
import org.mariotaku.twidere.adapter.iface.IGapSupportedAdapter
import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter
import org.mariotaku.twidere.adapter.iface.IStatusesAdapter
import org.mariotaku.twidere.constant.SharedPreferenceConstants
import org.mariotaku.twidere.constant.SharedPreferenceConstants.*
import org.mariotaku.twidere.model.ParcelableStatus
import org.mariotaku.twidere.model.ParcelableStatusCursorIndices
import org.mariotaku.twidere.model.UserKey
@ -52,7 +52,9 @@ import org.mariotaku.twidere.view.holder.iface.IStatusViewHolder
abstract class ParcelableStatusesAdapter(
context: Context
) : LoadMoreSupportAdapter<RecyclerView.ViewHolder>(context), Constants, IStatusesAdapter<List<ParcelableStatus>> {
protected val inflater: LayoutInflater
override val mediaLoadingHandler: MediaLoadingHandler
override val twidereLinkify: TwidereLinkify
override val textSize: Float
@ -88,6 +90,7 @@ abstract class ParcelableStatusesAdapter(
field = value
notifyDataSetChanged()
}
private var data: List<ParcelableStatus>? = null
private var showingActionCardId = RecyclerView.NO_ID
private var lastItemFiltered: Boolean = false
@ -95,17 +98,17 @@ abstract class ParcelableStatusesAdapter(
init {
inflater = LayoutInflater.from(context)
mediaLoadingHandler = MediaLoadingHandler(*progressViewIds)
textSize = preferences.getInt(SharedPreferenceConstants.KEY_TEXT_SIZE, context.resources.getInteger(R.integer.default_text_size)).toFloat()
profileImageStyle = Utils.getProfileImageStyle(preferences.getString(SharedPreferenceConstants.KEY_PROFILE_IMAGE_STYLE, null))
mediaPreviewStyle = Utils.getMediaPreviewStyle(preferences.getString(SharedPreferenceConstants.KEY_MEDIA_PREVIEW_STYLE, null))
linkHighlightingStyle = Utils.getLinkHighlightingStyleInt(preferences.getString(SharedPreferenceConstants.KEY_LINK_HIGHLIGHT_OPTION, null))
nameFirst = preferences.getBoolean(SharedPreferenceConstants.KEY_NAME_FIRST, true)
profileImageEnabled = preferences.getBoolean(SharedPreferenceConstants.KEY_DISPLAY_PROFILE_IMAGE, true)
textSize = preferences.getInt(KEY_TEXT_SIZE, context.resources.getInteger(R.integer.default_text_size)).toFloat()
profileImageStyle = Utils.getProfileImageStyle(preferences.getString(KEY_PROFILE_IMAGE_STYLE, null))
mediaPreviewStyle = Utils.getMediaPreviewStyle(preferences.getString(KEY_MEDIA_PREVIEW_STYLE, null))
linkHighlightingStyle = Utils.getLinkHighlightingStyleInt(preferences.getString(KEY_LINK_HIGHLIGHT_OPTION, null))
nameFirst = preferences.getBoolean(KEY_NAME_FIRST, true)
profileImageEnabled = preferences.getBoolean(KEY_DISPLAY_PROFILE_IMAGE, true)
mediaPreviewEnabled = Utils.isMediaPreviewEnabled(context, preferences)
sensitiveContentEnabled = preferences.getBoolean(SharedPreferenceConstants.KEY_DISPLAY_SENSITIVE_CONTENTS, false)
showCardActions = !preferences.getBoolean(SharedPreferenceConstants.KEY_HIDE_CARD_ACTIONS, false)
useStarsForLikes = preferences.getBoolean(SharedPreferenceConstants.KEY_I_WANT_MY_STARS_BACK)
isShowAbsoluteTime = preferences.getBoolean(SharedPreferenceConstants.KEY_SHOW_ABSOLUTE_TIME, false)
sensitiveContentEnabled = preferences.getBoolean(KEY_DISPLAY_SENSITIVE_CONTENTS, false)
showCardActions = !preferences.getBoolean(KEY_HIDE_CARD_ACTIONS, false)
useStarsForLikes = preferences.getBoolean(KEY_I_WANT_MY_STARS_BACK)
isShowAbsoluteTime = preferences.getBoolean(KEY_SHOW_ABSOLUTE_TIME, false)
val handler = StatusAdapterLinkClickHandler<List<ParcelableStatus>>(context, preferences)
twidereLinkify = TwidereLinkify(handler)
handler.setAdapter(this)
@ -142,10 +145,7 @@ abstract class ParcelableStatusesAdapter(
}
override val rawStatusCount: Int
get() {
if (data == null) return 0
return data!!.size
}
get() = data?.size ?: 0
override fun getItemId(position: Int): Long {
val dataPosition = position - statusStartIndex

View File

@ -161,7 +161,9 @@ abstract class AbsStatusesFragment protected constructor() : AbsContentListRecyc
return true
}
KeyboardShortcutConstants.ACTION_STATUS_RETWEET -> {
RetweetQuoteDialogFragment.show(fragmentManager, status)
executeAfterFragmentResumed {
RetweetQuoteDialogFragment.show(fragmentManager, status)
}
return true
}
KeyboardShortcutConstants.ACTION_STATUS_FAVORITE -> {
@ -410,7 +412,7 @@ abstract class AbsStatusesFragment protected constructor() : AbsContentListRecyc
}
}
}
task.setCallback(recyclerView)
task.callback = recyclerView
TaskStarter.execute(task)
bus.register(statusesBusCallback)
}

View File

@ -80,7 +80,7 @@ object ParcelableActivityUtils {
if (item.isFollowing) {
return@fold true
}
return@fold false
return@fold folded
}
if (result.sources != null) {
result.source_ids = arrayOfNulls<UserKey>(result.sources.size)