refactoring
make streaming extension work again
@ -1,10 +1,16 @@
|
||||
include ':twidere'
|
||||
include ':twidere.component.twitter4j'
|
||||
include ':twidere.component.twitter4j.streaming'
|
||||
include ':twidere.component.common'
|
||||
include ':twidere.library.extension'
|
||||
include ':twidere.component.jsonserializer'
|
||||
include ':twidere.component.querybuilder'
|
||||
include ':twidere.wear'
|
||||
include ':twidere.donate.nyanwp'
|
||||
include ':twidere.donate.nyanwp.wear'
|
||||
include ':twidere.component.nyan'
|
||||
include ':twidere.component.viewer.media'
|
||||
//include ':twidere.extension.streaming'
|
||||
include ':twidere.extension.streaming'
|
||||
include ':SlidingMenu', ':DragSortListView', ':MenuComponent', ':RefreshNow', ':PullToRefresh', ':MessageBubbleView'
|
||||
|
||||
project(':SlidingMenu').projectDir = file('libraries/SlidingMenu/library')
|
||||
|
62
signing.gradle
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
|
||||
signingConfigs {
|
||||
debug {
|
||||
File signingPropFile = rootProject.file('signing.properties')
|
||||
if (signingPropFile.exists()) {
|
||||
Properties signingProp = new Properties()
|
||||
signingProp.load(signingPropFile.newDataInputStream())
|
||||
storeFile file(signingProp.get("twidere.debug.storeFile"))
|
||||
storePassword signingProp.get("twidere.debug.storePassword")
|
||||
keyAlias signingProp.get("twidere.debug.keyAlias")
|
||||
keyPassword signingProp.get("twidere.debug.keyPassword")
|
||||
}
|
||||
}
|
||||
release {
|
||||
File signingPropFile = rootProject.file('signing.properties')
|
||||
if (signingPropFile.exists()) {
|
||||
Properties signingProp = new Properties()
|
||||
signingProp.load(signingPropFile.newDataInputStream())
|
||||
storeFile file(signingProp.get("twidere.release.storeFile"))
|
||||
storePassword signingProp.get("twidere.release.storePassword")
|
||||
keyAlias signingProp.get("twidere.release.keyAlias")
|
||||
keyPassword signingProp.get("twidere.release.keyPassword")
|
||||
}
|
||||
}
|
||||
}
|
||||
buildTypes {
|
||||
debug {
|
||||
File signingPropFile = rootProject.file('signing.properties')
|
||||
if (signingPropFile.exists()) {
|
||||
signingConfig signingConfigs.debug
|
||||
}
|
||||
}
|
||||
release {
|
||||
File signingPropFile = rootProject.file('signing.properties')
|
||||
if (signingPropFile.exists()) {
|
||||
signingConfig signingConfigs.release
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
1
twidere.component.common/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/build
|
47
twidere.component.common/build.gradle
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 21
|
||||
buildToolsVersion "21.1.2"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 21
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile 'com.android.support:support-annotations:21.0.3'
|
||||
compile 'org.apache.commons:commons-lang3:3.3.2'
|
||||
compile project(':twidere.component.jsonserializer')
|
||||
compile project(':twidere.component.querybuilder')
|
||||
compile project(':twidere.component.twitter4j')
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
}
|
17
twidere.component.common/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in /Users/mariotaku/Tools/android-sdk/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.common;
|
||||
|
||||
import android.app.Application;
|
||||
import android.test.ApplicationTestCase;
|
||||
|
||||
/**
|
||||
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
|
||||
*/
|
||||
public class ApplicationTest extends ApplicationTestCase<Application> {
|
||||
public ApplicationTest() {
|
||||
super(Application.class);
|
||||
}
|
||||
}
|
20
twidere.component.common/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<!--
|
||||
~ 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/>.
|
||||
-->
|
||||
|
||||
<manifest package="org.mariotaku.twidere.common"/>
|
@ -19,10 +19,9 @@
|
||||
|
||||
package org.mariotaku.twidere.constant;
|
||||
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.TwidereConstants;
|
||||
import org.mariotaku.twidere.annotation.Preference;
|
||||
import org.mariotaku.twidere.provider.TweetStore.Accounts;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
|
||||
|
||||
import static org.mariotaku.twidere.annotation.Preference.Type.BOOLEAN;
|
||||
import static org.mariotaku.twidere.annotation.Preference.Type.INT;
|
||||
@ -134,7 +133,7 @@ public interface SharedPreferenceConstants {
|
||||
public static final String KEY_DATABASE_ITEM_LIMIT = "database_item_limit";
|
||||
@Preference(type = INT, hasDefault = true, defaultInt = DEFAULT_LOAD_ITEM_LIMIT)
|
||||
public static final String KEY_LOAD_ITEM_LIMIT = "load_item_limit";
|
||||
@Preference(type = INT, hasDefault = true, defaultResource = R.integer.default_text_size)
|
||||
@Preference(type = INT, hasDefault = true, defaultInt = 15)
|
||||
public static final String KEY_TEXT_SIZE = "text_size_int";
|
||||
@Preference(type = STRING, hasDefault = true, defaultString = DEFAULT_THEME)
|
||||
public static final String KEY_THEME = "theme";
|
@ -26,8 +26,8 @@ import android.text.TextUtils;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.mariotaku.twidere.provider.TweetStore.Drafts;
|
||||
import org.mariotaku.twidere.util.ArrayUtils;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Drafts;
|
||||
import org.mariotaku.twidere.util.TwidereArrayUtils;
|
||||
|
||||
public class DraftItem implements Parcelable {
|
||||
|
||||
@ -56,7 +56,7 @@ public class DraftItem implements Parcelable {
|
||||
_id = cursor.getLong(indices._id);
|
||||
text = cursor.getString(indices.text);
|
||||
media = ParcelableMediaUpdate.fromJSONString(cursor.getString(indices.media));
|
||||
account_ids = ArrayUtils.parseLongArray(cursor.getString(indices.account_ids), ',');
|
||||
account_ids = TwidereArrayUtils.parseLongArray(cursor.getString(indices.account_ids), ',');
|
||||
in_reply_to_status_id = cursor.getLong(indices.in_reply_to_status_id);
|
||||
is_possibly_sensitive = cursor.getShort(indices.is_possibly_sensitive) == 1;
|
||||
location = new ParcelableLocation(cursor.getString(indices.location));
|
@ -29,16 +29,14 @@ import android.support.annotation.NonNull;
|
||||
import org.mariotaku.querybuilder.Columns.Column;
|
||||
import org.mariotaku.querybuilder.Expression;
|
||||
import org.mariotaku.querybuilder.RawItemArray;
|
||||
import org.mariotaku.twidere.provider.TweetStore.Accounts;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
|
||||
import org.mariotaku.twidere.util.TwitterContentUtils;
|
||||
import org.mariotaku.twidere.util.content.ContentResolverUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.mariotaku.twidere.util.Utils.isOfficialConsumerKeySecret;
|
||||
import static org.mariotaku.twidere.util.Utils.shouldForceUsingPrivateAPIs;
|
||||
|
||||
public class ParcelableAccount implements Parcelable {
|
||||
|
||||
public static final Parcelable.Creator<ParcelableAccount> CREATOR = new Parcelable.Creator<ParcelableAccount>() {
|
||||
@ -187,8 +185,7 @@ public class ParcelableAccount implements Parcelable {
|
||||
} else {
|
||||
final String consumerKey = cur.getString(indices.consumer_key);
|
||||
final String consumerSecret = cur.getString(indices.consumer_secret);
|
||||
if (shouldForceUsingPrivateAPIs(context)
|
||||
|| isOfficialConsumerKeySecret(context, consumerKey, consumerSecret)) {
|
||||
if (TwitterContentUtils.isOfficialKey(context, consumerKey, consumerSecret)) {
|
||||
accounts.add(new ParcelableAccount(cur, indices));
|
||||
}
|
||||
}
|
||||
@ -294,8 +291,7 @@ public class ParcelableAccount implements Parcelable {
|
||||
} else {
|
||||
final String consumerKey = cur.getString(indices.consumer_key);
|
||||
final String consumerSecret = cur.getString(indices.consumer_secret);
|
||||
if (shouldForceUsingPrivateAPIs(context)
|
||||
|| isOfficialConsumerKeySecret(context, consumerKey, consumerSecret)) {
|
||||
if (TwitterContentUtils.isOfficialKey(context, consumerKey, consumerSecret)) {
|
||||
accounts.add(new ParcelableCredentials(cur, indices));
|
||||
}
|
||||
}
|
||||
@ -305,14 +301,6 @@ public class ParcelableAccount implements Parcelable {
|
||||
return accounts;
|
||||
}
|
||||
|
||||
public static boolean isOfficialCredentials(final Context context, final ParcelableCredentials account) {
|
||||
if (account == null) return false;
|
||||
final boolean isOAuth = account.auth_type == Accounts.AUTH_TYPE_OAUTH
|
||||
|| account.auth_type == Accounts.AUTH_TYPE_XAUTH;
|
||||
final String consumerKey = account.consumer_key, consumerSecret = account.consumer_secret;
|
||||
return isOAuth && isOfficialConsumerKeySecret(context, consumerKey, consumerSecret);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
super.writeToParcel(out, flags);
|
@ -0,0 +1,262 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages;
|
||||
import org.mariotaku.twidere.util.TwitterContentUtils;
|
||||
import org.mariotaku.twidere.util.ParseUtils;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
|
||||
import twitter4j.DirectMessage;
|
||||
import twitter4j.User;
|
||||
|
||||
import static org.mariotaku.twidere.util.HtmlEscapeHelper.toPlainText;
|
||||
import static org.mariotaku.twidere.util.content.ContentValuesUtils.getAsBoolean;
|
||||
import static org.mariotaku.twidere.util.content.ContentValuesUtils.getAsLong;
|
||||
|
||||
public class ParcelableDirectMessage implements Parcelable, Comparable<ParcelableDirectMessage> {
|
||||
|
||||
public static final Parcelable.Creator<ParcelableDirectMessage> CREATOR = new Parcelable.Creator<ParcelableDirectMessage>() {
|
||||
@Override
|
||||
public ParcelableDirectMessage createFromParcel(final Parcel in) {
|
||||
return new ParcelableDirectMessage(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParcelableDirectMessage[] newArray(final int size) {
|
||||
return new ParcelableDirectMessage[size];
|
||||
}
|
||||
};
|
||||
public static final Comparator<ParcelableDirectMessage> MESSAGE_ID_COMPARATOR = new Comparator<ParcelableDirectMessage>() {
|
||||
|
||||
@Override
|
||||
public int compare(final ParcelableDirectMessage object1, final ParcelableDirectMessage object2) {
|
||||
final long diff = object2.id - object1.id;
|
||||
if (diff > Integer.MAX_VALUE) return Integer.MAX_VALUE;
|
||||
if (diff < Integer.MIN_VALUE) return Integer.MIN_VALUE;
|
||||
return (int) diff;
|
||||
}
|
||||
};
|
||||
|
||||
public final long account_id, id, timestamp;
|
||||
|
||||
public final long sender_id, recipient_id;
|
||||
|
||||
public final boolean is_outgoing;
|
||||
|
||||
public final String text_html, text_plain, text_unescaped;
|
||||
|
||||
public final String sender_name, recipient_name, sender_screen_name, recipient_screen_name;
|
||||
|
||||
public final String sender_profile_image_url, recipient_profile_image_url;
|
||||
|
||||
public final String first_media;
|
||||
|
||||
public final ParcelableMedia[] media;
|
||||
|
||||
public ParcelableDirectMessage(final ContentValues values) {
|
||||
text_plain = values.getAsString(DirectMessages.TEXT_PLAIN);
|
||||
text_html = values.getAsString(DirectMessages.TEXT_HTML);
|
||||
text_unescaped = toPlainText(text_html);
|
||||
sender_screen_name = values.getAsString(DirectMessages.SENDER_SCREEN_NAME);
|
||||
sender_profile_image_url = values.getAsString(DirectMessages.SENDER_PROFILE_IMAGE_URL);
|
||||
sender_name = values.getAsString(DirectMessages.SENDER_NAME);
|
||||
sender_id = getAsLong(values, DirectMessages.SENDER_ID, -1);
|
||||
recipient_screen_name = values.getAsString(DirectMessages.RECIPIENT_SCREEN_NAME);
|
||||
recipient_profile_image_url = values.getAsString(DirectMessages.RECIPIENT_PROFILE_IMAGE_URL);
|
||||
recipient_name = values.getAsString(DirectMessages.RECIPIENT_NAME);
|
||||
recipient_id = getAsLong(values, DirectMessages.RECIPIENT_ID, -1);
|
||||
timestamp = getAsLong(values, DirectMessages.MESSAGE_TIMESTAMP, -1);
|
||||
id = getAsLong(values, DirectMessages.MESSAGE_ID, -1);
|
||||
is_outgoing = getAsBoolean(values, DirectMessages.IS_OUTGOING, false);
|
||||
account_id = getAsLong(values, DirectMessages.ACCOUNT_ID, -1);
|
||||
media = ParcelableMedia.fromJSONString(values.getAsString(DirectMessages.MEDIA));
|
||||
first_media = values.getAsString(DirectMessages.FIRST_MEDIA);
|
||||
}
|
||||
|
||||
public ParcelableDirectMessage(final Cursor c, final CursorIndices idx) {
|
||||
account_id = idx.account_id != -1 ? c.getLong(idx.account_id) : -1;
|
||||
is_outgoing = idx.is_outgoing != -1 ? c.getShort(idx.is_outgoing) == 1 : null;
|
||||
id = idx.message_id != -1 ? c.getLong(idx.message_id) : -1;
|
||||
timestamp = idx.message_timestamp != -1 ? c.getLong(idx.message_timestamp) : -1;
|
||||
sender_id = idx.sender_id != -1 ? c.getLong(idx.sender_id) : -1;
|
||||
recipient_id = idx.recipient_id != -1 ? c.getLong(idx.recipient_id) : -1;
|
||||
text_html = idx.text != -1 ? c.getString(idx.text) : null;
|
||||
text_plain = idx.text_plain != -1 ? c.getString(idx.text_plain) : null;
|
||||
text_unescaped = toPlainText(text_html);
|
||||
sender_name = idx.sender_name != -1 ? c.getString(idx.sender_name) : null;
|
||||
recipient_name = idx.recipient_name != -1 ? c.getString(idx.recipient_name) : null;
|
||||
sender_screen_name = idx.sender_screen_name != -1 ? c.getString(idx.sender_screen_name) : null;
|
||||
recipient_screen_name = idx.recipient_screen_name != -1 ? c.getString(idx.recipient_screen_name) : null;
|
||||
sender_profile_image_url = idx.sender_profile_image_url != -1 ? c.getString(idx.sender_profile_image_url)
|
||||
: null;
|
||||
recipient_profile_image_url = idx.recipient_profile_image_url != -1 ? c
|
||||
.getString(idx.recipient_profile_image_url) : null;
|
||||
media = ParcelableMedia.fromJSONString(idx.media != -1 ? c.getString(idx.media) : null);
|
||||
first_media = idx.first_media != -1 ? c.getString(idx.first_media) : null;
|
||||
}
|
||||
|
||||
public ParcelableDirectMessage(final DirectMessage message, final long account_id, final boolean is_outgoing) {
|
||||
this.account_id = account_id;
|
||||
this.is_outgoing = is_outgoing;
|
||||
final User sender = message.getSender(), recipient = message.getRecipient();
|
||||
final String sender_profile_image_url_string = sender != null ? ParseUtils.parseString(sender
|
||||
.getProfileImageUrlHttps()) : null;
|
||||
final String recipient_profile_image_url_string = recipient != null ? ParseUtils.parseString(recipient
|
||||
.getProfileImageUrlHttps()) : null;
|
||||
id = message.getId();
|
||||
timestamp = getTime(message.getCreatedAt());
|
||||
sender_id = sender != null ? sender.getId() : -1;
|
||||
recipient_id = recipient != null ? recipient.getId() : -1;
|
||||
text_html = TwitterContentUtils.formatDirectMessageText(message);
|
||||
text_plain = message.getText();
|
||||
sender_name = sender != null ? sender.getName() : null;
|
||||
recipient_name = recipient != null ? recipient.getName() : null;
|
||||
sender_screen_name = sender != null ? sender.getScreenName() : null;
|
||||
recipient_screen_name = recipient != null ? recipient.getScreenName() : null;
|
||||
sender_profile_image_url = sender_profile_image_url_string;
|
||||
recipient_profile_image_url = recipient_profile_image_url_string;
|
||||
text_unescaped = toPlainText(text_html);
|
||||
media = ParcelableMedia.fromEntities(message);
|
||||
first_media = media != null && media.length > 0 ? media[0].url : null;
|
||||
}
|
||||
|
||||
public ParcelableDirectMessage(final Parcel in) {
|
||||
account_id = in.readLong();
|
||||
id = in.readLong();
|
||||
timestamp = in.readLong();
|
||||
sender_id = in.readLong();
|
||||
recipient_id = in.readLong();
|
||||
is_outgoing = in.readInt() == 1;
|
||||
text_html = in.readString();
|
||||
text_plain = in.readString();
|
||||
sender_name = in.readString();
|
||||
recipient_name = in.readString();
|
||||
sender_screen_name = in.readString();
|
||||
recipient_screen_name = in.readString();
|
||||
sender_profile_image_url = in.readString();
|
||||
recipient_profile_image_url = in.readString();
|
||||
text_unescaped = in.readString();
|
||||
media = in.createTypedArray(ParcelableMedia.CREATOR);
|
||||
first_media = media != null && media.length > 0 ? media[0].url : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(final ParcelableDirectMessage another) {
|
||||
if (another == null) return 0;
|
||||
final long diff = another.id - id;
|
||||
if (diff > Integer.MAX_VALUE) return Integer.MAX_VALUE;
|
||||
if (diff < Integer.MIN_VALUE) return Integer.MIN_VALUE;
|
||||
return (int) diff;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (obj == null) return false;
|
||||
if (!(obj instanceof ParcelableDirectMessage)) return false;
|
||||
final ParcelableDirectMessage other = (ParcelableDirectMessage) obj;
|
||||
if (account_id != other.account_id) return false;
|
||||
if (id != other.id) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + (int) (account_id ^ account_id >>> 32);
|
||||
result = prime * result + (int) (id ^ id >>> 32);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ParcelableDirectMessage{account_id=" + account_id + ", id=" + id + ", timestamp=" + timestamp
|
||||
+ ", sender_id=" + sender_id + ", recipient_id=" + recipient_id + ", is_outgoing=" + is_outgoing
|
||||
+ ", text_html=" + text_html + ", text_plain=" + text_plain + ", text_unescaped=" + text_unescaped
|
||||
+ ", sender_name=" + sender_name + ", recipient_name=" + recipient_name + ", sender_screen_name="
|
||||
+ sender_screen_name + ", recipient_screen_name=" + recipient_screen_name
|
||||
+ ", sender_profile_image_url=" + sender_profile_image_url + ", recipient_profile_image_url="
|
||||
+ recipient_profile_image_url + "}";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(final Parcel out, final int flags) {
|
||||
out.writeLong(account_id);
|
||||
out.writeLong(id);
|
||||
out.writeLong(timestamp);
|
||||
out.writeLong(sender_id);
|
||||
out.writeLong(recipient_id);
|
||||
out.writeInt(is_outgoing ? 1 : 0);
|
||||
out.writeString(text_html);
|
||||
out.writeString(text_plain);
|
||||
out.writeString(sender_name);
|
||||
out.writeString(recipient_name);
|
||||
out.writeString(sender_screen_name);
|
||||
out.writeString(recipient_screen_name);
|
||||
out.writeString(sender_profile_image_url);
|
||||
out.writeString(recipient_profile_image_url);
|
||||
out.writeString(text_unescaped);
|
||||
out.writeTypedArray(media, flags);
|
||||
}
|
||||
|
||||
private static long getTime(final Date date) {
|
||||
return date != null ? date.getTime() : 0;
|
||||
}
|
||||
|
||||
public static class CursorIndices {
|
||||
|
||||
public final int account_id, message_id, message_timestamp, sender_name, sender_screen_name, text, text_plain,
|
||||
recipient_name, recipient_screen_name, sender_profile_image_url, is_outgoing,
|
||||
recipient_profile_image_url, sender_id, recipient_id, media, first_media;
|
||||
|
||||
public CursorIndices(final Cursor cursor) {
|
||||
account_id = cursor.getColumnIndex(DirectMessages.ACCOUNT_ID);
|
||||
message_id = cursor.getColumnIndex(DirectMessages.MESSAGE_ID);
|
||||
message_timestamp = cursor.getColumnIndex(DirectMessages.MESSAGE_TIMESTAMP);
|
||||
sender_id = cursor.getColumnIndex(DirectMessages.SENDER_ID);
|
||||
recipient_id = cursor.getColumnIndex(DirectMessages.RECIPIENT_ID);
|
||||
is_outgoing = cursor.getColumnIndex(DirectMessages.IS_OUTGOING);
|
||||
text = cursor.getColumnIndex(DirectMessages.TEXT_HTML);
|
||||
text_plain = cursor.getColumnIndex(DirectMessages.TEXT_PLAIN);
|
||||
sender_name = cursor.getColumnIndex(DirectMessages.SENDER_NAME);
|
||||
recipient_name = cursor.getColumnIndex(DirectMessages.RECIPIENT_NAME);
|
||||
sender_screen_name = cursor.getColumnIndex(DirectMessages.SENDER_SCREEN_NAME);
|
||||
recipient_screen_name = cursor.getColumnIndex(DirectMessages.RECIPIENT_SCREEN_NAME);
|
||||
sender_profile_image_url = cursor.getColumnIndex(DirectMessages.SENDER_PROFILE_IMAGE_URL);
|
||||
recipient_profile_image_url = cursor.getColumnIndex(DirectMessages.RECIPIENT_PROFILE_IMAGE_URL);
|
||||
media = cursor.getColumnIndex(DirectMessages.MEDIA);
|
||||
first_media = cursor.getColumnIndex(DirectMessages.FIRST_MEDIA);
|
||||
}
|
||||
}
|
||||
}
|
@ -22,6 +22,7 @@ import twitter4j.MediaEntity;
|
||||
import twitter4j.MediaEntity.Size;
|
||||
import twitter4j.URLEntity;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class ParcelableMedia implements Parcelable, JSONParcelable {
|
||||
|
||||
public static final int TYPE_IMAGE = 1;
|
@ -31,8 +31,11 @@ import org.json.JSONObject;
|
||||
import org.mariotaku.jsonserializer.JSONParcel;
|
||||
import org.mariotaku.jsonserializer.JSONParcelable;
|
||||
import org.mariotaku.jsonserializer.JSONSerializer;
|
||||
import org.mariotaku.twidere.provider.TweetStore.Statuses;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Statuses;
|
||||
import org.mariotaku.twidere.util.HtmlEscapeHelper;
|
||||
import org.mariotaku.twidere.util.TwitterContentUtils;
|
||||
import org.mariotaku.twidere.util.ParseUtils;
|
||||
import org.mariotaku.twidere.util.content.ContentValuesUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
@ -46,13 +49,7 @@ import twitter4j.CardEntity.UserValue;
|
||||
import twitter4j.Status;
|
||||
import twitter4j.User;
|
||||
|
||||
import static org.mariotaku.twidere.util.HtmlEscapeHelper.toPlainText;
|
||||
import static org.mariotaku.twidere.util.Utils.formatStatusText;
|
||||
import static org.mariotaku.twidere.util.Utils.getInReplyToName;
|
||||
import static org.mariotaku.twidere.util.content.ContentValuesUtils.getAsBoolean;
|
||||
import static org.mariotaku.twidere.util.content.ContentValuesUtils.getAsInteger;
|
||||
import static org.mariotaku.twidere.util.content.ContentValuesUtils.getAsLong;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class ParcelableStatus implements TwidereParcelable, Comparable<ParcelableStatus> {
|
||||
|
||||
public static final Parcelable.Creator<ParcelableStatus> CREATOR = new Parcelable.Creator<ParcelableStatus>() {
|
||||
@ -121,41 +118,41 @@ public class ParcelableStatus implements TwidereParcelable, Comparable<Parcelabl
|
||||
public final ParcelableCardEntity card;
|
||||
|
||||
public ParcelableStatus(final ContentValues values) {
|
||||
id = getAsLong(values, Statuses.STATUS_ID, -1);
|
||||
account_id = getAsLong(values, Statuses.ACCOUNT_ID, -1);
|
||||
timestamp = getAsLong(values, Statuses.STATUS_TIMESTAMP, -1);
|
||||
user_id = getAsLong(values, Statuses.USER_ID, -1);
|
||||
retweet_id = getAsLong(values, Statuses.RETWEET_ID, -1);
|
||||
retweet_timestamp = getAsLong(values, Statuses.RETWEET_TIMESTAMP, -1);
|
||||
retweeted_by_id = getAsLong(values, Statuses.RETWEETED_BY_USER_ID, -1);
|
||||
id = ContentValuesUtils.getAsLong(values, Statuses.STATUS_ID, -1);
|
||||
account_id = ContentValuesUtils.getAsLong(values, Statuses.ACCOUNT_ID, -1);
|
||||
timestamp = ContentValuesUtils.getAsLong(values, Statuses.STATUS_TIMESTAMP, -1);
|
||||
user_id = ContentValuesUtils.getAsLong(values, Statuses.USER_ID, -1);
|
||||
retweet_id = ContentValuesUtils.getAsLong(values, Statuses.RETWEET_ID, -1);
|
||||
retweet_timestamp = ContentValuesUtils.getAsLong(values, Statuses.RETWEET_TIMESTAMP, -1);
|
||||
retweeted_by_id = ContentValuesUtils.getAsLong(values, Statuses.RETWEETED_BY_USER_ID, -1);
|
||||
user_name = values.getAsString(Statuses.USER_NAME);
|
||||
user_screen_name = values.getAsString(Statuses.USER_SCREEN_NAME);
|
||||
text_html = values.getAsString(Statuses.TEXT_HTML);
|
||||
text_plain = values.getAsString(Statuses.TEXT_PLAIN);
|
||||
user_profile_image_url = values.getAsString(Statuses.USER_PROFILE_IMAGE_URL);
|
||||
is_favorite = getAsBoolean(values, Statuses.IS_FAVORITE, false);
|
||||
is_retweet = getAsBoolean(values, Statuses.IS_RETWEET, false);
|
||||
is_gap = getAsBoolean(values, Statuses.IS_GAP, false);
|
||||
is_favorite = ContentValuesUtils.getAsBoolean(values, Statuses.IS_FAVORITE, false);
|
||||
is_retweet = ContentValuesUtils.getAsBoolean(values, Statuses.IS_RETWEET, false);
|
||||
is_gap = ContentValuesUtils.getAsBoolean(values, Statuses.IS_GAP, false);
|
||||
location = ParcelableLocation.fromString(values.getAsString(Statuses.LOCATION));
|
||||
user_is_protected = getAsBoolean(values, Statuses.IS_PROTECTED, false);
|
||||
user_is_verified = getAsBoolean(values, Statuses.IS_VERIFIED, false);
|
||||
in_reply_to_status_id = getAsLong(values, Statuses.IN_REPLY_TO_STATUS_ID, -1);
|
||||
in_reply_to_user_id = getAsLong(values, Statuses.IN_REPLY_TO_USER_ID, -1);
|
||||
user_is_protected = ContentValuesUtils.getAsBoolean(values, Statuses.IS_PROTECTED, false);
|
||||
user_is_verified = ContentValuesUtils.getAsBoolean(values, Statuses.IS_VERIFIED, false);
|
||||
in_reply_to_status_id = ContentValuesUtils.getAsLong(values, Statuses.IN_REPLY_TO_STATUS_ID, -1);
|
||||
in_reply_to_user_id = ContentValuesUtils.getAsLong(values, Statuses.IN_REPLY_TO_USER_ID, -1);
|
||||
in_reply_to_name = values.getAsString(Statuses.IN_REPLY_TO_USER_NAME);
|
||||
in_reply_to_screen_name = values.getAsString(Statuses.IN_REPLY_TO_USER_SCREEN_NAME);
|
||||
my_retweet_id = getAsLong(values, Statuses.MY_RETWEET_ID, -1);
|
||||
my_retweet_id = ContentValuesUtils.getAsLong(values, Statuses.MY_RETWEET_ID, -1);
|
||||
retweeted_by_name = values.getAsString(Statuses.RETWEETED_BY_USER_NAME);
|
||||
retweeted_by_screen_name = values.getAsString(Statuses.RETWEETED_BY_USER_SCREEN_NAME);
|
||||
retweeted_by_profile_image = values.getAsString(Statuses.RETWEETED_BY_USER_PROFILE_IMAGE);
|
||||
source = values.getAsString(Statuses.SOURCE);
|
||||
retweet_count = getAsInteger(values, Statuses.RETWEET_COUNT, 0);
|
||||
favorite_count = getAsInteger(values, Statuses.FAVORITE_COUNT, 0);
|
||||
reply_count = getAsInteger(values, Statuses.REPLY_COUNT, 0);
|
||||
descendent_reply_count = getAsInteger(values, Statuses.DESCENDENT_REPLY_COUNT, 0);
|
||||
retweet_count = ContentValuesUtils.getAsInteger(values, Statuses.RETWEET_COUNT, 0);
|
||||
favorite_count = ContentValuesUtils.getAsInteger(values, Statuses.FAVORITE_COUNT, 0);
|
||||
reply_count = ContentValuesUtils.getAsInteger(values, Statuses.REPLY_COUNT, 0);
|
||||
descendent_reply_count = ContentValuesUtils.getAsInteger(values, Statuses.DESCENDENT_REPLY_COUNT, 0);
|
||||
text_unescaped = values.getAsString(Statuses.TEXT_UNESCAPED);
|
||||
media = ParcelableMedia.fromJSONString(values.getAsString(Statuses.MEDIA));
|
||||
is_possibly_sensitive = getAsBoolean(values, Statuses.IS_POSSIBLY_SENSITIVE, false);
|
||||
user_is_following = getAsBoolean(values, Statuses.IS_FOLLOWING, false);
|
||||
is_possibly_sensitive = ContentValuesUtils.getAsBoolean(values, Statuses.IS_POSSIBLY_SENSITIVE, false);
|
||||
user_is_following = ContentValuesUtils.getAsBoolean(values, Statuses.IS_FOLLOWING, false);
|
||||
mentions = ParcelableUserMention.fromJSONString(values.getAsString(Statuses.MENTIONS));
|
||||
first_media = values.getAsString(Statuses.FIRST_MEDIA);
|
||||
card = ParcelableCardEntity.fromJSONString(values.getAsString(Statuses.CARD));
|
||||
@ -353,21 +350,21 @@ public class ParcelableStatus implements TwidereParcelable, Comparable<Parcelabl
|
||||
user_is_protected = user.isProtected();
|
||||
user_is_verified = user.isVerified();
|
||||
user_is_following = user.isFollowing();
|
||||
text_html = formatStatusText(status);
|
||||
text_html = TwitterContentUtils.formatStatusText(status);
|
||||
media = ParcelableMedia.fromEntities(status);
|
||||
text_plain = status.getText();
|
||||
retweet_count = status.getRetweetCount();
|
||||
favorite_count = status.getFavoriteCount();
|
||||
reply_count = status.getReplyCount();
|
||||
descendent_reply_count = status.getDescendentReplyCount();
|
||||
in_reply_to_name = getInReplyToName(status);
|
||||
in_reply_to_name = TwitterContentUtils.getInReplyToName(status);
|
||||
in_reply_to_screen_name = status.getInReplyToScreenName();
|
||||
in_reply_to_status_id = status.getInReplyToStatusId();
|
||||
in_reply_to_user_id = status.getInReplyToUserId();
|
||||
source = status.getSource();
|
||||
location = new ParcelableLocation(status.getGeoLocation());
|
||||
is_favorite = status.isFavorited();
|
||||
text_unescaped = toPlainText(text_html);
|
||||
text_unescaped = HtmlEscapeHelper.toPlainText(text_html);
|
||||
my_retweet_id = retweeted_by_id == account_id ? id : status.getCurrentUserRetweet();
|
||||
is_possibly_sensitive = status.isPossiblySensitive();
|
||||
mentions = ParcelableUserMention.fromUserMentionEntities(status.getUserMentionEntities());
|
||||
@ -762,23 +759,21 @@ public class ParcelableStatus implements TwidereParcelable, Comparable<Parcelabl
|
||||
public ParcelableValueItem(JSONParcel in) {
|
||||
this.name = in.readString("name");
|
||||
this.type = in.readString("type");
|
||||
if ("STRING".equals(type)) {
|
||||
value = in.readString("value");
|
||||
} else if ("IMAGE".equals(type)) {
|
||||
value = in.readParcelable("value", ParcelableImageValue.JSON_CREATOR);
|
||||
} else if ("USER".equals(type)) {
|
||||
value = in.readParcelable("value", ParcelableUserValue.JSON_CREATOR);
|
||||
} else {
|
||||
throw new UnsupportedOperationException();
|
||||
switch (type) {
|
||||
case "STRING":
|
||||
value = in.readString("value");
|
||||
break;
|
||||
case "IMAGE":
|
||||
value = in.readParcelable("value", ParcelableImageValue.JSON_CREATOR);
|
||||
break;
|
||||
case "USER":
|
||||
value = in.readParcelable("value", ParcelableUserValue.JSON_CREATOR);
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
public ParcelableValueItem(String name, String type, Object value) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public ParcelableValueItem(Parcel in) {
|
||||
this.name = in.readString();
|
||||
this.type = in.readString();
|
||||
@ -788,14 +783,19 @@ public class ParcelableStatus implements TwidereParcelable, Comparable<Parcelabl
|
||||
public ParcelableValueItem(BindingValue bindingValue) {
|
||||
name = bindingValue.getName();
|
||||
type = bindingValue.getType();
|
||||
if ("STRING".equals(type)) {
|
||||
value = ((StringValue) bindingValue).getValue();
|
||||
} else if ("IMAGE".equals(type)) {
|
||||
value = new ParcelableImageValue((ImageValue) bindingValue);
|
||||
} else if ("USER".equals(type)) {
|
||||
value = new ParcelableUserValue((UserValue) bindingValue);
|
||||
} else {
|
||||
value = null;
|
||||
switch (type) {
|
||||
case "STRING":
|
||||
value = ((StringValue) bindingValue).getValue();
|
||||
break;
|
||||
case "IMAGE":
|
||||
value = new ParcelableImageValue((ImageValue) bindingValue);
|
||||
break;
|
||||
case "USER":
|
||||
value = new ParcelableUserValue((UserValue) bindingValue);
|
||||
break;
|
||||
default:
|
||||
value = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -28,17 +28,15 @@ import android.support.annotation.Nullable;
|
||||
|
||||
import org.mariotaku.jsonserializer.JSONParcel;
|
||||
import org.mariotaku.jsonserializer.JSONParcelable;
|
||||
import org.mariotaku.twidere.provider.TweetStore.CachedUsers;
|
||||
import org.mariotaku.twidere.provider.TweetStore.DirectMessages.ConversationEntries;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.CachedUsers;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages.ConversationEntries;
|
||||
import org.mariotaku.twidere.util.HtmlEscapeHelper;
|
||||
import org.mariotaku.twidere.util.TwitterContentUtils;
|
||||
import org.mariotaku.twidere.util.ParseUtils;
|
||||
|
||||
import twitter4j.URLEntity;
|
||||
import twitter4j.User;
|
||||
|
||||
import static org.mariotaku.twidere.util.HtmlEscapeHelper.toPlainText;
|
||||
import static org.mariotaku.twidere.util.Utils.formatExpandedUserDescription;
|
||||
import static org.mariotaku.twidere.util.Utils.formatUserDescription;
|
||||
|
||||
public class ParcelableUser implements TwidereParcelable, Comparable<ParcelableUser> {
|
||||
|
||||
public static final Parcelable.Creator<ParcelableUser> CREATOR = new Parcelable.Creator<ParcelableUser>() {
|
||||
@ -139,7 +137,7 @@ public class ParcelableUser implements TwidereParcelable, Comparable<ParcelableU
|
||||
url_expanded = indices.url_expanded != -1 ? cursor.getString(indices.url_expanded) : null;
|
||||
profile_banner_url = indices.profile_banner_url != -1 ? cursor.getString(indices.profile_banner_url) : null;
|
||||
is_cache = true;
|
||||
description_unescaped = toPlainText(description_html);
|
||||
description_unescaped = HtmlEscapeHelper.toPlainText(description_html);
|
||||
is_following = indices.is_following != -1 && cursor.getInt(indices.is_following) == 1;
|
||||
background_color = indices.background_color != -1 ? cursor.getInt(indices.background_color) : 0;
|
||||
link_color = indices.link_color != -1 ? cursor.getInt(indices.link_color) : 0;
|
||||
@ -223,9 +221,9 @@ public class ParcelableUser implements TwidereParcelable, Comparable<ParcelableU
|
||||
name = user.getName();
|
||||
screen_name = user.getScreenName();
|
||||
description_plain = user.getDescription();
|
||||
description_html = formatUserDescription(user);
|
||||
description_expanded = formatExpandedUserDescription(user);
|
||||
description_unescaped = toPlainText(description_html);
|
||||
description_html = TwitterContentUtils.formatUserDescription(user);
|
||||
description_expanded = TwitterContentUtils.formatExpandedUserDescription(user);
|
||||
description_unescaped = HtmlEscapeHelper.toPlainText(description_html);
|
||||
location = user.getLocation();
|
||||
profile_image_url = ParseUtils.parseString(user.getProfileImageUrlHttps());
|
||||
profile_banner_url = user.getProfileBannerImageUrl();
|
@ -23,7 +23,8 @@ import android.content.ContentResolver;
|
||||
import android.net.Uri;
|
||||
import android.provider.BaseColumns;
|
||||
|
||||
public interface TweetStore {
|
||||
@SuppressWarnings("unused")
|
||||
public interface TwidereDataStore {
|
||||
|
||||
public static final String AUTHORITY = "twidere";
|
||||
|
@ -34,15 +34,15 @@ import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
import org.mariotaku.twidere.model.ParcelableStatusUpdate;
|
||||
import org.mariotaku.twidere.model.ParcelableUser;
|
||||
import org.mariotaku.twidere.model.ParcelableUserMention;
|
||||
import org.mariotaku.twidere.provider.TweetStore.Accounts;
|
||||
import org.mariotaku.twidere.provider.TweetStore.CachedRelationships;
|
||||
import org.mariotaku.twidere.provider.TweetStore.CachedTrends;
|
||||
import org.mariotaku.twidere.provider.TweetStore.CachedUsers;
|
||||
import org.mariotaku.twidere.provider.TweetStore.DirectMessages;
|
||||
import org.mariotaku.twidere.provider.TweetStore.Drafts;
|
||||
import org.mariotaku.twidere.provider.TweetStore.Filters;
|
||||
import org.mariotaku.twidere.provider.TweetStore.SavedSearches;
|
||||
import org.mariotaku.twidere.provider.TweetStore.Statuses;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.CachedRelationships;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.CachedTrends;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.CachedUsers;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Drafts;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Filters;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.SavedSearches;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Statuses;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -162,8 +162,8 @@ public final class ContentValuesCreator implements TwidereConstants {
|
||||
values.put(CachedUsers.LISTED_COUNT, user.getListedCount());
|
||||
values.put(CachedUsers.LOCATION, user.getLocation());
|
||||
values.put(CachedUsers.DESCRIPTION_PLAIN, user.getDescription());
|
||||
values.put(CachedUsers.DESCRIPTION_HTML, Utils.formatUserDescription(user));
|
||||
values.put(CachedUsers.DESCRIPTION_EXPANDED, Utils.formatExpandedUserDescription(user));
|
||||
values.put(CachedUsers.DESCRIPTION_HTML, TwitterContentUtils.formatUserDescription(user));
|
||||
values.put(CachedUsers.DESCRIPTION_EXPANDED, TwitterContentUtils.formatExpandedUserDescription(user));
|
||||
values.put(CachedUsers.URL, url);
|
||||
if (url != null && urls != null && urls.length > 0) {
|
||||
values.put(CachedUsers.URL_EXPANDED, ParseUtils.parseString(urls[0].getExpandedURL()));
|
||||
@ -187,7 +187,7 @@ public final class ContentValuesCreator implements TwidereConstants {
|
||||
values.put(DirectMessages.MESSAGE_TIMESTAMP, message.getCreatedAt().getTime());
|
||||
values.put(DirectMessages.SENDER_ID, sender.getId());
|
||||
values.put(DirectMessages.RECIPIENT_ID, recipient.getId());
|
||||
final String text_html = Utils.formatDirectMessageText(message);
|
||||
final String text_html = TwitterContentUtils.formatDirectMessageText(message);
|
||||
values.put(DirectMessages.TEXT_HTML, text_html);
|
||||
values.put(DirectMessages.TEXT_PLAIN, message.getText());
|
||||
values.put(DirectMessages.TEXT_UNESCAPED, toPlainText(text_html));
|
||||
@ -262,7 +262,7 @@ public final class ContentValuesCreator implements TwidereConstants {
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(Drafts.ACTION_TYPE, Drafts.ACTION_SEND_DIRECT_MESSAGE);
|
||||
values.put(Drafts.TEXT, text);
|
||||
values.put(Drafts.ACCOUNT_IDS, ArrayUtils.toString(new long[]{accountId}, ',', false));
|
||||
values.put(Drafts.ACCOUNT_IDS, TwidereArrayUtils.toString(new long[]{accountId}, ',', false));
|
||||
values.put(Drafts.TIMESTAMP, System.currentTimeMillis());
|
||||
if (imageUri != null) {
|
||||
final ParcelableMediaUpdate[] mediaArray = {new ParcelableMediaUpdate(imageUri, 0)};
|
||||
@ -335,7 +335,7 @@ public final class ContentValuesCreator implements TwidereConstants {
|
||||
values.put(Statuses.IS_VERIFIED, user.isVerified());
|
||||
values.put(Statuses.USER_PROFILE_IMAGE_URL, profileImageUrl);
|
||||
values.put(CachedUsers.IS_FOLLOWING, user.isFollowing());
|
||||
final String text_html = Utils.formatStatusText(status);
|
||||
final String text_html = TwitterContentUtils.formatStatusText(status);
|
||||
values.put(Statuses.TEXT_HTML, text_html);
|
||||
values.put(Statuses.TEXT_PLAIN, status.getText());
|
||||
values.put(Statuses.TEXT_UNESCAPED, toPlainText(text_html));
|
||||
@ -344,7 +344,7 @@ public final class ContentValuesCreator implements TwidereConstants {
|
||||
values.put(Statuses.DESCENDENT_REPLY_COUNT, status.getDescendentReplyCount());
|
||||
values.put(Statuses.IN_REPLY_TO_STATUS_ID, status.getInReplyToStatusId());
|
||||
values.put(Statuses.IN_REPLY_TO_USER_ID, status.getInReplyToUserId());
|
||||
values.put(Statuses.IN_REPLY_TO_USER_NAME, Utils.getInReplyToName(status));
|
||||
values.put(Statuses.IN_REPLY_TO_USER_NAME, TwitterContentUtils.getInReplyToName(status));
|
||||
values.put(Statuses.IN_REPLY_TO_USER_SCREEN_NAME, status.getInReplyToScreenName());
|
||||
values.put(Statuses.SOURCE, status.getSource());
|
||||
values.put(Statuses.IS_POSSIBLY_SENSITIVE, status.isPossiblySensitive());
|
||||
@ -375,7 +375,7 @@ public final class ContentValuesCreator implements TwidereConstants {
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(Drafts.ACTION_TYPE, Drafts.ACTION_UPDATE_STATUS);
|
||||
values.put(Drafts.TEXT, status.text);
|
||||
values.put(Drafts.ACCOUNT_IDS, ArrayUtils.toString(accountIds, ',', false));
|
||||
values.put(Drafts.ACCOUNT_IDS, TwidereArrayUtils.toString(accountIds, ',', false));
|
||||
values.put(Drafts.IN_REPLY_TO_STATUS_ID, status.in_reply_to_status_id);
|
||||
values.put(Drafts.LOCATION, ParcelableLocation.toString(status.location));
|
||||
values.put(Drafts.IS_POSSIBLY_SENSITIVE, status.is_possibly_sensitive);
|
@ -0,0 +1,217 @@
|
||||
/*
|
||||
* 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.util;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Locale;
|
||||
|
||||
import static android.text.TextUtils.isEmpty;
|
||||
import static org.mariotaku.twidere.util.HtmlEscapeHelper.escape;
|
||||
import static org.mariotaku.twidere.util.HtmlEscapeHelper.toHtml;
|
||||
import static org.mariotaku.twidere.util.HtmlEscapeHelper.unescape;
|
||||
|
||||
public class HtmlBuilder {
|
||||
|
||||
private final String source;
|
||||
private final int[] codePoints;
|
||||
private final int codePointsLength;
|
||||
private final boolean throwExceptions, sourceIsEscaped, shouldReEscape;
|
||||
|
||||
private final ArrayList<LinkSpec> links = new ArrayList<>();
|
||||
|
||||
public HtmlBuilder(final String source, final boolean strict, final boolean sourceIsEscaped,
|
||||
final boolean shouldReEscape) {
|
||||
if (source == null) throw new NullPointerException();
|
||||
this.source = source;
|
||||
final int length = source.length();
|
||||
final int[] codepointsTemp = new int[length];
|
||||
int codePointsLength = 0;
|
||||
for (int offset = 0; offset < length; ) {
|
||||
final int codepoint = source.codePointAt(offset);
|
||||
codepointsTemp[codePointsLength++] = codepoint;
|
||||
offset += Character.charCount(codepoint);
|
||||
}
|
||||
codePoints = new int[codePointsLength];
|
||||
System.arraycopy(codepointsTemp, 0, codePoints, 0, codePointsLength);
|
||||
throwExceptions = strict;
|
||||
this.sourceIsEscaped = sourceIsEscaped;
|
||||
this.shouldReEscape = shouldReEscape;
|
||||
this.codePointsLength = codePointsLength;
|
||||
}
|
||||
|
||||
public boolean addLink(final String link, final String display, final int start, final int end) {
|
||||
return addLink(link, display, start, end, false);
|
||||
}
|
||||
|
||||
public boolean addLink(final String link, final String display, final int start, final int end,
|
||||
final boolean display_is_html) {
|
||||
if (start < 0 || end < 0 || start > end || end > codePointsLength) {
|
||||
final String message = String.format(Locale.US, "text:%s, length:%d, start:%d, end:%d", source,
|
||||
codePointsLength, start, end);
|
||||
if (throwExceptions) throw new StringIndexOutOfBoundsException(message);
|
||||
return false;
|
||||
}
|
||||
if (hasLink(start, end)) {
|
||||
final String message = String.format(Locale.US,
|
||||
"link already added in this range! text:%s, link:%s, display:%s, start:%d, end:%d", source, link,
|
||||
display, start, end);
|
||||
if (throwExceptions) throw new IllegalArgumentException(message);
|
||||
return false;
|
||||
}
|
||||
return links.add(new LinkSpec(link, display, start, end, display_is_html));
|
||||
}
|
||||
|
||||
public String build() {
|
||||
if (links.isEmpty()) return escapeSource(source);
|
||||
Collections.sort(links);
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
final int linksSize = links.size();
|
||||
for (int i = 0; i < linksSize; i++) {
|
||||
final LinkSpec spec = links.get(i);
|
||||
if (spec == null) {
|
||||
continue;
|
||||
}
|
||||
final int start = spec.start, end = spec.end;
|
||||
if (i == 0) {
|
||||
if (start >= 0 && start <= codePointsLength) {
|
||||
appendSource(builder, 0, start);
|
||||
}
|
||||
} else if (i > 0) {
|
||||
final int lastEnd = links.get(i - 1).end;
|
||||
if (lastEnd >= 0 && lastEnd <= start && start <= codePointsLength) {
|
||||
appendSource(builder, lastEnd, start);
|
||||
}
|
||||
}
|
||||
builder.append("<a href=\"");
|
||||
builder.append(spec.link);
|
||||
builder.append("\">");
|
||||
if (start >= 0 && start <= end && end <= codePointsLength) {
|
||||
builder.append(!isEmpty(spec.display) ? spec.display_is_html ? spec.display : toHtml(spec.display)
|
||||
: spec.link);
|
||||
}
|
||||
builder.append("</a>");
|
||||
if (i == linksSize - 1 && end >= 0 && end <= codePointsLength) {
|
||||
appendSource(builder, end, codePointsLength);
|
||||
}
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public boolean hasLink(final int start, final int end) {
|
||||
for (final LinkSpec spec : links) {
|
||||
if (start >= spec.start && start <= spec.end || end >= spec.start && end <= spec.end)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HtmlBuilder{orig=" + source + ", codePoints=" + Arrays.toString(codePoints) + ", string_length="
|
||||
+ codePointsLength + ", throw_exceptions=" + throwExceptions + ", source_is_escaped=" + sourceIsEscaped
|
||||
+ ", should_re_escape=" + shouldReEscape + ", links=" + links + "}";
|
||||
}
|
||||
|
||||
private void appendSource(final StringBuilder builder, final int start, final int end) {
|
||||
if (sourceIsEscaped == shouldReEscape) {
|
||||
for (int i = start; i < end; i++) {
|
||||
builder.appendCodePoint(codePoints[i]);
|
||||
}
|
||||
} else if (shouldReEscape) {
|
||||
builder.append(escape(subString(start, end)));
|
||||
} else {
|
||||
builder.append(unescape(subString(start, end)));
|
||||
}
|
||||
}
|
||||
|
||||
private String escapeSource(final String source) {
|
||||
if (sourceIsEscaped == shouldReEscape) return source;
|
||||
return shouldReEscape ? escape(source) : unescape(source);
|
||||
}
|
||||
|
||||
private String subString(final int start, final int end) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
for (int i = start; i < end; i++) {
|
||||
sb.appendCodePoint(codePoints[i]);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
static final class LinkSpec implements Comparable<LinkSpec> {
|
||||
|
||||
final String link, display;
|
||||
final int start, end;
|
||||
final boolean display_is_html;
|
||||
|
||||
LinkSpec(final String link, final String display, final int start, final int end, final boolean display_is_html) {
|
||||
this.link = link;
|
||||
this.display = display;
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.display_is_html = display_is_html;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NonNull final LinkSpec that) {
|
||||
return start - that.start;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (obj == null) return false;
|
||||
if (!(obj instanceof LinkSpec)) return false;
|
||||
final LinkSpec other = (LinkSpec) obj;
|
||||
if (display == null) {
|
||||
if (other.display != null) return false;
|
||||
} else if (!display.equals(other.display)) return false;
|
||||
if (display_is_html != other.display_is_html) return false;
|
||||
if (end != other.end) return false;
|
||||
if (link == null) {
|
||||
if (other.link != null) return false;
|
||||
} else if (!link.equals(other.link)) return false;
|
||||
if (start != other.start) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + (display == null ? 0 : display.hashCode());
|
||||
result = prime * result + (display_is_html ? 1231 : 1237);
|
||||
result = prime * result + end;
|
||||
result = prime * result + (link == null ? 0 : link.hashCode());
|
||||
result = prime * result + start;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LinkSpec{link=" + link + ", display=" + display + ", start=" + start + ", end=" + end
|
||||
+ ", display_is_html=" + display_is_html + "}";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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.util;
|
||||
|
||||
import java.util.Vector;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class HtmlLinkExtractor {
|
||||
|
||||
private final Pattern patternTag, patternLink;
|
||||
|
||||
private static final String HTML_A_TAG_PATTERN = "(?i)<a([^>]+)>(.+?)</a>";
|
||||
private static final String HTML_A_HREF_TAG_PATTERN = "\\s*(?i)href\\s*=\\s*(\"([^\"]*\")|'[^']*'|([^'\">\\s]+))";
|
||||
|
||||
public HtmlLinkExtractor() {
|
||||
patternTag = Pattern.compile(HTML_A_TAG_PATTERN);
|
||||
patternLink = Pattern.compile(HTML_A_HREF_TAG_PATTERN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate html with regular expression
|
||||
*
|
||||
* @param html html content for validation
|
||||
* @return Vector links and link text
|
||||
*/
|
||||
public Vector<HtmlLink> grabLinks(final String html) {
|
||||
final Vector<HtmlLink> result = new Vector<HtmlLink>();
|
||||
final Matcher matcherTag = patternTag.matcher(html);
|
||||
while (matcherTag.find()) {
|
||||
final String href = matcherTag.group(1); // href
|
||||
final String linkText = matcherTag.group(2); // link text
|
||||
final Matcher matcherLink = patternLink.matcher(href);
|
||||
while (matcherLink.find()) {
|
||||
final String link = matcherLink.group(1); // link
|
||||
final HtmlLink obj = new HtmlLink(link, linkText);
|
||||
result.add(obj);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static class HtmlLink {
|
||||
|
||||
private final String link;
|
||||
private final String text;
|
||||
|
||||
private HtmlLink(final String link, final String text) {
|
||||
this.link = replaceInvalidChar(link);
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public String getLink() {
|
||||
return link;
|
||||
}
|
||||
|
||||
public String getLinkText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
private static String replaceInvalidChar(String link) {
|
||||
link = link.replaceAll("'", "");
|
||||
link = link.replaceAll("\"", "");
|
||||
return link;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -19,24 +19,15 @@
|
||||
|
||||
package org.mariotaku.twidere.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.model.ParcelableMedia;
|
||||
import org.mariotaku.twidere.util.HtmlLinkExtractor.HtmlLink;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Locale;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
@ -50,7 +41,6 @@ import twitter4j.http.HttpParameter;
|
||||
import twitter4j.http.HttpResponse;
|
||||
|
||||
import static android.text.TextUtils.isEmpty;
|
||||
import static org.mariotaku.twidere.util.Utils.matcherGroup;
|
||||
|
||||
public class MediaPreviewUtils {
|
||||
|
||||
@ -193,52 +183,6 @@ public class MediaPreviewUtils {
|
||||
|
||||
private static final String URL_PHOTOZOU_PHOTO_INFO = "https://api.photozou.jp/rest/photo_info.json";
|
||||
|
||||
public static void addToLinearLayout(final LinearLayout container, final ImageLoaderWrapper loader,
|
||||
final List<ParcelableMedia> mediaList, final long accountId,
|
||||
final int maxColumnCount, final OnMediaClickListener mediaClickListener) {
|
||||
if (container.getOrientation() != LinearLayout.VERTICAL)
|
||||
throw new IllegalArgumentException();
|
||||
final Context context = container.getContext();
|
||||
final ImageLoadingHandler loadingHandler = new ImageLoadingHandler(R.id.media_preview_progress);
|
||||
final LayoutInflater inflater = LayoutInflater.from(context);
|
||||
final ListIterator<ParcelableMedia> iterator = mediaList.listIterator();
|
||||
final int imageCount = mediaList.size();
|
||||
final double imageCountSqrt = Math.sqrt(imageCount);
|
||||
final int bestColumnCount = imageCountSqrt % 1 == 0 ? (int) imageCountSqrt : maxColumnCount;
|
||||
final int firstColumn = imageCount % bestColumnCount, fullRowCount = imageCount / bestColumnCount;
|
||||
final int rowCount = fullRowCount + (firstColumn > 0 ? 1 : 0);
|
||||
final View.OnClickListener clickListener = new ImageGridClickListener(mediaClickListener, accountId);
|
||||
container.setMotionEventSplittingEnabled(false);
|
||||
for (int currentRow = 0; currentRow < rowCount; currentRow++) {
|
||||
final LinearLayout rowContainer = new LinearLayout(context);
|
||||
rowContainer.setOrientation(LinearLayout.HORIZONTAL);
|
||||
rowContainer.setMotionEventSplittingEnabled(false);
|
||||
container.addView(rowContainer, LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||
final int columnCount = currentRow == 0 && firstColumn > 0 ? firstColumn : bestColumnCount;
|
||||
for (int currentColumn = 0; currentColumn < columnCount; currentColumn++) {
|
||||
final ParcelableMedia media = iterator.next();
|
||||
final View item = inflater.inflate(R.layout.grid_item_media_preview, rowContainer, false);
|
||||
item.setTag(media);
|
||||
if (mediaClickListener != null) {
|
||||
item.setOnClickListener(clickListener);
|
||||
}
|
||||
final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) item.getLayoutParams();
|
||||
lp.weight = 1.0f;
|
||||
rowContainer.addView(item, lp);
|
||||
final ImageView imageView = (ImageView) item.findViewById(R.id.media_preview_item);
|
||||
loader.displayPreviewImage(imageView, media.url, loadingHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void addToLinearLayout(final LinearLayout container, final ImageLoaderWrapper loader,
|
||||
final ParcelableMedia[] mediaArray, final long accountId,
|
||||
final int maxColumnCount, final OnMediaClickListener listener) {
|
||||
addToLinearLayout(container, loader, Arrays.asList(mediaArray), accountId, maxColumnCount,
|
||||
listener);
|
||||
}
|
||||
|
||||
public static ParcelableMedia getAllAvailableImage(final String link, final boolean fullImage) {
|
||||
try {
|
||||
return getAllAvailableImage(link, fullImage, null);
|
||||
@ -250,43 +194,47 @@ public class MediaPreviewUtils {
|
||||
public static ParcelableMedia getAllAvailableImage(final String link, final boolean fullImage,
|
||||
final HttpClientWrapper client) throws IOException {
|
||||
if (link == null) return null;
|
||||
StrictModeUtils.checkLengthyOperation();
|
||||
Matcher m;
|
||||
m = PATTERN_TWITTER_IMAGES.matcher(link);
|
||||
if (m.matches()) return getTwitterImage(link, fullImage);
|
||||
m = PATTERN_INSTAGRAM.matcher(link);
|
||||
if (m.matches())
|
||||
return getInstagramImage(matcherGroup(m, INSTAGRAM_GROUP_ID), link, fullImage);
|
||||
return getInstagramImage(RegexUtils.matcherGroup(m, INSTAGRAM_GROUP_ID), link, fullImage);
|
||||
m = PATTERN_GOOGLE_IMAGES.matcher(link);
|
||||
if (m.matches())
|
||||
return getGoogleImage(matcherGroup(m, GOOGLE_IMAGES_GROUP_SERVER), matcherGroup(m, GOOGLE_IMAGES_GROUP_ID),
|
||||
return getGoogleImage(RegexUtils.matcherGroup(m, GOOGLE_IMAGES_GROUP_SERVER), RegexUtils.matcherGroup(m, GOOGLE_IMAGES_GROUP_ID),
|
||||
fullImage);
|
||||
m = PATTERN_GOOGLE_PROXY_IMAGES.matcher(link);
|
||||
if (m.matches())
|
||||
return getGoogleProxyImage(matcherGroup(m, GOOGLE_PROXY_IMAGES_GROUP_SERVER),
|
||||
matcherGroup(m, GOOGLE_PROXY_IMAGES_GROUP_ID), fullImage);
|
||||
return getGoogleProxyImage(RegexUtils.matcherGroup(m, GOOGLE_PROXY_IMAGES_GROUP_SERVER),
|
||||
RegexUtils.matcherGroup(m, GOOGLE_PROXY_IMAGES_GROUP_ID), fullImage);
|
||||
m = PATTERN_SINA_WEIBO_IMAGES.matcher(link);
|
||||
if (m.matches()) return getSinaWeiboImage(link, fullImage);
|
||||
m = PATTERN_TWITPIC.matcher(link);
|
||||
if (m.matches()) return getTwitpicImage(matcherGroup(m, TWITPIC_GROUP_ID), link, fullImage);
|
||||
if (m.matches())
|
||||
return getTwitpicImage(RegexUtils.matcherGroup(m, TWITPIC_GROUP_ID), link, fullImage);
|
||||
m = PATTERN_IMGUR.matcher(link);
|
||||
if (m.matches()) return getImgurImage(matcherGroup(m, IMGUR_GROUP_ID), link, fullImage);
|
||||
if (m.matches())
|
||||
return getImgurImage(RegexUtils.matcherGroup(m, IMGUR_GROUP_ID), link, fullImage);
|
||||
m = PATTERN_IMGLY.matcher(link);
|
||||
if (m.matches()) return getImglyImage(matcherGroup(m, IMGLY_GROUP_ID), link, fullImage);
|
||||
if (m.matches())
|
||||
return getImglyImage(RegexUtils.matcherGroup(m, IMGLY_GROUP_ID), link, fullImage);
|
||||
m = PATTERN_YFROG.matcher(link);
|
||||
if (m.matches()) return getYfrogImage(matcherGroup(m, YFROG_GROUP_ID), link, fullImage);
|
||||
if (m.matches())
|
||||
return getYfrogImage(RegexUtils.matcherGroup(m, YFROG_GROUP_ID), link, fullImage);
|
||||
m = PATTERN_LOCKERZ.matcher(link);
|
||||
if (m.matches()) return getLockerzAndPlixiImage(link, fullImage);
|
||||
m = PATTERN_PLIXI.matcher(link);
|
||||
if (m.matches()) return getLockerzAndPlixiImage(link, fullImage);
|
||||
m = PATTERN_TWITGOO.matcher(link);
|
||||
if (m.matches()) return getTwitgooImage(matcherGroup(m, TWITGOO_GROUP_ID), link, fullImage);
|
||||
if (m.matches())
|
||||
return getTwitgooImage(RegexUtils.matcherGroup(m, TWITGOO_GROUP_ID), link, fullImage);
|
||||
m = PATTERN_MOBYPICTURE.matcher(link);
|
||||
if (m.matches())
|
||||
return getMobyPictureImage(matcherGroup(m, MOBYPICTURE_GROUP_ID), link, fullImage);
|
||||
return getMobyPictureImage(RegexUtils.matcherGroup(m, MOBYPICTURE_GROUP_ID), link, fullImage);
|
||||
m = PATTERN_PHOTOZOU.matcher(link);
|
||||
if (m.matches())
|
||||
return getPhotozouImage(client, matcherGroup(m, PHOTOZOU_GROUP_ID), link, fullImage);
|
||||
return getPhotozouImage(client, RegexUtils.matcherGroup(m, PHOTOZOU_GROUP_ID), link, fullImage);
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -461,24 +409,4 @@ public class MediaPreviewUtils {
|
||||
|
||||
}
|
||||
|
||||
public interface OnMediaClickListener {
|
||||
void onMediaClick(View view, ParcelableMedia media, long accountId);
|
||||
}
|
||||
|
||||
private static class ImageGridClickListener implements View.OnClickListener {
|
||||
private final OnMediaClickListener mListener;
|
||||
private final long mAccountId;
|
||||
|
||||
ImageGridClickListener(final OnMediaClickListener listener, final long accountId) {
|
||||
mListener = listener;
|
||||
mAccountId = accountId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(final View v) {
|
||||
if (mListener == null) return;
|
||||
mListener.onMediaClick(v, (ParcelableMedia) v.getTag(), mAccountId);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,205 @@
|
||||
/*
|
||||
* 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.util;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.mariotaku.twidere.TwidereConstants;
|
||||
import org.mariotaku.twidere.constant.IntentConstants;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import static android.text.TextUtils.isEmpty;
|
||||
|
||||
public final class ParseUtils {
|
||||
|
||||
public static String bundleToJSON(final Bundle args) {
|
||||
final Set<String> keys = args.keySet();
|
||||
final JSONObject json = new JSONObject();
|
||||
for (final String key : keys) {
|
||||
final Object value = args.get(key);
|
||||
if (value == null) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
if (value instanceof Boolean) {
|
||||
json.put(key, args.getBoolean(key));
|
||||
} else if (value instanceof Integer) {
|
||||
json.put(key, args.getInt(key));
|
||||
} else if (value instanceof Long) {
|
||||
json.put(key, args.getLong(key));
|
||||
} else if (value instanceof String) {
|
||||
json.put(key, args.getString(key));
|
||||
} else {
|
||||
Log.w(TwidereConstants.LOGTAG, "Unknown type " + value.getClass().getSimpleName() + " in arguments key " + key);
|
||||
}
|
||||
} catch (final JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return json.toString();
|
||||
}
|
||||
|
||||
public static Bundle jsonToBundle(final String string) {
|
||||
final Bundle bundle = new Bundle();
|
||||
if (string == null) return bundle;
|
||||
try {
|
||||
final JSONObject json = new JSONObject(string);
|
||||
final Iterator<?> it = json.keys();
|
||||
while (it.hasNext()) {
|
||||
final Object key_obj = it.next();
|
||||
if (key_obj == null) {
|
||||
continue;
|
||||
}
|
||||
final String key = key_obj.toString();
|
||||
final Object value = json.get(key);
|
||||
if (value instanceof Boolean) {
|
||||
bundle.putBoolean(key, json.optBoolean(key));
|
||||
} else if (value instanceof Integer) {
|
||||
// Simple workaround for account_id
|
||||
if (shouldPutLong(key)) {
|
||||
bundle.putLong(key, json.optLong(key));
|
||||
} else {
|
||||
bundle.putInt(key, json.optInt(key));
|
||||
}
|
||||
} else if (value instanceof Long) {
|
||||
bundle.putLong(key, json.optLong(key));
|
||||
} else if (value instanceof String) {
|
||||
bundle.putString(key, json.optString(key));
|
||||
} else {
|
||||
Log.w(TwidereConstants.LOGTAG, "Unknown type " + value.getClass().getSimpleName() + " in arguments key " + key);
|
||||
}
|
||||
}
|
||||
} catch (final JSONException e) {
|
||||
e.printStackTrace();
|
||||
} catch (final ClassCastException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return bundle;
|
||||
}
|
||||
|
||||
public static double parseDouble(final String source) {
|
||||
return parseDouble(source, -1);
|
||||
}
|
||||
|
||||
public static double parseDouble(final String source, final double def) {
|
||||
if (source == null) return def;
|
||||
try {
|
||||
return Double.parseDouble(source);
|
||||
} catch (final NumberFormatException e) {
|
||||
// Wrong number format? Ignore them.
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
public static float parseFloat(final String source) {
|
||||
return parseFloat(source, -1);
|
||||
}
|
||||
|
||||
public static float parseFloat(final String source, final float def) {
|
||||
if (source == null) return def;
|
||||
try {
|
||||
return Float.parseFloat(source);
|
||||
} catch (final NumberFormatException e) {
|
||||
// Wrong number format? Ignore them.
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
public static int parseInt(final String source) {
|
||||
return parseInt(source, -1);
|
||||
}
|
||||
|
||||
public static int parseInt(final String source, final int def) {
|
||||
if (source == null) return def;
|
||||
try {
|
||||
return Integer.valueOf(source);
|
||||
} catch (final NumberFormatException e) {
|
||||
// Wrong number format? Ignore them.
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
public static long parseLong(final String source) {
|
||||
return parseLong(source, -1);
|
||||
}
|
||||
|
||||
public static long parseLong(final String source, final long def) {
|
||||
if (source == null) return def;
|
||||
try {
|
||||
return Long.parseLong(source);
|
||||
} catch (final NumberFormatException e) {
|
||||
// Wrong number format? Ignore them.
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
public static String parseString(final Object object) {
|
||||
return parseString(object, null);
|
||||
}
|
||||
|
||||
public static String parseString(final Object object, final String def) {
|
||||
if (object == null) return def;
|
||||
return String.valueOf(object);
|
||||
}
|
||||
|
||||
public static URI parseURI(final String uriString) {
|
||||
if (uriString == null) return null;
|
||||
try {
|
||||
return new URI(uriString);
|
||||
} catch (final URISyntaxException e) {
|
||||
// This should not happen.
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static URL parseURL(final String urlString) {
|
||||
if (urlString == null) return null;
|
||||
try {
|
||||
return new URL(urlString);
|
||||
} catch (final MalformedURLException e) {
|
||||
// This should not happen.
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean shouldPutLong(final String key) {
|
||||
return IntentConstants.EXTRA_ACCOUNT_ID.equals(key) || IntentConstants.EXTRA_USER_ID.equals(key) || IntentConstants.EXTRA_STATUS_ID.equals(key)
|
||||
|| IntentConstants.EXTRA_LIST_ID.equals(key);
|
||||
}
|
||||
|
||||
public static int parseColor(String str, int def) {
|
||||
if (isEmpty(str)) return def;
|
||||
try {
|
||||
return Color.parseColor(str);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.util;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/1/11.
|
||||
*/
|
||||
public class RegexUtils {
|
||||
public static int matcherEnd(final Matcher matcher, final int group) {
|
||||
try {
|
||||
return matcher.end(group);
|
||||
} catch (final IllegalStateException e) {
|
||||
// Ignore.
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static String matcherGroup(final Matcher matcher, final int group) {
|
||||
try {
|
||||
return matcher.group(group);
|
||||
} catch (final IllegalStateException e) {
|
||||
// Ignore.
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static int matcherStart(final Matcher matcher, final int group) {
|
||||
try {
|
||||
return matcher.start(group);
|
||||
} catch (final IllegalStateException e) {
|
||||
// Ignore.
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
@ -21,48 +21,33 @@ package org.mariotaku.twidere.util;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public final class ArrayUtils {
|
||||
public final class TwidereArrayUtils {
|
||||
|
||||
private ArrayUtils() {
|
||||
private TwidereArrayUtils() {
|
||||
throw new AssertionError("You are trying to create an instance for this utility class!");
|
||||
}
|
||||
|
||||
public static boolean contains(final int[] array, final int value) {
|
||||
if (array == null) return false;
|
||||
for (final int item : array) {
|
||||
if (item == value) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean contains(final long[] array, final long value) {
|
||||
if (array == null) return false;
|
||||
for (final long item : array) {
|
||||
if (item == value) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean contains(final Object[] array, final Object value) {
|
||||
if (array == null || value == null) return false;
|
||||
return contains(array, new Object[]{value});
|
||||
}
|
||||
|
||||
public static boolean contains(final Object[] array, final Object[] values) {
|
||||
if (array == null || values == null) return false;
|
||||
for (final Object item : array) {
|
||||
for (final Object value : values) {
|
||||
if (item == null || value == null) {
|
||||
if (item == value) return true;
|
||||
continue;
|
||||
}
|
||||
if (item.equals(value)) return true;
|
||||
}
|
||||
for (final Object value : values) {
|
||||
if (!ArrayUtils.contains(array, value)) return false;
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean contentMatch(final long[] array1, final long[] array2) {
|
||||
if (array1 == null || array2 == null) return array1 == array2;
|
||||
if (array1.length != array2.length) return false;
|
||||
final int length = array1.length;
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (!ArrayUtils.contains(array2, array1[i])) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean contentMatch(final Object[] array1, final Object[] array2) {
|
||||
@ -70,7 +55,7 @@ public final class ArrayUtils {
|
||||
if (array1.length != array2.length) return false;
|
||||
final int length = array1.length;
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (!contains(array2, array1[i])) return false;
|
||||
if (!ArrayUtils.contains(array2, array1[i])) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -85,29 +70,6 @@ public final class ArrayUtils {
|
||||
return array;
|
||||
}
|
||||
|
||||
public static int indexOf(final int[] array, final int value) {
|
||||
final int length = array.length;
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (array[i] == value) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static int indexOf(final long[] array, final long value) {
|
||||
final int length = array.length;
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (array[i] == value) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static int indexOf(final Object[] array, final Object value) {
|
||||
final int length = array.length;
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (array[i].equals(value)) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static long[] intersection(final long[] array1, final long[] array2) {
|
||||
if (array1 == null || array2 == null) return new long[0];
|
||||
@ -220,13 +182,11 @@ public final class ArrayUtils {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
final int length = array.length;
|
||||
for (int i = 0; i < length; i++) {
|
||||
final String id_string = String.valueOf(array[i]);
|
||||
if (id_string != null) {
|
||||
if (i > 0) {
|
||||
builder.append(include_space ? token + " " : token);
|
||||
}
|
||||
builder.append(id_string);
|
||||
final String idString = String.valueOf(array[i]);
|
||||
if (i > 0) {
|
||||
builder.append(include_space ? token + " " : token);
|
||||
}
|
||||
builder.append(idString);
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.mariotaku.twidere.common.R;
|
||||
|
||||
import java.net.URL;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.zip.CRC32;
|
||||
|
||||
import twitter4j.DirectMessage;
|
||||
import twitter4j.EntitySupport;
|
||||
import twitter4j.MediaEntity;
|
||||
import twitter4j.Status;
|
||||
import twitter4j.URLEntity;
|
||||
import twitter4j.User;
|
||||
import twitter4j.UserMentionEntity;
|
||||
|
||||
import static org.mariotaku.twidere.util.HtmlEscapeHelper.toPlainText;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/1/11.
|
||||
*/
|
||||
public class TwitterContentUtils {
|
||||
public static String formatDirectMessageText(final DirectMessage message) {
|
||||
if (message == null) return null;
|
||||
final String text = message.getRawText();
|
||||
if (text == null) return null;
|
||||
final HtmlBuilder builder = new HtmlBuilder(text, false, true, true);
|
||||
TwitterContentUtils.parseEntities(builder, message);
|
||||
return builder.build().replace("\n", "<br/>");
|
||||
}
|
||||
|
||||
public static String formatExpandedUserDescription(final User user) {
|
||||
if (user == null) return null;
|
||||
final String text = user.getDescription();
|
||||
if (text == null) return null;
|
||||
final HtmlBuilder builder = new HtmlBuilder(text, false, true, true);
|
||||
final URLEntity[] urls = user.getDescriptionEntities();
|
||||
if (urls != null) {
|
||||
for (final URLEntity url : urls) {
|
||||
final String expanded_url = ParseUtils.parseString(url.getExpandedURL());
|
||||
if (expanded_url != null) {
|
||||
builder.addLink(expanded_url, expanded_url, url.getStart(), url.getEnd());
|
||||
}
|
||||
}
|
||||
}
|
||||
return toPlainText(builder.build().replace("\n", "<br/>"));
|
||||
}
|
||||
|
||||
public static String formatStatusText(final Status status) {
|
||||
if (status == null) return null;
|
||||
final String text = status.getRawText();
|
||||
if (text == null) return null;
|
||||
final HtmlBuilder builder = new HtmlBuilder(text, false, true, true);
|
||||
TwitterContentUtils.parseEntities(builder, status);
|
||||
return builder.build().replace("\n", "<br/>");
|
||||
}
|
||||
|
||||
public static String formatUserDescription(final User user) {
|
||||
if (user == null) return null;
|
||||
final String text = user.getDescription();
|
||||
if (text == null) return null;
|
||||
final HtmlBuilder builder = new HtmlBuilder(text, false, true, true);
|
||||
final URLEntity[] urls = user.getDescriptionEntities();
|
||||
if (urls != null) {
|
||||
for (final URLEntity url : urls) {
|
||||
final URL expanded_url = url.getExpandedURL();
|
||||
if (expanded_url != null) {
|
||||
builder.addLink(ParseUtils.parseString(expanded_url), url.getDisplayURL(), url.getStart(),
|
||||
url.getEnd());
|
||||
}
|
||||
}
|
||||
}
|
||||
return builder.build().replace("\n", "<br/>");
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static String getInReplyToName(@NonNull final Status status) {
|
||||
final Status orig = status.isRetweet() ? status.getRetweetedStatus() : status;
|
||||
final long inReplyToUserId = status.getInReplyToUserId();
|
||||
final UserMentionEntity[] entities = status.getUserMentionEntities();
|
||||
if (entities == null) return orig.getInReplyToScreenName();
|
||||
for (final UserMentionEntity entity : entities) {
|
||||
if (inReplyToUserId == entity.getId()) return entity.getName();
|
||||
}
|
||||
return orig.getInReplyToScreenName();
|
||||
}
|
||||
|
||||
public static boolean isOfficialKey(final Context context, final String consumerKey,
|
||||
final String consumerSecret) {
|
||||
if (context == null || consumerKey == null || consumerSecret == null) return false;
|
||||
final String[] keySecrets = context.getResources().getStringArray(R.array.values_official_consumer_secret_crc32);
|
||||
final CRC32 crc32 = new CRC32();
|
||||
final byte[] consumerSecretBytes = consumerSecret.getBytes(Charset.forName("UTF-8"));
|
||||
crc32.update(consumerSecretBytes, 0, consumerSecretBytes.length);
|
||||
final long value = crc32.getValue();
|
||||
crc32.reset();
|
||||
for (final String keySecret : keySecrets) {
|
||||
if (Long.parseLong(keySecret, 16) == value) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void parseEntities(final HtmlBuilder builder, final EntitySupport entities) {
|
||||
// Format media.
|
||||
final MediaEntity[] mediaEntities = entities.getMediaEntities();
|
||||
if (mediaEntities != null) {
|
||||
for (final MediaEntity mediaEntity : mediaEntities) {
|
||||
final int start = mediaEntity.getStart(), end = mediaEntity.getEnd();
|
||||
final URL mediaUrl = mediaEntity.getMediaURL();
|
||||
if (mediaUrl != null && start >= 0 && end >= 0) {
|
||||
builder.addLink(ParseUtils.parseString(mediaUrl), mediaEntity.getDisplayURL(),
|
||||
start, end);
|
||||
}
|
||||
}
|
||||
}
|
||||
final URLEntity[] urlEntities = entities.getURLEntities();
|
||||
if (urlEntities != null) {
|
||||
for (final URLEntity urlEntity : urlEntities) {
|
||||
final int start = urlEntity.getStart(), end = urlEntity.getEnd();
|
||||
final URL expandedUrl = urlEntity.getExpandedURL();
|
||||
if (expandedUrl != null && start >= 0 && end >= 0) {
|
||||
builder.addLink(ParseUtils.parseString(expandedUrl), urlEntity.getDisplayURL(),
|
||||
start, end);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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.util.content;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.CancellationSignal;
|
||||
|
||||
import org.mariotaku.twidere.util.TwidereArrayUtils;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import static android.text.TextUtils.isEmpty;
|
||||
|
||||
public class ContentResolverUtils {
|
||||
|
||||
private static final int MAX_DELETE_COUNT = 128;
|
||||
|
||||
public static <T> int bulkDelete(final ContentResolver resolver, final Uri uri, final String inColumn,
|
||||
final Collection<T> colValues, final String extraWhere, final boolean valuesIsString) {
|
||||
if (colValues == null) return 0;
|
||||
return bulkDelete(resolver, uri, inColumn, colValues.toArray(), extraWhere, valuesIsString);
|
||||
}
|
||||
|
||||
public static <T> int bulkDelete(final ContentResolver resolver, final Uri uri, final String inColumn,
|
||||
final T[] colValues, final String extraWhere, final boolean valuesIsString) {
|
||||
if (resolver == null || uri == null || isEmpty(inColumn) || colValues == null || colValues.length == 0)
|
||||
return 0;
|
||||
final int col_values_length = colValues.length, blocks_count = col_values_length / MAX_DELETE_COUNT + 1;
|
||||
int rows_deleted = 0;
|
||||
for (int i = 0; i < blocks_count; i++) {
|
||||
final int start = i * MAX_DELETE_COUNT, end = Math.min(start + MAX_DELETE_COUNT, col_values_length);
|
||||
final String[] block = TwidereArrayUtils.toStringArray(TwidereArrayUtils.subArray(colValues, start, end));
|
||||
if (valuesIsString) {
|
||||
final StringBuilder where = new StringBuilder(inColumn + " IN(" + TwidereArrayUtils.toStringForSQL(block)
|
||||
+ ")");
|
||||
if (!isEmpty(extraWhere)) {
|
||||
where.append("AND ").append(extraWhere);
|
||||
}
|
||||
rows_deleted += resolver.delete(uri, where.toString(), block);
|
||||
} else {
|
||||
final StringBuilder where = new StringBuilder(inColumn + " IN("
|
||||
+ TwidereArrayUtils.toString(block, ',', true) + ")");
|
||||
if (!isEmpty(extraWhere)) {
|
||||
where.append("AND ").append(extraWhere);
|
||||
}
|
||||
rows_deleted += resolver.delete(uri, where.toString(), null);
|
||||
}
|
||||
}
|
||||
return rows_deleted;
|
||||
}
|
||||
|
||||
public static int bulkInsert(final ContentResolver resolver, final Uri uri, final Collection<ContentValues> values) {
|
||||
if (values == null) return 0;
|
||||
return bulkInsert(resolver, uri, values.toArray(new ContentValues[values.size()]));
|
||||
}
|
||||
|
||||
public static int bulkInsert(final ContentResolver resolver, final Uri uri, final ContentValues[] values) {
|
||||
if (resolver == null || uri == null || values == null || values.length == 0) return 0;
|
||||
final int colValuesLength = values.length, blocksCount = colValuesLength / MAX_DELETE_COUNT + 1;
|
||||
int rowsInserted = 0;
|
||||
for (int i = 0; i < blocksCount; i++) {
|
||||
final int start = i * MAX_DELETE_COUNT, end = Math.min(start + MAX_DELETE_COUNT, colValuesLength);
|
||||
final ContentValues[] block = new ContentValues[end - start];
|
||||
System.arraycopy(values, start, block, 0, end - start);
|
||||
rowsInserted += resolver.bulkInsert(uri, block);
|
||||
}
|
||||
return rowsInserted;
|
||||
}
|
||||
|
||||
public static Cursor query(final ContentResolver resolver, final Uri uri, final String[] projection,
|
||||
final String selection, final String[] selectionArgs, final String sortOrder) {
|
||||
return resolver.query(uri, projection, selection, selectionArgs, sortOrder);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
|
||||
public static Cursor query(final ContentResolver resolver, final Uri uri, final String[] projection,
|
||||
final String selection, final String[] selectionArgs, final String sortOrder,
|
||||
final CancellationSignal cancellationSignal) {
|
||||
return resolver.query(uri, projection, selection, selectionArgs, sortOrder, cancellationSignal);
|
||||
}
|
||||
|
||||
}
|
37
twidere.component.common/src/main/res/values/arrays.xml
Normal file
@ -0,0 +1,37 @@
|
||||
<?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/>.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<!-- CRC32 checksum of consumer secret of official clients to check whether user is using official keys -->
|
||||
<string-array name="values_official_consumer_secret_crc32">
|
||||
<!--Twitter for Android-->
|
||||
<item>6ce85096</item>
|
||||
<!--Twitter for iPhone-->
|
||||
<item>deffe9c7</item>
|
||||
<!--Twitter for iPad-->
|
||||
<item>9f00e0cb</item>
|
||||
<!--Twitter for Mac-->
|
||||
<item>df27640e</item>
|
||||
<!--Twitter for Windows Phone-->
|
||||
<item>62bd0d33</item>
|
||||
<!--Twitter for Google TV-->
|
||||
<item>56d8f9ff</item>
|
||||
</string-array>
|
||||
</resources>
|
23
twidere.component.common/src/main/res/values/defaults.xml
Normal file
@ -0,0 +1,23 @@
|
||||
<?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/>.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<integer name="default_text_size">15</integer>
|
||||
</resources>
|
1
twidere.component.jsonserializer/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/build
|
42
twidere.component.jsonserializer/build.gradle
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 21
|
||||
buildToolsVersion "21.1.2"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 21
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
}
|
17
twidere.component.jsonserializer/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in /Users/mariotaku/Tools/android-sdk/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.jsonserializer;
|
||||
|
||||
import android.app.Application;
|
||||
import android.test.ApplicationTestCase;
|
||||
|
||||
/**
|
||||
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
|
||||
*/
|
||||
public class ApplicationTest extends ApplicationTestCase<Application> {
|
||||
public ApplicationTest() {
|
||||
super(Application.class);
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
<!--
|
||||
~ 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/>.
|
||||
-->
|
||||
|
||||
<manifest package="org.mariotaku.jsonserializer"/>
|
After Width: | Height: | Size: 9.2 KiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 19 KiB |
@ -0,0 +1,22 @@
|
||||
<!--
|
||||
~ 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/>.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<string name="app_name">twidere.component.jsonserializer</string>
|
||||
</resources>
|
1
twidere.component.querybuilder/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/build
|
42
twidere.component.querybuilder/build.gradle
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 21
|
||||
buildToolsVersion "21.1.2"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 21
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
}
|
17
twidere.component.querybuilder/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in /Users/mariotaku/Tools/android-sdk/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.twiderecomponentsqlquerybuilder;
|
||||
|
||||
import android.app.Application;
|
||||
import android.test.ApplicationTestCase;
|
||||
|
||||
/**
|
||||
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
|
||||
*/
|
||||
public class ApplicationTest extends ApplicationTestCase<Application> {
|
||||
public ApplicationTest() {
|
||||
super(Application.class);
|
||||
}
|
||||
}
|
20
twidere.component.querybuilder/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<!--
|
||||
~ 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/>.
|
||||
-->
|
||||
|
||||
<manifest package="org.mariotaku.querybuilder"/>
|
@ -28,8 +28,6 @@
|
||||
package org.mariotaku.querybuilder;
|
||||
|
||||
|
||||
import org.mariotaku.twidere.util.ArrayUtils;
|
||||
|
||||
public class OrderBy implements SQLLang {
|
||||
|
||||
private final String[] orderBy;
|
||||
@ -40,7 +38,7 @@ public class OrderBy implements SQLLang {
|
||||
|
||||
@Override
|
||||
public String getSQL() {
|
||||
return ArrayUtils.toString(orderBy, ',', false);
|
||||
return Utils.toString(orderBy, ',', false);
|
||||
}
|
||||
|
||||
}
|
After Width: | Height: | Size: 9.2 KiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 19 KiB |
@ -0,0 +1,22 @@
|
||||
<!--
|
||||
~ 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/>.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<string name="app_name">twidere.component.sqlquerybuilder</string>
|
||||
</resources>
|
1
twidere.component.twitter4j.streaming/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/build
|
43
twidere.component.twitter4j.streaming/build.gradle
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 21
|
||||
buildToolsVersion "21.1.2"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 21
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile project(':twidere.component.twitter4j')
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
}
|
17
twidere.component.twitter4j.streaming/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in /Users/mariotaku/Tools/android-sdk/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.library.twitter4j.streaming;
|
||||
|
||||
import android.app.Application;
|
||||
import android.test.ApplicationTestCase;
|
||||
|
||||
/**
|
||||
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
|
||||
*/
|
||||
public class ApplicationTest extends ApplicationTestCase<Application> {
|
||||
public ApplicationTest() {
|
||||
super(Application.class);
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
<!--
|
||||
~ 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/>.
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.mariotaku.twidere.library.twitter4j.streaming">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
|
||||
<application/>
|
||||
|
||||
</manifest>
|
@ -16,21 +16,23 @@
|
||||
|
||||
package twitter4j;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Mariotaku Lee
|
||||
* @since Twitter4J 2.2.5
|
||||
* @author Yusuke Yamamoto - yusuke at mac.com
|
||||
* @since Twitter4J 2.1.7
|
||||
*/
|
||||
public interface ExtendedEntitySupport extends EntitySupport {
|
||||
public interface ConnectionLifeCycleListener {
|
||||
/**
|
||||
* called before thread gets cleaned up
|
||||
*/
|
||||
void onCleanUp();
|
||||
|
||||
/**
|
||||
* Returns an array of MediaEntities if media are available in the tweet,
|
||||
* or null if no media is included in the tweet.
|
||||
*
|
||||
* @return an array of MediaEntities.
|
||||
* @since Twitter4J 2.2.3
|
||||
* called after connection was established
|
||||
*/
|
||||
MediaEntity[] getExtendedMediaEntities();
|
||||
void onConnect();
|
||||
|
||||
/**
|
||||
* called after connection was disconnected
|
||||
*/
|
||||
void onDisconnect();
|
||||
}
|
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 2007 Yusuke Yamamoto
|
||||
* Copyright (C) 2012 Twitter, Inc.
|
||||
*
|
||||
* 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;
|
||||
|
||||
import static twitter4j.internal.util.InternalParseUtil.getBoolean;
|
||||
import static twitter4j.internal.util.InternalParseUtil.getRawString;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* @author Yusuke Yamamoto - yusuke at twitter.com
|
||||
* @since Twitter4J 2.2.6
|
||||
*/
|
||||
public final class ControlStreamInfo implements Serializable {
|
||||
private static final long serialVersionUID = -6761659771734942177L;
|
||||
private final StreamController.User[] users;
|
||||
private final boolean includeFollowingsActivity;
|
||||
private final boolean includeUserChanges;
|
||||
private final String replies;
|
||||
private final String with;
|
||||
private transient final StreamController controller;
|
||||
|
||||
/* package */ControlStreamInfo(final StreamController controller, final JSONObject json) throws TwitterException {
|
||||
this.controller = controller;
|
||||
try {
|
||||
final JSONObject info = json.getJSONObject("info");
|
||||
includeFollowingsActivity = getBoolean("include_followings_activity", info);
|
||||
includeUserChanges = getBoolean("include_user_changes", info);
|
||||
replies = getRawString("replies", info);
|
||||
with = getRawString("with", info);
|
||||
final JSONArray usersJSON = info.getJSONArray("users");
|
||||
users = new StreamController.User[usersJSON.length()];
|
||||
for (int i = 0; i < usersJSON.length(); i++) {
|
||||
users[i] = this.controller.createUser(usersJSON.getJSONObject(i));
|
||||
}
|
||||
|
||||
} catch (final JSONException e) {
|
||||
throw new TwitterException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
final ControlStreamInfo that = (ControlStreamInfo) o;
|
||||
|
||||
if (includeFollowingsActivity != that.includeFollowingsActivity) return false;
|
||||
if (includeUserChanges != that.includeUserChanges) return false;
|
||||
if (replies != null ? !replies.equals(that.replies) : that.replies != null) return false;
|
||||
if (!Arrays.equals(users, that.users)) return false;
|
||||
if (with != null ? !with.equals(that.with) : that.with != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public StreamController.User[] getUsers() {
|
||||
return users;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = users != null ? Arrays.hashCode(users) : 0;
|
||||
result = 31 * result + (includeFollowingsActivity ? 1 : 0);
|
||||
result = 31 * result + (includeUserChanges ? 1 : 0);
|
||||
result = 31 * result + (replies != null ? replies.hashCode() : 0);
|
||||
result = 31 * result + (with != null ? with.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean isIncludeFollowingsActivity() {
|
||||
return includeFollowingsActivity;
|
||||
}
|
||||
|
||||
public boolean isIncludeUserChanges() {
|
||||
return includeUserChanges;
|
||||
}
|
||||
|
||||
public String isReplies() {
|
||||
return replies;
|
||||
}
|
||||
|
||||
public String isWith() {
|
||||
return with;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ControlStreamInfo{" + "users=" + (users == null ? null : Arrays.asList(users))
|
||||
+ ", includeFollowingsActivity=" + includeFollowingsActivity + ", includeUserChanges="
|
||||
+ includeUserChanges + ", replies='" + replies + '\'' + ", with='" + with + '\'' + '}';
|
||||
}
|
||||
}
|
@ -0,0 +1,205 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import twitter4j.http.HttpParameter;
|
||||
import twitter4j.internal.util.InternalStringUtil;
|
||||
|
||||
/**
|
||||
* @author Yusuke Yamamoto - yusuke at mac.com
|
||||
* @since Twitter4J 2.1.2
|
||||
*/
|
||||
public final class FilterQuery implements java.io.Serializable {
|
||||
private static final long serialVersionUID = 430966623248982833L;
|
||||
private int count;
|
||||
private long[] follow;
|
||||
private String[] track;
|
||||
private double[][] locations;
|
||||
|
||||
/**
|
||||
* Creates a new FilterQuery
|
||||
*/
|
||||
public FilterQuery() {
|
||||
count = 0;
|
||||
follow = null;
|
||||
track = null;
|
||||
locations = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new FilterQuery
|
||||
*
|
||||
* @param count Indicates the number of previous statuses to stream before
|
||||
* transitioning to the live stream.
|
||||
* @param follow Specifies the users, by ID, to receive public tweets from.
|
||||
*/
|
||||
public FilterQuery(final int count, final long[] follow) {
|
||||
this();
|
||||
this.count = count;
|
||||
this.follow = follow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new FilterQuery
|
||||
*
|
||||
* @param count Indicates the number of previous statuses to stream before
|
||||
* transitioning to the live stream.
|
||||
* @param follow Specifies the users, by ID, to receive public tweets from.
|
||||
* @param track Specifies keywords to track.
|
||||
*/
|
||||
public FilterQuery(final int count, final long[] follow, final String[] track) {
|
||||
this();
|
||||
this.count = count;
|
||||
this.follow = follow;
|
||||
this.track = track;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new FilterQuery
|
||||
*
|
||||
* @param count Indicates the number of previous statuses to stream before
|
||||
* transitioning to the live stream.
|
||||
* @param follow Specifies the users, by ID, to receive public tweets from.
|
||||
* @param track Specifies keywords to track.
|
||||
* @param locations Specifies the locations to track. 2D array
|
||||
*/
|
||||
public FilterQuery(final int count, final long[] follow, final String[] track, final double[][] locations) {
|
||||
this.count = count;
|
||||
this.follow = follow;
|
||||
this.track = track;
|
||||
this.locations = locations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new FilterQuery
|
||||
*
|
||||
* @param follow Specifies the users, by ID, to receive public tweets from.
|
||||
*/
|
||||
public FilterQuery(final long[] follow) {
|
||||
this();
|
||||
count = 0;
|
||||
this.follow = follow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets count
|
||||
*
|
||||
* @param count Indicates the number of previous statuses to stream before
|
||||
* transitioning to the live stream.
|
||||
* @return this instance
|
||||
*/
|
||||
public FilterQuery count(final int count) {
|
||||
this.count = count;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
final FilterQuery that = (FilterQuery) o;
|
||||
|
||||
if (count != that.count) return false;
|
||||
if (!Arrays.equals(follow, that.follow)) return false;
|
||||
if (!Arrays.equals(track, that.track)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets follow
|
||||
*
|
||||
* @param follow Specifies the users, by ID, to receive public tweets from.
|
||||
* @return this instance
|
||||
*/
|
||||
public FilterQuery follow(final long[] follow) {
|
||||
this.follow = follow;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = count;
|
||||
result = 31 * result + (follow != null ? Arrays.hashCode(follow) : 0);
|
||||
result = 31 * result + (track != null ? Arrays.hashCode(track) : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets locations
|
||||
*
|
||||
* @param locations Specifies the locations to track. 2D array
|
||||
* @return this instance
|
||||
*/
|
||||
public FilterQuery locations(final double[][] locations) {
|
||||
this.locations = locations;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FilterQuery{" + "count=" + count + ", follow=" + Arrays.toString(follow) + ", track="
|
||||
+ (track == null ? null : Arrays.asList(track)) + ", locations="
|
||||
+ (locations == null ? null : Arrays.asList(locations)) + '}';
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets track
|
||||
*
|
||||
* @param track Specifies keywords to track.
|
||||
* @return this instance
|
||||
*/
|
||||
public FilterQuery track(final String[] track) {
|
||||
this.track = track;
|
||||
return this;
|
||||
}
|
||||
|
||||
private String toLocationsString(final double[][] keywords) {
|
||||
final StringBuilder buf = new StringBuilder(20 * keywords.length * 2);
|
||||
for (final double[] keyword : keywords) {
|
||||
if (0 != buf.length()) {
|
||||
buf.append(",");
|
||||
}
|
||||
buf.append(keyword[0]);
|
||||
buf.append(",");
|
||||
buf.append(keyword[1]);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/* package */HttpParameter[] asHttpParameterArray(final HttpParameter stallWarningsParam) {
|
||||
final ArrayList<HttpParameter> params = new ArrayList<HttpParameter>();
|
||||
|
||||
params.add(new HttpParameter("count", count));
|
||||
if (follow != null && follow.length > 0) {
|
||||
params.add(new HttpParameter("follow", InternalStringUtil.join(follow)));
|
||||
}
|
||||
if (track != null && track.length > 0) {
|
||||
params.add(new HttpParameter("track", InternalStringUtil.join(track)));
|
||||
}
|
||||
if (locations != null && locations.length > 0) {
|
||||
params.add(new HttpParameter("locations", toLocationsString(locations)));
|
||||
}
|
||||
params.add(stallWarningsParam);
|
||||
final HttpParameter[] paramArray = new HttpParameter[params.size()];
|
||||
return params.toArray(paramArray);
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* @author Yusuke Yamamoto - yusuke at mac.com
|
||||
* @since Twitter4J 3.0.2
|
||||
*/
|
||||
public interface RawStreamListener extends StreamListener {
|
||||
void onMessage(String rawString);
|
||||
}
|