removed dashclock support
fixed 404 errors when signing in fixed share in tweet list fixed white button on pre-lollipop versions
This commit is contained in:
parent
c2dae75dec
commit
7a3d995b0e
|
@ -99,6 +99,7 @@ public interface TwidereConstants extends SharedPreferenceConstants, IntentConst
|
|||
public static final String AUTHORITY_STATUS_REPLIES = "status_replies";
|
||||
public static final String AUTHORITY_RETWEETS_OF_ME = "retweets_of_me";
|
||||
public static final String AUTHORITY_MUTES_USERS = "mutes_users";
|
||||
public static final String AUTHORITY_NOTIFICATIONS = "notifications";
|
||||
|
||||
public static final String QUERY_PARAM_ACCOUNT_ID = "account_id";
|
||||
public static final String QUERY_PARAM_ACCOUNT_IDS = "account_ids";
|
||||
|
@ -120,6 +121,8 @@ public interface TwidereConstants extends SharedPreferenceConstants, IntentConst
|
|||
public static final String QUERY_PARAM_FINISH_ONLY = "finish_only";
|
||||
public static final String QUERY_PARAM_NEW_ITEMS_COUNT = "new_items_count";
|
||||
public static final String QUERY_PARAM_RECIPIENT_ID = "recipient_id";
|
||||
public static final String QUERY_PARAM_READ_POSITION = "param_read_position";
|
||||
public static final String QUERY_PARAM_READ_POSITIONS = "param_read_positions";
|
||||
|
||||
public static final String DEFAULT_PROTOCOL = PROTOCOL_HTTPS;
|
||||
|
||||
|
|
|
@ -18,12 +18,11 @@ package twitter4j.conf;
|
|||
|
||||
import java.io.ObjectStreamException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import twitter4j.TwitterConstants;
|
||||
import twitter4j.Version;
|
||||
import twitter4j.http.HeaderMap;
|
||||
import twitter4j.http.HostAddressResolverFactory;
|
||||
import twitter4j.http.HttpClientFactory;
|
||||
|
||||
|
@ -98,7 +97,7 @@ class ConfigurationBase implements TwitterConstants, Configuration {
|
|||
private HostAddressResolverFactory hostAddressResolverFactory;
|
||||
|
||||
// method for HttpRequestFactoryConfiguration
|
||||
Map<String, String> requestHeaders;
|
||||
HeaderMap requestHeaders;
|
||||
|
||||
private static final List<ConfigurationBase> instances = new ArrayList<ConfigurationBase>();
|
||||
private boolean includeCards;
|
||||
|
@ -394,7 +393,7 @@ class ConfigurationBase implements TwitterConstants, Configuration {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getRequestHeaders() {
|
||||
public HeaderMap getRequestHeaders() {
|
||||
return requestHeaders;
|
||||
}
|
||||
|
||||
|
@ -714,6 +713,10 @@ class ConfigurationBase implements TwitterConstants, Configuration {
|
|||
oAuthAccessTokenSecret = accessTokenSecret;
|
||||
}
|
||||
|
||||
public void setOAuthAuthorizationURL(String oAuthAuthorizationURL) {
|
||||
// this.oAuthAuthorizationURL = oAuthAuthorizationURL;
|
||||
}
|
||||
|
||||
protected final void setOAuthBaseURL(String oAuthBaseURL) {
|
||||
if (isNullOrEmpty(oAuthBaseURL)) {
|
||||
oAuthBaseURL = DEFAULT_OAUTH_BASE_URL;
|
||||
|
@ -869,23 +872,23 @@ class ConfigurationBase implements TwitterConstants, Configuration {
|
|||
}
|
||||
|
||||
final void initRequestHeaders() {
|
||||
requestHeaders = new HashMap<String, String>();
|
||||
requestHeaders = new HeaderMap();
|
||||
if (includeTwitterClientHeader) {
|
||||
requestHeaders.put("X-Twitter-Client-Version", getClientVersion());
|
||||
requestHeaders.put("X-Twitter-Client-URL", getClientURL());
|
||||
requestHeaders.put("X-Twitter-Client", getClientName());
|
||||
requestHeaders.addHeader("X-Twitter-Client-Version", getClientVersion());
|
||||
requestHeaders.addHeader("X-Twitter-Client-URL", getClientURL());
|
||||
requestHeaders.addHeader("X-Twitter-Client", getClientName());
|
||||
}
|
||||
|
||||
requestHeaders.put("User-Agent", getHttpUserAgent());
|
||||
requestHeaders.addHeader("User-Agent", getHttpUserAgent());
|
||||
if (gzipEnabled) {
|
||||
requestHeaders.put("Accept-Encoding", "gzip");
|
||||
requestHeaders.addHeader("Accept-Encoding", "gzip");
|
||||
}
|
||||
// I found this may cause "Socket is closed" error in Android, so I
|
||||
// changed it to "keep-alive".
|
||||
if (!isNullOrEmpty(httpProxyHost) && httpProxyPort > 0) {
|
||||
requestHeaders.put("Connection", "keep-alive");
|
||||
requestHeaders.addHeader("Connection", "keep-alive");
|
||||
} else {
|
||||
requestHeaders.put("Connection", "close");
|
||||
requestHeaders.addHeader("Connection", "close");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -253,6 +253,13 @@ public final class ConfigurationBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
|
||||
public ConfigurationBuilder setOAuthAuthorizationURL(final String oAuthAuthorizationURL) {
|
||||
checkNotBuilt();
|
||||
configuration.setOAuthAuthorizationURL(oAuthAuthorizationURL);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigurationBuilder setOAuthConsumerKey(final String oAuthConsumerKey) {
|
||||
checkNotBuilt();
|
||||
configuration.setOAuthConsumerKey(oAuthConsumerKey);
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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 twitter4j.http;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/4/4.
|
||||
*/
|
||||
public class HeaderMap extends HashMap<String, List<String>> {
|
||||
|
||||
public void addHeader(String key, String value) {
|
||||
List<String> values = get(key);
|
||||
if (values == null) values = new ArrayList<>();
|
||||
values.add(value);
|
||||
put(key, values);
|
||||
}
|
||||
|
||||
}
|
|
@ -20,6 +20,7 @@
|
|||
package twitter4j.http;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import twitter4j.TwitterException;
|
||||
|
@ -35,190 +36,190 @@ import static twitter4j.http.RequestMethod.PUT;
|
|||
|
||||
/**
|
||||
* HTTP Client wrapper with handy request methods, ResponseListener mechanism
|
||||
*
|
||||
*
|
||||
* @author Yusuke Yamamoto - yusuke at mac.com
|
||||
*/
|
||||
public final class HttpClientWrapper {
|
||||
private final Configuration wrapperConf;
|
||||
private final HttpClient http;
|
||||
private final Configuration wrapperConf;
|
||||
private final HttpClient http;
|
||||
|
||||
private final Map<String, String> requestHeaders;
|
||||
private final Map<String, List<String>> requestHeaders;
|
||||
|
||||
private HttpResponseListener httpResponseListener;
|
||||
private HttpResponseListener httpResponseListener;
|
||||
|
||||
// never used with this project. Just for handiness for those using this
|
||||
// class.
|
||||
public HttpClientWrapper() {
|
||||
wrapperConf = ConfigurationContext.getInstance();
|
||||
requestHeaders = wrapperConf.getRequestHeaders();
|
||||
http = FactoryUtils.getHttpClient(wrapperConf);
|
||||
}
|
||||
// never used with this project. Just for handiness for those using this
|
||||
// class.
|
||||
public HttpClientWrapper() {
|
||||
wrapperConf = ConfigurationContext.getInstance();
|
||||
requestHeaders = wrapperConf.getRequestHeaders();
|
||||
http = FactoryUtils.getHttpClient(wrapperConf);
|
||||
}
|
||||
|
||||
public HttpClientWrapper(final Configuration wrapperConf) {
|
||||
this.wrapperConf = wrapperConf;
|
||||
requestHeaders = wrapperConf.getRequestHeaders();
|
||||
http = FactoryUtils.getHttpClient(wrapperConf);
|
||||
}
|
||||
public HttpClientWrapper(final Configuration wrapperConf) {
|
||||
this.wrapperConf = wrapperConf;
|
||||
requestHeaders = wrapperConf.getRequestHeaders();
|
||||
http = FactoryUtils.getHttpClient(wrapperConf);
|
||||
}
|
||||
|
||||
public HttpResponse delete(final String url, final String signUrl) throws TwitterException {
|
||||
return delete(url, signUrl, null, null);
|
||||
}
|
||||
public HttpResponse delete(final String url, final String signUrl) throws TwitterException {
|
||||
return delete(url, signUrl, null, null);
|
||||
}
|
||||
|
||||
public HttpResponse delete(final String url, final String signUrl, final Authorization authorization)
|
||||
throws TwitterException {
|
||||
return delete(url, signUrl, null, authorization);
|
||||
}
|
||||
public HttpResponse delete(final String url, final String signUrl, final Authorization authorization)
|
||||
throws TwitterException {
|
||||
return delete(url, signUrl, null, authorization);
|
||||
}
|
||||
|
||||
public HttpResponse delete(final String url, final String signUrl, final HttpParameter[] parameters)
|
||||
throws TwitterException {
|
||||
return delete(url, signUrl, parameters, null);
|
||||
}
|
||||
public HttpResponse delete(final String url, final String signUrl, final HttpParameter[] parameters)
|
||||
throws TwitterException {
|
||||
return delete(url, signUrl, parameters, null);
|
||||
}
|
||||
|
||||
public HttpResponse delete(final String url, final String signUrl, final HttpParameter[] parameters,
|
||||
final Authorization authorization) throws TwitterException {
|
||||
return request(new HttpRequest(DELETE, url, signUrl, parameters, authorization, requestHeaders));
|
||||
}
|
||||
public HttpResponse delete(final String url, final String signUrl, final HttpParameter[] parameters,
|
||||
final Authorization authorization) throws TwitterException {
|
||||
return request(new HttpRequest(DELETE, url, signUrl, parameters, authorization, requestHeaders));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
final HttpClientWrapper that = (HttpClientWrapper) o;
|
||||
final HttpClientWrapper that = (HttpClientWrapper) o;
|
||||
|
||||
if (!http.equals(that.http)) return false;
|
||||
if (!requestHeaders.equals(that.requestHeaders)) return false;
|
||||
if (!wrapperConf.equals(that.wrapperConf)) return false;
|
||||
if (!http.equals(that.http)) return false;
|
||||
if (!requestHeaders.equals(that.requestHeaders)) return false;
|
||||
if (!wrapperConf.equals(that.wrapperConf)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public HttpResponse get(final String url, final String signUrl) throws TwitterException {
|
||||
return get(url, signUrl, null, null);
|
||||
}
|
||||
public HttpResponse get(final String url, final String signUrl) throws TwitterException {
|
||||
return get(url, signUrl, null, null);
|
||||
}
|
||||
|
||||
public HttpResponse get(final String url, final String signUrl, final Authorization authorization)
|
||||
throws TwitterException {
|
||||
return get(url, signUrl, null, authorization);
|
||||
}
|
||||
public HttpResponse get(final String url, final String signUrl, final Authorization authorization)
|
||||
throws TwitterException {
|
||||
return get(url, signUrl, null, authorization);
|
||||
}
|
||||
|
||||
public HttpResponse get(final String url, final String signUrl, final HttpParameter[] parameters)
|
||||
throws TwitterException {
|
||||
return get(url, signUrl, parameters, null);
|
||||
}
|
||||
public HttpResponse get(final String url, final String signUrl, final HttpParameter[] parameters)
|
||||
throws TwitterException {
|
||||
return get(url, signUrl, parameters, null);
|
||||
}
|
||||
|
||||
public HttpResponse get(final String url, final String signUrl, final HttpParameter[] parameters,
|
||||
final Authorization authorization) throws TwitterException {
|
||||
return request(new HttpRequest(GET, url, signUrl, parameters, authorization, requestHeaders));
|
||||
}
|
||||
public HttpResponse get(final String url, final String signUrl, final HttpParameter[] parameters,
|
||||
final Authorization authorization) throws TwitterException {
|
||||
return request(new HttpRequest(GET, url, signUrl, parameters, authorization, requestHeaders));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = wrapperConf.hashCode();
|
||||
result = 31 * result + http.hashCode();
|
||||
result = 31 * result + requestHeaders.hashCode();
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = wrapperConf.hashCode();
|
||||
result = 31 * result + http.hashCode();
|
||||
result = 31 * result + requestHeaders.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
public HttpResponse head(final String url, final String signUrl) throws TwitterException {
|
||||
return head(url, signUrl, null, null);
|
||||
}
|
||||
public HttpResponse head(final String url, final String signUrl) throws TwitterException {
|
||||
return head(url, signUrl, null, null);
|
||||
}
|
||||
|
||||
public HttpResponse head(final String url, final String signUrl, final Authorization authorization)
|
||||
throws TwitterException {
|
||||
return head(url, signUrl, null, authorization);
|
||||
}
|
||||
public HttpResponse head(final String url, final String signUrl, final Authorization authorization)
|
||||
throws TwitterException {
|
||||
return head(url, signUrl, null, authorization);
|
||||
}
|
||||
|
||||
public HttpResponse head(final String url, final String signUrl, final HttpParameter[] parameters)
|
||||
throws TwitterException {
|
||||
return head(url, signUrl, parameters, null);
|
||||
}
|
||||
public HttpResponse head(final String url, final String signUrl, final HttpParameter[] parameters)
|
||||
throws TwitterException {
|
||||
return head(url, signUrl, parameters, null);
|
||||
}
|
||||
|
||||
public HttpResponse head(final String url, final String signUrl, final HttpParameter[] parameters,
|
||||
final Authorization authorization) throws TwitterException {
|
||||
return request(new HttpRequest(HEAD, url, signUrl, parameters, authorization, requestHeaders));
|
||||
}
|
||||
public HttpResponse head(final String url, final String signUrl, final HttpParameter[] parameters,
|
||||
final Authorization authorization) throws TwitterException {
|
||||
return request(new HttpRequest(HEAD, url, signUrl, parameters, authorization, requestHeaders));
|
||||
}
|
||||
|
||||
public HttpResponse post(final String url, final String signUrl) throws TwitterException {
|
||||
return post(url, signUrl, null, null, null);
|
||||
}
|
||||
public HttpResponse post(final String url, final String signUrl) throws TwitterException {
|
||||
return post(url, signUrl, null, null, null);
|
||||
}
|
||||
|
||||
public HttpResponse post(final String url, final String signUrl, final Authorization authorization)
|
||||
throws TwitterException {
|
||||
return post(url, signUrl, null, authorization, null);
|
||||
}
|
||||
public HttpResponse post(final String url, final String signUrl, final Authorization authorization)
|
||||
throws TwitterException {
|
||||
return post(url, signUrl, null, authorization, null);
|
||||
}
|
||||
|
||||
public HttpResponse post(final String url, final String signUrl, final HttpParameter[] parameters)
|
||||
throws TwitterException {
|
||||
return post(url, signUrl, parameters, null, null);
|
||||
}
|
||||
public HttpResponse post(final String url, final String signUrl, final HttpParameter[] parameters)
|
||||
throws TwitterException {
|
||||
return post(url, signUrl, parameters, null, null);
|
||||
}
|
||||
|
||||
public HttpResponse post(final String url, final String signUrl, final HttpParameter[] parameters,
|
||||
final Authorization authorization) throws TwitterException {
|
||||
return post(url, signUrl, parameters, authorization, null);
|
||||
}
|
||||
public HttpResponse post(final String url, final String signUrl, final HttpParameter[] parameters,
|
||||
final Authorization authorization) throws TwitterException {
|
||||
return post(url, signUrl, parameters, authorization, null);
|
||||
}
|
||||
|
||||
public HttpResponse post(final String url, final String signUrl, final HttpParameter[] parameters,
|
||||
final Authorization authorization, final Map<String, String> requestHeaders) throws TwitterException {
|
||||
final Map<String, String> headers = new HashMap<String, String>(this.requestHeaders);
|
||||
if (requestHeaders != null) {
|
||||
headers.putAll(requestHeaders);
|
||||
}
|
||||
return request(new HttpRequest(POST, url, signUrl, parameters, authorization, headers));
|
||||
}
|
||||
public HttpResponse post(final String url, final String signUrl, final HttpParameter[] parameters,
|
||||
final Authorization authorization, final Map<String, List<String>> requestHeaders) throws TwitterException {
|
||||
final Map<String, List<String>> headers = new HashMap<>(this.requestHeaders);
|
||||
if (requestHeaders != null) {
|
||||
headers.putAll(requestHeaders);
|
||||
}
|
||||
return request(new HttpRequest(POST, url, signUrl, parameters, authorization, headers));
|
||||
}
|
||||
|
||||
public HttpResponse post(final String url, final String signUrl, final HttpParameter[] parameters,
|
||||
final Map<String, String> requestHeaders) throws TwitterException {
|
||||
return post(url, signUrl, parameters, null, requestHeaders);
|
||||
}
|
||||
public HttpResponse post(final String url, final String signUrl, final HttpParameter[] parameters,
|
||||
final Map<String, List<String>> requestHeaders) throws TwitterException {
|
||||
return post(url, signUrl, parameters, null, requestHeaders);
|
||||
}
|
||||
|
||||
public HttpResponse put(final String url, final String signUrl) throws TwitterException {
|
||||
return put(url, signUrl, null, null);
|
||||
}
|
||||
public HttpResponse put(final String url, final String signUrl) throws TwitterException {
|
||||
return put(url, signUrl, null, null);
|
||||
}
|
||||
|
||||
public HttpResponse put(final String url, final String signUrl, final Authorization authorization)
|
||||
throws TwitterException {
|
||||
return put(url, signUrl, null, authorization);
|
||||
}
|
||||
public HttpResponse put(final String url, final String signUrl, final Authorization authorization)
|
||||
throws TwitterException {
|
||||
return put(url, signUrl, null, authorization);
|
||||
}
|
||||
|
||||
public HttpResponse put(final String url, final String signUrl, final HttpParameter[] parameters)
|
||||
throws TwitterException {
|
||||
return put(url, signUrl, parameters, null);
|
||||
}
|
||||
public HttpResponse put(final String url, final String signUrl, final HttpParameter[] parameters)
|
||||
throws TwitterException {
|
||||
return put(url, signUrl, parameters, null);
|
||||
}
|
||||
|
||||
public HttpResponse put(final String url, final String signUrl, final HttpParameter[] parameters,
|
||||
final Authorization authorization) throws TwitterException {
|
||||
return request(new HttpRequest(PUT, url, signUrl, parameters, authorization, requestHeaders));
|
||||
}
|
||||
public HttpResponse put(final String url, final String signUrl, final HttpParameter[] parameters,
|
||||
final Authorization authorization) throws TwitterException {
|
||||
return request(new HttpRequest(PUT, url, signUrl, parameters, authorization, requestHeaders));
|
||||
}
|
||||
|
||||
public void setHttpResponseListener(final HttpResponseListener listener) {
|
||||
httpResponseListener = listener;
|
||||
}
|
||||
public void setHttpResponseListener(final HttpResponseListener listener) {
|
||||
httpResponseListener = listener;
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
http.shutdown();
|
||||
}
|
||||
public void shutdown() {
|
||||
http.shutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HttpClientWrapper{" + "wrapperConf=" + wrapperConf + ", http=" + http + ", requestHeaders="
|
||||
+ requestHeaders + ", httpResponseListener=" + httpResponseListener + '}';
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HttpClientWrapper{" + "wrapperConf=" + wrapperConf + ", http=" + http + ", requestHeaders="
|
||||
+ requestHeaders + ", httpResponseListener=" + httpResponseListener + '}';
|
||||
}
|
||||
|
||||
private HttpResponse request(final HttpRequest req) throws TwitterException {
|
||||
HttpResponse res;
|
||||
try {
|
||||
res = http.request(req);
|
||||
// fire HttpResponseEvent
|
||||
if (httpResponseListener != null) {
|
||||
httpResponseListener.httpResponseReceived(new HttpResponseEvent(req, res, null));
|
||||
}
|
||||
} catch (final TwitterException te) {
|
||||
if (httpResponseListener != null) {
|
||||
httpResponseListener.httpResponseReceived(new HttpResponseEvent(req, null, te));
|
||||
}
|
||||
throw te;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
private HttpResponse request(final HttpRequest req) throws TwitterException {
|
||||
HttpResponse res;
|
||||
try {
|
||||
res = http.request(req);
|
||||
// fire HttpResponseEvent
|
||||
if (httpResponseListener != null) {
|
||||
httpResponseListener.httpResponseReceived(new HttpResponseEvent(req, res, null));
|
||||
}
|
||||
} catch (final TwitterException te) {
|
||||
if (httpResponseListener != null) {
|
||||
httpResponseListener.httpResponseReceived(new HttpResponseEvent(req, null, te));
|
||||
}
|
||||
throw te;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,11 +16,12 @@
|
|||
|
||||
package twitter4j.http;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface HttpClientWrapperConfiguration extends HttpClientConfiguration {
|
||||
/**
|
||||
* @return request headers
|
||||
*/
|
||||
Map<String, String> getRequestHeaders();
|
||||
HeaderMap getRequestHeaders();
|
||||
}
|
||||
|
|
|
@ -20,113 +20,114 @@
|
|||
package twitter4j.http;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import twitter4j.auth.Authorization;
|
||||
|
||||
/**
|
||||
* HTTP Request parameter object
|
||||
*
|
||||
*
|
||||
* @author Yusuke Yamamoto - yusuke at mac.com
|
||||
*/
|
||||
public final class HttpRequest {
|
||||
|
||||
private final RequestMethod method;
|
||||
private final RequestMethod method;
|
||||
|
||||
private final String url, signUrl;
|
||||
private final String url, signUrl;
|
||||
|
||||
private final HttpParameter[] parameters;
|
||||
private final HttpParameter[] parameters;
|
||||
|
||||
private final Authorization authorization;
|
||||
private final Authorization authorization;
|
||||
|
||||
private final Map<String, String> requestHeaders;
|
||||
private final Map<String, List<String>> requestHeaders;
|
||||
|
||||
private static final HttpParameter[] NULL_PARAMETERS = new HttpParameter[0];
|
||||
private static final HttpParameter[] NULL_PARAMETERS = new HttpParameter[0];
|
||||
|
||||
/**
|
||||
* @param method Specifies the HTTP method
|
||||
* @param url the request to request
|
||||
* @param parameters parameters
|
||||
* @param authorization Authentication implementation. Currently
|
||||
* BasicAuthentication, OAuthAuthentication and
|
||||
* NullAuthentication are supported.
|
||||
* @param requestHeaders
|
||||
*/
|
||||
public HttpRequest(final RequestMethod method, final String url, final String signUrl,
|
||||
final HttpParameter[] parameters, final Authorization authorization,
|
||||
final Map<String, String> requestHeaders) {
|
||||
this.method = method;
|
||||
if (method != RequestMethod.POST && parameters != null && parameters.length != 0) {
|
||||
final String paramString = HttpParameter.encodeParameters(parameters);
|
||||
this.url = url + "?" + paramString;
|
||||
this.signUrl = signUrl + "?" + paramString;
|
||||
this.parameters = NULL_PARAMETERS;
|
||||
} else {
|
||||
this.url = url;
|
||||
this.signUrl = signUrl;
|
||||
this.parameters = parameters;
|
||||
}
|
||||
this.authorization = authorization;
|
||||
this.requestHeaders = requestHeaders;
|
||||
}
|
||||
/**
|
||||
* @param method Specifies the HTTP method
|
||||
* @param url the request to request
|
||||
* @param parameters parameters
|
||||
* @param authorization Authentication implementation. Currently
|
||||
* BasicAuthentication, OAuthAuthentication and
|
||||
* NullAuthentication are supported.
|
||||
* @param requestHeaders
|
||||
*/
|
||||
public HttpRequest(final RequestMethod method, final String url, final String signUrl,
|
||||
final HttpParameter[] parameters, final Authorization authorization,
|
||||
final Map<String, List<String>> requestHeaders) {
|
||||
this.method = method;
|
||||
if (method != RequestMethod.POST && parameters != null && parameters.length != 0) {
|
||||
final String paramString = HttpParameter.encodeParameters(parameters);
|
||||
this.url = url + "?" + paramString;
|
||||
this.signUrl = signUrl + "?" + paramString;
|
||||
this.parameters = NULL_PARAMETERS;
|
||||
} else {
|
||||
this.url = url;
|
||||
this.signUrl = signUrl;
|
||||
this.parameters = parameters;
|
||||
}
|
||||
this.authorization = authorization;
|
||||
this.requestHeaders = requestHeaders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
final HttpRequest that = (HttpRequest) o;
|
||||
final HttpRequest that = (HttpRequest) o;
|
||||
|
||||
if (authorization != null ? !authorization.equals(that.authorization) : that.authorization != null)
|
||||
return false;
|
||||
if (!Arrays.equals(parameters, that.parameters)) return false;
|
||||
if (requestHeaders != null ? !requestHeaders.equals(that.requestHeaders) : that.requestHeaders != null)
|
||||
return false;
|
||||
if (method != null ? !method.equals(that.method) : that.method != null) return false;
|
||||
if (url != null ? !url.equals(that.url) : that.url != null) return false;
|
||||
if (authorization != null ? !authorization.equals(that.authorization) : that.authorization != null)
|
||||
return false;
|
||||
if (!Arrays.equals(parameters, that.parameters)) return false;
|
||||
if (requestHeaders != null ? !requestHeaders.equals(that.requestHeaders) : that.requestHeaders != null)
|
||||
return false;
|
||||
if (method != null ? !method.equals(that.method) : that.method != null) return false;
|
||||
if (url != null ? !url.equals(that.url) : that.url != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public Authorization getAuthorization() {
|
||||
return authorization;
|
||||
}
|
||||
public Authorization getAuthorization() {
|
||||
return authorization;
|
||||
}
|
||||
|
||||
public RequestMethod getMethod() {
|
||||
return method;
|
||||
}
|
||||
public RequestMethod getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public HttpParameter[] getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
public HttpParameter[] getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public Map<String, String> getRequestHeaders() {
|
||||
return requestHeaders;
|
||||
}
|
||||
public Map<String, List<String>> getRequestHeaders() {
|
||||
return requestHeaders;
|
||||
}
|
||||
|
||||
public String getSignURL() {
|
||||
return signUrl != null ? signUrl : url;
|
||||
}
|
||||
public String getSignURL() {
|
||||
return signUrl != null ? signUrl : url;
|
||||
}
|
||||
|
||||
public String getURL() {
|
||||
return url;
|
||||
}
|
||||
public String getURL() {
|
||||
return url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = method != null ? method.hashCode() : 0;
|
||||
result = 31 * result + (url != null ? url.hashCode() : 0);
|
||||
result = 31 * result + (signUrl != null ? signUrl.hashCode() : 0);
|
||||
result = 31 * result + (parameters != null ? Arrays.hashCode(parameters) : 0);
|
||||
result = 31 * result + (authorization != null ? authorization.hashCode() : 0);
|
||||
result = 31 * result + (requestHeaders != null ? requestHeaders.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = method != null ? method.hashCode() : 0;
|
||||
result = 31 * result + (url != null ? url.hashCode() : 0);
|
||||
result = 31 * result + (signUrl != null ? signUrl.hashCode() : 0);
|
||||
result = 31 * result + (parameters != null ? Arrays.hashCode(parameters) : 0);
|
||||
result = 31 * result + (authorization != null ? authorization.hashCode() : 0);
|
||||
result = 31 * result + (requestHeaders != null ? requestHeaders.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HttpRequest{" + "requestMethod=" + method + ", url='" + url + '\'' + ", signUrl='" + signUrl + '\''
|
||||
+ ", postParams=" + (parameters == null ? null : Arrays.asList(parameters)) + ", authentication="
|
||||
+ authorization + ", requestHeaders=" + requestHeaders + '}';
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HttpRequest{" + "requestMethod=" + method + ", url='" + url + '\'' + ", signUrl='" + signUrl + '\''
|
||||
+ ", postParams=" + (parameters == null ? null : Arrays.asList(parameters)) + ", authentication="
|
||||
+ authorization + ", requestHeaders=" + requestHeaders + '}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -206,6 +206,8 @@ public abstract class HttpResponse {
|
|||
|
||||
public abstract String getResponseHeader(String name);
|
||||
|
||||
public abstract List<String> getResponseHeaders(String name);
|
||||
|
||||
public abstract Map<String, List<String>> getResponseHeaderFields();
|
||||
|
||||
public int getStatusCode() {
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
/*
|
||||
* Copyright 2007 Yusuke Yamamoto
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package twitter4j.http;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Yusuke Yamamoto - yusuke at mac.com
|
||||
* @since Twitter4J 2.1.2
|
||||
*/
|
||||
public class HttpResponseImpl extends HttpResponse {
|
||||
private HttpURLConnection con;
|
||||
|
||||
HttpResponseImpl(final HttpURLConnection con, final HttpClientConfiguration conf) throws IOException {
|
||||
super(conf);
|
||||
this.con = con;
|
||||
if (con == null) return;
|
||||
statusCode = con.getResponseCode();
|
||||
if (null == (is = con.getErrorStream())) {
|
||||
is = con.getInputStream();
|
||||
}
|
||||
if (is != null && "gzip".equals(con.getContentEncoding())) {
|
||||
// the response is gzipped
|
||||
is = new StreamingGZIPInputStream(is);
|
||||
}
|
||||
}
|
||||
|
||||
// for test purpose
|
||||
/* package */HttpResponseImpl(final String content) {
|
||||
super();
|
||||
responseAsString = content;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void disconnect() {
|
||||
con.disconnect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getResponseHeader(final String name) {
|
||||
return con.getHeaderField(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<String>> getResponseHeaderFields() {
|
||||
return con.getHeaderFields();
|
||||
}
|
||||
}
|
|
@ -81,8 +81,11 @@ public class OkHttpClientImpl implements HttpClient, TwidereConstants {
|
|||
@Override
|
||||
public HttpResponse request(HttpRequest req) throws TwitterException {
|
||||
final Builder builder = new Builder();
|
||||
for (Entry<String, String> headerEntry : req.getRequestHeaders().entrySet()) {
|
||||
builder.header(headerEntry.getKey(), headerEntry.getValue());
|
||||
for (Entry<String, List<String>> headerEntry : req.getRequestHeaders().entrySet()) {
|
||||
final String name = headerEntry.getKey();
|
||||
for (String value : headerEntry.getValue()) {
|
||||
builder.addHeader(name, value);
|
||||
}
|
||||
}
|
||||
final Authorization authorization = req.getAuthorization();
|
||||
if (authorization != null) {
|
||||
|
@ -259,6 +262,11 @@ public class OkHttpClientImpl implements HttpClient, TwidereConstants {
|
|||
return response.header(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getResponseHeaders(String name) {
|
||||
return response.headers(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<String>> getResponseHeaderFields() {
|
||||
final Headers headers = response.headers();
|
||||
|
|
|
@ -72,7 +72,6 @@ dependencies {
|
|||
compile 'com.sothree.slidinguppanel:library:3.0.0'
|
||||
compile 'com.twitter:twitter-text:1.11.1'
|
||||
compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.3'
|
||||
compile 'com.google.android.apps.dashclock:dashclock-api:2.0.0'
|
||||
compile 'com.squareup:otto:1.3.6'
|
||||
compile 'dnsjava:dnsjava:2.1.7'
|
||||
compile 'com.commonsware.cwac:merge:1.1.1'
|
||||
|
|
|
@ -599,63 +599,6 @@
|
|||
<service
|
||||
android:name=".service.BackgroundOperationService"
|
||||
android:label="@string/label_background_operation_service"/>
|
||||
<service
|
||||
android:name=".service.DashClockHomeUnreadCountService"
|
||||
android:icon="@drawable/ic_extension_twidere"
|
||||
android:label="@string/dashclock_home_unread_count_name"
|
||||
android:permission="com.google.android.apps.dashclock.permission.READ_EXTENSION_DATA">
|
||||
<intent-filter>
|
||||
<action android:name="com.google.android.apps.dashclock.Extension"/>
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="protocolVersion"
|
||||
android:value="2"/>
|
||||
<meta-data
|
||||
android:name="worldReadable"
|
||||
android:value="true"/>
|
||||
<meta-data
|
||||
android:name="description"
|
||||
android:value="@string/dashclock_home_unread_count_description"/>
|
||||
</service>
|
||||
<service
|
||||
android:name=".service.DashClockMentionsUnreadCountService"
|
||||
android:icon="@drawable/ic_extension_mentions"
|
||||
android:label="@string/dashclock_mentions_unread_count_name"
|
||||
android:permission="com.google.android.apps.dashclock.permission.READ_EXTENSION_DATA">
|
||||
<intent-filter>
|
||||
<action android:name="com.google.android.apps.dashclock.Extension"/>
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="protocolVersion"
|
||||
android:value="2"/>
|
||||
<meta-data
|
||||
android:name="worldReadable"
|
||||
android:value="true"/>
|
||||
<meta-data
|
||||
android:name="description"
|
||||
android:value="@string/dashclock_mentions_unread_count_description"/>
|
||||
</service>
|
||||
<service
|
||||
android:name=".service.DashClockMessagesUnreadCountService"
|
||||
android:icon="@drawable/ic_extension_messages"
|
||||
android:label="@string/dashclock_messages_unread_count_name"
|
||||
android:permission="com.google.android.apps.dashclock.permission.READ_EXTENSION_DATA">
|
||||
<intent-filter>
|
||||
<action android:name="com.google.android.apps.dashclock.Extension"/>
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="protocolVersion"
|
||||
android:value="2"/>
|
||||
<meta-data
|
||||
android:name="worldReadable"
|
||||
android:value="true"/>
|
||||
<meta-data
|
||||
android:name="description"
|
||||
android:value="@string/dashclock_messages_unread_count_description"/>
|
||||
</service>
|
||||
<service
|
||||
android:name=".nyan.NyanWallpaperService"
|
||||
android:enabled="false"
|
||||
|
|
|
@ -28,6 +28,7 @@ public interface IThemedActivity {
|
|||
public Resources getDefaultResources();
|
||||
|
||||
public int getThemeBackgroundAlpha();
|
||||
|
||||
public int getCurrentThemeBackgroundAlpha();
|
||||
|
||||
public int getThemeColor();
|
||||
|
|
|
@ -34,6 +34,8 @@ import android.view.View;
|
|||
import android.view.Window;
|
||||
import android.webkit.JavascriptInterface;
|
||||
import android.webkit.SslErrorHandler;
|
||||
import android.webkit.WebResourceRequest;
|
||||
import android.webkit.WebResourceResponse;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
|
@ -170,6 +172,11 @@ public class BrowserSignInActivity extends BaseSupportDialogActivity implements
|
|||
mActivity.setLoadProgressShown(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadResource(WebView view, String url) {
|
||||
super.onLoadResource(view, url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceivedError(final WebView view, final int errorCode, final String description,
|
||||
final String failingUrl) {
|
||||
|
|
|
@ -31,7 +31,6 @@ import android.database.ContentObserver;
|
|||
import android.graphics.Canvas;
|
||||
import android.graphics.PorterDuff.Mode;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
|
@ -724,9 +723,21 @@ public class HomeActivity extends BaseActionBarActivity implements OnClickListen
|
|||
final int actionBarAlpha = isTransparent ? ThemeUtils.getUserThemeBackgroundAlpha(this) : 0xFF;
|
||||
final IHomeActionButton homeActionButton = (IHomeActionButton) mActionsButton;
|
||||
mTabIndicator.setItemContext(ThemeUtils.getActionBarContext(this));
|
||||
if (ThemeUtils.isColoredActionBar(themeResId)) {
|
||||
ViewAccessor.setBackground(mActionBar, ThemeUtils.getActionBarBackground(this, themeResId, themeColor, true));
|
||||
if (ThemeUtils.isDarkTheme(themeResId)) {
|
||||
final int backgroundColor = ThemeUtils.getThemeBackgroundColor(mTabIndicator.getItemContext());
|
||||
final int foregroundColor = ThemeUtils.getThemeForegroundColor(mTabIndicator.getItemContext());
|
||||
homeActionButton.setButtonColor(backgroundColor);
|
||||
homeActionButton.setIconColor(foregroundColor, Mode.SRC_ATOP);
|
||||
mTabIndicator.setStripColor(themeColor);
|
||||
mTabIndicator.setIconColor(foregroundColor);
|
||||
mTabIndicator.setLabelColor(foregroundColor);
|
||||
mColorStatusFrameLayout.setDrawColor(true);
|
||||
mColorStatusFrameLayout.setDrawShadow(false);
|
||||
mColorStatusFrameLayout.setColor(getResources().getColor(R.color.background_color_action_bar_dark), actionBarAlpha);
|
||||
mColorStatusFrameLayout.setFactor(1);
|
||||
} else {
|
||||
final int contrastColor = ColorUtils.getContrastYIQ(themeColor, 192);
|
||||
ViewAccessor.setBackground(mActionBar, new ColorDrawable(themeColor));
|
||||
homeActionButton.setButtonColor(themeColor);
|
||||
homeActionButton.setIconColor(contrastColor, Mode.SRC_ATOP);
|
||||
mTabIndicator.setStripColor(contrastColor);
|
||||
|
@ -737,17 +748,6 @@ public class HomeActivity extends BaseActionBarActivity implements OnClickListen
|
|||
mColorStatusFrameLayout.setDrawShadow(false);
|
||||
mColorStatusFrameLayout.setColor(themeColor, actionBarAlpha);
|
||||
mColorStatusFrameLayout.setFactor(1);
|
||||
} else {
|
||||
final int backgroundColor = ThemeUtils.getThemeBackgroundColor(mTabIndicator.getItemContext());
|
||||
final int foregroundColor = ThemeUtils.getThemeForegroundColor(mTabIndicator.getItemContext());
|
||||
ViewAccessor.setBackground(mActionBar, ThemeUtils.getActionBarBackground(this, themeResId));
|
||||
homeActionButton.setButtonColor(backgroundColor);
|
||||
homeActionButton.setIconColor(foregroundColor, Mode.SRC_ATOP);
|
||||
mTabIndicator.setStripColor(themeColor);
|
||||
mTabIndicator.setIconColor(foregroundColor);
|
||||
mTabIndicator.setLabelColor(foregroundColor);
|
||||
mColorStatusFrameLayout.setDrawColor(false);
|
||||
mColorStatusFrameLayout.setDrawShadow(false);
|
||||
}
|
||||
mTabIndicator.setAlpha(actionBarAlpha / 255f);
|
||||
mActionsButton.setAlpha(actionBarAlpha / 255f);
|
||||
|
|
|
@ -255,16 +255,20 @@ public class LinkHandlerActivity extends BaseActionBarActivity implements OnClic
|
|||
case LINK_ID_USER: {
|
||||
mMainContent.setShadowColor(0xA0000000);
|
||||
mMainContent.setDrawShadow(false);
|
||||
mMainContent.setDrawColor(!ThemeUtils.isDarkTheme(getCurrentThemeResourceId()));
|
||||
mMainContent.setDrawColor(true);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
mMainContent.setDrawShadow(false);
|
||||
mMainContent.setDrawColor(!ThemeUtils.isDarkTheme(getCurrentThemeResourceId()));
|
||||
mMainContent.setDrawColor(true);
|
||||
mMainContent.setFactor(1);
|
||||
final int color = getCurrentThemeColor();
|
||||
final int alpha = getCurrentThemeBackgroundAlpha();
|
||||
mMainContent.setColor(color, alpha);
|
||||
if (ThemeUtils.isDarkTheme(getCurrentThemeResourceId())) {
|
||||
mMainContent.setColor(getResources().getColor(R.color.background_color_action_bar_dark), alpha);
|
||||
} else {
|
||||
mMainContent.setColor(color, alpha);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ import android.support.v4.app.Fragment;
|
|||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.text.Editable;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
@ -95,6 +96,7 @@ public class SignInActivity extends BaseActionBarActivity implements TwitterCons
|
|||
private static final String TWITTER_SIGNUP_URL = "https://twitter.com/signup";
|
||||
private static final String EXTRA_API_LAST_CHANGE = "api_last_change";
|
||||
public static final String FRAGMENT_TAG_SIGN_IN_PROGRESS = "sign_in_progress";
|
||||
private static final String DEFAULT_TWITTER_API_URL_FORMAT = "https://[DOMAIN.]twitter.com/";
|
||||
|
||||
private String mAPIUrlFormat;
|
||||
private int mAuthType;
|
||||
|
@ -367,16 +369,17 @@ public class SignInActivity extends BaseActionBarActivity implements TwitterCons
|
|||
} else {
|
||||
Utils.setUserAgent(this, cb);
|
||||
}
|
||||
if (!isEmpty(mAPIUrlFormat)) {
|
||||
final String versionSuffix = mNoVersionSuffix ? null : "/1.1/";
|
||||
cb.setRestBaseURL(Utils.getApiUrl(mAPIUrlFormat, "api", versionSuffix));
|
||||
cb.setOAuthBaseURL(Utils.getApiUrl(mAPIUrlFormat, "api", "/oauth/"));
|
||||
cb.setUploadBaseURL(Utils.getApiUrl(mAPIUrlFormat, "upload", versionSuffix));
|
||||
if (!mSameOAuthSigningUrl) {
|
||||
cb.setSigningRestBaseURL(DEFAULT_SIGNING_REST_BASE_URL);
|
||||
cb.setSigningOAuthBaseURL(DEFAULT_SIGNING_OAUTH_BASE_URL);
|
||||
cb.setSigningUploadBaseURL(DEFAULT_SIGNING_UPLOAD_BASE_URL);
|
||||
}
|
||||
final String apiUrlFormat = TextUtils.isEmpty(mAPIUrlFormat) ? DEFAULT_TWITTER_API_URL_FORMAT : mAPIUrlFormat;
|
||||
final String versionSuffix = mNoVersionSuffix ? null : "/1.1/";
|
||||
cb.setRestBaseURL(Utils.getApiUrl(apiUrlFormat, "api", versionSuffix));
|
||||
cb.setOAuthBaseURL(Utils.getApiUrl(apiUrlFormat, "api", "/oauth/"));
|
||||
cb.setUploadBaseURL(Utils.getApiUrl(apiUrlFormat, "upload", versionSuffix));
|
||||
cb.setOAuthAuthorizationURL(Utils.getApiUrl(apiUrlFormat, null, "/oauth/authorize"));
|
||||
cb.setHttpUserAgent(Utils.generateBrowserUserAgent());
|
||||
if (!mSameOAuthSigningUrl) {
|
||||
cb.setSigningRestBaseURL(DEFAULT_SIGNING_REST_BASE_URL);
|
||||
cb.setSigningOAuthBaseURL(DEFAULT_SIGNING_OAUTH_BASE_URL);
|
||||
cb.setSigningUploadBaseURL(DEFAULT_SIGNING_UPLOAD_BASE_URL);
|
||||
}
|
||||
if (isEmpty(mConsumerKey) || isEmpty(mConsumerSecret)) {
|
||||
cb.setOAuthConsumerKey(TWITTER_CONSUMER_KEY_3);
|
||||
|
@ -501,6 +504,7 @@ public class SignInActivity extends BaseActionBarActivity implements TwitterCons
|
|||
}
|
||||
|
||||
void onSignInStart() {
|
||||
if (isFinishing()) return;
|
||||
final SupportProgressDialogFragment fragment = SupportProgressDialogFragment.show(this, FRAGMENT_TAG_SIGN_IN_PROGRESS);
|
||||
fragment.setCancelable(false);
|
||||
}
|
||||
|
|
|
@ -45,6 +45,8 @@ import static org.mariotaku.twidere.util.Utils.announceForAccessibilityCompat;
|
|||
public class SupportTabsAdapter extends SupportFixedFragmentStatePagerAdapter implements TabProvider, TabListener,
|
||||
Constants {
|
||||
|
||||
private static final String EXTRA_ADAPTER_POSITION = "adapter_position";
|
||||
|
||||
private final ArrayList<SupportTabSpec> mTabs = new ArrayList<>();
|
||||
|
||||
private final Context mContext;
|
||||
|
@ -105,7 +107,7 @@ public class SupportTabsAdapter extends SupportFixedFragmentStatePagerAdapter im
|
|||
if (args == null) {
|
||||
args = new Bundle();
|
||||
}
|
||||
args.putInt(EXTRA_TAB_POSITION, position);
|
||||
args.putInt(EXTRA_ADAPTER_POSITION, position);
|
||||
return args;
|
||||
}
|
||||
|
||||
|
@ -155,7 +157,7 @@ public class SupportTabsAdapter extends SupportFixedFragmentStatePagerAdapter im
|
|||
if (!(object instanceof Fragment)) return POSITION_NONE;
|
||||
final Bundle args = ((Fragment) object).getArguments();
|
||||
if (args == null) return POSITION_NONE;
|
||||
return args.getInt(EXTRA_TAB_POSITION, POSITION_NONE);
|
||||
return args.getInt(EXTRA_ADAPTER_POSITION, POSITION_NONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -83,6 +83,11 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
|
|||
public boolean onMenuItemClick(MenuItem item) {
|
||||
final ParcelableStatus status = mSelectedStatus;
|
||||
if (status == null) return false;
|
||||
if (item.getItemId() == MENU_SHARE) {
|
||||
final Intent shareIntent = Utils.createStatusShareIntent(getActivity(), status);
|
||||
startActivity(Intent.createChooser(shareIntent, getString(R.string.share_status)));
|
||||
return true;
|
||||
}
|
||||
return Utils.handleMenuItemClick(getActivity(), AbsStatusesFragment.this,
|
||||
getFragmentManager(), getTwitterWrapper(), status, item);
|
||||
}
|
||||
|
@ -461,7 +466,7 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
|
|||
protected abstract AbsStatusesAdapter<Data> onCreateAdapter(Context context, boolean compact);
|
||||
|
||||
protected void saveReadPosition() {
|
||||
final String readPositionTag = getReadPositionTag();
|
||||
final String readPositionTag = getReadPositionTagWithAccounts();
|
||||
if (readPositionTag == null) return;
|
||||
final int position = mLayoutManager.findFirstVisibleItemPosition();
|
||||
if (position == RecyclerView.NO_POSITION) return;
|
||||
|
|
|
@ -115,9 +115,12 @@ public class SearchFragment extends BaseSupportFragment implements RefreshScroll
|
|||
private void updateTabOffset() {
|
||||
final int controlBarHeight = getControlBarHeight();
|
||||
final int translationY = controlBarHeight - mControlBarOffsetPixels;
|
||||
final View view = getActivity().getWindow().findViewById(android.support.v7.appcompat.R.id.action_bar);
|
||||
if (view != null && controlBarHeight != 0) {
|
||||
view.setAlpha(translationY / (float) controlBarHeight);
|
||||
final FragmentActivity activity = getActivity();
|
||||
if (activity instanceof LinkHandlerActivity) {
|
||||
final View view = activity.getWindow().findViewById(android.support.v7.appcompat.R.id.action_bar);
|
||||
if (view != null && controlBarHeight != 0) {
|
||||
view.setAlpha(translationY / (float) controlBarHeight);
|
||||
}
|
||||
}
|
||||
mPagerIndicator.setTranslationY(translationY);
|
||||
mPagerWindowOverlay.setTranslationY(translationY);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -30,12 +30,8 @@ import android.content.Intent;
|
|||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.Outline;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.PorterDuff.Mode;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
|
@ -61,6 +57,7 @@ import android.support.v4.content.res.ResourcesCompat;
|
|||
import android.support.v4.view.ViewCompat;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.internal.widget.TintButton;
|
||||
import android.text.Html;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
|
@ -197,7 +194,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
|
|||
private TabPagerIndicator mPagerIndicator;
|
||||
private View mUuckyFooter;
|
||||
private View mProfileBannerContainer;
|
||||
private Button mFollowButton;
|
||||
private TintButton mFollowButton;
|
||||
private ProgressBar mFollowProgress;
|
||||
private View mPagesContent, mPagesErrorContainer;
|
||||
private ImageView mPagesErrorIcon;
|
||||
|
@ -389,13 +386,8 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
|
|||
mFollowButton.setCompoundDrawablePadding(Math.round(mFollowButton.getTextSize() * 0.25f));
|
||||
|
||||
final ContentResolver resolver = getContentResolver();
|
||||
final String where = Expression.equals(CachedUsers.USER_ID, user.id).getSQL();
|
||||
final ContentValues cachedValues = ParcelableUser.makeCachedUserContentValues(user);
|
||||
resolver.insert(CachedUsers.CONTENT_URI, cachedValues);
|
||||
// I bet you don't want to see blocked user in your auto
|
||||
// complete list.
|
||||
if (!data.getData().isSourceBlockingTarget()) {
|
||||
}
|
||||
mFollowButton.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
mFollowButton.setText(null);
|
||||
|
@ -1132,7 +1124,6 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
|
|||
mErrorMessageView = (TextView) headerView.findViewById(R.id.error_message);
|
||||
mProfileBannerView = (ProfileBannerImageView) view.findViewById(R.id.profile_banner);
|
||||
mProfileBannerContainer = view.findViewById(R.id.profile_banner_container);
|
||||
// mCardView = (CardView) headerView.findViewById(R.id.card);
|
||||
mNameView = (TextView) headerView.findViewById(R.id.name);
|
||||
mScreenNameView = (TextView) headerView.findViewById(R.id.screen_name);
|
||||
mDescriptionView = (TextView) headerView.findViewById(R.id.description);
|
||||
|
@ -1154,7 +1145,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
|
|||
mProfileBannerSpace = headerView.findViewById(R.id.profile_banner_space);
|
||||
mViewPager = (ViewPager) contentView.findViewById(R.id.view_pager);
|
||||
mPagerIndicator = (TabPagerIndicator) contentView.findViewById(R.id.view_pager_tabs);
|
||||
mFollowButton = (Button) headerView.findViewById(R.id.follow);
|
||||
mFollowButton = (TintButton) headerView.findViewById(R.id.follow);
|
||||
mFollowProgress = (ProgressBar) headerView.findViewById(R.id.follow_progress);
|
||||
mUuckyFooter = headerView.findViewById(R.id.uucky_footer);
|
||||
mPagesContent = view.findViewById(R.id.pages_content);
|
||||
|
@ -1183,11 +1174,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
|
|||
public void setListShown(boolean shown) {
|
||||
final TintedStatusFrameLayout tintedStatus = mTintedStatusContent;
|
||||
if (tintedStatus == null) return;
|
||||
final FragmentActivity activity = getActivity();
|
||||
final LinkHandlerActivity linkHandler = (LinkHandlerActivity) activity;
|
||||
final boolean drawColor = !ThemeUtils.isDarkTheme(linkHandler.getCurrentThemeResourceId());
|
||||
tintedStatus.setDrawShadow(shown);
|
||||
tintedStatus.setDrawColor(drawColor);
|
||||
}
|
||||
|
||||
private void getFriendship() {
|
||||
|
@ -1253,10 +1240,8 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
|
|||
final LinkHandlerActivity linkHandler = (LinkHandlerActivity) activity;
|
||||
final ActionBar actionBar = linkHandler.getSupportActionBar();
|
||||
if (actionBar == null) return;
|
||||
final int themeResId = linkHandler.getCurrentThemeResourceId();
|
||||
final Drawable shadow = ResourcesCompat.getDrawable(activity.getResources(), R.drawable.shadow_user_banner_action_bar, null);
|
||||
final Drawable background = ThemeUtils.getActionBarBackground(activity, themeResId);
|
||||
mActionBarBackground = new ActionBarDrawable(getResources(), shadow, background, ThemeUtils.isDarkTheme(themeResId));
|
||||
mActionBarBackground = new ActionBarDrawable(getResources(), shadow);
|
||||
mActionBarBackground.setAlpha(linkHandler.getCurrentThemeBackgroundAlpha());
|
||||
mProfileBannerView.setAlpha(linkHandler.getCurrentThemeBackgroundAlpha() / 255f);
|
||||
actionBar.setBackgroundDrawable(mActionBarBackground);
|
||||
|
@ -1266,19 +1251,22 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
|
|||
if (mActionBarBackground == null) {
|
||||
setupBaseActionBar();
|
||||
}
|
||||
mActionBarBackground.setColor(color);
|
||||
final FragmentActivity activity = getActivity();
|
||||
mTintedStatusContent.setColor(color, ThemeUtils.getThemeAlpha(activity));
|
||||
final IThemedActivity themed = (IThemedActivity) activity;
|
||||
final int themeRes = themed.getCurrentThemeResourceId();
|
||||
if (ThemeUtils.isDarkTheme(themeRes)) {
|
||||
final int actionBarColor = getResources().getColor(R.color.background_color_action_bar_dark);
|
||||
mTintedStatusContent.setColor(actionBarColor, themed.getCurrentThemeBackgroundAlpha());
|
||||
mActionBarBackground.setColor(actionBarColor);
|
||||
} else {
|
||||
mTintedStatusContent.setColor(color, themed.getCurrentThemeBackgroundAlpha());
|
||||
mActionBarBackground.setColor(color);
|
||||
}
|
||||
mDescriptionView.setLinkTextColor(color);
|
||||
mProfileBannerView.setBackgroundColor(color);
|
||||
mLocationView.setLinkTextColor(color);
|
||||
mURLView.setLinkTextColor(color);
|
||||
if (activity instanceof IThemedActivity) {
|
||||
final int themeRes = ((IThemedActivity) activity).getCurrentThemeResourceId();
|
||||
ViewAccessor.setBackground(mPagerIndicator, ThemeUtils.getActionBarStackedBackground(activity, themeRes, color, true));
|
||||
} else {
|
||||
mPagerIndicator.setBackgroundColor(color);
|
||||
}
|
||||
ViewAccessor.setBackground(mPagerIndicator, ThemeUtils.getActionBarStackedBackground(activity, themeRes, color, true));
|
||||
|
||||
final HeaderDrawerLayout drawer = mHeaderDrawerLayout;
|
||||
if (drawer != null) {
|
||||
|
@ -1445,22 +1433,17 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
|
|||
private static class ActionBarDrawable extends LayerDrawable {
|
||||
|
||||
private final Drawable mShadowDrawable;
|
||||
private final Drawable mBackgroundDrawable;
|
||||
private final ColorDrawable mColorDrawable;
|
||||
private final boolean mColorLineOnly;
|
||||
|
||||
private float mFactor;
|
||||
private int mColor;
|
||||
private int mAlpha;
|
||||
private float mOutlineAlphaFactor;
|
||||
|
||||
public ActionBarDrawable(Resources resources, Drawable shadow, Drawable background,
|
||||
boolean colorLineOnly) {
|
||||
super(new Drawable[]{shadow, background, new ActionBarColorDrawable(true)});
|
||||
public ActionBarDrawable(Resources resources, Drawable shadow) {
|
||||
super(new Drawable[]{shadow, new ActionBarColorDrawable(true)});
|
||||
mShadowDrawable = getDrawable(0);
|
||||
mBackgroundDrawable = getDrawable(1);
|
||||
mColorDrawable = (ColorDrawable) getDrawable(2);
|
||||
mColorLineOnly = colorLineOnly;
|
||||
mColorDrawable = (ColorDrawable) getDrawable(1);
|
||||
setAlpha(0xFF);
|
||||
setOutlineAlphaFactor(1);
|
||||
}
|
||||
|
@ -1472,12 +1455,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
|
|||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
@Override
|
||||
public void getOutline(Outline outline) {
|
||||
final boolean showColor = !mColorLineOnly && mColor != 0;
|
||||
if (showColor) {
|
||||
mColorDrawable.getOutline(outline);
|
||||
} else {
|
||||
mBackgroundDrawable.getOutline(outline);
|
||||
}
|
||||
mColorDrawable.getOutline(outline);
|
||||
outline.setAlpha(mFactor * mOutlineAlphaFactor * 0.99f);
|
||||
}
|
||||
|
||||
|
@ -1494,22 +1472,12 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
|
|||
|
||||
@Override
|
||||
public int getIntrinsicWidth() {
|
||||
final boolean showColor = !mColorLineOnly && mColor != 0;
|
||||
if (showColor) {
|
||||
return mColorDrawable.getIntrinsicWidth();
|
||||
} else {
|
||||
return mBackgroundDrawable.getIntrinsicWidth();
|
||||
}
|
||||
return mColorDrawable.getIntrinsicWidth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicHeight() {
|
||||
final boolean showColor = !mColorLineOnly && mColor != 0;
|
||||
if (showColor) {
|
||||
return mColorDrawable.getIntrinsicHeight();
|
||||
} else {
|
||||
return mBackgroundDrawable.getIntrinsicHeight();
|
||||
}
|
||||
return mColorDrawable.getIntrinsicHeight();
|
||||
}
|
||||
|
||||
public void setColor(int color) {
|
||||
|
@ -1522,81 +1490,9 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
|
|||
mFactor = f;
|
||||
mShadowDrawable.setAlpha(Math.round(mAlpha * MathUtils.clamp(1 - f, 0, 1)));
|
||||
final boolean hasColor = mColor != 0;
|
||||
final boolean showBackground = mColorLineOnly || !hasColor;
|
||||
final boolean showLine = mColorLineOnly && hasColor;
|
||||
final boolean showColor = !mColorLineOnly && hasColor;
|
||||
mBackgroundDrawable.setAlpha(showBackground ? Math.round(mAlpha * MathUtils.clamp(f, 0, 1)) : 0);
|
||||
mColorDrawable.setAlpha(showColor ? Math.round(mAlpha * MathUtils.clamp(f, 0, 1)) : 0);
|
||||
mColorDrawable.setAlpha(hasColor ? Math.round(mAlpha * MathUtils.clamp(f, 0, 1)) : 0);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
private static class LineBackgroundDrawable extends Drawable {
|
||||
|
||||
private final Rect mBounds;
|
||||
private final Paint mPaint;
|
||||
private final float mLineSize;
|
||||
|
||||
private int mAlpha;
|
||||
private int mColor;
|
||||
|
||||
LineBackgroundDrawable(Resources resources, float lineSizeDp) {
|
||||
mBounds = new Rect();
|
||||
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
mLineSize = resources.getDisplayMetrics().density * lineSizeDp;
|
||||
setColor(Color.TRANSPARENT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
canvas.drawRect(mBounds.left, mBounds.bottom - mLineSize, mBounds.right,
|
||||
mBounds.bottom, mPaint);
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return mColor;
|
||||
}
|
||||
|
||||
public void setColor(int color) {
|
||||
mColor = color;
|
||||
updatePaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBoundsChange(Rect bounds) {
|
||||
super.onBoundsChange(bounds);
|
||||
mBounds.set(bounds);
|
||||
}
|
||||
|
||||
private void updatePaint() {
|
||||
mPaint.setColor(mColor);
|
||||
mPaint.setAlpha(Color.alpha(mColor) * mAlpha / 0xFF);
|
||||
invalidateSelf();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getAlpha() {
|
||||
return mAlpha;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
mAlpha = alpha;
|
||||
updatePaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(ColorFilter cf) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
return PixelFormat.TRANSLUCENT;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -21,6 +21,8 @@ package org.mariotaku.twidere.model;
|
|||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.mariotaku.twidere.util.TwidereArrayUtils;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/3/25.
|
||||
*/
|
||||
|
@ -69,9 +71,25 @@ public class StringLongPair {
|
|||
return key + ":" + value;
|
||||
}
|
||||
|
||||
public static StringLongPair valueOf(String s) {
|
||||
public static StringLongPair valueOf(String s) throws NumberFormatException {
|
||||
if (s == null) return null;
|
||||
final String[] segs = s.split(":");
|
||||
if (segs.length != 2) throw new NumberFormatException();
|
||||
return new StringLongPair(segs[0], Long.parseLong(segs[1]));
|
||||
}
|
||||
|
||||
public static String toString(StringLongPair[] pairs) {
|
||||
if (pairs==null)return null;
|
||||
return TwidereArrayUtils.toString(pairs, ';', false);
|
||||
}
|
||||
|
||||
public static StringLongPair[] valuesOf(String s) throws NumberFormatException {
|
||||
if (s == null) return null;
|
||||
final String[] segs = s.split(";");
|
||||
final StringLongPair[] pairs = new StringLongPair[segs.length];
|
||||
for (int i = 0, j = segs.length; i < j; i++) {
|
||||
pairs[i] = valueOf(segs[i]);
|
||||
}
|
||||
return pairs;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ import android.os.ParcelFileDescriptor;
|
|||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.support.v4.app.NotificationCompat.InboxStyle;
|
||||
import android.support.v4.util.LongSparseArray;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.style.StyleSpan;
|
||||
|
@ -83,6 +84,7 @@ import org.mariotaku.twidere.provider.TwidereDataStore.Preferences;
|
|||
import org.mariotaku.twidere.provider.TwidereDataStore.SearchHistory;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Statuses;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.UnreadCounts;
|
||||
import org.mariotaku.twidere.receiver.NotificationReceiver;
|
||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||
import org.mariotaku.twidere.util.ImagePreloader;
|
||||
import org.mariotaku.twidere.util.MediaPreviewUtils;
|
||||
|
@ -873,7 +875,7 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
final String filteredSelection = Utils.buildStatusFilterWhereClause(Statuses.TABLE_NAME,
|
||||
selection, true).getSQL();
|
||||
final String[] userProjection = {Statuses.USER_ID, Statuses.USER_NAME, Statuses.USER_SCREEN_NAME};
|
||||
final String[] statusProjection = new String[0];
|
||||
final String[] statusProjection = {Statuses.STATUS_ID};
|
||||
final Cursor statusCursor = mDatabaseWrapper.query(Statuses.TABLE_NAME, statusProjection,
|
||||
filteredSelection, null, null, null, Statuses.SORT_ORDER_TIMESTAMP_DESC);
|
||||
final Cursor userCursor = mDatabaseWrapper.query(Statuses.TABLE_NAME, userProjection,
|
||||
|
@ -882,9 +884,11 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
final int usersCount = userCursor.getCount();
|
||||
final int statusesCount = statusCursor.getCount();
|
||||
if (statusesCount == 0 || usersCount == 0) return;
|
||||
final int idxUserName = userCursor.getColumnIndex(Statuses.USER_NAME),
|
||||
final int idxStatusId = statusCursor.getColumnIndex(Statuses.STATUS_ID),
|
||||
idxUserName = userCursor.getColumnIndex(Statuses.USER_NAME),
|
||||
idxUserScreenName = userCursor.getColumnIndex(Statuses.USER_NAME),
|
||||
idxUserId = userCursor.getColumnIndex(Statuses.USER_NAME);
|
||||
final long statusId = statusCursor.moveToFirst() ? statusCursor.getLong(idxStatusId) : -1;
|
||||
final String notificationTitle = resources.getQuantityString(R.plurals.N_new_statuses,
|
||||
statusesCount, statusesCount);
|
||||
final String notificationContent;
|
||||
|
@ -906,15 +910,6 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
notificationContent = resources.getString(R.string.from_name_and_N_others, othersName, usersCount - 1);
|
||||
}
|
||||
|
||||
// Setup on click intent
|
||||
final Intent homeIntent = new Intent(context, HomeActivity.class);
|
||||
final Uri.Builder homeLinkBuilder = new Uri.Builder();
|
||||
homeLinkBuilder.scheme(SCHEME_TWIDERE);
|
||||
homeLinkBuilder.authority(AUTHORITY_HOME);
|
||||
homeLinkBuilder.appendQueryParameter(QUERY_PARAM_ACCOUNT_ID, String.valueOf(accountId));
|
||||
homeIntent.setData(homeLinkBuilder.build());
|
||||
final PendingIntent clickIntent = PendingIntent.getActivity(context, 0, homeIntent, 0);
|
||||
|
||||
// Setup notification
|
||||
final NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
|
||||
builder.setAutoCancel(true);
|
||||
|
@ -923,7 +918,8 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
builder.setContentTitle(notificationTitle);
|
||||
builder.setContentText(notificationContent);
|
||||
builder.setCategory(NotificationCompat.CATEGORY_SOCIAL);
|
||||
builder.setContentIntent(clickIntent);
|
||||
builder.setContentIntent(getContentIntent(context, AUTHORITY_HOME, accountId));
|
||||
builder.setDeleteIntent(getDeleteIntent(context, AUTHORITY_HOME, accountId, statusId));
|
||||
builder.setNumber(statusesCount);
|
||||
builder.setColor(pref.getNotificationLightColor());
|
||||
setNotificationPreferences(builder, pref, pref.getHomeTimelineNotificationType());
|
||||
|
@ -951,7 +947,7 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
final String filteredSelection = Utils.buildStatusFilterWhereClause(Mentions.TABLE_NAME,
|
||||
selection, true).getSQL();
|
||||
final String[] userProjection = {Statuses.USER_ID, Statuses.USER_NAME, Statuses.USER_SCREEN_NAME};
|
||||
final String[] statusProjection = {Statuses.USER_ID, Statuses.USER_NAME, Statuses.USER_SCREEN_NAME,
|
||||
final String[] statusProjection = {Statuses.STATUS_ID, Statuses.USER_ID, Statuses.USER_NAME, Statuses.USER_SCREEN_NAME,
|
||||
Statuses.TEXT_UNESCAPED, Statuses.STATUS_TIMESTAMP};
|
||||
final Cursor statusCursor = mDatabaseWrapper.query(Mentions.TABLE_NAME, statusProjection,
|
||||
filteredSelection, null, null, null, Statuses.SORT_ORDER_TIMESTAMP_DESC);
|
||||
|
@ -964,6 +960,7 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
final String accountName = Utils.getAccountName(context, accountId);
|
||||
final String accountScreenName = Utils.getAccountScreenName(context, accountId);
|
||||
final int idxStatusText = statusCursor.getColumnIndex(Statuses.TEXT_UNESCAPED),
|
||||
idxStatusId = statusCursor.getColumnIndex(Statuses.STATUS_ID),
|
||||
idxStatusTimestamp = statusCursor.getColumnIndex(Statuses.STATUS_TIMESTAMP),
|
||||
idxStatusUserName = statusCursor.getColumnIndex(Statuses.USER_NAME),
|
||||
idxStatusUserScreenName = statusCursor.getColumnIndex(Statuses.USER_SCREEN_NAME),
|
||||
|
@ -985,12 +982,15 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
}
|
||||
|
||||
// Add rich notification and get latest tweet timestamp
|
||||
long when = -1;
|
||||
long when = -1, statusId = -1;
|
||||
final InboxStyle style = new InboxStyle();
|
||||
for (int i = 0, j = Math.min(statusesCount, 5); statusCursor.moveToPosition(i) && i < j; i++) {
|
||||
if (when < 0) {
|
||||
if (when == -1) {
|
||||
when = statusCursor.getLong(idxStatusTimestamp);
|
||||
}
|
||||
if (statusId == -1) {
|
||||
statusId = statusCursor.getLong(idxStatusId);
|
||||
}
|
||||
final SpannableStringBuilder sb = new SpannableStringBuilder();
|
||||
sb.append(UserColorNameUtils.getUserNickname(context, statusCursor.getLong(idxUserId),
|
||||
mNameFirst ? statusCursor.getString(idxStatusUserName) : statusCursor.getString(idxStatusUserScreenName)));
|
||||
|
@ -1005,15 +1005,6 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
style.setSummaryText("@" + accountScreenName);
|
||||
}
|
||||
|
||||
// Setup on click intent
|
||||
final Intent homeIntent = new Intent(context, HomeActivity.class);
|
||||
final Uri.Builder homeLinkBuilder = new Uri.Builder();
|
||||
homeLinkBuilder.scheme(SCHEME_TWIDERE);
|
||||
homeLinkBuilder.authority(AUTHORITY_MENTIONS);
|
||||
homeLinkBuilder.appendQueryParameter(QUERY_PARAM_ACCOUNT_ID, String.valueOf(accountId));
|
||||
homeIntent.setData(homeLinkBuilder.build());
|
||||
final PendingIntent clickIntent = PendingIntent.getActivity(context, 0, homeIntent, 0);
|
||||
|
||||
// Setup notification
|
||||
final NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
|
||||
builder.setAutoCancel(true);
|
||||
|
@ -1022,7 +1013,8 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
builder.setContentTitle(notificationTitle);
|
||||
builder.setContentText(notificationContent);
|
||||
builder.setCategory(NotificationCompat.CATEGORY_SOCIAL);
|
||||
builder.setContentIntent(clickIntent);
|
||||
builder.setContentIntent(getContentIntent(context, AUTHORITY_MENTIONS, accountId));
|
||||
builder.setDeleteIntent(getDeleteIntent(context, AUTHORITY_MENTIONS, accountId, statusId));
|
||||
builder.setNumber(statusesCount);
|
||||
builder.setWhen(when);
|
||||
builder.setStyle(style);
|
||||
|
@ -1036,6 +1028,43 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
}
|
||||
}
|
||||
|
||||
private PendingIntent getContentIntent(Context context, String type, long accountId) {
|
||||
// Setup click intent
|
||||
final Intent homeIntent = new Intent(context, HomeActivity.class);
|
||||
final Uri.Builder homeLinkBuilder = new Uri.Builder();
|
||||
homeLinkBuilder.scheme(SCHEME_TWIDERE);
|
||||
homeLinkBuilder.authority(type);
|
||||
homeLinkBuilder.appendQueryParameter(QUERY_PARAM_ACCOUNT_ID, String.valueOf(accountId));
|
||||
homeIntent.setData(homeLinkBuilder.build());
|
||||
return PendingIntent.getActivity(context, 0, homeIntent, 0);
|
||||
}
|
||||
|
||||
private static PendingIntent getDeleteIntent(Context context, String type, long accountId, long position) {
|
||||
// Setup delete intent
|
||||
final Intent recvIntent = new Intent(context, NotificationReceiver.class);
|
||||
final Uri.Builder recvLinkBuilder = new Uri.Builder();
|
||||
recvLinkBuilder.scheme(SCHEME_TWIDERE);
|
||||
recvLinkBuilder.authority(AUTHORITY_NOTIFICATIONS);
|
||||
recvLinkBuilder.appendPath(type);
|
||||
recvLinkBuilder.appendQueryParameter(QUERY_PARAM_ACCOUNT_ID, String.valueOf(accountId));
|
||||
recvLinkBuilder.appendQueryParameter(QUERY_PARAM_READ_POSITION, String.valueOf(position));
|
||||
recvIntent.setData(recvLinkBuilder.build());
|
||||
return PendingIntent.getBroadcast(context, 0, recvIntent, 0);
|
||||
}
|
||||
|
||||
private static PendingIntent getDeleteIntent(Context context, String type, long accountId, StringLongPair[] positions) {
|
||||
// Setup delete intent
|
||||
final Intent recvIntent = new Intent(context, NotificationReceiver.class);
|
||||
final Uri.Builder recvLinkBuilder = new Uri.Builder();
|
||||
recvLinkBuilder.scheme(SCHEME_TWIDERE);
|
||||
recvLinkBuilder.authority(AUTHORITY_NOTIFICATIONS);
|
||||
recvLinkBuilder.appendPath(type);
|
||||
recvLinkBuilder.appendQueryParameter(QUERY_PARAM_ACCOUNT_ID, String.valueOf(accountId));
|
||||
recvLinkBuilder.appendQueryParameter(QUERY_PARAM_READ_POSITIONS, StringLongPair.toString(positions));
|
||||
recvIntent.setData(recvLinkBuilder.build());
|
||||
return PendingIntent.getBroadcast(context, 0, recvIntent, 0);
|
||||
}
|
||||
|
||||
private void setNotificationPreferences(NotificationCompat.Builder builder, AccountPreferences pref, int defaultFlags) {
|
||||
int notificationDefaults = 0;
|
||||
if (AccountPreferences.isNotificationHasLight(defaultFlags)) {
|
||||
|
@ -1089,8 +1118,8 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
final String filteredSelection = selection.getSQL();
|
||||
final String[] userProjection = {DirectMessages.SENDER_ID, DirectMessages.SENDER_NAME,
|
||||
DirectMessages.SENDER_SCREEN_NAME};
|
||||
final String[] messageProjection = {DirectMessages.SENDER_ID, DirectMessages.SENDER_NAME,
|
||||
DirectMessages.SENDER_SCREEN_NAME, DirectMessages.TEXT_UNESCAPED,
|
||||
final String[] messageProjection = {DirectMessages.MESSAGE_ID, DirectMessages.SENDER_ID,
|
||||
DirectMessages.SENDER_NAME, DirectMessages.SENDER_SCREEN_NAME, DirectMessages.TEXT_UNESCAPED,
|
||||
DirectMessages.MESSAGE_TIMESTAMP};
|
||||
final Cursor messageCursor = mDatabaseWrapper.query(DirectMessages.Inbox.TABLE_NAME, messageProjection,
|
||||
filteredSelection, null, null, null, DirectMessages.DEFAULT_SORT_ORDER);
|
||||
|
@ -1104,6 +1133,8 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
final String accountScreenName = Utils.getAccountScreenName(context, accountId);
|
||||
final int idxMessageText = messageCursor.getColumnIndex(DirectMessages.TEXT_UNESCAPED),
|
||||
idxMessageTimestamp = messageCursor.getColumnIndex(DirectMessages.MESSAGE_TIMESTAMP),
|
||||
idxMessageId = messageCursor.getColumnIndex(DirectMessages.MESSAGE_ID),
|
||||
idxMessageUserId = messageCursor.getColumnIndex(DirectMessages.SENDER_ID),
|
||||
idxMessageUserName = messageCursor.getColumnIndex(DirectMessages.SENDER_NAME),
|
||||
idxMessageUserScreenName = messageCursor.getColumnIndex(DirectMessages.SENDER_SCREEN_NAME),
|
||||
idxUserName = userCursor.getColumnIndex(DirectMessages.SENDER_NAME),
|
||||
|
@ -1128,35 +1159,36 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
displayName, usersCount - 1, messagesCount);
|
||||
}
|
||||
|
||||
final LongSparseArray<Long> idsMap = new LongSparseArray<>();
|
||||
// Add rich notification and get latest tweet timestamp
|
||||
long when = -1;
|
||||
final InboxStyle style = new InboxStyle();
|
||||
for (int i = 0, j = Math.min(messagesCount, 5); messageCursor.moveToPosition(i) && i < j; i++) {
|
||||
for (int i = 0; messageCursor.moveToPosition(i) && i < messagesCount; i++) {
|
||||
if (when < 0) {
|
||||
when = messageCursor.getLong(idxMessageTimestamp);
|
||||
}
|
||||
final SpannableStringBuilder sb = new SpannableStringBuilder();
|
||||
sb.append(UserColorNameUtils.getUserNickname(context, messageCursor.getLong(idxUserId),
|
||||
mNameFirst ? messageCursor.getString(idxMessageUserName) : messageCursor.getString(idxMessageUserScreenName)));
|
||||
sb.setSpan(new StyleSpan(Typeface.BOLD), 0, sb.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
sb.append(' ');
|
||||
sb.append(messageCursor.getString(idxMessageText));
|
||||
style.addLine(sb);
|
||||
if (i < 5) {
|
||||
final SpannableStringBuilder sb = new SpannableStringBuilder();
|
||||
sb.append(UserColorNameUtils.getUserNickname(context, messageCursor.getLong(idxUserId),
|
||||
mNameFirst ? messageCursor.getString(idxMessageUserName) : messageCursor.getString(idxMessageUserScreenName)));
|
||||
sb.setSpan(new StyleSpan(Typeface.BOLD), 0, sb.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
sb.append(' ');
|
||||
sb.append(messageCursor.getString(idxMessageText));
|
||||
style.addLine(sb);
|
||||
}
|
||||
final long userId = messageCursor.getLong(idxMessageUserId);
|
||||
final long messageId = messageCursor.getLong(idxMessageId);
|
||||
idsMap.put(userId, Math.max(idsMap.get(userId, -1L), messageId));
|
||||
}
|
||||
if (mNameFirst) {
|
||||
style.setSummaryText(accountName);
|
||||
} else {
|
||||
style.setSummaryText("@" + accountScreenName);
|
||||
}
|
||||
|
||||
// Setup on click intent
|
||||
final Intent homeIntent = new Intent(context, HomeActivity.class);
|
||||
final Uri.Builder homeLinkBuilder = new Uri.Builder();
|
||||
homeLinkBuilder.scheme(SCHEME_TWIDERE);
|
||||
homeLinkBuilder.authority(AUTHORITY_DIRECT_MESSAGES);
|
||||
homeLinkBuilder.appendQueryParameter(QUERY_PARAM_ACCOUNT_ID, String.valueOf(accountId));
|
||||
homeIntent.setData(homeLinkBuilder.build());
|
||||
final PendingIntent clickIntent = PendingIntent.getActivity(context, 0, homeIntent, 0);
|
||||
final StringLongPair[] positions = new StringLongPair[idsMap.size()];
|
||||
for (int i = 0, j = idsMap.size(); i < j; i++) {
|
||||
positions[i] = new StringLongPair(String.valueOf(idsMap.keyAt(i)), idsMap.valueAt(i));
|
||||
}
|
||||
|
||||
// Setup notification
|
||||
final NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
|
||||
|
@ -1166,7 +1198,8 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
builder.setContentTitle(notificationTitle);
|
||||
builder.setContentText(notificationContent);
|
||||
builder.setCategory(NotificationCompat.CATEGORY_SOCIAL);
|
||||
builder.setContentIntent(clickIntent);
|
||||
builder.setContentIntent(getContentIntent(context, AUTHORITY_DIRECT_MESSAGES, accountId));
|
||||
builder.setContentIntent(getDeleteIntent(context, AUTHORITY_DIRECT_MESSAGES, accountId, positions));
|
||||
builder.setNumber(messagesCount);
|
||||
builder.setWhen(when);
|
||||
builder.setStyle(style);
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* 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.receiver;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.mariotaku.twidere.Constants;
|
||||
import org.mariotaku.twidere.app.TwidereApplication;
|
||||
import org.mariotaku.twidere.fragment.support.DirectMessagesFragment;
|
||||
import org.mariotaku.twidere.fragment.support.HomeTimelineFragment;
|
||||
import org.mariotaku.twidere.fragment.support.MentionsTimelineFragment;
|
||||
import org.mariotaku.twidere.model.StringLongPair;
|
||||
import org.mariotaku.twidere.util.ParseUtils;
|
||||
import org.mariotaku.twidere.util.ReadStateManager;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/4/4.
|
||||
*/
|
||||
public class NotificationReceiver extends BroadcastReceiver implements Constants {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
switch (intent.getAction()) {
|
||||
case BROADCAST_NOTIFICATION_DELETED: {
|
||||
final Uri uri = intent.getData();
|
||||
final String tag = getPositionTag(uri.getLastPathSegment());
|
||||
if (tag == null) return;
|
||||
final long accountId = ParseUtils.parseLong(uri.getQueryParameter(QUERY_PARAM_ACCOUNT_ID), -1);
|
||||
final TwidereApplication app = TwidereApplication.getInstance(context);
|
||||
final ReadStateManager manager = app.getReadStateManager();
|
||||
final String paramReadPosition, paramReadPositions;
|
||||
if (!TextUtils.isEmpty(paramReadPosition = uri.getQueryParameter(QUERY_PARAM_READ_POSITION))) {
|
||||
manager.setPosition(Utils.getReadPositionTagWithAccounts(tag, accountId),
|
||||
ParseUtils.parseLong(paramReadPosition, -1));
|
||||
} else if (!TextUtils.isEmpty(paramReadPositions = uri.getQueryParameter(QUERY_PARAM_READ_POSITIONS))) {
|
||||
try {
|
||||
final StringLongPair[] pairs = StringLongPair.valuesOf(paramReadPositions);
|
||||
for (StringLongPair pair : pairs) {
|
||||
manager.setPosition(tag, pair.getKey(), pair.getValue());
|
||||
}
|
||||
} catch (NumberFormatException ignore) {
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getPositionTag(String type) {
|
||||
switch (type) {
|
||||
case AUTHORITY_HOME: {
|
||||
return HomeTimelineFragment.KEY_READ_POSITION_TAG;
|
||||
}
|
||||
case AUTHORITY_MENTIONS: {
|
||||
return MentionsTimelineFragment.KEY_READ_POSITION_TAG;
|
||||
}
|
||||
case AUTHORITY_DIRECT_MESSAGES: {
|
||||
return DirectMessagesFragment.KEY_READ_POSITION_TAG;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2014 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.service;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
|
||||
import com.google.android.apps.dashclock.api.DashClockExtension;
|
||||
import com.google.android.apps.dashclock.api.ExtensionData;
|
||||
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.TwidereConstants;
|
||||
import org.mariotaku.twidere.activity.support.HomeActivity;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.UnreadCounts;
|
||||
import org.mariotaku.twidere.util.UnreadCountUtils;
|
||||
|
||||
public class DashClockHomeUnreadCountService extends DashClockExtension implements TwidereConstants {
|
||||
|
||||
private static final String[] URIS = { UnreadCounts.CONTENT_URI.toString() };
|
||||
|
||||
@Override
|
||||
protected void onInitialize(final boolean isReconnect) {
|
||||
super.onInitialize(isReconnect);
|
||||
addWatchContentUris(URIS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onUpdateData(final int reason) {
|
||||
final ExtensionData data = new ExtensionData();
|
||||
final int count = UnreadCountUtils.getUnreadCount(this, TAB_TYPE_HOME_TIMELINE);
|
||||
final Resources res = getResources();
|
||||
data.visible(count > 0);
|
||||
data.icon(R.drawable.ic_extension_twidere);
|
||||
data.status(Integer.toString(count));
|
||||
data.expandedTitle(res.getQuantityString(R.plurals.N_new_statuses, count, count));
|
||||
data.clickIntent(new Intent(this, HomeActivity.class));
|
||||
publishUpdate(data);
|
||||
}
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2014 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.service;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
|
||||
import com.google.android.apps.dashclock.api.DashClockExtension;
|
||||
import com.google.android.apps.dashclock.api.ExtensionData;
|
||||
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.TwidereConstants;
|
||||
import org.mariotaku.twidere.activity.support.HomeActivity;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.UnreadCounts;
|
||||
import org.mariotaku.twidere.util.UnreadCountUtils;
|
||||
|
||||
public class DashClockMentionsUnreadCountService extends DashClockExtension implements TwidereConstants {
|
||||
|
||||
private static final String[] URIS = { UnreadCounts.CONTENT_URI.toString() };
|
||||
|
||||
@Override
|
||||
protected void onInitialize(final boolean isReconnect) {
|
||||
super.onInitialize(isReconnect);
|
||||
addWatchContentUris(URIS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onUpdateData(final int reason) {
|
||||
final ExtensionData data = new ExtensionData();
|
||||
final int count = UnreadCountUtils.getUnreadCount(this, TAB_TYPE_MENTIONS_TIMELINE);
|
||||
final Resources res = getResources();
|
||||
data.visible(count > 0);
|
||||
data.icon(R.drawable.ic_extension_mentions);
|
||||
data.status(Integer.toString(count));
|
||||
data.expandedTitle(res.getQuantityString(R.plurals.N_new_mentions, count, count));
|
||||
data.clickIntent(new Intent(this, HomeActivity.class));
|
||||
publishUpdate(data);
|
||||
}
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2014 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.service;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
|
||||
import com.google.android.apps.dashclock.api.DashClockExtension;
|
||||
import com.google.android.apps.dashclock.api.ExtensionData;
|
||||
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.TwidereConstants;
|
||||
import org.mariotaku.twidere.activity.support.HomeActivity;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.UnreadCounts;
|
||||
import org.mariotaku.twidere.util.UnreadCountUtils;
|
||||
|
||||
public class DashClockMessagesUnreadCountService extends DashClockExtension implements TwidereConstants {
|
||||
|
||||
private static final String[] URIS = { UnreadCounts.CONTENT_URI.toString() };
|
||||
|
||||
@Override
|
||||
protected void onInitialize(final boolean isReconnect) {
|
||||
super.onInitialize(isReconnect);
|
||||
addWatchContentUris(URIS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onUpdateData(final int reason) {
|
||||
final ExtensionData data = new ExtensionData();
|
||||
final int count = UnreadCountUtils.getUnreadCount(this, TAB_TYPE_DIRECT_MESSAGES);
|
||||
final Resources res = getResources();
|
||||
data.visible(count > 0);
|
||||
data.icon(R.drawable.ic_extension_messages);
|
||||
data.status(Integer.toString(count));
|
||||
data.expandedTitle(res.getQuantityString(R.plurals.N_new_messages, count, count));
|
||||
data.clickIntent(new Intent(this, HomeActivity.class));
|
||||
publishUpdate(data);
|
||||
}
|
||||
}
|
|
@ -53,265 +53,257 @@ import static org.mariotaku.twidere.util.Utils.shouldStopAutoRefreshOnBatteryLow
|
|||
|
||||
public class RefreshService extends Service implements Constants {
|
||||
|
||||
private SharedPreferencesWrapper mPreferences;
|
||||
private SharedPreferencesWrapper mPreferences;
|
||||
|
||||
private AlarmManager mAlarmManager;
|
||||
private AsyncTwitterWrapper mTwitterWrapper;
|
||||
private PendingIntent mPendingRefreshHomeTimelineIntent, mPendingRefreshMentionsIntent,
|
||||
mPendingRefreshDirectMessagesIntent, mPendingRefreshTrendsIntent;
|
||||
private AlarmManager mAlarmManager;
|
||||
private AsyncTwitterWrapper mTwitterWrapper;
|
||||
private PendingIntent mPendingRefreshHomeTimelineIntent, mPendingRefreshMentionsIntent,
|
||||
mPendingRefreshDirectMessagesIntent, mPendingRefreshTrendsIntent;
|
||||
|
||||
private final BroadcastReceiver mStateReceiver = new BroadcastReceiver() {
|
||||
private final BroadcastReceiver mStateReceiver = new BroadcastReceiver() {
|
||||
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
final String action = intent.getAction();
|
||||
if (isDebugBuild()) {
|
||||
Log.d(LOGTAG, String.format("Refresh service received action %s", action));
|
||||
}
|
||||
if (BROADCAST_NOTIFICATION_DELETED.equals(action)) {
|
||||
final int notificationId = intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1);
|
||||
final long accountId = intent.getLongExtra(EXTRA_NOTIFICATION_ACCOUNT, -1);
|
||||
clearNotification(notificationId, accountId);
|
||||
} else if (BROADCAST_RESCHEDULE_HOME_TIMELINE_REFRESHING.equals(action)) {
|
||||
rescheduleHomeTimelineRefreshing();
|
||||
} else if (BROADCAST_RESCHEDULE_MENTIONS_REFRESHING.equals(action)) {
|
||||
rescheduleMentionsRefreshing();
|
||||
} else if (BROADCAST_RESCHEDULE_DIRECT_MESSAGES_REFRESHING.equals(action)) {
|
||||
rescheduleDirectMessagesRefreshing();
|
||||
} else if (BROADCAST_RESCHEDULE_TRENDS_REFRESHING.equals(action)) {
|
||||
rescheduleTrendsRefreshing();
|
||||
} else if (isAutoRefreshAllowed()) {
|
||||
final long[] accountIds = getAccountIds(context);
|
||||
final AccountPreferences[] accountPrefs = AccountPreferences.getAccountPreferences(context, accountIds);
|
||||
if (BROADCAST_REFRESH_HOME_TIMELINE.equals(action)) {
|
||||
final long[] refreshIds = getRefreshableIds(accountPrefs, new HomeRefreshableFilter());
|
||||
final long[] sinceIds = getNewestStatusIdsFromDatabase(context, Statuses.CONTENT_URI, refreshIds);
|
||||
if (isDebugBuild()) {
|
||||
Log.d(LOGTAG, String.format("Auto refreshing home for %s", Arrays.toString(refreshIds)));
|
||||
}
|
||||
if (!isHomeTimelineRefreshing()) {
|
||||
getHomeTimeline(refreshIds, null, sinceIds);
|
||||
}
|
||||
} else if (BROADCAST_REFRESH_MENTIONS.equals(action)) {
|
||||
final long[] refreshIds = getRefreshableIds(accountPrefs, new MentionsRefreshableFilter());
|
||||
final long[] sinceIds = getNewestStatusIdsFromDatabase(context, Mentions.CONTENT_URI, refreshIds);
|
||||
if (isDebugBuild()) {
|
||||
Log.d(LOGTAG, String.format("Auto refreshing mentions for %s", Arrays.toString(refreshIds)));
|
||||
}
|
||||
if (!isMentionsRefreshing()) {
|
||||
getMentions(refreshIds, null, sinceIds);
|
||||
}
|
||||
} else if (BROADCAST_REFRESH_DIRECT_MESSAGES.equals(action)) {
|
||||
final long[] refreshIds = getRefreshableIds(accountPrefs, new MessagesRefreshableFilter());
|
||||
final long[] sinceIds = getNewestMessageIdsFromDatabase(context, DirectMessages.Inbox.CONTENT_URI,
|
||||
refreshIds);
|
||||
if (isDebugBuild()) {
|
||||
Log.d(LOGTAG, String.format("Auto refreshing messages for %s", Arrays.toString(refreshIds)));
|
||||
}
|
||||
if (!isReceivedDirectMessagesRefreshing()) {
|
||||
getReceivedDirectMessages(refreshIds, null, sinceIds);
|
||||
}
|
||||
} else if (BROADCAST_REFRESH_TRENDS.equals(action)) {
|
||||
final long[] refreshIds = getRefreshableIds(accountPrefs, new TrendsRefreshableFilter());
|
||||
if (isDebugBuild()) {
|
||||
Log.d(LOGTAG, String.format("Auto refreshing trends for %s", Arrays.toString(refreshIds)));
|
||||
}
|
||||
if (!isLocalTrendsRefreshing()) {
|
||||
getLocalTrends(refreshIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
final String action = intent.getAction();
|
||||
if (isDebugBuild()) {
|
||||
Log.d(LOGTAG, String.format("Refresh service received action %s", action));
|
||||
}
|
||||
if (BROADCAST_RESCHEDULE_HOME_TIMELINE_REFRESHING.equals(action)) {
|
||||
rescheduleHomeTimelineRefreshing();
|
||||
} else if (BROADCAST_RESCHEDULE_MENTIONS_REFRESHING.equals(action)) {
|
||||
rescheduleMentionsRefreshing();
|
||||
} else if (BROADCAST_RESCHEDULE_DIRECT_MESSAGES_REFRESHING.equals(action)) {
|
||||
rescheduleDirectMessagesRefreshing();
|
||||
} else if (BROADCAST_RESCHEDULE_TRENDS_REFRESHING.equals(action)) {
|
||||
rescheduleTrendsRefreshing();
|
||||
} else if (isAutoRefreshAllowed()) {
|
||||
final long[] accountIds = getAccountIds(context);
|
||||
final AccountPreferences[] accountPrefs = AccountPreferences.getAccountPreferences(context, accountIds);
|
||||
if (BROADCAST_REFRESH_HOME_TIMELINE.equals(action)) {
|
||||
final long[] refreshIds = getRefreshableIds(accountPrefs, new HomeRefreshableFilter());
|
||||
final long[] sinceIds = getNewestStatusIdsFromDatabase(context, Statuses.CONTENT_URI, refreshIds);
|
||||
if (isDebugBuild()) {
|
||||
Log.d(LOGTAG, String.format("Auto refreshing home for %s", Arrays.toString(refreshIds)));
|
||||
}
|
||||
if (!isHomeTimelineRefreshing()) {
|
||||
getHomeTimeline(refreshIds, null, sinceIds);
|
||||
}
|
||||
} else if (BROADCAST_REFRESH_MENTIONS.equals(action)) {
|
||||
final long[] refreshIds = getRefreshableIds(accountPrefs, new MentionsRefreshableFilter());
|
||||
final long[] sinceIds = getNewestStatusIdsFromDatabase(context, Mentions.CONTENT_URI, refreshIds);
|
||||
if (isDebugBuild()) {
|
||||
Log.d(LOGTAG, String.format("Auto refreshing mentions for %s", Arrays.toString(refreshIds)));
|
||||
}
|
||||
if (!isMentionsRefreshing()) {
|
||||
getMentions(refreshIds, null, sinceIds);
|
||||
}
|
||||
} else if (BROADCAST_REFRESH_DIRECT_MESSAGES.equals(action)) {
|
||||
final long[] refreshIds = getRefreshableIds(accountPrefs, new MessagesRefreshableFilter());
|
||||
final long[] sinceIds = getNewestMessageIdsFromDatabase(context, DirectMessages.Inbox.CONTENT_URI,
|
||||
refreshIds);
|
||||
if (isDebugBuild()) {
|
||||
Log.d(LOGTAG, String.format("Auto refreshing messages for %s", Arrays.toString(refreshIds)));
|
||||
}
|
||||
if (!isReceivedDirectMessagesRefreshing()) {
|
||||
getReceivedDirectMessages(refreshIds, null, sinceIds);
|
||||
}
|
||||
} else if (BROADCAST_REFRESH_TRENDS.equals(action)) {
|
||||
final long[] refreshIds = getRefreshableIds(accountPrefs, new TrendsRefreshableFilter());
|
||||
if (isDebugBuild()) {
|
||||
Log.d(LOGTAG, String.format("Auto refreshing trends for %s", Arrays.toString(refreshIds)));
|
||||
}
|
||||
if (!isLocalTrendsRefreshing()) {
|
||||
getLocalTrends(refreshIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
@Override
|
||||
public IBinder onBind(final Intent intent) {
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public IBinder onBind(final Intent intent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
mAlarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
|
||||
final TwidereApplication app = TwidereApplication.getInstance(this);
|
||||
mTwitterWrapper = app.getTwitterWrapper();
|
||||
mPreferences = SharedPreferencesWrapper.getInstance(app, SHARED_PREFERENCES_NAME, MODE_PRIVATE);
|
||||
mPendingRefreshHomeTimelineIntent = PendingIntent.getBroadcast(this, 0, new Intent(
|
||||
BROADCAST_REFRESH_HOME_TIMELINE), 0);
|
||||
mPendingRefreshMentionsIntent = PendingIntent.getBroadcast(this, 0, new Intent(BROADCAST_REFRESH_MENTIONS), 0);
|
||||
mPendingRefreshDirectMessagesIntent = PendingIntent.getBroadcast(this, 0, new Intent(
|
||||
BROADCAST_REFRESH_DIRECT_MESSAGES), 0);
|
||||
mPendingRefreshTrendsIntent = PendingIntent.getBroadcast(this, 0, new Intent(BROADCAST_REFRESH_TRENDS), 0);
|
||||
final IntentFilter filter = new IntentFilter(BROADCAST_NOTIFICATION_DELETED);
|
||||
filter.addAction(BROADCAST_REFRESH_HOME_TIMELINE);
|
||||
filter.addAction(BROADCAST_REFRESH_MENTIONS);
|
||||
filter.addAction(BROADCAST_REFRESH_DIRECT_MESSAGES);
|
||||
filter.addAction(BROADCAST_RESCHEDULE_HOME_TIMELINE_REFRESHING);
|
||||
filter.addAction(BROADCAST_RESCHEDULE_MENTIONS_REFRESHING);
|
||||
filter.addAction(BROADCAST_RESCHEDULE_DIRECT_MESSAGES_REFRESHING);
|
||||
registerReceiver(mStateReceiver, filter);
|
||||
startAutoRefresh();
|
||||
}
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
mAlarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
|
||||
final TwidereApplication app = TwidereApplication.getInstance(this);
|
||||
mTwitterWrapper = app.getTwitterWrapper();
|
||||
mPreferences = SharedPreferencesWrapper.getInstance(app, SHARED_PREFERENCES_NAME, MODE_PRIVATE);
|
||||
mPendingRefreshHomeTimelineIntent = PendingIntent.getBroadcast(this, 0, new Intent(
|
||||
BROADCAST_REFRESH_HOME_TIMELINE), 0);
|
||||
mPendingRefreshMentionsIntent = PendingIntent.getBroadcast(this, 0, new Intent(BROADCAST_REFRESH_MENTIONS), 0);
|
||||
mPendingRefreshDirectMessagesIntent = PendingIntent.getBroadcast(this, 0, new Intent(
|
||||
BROADCAST_REFRESH_DIRECT_MESSAGES), 0);
|
||||
mPendingRefreshTrendsIntent = PendingIntent.getBroadcast(this, 0, new Intent(BROADCAST_REFRESH_TRENDS), 0);
|
||||
final IntentFilter filter = new IntentFilter(BROADCAST_NOTIFICATION_DELETED);
|
||||
filter.addAction(BROADCAST_REFRESH_HOME_TIMELINE);
|
||||
filter.addAction(BROADCAST_REFRESH_MENTIONS);
|
||||
filter.addAction(BROADCAST_REFRESH_DIRECT_MESSAGES);
|
||||
filter.addAction(BROADCAST_RESCHEDULE_HOME_TIMELINE_REFRESHING);
|
||||
filter.addAction(BROADCAST_RESCHEDULE_MENTIONS_REFRESHING);
|
||||
filter.addAction(BROADCAST_RESCHEDULE_DIRECT_MESSAGES_REFRESHING);
|
||||
registerReceiver(mStateReceiver, filter);
|
||||
startAutoRefresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
unregisterReceiver(mStateReceiver);
|
||||
if (hasAutoRefreshAccounts(this)) {
|
||||
// Auto refresh enabled, so I will try to start service after it was
|
||||
// stopped.
|
||||
startService(new Intent(this, getClass()));
|
||||
}
|
||||
super.onDestroy();
|
||||
}
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
unregisterReceiver(mStateReceiver);
|
||||
if (hasAutoRefreshAccounts(this)) {
|
||||
// Auto refresh enabled, so I will try to start service after it was
|
||||
// stopped.
|
||||
startService(new Intent(this, getClass()));
|
||||
}
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
protected boolean isAutoRefreshAllowed() {
|
||||
return isNetworkAvailable(this) && (isBatteryOkay(this) || !shouldStopAutoRefreshOnBatteryLow(this));
|
||||
}
|
||||
protected boolean isAutoRefreshAllowed() {
|
||||
return isNetworkAvailable(this) && (isBatteryOkay(this) || !shouldStopAutoRefreshOnBatteryLow(this));
|
||||
}
|
||||
|
||||
private void clearNotification(final int notificationId, final long notificationAccount) {
|
||||
mTwitterWrapper.clearNotificationAsync(notificationId, notificationAccount);
|
||||
}
|
||||
private int getHomeTimeline(final long[] accountIds, final long[] maxIds, final long[] sinceIds) {
|
||||
return mTwitterWrapper.getHomeTimelineAsync(accountIds, maxIds, sinceIds);
|
||||
}
|
||||
|
||||
private int getHomeTimeline(final long[] accountIds, final long[] maxIds, final long[] sinceIds) {
|
||||
return mTwitterWrapper.getHomeTimelineAsync(accountIds, maxIds, sinceIds);
|
||||
}
|
||||
private int getLocalTrends(final long[] accountIds) {
|
||||
final long account_id = getDefaultAccountId(this);
|
||||
final int woeid = mPreferences.getInt(KEY_LOCAL_TRENDS_WOEID, 1);
|
||||
return mTwitterWrapper.getLocalTrendsAsync(account_id, woeid);
|
||||
}
|
||||
|
||||
private int getLocalTrends(final long[] accountIds) {
|
||||
final long account_id = getDefaultAccountId(this);
|
||||
final int woeid = mPreferences.getInt(KEY_LOCAL_TRENDS_WOEID, 1);
|
||||
return mTwitterWrapper.getLocalTrendsAsync(account_id, woeid);
|
||||
}
|
||||
private int getMentions(final long[] accountIds, final long[] maxIds, final long[] sinceIds) {
|
||||
return mTwitterWrapper.getMentionsTimelineAsync(accountIds, maxIds, sinceIds);
|
||||
}
|
||||
|
||||
private int getMentions(final long[] accountIds, final long[] maxIds, final long[] sinceIds) {
|
||||
return mTwitterWrapper.getMentionsTimelineAsync(accountIds, maxIds, sinceIds);
|
||||
}
|
||||
private int getReceivedDirectMessages(final long[] accountIds, final long[] maxIds, final long[] sinceIds) {
|
||||
return mTwitterWrapper.getReceivedDirectMessagesAsync(accountIds, maxIds, sinceIds);
|
||||
}
|
||||
|
||||
private int getReceivedDirectMessages(final long[] accountIds, final long[] maxIds, final long[] sinceIds) {
|
||||
return mTwitterWrapper.getReceivedDirectMessagesAsync(accountIds, maxIds, sinceIds);
|
||||
}
|
||||
private long[] getRefreshableIds(final AccountPreferences[] prefs, final RefreshableAccountFilter filter) {
|
||||
if (prefs == null) return null;
|
||||
final long[] temp = new long[prefs.length];
|
||||
int i = 0;
|
||||
for (final AccountPreferences pref : prefs) {
|
||||
if (pref.isAutoRefreshEnabled() && filter.isRefreshable(pref)) {
|
||||
temp[i++] = pref.getAccountId();
|
||||
}
|
||||
}
|
||||
final long[] result = new long[i];
|
||||
System.arraycopy(temp, 0, result, 0, i);
|
||||
return result;
|
||||
}
|
||||
|
||||
private long[] getRefreshableIds(final AccountPreferences[] prefs, final RefreshableAccountFilter filter) {
|
||||
if (prefs == null) return null;
|
||||
final long[] temp = new long[prefs.length];
|
||||
int i = 0;
|
||||
for (final AccountPreferences pref : prefs) {
|
||||
if (pref.isAutoRefreshEnabled() && filter.isRefreshable(pref)) {
|
||||
temp[i++] = pref.getAccountId();
|
||||
}
|
||||
}
|
||||
final long[] result = new long[i];
|
||||
System.arraycopy(temp, 0, result, 0, i);
|
||||
return result;
|
||||
}
|
||||
private long getRefreshInterval() {
|
||||
if (mPreferences == null) return 0;
|
||||
final int prefValue = parseInt(mPreferences.getString(KEY_REFRESH_INTERVAL, DEFAULT_REFRESH_INTERVAL));
|
||||
return Math.max(prefValue, 3) * 60 * 1000;
|
||||
}
|
||||
|
||||
private long getRefreshInterval() {
|
||||
if (mPreferences == null) return 0;
|
||||
final int prefValue = parseInt(mPreferences.getString(KEY_REFRESH_INTERVAL, DEFAULT_REFRESH_INTERVAL));
|
||||
return Math.max(prefValue, 3) * 60 * 1000;
|
||||
}
|
||||
private boolean isHomeTimelineRefreshing() {
|
||||
return mTwitterWrapper.isHomeTimelineRefreshing();
|
||||
}
|
||||
|
||||
private boolean isHomeTimelineRefreshing() {
|
||||
return mTwitterWrapper.isHomeTimelineRefreshing();
|
||||
}
|
||||
private boolean isLocalTrendsRefreshing() {
|
||||
return mTwitterWrapper.isLocalTrendsRefreshing();
|
||||
}
|
||||
|
||||
private boolean isLocalTrendsRefreshing() {
|
||||
return mTwitterWrapper.isLocalTrendsRefreshing();
|
||||
}
|
||||
private boolean isMentionsRefreshing() {
|
||||
return mTwitterWrapper.isMentionsTimelineRefreshing();
|
||||
}
|
||||
|
||||
private boolean isMentionsRefreshing() {
|
||||
return mTwitterWrapper.isMentionsTimelineRefreshing();
|
||||
}
|
||||
private boolean isReceivedDirectMessagesRefreshing() {
|
||||
return mTwitterWrapper.isReceivedDirectMessagesRefreshing();
|
||||
}
|
||||
|
||||
private boolean isReceivedDirectMessagesRefreshing() {
|
||||
return mTwitterWrapper.isReceivedDirectMessagesRefreshing();
|
||||
}
|
||||
private void rescheduleDirectMessagesRefreshing() {
|
||||
mAlarmManager.cancel(mPendingRefreshDirectMessagesIntent);
|
||||
final long refreshInterval = getRefreshInterval();
|
||||
if (refreshInterval > 0) {
|
||||
mAlarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + refreshInterval,
|
||||
refreshInterval, mPendingRefreshDirectMessagesIntent);
|
||||
}
|
||||
}
|
||||
|
||||
private void rescheduleDirectMessagesRefreshing() {
|
||||
mAlarmManager.cancel(mPendingRefreshDirectMessagesIntent);
|
||||
final long refreshInterval = getRefreshInterval();
|
||||
if (refreshInterval > 0) {
|
||||
mAlarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + refreshInterval,
|
||||
refreshInterval, mPendingRefreshDirectMessagesIntent);
|
||||
}
|
||||
}
|
||||
private void rescheduleHomeTimelineRefreshing() {
|
||||
mAlarmManager.cancel(mPendingRefreshHomeTimelineIntent);
|
||||
final long refreshInterval = getRefreshInterval();
|
||||
if (refreshInterval > 0) {
|
||||
mAlarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + refreshInterval,
|
||||
refreshInterval, mPendingRefreshHomeTimelineIntent);
|
||||
}
|
||||
}
|
||||
|
||||
private void rescheduleHomeTimelineRefreshing() {
|
||||
mAlarmManager.cancel(mPendingRefreshHomeTimelineIntent);
|
||||
final long refreshInterval = getRefreshInterval();
|
||||
if (refreshInterval > 0) {
|
||||
mAlarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + refreshInterval,
|
||||
refreshInterval, mPendingRefreshHomeTimelineIntent);
|
||||
}
|
||||
}
|
||||
private void rescheduleMentionsRefreshing() {
|
||||
mAlarmManager.cancel(mPendingRefreshMentionsIntent);
|
||||
final long refreshInterval = getRefreshInterval();
|
||||
if (refreshInterval > 0) {
|
||||
mAlarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + refreshInterval,
|
||||
refreshInterval, mPendingRefreshMentionsIntent);
|
||||
}
|
||||
}
|
||||
|
||||
private void rescheduleMentionsRefreshing() {
|
||||
mAlarmManager.cancel(mPendingRefreshMentionsIntent);
|
||||
final long refreshInterval = getRefreshInterval();
|
||||
if (refreshInterval > 0) {
|
||||
mAlarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + refreshInterval,
|
||||
refreshInterval, mPendingRefreshMentionsIntent);
|
||||
}
|
||||
}
|
||||
private void rescheduleTrendsRefreshing() {
|
||||
mAlarmManager.cancel(mPendingRefreshTrendsIntent);
|
||||
final long refreshInterval = getRefreshInterval();
|
||||
if (refreshInterval > 0) {
|
||||
mAlarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + refreshInterval,
|
||||
refreshInterval, mPendingRefreshTrendsIntent);
|
||||
}
|
||||
}
|
||||
|
||||
private void rescheduleTrendsRefreshing() {
|
||||
mAlarmManager.cancel(mPendingRefreshTrendsIntent);
|
||||
final long refreshInterval = getRefreshInterval();
|
||||
if (refreshInterval > 0) {
|
||||
mAlarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + refreshInterval,
|
||||
refreshInterval, mPendingRefreshTrendsIntent);
|
||||
}
|
||||
}
|
||||
private boolean startAutoRefresh() {
|
||||
stopAutoRefresh();
|
||||
final long refreshInterval = getRefreshInterval();
|
||||
if (refreshInterval <= 0) return false;
|
||||
rescheduleHomeTimelineRefreshing();
|
||||
rescheduleMentionsRefreshing();
|
||||
rescheduleDirectMessagesRefreshing();
|
||||
rescheduleTrendsRefreshing();
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean startAutoRefresh() {
|
||||
stopAutoRefresh();
|
||||
final long refreshInterval = getRefreshInterval();
|
||||
if (refreshInterval <= 0) return false;
|
||||
rescheduleHomeTimelineRefreshing();
|
||||
rescheduleMentionsRefreshing();
|
||||
rescheduleDirectMessagesRefreshing();
|
||||
rescheduleTrendsRefreshing();
|
||||
return true;
|
||||
}
|
||||
private void stopAutoRefresh() {
|
||||
mAlarmManager.cancel(mPendingRefreshHomeTimelineIntent);
|
||||
mAlarmManager.cancel(mPendingRefreshMentionsIntent);
|
||||
mAlarmManager.cancel(mPendingRefreshDirectMessagesIntent);
|
||||
mAlarmManager.cancel(mPendingRefreshTrendsIntent);
|
||||
}
|
||||
|
||||
private void stopAutoRefresh() {
|
||||
mAlarmManager.cancel(mPendingRefreshHomeTimelineIntent);
|
||||
mAlarmManager.cancel(mPendingRefreshMentionsIntent);
|
||||
mAlarmManager.cancel(mPendingRefreshDirectMessagesIntent);
|
||||
mAlarmManager.cancel(mPendingRefreshTrendsIntent);
|
||||
}
|
||||
private static class HomeRefreshableFilter implements RefreshableAccountFilter {
|
||||
@Override
|
||||
public boolean isRefreshable(final AccountPreferences pref) {
|
||||
return pref.isAutoRefreshHomeTimelineEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
private static class HomeRefreshableFilter implements RefreshableAccountFilter {
|
||||
@Override
|
||||
public boolean isRefreshable(final AccountPreferences pref) {
|
||||
return pref.isAutoRefreshHomeTimelineEnabled();
|
||||
}
|
||||
}
|
||||
private static class MentionsRefreshableFilter implements RefreshableAccountFilter {
|
||||
|
||||
private static class MentionsRefreshableFilter implements RefreshableAccountFilter {
|
||||
@Override
|
||||
public boolean isRefreshable(final AccountPreferences pref) {
|
||||
return pref.isAutoRefreshMentionsEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRefreshable(final AccountPreferences pref) {
|
||||
return pref.isAutoRefreshMentionsEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
private static class MessagesRefreshableFilter implements RefreshableAccountFilter {
|
||||
@Override
|
||||
public boolean isRefreshable(final AccountPreferences pref) {
|
||||
return pref.isAutoRefreshDirectMessagesEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
private static class MessagesRefreshableFilter implements RefreshableAccountFilter {
|
||||
@Override
|
||||
public boolean isRefreshable(final AccountPreferences pref) {
|
||||
return pref.isAutoRefreshDirectMessagesEnabled();
|
||||
}
|
||||
}
|
||||
private static interface RefreshableAccountFilter {
|
||||
boolean isRefreshable(AccountPreferences pref);
|
||||
}
|
||||
|
||||
private static interface RefreshableAccountFilter {
|
||||
boolean isRefreshable(AccountPreferences pref);
|
||||
}
|
||||
|
||||
private static class TrendsRefreshableFilter implements RefreshableAccountFilter {
|
||||
@Override
|
||||
public boolean isRefreshable(final AccountPreferences pref) {
|
||||
return pref.isAutoRefreshTrendsEnabled();
|
||||
}
|
||||
}
|
||||
private static class TrendsRefreshableFilter implements RefreshableAccountFilter {
|
||||
@Override
|
||||
public boolean isRefreshable(final AccountPreferences pref) {
|
||||
return pref.isAutoRefreshTrendsEnabled();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ package org.mariotaku.twidere.util;
|
|||
import android.text.TextUtils;
|
||||
import android.util.Xml;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.mariotaku.twidere.Constants;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
@ -29,19 +30,28 @@ import org.xmlpull.v1.XmlPullParserFactory;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import twitter4j.Twitter;
|
||||
import twitter4j.TwitterException;
|
||||
import twitter4j.auth.AccessToken;
|
||||
import twitter4j.auth.RequestToken;
|
||||
import twitter4j.conf.Configuration;
|
||||
import twitter4j.http.HeaderMap;
|
||||
import twitter4j.http.HttpClientWrapper;
|
||||
import twitter4j.http.HttpParameter;
|
||||
import twitter4j.http.HttpResponse;
|
||||
|
||||
import static android.text.TextUtils.isEmpty;
|
||||
|
||||
public class OAuthPasswordAuthenticator implements Constants {
|
||||
|
||||
private static final String INPUT_AUTHENTICITY_TOKEN = "authenticity_token";
|
||||
private static final String INPUT_REDIRECT_AFTER_LOGIN = "redirect_after_login";
|
||||
|
||||
private final Twitter twitter;
|
||||
private final HttpClientWrapper client;
|
||||
|
||||
|
@ -62,18 +72,27 @@ public class OAuthPasswordAuthenticator implements Constants {
|
|||
try {
|
||||
final String oauthToken = requestToken.getToken();
|
||||
final String authorizationUrl = requestToken.getAuthorizationURL();
|
||||
final String authenticityToken = readAuthenticityTokenFromHtml(client.get(authorizationUrl,
|
||||
authorizationUrl, null, null).asReader());
|
||||
if (authenticityToken == null) throw new AuthenticityTokenException();
|
||||
final HashMap<String, String> inputMap = new HashMap<>();
|
||||
final HttpResponse authorizePage = client.get(authorizationUrl, authorizationUrl, null, null);
|
||||
final List<String> cookieHeaders = authorizePage.getResponseHeaders("Set-Cookie");
|
||||
readInputFromHtml(authorizePage.asReader(),
|
||||
inputMap, INPUT_AUTHENTICITY_TOKEN, INPUT_REDIRECT_AFTER_LOGIN);
|
||||
final Configuration conf = twitter.getConfiguration();
|
||||
final HttpParameter[] params = new HttpParameter[4];
|
||||
params[0] = new HttpParameter("authenticity_token", authenticityToken);
|
||||
params[1] = new HttpParameter("oauth_token", oauthToken);
|
||||
params[2] = new HttpParameter("session[username_or_email]", username);
|
||||
params[3] = new HttpParameter("session[password]", password);
|
||||
final List<HttpParameter> params = new ArrayList<>();
|
||||
params.add(new HttpParameter("oauth_token", oauthToken));
|
||||
params.add(new HttpParameter(INPUT_AUTHENTICITY_TOKEN, inputMap.get(INPUT_AUTHENTICITY_TOKEN)));
|
||||
if (inputMap.containsKey(INPUT_REDIRECT_AFTER_LOGIN)) {
|
||||
params.add(new HttpParameter(INPUT_REDIRECT_AFTER_LOGIN, inputMap.get(INPUT_REDIRECT_AFTER_LOGIN)));
|
||||
}
|
||||
params.add(new HttpParameter("session[username_or_email]", username));
|
||||
params.add(new HttpParameter("session[password]", password));
|
||||
final HeaderMap requestHeaders = new HeaderMap();
|
||||
requestHeaders.addHeader("Origin", "https://twitter.com");
|
||||
requestHeaders.addHeader("Referer", "https://twitter.com/oauth/authorize?oauth_token=" + requestToken.getToken());
|
||||
requestHeaders.put("Cookie", cookieHeaders);
|
||||
final String oAuthAuthorizationUrl = conf.getOAuthAuthorizationURL();
|
||||
final String oauthPin = readOAuthPINFromHtml(client.post(oAuthAuthorizationUrl, oAuthAuthorizationUrl,
|
||||
params).asReader());
|
||||
params.toArray(new HttpParameter[params.size()]), requestHeaders).asReader());
|
||||
if (isEmpty(oauthPin)) throw new WrongUserPassException();
|
||||
return twitter.getOAuthAccessToken(requestToken, oauthPin);
|
||||
} catch (final IOException | TwitterException | NullPointerException | XmlPullParserException e) {
|
||||
|
@ -81,7 +100,7 @@ public class OAuthPasswordAuthenticator implements Constants {
|
|||
}
|
||||
}
|
||||
|
||||
public static String readAuthenticityTokenFromHtml(final Reader in) throws IOException, XmlPullParserException {
|
||||
public static void readInputFromHtml(final Reader in, Map<String, String> map, String... desiredNames) throws IOException, XmlPullParserException {
|
||||
final XmlPullParserFactory f = XmlPullParserFactory.newInstance();
|
||||
final XmlPullParser parser = f.newPullParser();
|
||||
parser.setFeature(Xml.FEATURE_RELAXED, true);
|
||||
|
@ -90,12 +109,14 @@ public class OAuthPasswordAuthenticator implements Constants {
|
|||
final String tag = parser.getName();
|
||||
switch (parser.getEventType()) {
|
||||
case XmlPullParser.START_TAG: {
|
||||
if ("input".equals(tag) && "authenticity_token".equals(parser.getAttributeValue(null, "name")))
|
||||
return parser.getAttributeValue(null, "value");
|
||||
final String name = parser.getAttributeValue(null, "name");
|
||||
if ("input".equalsIgnoreCase(tag) && ArrayUtils.contains(desiredNames, name)) {
|
||||
map.put(name, parser.getAttributeValue(null, "value"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String readOAuthPINFromHtml(final Reader in) throws XmlPullParserException, IOException {
|
||||
|
|
|
@ -83,6 +83,10 @@ public class ReadStateManager implements Constants {
|
|||
mPreferences.registerOnSharedPreferenceChangeListener(listener);
|
||||
}
|
||||
|
||||
public boolean setPosition(String key, String keyId, long position) {
|
||||
return setPosition(key, keyId, position, false);
|
||||
}
|
||||
|
||||
public void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
|
||||
mPreferences.unregisterOnSharedPreferenceChangeListener(listener);
|
||||
}
|
||||
|
|
|
@ -142,8 +142,8 @@ import org.mariotaku.twidere.app.TwidereApplication;
|
|||
import org.mariotaku.twidere.fragment.iface.IBaseFragment.SystemWindowsInsetsCallback;
|
||||
import org.mariotaku.twidere.fragment.support.AddStatusFilterDialogFragment;
|
||||
import org.mariotaku.twidere.fragment.support.DestroyStatusDialogFragment;
|
||||
import org.mariotaku.twidere.fragment.support.MessagesConversationFragment;
|
||||
import org.mariotaku.twidere.fragment.support.IncomingFriendshipsFragment;
|
||||
import org.mariotaku.twidere.fragment.support.MessagesConversationFragment;
|
||||
import org.mariotaku.twidere.fragment.support.MutesUsersListFragment;
|
||||
import org.mariotaku.twidere.fragment.support.SavedSearchesListFragment;
|
||||
import org.mariotaku.twidere.fragment.support.SearchFragment;
|
||||
|
@ -1078,8 +1078,8 @@ public final class Utils implements Constants, TwitterConstants {
|
|||
public static Intent createStatusShareIntent(final Context context, final ParcelableStatus status) {
|
||||
final Intent intent = new Intent(Intent.ACTION_SEND);
|
||||
intent.setType("text/plain");
|
||||
intent.putExtra(Intent.EXTRA_SUBJECT, getStatusShareText(context, status));
|
||||
intent.putExtra(Intent.EXTRA_TEXT, getStatusShareSubject(context, status));
|
||||
intent.putExtra(Intent.EXTRA_SUBJECT, getStatusShareSubject(context, status));
|
||||
intent.putExtra(Intent.EXTRA_TEXT, getStatusShareText(context, status));
|
||||
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
return intent;
|
||||
}
|
||||
|
@ -2331,6 +2331,7 @@ public final class Utils implements Constants, TwitterConstants {
|
|||
cb.setRestBaseURL(getApiUrl(account.api_url_format, "api", versionSuffix));
|
||||
cb.setOAuthBaseURL(getApiUrl(account.api_url_format, "api", "/oauth/"));
|
||||
cb.setUploadBaseURL(getApiUrl(account.api_url_format, "upload", versionSuffix));
|
||||
cb.setOAuthAuthorizationURL(getApiUrl(account.api_url_format, null, null));
|
||||
if (!account.same_oauth_signing_url) {
|
||||
cb.setSigningRestBaseURL(DEFAULT_SIGNING_REST_BASE_URL);
|
||||
cb.setSigningOAuthBaseURL(DEFAULT_SIGNING_OAUTH_BASE_URL);
|
||||
|
@ -2393,6 +2394,7 @@ public final class Utils implements Constants, TwitterConstants {
|
|||
cb.setRestBaseURL(getApiUrl(apiUrlFormat, "api", "/1.1/"));
|
||||
cb.setOAuthBaseURL(getApiUrl(apiUrlFormat, "api", "/oauth/"));
|
||||
cb.setUploadBaseURL(getApiUrl(apiUrlFormat, "upload", "/1.1/"));
|
||||
cb.setOAuthAuthorizationURL(getApiUrl(apiUrlFormat, null, null));
|
||||
if (!sameOAuthSigningUrl) {
|
||||
cb.setSigningRestBaseURL(DEFAULT_SIGNING_REST_BASE_URL);
|
||||
cb.setSigningOAuthBaseURL(DEFAULT_SIGNING_OAUTH_BASE_URL);
|
||||
|
@ -2521,6 +2523,7 @@ public final class Utils implements Constants, TwitterConstants {
|
|||
cb.setRestBaseURL(getApiUrl(apiUrlFormat, "api", versionSuffix));
|
||||
cb.setOAuthBaseURL(getApiUrl(apiUrlFormat, "api", "/oauth/"));
|
||||
cb.setUploadBaseURL(getApiUrl(apiUrlFormat, "upload", versionSuffix));
|
||||
cb.setOAuthAuthorizationURL(getApiUrl(apiUrlFormat, null, null));
|
||||
if (!sameOAuthSigningUrl) {
|
||||
cb.setSigningRestBaseURL(DEFAULT_SIGNING_REST_BASE_URL);
|
||||
cb.setSigningOAuthBaseURL(DEFAULT_SIGNING_OAUTH_BASE_URL);
|
||||
|
|
|
@ -52,7 +52,6 @@ import java.util.concurrent.TimeUnit;
|
|||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import javax.net.SocketFactory;
|
||||
import javax.net.ssl.TrustManager;
|
||||
|
||||
import okio.BufferedSink;
|
||||
import twitter4j.TwitterException;
|
||||
|
@ -86,8 +85,11 @@ public class OkHttpClientImpl implements HttpClient, TwidereConstants {
|
|||
@Override
|
||||
public HttpResponse request(HttpRequest req) throws TwitterException {
|
||||
final Builder builder = new Builder();
|
||||
for (Entry<String, String> headerEntry : req.getRequestHeaders().entrySet()) {
|
||||
builder.header(headerEntry.getKey(), headerEntry.getValue());
|
||||
for (Entry<String, List<String>> headerEntry : req.getRequestHeaders().entrySet()) {
|
||||
final String name = headerEntry.getKey();
|
||||
for (String value : headerEntry.getValue()) {
|
||||
builder.addHeader(name, value);
|
||||
}
|
||||
}
|
||||
final Authorization authorization = req.getAuthorization();
|
||||
if (authorization != null) {
|
||||
|
@ -280,5 +282,10 @@ public class OkHttpClientImpl implements HttpClient, TwidereConstants {
|
|||
}
|
||||
return maps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getResponseHeaders(String name) {
|
||||
return response.headers(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
android:layout_centerInParent="true"
|
||||
android:minWidth="48dp">
|
||||
|
||||
<Button
|
||||
<android.support.v7.internal.widget.TintButton
|
||||
android:id="@+id/follow"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ 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/>.
|
||||
-->
|
||||
|
||||
|
||||
<android.support.v7.widget.CardView
|
||||
android:id="@+id/card"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/element_spacing_normal"
|
||||
app:cardBackgroundColor="?cardItemBackgroundColor"
|
||||
app:cardCornerRadius="@dimen/corner_radius_card"
|
||||
app:cardElevation="@dimen/elevation_card">
|
||||
|
||||
<include layout="@layout/layout_user_details_common"/>
|
||||
|
||||
</android.support.v7.widget.CardView>
|
|
@ -1,252 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ 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/>.
|
||||
-->
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/card_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:splitMotionEvents="false">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/description_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/element_spacing_small">
|
||||
|
||||
<org.mariotaku.twidere.view.themed.ThemedTextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/element_spacing_small"
|
||||
android:singleLine="true"
|
||||
android:text="@string/description"
|
||||
android:textAllCaps="true"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textStyle="bold"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<org.mariotaku.twidere.view.HandleSpanClickTextView
|
||||
android:id="@+id/description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="@dimen/element_spacing_small"
|
||||
android:paddingRight="@dimen/element_spacing_small"
|
||||
android:textAppearance="?android:textAppearanceSmall"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
tools:text="Line 1\nLine 2\nLine 3"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/location_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/element_spacing_small">
|
||||
|
||||
<org.mariotaku.twidere.view.ActionIconView
|
||||
android:layout_width="@dimen/element_size_small"
|
||||
android:layout_height="@dimen/element_size_small"
|
||||
android:color="?android:textColorPrimary"
|
||||
android:src="@drawable/ic_action_location"/>
|
||||
|
||||
<org.mariotaku.twidere.view.themed.ThemedTextView
|
||||
android:id="@+id/location"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="@dimen/element_spacing_small"
|
||||
android:paddingRight="@dimen/element_spacing_small"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:textAppearanceSmall"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
tools:text="Zhengzhou China"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/url_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/element_spacing_small">
|
||||
|
||||
<org.mariotaku.twidere.view.ActionIconView
|
||||
android:layout_width="@dimen/element_size_small"
|
||||
android:layout_height="@dimen/element_size_small"
|
||||
android:color="?android:textColorPrimary"
|
||||
android:src="@drawable/ic_action_link"/>
|
||||
|
||||
<org.mariotaku.twidere.view.HandleSpanClickTextView
|
||||
android:id="@+id/url"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:autoLink="web"
|
||||
android:paddingLeft="@dimen/element_spacing_small"
|
||||
android:paddingRight="@dimen/element_spacing_small"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:textAppearanceSmall"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
tools:text="mariotaku.org"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/created_at_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/element_spacing_small">
|
||||
|
||||
<org.mariotaku.twidere.view.ActionIconView
|
||||
android:layout_width="@dimen/element_size_small"
|
||||
android:layout_height="@dimen/element_size_small"
|
||||
android:color="?android:textColorPrimary"
|
||||
android:src="@drawable/ic_action_portal_cake"/>
|
||||
|
||||
<org.mariotaku.twidere.view.themed.ThemedTextView
|
||||
android:id="@+id/created_at"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="@dimen/element_spacing_small"
|
||||
android:paddingRight="@dimen/element_spacing_small"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:textAppearanceSmall"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
tools:text="July 17, 2009 18:35 (20 tweets per day)"/>
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0.2dp"
|
||||
android:background="?android:dividerVertical"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/action_button_size"
|
||||
android:baselineAligned="false"
|
||||
android:divider="?android:dividerHorizontal"
|
||||
android:orientation="horizontal"
|
||||
android:showDividers="middle"
|
||||
android:splitMotionEvents="false">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/followers_container"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="?android:selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/element_spacing_small">
|
||||
|
||||
<org.mariotaku.twidere.view.themed.ThemedTextView
|
||||
android:id="@+id/followers_count"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:textAppearanceMedium"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
tools:text="255"/>
|
||||
|
||||
<org.mariotaku.twidere.view.themed.ThemedTextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:text="@string/followers"
|
||||
android:textAppearance="?android:textAppearanceSmall"
|
||||
android:textColor="?android:textColorSecondary"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/friends_container"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="?android:selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/element_spacing_small">
|
||||
|
||||
<org.mariotaku.twidere.view.themed.ThemedTextView
|
||||
android:id="@+id/friends_count"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:textAppearanceMedium"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
tools:text="255"/>
|
||||
|
||||
<org.mariotaku.twidere.view.themed.ThemedTextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:text="@string/following"
|
||||
android:textAppearance="?android:textAppearanceSmall"
|
||||
android:textColor="?android:textColorSecondary"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/listed_container"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="?android:selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/element_spacing_small">
|
||||
|
||||
<org.mariotaku.twidere.view.themed.ThemedTextView
|
||||
android:id="@+id/listed_count"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:textAppearanceMedium"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
tools:text="255"/>
|
||||
|
||||
<org.mariotaku.twidere.view.themed.ThemedTextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:text="@string/listed"
|
||||
android:textAppearance="?android:textAppearanceSmall"
|
||||
android:textColor="?android:textColorSecondary"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<include layout="@layout/layout_content_fragment_common"/>
|
||||
|
||||
</merge>
|
|
@ -1,35 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ 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/>.
|
||||
-->
|
||||
|
||||
|
||||
<android.support.v7.widget.CardView
|
||||
android:id="@+id/card"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/element_spacing_normal"
|
||||
app:cardBackgroundColor="?cardItemBackgroundColor"
|
||||
app:cardCornerRadius="0dp"
|
||||
app:cardElevation="0dp">
|
||||
|
||||
<include layout="@layout/layout_user_details_common"/>
|
||||
|
||||
</android.support.v7.widget.CardView>
|
|
@ -1,5 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
>
|
||||
|
||||
<item
|
||||
android:id="@id/reply"
|
||||
|
|
|
@ -733,6 +733,7 @@
|
|||
<string name="user_type_verified">Verified</string>
|
||||
<string name="user_type_protected">Protected</string>
|
||||
<string name="tweet_hashtag">Tweet #<xliff:g id="text">%1$s</xliff:g></string>
|
||||
<string name="share_status">Share tweet</string>
|
||||
|
||||
<!-- 'Tweet' here is a verb -->
|
||||
<string name="tweet_from_name">Tweet from <xliff:g id="text">%1$s</xliff:g></string>
|
||||
|
|
Loading…
Reference in New Issue