parent
deae5ed743
commit
281eaf6910
|
@ -93,7 +93,7 @@ dependencies {
|
|||
compile 'com.android.support:palette-v7:21.0.3'
|
||||
compile 'com.sothree.slidinguppanel:library:2.0.4'
|
||||
compile 'it.sephiroth.android.library.imagezoom:imagezoom:2.1.1'
|
||||
compile 'com.twitter:twitter-text:1.10.2'
|
||||
compile 'com.twitter:twitter-text:1.9.9'
|
||||
compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.3'
|
||||
compile 'org.apache.httpcomponents:httpclient-android:4.3.5'
|
||||
compile 'org.apache.httpcomponents:httpmime:4.3.5'
|
||||
|
|
|
@ -170,7 +170,7 @@
|
|||
android:value=".activity.support.HomeActivity"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.support.GlobalSearchBoxActivity"
|
||||
android:name=".activity.support.QuickSearchBoxActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@style/Theme.Blank.Dialog"
|
||||
android:windowSoftInputMode="adjustResize"
|
||||
|
|
|
@ -28,7 +28,7 @@ package org.mariotaku.twidere;
|
|||
public interface Constants extends TwidereConstants {
|
||||
|
||||
public static final String DATABASES_NAME = "twidere.sqlite";
|
||||
public static final int DATABASES_VERSION = 76;
|
||||
public static final int DATABASES_VERSION = 78;
|
||||
|
||||
public static final int MENU_GROUP_STATUS_EXTENSION = 10;
|
||||
public static final int MENU_GROUP_COMPOSE_EXTENSION = 11;
|
||||
|
|
|
@ -159,6 +159,7 @@ public interface TwidereConstants extends SharedPreferenceConstants, IntentConst
|
|||
public static final int TABLE_ID_FILTERED_SOURCES = 33;
|
||||
public static final int TABLE_ID_FILTERED_LINKS = 34;
|
||||
public static final int TABLE_ID_TRENDS_LOCAL = 41;
|
||||
public static final int TABLE_ID_SAVED_SEARCHES = 42;
|
||||
public static final int TABLE_ID_DRAFTS = 51;
|
||||
public static final int TABLE_ID_TABS = 52;
|
||||
public static final int TABLE_ID_CACHED_USERS = 61;
|
||||
|
|
|
@ -209,7 +209,7 @@ public class FiltersActivity extends BaseSupportActivity implements TabListener,
|
|||
if (resultCode != RESULT_OK || !(filter instanceof FilteredUsersFragment) || !data.hasExtra(EXTRA_USER))
|
||||
return;
|
||||
final ParcelableUser user = data.getParcelableExtra(EXTRA_USER);
|
||||
final ContentValues values = ContentValuesCreator.makeFilteredUserContentValues(user);
|
||||
final ContentValues values = ContentValuesCreator.createFilteredUser(user);
|
||||
final ContentResolver resolver = getContentResolver();
|
||||
resolver.delete(Filters.Users.CONTENT_URI, Expression.equals(Filters.Users.USER_ID, user.id).getSQL(), null);
|
||||
resolver.insert(Filters.Users.CONTENT_URI, values);
|
||||
|
|
|
@ -543,7 +543,7 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa
|
|||
if (hasMedia()) {
|
||||
builder.media(getMedia());
|
||||
}
|
||||
final ContentValues values = ContentValuesCreator.makeStatusDraftContentValues(builder.build());
|
||||
final ContentValues values = ContentValuesCreator.createStatusDraft(builder.build());
|
||||
mResolver.insert(Drafts.CONTENT_URI, values);
|
||||
}
|
||||
|
||||
|
|
|
@ -838,7 +838,7 @@ public class HomeActivity extends BaseSupportActivity implements OnClickListener
|
|||
final IHomeActionButton hab = (IHomeActionButton) mActionsButton;
|
||||
hab.setIcon(icon);
|
||||
hab.setTitle(title);
|
||||
hab.setShowProgress(hasActivatedTask);
|
||||
// hab.setShowProgress(hasActivatedTask);
|
||||
}
|
||||
if (mSmartBarProgress != null) {
|
||||
mSmartBarProgress.setVisibility(hasActivatedTask ? View.VISIBLE : View.INVISIBLE);
|
||||
|
|
|
@ -21,34 +21,39 @@ package org.mariotaku.twidere.activity.support;
|
|||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.Gravity;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
import android.widget.TextView.OnEditorActionListener;
|
||||
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.adapter.AccountsSpinnerAdapter;
|
||||
import org.mariotaku.twidere.model.ParcelableAccount;
|
||||
import org.mariotaku.twidere.util.ParseUtils;
|
||||
import org.mariotaku.twidere.util.ThemeUtils;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/1/6.
|
||||
*/
|
||||
public class GlobalSearchBoxActivity extends BaseSupportActivity {
|
||||
public class QuickSearchBoxActivity extends BaseSupportActivity implements OnClickListener, OnEditorActionListener {
|
||||
|
||||
private Spinner mAccountSpinner;
|
||||
private EditText mSearchQuery;
|
||||
private View mSearchSubmit;
|
||||
|
||||
@Override
|
||||
public int getThemeResourceId() {
|
||||
return ThemeUtils.getGlobalSearchThemeResource(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onContentChanged() {
|
||||
super.onContentChanged();
|
||||
mAccountSpinner = (Spinner) findViewById(R.id.account_spinner);
|
||||
return ThemeUtils.getQuickSearchBoxThemeResource(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -67,6 +72,8 @@ public class GlobalSearchBoxActivity extends BaseSupportActivity {
|
|||
mAccountSpinner.setSelection(index);
|
||||
}
|
||||
}
|
||||
mSearchSubmit.setOnClickListener(this);
|
||||
mSearchQuery.setOnEditorActionListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -75,6 +82,44 @@ public class GlobalSearchBoxActivity extends BaseSupportActivity {
|
|||
updateWindowAttributes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
switch (v.getId()) {
|
||||
case R.id.search_submit: {
|
||||
doSearch();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onContentChanged() {
|
||||
super.onContentChanged();
|
||||
mAccountSpinner = (Spinner) findViewById(R.id.account_spinner);
|
||||
mSearchQuery = (EditText) findViewById(R.id.search_query);
|
||||
mSearchSubmit = findViewById(R.id.search_submit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||
if (event == null) return false;
|
||||
switch (event.getKeyCode()) {
|
||||
case KeyEvent.KEYCODE_ENTER: {
|
||||
doSearch();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void doSearch() {
|
||||
final String query = ParseUtils.parseString(mSearchQuery.getText());
|
||||
if (TextUtils.isEmpty(query)) return;
|
||||
final long accountId = mAccountSpinner.getSelectedItemId();
|
||||
Utils.openSearch(this, accountId, query);
|
||||
finish();
|
||||
}
|
||||
|
||||
private void updateWindowAttributes() {
|
||||
final Window window = getWindow();
|
||||
final WindowManager.LayoutParams attributes = window.getAttributes();
|
||||
|
@ -82,4 +127,8 @@ public class GlobalSearchBoxActivity extends BaseSupportActivity {
|
|||
window.setAttributes(attributes);
|
||||
}
|
||||
|
||||
public static class SuggestionItem {
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -51,6 +51,7 @@ import org.mariotaku.twidere.app.TwidereApplication;
|
|||
import org.mariotaku.twidere.fragment.support.BaseSupportDialogFragment;
|
||||
import org.mariotaku.twidere.provider.TweetStore.Accounts;
|
||||
import org.mariotaku.twidere.task.TwidereAsyncTask;
|
||||
import org.mariotaku.twidere.util.ContentValuesCreator;
|
||||
import org.mariotaku.twidere.util.OAuthPasswordAuthenticator;
|
||||
import org.mariotaku.twidere.util.OAuthPasswordAuthenticator.AuthenticationException;
|
||||
import org.mariotaku.twidere.util.OAuthPasswordAuthenticator.AuthenticityTokenException;
|
||||
|
@ -76,9 +77,7 @@ import twitter4j.http.HttpClientWrapper;
|
|||
import twitter4j.http.HttpResponse;
|
||||
|
||||
import static android.text.TextUtils.isEmpty;
|
||||
import static org.mariotaku.twidere.util.ContentValuesCreator.makeAccountContentValuesBasic;
|
||||
import static org.mariotaku.twidere.util.ContentValuesCreator.makeAccountContentValuesOAuth;
|
||||
import static org.mariotaku.twidere.util.ContentValuesCreator.makeAccountContentValuesTWIP;
|
||||
import static org.mariotaku.twidere.util.ContentValuesCreator.createAccount;
|
||||
import static org.mariotaku.twidere.util.Utils.getActivatedAccountIds;
|
||||
import static org.mariotaku.twidere.util.Utils.getNonEmptyString;
|
||||
import static org.mariotaku.twidere.util.Utils.isUserLoggedIn;
|
||||
|
@ -435,19 +434,19 @@ public class SignInActivity extends BaseSupportActivity implements TwitterConsta
|
|||
final ContentValues values;
|
||||
switch (result.auth_type) {
|
||||
case Accounts.AUTH_TYPE_BASIC: {
|
||||
values = makeAccountContentValuesBasic(result.conf, result.basic_username,
|
||||
values = createAccount(result.conf, result.basic_username,
|
||||
result.basic_password, result.user, result.color,
|
||||
result.api_url_format, result.no_version_suffix);
|
||||
break;
|
||||
}
|
||||
case Accounts.AUTH_TYPE_TWIP_O_MODE: {
|
||||
values = makeAccountContentValuesTWIP(result.conf, result.user, result.color,
|
||||
values = ContentValuesCreator.createAccount(result.conf, result.user, result.color,
|
||||
result.api_url_format, result.no_version_suffix);
|
||||
break;
|
||||
}
|
||||
case Accounts.AUTH_TYPE_OAUTH:
|
||||
case Accounts.AUTH_TYPE_XAUTH: {
|
||||
values = makeAccountContentValuesOAuth(result.conf, result.access_token,
|
||||
values = ContentValuesCreator.createAccount(result.conf, result.access_token,
|
||||
result.user, result.auth_type, result.color, result.api_url_format,
|
||||
result.same_oauth_signing_url, result.no_version_suffix);
|
||||
break;
|
||||
|
|
|
@ -65,7 +65,7 @@ import org.mariotaku.twidere.activity.iface.IThemedActivity;
|
|||
import org.mariotaku.twidere.activity.support.AccountsManagerActivity;
|
||||
import org.mariotaku.twidere.activity.support.ComposeActivity;
|
||||
import org.mariotaku.twidere.activity.support.DraftsActivity;
|
||||
import org.mariotaku.twidere.activity.support.GlobalSearchBoxActivity;
|
||||
import org.mariotaku.twidere.activity.support.QuickSearchBoxActivity;
|
||||
import org.mariotaku.twidere.activity.support.HomeActivity;
|
||||
import org.mariotaku.twidere.activity.support.UserProfileEditorActivity;
|
||||
import org.mariotaku.twidere.adapter.ArrayAdapter;
|
||||
|
@ -194,7 +194,7 @@ public class AccountsDashboardFragment extends BaseSupportListFragment implement
|
|||
// } else {
|
||||
// getActivity().onSearchRequested();
|
||||
// }
|
||||
final Intent intent = new Intent(getActivity(), GlobalSearchBoxActivity.class);
|
||||
final Intent intent = new Intent(getActivity(), QuickSearchBoxActivity.class);
|
||||
intent.putExtra(EXTRA_ACCOUNT_ID, account.account_id);
|
||||
startActivity(intent);
|
||||
closeAccountsDrawer();
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
package org.mariotaku.twidere.fragment.support;
|
||||
|
||||
import static org.mariotaku.twidere.util.ContentValuesCreator.makeFilteredUserContentValues;
|
||||
import static org.mariotaku.twidere.util.ContentValuesCreator.createFilteredUser;
|
||||
import static org.mariotaku.twidere.util.UserColorNameUtils.getDisplayName;
|
||||
import static org.mariotaku.twidere.util.content.ContentResolverUtils.bulkDelete;
|
||||
import static org.mariotaku.twidere.util.content.ContentResolverUtils.bulkInsert;
|
||||
|
@ -73,11 +73,11 @@ public class AddStatusFilterDialogFragment extends BaseSupportDialogFragment imp
|
|||
if (value instanceof ParcelableUserMention) {
|
||||
final ParcelableUserMention mention = (ParcelableUserMention) value;
|
||||
user_ids.add(mention.id);
|
||||
user_values.add(makeFilteredUserContentValues(mention));
|
||||
user_values.add(createFilteredUser(mention));
|
||||
} else if (value instanceof ParcelableStatus) {
|
||||
final ParcelableStatus status = (ParcelableStatus) value;
|
||||
user_ids.add(status.user_id);
|
||||
user_values.add(ContentValuesCreator.makeFilteredUserContentValues(status));
|
||||
user_values.add(ContentValuesCreator.createFilteredUser(status));
|
||||
} else if (info.type == FilterItemInfo.FILTER_TYPE_KEYWORD) {
|
||||
if (value != null) {
|
||||
final String keyword = ParseUtils.parseString(value);
|
||||
|
|
|
@ -19,15 +19,11 @@
|
|||
|
||||
package org.mariotaku.twidere.fragment.support;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.net.Uri;
|
||||
|
||||
import com.squareup.otto.Bus;
|
||||
import com.squareup.otto.Subscribe;
|
||||
|
||||
import org.mariotaku.twidere.app.TwidereApplication;
|
||||
import org.mariotaku.twidere.provider.TweetStore.Statuses;
|
||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||
import org.mariotaku.twidere.util.message.TaskStateChangedEvent;
|
||||
|
@ -57,6 +53,9 @@ public class HomeTimelineFragment extends CursorStatusesFragment {
|
|||
public int getStatuses(long[] accountIds, long[] maxIds, long[] sinceIds) {
|
||||
final AsyncTwitterWrapper twitter = getTwitterWrapper();
|
||||
if (twitter == null) return -1;
|
||||
if (maxIds == null) {
|
||||
return twitter.refreshAll(accountIds);
|
||||
}
|
||||
return twitter.getHomeTimelineAsync(accountIds, maxIds, sinceIds);
|
||||
}
|
||||
|
||||
|
|
|
@ -84,6 +84,7 @@ public class SearchFragment extends BaseSupportFragment implements RefreshScroll
|
|||
mViewPager.setAdapter(mAdapter);
|
||||
mViewPager.setOffscreenPageLimit(2);
|
||||
mPagerIndicator.setViewPager(mViewPager);
|
||||
mPagerIndicator.setTabDisplayOption(TabPagerIndicator.LABEL);
|
||||
if (activity instanceof IThemedActivity) {
|
||||
mPagerIndicator.setStripColor(((IThemedActivity) activity).getCurrentThemeColor());
|
||||
} else {
|
||||
|
|
|
@ -28,6 +28,7 @@ import android.content.res.Resources;
|
|||
import android.graphics.Color;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
|
@ -58,6 +59,7 @@ import android.widget.LinearLayout;
|
|||
import android.widget.Space;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.apache.http.protocol.HTTP;
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.activity.support.AccountSelectorActivity;
|
||||
import org.mariotaku.twidere.activity.support.ColorPickerDialogActivity;
|
||||
|
@ -97,6 +99,8 @@ import org.mariotaku.twidere.view.holder.GapViewHolder;
|
|||
import org.mariotaku.twidere.view.holder.LoadIndicatorViewHolder;
|
||||
import org.mariotaku.twidere.view.holder.StatusViewHolder;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
@ -340,7 +344,7 @@ public class StatusFragment extends BaseSupportFragment
|
|||
if (status == null) return;
|
||||
final Bundle args = new Bundle();
|
||||
args.putLong(EXTRA_ACCOUNT_ID, status.account_id);
|
||||
args.putLong(EXTRA_STATUS_ID, status.id);
|
||||
args.putLong(EXTRA_STATUS_ID, status.retweet_id > 0 ? status.retweet_id : status.id);
|
||||
args.putString(EXTRA_SCREEN_NAME, status.user_screen_name);
|
||||
if (mRepliesLoaderInitialized) {
|
||||
getLoaderManager().restartLoader(LOADER_ID_STATUS_REPLIES, args, mRepliesLoaderCallback);
|
||||
|
@ -863,6 +867,13 @@ public class StatusFragment extends BaseSupportFragment
|
|||
activityOption);
|
||||
break;
|
||||
}
|
||||
case R.id.retweets_container: {
|
||||
final ParcelableStatus status = adapter.getStatus(getPosition());
|
||||
final Fragment fragment = adapter.getFragment();
|
||||
final FragmentActivity activity = fragment.getActivity();
|
||||
Utils.openStatusRetweeters(activity, status.account_id, status.id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -947,7 +958,20 @@ public class StatusFragment extends BaseSupportFragment
|
|||
if (ParcelableCredentials.isOfficialCredentials(activity, account)) {
|
||||
StatusTranslateDialogFragment.show(fragment.getFragmentManager(), status);
|
||||
} else {
|
||||
final Resources resources = fragment.getResources();
|
||||
final Locale locale = resources.getConfiguration().locale;
|
||||
try {
|
||||
final String template = "http://translate.google.com/#%s|%s|%s";
|
||||
final String sourceLang = "auto";
|
||||
final String targetLang = URLEncoder.encode(locale.getLanguage(), HTTP.UTF_8);
|
||||
final String text = URLEncoder.encode(status.text_unescaped, HTTP.UTF_8);
|
||||
final Uri uri = Uri.parse(String.format(Locale.ROOT, template, sourceLang, targetLang, text));
|
||||
final Intent intent = new Intent(Intent.ACTION_VIEW, uri);
|
||||
intent.addCategory(Intent.CATEGORY_BROWSABLE);
|
||||
fragment.startActivity(intent);
|
||||
} catch (UnsupportedEncodingException ignore) {
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1079,6 +1103,8 @@ public class StatusFragment extends BaseSupportFragment
|
|||
mediaPreviewLoad.setOnClickListener(this);
|
||||
profileContainer.setOnClickListener(this);
|
||||
|
||||
retweetsContainer.setOnClickListener(this);
|
||||
|
||||
final float defaultTextSize = adapter.getTextSize();
|
||||
nameView.setTextSize(defaultTextSize * 1.25f);
|
||||
textView.setTextSize(defaultTextSize * 1.25f);
|
||||
|
|
|
@ -794,7 +794,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
|
|||
cr.delete(Filters.Users.CONTENT_URI, where.getSQL(), null);
|
||||
showInfoMessage(getActivity(), R.string.message_user_unmuted, false);
|
||||
} else {
|
||||
cr.insert(Filters.Users.CONTENT_URI, ContentValuesCreator.makeFilteredUserContentValues(user));
|
||||
cr.insert(Filters.Users.CONTENT_URI, ContentValuesCreator.createFilteredUser(user));
|
||||
showInfoMessage(getActivity(), R.string.message_user_muted, false);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -38,7 +38,7 @@ import twitter4j.Twitter;
|
|||
import twitter4j.TwitterException;
|
||||
import twitter4j.User;
|
||||
|
||||
import static org.mariotaku.twidere.util.ContentValuesCreator.makeCachedUserContentValues;
|
||||
import static org.mariotaku.twidere.util.ContentValuesCreator.createCachedUser;
|
||||
import static org.mariotaku.twidere.util.Utils.getTwitterInstance;
|
||||
import static org.mariotaku.twidere.util.Utils.isMyAccount;
|
||||
|
||||
|
@ -92,7 +92,7 @@ public final class ParcelableUserLoader extends AsyncTaskLoader<SingleResponse<P
|
|||
}
|
||||
try {
|
||||
final User user = TwitterWrapper.tryShowUser(twitter, mUserId, mScreenName);
|
||||
final ContentValues cachedUserValues = makeCachedUserContentValues(user);
|
||||
final ContentValues cachedUserValues = createCachedUser(user);
|
||||
final long userId = user.getId();
|
||||
final String cachedUserWhere = Expression.equals(CachedUsers.USER_ID, userId).getSQL();
|
||||
resolver.delete(CachedUsers.CONTENT_URI, cachedUserWhere, null);
|
||||
|
|
|
@ -425,6 +425,26 @@ public interface TweetStore {
|
|||
public static final String[] COLUMNS = new String[]{_ID, HOST, ADDRESS};
|
||||
}
|
||||
|
||||
public static interface SavedSearches extends BaseColumns {
|
||||
|
||||
public static final String TABLE_NAME = "saved_searches";
|
||||
|
||||
public static final String CONTENT_PATH = TABLE_NAME;
|
||||
|
||||
public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, CONTENT_PATH);
|
||||
|
||||
public static final String ACCOUNT_ID = "account_id";
|
||||
public static final String SEARCH_ID = "search_id";
|
||||
public static final String QUERY = "query";
|
||||
public static final String NAME = "name";
|
||||
public static final String CREATED_AT = "created_at";
|
||||
|
||||
public static final String[] COLUMNS = new String[]{_ID, ACCOUNT_ID, SEARCH_ID, CREATED_AT,
|
||||
QUERY, NAME};
|
||||
public static final String[] TYPES = new String[]{TYPE_PRIMARY_KEY, TYPE_INT, TYPE_INT,
|
||||
TYPE_INT, TYPE_TEXT, TYPE_TEXT};
|
||||
}
|
||||
|
||||
public static interface Drafts extends BaseColumns {
|
||||
|
||||
public static final int ACTION_UPDATE_STATUS = 1;
|
||||
|
|
|
@ -88,8 +88,7 @@ import twitter4j.TwitterException;
|
|||
import twitter4j.UserMentionEntity;
|
||||
|
||||
import static android.text.TextUtils.isEmpty;
|
||||
import static org.mariotaku.twidere.util.ContentValuesCreator.makeDirectMessageContentValues;
|
||||
import static org.mariotaku.twidere.util.ContentValuesCreator.makeDirectMessageDraftContentValues;
|
||||
import static org.mariotaku.twidere.util.ContentValuesCreator.createMessageDraft;
|
||||
import static org.mariotaku.twidere.util.Utils.getImagePathFromUri;
|
||||
import static org.mariotaku.twidere.util.Utils.getImageUploadStatus;
|
||||
import static org.mariotaku.twidere.util.Utils.getTwitterInstance;
|
||||
|
@ -241,14 +240,14 @@ public class BackgroundOperationService extends IntentService implements Constan
|
|||
final SingleResponse<ParcelableDirectMessage> result = sendDirectMessage(builder, accountId, recipientId, text,
|
||||
imageUri);
|
||||
if (result.getData() != null && result.getData().id > 0) {
|
||||
final ContentValues values = makeDirectMessageContentValues(result.getData());
|
||||
final ContentValues values = ContentValuesCreator.createDirectMessage(result.getData());
|
||||
final String delete_where = DirectMessages.ACCOUNT_ID + " = " + accountId + " AND "
|
||||
+ DirectMessages.MESSAGE_ID + " = " + result.getData().id;
|
||||
mResolver.delete(DirectMessages.Outbox.CONTENT_URI, delete_where, null);
|
||||
mResolver.insert(DirectMessages.Outbox.CONTENT_URI, values);
|
||||
showOkMessage(R.string.direct_message_sent, false);
|
||||
} else {
|
||||
final ContentValues values = makeDirectMessageDraftContentValues(accountId, recipientId, text, imageUri);
|
||||
final ContentValues values = createMessageDraft(accountId, recipientId, text, imageUri);
|
||||
mResolver.insert(Drafts.CONTENT_URI, values);
|
||||
showErrorMessage(R.string.action_sending_direct_message, result.getException(), true);
|
||||
}
|
||||
|
@ -323,7 +322,7 @@ public class BackgroundOperationService extends IntentService implements Constan
|
|||
}
|
||||
|
||||
private void saveDrafts(final ParcelableStatusUpdate status, final List<Long> account_ids) {
|
||||
final ContentValues values = ContentValuesCreator.makeStatusDraftContentValues(status,
|
||||
final ContentValues values = ContentValuesCreator.createStatusDraft(status,
|
||||
ArrayUtils.fromList(account_ids));
|
||||
mResolver.insert(Drafts.CONTENT_URI, values);
|
||||
final String title = getString(R.string.status_not_updated);
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
|
||||
package org.mariotaku.twidere.task;
|
||||
|
||||
import static org.mariotaku.twidere.util.ContentValuesCreator.makeCachedUserContentValues;
|
||||
import static org.mariotaku.twidere.util.ContentValuesCreator.makeStatusContentValues;
|
||||
import static org.mariotaku.twidere.util.ContentValuesCreator.createCachedUser;
|
||||
import static org.mariotaku.twidere.util.ContentValuesCreator.createStatus;
|
||||
import static org.mariotaku.twidere.util.content.ContentResolverUtils.bulkDelete;
|
||||
import static org.mariotaku.twidere.util.content.ContentResolverUtils.bulkInsert;
|
||||
|
||||
|
@ -76,7 +76,7 @@ public class CacheUsersStatusesTask extends TwidereAsyncTask<Void, Void, Void> i
|
|||
continue;
|
||||
}
|
||||
status_ids.add(status.getId());
|
||||
cached_statuses_values.add(makeStatusContentValues(status, values.account_id));
|
||||
cached_statuses_values.add(createStatus(status, values.account_id));
|
||||
hashtags.addAll(extractor.extractHashtags(status.getText()));
|
||||
final User user = status.getUser();
|
||||
if (user != null && user.getId() > 0) {
|
||||
|
@ -103,7 +103,7 @@ public class CacheUsersStatusesTask extends TwidereAsyncTask<Void, Void, Void> i
|
|||
|
||||
for (final User user : users) {
|
||||
userIds.add(user.getId());
|
||||
cachedUsersValues.add(makeCachedUserContentValues(user));
|
||||
cachedUsersValues.add(createCachedUser(user));
|
||||
}
|
||||
bulkDelete(resolver, CachedUsers.CONTENT_URI, CachedUsers.USER_ID, userIds, null, false);
|
||||
bulkInsert(resolver, CachedUsers.CONTENT_URI, cachedUsersValues);
|
||||
|
|
|
@ -25,6 +25,7 @@ import android.text.style.URLSpan;
|
|||
import android.view.View;
|
||||
|
||||
import org.mariotaku.twidere.Constants;
|
||||
import org.mariotaku.twidere.util.ThemeUtils;
|
||||
import org.mariotaku.twidere.util.TwidereLinkify.OnLinkClickListener;
|
||||
|
||||
public class TwidereURLSpan extends URLSpan implements Constants {
|
||||
|
@ -65,7 +66,7 @@ public class TwidereURLSpan extends URLSpan implements Constants {
|
|||
ds.setUnderlineText(true);
|
||||
}
|
||||
if ((highlightStyle & VALUE_LINK_HIGHLIGHT_OPTION_CODE_HIGHLIGHT) != 0) {
|
||||
ds.setColor(ds.linkColor);
|
||||
ds.setColor(ThemeUtils.getOptimalLinkColor(ds.linkColor, ds.getColor()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,12 +54,14 @@ import org.mariotaku.twidere.provider.TweetStore.CachedTrends;
|
|||
import org.mariotaku.twidere.provider.TweetStore.CachedUsers;
|
||||
import org.mariotaku.twidere.provider.TweetStore.DirectMessages;
|
||||
import org.mariotaku.twidere.provider.TweetStore.Mentions;
|
||||
import org.mariotaku.twidere.provider.TweetStore.SavedSearches;
|
||||
import org.mariotaku.twidere.provider.TweetStore.Statuses;
|
||||
import org.mariotaku.twidere.service.BackgroundOperationService;
|
||||
import org.mariotaku.twidere.task.CacheUsersStatusesTask;
|
||||
import org.mariotaku.twidere.task.ManagedAsyncTask;
|
||||
import org.mariotaku.twidere.task.TwidereAsyncTask;
|
||||
import org.mariotaku.twidere.util.collection.LongSparseMap;
|
||||
import org.mariotaku.twidere.util.content.ContentResolverUtils;
|
||||
import org.mariotaku.twidere.util.message.FavoriteCreatedEvent;
|
||||
import org.mariotaku.twidere.util.message.FavoriteDestroyedEvent;
|
||||
import org.mariotaku.twidere.util.message.FriendshipUpdatedEvent;
|
||||
|
@ -88,9 +90,9 @@ import twitter4j.UserList;
|
|||
import twitter4j.http.HttpResponseCode;
|
||||
|
||||
import static org.mariotaku.twidere.provider.TweetStore.STATUSES_URIS;
|
||||
import static org.mariotaku.twidere.util.ContentValuesCreator.makeDirectMessageContentValues;
|
||||
import static org.mariotaku.twidere.util.ContentValuesCreator.makeStatusContentValues;
|
||||
import static org.mariotaku.twidere.util.ContentValuesCreator.makeTrendsContentValues;
|
||||
import static org.mariotaku.twidere.util.ContentValuesCreator.createDirectMessage;
|
||||
import static org.mariotaku.twidere.util.ContentValuesCreator.createStatus;
|
||||
import static org.mariotaku.twidere.util.ContentValuesCreator.createTrends;
|
||||
import static org.mariotaku.twidere.util.Utils.appendQueryParameters;
|
||||
import static org.mariotaku.twidere.util.Utils.getActivatedAccountIds;
|
||||
import static org.mariotaku.twidere.util.Utils.getDefaultAccountId;
|
||||
|
@ -142,6 +144,14 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
|||
return mAsyncTaskManager.add(task, true);
|
||||
}
|
||||
|
||||
public Context getContext() {
|
||||
return mContext;
|
||||
}
|
||||
|
||||
public AsyncTaskManager getTaskManager() {
|
||||
return mAsyncTaskManager;
|
||||
}
|
||||
|
||||
public boolean isCreatingFavorite(final long accountId, final long statusId) {
|
||||
return mCreatingFavoriteIds.has(accountId, statusId);
|
||||
}
|
||||
|
@ -388,6 +398,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
|||
final int woeId = mPreferences.getInt(KEY_LOCAL_TRENDS_WOEID, 1);
|
||||
getLocalTrendsAsync(accountId, woeId);
|
||||
}
|
||||
getSavedSearchesAsync(accountIds);
|
||||
final long[] statusSinceIds = getNewestStatusIdsFromDatabase(mContext, Statuses.CONTENT_URI, accountIds);
|
||||
return getHomeTimelineAsync(accountIds, null, statusSinceIds);
|
||||
}
|
||||
|
@ -2182,7 +2193,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
|||
for (int i = 0, j = messages.size(); i < j; i++) {
|
||||
final DirectMessage message = messages.get(i);
|
||||
messageIds[i] = message.getId();
|
||||
values_array[i] = makeDirectMessageContentValues(message, accountId, isOutgoing());
|
||||
values_array[i] = createDirectMessage(message, accountId, isOutgoing());
|
||||
}
|
||||
|
||||
// Delete all rows conflicting before new data inserted.
|
||||
|
@ -2248,6 +2259,43 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
|||
|
||||
}
|
||||
|
||||
public int getSavedSearchesAsync(long[] accountIds) {
|
||||
final GetSavedSearchesTask task = new GetSavedSearchesTask(this);
|
||||
final Long[] ids = new Long[accountIds.length];
|
||||
for (int i = 0, j = accountIds.length; i < j; i++) {
|
||||
ids[i] = accountIds[i];
|
||||
}
|
||||
return mAsyncTaskManager.add(task, true, ids);
|
||||
}
|
||||
|
||||
static class GetSavedSearchesTask extends ManagedAsyncTask<Long, Void, SingleResponse<Void>> {
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
GetSavedSearchesTask(AsyncTwitterWrapper twitter) {
|
||||
super(twitter.getContext(), twitter.getTaskManager());
|
||||
this.mContext = twitter.getContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SingleResponse<Void> doInBackground(Long... params) {
|
||||
final ContentResolver cr = mContext.getContentResolver();
|
||||
for (long accountId : params) {
|
||||
final Twitter twitter = Utils.getTwitterInstance(mContext, accountId, true);
|
||||
try {
|
||||
final ResponseList<SavedSearch> searches = twitter.getSavedSearches();
|
||||
final ContentValues[] values = ContentValuesCreator.createSavedSearches(searches, accountId);
|
||||
final Expression where = Expression.equals(SavedSearches.ACCOUNT_ID, accountId);
|
||||
cr.delete(SavedSearches.CONTENT_URI, where.getSQL(), null);
|
||||
ContentResolverUtils.bulkInsert(cr, SavedSearches.CONTENT_URI, values);
|
||||
} catch (TwitterException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return SingleResponse.getInstance();
|
||||
}
|
||||
}
|
||||
|
||||
class StoreReceivedDirectMessagesTask extends StoreDirectMessagesTask {
|
||||
|
||||
public StoreReceivedDirectMessagesTask(final List<MessageListResponse> result, final boolean notify) {
|
||||
|
@ -2303,7 +2351,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
|||
final long[] statusIds = new long[statuses.size()];
|
||||
for (int i = 0, j = statuses.size(); i < j; i++) {
|
||||
final twitter4j.Status status = statuses.get(i);
|
||||
values[i] = makeStatusContentValues(status, accountId);
|
||||
values[i] = createStatus(status, accountId);
|
||||
statusIds[i] = status.getId();
|
||||
}
|
||||
// Delete all rows conflicting before new data inserted.
|
||||
|
@ -2366,7 +2414,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
|||
final ArrayList<String> hashtags = new ArrayList<>();
|
||||
final ArrayList<ContentValues> hashtagValues = new ArrayList<>();
|
||||
if (messages != null && messages.size() > 0) {
|
||||
final ContentValues[] valuesArray = makeTrendsContentValues(messages);
|
||||
final ContentValues[] valuesArray = createTrends(messages);
|
||||
for (final ContentValues values : valuesArray) {
|
||||
final String hashtag = values.getAsString(CachedTrends.NAME).replaceFirst("#", "");
|
||||
if (hashtags.contains(hashtag)) {
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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.twidere.util;
|
||||
|
||||
import android.graphics.Color;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/1/8.
|
||||
*/
|
||||
public class ColorUtils {
|
||||
|
||||
|
||||
public static void colorToYIQ(int color, int[] yiq) {
|
||||
final int r = Color.red(color), g = Color.green(color), b = Color.blue(color);
|
||||
yiq[0] = (r * 299 + g * 587 + b * 114) / 1000;
|
||||
yiq[1] = (r * 596 - g * 275 - b * 321) / 1000;
|
||||
yiq[2] = (r * 212 - g * 523 + b * 311) / 1000;
|
||||
}
|
||||
|
||||
|
||||
public static int YIQToColor(int alpha, int[] yiq) {
|
||||
final int r = MathUtils.clamp((yiq[0] * 1000 + yiq[1] * 956 + yiq[2] * 620) / 1000, 0, 255);
|
||||
final int g = MathUtils.clamp((yiq[0] * 1000 - yiq[1] * 272 - yiq[2] * 647) / 1000, 0, 255);
|
||||
final int b = MathUtils.clamp((yiq[0] * 1000 - yiq[1] * 1108 + yiq[2] * 1705) / 1000, 0, 255);
|
||||
return Color.argb(alpha, r, g, b);
|
||||
}
|
||||
|
||||
}
|
|
@ -40,6 +40,7 @@ import org.mariotaku.twidere.provider.TweetStore.CachedUsers;
|
|||
import org.mariotaku.twidere.provider.TweetStore.DirectMessages;
|
||||
import org.mariotaku.twidere.provider.TweetStore.Drafts;
|
||||
import org.mariotaku.twidere.provider.TweetStore.Filters;
|
||||
import org.mariotaku.twidere.provider.TweetStore.SavedSearches;
|
||||
import org.mariotaku.twidere.provider.TweetStore.Statuses;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -47,6 +48,7 @@ import java.util.List;
|
|||
|
||||
import twitter4j.DirectMessage;
|
||||
import twitter4j.GeoLocation;
|
||||
import twitter4j.SavedSearch;
|
||||
import twitter4j.Status;
|
||||
import twitter4j.Trend;
|
||||
import twitter4j.Trends;
|
||||
|
@ -59,9 +61,10 @@ import static org.mariotaku.twidere.util.HtmlEscapeHelper.toPlainText;
|
|||
|
||||
public final class ContentValuesCreator implements TwidereConstants {
|
||||
|
||||
public static ContentValues makeAccountContentValuesBasic(final Configuration conf, final String basicUsername,
|
||||
final String basicPassword, final User user, final int color, final String apiUrlFormat,
|
||||
final boolean noVersionSuffix) {
|
||||
public static ContentValues createAccount(final Configuration conf, final String basicUsername,
|
||||
final String basicPassword, final User user,
|
||||
final int color, final String apiUrlFormat,
|
||||
final boolean noVersionSuffix) {
|
||||
if (user == null || user.getId() <= 0) return null;
|
||||
final ContentValues values = new ContentValues();
|
||||
if (basicUsername == null || basicPassword == null) return null;
|
||||
|
@ -80,9 +83,10 @@ public final class ContentValuesCreator implements TwidereConstants {
|
|||
return values;
|
||||
}
|
||||
|
||||
public static ContentValues makeAccountContentValuesOAuth(final Configuration conf, final AccessToken accessToken,
|
||||
final User user, final int authType, final int color, final String apiUrlFormat,
|
||||
final boolean sameOAuthSigningUrl, final boolean noVersionSuffix) {
|
||||
public static ContentValues createAccount(final Configuration conf, final AccessToken accessToken,
|
||||
final User user, final int authType, final int color,
|
||||
final String apiUrlFormat, final boolean sameOAuthSigningUrl,
|
||||
final boolean noVersionSuffix) {
|
||||
if (user == null || user.getId() <= 0 || accessToken == null || user.getId() != accessToken.getUserId())
|
||||
return null;
|
||||
final ContentValues values = new ContentValues();
|
||||
|
@ -104,8 +108,8 @@ public final class ContentValuesCreator implements TwidereConstants {
|
|||
return values;
|
||||
}
|
||||
|
||||
public static ContentValues makeAccountContentValuesTWIP(final Configuration conf, final User user,
|
||||
final int color, final String apiUrlFormat, final boolean noVersionSuffix) {
|
||||
public static ContentValues createAccount(final Configuration conf, final User user, final int color,
|
||||
final String apiUrlFormat, final boolean noVersionSuffix) {
|
||||
if (user == null || user.getId() <= 0) return null;
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(Accounts.AUTH_TYPE, Accounts.AUTH_TYPE_TWIP_O_MODE);
|
||||
|
@ -121,7 +125,7 @@ public final class ContentValuesCreator implements TwidereConstants {
|
|||
return values;
|
||||
}
|
||||
|
||||
public static ContentValues makeCachedUserContentValues(final User user) {
|
||||
public static ContentValues createCachedUser(final User user) {
|
||||
if (user == null || user.getId() <= 0) return null;
|
||||
final String profile_image_url = ParseUtils.parseString(user.getProfileImageUrlHttps());
|
||||
final String url = ParseUtils.parseString(user.getURL());
|
||||
|
@ -155,15 +159,15 @@ public final class ContentValuesCreator implements TwidereConstants {
|
|||
return values;
|
||||
}
|
||||
|
||||
public static ContentValues makeDirectMessageContentValues(final DirectMessage message, final long account_id,
|
||||
final boolean is_outgoing) {
|
||||
if (message == null || message.getId() <= 0) return null;
|
||||
public static ContentValues createDirectMessage(final DirectMessage message, final long accountId,
|
||||
final boolean isOutgoing) {
|
||||
if (message == null) return null;
|
||||
final ContentValues values = new ContentValues();
|
||||
final User sender = message.getSender(), recipient = message.getRecipient();
|
||||
if (sender == null || recipient == null) return null;
|
||||
final String sender_profile_image_url = ParseUtils.parseString(sender.getProfileImageUrlHttps());
|
||||
final String recipient_profile_image_url = ParseUtils.parseString(recipient.getProfileImageUrlHttps());
|
||||
values.put(DirectMessages.ACCOUNT_ID, account_id);
|
||||
values.put(DirectMessages.ACCOUNT_ID, accountId);
|
||||
values.put(DirectMessages.MESSAGE_ID, message.getId());
|
||||
values.put(DirectMessages.MESSAGE_TIMESTAMP, message.getCreatedAt().getTime());
|
||||
values.put(DirectMessages.SENDER_ID, sender.getId());
|
||||
|
@ -172,7 +176,7 @@ public final class ContentValuesCreator implements TwidereConstants {
|
|||
values.put(DirectMessages.TEXT_HTML, text_html);
|
||||
values.put(DirectMessages.TEXT_PLAIN, message.getText());
|
||||
values.put(DirectMessages.TEXT_UNESCAPED, toPlainText(text_html));
|
||||
values.put(DirectMessages.IS_OUTGOING, is_outgoing);
|
||||
values.put(DirectMessages.IS_OUTGOING, isOutgoing);
|
||||
values.put(DirectMessages.SENDER_NAME, sender.getName());
|
||||
values.put(DirectMessages.SENDER_SCREEN_NAME, sender.getScreenName());
|
||||
values.put(DirectMessages.RECIPIENT_NAME, recipient.getName());
|
||||
|
@ -187,8 +191,8 @@ public final class ContentValuesCreator implements TwidereConstants {
|
|||
return values;
|
||||
}
|
||||
|
||||
public static ContentValues makeDirectMessageContentValues(final ParcelableDirectMessage message) {
|
||||
if (message == null || message.id <= 0) return null;
|
||||
public static ContentValues createDirectMessage(final ParcelableDirectMessage message) {
|
||||
if (message == null) return null;
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(DirectMessages.ACCOUNT_ID, message.account_id);
|
||||
values.put(DirectMessages.MESSAGE_ID, message.id);
|
||||
|
@ -211,8 +215,8 @@ public final class ContentValuesCreator implements TwidereConstants {
|
|||
return values;
|
||||
}
|
||||
|
||||
public static ContentValues makeDirectMessageDraftContentValues(final long accountId, final long recipientId,
|
||||
final String text, final String imageUri) {
|
||||
public static ContentValues createMessageDraft(final long accountId, final long recipientId,
|
||||
final String text, final String imageUri) {
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(Drafts.ACTION_TYPE, Drafts.ACTION_SEND_DIRECT_MESSAGE);
|
||||
values.put(Drafts.TEXT, text);
|
||||
|
@ -232,7 +236,7 @@ public final class ContentValuesCreator implements TwidereConstants {
|
|||
return values;
|
||||
}
|
||||
|
||||
public static ContentValues makeFilteredUserContentValues(final ParcelableStatus status) {
|
||||
public static ContentValues createFilteredUser(final ParcelableStatus status) {
|
||||
if (status == null) return null;
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(Filters.Users.USER_ID, status.user_id);
|
||||
|
@ -241,7 +245,7 @@ public final class ContentValuesCreator implements TwidereConstants {
|
|||
return values;
|
||||
}
|
||||
|
||||
public static ContentValues makeFilteredUserContentValues(final ParcelableUser user) {
|
||||
public static ContentValues createFilteredUser(final ParcelableUser user) {
|
||||
if (user == null) return null;
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(Filters.Users.USER_ID, user.id);
|
||||
|
@ -250,7 +254,7 @@ public final class ContentValuesCreator implements TwidereConstants {
|
|||
return values;
|
||||
}
|
||||
|
||||
public static ContentValues makeFilteredUserContentValues(final ParcelableUserMention user) {
|
||||
public static ContentValues createFilteredUser(final ParcelableUserMention user) {
|
||||
if (user == null) return null;
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(Filters.Users.USER_ID, user.id);
|
||||
|
@ -259,7 +263,7 @@ public final class ContentValuesCreator implements TwidereConstants {
|
|||
return values;
|
||||
}
|
||||
|
||||
public static ContentValues makeStatusContentValues(final Status orig, final long accountId) {
|
||||
public static ContentValues createStatus(final Status orig, final long accountId) {
|
||||
if (orig == null || orig.getId() <= 0) return null;
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(Statuses.ACCOUNT_ID, accountId);
|
||||
|
@ -329,12 +333,12 @@ public final class ContentValuesCreator implements TwidereConstants {
|
|||
return values;
|
||||
}
|
||||
|
||||
public static ContentValues makeStatusDraftContentValues(final ParcelableStatusUpdate status) {
|
||||
return makeStatusDraftContentValues(status, ParcelableAccount.getAccountIds(status.accounts));
|
||||
public static ContentValues createStatusDraft(final ParcelableStatusUpdate status) {
|
||||
return createStatusDraft(status, ParcelableAccount.getAccountIds(status.accounts));
|
||||
}
|
||||
|
||||
public static ContentValues makeStatusDraftContentValues(final ParcelableStatusUpdate status,
|
||||
final long[] accountIds) {
|
||||
public static ContentValues createStatusDraft(final ParcelableStatusUpdate status,
|
||||
final long[] accountIds) {
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(Drafts.ACTION_TYPE, Drafts.ACTION_UPDATE_STATUS);
|
||||
values.put(Drafts.TEXT, status.text);
|
||||
|
@ -349,13 +353,30 @@ public final class ContentValuesCreator implements TwidereConstants {
|
|||
return values;
|
||||
}
|
||||
|
||||
public static ContentValues[] makeTrendsContentValues(final List<Trends> trendsList) {
|
||||
|
||||
public static ContentValues createSavedSearch(final SavedSearch savedSearch, final long accountId) {
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(SavedSearches.ACCOUNT_ID, accountId);
|
||||
values.put(SavedSearches.SEARCH_ID, savedSearch.getId());
|
||||
values.put(SavedSearches.CREATED_AT, savedSearch.getCreatedAt().getTime());
|
||||
values.put(SavedSearches.NAME, savedSearch.getName());
|
||||
values.put(SavedSearches.QUERY, savedSearch.getQuery());
|
||||
return values;
|
||||
}
|
||||
|
||||
|
||||
public static ContentValues[] createSavedSearches(final List<SavedSearch> savedSearches, long accountId) {
|
||||
final ContentValues[] resultValuesArray = new ContentValues[savedSearches.size()];
|
||||
for (int i = 0, j = savedSearches.size(); i < j; i++) {
|
||||
resultValuesArray[i] = createSavedSearch(savedSearches.get(i), accountId);
|
||||
}
|
||||
return resultValuesArray;
|
||||
}
|
||||
|
||||
public static ContentValues[] createTrends(final List<Trends> trendsList) {
|
||||
if (trendsList == null) return new ContentValues[0];
|
||||
final List<ContentValues> resultList = new ArrayList<>();
|
||||
for (final Trends trends : trendsList) {
|
||||
if (trends == null) {
|
||||
continue;
|
||||
}
|
||||
final long timestamp = trends.getTrendAt().getTime();
|
||||
for (final Trend trend : trends.getTrends()) {
|
||||
final ContentValues values = new ContentValues();
|
||||
|
|
|
@ -141,11 +141,11 @@ public class MultiSelectEventHandler implements Constants, ActionMode.Callback,
|
|||
if (object instanceof ParcelableStatus) {
|
||||
final ParcelableStatus status = (ParcelableStatus) object;
|
||||
userIds.add(status.user_id);
|
||||
valuesList.add(ContentValuesCreator.makeFilteredUserContentValues(status));
|
||||
valuesList.add(ContentValuesCreator.createFilteredUser(status));
|
||||
} else if (object instanceof ParcelableUser) {
|
||||
final ParcelableUser user = (ParcelableUser) object;
|
||||
userIds.add(user.id);
|
||||
valuesList.add(ContentValuesCreator.makeFilteredUserContentValues(user));
|
||||
valuesList.add(ContentValuesCreator.createFilteredUser(user));
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -35,7 +35,6 @@ import android.graphics.drawable.Drawable;
|
|||
import android.graphics.drawable.LayerDrawable;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.graphics.drawable.DrawableCompat;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextPaint;
|
||||
|
@ -215,13 +214,27 @@ public class ThemeUtils implements Constants {
|
|||
return view;
|
||||
}
|
||||
|
||||
public static int getGlobalSearchThemeResource(final Context context) {
|
||||
public static int getOptimalLinkColor(int linkColor, int color) {
|
||||
final int[] yiq = new int[3];
|
||||
ColorUtils.colorToYIQ(color, yiq);
|
||||
final int y = yiq[0];
|
||||
ColorUtils.colorToYIQ(linkColor, yiq);
|
||||
if (y < 32 && yiq[0] < 192) {
|
||||
return linkColor;
|
||||
} else if (y > 192 && yiq[0] > 32) {
|
||||
return linkColor;
|
||||
}
|
||||
yiq[0] = yiq[0] + (y - yiq[0]) / 2;
|
||||
return ColorUtils.YIQToColor(Color.alpha(linkColor), yiq);
|
||||
}
|
||||
|
||||
public static int getQuickSearchBoxThemeResource(final Context context) {
|
||||
return getGlobalSearchThemeResource(getThemeNameOption(context));
|
||||
}
|
||||
|
||||
public static int getGlobalSearchThemeResource(final String name) {
|
||||
if (VALUE_THEME_NAME_DARK.equals(name)) return R.style.Theme_Twidere_Dark_GlobalSearch;
|
||||
return R.style.Theme_Twidere_Light_GlobalSearch;
|
||||
if (VALUE_THEME_NAME_DARK.equals(name)) return R.style.Theme_Twidere_Dark_QuickSearchBox;
|
||||
return R.style.Theme_Twidere_Light_QuickSearchBox;
|
||||
}
|
||||
|
||||
private static void applyColorTintForView(View view, int tintColor) {
|
||||
|
@ -244,9 +257,6 @@ public class ThemeUtils implements Constants {
|
|||
final ColorStateList tintList = ColorStateList.valueOf(tintColor);
|
||||
final CompoundButton compoundButton = (CompoundButton) view;
|
||||
ViewAccessor.setButtonTintList(compoundButton, tintList);
|
||||
} else if (view instanceof TextView) {
|
||||
final TextView textView = (TextView) view;
|
||||
textView.setLinkTextColor(tintColor);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -181,6 +181,7 @@ import org.mariotaku.twidere.provider.TweetStore.Mentions;
|
|||
import org.mariotaku.twidere.provider.TweetStore.Notifications;
|
||||
import org.mariotaku.twidere.provider.TweetStore.Permissions;
|
||||
import org.mariotaku.twidere.provider.TweetStore.Preferences;
|
||||
import org.mariotaku.twidere.provider.TweetStore.SavedSearches;
|
||||
import org.mariotaku.twidere.provider.TweetStore.Statuses;
|
||||
import org.mariotaku.twidere.provider.TweetStore.Tabs;
|
||||
import org.mariotaku.twidere.provider.TweetStore.UnreadCounts;
|
||||
|
@ -305,6 +306,8 @@ public final class Utils implements Constants, TwitterConstants {
|
|||
CONTENT_PROVIDER_URI_MATCHER.addURI(TweetStore.AUTHORITY, DNS.CONTENT_PATH + "/*", VIRTUAL_TABLE_ID_DNS);
|
||||
CONTENT_PROVIDER_URI_MATCHER.addURI(TweetStore.AUTHORITY, CachedImages.CONTENT_PATH,
|
||||
VIRTUAL_TABLE_ID_CACHED_IMAGES);
|
||||
CONTENT_PROVIDER_URI_MATCHER.addURI(TweetStore.AUTHORITY, SavedSearches.CONTENT_PATH,
|
||||
TABLE_ID_SAVED_SEARCHES);
|
||||
CONTENT_PROVIDER_URI_MATCHER.addURI(TweetStore.AUTHORITY, CacheFiles.CONTENT_PATH + "/*",
|
||||
VIRTUAL_TABLE_ID_CACHE_FILES);
|
||||
CONTENT_PROVIDER_URI_MATCHER.addURI(TweetStore.AUTHORITY, Preferences.CONTENT_PATH,
|
||||
|
@ -1136,7 +1139,7 @@ public final class Utils implements Constants, TwitterConstants {
|
|||
final ContentResolver resolver = context.getContentResolver();
|
||||
resolver.delete(CachedStatuses.CONTENT_URI, where, null);
|
||||
resolver.insert(CachedStatuses.CONTENT_URI,
|
||||
ContentValuesCreator.makeStatusContentValues(status, accountId));
|
||||
ContentValuesCreator.createStatus(status, accountId));
|
||||
return new ParcelableStatus(status, accountId, false);
|
||||
}
|
||||
|
||||
|
@ -2245,6 +2248,8 @@ public final class Utils implements Constants, TwitterConstants {
|
|||
return CachedUsers.TABLE_NAME;
|
||||
case TABLE_ID_CACHED_HASHTAGS:
|
||||
return CachedHashtags.TABLE_NAME;
|
||||
case TABLE_ID_SAVED_SEARCHES:
|
||||
return SavedSearches.TABLE_NAME;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
@ -3046,15 +3051,15 @@ public final class Utils implements Constants, TwitterConstants {
|
|||
activity.startActivity(intent);
|
||||
}
|
||||
|
||||
public static void openStatusRetweeters(final Activity activity, final long accountId, final long statusId) {
|
||||
if (activity == null) return;
|
||||
public static void openStatusRetweeters(final Context context, final long accountId, final long statusId) {
|
||||
if (context == null) return;
|
||||
final Uri.Builder builder = new Uri.Builder();
|
||||
builder.scheme(SCHEME_TWIDERE);
|
||||
builder.authority(AUTHORITY_STATUS_RETWEETERS);
|
||||
builder.appendQueryParameter(QUERY_PARAM_ACCOUNT_ID, String.valueOf(accountId));
|
||||
builder.appendQueryParameter(QUERY_PARAM_STATUS_ID, String.valueOf(statusId));
|
||||
final Intent intent = new Intent(Intent.ACTION_VIEW, builder.build());
|
||||
activity.startActivity(intent);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
public static void openTweetSearch(final Context context, final long accountId, final String query) {
|
||||
|
@ -3945,7 +3950,7 @@ public final class Utils implements Constants, TwitterConstants {
|
|||
*/
|
||||
public static int getContrastYIQ(int color, int threshold, int colorDark, int colorLight) {
|
||||
final int r = Color.red(color), g = Color.green(color), b = Color.blue(color);
|
||||
int yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000;
|
||||
final int yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000;
|
||||
return (yiq >= threshold) ? colorDark : colorLight;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ import org.mariotaku.twidere.provider.TweetStore.DirectMessages;
|
|||
import org.mariotaku.twidere.provider.TweetStore.Drafts;
|
||||
import org.mariotaku.twidere.provider.TweetStore.Filters;
|
||||
import org.mariotaku.twidere.provider.TweetStore.Mentions;
|
||||
import org.mariotaku.twidere.provider.TweetStore.SavedSearches;
|
||||
import org.mariotaku.twidere.provider.TweetStore.Statuses;
|
||||
import org.mariotaku.twidere.provider.TweetStore.Tabs;
|
||||
import org.mariotaku.twidere.util.TwidereQueryBuilder.ConversationsEntryQueryBuilder;
|
||||
|
@ -79,6 +80,7 @@ public final class TwidereSQLiteOpenHelper extends SQLiteOpenHelper implements C
|
|||
db.execSQL(createTable(CachedTrends.Local.TABLE_NAME, CachedTrends.Local.COLUMNS, CachedTrends.Local.TYPES,
|
||||
true));
|
||||
db.execSQL(createTable(Tabs.TABLE_NAME, Tabs.COLUMNS, Tabs.TYPES, true));
|
||||
db.execSQL(createTable(SavedSearches.TABLE_NAME, SavedSearches.COLUMNS, SavedSearches.TYPES, true));
|
||||
db.execSQL(createDirectMessagesView().getSQL());
|
||||
db.execSQL(createDirectMessageConversationEntriesView().getSQL());
|
||||
db.setTransactionSuccessful();
|
||||
|
@ -135,21 +137,26 @@ public final class TwidereSQLiteOpenHelper extends SQLiteOpenHelper implements C
|
|||
safeUpgrade(db, Mentions.TABLE_NAME, Mentions.COLUMNS, Mentions.TYPES, true, null);
|
||||
safeUpgrade(db, Drafts.TABLE_NAME, Drafts.COLUMNS, Drafts.TYPES, false, draftsAlias);
|
||||
safeUpgrade(db, CachedUsers.TABLE_NAME, CachedUsers.COLUMNS, CachedUsers.TYPES, true, null);
|
||||
safeUpgrade(db, CachedStatuses.TABLE_NAME, CachedStatuses.COLUMNS, CachedStatuses.TYPES, false, null);
|
||||
safeUpgrade(db, CachedHashtags.TABLE_NAME, CachedHashtags.COLUMNS, CachedHashtags.TYPES, false, null);
|
||||
safeUpgrade(db, Filters.Users.TABLE_NAME, Filters.Users.COLUMNS, Filters.Users.TYPES, oldVersion < 49, null);
|
||||
safeUpgrade(db, Filters.Keywords.TABLE_NAME, Filters.Keywords.COLUMNS, Filters.Keywords.TYPES, oldVersion < 49,
|
||||
filtersAlias);
|
||||
safeUpgrade(db, Filters.Sources.TABLE_NAME, Filters.Sources.COLUMNS, Filters.Sources.TYPES, oldVersion < 49,
|
||||
filtersAlias);
|
||||
safeUpgrade(db, Filters.Links.TABLE_NAME, Filters.Links.COLUMNS, Filters.Links.TYPES, oldVersion < 49,
|
||||
filtersAlias);
|
||||
safeUpgrade(db, DirectMessages.Inbox.TABLE_NAME, DirectMessages.Inbox.COLUMNS, DirectMessages.Inbox.TYPES,
|
||||
true, null);
|
||||
safeUpgrade(db, DirectMessages.Outbox.TABLE_NAME, DirectMessages.Outbox.COLUMNS, DirectMessages.Outbox.TYPES,
|
||||
true, null);
|
||||
safeUpgrade(db, CachedTrends.Local.TABLE_NAME, CachedTrends.Local.COLUMNS, CachedTrends.Local.TYPES, true, null);
|
||||
safeUpgrade(db, CachedStatuses.TABLE_NAME, CachedStatuses.COLUMNS, CachedStatuses.TYPES,
|
||||
false, null);
|
||||
safeUpgrade(db, CachedHashtags.TABLE_NAME, CachedHashtags.COLUMNS, CachedHashtags.TYPES,
|
||||
false, null);
|
||||
safeUpgrade(db, Filters.Users.TABLE_NAME, Filters.Users.COLUMNS, Filters.Users.TYPES,
|
||||
oldVersion < 49, null);
|
||||
safeUpgrade(db, Filters.Keywords.TABLE_NAME, Filters.Keywords.COLUMNS, Filters.Keywords.TYPES,
|
||||
oldVersion < 49, filtersAlias);
|
||||
safeUpgrade(db, Filters.Sources.TABLE_NAME, Filters.Sources.COLUMNS, Filters.Sources.TYPES,
|
||||
oldVersion < 49, filtersAlias);
|
||||
safeUpgrade(db, Filters.Links.TABLE_NAME, Filters.Links.COLUMNS, Filters.Links.TYPES,
|
||||
oldVersion < 49, filtersAlias);
|
||||
safeUpgrade(db, DirectMessages.Inbox.TABLE_NAME, DirectMessages.Inbox.COLUMNS,
|
||||
DirectMessages.Inbox.TYPES, true, null);
|
||||
safeUpgrade(db, DirectMessages.Outbox.TABLE_NAME, DirectMessages.Outbox.COLUMNS,
|
||||
DirectMessages.Outbox.TYPES, true, null);
|
||||
safeUpgrade(db, CachedTrends.Local.TABLE_NAME, CachedTrends.Local.COLUMNS,
|
||||
CachedTrends.Local.TYPES, true, null);
|
||||
safeUpgrade(db, Tabs.TABLE_NAME, Tabs.COLUMNS, Tabs.TYPES, false, null);
|
||||
safeUpgrade(db, SavedSearches.TABLE_NAME, SavedSearches.COLUMNS, SavedSearches.TYPES, true, null);
|
||||
db.beginTransaction();
|
||||
db.execSQL(createDirectMessagesView().getSQL());
|
||||
db.execSQL(createDirectMessageConversationEntriesView().getSQL());
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
|
||||
package org.mariotaku.twidere.util.net;
|
||||
|
||||
import static android.text.TextUtils.isEmpty;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.util.Log;
|
||||
|
@ -33,184 +31,181 @@ import org.xbill.DNS.AAAARecord;
|
|||
import org.xbill.DNS.ARecord;
|
||||
import org.xbill.DNS.CNAMERecord;
|
||||
import org.xbill.DNS.DClass;
|
||||
import org.xbill.DNS.Message;
|
||||
import org.xbill.DNS.Lookup;
|
||||
import org.xbill.DNS.Name;
|
||||
import org.xbill.DNS.Record;
|
||||
import org.xbill.DNS.Resolver;
|
||||
import org.xbill.DNS.Section;
|
||||
import org.xbill.DNS.SimpleResolver;
|
||||
import org.xbill.DNS.Type;
|
||||
|
||||
import twitter4j.http.HostAddressResolver;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
import twitter4j.http.HostAddressResolver;
|
||||
|
||||
import static android.text.TextUtils.isEmpty;
|
||||
|
||||
public class TwidereHostAddressResolver implements Constants, HostAddressResolver {
|
||||
|
||||
private static final String RESOLVER_LOGTAG = "TwidereHostAddressResolver";
|
||||
private static final String RESOLVER_LOGTAG = "TwidereHostAddressResolver";
|
||||
|
||||
private static final String DEFAULT_DNS_SERVER_ADDRESS = "8.8.8.8";
|
||||
private static final String DEFAULT_DNS_SERVER_ADDRESS = "8.8.8.8";
|
||||
|
||||
private final SharedPreferences mHostMapping, mPreferences;
|
||||
private final HostsFileParser mSystemHosts = new HostsFileParser();
|
||||
private final HostCache mHostCache = new HostCache(512);
|
||||
private final boolean mLocalMappingOnly;
|
||||
private final String mDnsAddress;
|
||||
private final SharedPreferences mHostMapping, mPreferences;
|
||||
private final HostsFileParser mSystemHosts = new HostsFileParser();
|
||||
private final HostCache mHostCache = new HostCache(512);
|
||||
private final boolean mLocalMappingOnly;
|
||||
private final String mDnsAddress;
|
||||
|
||||
private Resolver mDns;
|
||||
private Resolver mDns;
|
||||
|
||||
public TwidereHostAddressResolver(final Context context) {
|
||||
this(context, false);
|
||||
}
|
||||
public TwidereHostAddressResolver(final Context context) {
|
||||
this(context, false);
|
||||
}
|
||||
|
||||
public TwidereHostAddressResolver(final Context context, final boolean local_only) {
|
||||
mHostMapping = context.getSharedPreferences(HOST_MAPPING_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
mPreferences = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
final String address = mPreferences.getString(KEY_DNS_SERVER, DEFAULT_DNS_SERVER_ADDRESS);
|
||||
mDnsAddress = isValidIpAddress(address) ? address : DEFAULT_DNS_SERVER_ADDRESS;
|
||||
mLocalMappingOnly = local_only;
|
||||
}
|
||||
public TwidereHostAddressResolver(final Context context, final boolean localOnly) {
|
||||
mHostMapping = context.getSharedPreferences(HOST_MAPPING_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
mPreferences = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
final String address = mPreferences.getString(KEY_DNS_SERVER, DEFAULT_DNS_SERVER_ADDRESS);
|
||||
mDnsAddress = isValidIpAddress(address) ? address : DEFAULT_DNS_SERVER_ADDRESS;
|
||||
mLocalMappingOnly = localOnly;
|
||||
}
|
||||
|
||||
public synchronized void removeCachedHost(final String host) {
|
||||
mHostCache.remove(host);
|
||||
}
|
||||
public synchronized void removeCachedHost(final String host) {
|
||||
mHostCache.remove(host);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String resolve(final String host) throws IOException {
|
||||
if (host == null) return null;
|
||||
if (isValidIpAddress(host)) return null;
|
||||
// First, I'll try to load address cached.
|
||||
if (mHostCache.containsKey(host)) {
|
||||
if (Utils.isDebugBuild()) {
|
||||
Log.d(RESOLVER_LOGTAG, "Got cached address " + mHostCache.get(host) + " for host " + host);
|
||||
}
|
||||
return mHostCache.get(host);
|
||||
}
|
||||
// Then I'll try to load from custom host mapping.
|
||||
// Stupid way to find top domain, but really fast.
|
||||
if (mHostMapping.contains(host)) {
|
||||
final String mappedAddr = mHostMapping.getString(host, null);
|
||||
mHostCache.put(host, mappedAddr);
|
||||
if (Utils.isDebugBuild()) {
|
||||
Log.d(RESOLVER_LOGTAG, "Got mapped address " + mappedAddr + " for host " + host);
|
||||
}
|
||||
return mappedAddr;
|
||||
}
|
||||
mSystemHosts.reloadIfNeeded();
|
||||
if (mSystemHosts.contains(host)) {
|
||||
final String hostAddr = mSystemHosts.getAddress(host);
|
||||
mHostCache.put(host, hostAddr);
|
||||
if (Utils.isDebugBuild()) {
|
||||
Log.d(RESOLVER_LOGTAG, "Got mapped address " + hostAddr + " for host " + host);
|
||||
}
|
||||
return hostAddr;
|
||||
}
|
||||
final String customMappedHost = findHost(host);
|
||||
if (customMappedHost != null) {
|
||||
mHostCache.put(host, customMappedHost);
|
||||
if (Utils.isDebugBuild()) {
|
||||
Log.d(RESOLVER_LOGTAG, "Got mapped address " + customMappedHost + " for host " + host);
|
||||
}
|
||||
return customMappedHost;
|
||||
}
|
||||
initDns();
|
||||
// Use TCP DNS Query if enabled.
|
||||
if (mDns != null && mPreferences.getBoolean(KEY_TCP_DNS_QUERY, false)) {
|
||||
final Name name = new Name(host);
|
||||
final Record query = Record.newRecord(name, Type.A, DClass.IN);
|
||||
if (query == null) return host;
|
||||
final Message response;
|
||||
try {
|
||||
response = mDns.send(Message.newQuery(query));
|
||||
} catch (final IOException e) {
|
||||
return host;
|
||||
}
|
||||
if (response == null) return host;
|
||||
final Record[] records = response.getSectionArray(Section.ANSWER);
|
||||
if (records == null || records.length < 1) throw new IOException("Could not find " + host);
|
||||
String hostAddr = null;
|
||||
// Test each IP address resolved.
|
||||
for (final Record record : records) {
|
||||
if (record instanceof ARecord) {
|
||||
final InetAddress ipv4Addr = ((ARecord) record).getAddress();
|
||||
if (ipv4Addr.isReachable(300)) {
|
||||
hostAddr = ipv4Addr.getHostAddress();
|
||||
}
|
||||
} else if (record instanceof AAAARecord) {
|
||||
final InetAddress ipv6Addr = ((AAAARecord) record).getAddress();
|
||||
if (ipv6Addr.isReachable(300)) {
|
||||
hostAddr = ipv6Addr.getHostAddress();
|
||||
}
|
||||
}
|
||||
if (hostAddr != null) {
|
||||
mHostCache.put(host, hostAddr);
|
||||
if (Utils.isDebugBuild()) {
|
||||
Log.d(RESOLVER_LOGTAG, "Resolved address " + hostAddr + " for host " + host);
|
||||
}
|
||||
return hostAddr;
|
||||
}
|
||||
}
|
||||
// No address is reachable, but I believe the IP is correct.
|
||||
final Record record = records[0];
|
||||
if (record instanceof ARecord) {
|
||||
final InetAddress ipv4Addr = ((ARecord) record).getAddress();
|
||||
hostAddr = ipv4Addr.getHostAddress();
|
||||
} else if (record instanceof AAAARecord) {
|
||||
final InetAddress ipv6Addr = ((AAAARecord) record).getAddress();
|
||||
hostAddr = ipv6Addr.getHostAddress();
|
||||
} else if (record instanceof CNAMERecord) return resolve(((CNAMERecord) record).getTarget().toString());
|
||||
mHostCache.put(host, hostAddr);
|
||||
if (Utils.isDebugBuild()) {
|
||||
Log.d(RESOLVER_LOGTAG, "Resolved address " + hostAddr + " for host " + host);
|
||||
}
|
||||
return hostAddr;
|
||||
}
|
||||
if (Utils.isDebugBuild()) {
|
||||
Log.w(RESOLVER_LOGTAG, "Resolve address " + host + " failed, using original host");
|
||||
}
|
||||
return host;
|
||||
}
|
||||
@Override
|
||||
public String resolve(final String host) throws IOException {
|
||||
if (host == null) return null;
|
||||
if (isValidIpAddress(host)) return null;
|
||||
// First, I'll try to load address cached.
|
||||
if (mHostCache.containsKey(host)) {
|
||||
if (Utils.isDebugBuild()) {
|
||||
Log.d(RESOLVER_LOGTAG, "Got cached address " + mHostCache.get(host) + " for host " + host);
|
||||
}
|
||||
return mHostCache.get(host);
|
||||
}
|
||||
// Then I'll try to load from custom host mapping.
|
||||
// Stupid way to find top domain, but really fast.
|
||||
if (mHostMapping.contains(host)) {
|
||||
final String mappedAddr = mHostMapping.getString(host, null);
|
||||
mHostCache.put(host, mappedAddr);
|
||||
if (Utils.isDebugBuild()) {
|
||||
Log.d(RESOLVER_LOGTAG, "Got mapped address " + mappedAddr + " for host " + host);
|
||||
}
|
||||
return mappedAddr;
|
||||
}
|
||||
mSystemHosts.reloadIfNeeded();
|
||||
if (mSystemHosts.contains(host)) {
|
||||
final String hostAddr = mSystemHosts.getAddress(host);
|
||||
mHostCache.put(host, hostAddr);
|
||||
if (Utils.isDebugBuild()) {
|
||||
Log.d(RESOLVER_LOGTAG, "Got mapped address " + hostAddr + " for host " + host);
|
||||
}
|
||||
return hostAddr;
|
||||
}
|
||||
final String customMappedHost = findHost(host);
|
||||
if (customMappedHost != null) {
|
||||
mHostCache.put(host, customMappedHost);
|
||||
if (Utils.isDebugBuild()) {
|
||||
Log.d(RESOLVER_LOGTAG, "Got mapped address " + customMappedHost + " for host " + host);
|
||||
}
|
||||
return customMappedHost;
|
||||
}
|
||||
initDns();
|
||||
// Use TCP DNS Query if enabled.
|
||||
if (mDns != null && mPreferences.getBoolean(KEY_TCP_DNS_QUERY, false)) {
|
||||
final Lookup lookup = new Lookup(new Name(host), Type.A, DClass.IN);
|
||||
final Record[] records;
|
||||
lookup.setResolver(mDns);
|
||||
lookup.run();
|
||||
final int result = lookup.getResult();
|
||||
if (result != Lookup.SUCCESSFUL) {
|
||||
throw new IOException("Could not find " + host);
|
||||
}
|
||||
records = lookup.getAnswers();
|
||||
String hostAddr = null;
|
||||
// Test each IP address resolved.
|
||||
for (final Record record : records) {
|
||||
if (record instanceof ARecord) {
|
||||
final InetAddress ipv4Addr = ((ARecord) record).getAddress();
|
||||
if (ipv4Addr.isReachable(300)) {
|
||||
hostAddr = ipv4Addr.getHostAddress();
|
||||
}
|
||||
} else if (record instanceof AAAARecord) {
|
||||
final InetAddress ipv6Addr = ((AAAARecord) record).getAddress();
|
||||
if (ipv6Addr.isReachable(300)) {
|
||||
hostAddr = ipv6Addr.getHostAddress();
|
||||
}
|
||||
}
|
||||
if (hostAddr != null) {
|
||||
mHostCache.put(host, hostAddr);
|
||||
if (Utils.isDebugBuild()) {
|
||||
Log.d(RESOLVER_LOGTAG, "Resolved address " + hostAddr + " for host " + host);
|
||||
}
|
||||
return hostAddr;
|
||||
}
|
||||
}
|
||||
// No address is reachable, but I believe the IP is correct.
|
||||
final Record record = records[0];
|
||||
if (record instanceof ARecord) {
|
||||
final InetAddress ipv4Addr = ((ARecord) record).getAddress();
|
||||
hostAddr = ipv4Addr.getHostAddress();
|
||||
} else if (record instanceof AAAARecord) {
|
||||
final InetAddress ipv6Addr = ((AAAARecord) record).getAddress();
|
||||
hostAddr = ipv6Addr.getHostAddress();
|
||||
} else if (record instanceof CNAMERecord)
|
||||
return resolve(((CNAMERecord) record).getTarget().toString());
|
||||
mHostCache.put(host, hostAddr);
|
||||
if (Utils.isDebugBuild()) {
|
||||
Log.d(RESOLVER_LOGTAG, "Resolved address " + hostAddr + " for host " + host);
|
||||
}
|
||||
return hostAddr;
|
||||
}
|
||||
if (Utils.isDebugBuild()) {
|
||||
Log.w(RESOLVER_LOGTAG, "Resolve address " + host + " failed, using original host");
|
||||
}
|
||||
return host;
|
||||
}
|
||||
|
||||
private String findHost(final String host) {
|
||||
for (final String rule : mHostMapping.getAll().keySet()) {
|
||||
if (hostMatches(host, rule)) return mHostMapping.getString(rule, null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private String findHost(final String host) {
|
||||
for (final String rule : mHostMapping.getAll().keySet()) {
|
||||
if (hostMatches(host, rule)) return mHostMapping.getString(rule, null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void initDns() throws IOException {
|
||||
if (mDns != null) return;
|
||||
mDns = mLocalMappingOnly ? null : new SimpleResolver(mDnsAddress);
|
||||
if (mDns != null) {
|
||||
mDns.setTCP(true);
|
||||
}
|
||||
}
|
||||
private void initDns() throws IOException {
|
||||
if (mDns != null) return;
|
||||
mDns = new SimpleResolver(mDnsAddress);
|
||||
mDns.setTCP(true);
|
||||
}
|
||||
|
||||
private static boolean hostMatches(final String host, final String rule) {
|
||||
if (rule == null || host == null) return false;
|
||||
if (rule.startsWith(".")) return host.toLowerCase().endsWith(rule.toLowerCase());
|
||||
return host.equalsIgnoreCase(rule);
|
||||
}
|
||||
private static boolean hostMatches(final String host, final String rule) {
|
||||
if (rule == null || host == null) return false;
|
||||
if (rule.startsWith(".")) return host.toLowerCase().endsWith(rule.toLowerCase());
|
||||
return host.equalsIgnoreCase(rule);
|
||||
}
|
||||
|
||||
private static boolean isValidIpAddress(final String address) {
|
||||
if (isEmpty(address)) return false;
|
||||
return InetAddressUtilsHC4.isIPv4Address(address) || InetAddressUtilsHC4.isIPv6Address(address);
|
||||
}
|
||||
private static boolean isValidIpAddress(final String address) {
|
||||
if (isEmpty(address)) return false;
|
||||
return InetAddressUtilsHC4.isIPv4Address(address) || InetAddressUtilsHC4.isIPv6Address(address);
|
||||
}
|
||||
|
||||
private static class HostCache extends LinkedHashMap<String, String> {
|
||||
private static class HostCache extends LinkedHashMap<String, String> {
|
||||
|
||||
private static final long serialVersionUID = -9216545511009449147L;
|
||||
private static final long serialVersionUID = -9216545511009449147L;
|
||||
|
||||
HostCache(final int initialCapacity) {
|
||||
super(initialCapacity);
|
||||
}
|
||||
HostCache(final int initialCapacity) {
|
||||
super(initialCapacity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String put(final String key, final String value) {
|
||||
if (value == null) return value;
|
||||
return super.put(key, value);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public String put(final String key, final String value) {
|
||||
if (value == null) return null;
|
||||
return super.put(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,6 @@ public class ThemedTextView extends TextView implements IThemedView {
|
|||
|
||||
@Override
|
||||
public void setThemeTintColor(ColorStateList color) {
|
||||
setLinkTextColor(color);
|
||||
setLinkTextColor(ThemeUtils.getOptimalLinkColor(color.getDefaultColor(), getCurrentTextColor()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,12 +23,12 @@
|
|||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/element_spacing_normal">
|
||||
android:layout_height="match_parent"
|
||||
android:padding="@dimen/element_spacing_normal">
|
||||
|
||||
<android.support.v7.widget.CardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/element_size_normal"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentTop="true"
|
||||
|
@ -38,30 +38,47 @@
|
|||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal">
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/account_spinner"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="0"
|
||||
tools:listitem="@layout/spinner_item_account_icon"/>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/element_size_normal"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<EditText
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:hint="@string/search_hint"/>
|
||||
<Spinner
|
||||
android:id="@+id/account_spinner"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="0"
|
||||
tools:listitem="@layout/spinner_item_account_icon"/>
|
||||
|
||||
<org.mariotaku.twidere.view.ActionIconButton
|
||||
android:layout_width="@dimen/element_size_normal"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?android:actionBarItemBackground"
|
||||
android:layout_weight="0"
|
||||
android:src="@drawable/ic_action_search"/>
|
||||
<EditText
|
||||
android:id="@+id/search_query"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:hint="@string/search_hint"
|
||||
android:imeActionLabel="@android:string/search_go"
|
||||
android:imeOptions="actionSearch"
|
||||
android:inputType="text"
|
||||
android:singleLine="true"/>
|
||||
|
||||
<org.mariotaku.twidere.view.ActionIconButton
|
||||
android:id="@+id/search_submit"
|
||||
android:layout_width="@dimen/element_size_normal"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="0"
|
||||
android:background="?android:actionBarItemBackground"
|
||||
android:src="@drawable/ic_action_search"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ListView
|
||||
android:id="@+id/suggestions_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
</LinearLayout>
|
||||
|
||||
</android.support.v7.widget.CardView>
|
||||
|
|
|
@ -83,8 +83,6 @@
|
|||
android:layout_height="@dimen/icon_size_profile_type"
|
||||
android:layout_alignBottom="@id/profile_image"
|
||||
android:layout_alignRight="@id/profile_image"
|
||||
android:layout_marginBottom="-8dp"
|
||||
android:layout_marginRight="-8dp"
|
||||
android:scaleType="fitCenter"/>
|
||||
|
||||
<LinearLayout
|
||||
|
|
|
@ -178,14 +178,14 @@
|
|||
<item name="android:windowMinWidthMinor">@android:dimen/dialog_min_width_minor</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.Twidere.Light.GlobalSearch" parent="Theme.Twidere.Light.Dialog">
|
||||
<style name="Theme.Twidere.Light.QuickSearchBox" parent="Theme.Twidere.Light.Dialog">
|
||||
<item name="android:windowBackground">@android:color/transparent</item>
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
<item name="android:windowMinWidthMajor">@android:dimen/dialog_min_width_major</item>
|
||||
<item name="android:windowMinWidthMinor">100%</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.Twidere.Dark.GlobalSearch" parent="Theme.Twidere.Dark.Dialog">
|
||||
<style name="Theme.Twidere.Dark.QuickSearchBox" parent="Theme.Twidere.Dark.Dialog">
|
||||
<item name="android:windowBackground">@android:color/transparent</item>
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
<item name="android:windowMinWidthMajor">@android:dimen/dialog_min_width_major</item>
|
||||
|
|
Loading…
Reference in New Issue