implementing twitter card support
This commit is contained in:
parent
5209ae8db6
commit
5c355a1b12
|
@ -7,7 +7,7 @@ android {
|
|||
defaultConfig {
|
||||
applicationId "org.mariotaku.twidere"
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 21
|
||||
targetSdkVersion 19
|
||||
versionCode 98
|
||||
versionName "0.3.0-dev"
|
||||
|
||||
|
@ -101,5 +101,6 @@ dependencies {
|
|||
compile project(':MenuComponent')
|
||||
compile project(':MessageBubbleView')
|
||||
compile project(':twidere.nyan')
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
compile fileTree(dir: 'libs/main', include: ['*.jar'])
|
||||
googleCompile fileTree(dir: 'libs/google', include: ['*.jar'])
|
||||
}
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* 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 org.json.JSONArray;
|
||||
import org.mariotaku.jsonserializer.JSONParcelable.Creator;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/1/1.
|
||||
*/
|
||||
public final class JSONArrayParcel {
|
||||
|
||||
private final JSONArray jsonArray;
|
||||
|
||||
JSONArrayParcel(JSONArray json) {
|
||||
if (json == null) throw new NullPointerException();
|
||||
jsonArray = json;
|
||||
}
|
||||
|
||||
public String readString(int index) {
|
||||
return jsonArray.optString(index);
|
||||
}
|
||||
|
||||
public <T extends JSONParcelable> T readParcelable(int index, Creator<T> creator) {
|
||||
final JSONParcel parcel = new JSONParcel(jsonArray.optJSONObject(index));
|
||||
return creator.createFromParcel(parcel);
|
||||
}
|
||||
|
||||
|
||||
public int size() {
|
||||
return jsonArray.length();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,377 @@
|
|||
/*
|
||||
* 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 org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public final class JSONParcel {
|
||||
|
||||
private final JSONObject jsonObject;
|
||||
|
||||
JSONParcel() {
|
||||
this(new JSONObject());
|
||||
}
|
||||
|
||||
JSONParcel(final JSONObject json) {
|
||||
if (json == null) throw new NullPointerException();
|
||||
jsonObject = json;
|
||||
}
|
||||
|
||||
public boolean contains(final String key) {
|
||||
return jsonObject.has(key);
|
||||
}
|
||||
|
||||
public JSONObject getJSON() {
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
public boolean isNull(String key) {
|
||||
return jsonObject.isNull(key);
|
||||
}
|
||||
|
||||
public boolean readBoolean(final String key) {
|
||||
return jsonObject.optBoolean(key);
|
||||
}
|
||||
|
||||
public boolean readBoolean(final String key, final boolean def) {
|
||||
return jsonObject.optBoolean(key, def);
|
||||
}
|
||||
|
||||
public double readDouble(final String key) {
|
||||
return jsonObject.optDouble(key);
|
||||
}
|
||||
|
||||
public double readDouble(final String key, final double def) {
|
||||
return jsonObject.optDouble(key, def);
|
||||
}
|
||||
|
||||
public float readFloat(final String key, final float def) {
|
||||
return (float) readDouble(key, def);
|
||||
}
|
||||
|
||||
public int readInt(final String key) {
|
||||
return jsonObject.optInt(key);
|
||||
}
|
||||
|
||||
public int readInt(final String key, final int def) {
|
||||
return jsonObject.optInt(key, def);
|
||||
}
|
||||
|
||||
public JSONObject readJSONObject(final String key) {
|
||||
return jsonObject.optJSONObject(key);
|
||||
}
|
||||
|
||||
public JSONArray readJSONArray(final String key) {
|
||||
return jsonObject.optJSONArray(key);
|
||||
}
|
||||
|
||||
public JSONArrayParcel readJSONArrayParcel(final String key) {
|
||||
if (jsonObject.isNull(key)) return null;
|
||||
return new JSONArrayParcel(readJSONArray(key));
|
||||
}
|
||||
|
||||
public String[] readStringArray(final String key) {
|
||||
if (jsonObject.isNull(key)) return null;
|
||||
final JSONArray array = jsonObject.optJSONArray(key);
|
||||
final String[] stringArray = new String[array.length()];
|
||||
for (int i = 0, j = array.length(); i < j; i++) {
|
||||
try {
|
||||
stringArray[i] = array.getString(i);
|
||||
} catch (JSONException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return stringArray;
|
||||
}
|
||||
|
||||
public long readLong(final String key) {
|
||||
return jsonObject.optLong(key);
|
||||
}
|
||||
|
||||
public long readLong(final String key, final long def) {
|
||||
return jsonObject.optLong(key, def);
|
||||
}
|
||||
|
||||
public Object readObject(final String key) {
|
||||
return jsonObject.opt(key);
|
||||
}
|
||||
|
||||
public <T extends JSONParcelable> T readParcelable(final String key, final JSONParcelable.Creator<T> creator) {
|
||||
return JSONSerializer.createObject(creator, jsonObject.optJSONObject(key));
|
||||
}
|
||||
|
||||
public <T extends JSONParcelable> T[] readParcelableArray(final String key, final JSONParcelable.Creator<T> creator) {
|
||||
return JSONSerializer.createArray(creator, jsonObject.optJSONArray(key));
|
||||
}
|
||||
|
||||
public String readString(final String key) {
|
||||
return readString(key, null);
|
||||
}
|
||||
|
||||
public String readString(final String key, final String def) {
|
||||
return jsonObject.optString(key, def);
|
||||
}
|
||||
|
||||
public void writeBoolean(final String key, final boolean value) {
|
||||
try {
|
||||
jsonObject.put(key, value);
|
||||
} catch (final JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void writeBooleanArray(final String key, final boolean[] value) {
|
||||
if (key == null) return;
|
||||
try {
|
||||
if (value == null) {
|
||||
jsonObject.put(key, JSONObject.NULL);
|
||||
return;
|
||||
}
|
||||
final JSONArray array = new JSONArray();
|
||||
for (final boolean item : value) {
|
||||
array.put(item);
|
||||
}
|
||||
jsonObject.put(key, array);
|
||||
} catch (final JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void writeDouble(final String key, final double value) {
|
||||
try {
|
||||
jsonObject.put(key, value);
|
||||
} catch (final JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void writeDoubleArray(final String key, final double[] value) {
|
||||
if (key == null) return;
|
||||
try {
|
||||
if (value == null) {
|
||||
jsonObject.put(key, JSONObject.NULL);
|
||||
return;
|
||||
}
|
||||
final JSONArray array = new JSONArray();
|
||||
for (final double item : value) {
|
||||
array.put(item);
|
||||
}
|
||||
jsonObject.put(key, array);
|
||||
} catch (final JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void writeFloat(final String key, final float value) {
|
||||
writeDouble(key, value);
|
||||
}
|
||||
|
||||
public void writeFloatArray(final String key, final float[] value) {
|
||||
try {
|
||||
if (value == null) {
|
||||
jsonObject.put(key, JSONObject.NULL);
|
||||
return;
|
||||
}
|
||||
final JSONArray array = new JSONArray();
|
||||
for (final float item : value) {
|
||||
array.put(item);
|
||||
}
|
||||
jsonObject.put(key, array);
|
||||
} catch (final JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void writeInt(final String key, final int value) {
|
||||
try {
|
||||
jsonObject.put(key, value);
|
||||
} catch (final JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void writeIntArray(final String key, final int[] value) {
|
||||
if (key == null) return;
|
||||
try {
|
||||
if (value == null) {
|
||||
jsonObject.put(key, JSONObject.NULL);
|
||||
return;
|
||||
}
|
||||
final JSONArray array = new JSONArray();
|
||||
for (final int item : value) {
|
||||
array.put(item);
|
||||
}
|
||||
jsonObject.put(key, array);
|
||||
} catch (final JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void writeJSONArray(final String key, final JSONArray value) {
|
||||
try {
|
||||
jsonObject.put(key, value);
|
||||
} catch (final JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void writeJSONObject(final String key, final JSONObject value) {
|
||||
try {
|
||||
jsonObject.put(key, value);
|
||||
} catch (final JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void writeLong(final String key, final long value) {
|
||||
try {
|
||||
jsonObject.put(key, value);
|
||||
} catch (final JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void writeLongArray(final String key, final long[] value) {
|
||||
if (key == null) return;
|
||||
try {
|
||||
if (value == null) {
|
||||
jsonObject.put(key, JSONObject.NULL);
|
||||
return;
|
||||
}
|
||||
final JSONArray array = new JSONArray();
|
||||
for (final long item : value) {
|
||||
array.put(item);
|
||||
}
|
||||
jsonObject.put(key, array);
|
||||
} catch (final JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void writeObject(final String key, final Object value) {
|
||||
if (value instanceof JSONParcelable) {
|
||||
writeParcelable(key, (JSONParcelable) value);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
jsonObject.put(key, value);
|
||||
} catch (final JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void writeObjectArray(final String key, final Object[] value) {
|
||||
if (key == null) return;
|
||||
try {
|
||||
if (value == null) {
|
||||
jsonObject.put(key, JSONObject.NULL);
|
||||
return;
|
||||
}
|
||||
final JSONArray array = new JSONArray();
|
||||
for (final Object item : value) {
|
||||
if (item instanceof JSONParcelable) {
|
||||
final JSONObject json = JSONSerializer.toJSONObject((JSONParcelable) item);
|
||||
array.put(json);
|
||||
} else {
|
||||
array.put(item);
|
||||
}
|
||||
}
|
||||
jsonObject.put(key, array);
|
||||
} catch (final JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void writeObjectList(final String key, final List<Object> value) {
|
||||
if (key == null) return;
|
||||
writeObjectArray(key, value.toArray());
|
||||
}
|
||||
|
||||
public <T extends JSONParcelable> void writeParcelable(final String key, final T value) {
|
||||
if (key == null) return;
|
||||
try {
|
||||
if (value == null) {
|
||||
jsonObject.put(key, JSONObject.NULL);
|
||||
return;
|
||||
}
|
||||
final JSONObject json = JSONSerializer.toJSONObject(value);
|
||||
jsonObject.put(key, json);
|
||||
} catch (final JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public <T extends JSONParcelable> void writeParcelableArray(final String key, final T[] value) {
|
||||
if (key == null) return;
|
||||
try {
|
||||
if (value == null) {
|
||||
jsonObject.put(key, JSONObject.NULL);
|
||||
return;
|
||||
}
|
||||
final JSONArray array = new JSONArray();
|
||||
for (final T item : value) {
|
||||
final JSONObject json = JSONSerializer.toJSONObject(item);
|
||||
array.put(json != null ? json : JSONObject.NULL);
|
||||
}
|
||||
jsonObject.put(key, array);
|
||||
} catch (final JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void writeString(final String key, final String value) {
|
||||
if (key == null) return;
|
||||
try {
|
||||
jsonObject.put(key, value);
|
||||
} catch (final JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void writeStringArray(final String key, final String[] value) {
|
||||
if (key == null) return;
|
||||
try {
|
||||
if (value == null) {
|
||||
jsonObject.put(key, JSONObject.NULL);
|
||||
return;
|
||||
}
|
||||
final JSONArray array = new JSONArray();
|
||||
for (final String item : value) {
|
||||
array.put(item);
|
||||
}
|
||||
jsonObject.put(key, array);
|
||||
} catch (final JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void writeValue(final String key, final Object value) {
|
||||
if (key == null) return;
|
||||
try {
|
||||
jsonObject.put(key, value);
|
||||
} catch (final JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/**
|
||||
* This is free and unencumbered software released into the public domain.
|
||||
*
|
||||
* Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
* distribute this software, either in source code form or as a compiled
|
||||
* binary, for any purpose, commercial or non-commercial, and by any
|
||||
* means.
|
||||
*
|
||||
* In jurisdictions that recognize copyright laws, the author or authors
|
||||
* of this software dedicate any and all copyright interest in the
|
||||
* software to the public domain. We make this dedication for the benefit
|
||||
* of the public at large and to the detriment of our heirs and
|
||||
* successors. We intend this dedication to be an overt act of
|
||||
* relinquishment in perpetuity of all present and future rights to this
|
||||
* software under copyright law.
|
||||
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* For more information, please refer to <http://unlicense.org/>
|
||||
*/
|
||||
|
||||
package org.mariotaku.jsonserializer;
|
||||
|
||||
public interface JSONParcelable {
|
||||
|
||||
public void writeToParcel(JSONParcel out);
|
||||
|
||||
public interface Creator<T extends JSONParcelable> {
|
||||
|
||||
public T createFromParcel(JSONParcel in);
|
||||
|
||||
public T[] newArray(int size);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* 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 org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class JSONSerializer {
|
||||
private static boolean debugMode = false;
|
||||
|
||||
public static <T extends JSONParcelable> T[] createArray(final JSONParcelable.Creator<T> creator,
|
||||
final JSONArray json) {
|
||||
if (creator == null) throw new NullPointerException("JSON_CREATOR must not be null!");
|
||||
if (json == null) return null;
|
||||
final int size = json.length();
|
||||
final T[] array = creator.newArray(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
array[i] = creator.createFromParcel(new JSONParcel(json.optJSONObject(i)));
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public static <T extends JSONParcelable> ArrayList<T> createArrayList(final JSONParcelable.Creator<T> creator,
|
||||
final JSONArray json) {
|
||||
if (creator == null) throw new NullPointerException("JSON_CREATOR must not be null!");
|
||||
if (json == null) return null;
|
||||
final int size = json.length();
|
||||
final ArrayList<T> list = new ArrayList<T>(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
list.add(creator.createFromParcel(new JSONParcel(json.optJSONObject(i))));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static <T extends JSONParcelable> T createObject(final JSONParcelable.Creator<T> creator,
|
||||
final JSONObject json) {
|
||||
if (creator == null) throw new NullPointerException("JSON_CREATOR must not be null!");
|
||||
if (json == null) return null;
|
||||
return creator.createFromParcel(new JSONParcel(json));
|
||||
}
|
||||
|
||||
public static <T extends JSONParcelable> byte[] getByteArray(final T parcelable) {
|
||||
final JSONObject json = toJSONObject(parcelable);
|
||||
final String string = jsonToString(json);
|
||||
if (string == null) return null;
|
||||
return string.getBytes(Charset.defaultCharset());
|
||||
}
|
||||
|
||||
public static <T extends JSONParcelable> byte[] getByteArray(final T[] array) {
|
||||
final JSONArray json = toJSONArray(array);
|
||||
final String string = jsonToString(json);
|
||||
if (string == null) return null;
|
||||
return string.getBytes(Charset.defaultCharset());
|
||||
}
|
||||
|
||||
public static boolean isDebugMode() {
|
||||
return debugMode;
|
||||
}
|
||||
|
||||
public static void setIsDebugMode(final boolean debug) {
|
||||
debugMode = debug;
|
||||
}
|
||||
|
||||
public static <T extends JSONParcelable> byte[] toByteArray(final T parcelable) throws IOException {
|
||||
final String jsonString = jsonToString(toJSONObject(parcelable));
|
||||
if (jsonString == null) return null;
|
||||
return jsonString.getBytes(Charset.defaultCharset());
|
||||
}
|
||||
|
||||
public static <T extends JSONParcelable> byte[] toByteArray(final T[] array) throws IOException {
|
||||
final String jsonString = jsonToString(toJSONArray(array));
|
||||
if (jsonString == null) return null;
|
||||
return jsonString.getBytes(Charset.defaultCharset());
|
||||
}
|
||||
|
||||
public static <T extends JSONParcelable> JSONArray toJSONArray(final T[] array) {
|
||||
if (array == null) return null;
|
||||
final JSONArray json = new JSONArray();
|
||||
for (final T parcelable : array) {
|
||||
json.put(toJSONObject(parcelable));
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
public static <T extends JSONParcelable> String toJSONArrayString(final T[] array) {
|
||||
return jsonToString(toJSONArray(array));
|
||||
}
|
||||
|
||||
public static <T extends JSONParcelable> JSONObject toJSONObject(final T parcelable) {
|
||||
if (parcelable == null) return null;
|
||||
final JSONObject json = new JSONObject();
|
||||
parcelable.writeToParcel(new JSONParcel(json));
|
||||
return json;
|
||||
}
|
||||
|
||||
public static <T extends JSONParcelable> String toJSONObjectString(final T parcelable) {
|
||||
return jsonToString(toJSONObject(parcelable));
|
||||
}
|
||||
|
||||
static String jsonToString(final JSONArray json) {
|
||||
if (json == null) return null;
|
||||
if (debugMode) {
|
||||
try {
|
||||
return json.toString(4);
|
||||
} catch (final JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return json.toString();
|
||||
} else
|
||||
return json.toString();
|
||||
}
|
||||
|
||||
static String jsonToString(final JSONObject json) {
|
||||
if (json == null) return null;
|
||||
if (debugMode) {
|
||||
try {
|
||||
return json.toString(4);
|
||||
} catch (final JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return json.toString();
|
||||
} else
|
||||
return json.toString();
|
||||
}
|
||||
|
||||
}
|
|
@ -28,7 +28,7 @@ package org.mariotaku.twidere;
|
|||
public interface Constants extends TwidereConstants {
|
||||
|
||||
public static final String DATABASES_NAME = "twidere.sqlite";
|
||||
public static final int DATABASES_VERSION = 75;
|
||||
public static final int DATABASES_VERSION = 76;
|
||||
|
||||
public static final int MENU_GROUP_STATUS_EXTENSION = 10;
|
||||
public static final int MENU_GROUP_COMPOSE_EXTENSION = 11;
|
||||
|
|
|
@ -1208,8 +1208,13 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa
|
|||
final ImageLoaderWrapper loader = application.getImageLoaderWrapper();
|
||||
final ImageLoadingHandler handler = new ImageLoadingHandler(R.id.media_preview_progress);
|
||||
final AsyncTwitterWrapper twitter = getTwitterWrapper();
|
||||
final SharedPreferencesWrapper preferences = SharedPreferencesWrapper.getInstance(activity,
|
||||
SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
final ParcelableStatus status = args.getParcelable(EXTRA_STATUS);
|
||||
mHolder.displayStatus(activity, loader, handler, twitter, status);
|
||||
final int profileImageStyle = Utils.getProfileImageStyle(preferences.getString(KEY_PROFILE_IMAGE_STYLE, null));
|
||||
final int mediaPreviewStyle = Utils.getMediaPreviewStyle(preferences.getString(KEY_MEDIA_PREVIEW_STYLE, null));
|
||||
mHolder.displayStatus(activity, loader, handler, twitter, profileImageStyle,
|
||||
mediaPreviewStyle, status, null);
|
||||
mStatusContainer.findViewById(R.id.item_menu).setVisibility(View.GONE);
|
||||
mStatusContainer.findViewById(R.id.action_buttons).setVisibility(View.GONE);
|
||||
mStatusContainer.findViewById(R.id.reply_retweet_status).setVisibility(View.GONE);
|
||||
|
|
|
@ -45,9 +45,15 @@ public abstract class AbsStatusesAdapter<D> extends Adapter<ViewHolder> implemen
|
|||
private final AsyncTwitterWrapper mTwitterWrapper;
|
||||
private final int mCardBackgroundColor;
|
||||
private final int mTextSize;
|
||||
private final int mProfileImageStyle, mMediaPreviewStyle;
|
||||
private boolean mLoadMoreIndicatorEnabled;
|
||||
private StatusAdapterListener mStatusAdapterListener;
|
||||
|
||||
@Override
|
||||
public int getMediaPreviewStyle() {
|
||||
return mMediaPreviewStyle;
|
||||
}
|
||||
|
||||
public AbsStatusesAdapter(Context context, boolean compact) {
|
||||
mContext = context;
|
||||
final TwidereApplication app = TwidereApplication.getInstance(context);
|
||||
|
@ -56,13 +62,21 @@ public abstract class AbsStatusesAdapter<D> extends Adapter<ViewHolder> implemen
|
|||
mImageLoader = app.getImageLoaderWrapper();
|
||||
mLoadingHandler = new ImageLoadingHandler(R.id.media_preview_progress);
|
||||
mTwitterWrapper = app.getTwitterWrapper();
|
||||
final SharedPreferencesWrapper preferences = SharedPreferencesWrapper.getInstance(context, SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
final SharedPreferencesWrapper preferences = SharedPreferencesWrapper.getInstance(context,
|
||||
SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
mTextSize = preferences.getInt(KEY_TEXT_SIZE, context.getResources().getInteger(R.integer.default_text_size));
|
||||
if (compact) {
|
||||
mCardLayoutResource = R.layout.card_item_status_compat;
|
||||
} else {
|
||||
mCardLayoutResource = R.layout.card_item_status;
|
||||
}
|
||||
mProfileImageStyle = Utils.getProfileImageStyle(preferences.getString(KEY_PROFILE_IMAGE_STYLE, null));
|
||||
mMediaPreviewStyle = Utils.getMediaPreviewStyle(preferences.getString(KEY_MEDIA_PREVIEW_STYLE, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProfileImageStyle() {
|
||||
return mProfileImageStyle;
|
||||
}
|
||||
|
||||
public abstract D getData();
|
||||
|
|
|
@ -102,7 +102,7 @@ public class BaseArrayAdapter<T> extends ArrayAdapter<T> implements IBaseAdapter
|
|||
@Override
|
||||
public void onSharedPreferenceChanged(final SharedPreferences preferences, final String key) {
|
||||
if (KEY_NICKNAME_ONLY.equals(key) || KEY_DISPLAY_PROFILE_IMAGE.equals(key)
|
||||
|| KEY_DISPLAY_IMAGE_PREVIEW.equals(key) || KEY_DISPLAY_SENSITIVE_CONTENTS.equals(key)) {
|
||||
|| KEY_MEDIA_PREVIEW_STYLE.equals(key) || KEY_DISPLAY_SENSITIVE_CONTENTS.equals(key)) {
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package org.mariotaku.twidere.adapter;
|
|||
import android.content.Context;
|
||||
|
||||
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
import org.mariotaku.twidere.view.holder.StatusViewHolder;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -40,6 +41,11 @@ public class ParcelableStatusesAdapter extends AbsStatusesAdapter<List<Parcelabl
|
|||
return mData.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMediaPreviewStyle() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void setData(List<ParcelableStatus> data) {
|
||||
mData = data;
|
||||
notifyDataSetChanged();
|
||||
|
|
|
@ -23,6 +23,10 @@ public interface IStatusesAdapter<Data> extends IGapSupportedAdapter, ICardSuppo
|
|||
|
||||
int getStatusCount();
|
||||
|
||||
int getProfileImageStyle();
|
||||
|
||||
int getMediaPreviewStyle();
|
||||
|
||||
void onStatusClick(StatusViewHolder holder, int position);
|
||||
|
||||
void onUserProfileClick(StatusViewHolder holder, int position);
|
||||
|
|
|
@ -69,6 +69,7 @@ public interface IntentConstants {
|
|||
|
||||
public static final String INTENT_ACTION_UPDATE_STATUS = INTENT_PACKAGE_PREFIX + "UPDATE_STATUS";
|
||||
public static final String INTENT_ACTION_SEND_DIRECT_MESSAGE = INTENT_PACKAGE_PREFIX + "SEND_DIRECT_MESSAGE";
|
||||
public static final String INTENT_ACTION_DISCARD_DRAFT = INTENT_PACKAGE_PREFIX + "DISCARD_DRAFT";
|
||||
public static final String INTENT_ACTION_PICK_ACTIVITY = "org.mariotaku.twidere.PICK_ACTIVITY";
|
||||
|
||||
public static final String BROADCAST_NOTIFICATION_DELETED = INTENT_PACKAGE_PREFIX + "NOTIFICATION_DELETED";
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
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;
|
||||
|
@ -46,6 +47,14 @@ public interface SharedPreferenceConstants {
|
|||
public static final int VALUE_LINK_HIGHLIGHT_OPTION_CODE_BOTH = VALUE_LINK_HIGHLIGHT_OPTION_CODE_HIGHLIGHT
|
||||
| VALUE_LINK_HIGHLIGHT_OPTION_CODE_UNDERLINE;
|
||||
|
||||
public static final String VALUE_MEDIA_PREVIEW_STYLE_CROP = "crop";
|
||||
public static final String VALUE_MEDIA_PREVIEW_STYLE_SCALE = "scale";
|
||||
public static final String VALUE_MEDIA_PREVIEW_STYLE_NONE = VALUE_NONE;
|
||||
|
||||
public static final int VALUE_MEDIA_PREVIEW_STYLE_CODE_CROP = 1;
|
||||
public static final int VALUE_MEDIA_PREVIEW_STYLE_CODE_SCALE = 2;
|
||||
public static final int VALUE_MEDIA_PREVIEW_STYLE_CODE_NONE = 0;
|
||||
|
||||
public static final String VALUE_THEME_FONT_FAMILY_REGULAR = "sans-serif";
|
||||
public static final String VALUE_THEME_FONT_FAMILY_CONDENSED = "sans-serif-condensed";
|
||||
public static final String VALUE_THEME_FONT_FAMILY_LIGHT = "sans-serif-light";
|
||||
|
@ -76,6 +85,9 @@ public interface SharedPreferenceConstants {
|
|||
public static final String VALUE_THEME_NAME_DARK = "dark";
|
||||
public static final String VALUE_THEME_NAME_LIGHT = "light";
|
||||
|
||||
public static final String VALUE_PROFILE_IMAGE_STYLE_ROUND = "round";
|
||||
public static final String VALUE_PROFILE_IMAGE_STYLE_SQUARE = "square";
|
||||
|
||||
public static final String VALUE_COMPOSE_NOW_ACTION_COMPOSE = "compose";
|
||||
public static final String VALUE_COMPOSE_NOW_ACTION_TAKE_PHOTO = "take_photo";
|
||||
public static final String VALUE_COMPOSE_NOW_ACTION_PICK_IMAGE = "pick_image";
|
||||
|
@ -122,7 +134,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)
|
||||
@Preference(type = INT, hasDefault = true, defaultResource = R.integer.default_text_size)
|
||||
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";
|
||||
|
@ -138,8 +150,6 @@ public interface SharedPreferenceConstants {
|
|||
public static final String KEY_THEME_FONT_FAMILY = "theme_font_family";
|
||||
@Preference(type = BOOLEAN, hasDefault = true, defaultBoolean = true)
|
||||
public static final String KEY_DISPLAY_PROFILE_IMAGE = "display_profile_image";
|
||||
@Preference(type = BOOLEAN, hasDefault = true, defaultBoolean = false)
|
||||
public static final String KEY_DISPLAY_IMAGE_PREVIEW = "display_image_preview";
|
||||
@Preference(type = BOOLEAN)
|
||||
public static final String KEY_LEFTSIDE_COMPOSE_BUTTON = "leftside_compose_button";
|
||||
@Preference(type = BOOLEAN)
|
||||
|
@ -274,10 +284,13 @@ public interface SharedPreferenceConstants {
|
|||
@Preference(type = STRING, hasDefault = true, defaultString = VALUE_COMPOSE_NOW_ACTION_COMPOSE)
|
||||
public static final String KEY_COMPOSE_NOW_ACTION = "compose_now_action";
|
||||
public static final String KEY_FALLBACK_TWITTER_LINK_HANDLER = "fallback_twitter_link_handler";
|
||||
@Preference(type = STRING, hasDefault = true, defaultString = "CENTER_CROP")
|
||||
public static final String KEY_IMAGE_PREVIEW_SCALE_TYPE = "image_preview_scale_type";
|
||||
|
||||
@Preference(type = STRING, hasDefault = true, defaultString = VALUE_MEDIA_PREVIEW_STYLE_CROP)
|
||||
public static final String KEY_MEDIA_PREVIEW_STYLE = "media_preview_style";
|
||||
@Preference(type = BOOLEAN, hasDefault = true, defaultBoolean = false)
|
||||
public static final String KEY_SORT_TIMELINE_BY_ID = "sort_timeline_by_id";
|
||||
@Preference(type = STRING, hasDefault = true)
|
||||
public static final String KEY_PROFILE_IMAGE_STYLE = "profile_image_style";
|
||||
|
||||
public static final String KEY_QUICK_MENU_EXPANDED = "quick_menu_expanded";
|
||||
|
||||
|
|
|
@ -32,14 +32,14 @@ import org.mariotaku.twidere.util.webkit.DefaultWebViewClient;
|
|||
@SuppressLint("SetJavaScriptEnabled")
|
||||
public class BaseWebViewFragment extends WebViewFragment implements Constants {
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(final Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
final WebView view = getWebView();
|
||||
view.setWebViewClient(new DefaultWebViewClient(getActivity()));
|
||||
final WebSettings settings = view.getSettings();
|
||||
settings.setBuiltInZoomControls(true);
|
||||
settings.setJavaScriptEnabled(true);
|
||||
WebSettingsAccessor.setAllowUniversalAccessFromFileURLs(settings, true);
|
||||
}
|
||||
@Override
|
||||
public void onActivityCreated(final Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
final WebView view = getWebView();
|
||||
view.setWebViewClient(new DefaultWebViewClient(getActivity()));
|
||||
final WebSettings settings = view.getSettings();
|
||||
settings.setBuiltInZoomControls(true);
|
||||
settings.setJavaScriptEnabled(true);
|
||||
WebSettingsAccessor.setAllowUniversalAccessFromFileURLs(settings, true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@ import org.mariotaku.twidere.adapter.AbsStatusesAdapter;
|
|||
import org.mariotaku.twidere.adapter.AbsStatusesAdapter.StatusAdapterListener;
|
||||
import org.mariotaku.twidere.adapter.decorator.DividerItemDecoration;
|
||||
import org.mariotaku.twidere.app.TwidereApplication;
|
||||
import org.mariotaku.twidere.constant.IntentConstants;
|
||||
import org.mariotaku.twidere.fragment.iface.RefreshScrollTopInterface;
|
||||
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||
|
@ -193,9 +192,9 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
|
|||
switch (id) {
|
||||
case R.id.reply_count: {
|
||||
final Context context = getActivity();
|
||||
final Intent intent = new Intent(IntentConstants.INTENT_ACTION_REPLY);
|
||||
final Intent intent = new Intent(INTENT_ACTION_REPLY);
|
||||
intent.setPackage(context.getPackageName());
|
||||
intent.putExtra(IntentConstants.EXTRA_STATUS, status);
|
||||
intent.putExtra(EXTRA_STATUS, status);
|
||||
context.startActivity(intent);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -528,10 +528,8 @@ public class DirectMessagesConversationFragment extends BaseSupportFragment impl
|
|||
public void onResume() {
|
||||
super.onResume();
|
||||
configBaseCardAdapter(getActivity(), mAdapter);
|
||||
final boolean displayImagePreview = mPreferences.getBoolean(KEY_DISPLAY_IMAGE_PREVIEW, false);
|
||||
final String previewScaleType = Utils.getNonEmptyString(mPreferences, KEY_IMAGE_PREVIEW_SCALE_TYPE,
|
||||
final String previewScaleType = Utils.getNonEmptyString(mPreferences, KEY_MEDIA_PREVIEW_STYLE,
|
||||
ScaleType.CENTER_CROP.name());
|
||||
mAdapter.setDisplayImagePreview(displayImagePreview);
|
||||
mAdapter.setImagePreviewScaleType(previewScaleType);
|
||||
mAdapter.notifyDataSetChanged();
|
||||
mLoadMoreAutomatically = mPreferences.getBoolean(KEY_LOAD_MORE_AUTOMATICALLY, false);
|
||||
|
|
|
@ -36,7 +36,9 @@ import org.mariotaku.twidere.model.ParcelableStatus;
|
|||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||
import org.mariotaku.twidere.util.ImageLoaderWrapper;
|
||||
import org.mariotaku.twidere.util.ImageLoadingHandler;
|
||||
import org.mariotaku.twidere.util.SharedPreferencesWrapper;
|
||||
import org.mariotaku.twidere.util.ThemeUtils;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
import org.mariotaku.twidere.view.holder.StatusViewHolder;
|
||||
|
||||
import static org.mariotaku.twidere.util.Utils.isMyRetweet;
|
||||
|
@ -70,13 +72,16 @@ public class RetweetQuoteDialogFragment extends BaseSupportDialogFragment implem
|
|||
final Context wrapped = ThemeUtils.getDialogThemedContext(getActivity());
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(wrapped);
|
||||
final Context context = builder.getContext();
|
||||
final SharedPreferencesWrapper preferences = SharedPreferencesWrapper.getInstance(context,
|
||||
SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
final ImageLoaderWrapper loader = TwidereApplication.getInstance(context).getImageLoaderWrapper();
|
||||
final ImageLoadingHandler handler = new ImageLoadingHandler(R.id.media_preview_progress);
|
||||
final AsyncTwitterWrapper twitter = getTwitterWrapper();
|
||||
final LayoutInflater inflater = LayoutInflater.from(context);
|
||||
@SuppressLint("InflateParams") final View view = inflater.inflate(R.layout.dialog_scrollable_status, null);
|
||||
final StatusViewHolder holder = new StatusViewHolder(view.findViewById(R.id.item_content));
|
||||
|
||||
final int profileImageStyle = Utils.getProfileImageStyle(preferences.getString(KEY_PROFILE_IMAGE_STYLE, null));
|
||||
final int mediaPreviewStyle = Utils.getMediaPreviewStyle(preferences.getString(KEY_MEDIA_PREVIEW_STYLE, null));
|
||||
final ParcelableStatus status = getStatus();
|
||||
|
||||
builder.setView(view);
|
||||
|
@ -86,7 +91,8 @@ public class RetweetQuoteDialogFragment extends BaseSupportDialogFragment implem
|
|||
builder.setNegativeButton(android.R.string.cancel, null);
|
||||
|
||||
|
||||
holder.displayStatus(context, loader, handler, twitter, getStatus());
|
||||
holder.displayStatus(context, loader, handler, twitter, profileImageStyle, mediaPreviewStyle,
|
||||
getStatus(), null);
|
||||
view.findViewById(R.id.item_menu).setVisibility(View.GONE);
|
||||
view.findViewById(R.id.action_buttons).setVisibility(View.GONE);
|
||||
view.findViewById(R.id.reply_retweet_status).setVisibility(View.GONE);
|
||||
|
|
|
@ -31,6 +31,8 @@ import android.os.Bundle;
|
|||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.support.v4.app.LoaderManager.LoaderCallbacks;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.support.v4.util.Pair;
|
||||
|
@ -50,6 +52,7 @@ import android.view.MenuItem.OnMenuItemClickListener;
|
|||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.Space;
|
||||
|
@ -58,9 +61,11 @@ import android.widget.TextView;
|
|||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.activity.support.AccountSelectorActivity;
|
||||
import org.mariotaku.twidere.activity.support.ColorPickerDialogActivity;
|
||||
import org.mariotaku.twidere.adapter.AbsStatusesAdapter.StatusAdapterListener;
|
||||
import org.mariotaku.twidere.adapter.decorator.DividerItemDecoration;
|
||||
import org.mariotaku.twidere.adapter.iface.IStatusesAdapter;
|
||||
import org.mariotaku.twidere.app.TwidereApplication;
|
||||
import org.mariotaku.twidere.constant.IntentConstants;
|
||||
import org.mariotaku.twidere.loader.ParcelableStatusLoader;
|
||||
import org.mariotaku.twidere.loader.support.StatusRepliesLoader;
|
||||
import org.mariotaku.twidere.model.ListResponse;
|
||||
|
@ -86,6 +91,7 @@ import org.mariotaku.twidere.util.Utils;
|
|||
import org.mariotaku.twidere.view.ShapedImageView;
|
||||
import org.mariotaku.twidere.view.StatusTextView;
|
||||
import org.mariotaku.twidere.view.TwidereMenuBar;
|
||||
import org.mariotaku.twidere.view.holder.GapViewHolder;
|
||||
import org.mariotaku.twidere.view.holder.LoadIndicatorViewHolder;
|
||||
import org.mariotaku.twidere.view.holder.StatusViewHolder;
|
||||
|
||||
|
@ -117,26 +123,21 @@ import static org.mariotaku.twidere.util.Utils.startStatusShareChooser;
|
|||
* Created by mariotaku on 14/12/5.
|
||||
*/
|
||||
public class StatusFragment extends BaseSupportFragment
|
||||
implements LoaderCallbacks<SingleResponse<ParcelableStatus>>, OnMediaClickListener {
|
||||
implements LoaderCallbacks<SingleResponse<ParcelableStatus>>, OnMediaClickListener, StatusAdapterListener {
|
||||
|
||||
private static final int LOADER_ID_DETAIL_STATUS = 1;
|
||||
private static final int LOADER_ID_STATUS_REPLIES = 2;
|
||||
|
||||
private static final int STATE_LOADED = 1;
|
||||
private static final int STATE_LOADING = 2;
|
||||
private static final int STATE_ERROR = 3;
|
||||
|
||||
private RecyclerView mRecyclerView;
|
||||
private StatusAdapter mStatusAdapter;
|
||||
private boolean mRepliesLoaderInitialized;
|
||||
|
||||
private LoadConversationTask mLoadConversationTask;
|
||||
|
||||
private LinearLayoutManager mLayoutManager;
|
||||
private View mStatusContent;
|
||||
private View mProgressContainer;
|
||||
private View mErrorContainer;
|
||||
|
||||
private LoaderCallbacks<List<ParcelableStatus>> mRepliesLoaderCallback = new LoaderCallbacks<List<ParcelableStatus>>() {
|
||||
@Override
|
||||
public Loader<List<ParcelableStatus>> onCreateLoader(int id, Bundle args) {
|
||||
|
@ -196,14 +197,6 @@ public class StatusFragment extends BaseSupportFragment
|
|||
return inflater.inflate(R.layout.fragment_status, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Loader<SingleResponse<ParcelableStatus>> onCreateLoader(final int id, final Bundle args) {
|
||||
final Bundle fragmentArgs = getArguments();
|
||||
final long accountId = fragmentArgs.getLong(EXTRA_ACCOUNT_ID, -1);
|
||||
final long statusId = fragmentArgs.getLong(EXTRA_STATUS_ID, -1);
|
||||
return new ParcelableStatusLoader(getActivity(), false, fragmentArgs, accountId, statusId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
@ -219,6 +212,7 @@ public class StatusFragment extends BaseSupportFragment
|
|||
mRecyclerView.setLayoutManager(mLayoutManager);
|
||||
mRecyclerView.setClipToPadding(false);
|
||||
mStatusAdapter = new StatusAdapter(this, compact);
|
||||
mStatusAdapter.setEventListener(this);
|
||||
mRecyclerView.setAdapter(mStatusAdapter);
|
||||
|
||||
setState(STATE_LOADING);
|
||||
|
@ -226,11 +220,84 @@ public class StatusFragment extends BaseSupportFragment
|
|||
getLoaderManager().initLoader(LOADER_ID_DETAIL_STATUS, getArguments(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGapClick(GapViewHolder holder, int position) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatusActionClick(StatusViewHolder holder, int id, int position) {
|
||||
final ParcelableStatus status = mStatusAdapter.getStatus(position);
|
||||
if (status == null) return;
|
||||
switch (id) {
|
||||
case R.id.reply_count: {
|
||||
final Context context = getActivity();
|
||||
final Intent intent = new Intent(IntentConstants.INTENT_ACTION_REPLY);
|
||||
intent.setPackage(context.getPackageName());
|
||||
intent.putExtra(IntentConstants.EXTRA_STATUS, status);
|
||||
context.startActivity(intent);
|
||||
break;
|
||||
}
|
||||
case R.id.retweet_count: {
|
||||
RetweetQuoteDialogFragment.show(getFragmentManager(), status);
|
||||
break;
|
||||
}
|
||||
case R.id.favorite_count: {
|
||||
final AsyncTwitterWrapper twitter = getTwitterWrapper();
|
||||
if (twitter == null) return;
|
||||
if (status.is_favorite) {
|
||||
twitter.destroyFavoriteAsync(status.account_id, status.id);
|
||||
} else {
|
||||
twitter.createFavoriteAsync(status.account_id, status.id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatusClick(StatusViewHolder holder, int position) {
|
||||
openStatus(getActivity(), mStatusAdapter.getStatus(position), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatusMenuClick(StatusViewHolder holder, int position) {
|
||||
final Bundle args = new Bundle();
|
||||
args.putParcelable(EXTRA_STATUS, mStatusAdapter.getStatus(position));
|
||||
final StatusMenuDialogFragment f = new StatusMenuDialogFragment();
|
||||
f.setArguments(args);
|
||||
f.show(getActivity().getSupportFragmentManager(), "status_menu");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Loader<SingleResponse<ParcelableStatus>> onCreateLoader(final int id, final Bundle args) {
|
||||
final Bundle fragmentArgs = getArguments();
|
||||
final long accountId = fragmentArgs.getLong(EXTRA_ACCOUNT_ID, -1);
|
||||
final long statusId = fragmentArgs.getLong(EXTRA_STATUS_ID, -1);
|
||||
return new ParcelableStatusLoader(getActivity(), false, fragmentArgs, accountId, statusId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMediaClick(View view, ParcelableMedia media, long accountId) {
|
||||
Utils.openImageDirectly(getActivity(), accountId, media.url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
mStatusContent = view.findViewById(R.id.status_content);
|
||||
mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
|
||||
mProgressContainer = view.findViewById(R.id.progress_container);
|
||||
mErrorContainer = view.findViewById(R.id.error_retry_container);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fitSystemWindows(Rect insets) {
|
||||
super.fitSystemWindows(insets);
|
||||
// mRecyclerView.setPadding(insets.left, insets.top, insets.right, insets.bottom);
|
||||
getView().setPadding(insets.left, insets.top, insets.right, insets.bottom);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(final Loader<SingleResponse<ParcelableStatus>> loader,
|
||||
final SingleResponse<ParcelableStatus> data) {
|
||||
|
@ -256,28 +323,6 @@ public class StatusFragment extends BaseSupportFragment
|
|||
}
|
||||
}
|
||||
|
||||
private void setState(int state) {
|
||||
mStatusContent.setVisibility(state == STATE_LOADED ? View.VISIBLE : View.GONE);
|
||||
mProgressContainer.setVisibility(state == STATE_LOADING ? View.VISIBLE : View.GONE);
|
||||
mErrorContainer.setVisibility(state == STATE_ERROR ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
mStatusContent = view.findViewById(R.id.status_content);
|
||||
mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
|
||||
mProgressContainer = view.findViewById(R.id.progress_container);
|
||||
mErrorContainer = view.findViewById(R.id.error_retry_container);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fitSystemWindows(Rect insets) {
|
||||
super.fitSystemWindows(insets);
|
||||
// mRecyclerView.setPadding(insets.left, insets.top, insets.right, insets.bottom);
|
||||
getView().setPadding(insets.left, insets.top, insets.right, insets.bottom);
|
||||
}
|
||||
|
||||
private void loadConversation(ParcelableStatus status) {
|
||||
if (mLoadConversationTask != null && mLoadConversationTask.getStatus() == Status.RUNNING) {
|
||||
mLoadConversationTask.cancel(true);
|
||||
|
@ -300,11 +345,6 @@ public class StatusFragment extends BaseSupportFragment
|
|||
mRepliesLoaderInitialized = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(final Loader<SingleResponse<ParcelableStatus>> loader) {
|
||||
|
||||
}
|
||||
|
||||
private void setConversation(List<ParcelableStatus> data) {
|
||||
if (mLayoutManager.getChildCount() != 0) {
|
||||
final long itemId = mStatusAdapter.getItemId(mLayoutManager.findFirstVisibleItemPosition());
|
||||
|
@ -329,6 +369,12 @@ public class StatusFragment extends BaseSupportFragment
|
|||
}
|
||||
}
|
||||
|
||||
private void setState(int state) {
|
||||
mStatusContent.setVisibility(state == STATE_LOADED ? View.VISIBLE : View.GONE);
|
||||
mProgressContainer.setVisibility(state == STATE_LOADING ? View.VISIBLE : View.GONE);
|
||||
mErrorContainer.setVisibility(state == STATE_ERROR ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
private static class StatusAdapter extends Adapter<ViewHolder> implements IStatusesAdapter<List<ParcelableStatus>> {
|
||||
|
||||
private static final int VIEW_TYPE_DETAIL_STATUS = 0;
|
||||
|
@ -352,6 +398,8 @@ public class StatusFragment extends BaseSupportFragment
|
|||
private ParcelableCredentials mStatusAccount;
|
||||
private List<ParcelableStatus> mConversation, mReplies;
|
||||
private boolean mDetailMediaExpanded;
|
||||
private StatusAdapterListener mStatusAdapterListener;
|
||||
private DetailStatusViewHolder mCachedHolder;
|
||||
|
||||
public StatusAdapter(StatusFragment fragment, boolean compact) {
|
||||
final Context context = fragment.getActivity();
|
||||
|
@ -412,22 +460,26 @@ public class StatusFragment extends BaseSupportFragment
|
|||
}
|
||||
}
|
||||
|
||||
public ParcelableCredentials getStatusAccount() {
|
||||
return mStatusAccount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStatusCount() {
|
||||
return getConversationCount() + 1 + getRepliesCount() + 1;
|
||||
}
|
||||
|
||||
public float getTextSize() {
|
||||
return mTextSize;
|
||||
@Override
|
||||
public int getProfileImageStyle() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatusClick(StatusViewHolder holder, int position) {
|
||||
openStatus(mFragment.getActivity(), getStatus(position), null);
|
||||
public int getMediaPreviewStyle() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onStatusClick(StatusViewHolder holder, int position) {
|
||||
if (mStatusAdapterListener != null) {
|
||||
mStatusAdapterListener.onStatusClick(holder, position);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -445,20 +497,16 @@ public class StatusFragment extends BaseSupportFragment
|
|||
return mFragment.getTwitterWrapper();
|
||||
}
|
||||
|
||||
public float getTextSize() {
|
||||
return mTextSize;
|
||||
}
|
||||
|
||||
public ParcelableStatus getStatus() {
|
||||
return mStatus;
|
||||
}
|
||||
|
||||
public boolean setStatus(ParcelableStatus status) {
|
||||
final ParcelableStatus old = mStatus;
|
||||
mStatus = status;
|
||||
if (status != null) {
|
||||
mStatusAccount = ParcelableAccount.getCredentials(mContext, status.account_id);
|
||||
} else {
|
||||
mStatusAccount = null;
|
||||
}
|
||||
notifyDataSetChanged();
|
||||
return !CompareUtils.objectEquals(old, status);
|
||||
public ParcelableCredentials getStatusAccount() {
|
||||
return mStatusAccount;
|
||||
}
|
||||
|
||||
public boolean isDetailMediaExpanded() {
|
||||
|
@ -476,8 +524,10 @@ public class StatusFragment extends BaseSupportFragment
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onGapClick(ViewHolder holder, int position) {
|
||||
|
||||
public final void onGapClick(ViewHolder holder, int position) {
|
||||
if (mStatusAdapterListener != null) {
|
||||
mStatusAdapterListener.onGapClick((GapViewHolder) holder, position);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isNameFirst() {
|
||||
|
@ -488,10 +538,27 @@ public class StatusFragment extends BaseSupportFragment
|
|||
return mNicknameOnly;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewDetachedFromWindow(ViewHolder holder) {
|
||||
super.onViewDetachedFromWindow(holder);
|
||||
if (holder instanceof DetailStatusViewHolder) {
|
||||
mCachedHolder = (DetailStatusViewHolder) holder;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewAttachedToWindow(ViewHolder holder) {
|
||||
super.onViewAttachedToWindow(holder);
|
||||
if (mCachedHolder == holder) {
|
||||
mCachedHolder = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
switch (viewType) {
|
||||
case VIEW_TYPE_DETAIL_STATUS: {
|
||||
if (mCachedHolder != null) return mCachedHolder;
|
||||
final View view = mInflater.inflate(R.layout.header_status, parent, false);
|
||||
final CardView cardView = (CardView) view.findViewById(R.id.card);
|
||||
if (cardView != null) {
|
||||
|
@ -575,12 +642,16 @@ public class StatusFragment extends BaseSupportFragment
|
|||
|
||||
@Override
|
||||
public void onItemActionClick(ViewHolder holder, int id, int position) {
|
||||
|
||||
if (mStatusAdapterListener != null) {
|
||||
mStatusAdapterListener.onStatusActionClick((StatusViewHolder) holder, id, position);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemMenuClick(ViewHolder holder, int position) {
|
||||
|
||||
if (mStatusAdapterListener != null) {
|
||||
mStatusAdapterListener.onStatusMenuClick((StatusViewHolder) holder, position);
|
||||
}
|
||||
}
|
||||
|
||||
public void setConversation(List<ParcelableStatus> conversation) {
|
||||
|
@ -588,11 +659,27 @@ public class StatusFragment extends BaseSupportFragment
|
|||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void setEventListener(StatusAdapterListener listener) {
|
||||
mStatusAdapterListener = listener;
|
||||
}
|
||||
|
||||
public void setReplies(List<ParcelableStatus> replies) {
|
||||
mReplies = replies;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public boolean setStatus(ParcelableStatus status) {
|
||||
final ParcelableStatus old = mStatus;
|
||||
mStatus = status;
|
||||
if (status != null) {
|
||||
mStatusAccount = ParcelableAccount.getCredentials(mContext, status.account_id);
|
||||
} else {
|
||||
mStatusAccount = null;
|
||||
}
|
||||
notifyDataSetChanged();
|
||||
return !CompareUtils.objectEquals(old, status);
|
||||
}
|
||||
|
||||
private int getConversationCount() {
|
||||
return mConversation != null ? mConversation.size() : 1;
|
||||
}
|
||||
|
@ -602,6 +689,10 @@ public class StatusFragment extends BaseSupportFragment
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(final Loader<SingleResponse<ParcelableStatus>> loader) {
|
||||
|
||||
}
|
||||
|
||||
static class LoadConversationTask extends TwidereAsyncTask<ParcelableStatus, ParcelableStatus,
|
||||
ListResponse<ParcelableStatus>> {
|
||||
|
@ -680,6 +771,7 @@ public class StatusFragment extends BaseSupportFragment
|
|||
private final LinearLayout mediaPreviewGrid;
|
||||
|
||||
private final View locationContainer;
|
||||
private final FrameLayout twitterCard;
|
||||
|
||||
public DetailStatusViewHolder(StatusAdapter adapter, View itemView) {
|
||||
super(itemView);
|
||||
|
@ -704,6 +796,7 @@ public class StatusFragment extends BaseSupportFragment
|
|||
mediaPreviewGrid = (LinearLayout) itemView.findViewById(R.id.media_preview_grid);
|
||||
locationContainer = itemView.findViewById(R.id.location_container);
|
||||
profileContainer = itemView.findViewById(R.id.profile_container);
|
||||
twitterCard = (FrameLayout) itemView.findViewById(R.id.twitter_card);
|
||||
|
||||
setIsRecyclable(false);
|
||||
initViews();
|
||||
|
@ -839,6 +932,7 @@ public class StatusFragment extends BaseSupportFragment
|
|||
|
||||
public void showStatus(ParcelableStatus status) {
|
||||
if (status == null) return;
|
||||
final StatusFragment fragment = adapter.getFragment();
|
||||
final Context context = adapter.getContext();
|
||||
final Resources resources = context.getResources();
|
||||
final ImageLoaderWrapper loader = adapter.getImageLoader();
|
||||
|
@ -912,6 +1006,20 @@ public class StatusFragment extends BaseSupportFragment
|
|||
mediaPreviewGrid.setVisibility(View.GONE);
|
||||
mediaPreviewGrid.removeAllViews();
|
||||
}
|
||||
|
||||
if (Utils.isCardSupported(status.card)) {
|
||||
twitterCard.setVisibility(View.VISIBLE);
|
||||
final Fragment cardFragment = Utils.createTwitterCardFragment(status.card);
|
||||
final FragmentManager fm = fragment.getChildFragmentManager();
|
||||
final FragmentTransaction ft = fm.beginTransaction();
|
||||
ft.replace(R.id.twitter_card, cardFragment);
|
||||
ft.commit();
|
||||
} else {
|
||||
twitterCard.setVisibility(View.GONE);
|
||||
final FragmentManager fm = fragment.getChildFragmentManager();
|
||||
// final FragmentTransaction ft = fm.beginTransaction();
|
||||
}
|
||||
|
||||
setMenuForStatus(context, menuBar.getMenu(), status, adapter.getStatusAccount());
|
||||
menuBar.show();
|
||||
}
|
||||
|
@ -942,13 +1050,6 @@ public class StatusFragment extends BaseSupportFragment
|
|||
this.recyclerView = recyclerView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOrientation(int orientation) {
|
||||
if (orientation != VERTICAL)
|
||||
throw new IllegalArgumentException("Only VERTICAL orientation supported");
|
||||
super.setOrientation(orientation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDecoratedMeasuredHeight(View child) {
|
||||
final int height = super.getDecoratedMeasuredHeight(child);
|
||||
|
@ -974,6 +1075,13 @@ public class StatusFragment extends BaseSupportFragment
|
|||
return height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOrientation(int orientation) {
|
||||
if (orientation != VERTICAL)
|
||||
throw new IllegalArgumentException("Only VERTICAL orientation supported");
|
||||
super.setOrientation(orientation);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ import org.mariotaku.twidere.model.SingleResponse;
|
|||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||
import org.mariotaku.twidere.util.ImageLoaderWrapper;
|
||||
import org.mariotaku.twidere.util.ImageLoadingHandler;
|
||||
import org.mariotaku.twidere.util.SharedPreferencesWrapper;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
import org.mariotaku.twidere.view.holder.StatusViewHolder;
|
||||
|
||||
|
@ -130,7 +131,12 @@ public class StatusTranslateDialogFragment extends BaseSupportDialogFragment imp
|
|||
final ImageLoaderWrapper loader = application.getImageLoaderWrapper();
|
||||
final ImageLoadingHandler handler = new ImageLoadingHandler(R.id.media_preview_progress);
|
||||
final AsyncTwitterWrapper twitter = getTwitterWrapper();
|
||||
mHolder.displayStatus(activity, loader, handler, twitter, status);
|
||||
final SharedPreferencesWrapper preferences = SharedPreferencesWrapper.getInstance(activity,
|
||||
SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
final int profileImageStyle = Utils.getProfileImageStyle(preferences.getString(KEY_PROFILE_IMAGE_STYLE, null));
|
||||
final int mediaPreviewStyle = Utils.getMediaPreviewStyle(preferences.getString(KEY_MEDIA_PREVIEW_STYLE, null));
|
||||
mHolder.displayStatus(activity, loader, handler, twitter, profileImageStyle,
|
||||
mediaPreviewStyle, status, null);
|
||||
mStatusContainer.findViewById(R.id.item_menu).setVisibility(View.GONE);
|
||||
mStatusContainer.findViewById(R.id.action_buttons).setVisibility(View.GONE);
|
||||
mStatusContainer.findViewById(R.id.reply_retweet_status).setVisibility(View.GONE);
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.fragment.support;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.webkit.WebView;
|
||||
|
||||
import org.mariotaku.twidere.util.ParseUtils;
|
||||
|
||||
public class SupportBrowserFragment extends BaseSupportWebViewFragment {
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(final Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
final Bundle args = getArguments();
|
||||
final Object uri = args != null ? args.get(EXTRA_URI) : null;
|
||||
final WebView view = getWebView();
|
||||
view.loadUrl(ParseUtils.parseString(uri, "about:blank"));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,20 +1,17 @@
|
|||
/*
|
||||
* 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/>.
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* 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 org.mariotaku.twidere.fragment.support;
|
||||
|
@ -26,18 +23,76 @@ import android.view.View;
|
|||
import android.view.ViewGroup;
|
||||
import android.webkit.WebView;
|
||||
|
||||
import org.mariotaku.twidere.R;
|
||||
|
||||
/**
|
||||
* A fragment that displays a WebView.
|
||||
* <p/>
|
||||
* The WebView is automically paused or resumed when the Fragment is paused or resumed.
|
||||
*/
|
||||
public class SupportWebViewFragment extends Fragment {
|
||||
private WebView mWebView;
|
||||
private boolean mIsWebViewAvailable;
|
||||
|
||||
public final WebView getWebView() {
|
||||
final View view = getView();
|
||||
return (WebView) view.findViewById(R.id.webview);
|
||||
}
|
||||
public SupportWebViewFragment() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_webview, container, false);
|
||||
}
|
||||
/**
|
||||
* Called to instantiate the view. Creates and returns the WebView.
|
||||
*/
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
if (mWebView != null) {
|
||||
mWebView.destroy();
|
||||
}
|
||||
mWebView = new WebView(getActivity());
|
||||
mIsWebViewAvailable = true;
|
||||
return mWebView;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the fragment is visible to the user and actively running. Resumes the WebView.
|
||||
*/
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
mWebView.onPause();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the fragment is no longer resumed. Pauses the WebView.
|
||||
*/
|
||||
@Override
|
||||
public void onResume() {
|
||||
mWebView.onResume();
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the WebView has been detached from the fragment.
|
||||
* The WebView is no longer available after this time.
|
||||
*/
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
mIsWebViewAvailable = false;
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the fragment is no longer in use. Destroys the internal state of the WebView.
|
||||
*/
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
if (mWebView != null) {
|
||||
mWebView.destroy();
|
||||
mWebView = null;
|
||||
}
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the WebView.
|
||||
*/
|
||||
public WebView getWebView() {
|
||||
return mIsWebViewAvailable ? mWebView : null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,17 @@ public class UserFavoritesFragment extends ParcelableStatusesFragment {
|
|||
final String screenName = args.getString(EXTRA_SCREEN_NAME);
|
||||
final int tabPosition = args.getInt(EXTRA_TAB_POSITION, -1);
|
||||
return new UserFavoritesLoader(context, accountId, userId, screenName, maxId, sinceId,
|
||||
getAdapterData(), null, tabPosition);
|
||||
getAdapterData(), getSavedStatusesFileArgs(), tabPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] getSavedStatusesFileArgs() {
|
||||
final Bundle args = getArguments();
|
||||
if (args == null) return null;
|
||||
final long accountId = args.getLong(EXTRA_ACCOUNT_ID, -1);
|
||||
final long userId = args.getLong(EXTRA_USER_ID, -1);
|
||||
final String screenName = args.getString(EXTRA_SCREEN_NAME);
|
||||
return new String[]{AUTHORITY_USER_FAVORITES, "account" + accountId, "user" + userId, "name" + screenName};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -48,4 +48,17 @@ public class UserListTimelineFragment extends ParcelableStatusesFragment {
|
|||
listName, maxId, sinceId, getAdapterData(), getSavedStatusesFileArgs(), tabPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] getSavedStatusesFileArgs() {
|
||||
final Bundle args = getArguments();
|
||||
if (args == null) return null;
|
||||
final int listId = args.getInt(EXTRA_LIST_ID, -1);
|
||||
final long accountId = args.getLong(EXTRA_ACCOUNT_ID, -1);
|
||||
final long userId = args.getLong(EXTRA_USER_ID, -1);
|
||||
final String screenName = args.getString(EXTRA_SCREEN_NAME);
|
||||
final String listName = args.getString(EXTRA_LIST_NAME);
|
||||
return new String[]{AUTHORITY_USER_LIST_TIMELINE, "account" + accountId, "list_id" + listId,
|
||||
"list_name" + listName, "user_id" + userId, "screen_name" + screenName};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -45,7 +45,16 @@ public class UserTimelineFragment extends ParcelableStatusesFragment {
|
|||
final String screenName = args.getString(EXTRA_SCREEN_NAME);
|
||||
final int tabPosition = args.getInt(EXTRA_TAB_POSITION, -1);
|
||||
return new UserTimelineLoader(context, accountId, userId, screenName, maxId, sinceId, data,
|
||||
null, tabPosition);
|
||||
getSavedStatusesFileArgs(), tabPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] getSavedStatusesFileArgs() {
|
||||
final Bundle args = getArguments();
|
||||
if (args == null) return null;
|
||||
final long accountId = args.getLong(EXTRA_ACCOUNT_ID, -1);
|
||||
final long userId = args.getLong(EXTRA_USER_ID, -1);
|
||||
final String screenName = args.getString(EXTRA_SCREEN_NAME);
|
||||
return new String[]{AUTHORITY_USER_TIMELINE, "account" + accountId, "user" + userId + "name" + screenName};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,9 +24,13 @@ import android.database.Cursor;
|
|||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.json.JSONException;
|
||||
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.util.ParseUtils;
|
||||
|
||||
|
@ -34,6 +38,11 @@ import java.util.Arrays;
|
|||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
|
||||
import twitter4j.CardEntity;
|
||||
import twitter4j.CardEntity.BindingValue;
|
||||
import twitter4j.CardEntity.ImageValue;
|
||||
import twitter4j.CardEntity.StringValue;
|
||||
import twitter4j.CardEntity.UserValue;
|
||||
import twitter4j.Status;
|
||||
import twitter4j.User;
|
||||
|
||||
|
@ -109,6 +118,8 @@ public class ParcelableStatus implements TwidereParcelable, Comparable<Parcelabl
|
|||
|
||||
public final ParcelableMedia[] media;
|
||||
|
||||
public final ParcelableCardEntity card;
|
||||
|
||||
public ParcelableStatus(final ContentValues values) {
|
||||
id = getAsLong(values, Statuses.STATUS_ID, -1);
|
||||
account_id = getAsLong(values, Statuses.ACCOUNT_ID, -1);
|
||||
|
@ -147,6 +158,7 @@ public class ParcelableStatus implements TwidereParcelable, Comparable<Parcelabl
|
|||
user_is_following = 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));
|
||||
}
|
||||
|
||||
public ParcelableStatus(final Cursor c, final CursorIndices idx) {
|
||||
|
@ -190,6 +202,7 @@ public class ParcelableStatus implements TwidereParcelable, Comparable<Parcelabl
|
|||
user_is_following = idx.is_following != -1 && c.getInt(idx.is_following) == 1;
|
||||
mentions = idx.mentions != -1 ? ParcelableUserMention.fromJSONString(c.getString(idx.mentions)) : null;
|
||||
first_media = idx.first_media != -1 ? c.getString(idx.first_media) : null;
|
||||
card = idx.card != -1 ? ParcelableCardEntity.fromJSONString(c.getString(idx.card)) : null;
|
||||
}
|
||||
|
||||
public ParcelableStatus(final JSONParcel in) {
|
||||
|
@ -230,6 +243,7 @@ public class ParcelableStatus implements TwidereParcelable, Comparable<Parcelabl
|
|||
user_is_following = in.readBoolean("is_following");
|
||||
mentions = in.readParcelableArray("mentions", ParcelableUserMention.JSON_CREATOR);
|
||||
first_media = media != null && media.length > 0 ? media[0].url : null;
|
||||
card = in.readParcelable("card", ParcelableCardEntity.JSON_CREATOR);
|
||||
}
|
||||
|
||||
public ParcelableStatus(final Parcel in) {
|
||||
|
@ -270,6 +284,7 @@ public class ParcelableStatus implements TwidereParcelable, Comparable<Parcelabl
|
|||
in_reply_to_name = in.readString();
|
||||
mentions = in.createTypedArray(ParcelableUserMention.CREATOR);
|
||||
first_media = media != null && media.length > 0 ? media[0].url : null;
|
||||
card = in.readParcelable(ParcelableCardEntity.class.getClassLoader());
|
||||
}
|
||||
|
||||
public ParcelableStatus(final ParcelableStatus orig, final long override_my_retweet_id,
|
||||
|
@ -311,6 +326,7 @@ public class ParcelableStatus implements TwidereParcelable, Comparable<Parcelabl
|
|||
in_reply_to_name = orig.in_reply_to_name;
|
||||
mentions = orig.mentions;
|
||||
first_media = orig.first_media;
|
||||
card = orig.card;
|
||||
}
|
||||
|
||||
public ParcelableStatus(final Status orig, final long account_id, final boolean is_gap) {
|
||||
|
@ -352,10 +368,11 @@ public class ParcelableStatus implements TwidereParcelable, Comparable<Parcelabl
|
|||
location = new ParcelableLocation(status.getGeoLocation());
|
||||
is_favorite = status.isFavorited();
|
||||
text_unescaped = toPlainText(text_html);
|
||||
my_retweet_id = retweeted_by_id == account_id ? id : -1;
|
||||
my_retweet_id = retweeted_by_id == account_id ? id : status.getCurrentUserRetweet();
|
||||
is_possibly_sensitive = status.isPossiblySensitive();
|
||||
mentions = ParcelableUserMention.fromUserMentionEntities(status.getUserMentionEntities());
|
||||
first_media = media != null && media.length > 0 ? media[0].url : null;
|
||||
card = ParcelableCardEntity.fromCardEntity(status.getCard(), account_id);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -470,6 +487,7 @@ public class ParcelableStatus implements TwidereParcelable, Comparable<Parcelabl
|
|||
out.writeBoolean("is_possibly_sensitive", is_possibly_sensitive);
|
||||
out.writeBoolean("is_following", user_is_following);
|
||||
out.writeParcelableArray("mentions", mentions);
|
||||
out.writeParcelable("card", card);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -510,6 +528,7 @@ public class ParcelableStatus implements TwidereParcelable, Comparable<Parcelabl
|
|||
out.writeLong(in_reply_to_user_id);
|
||||
out.writeString(in_reply_to_name);
|
||||
out.writeTypedArray(mentions, flags);
|
||||
out.writeParcelable(card, flags);
|
||||
}
|
||||
|
||||
private static long getTime(final Date date) {
|
||||
|
@ -524,7 +543,8 @@ public class ParcelableStatus implements TwidereParcelable, Comparable<Parcelabl
|
|||
in_reply_to_user_name, in_reply_to_user_screen_name, my_retweet_id, retweeted_by_user_name,
|
||||
retweeted_by_user_screen_name, retweeted_by_user_profile_image, retweet_id, retweet_timestamp,
|
||||
retweeted_by_user_id, user_id, source, retweet_count, favorite_count, reply_count,
|
||||
descendent_reply_count, is_possibly_sensitive, is_following, media, first_media, mentions;
|
||||
descendent_reply_count, is_possibly_sensitive, is_following, media, first_media, mentions,
|
||||
card;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
@ -608,7 +628,317 @@ public class ParcelableStatus implements TwidereParcelable, Comparable<Parcelabl
|
|||
media = cursor.getColumnIndex(Statuses.MEDIA);
|
||||
first_media = cursor.getColumnIndex(Statuses.FIRST_MEDIA);
|
||||
mentions = cursor.getColumnIndex(Statuses.MENTIONS);
|
||||
card = cursor.getColumnIndex(Statuses.MENTIONS);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static final class ParcelableCardEntity implements TwidereParcelable {
|
||||
|
||||
public static ParcelableValueItem getValue(ParcelableCardEntity entity, String key) {
|
||||
for (ParcelableValueItem item : entity.values) {
|
||||
if (item.name.equals(key)) return item;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<ParcelableCardEntity> CREATOR = new Parcelable.Creator<ParcelableCardEntity>() {
|
||||
@Override
|
||||
public ParcelableCardEntity createFromParcel(final Parcel in) {
|
||||
return new ParcelableCardEntity(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParcelableCardEntity[] newArray(final int size) {
|
||||
return new ParcelableCardEntity[size];
|
||||
}
|
||||
};
|
||||
|
||||
public static final JSONParcelable.Creator<ParcelableCardEntity> JSON_CREATOR = new JSONParcelable.Creator<ParcelableCardEntity>() {
|
||||
@Override
|
||||
public ParcelableCardEntity createFromParcel(final JSONParcel in) {
|
||||
return new ParcelableCardEntity(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParcelableCardEntity[] newArray(final int size) {
|
||||
return new ParcelableCardEntity[size];
|
||||
}
|
||||
};
|
||||
|
||||
public final String name;
|
||||
public final ParcelableUser[] users;
|
||||
public final ParcelableValueItem[] values;
|
||||
|
||||
public ParcelableCardEntity(Parcel src) {
|
||||
name = src.readString();
|
||||
values = src.createTypedArray(ParcelableValueItem.CREATOR);
|
||||
users = src.createTypedArray(ParcelableUser.CREATOR);
|
||||
}
|
||||
|
||||
public ParcelableCardEntity(JSONParcel src) {
|
||||
name = src.readString("name");
|
||||
values = src.readParcelableArray("values", ParcelableValueItem.JSON_CREATOR);
|
||||
users = src.readParcelableArray("users", ParcelableUser.JSON_CREATOR);
|
||||
}
|
||||
|
||||
public ParcelableCardEntity(CardEntity card, long account_id) {
|
||||
name = card.getName();
|
||||
users = ParcelableUser.fromUsersArray(card.gerUsers(), account_id);
|
||||
final BindingValue[] bindingValues = card.getBindingValues();
|
||||
if (bindingValues != null) {
|
||||
values = new ParcelableValueItem[bindingValues.length];
|
||||
for (int i = 0, j = bindingValues.length; i < j; i++) {
|
||||
values[i] = new ParcelableValueItem(bindingValues[i]);
|
||||
}
|
||||
} else {
|
||||
values = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static ParcelableCardEntity fromCardEntity(CardEntity card, long account_id) {
|
||||
if (card == null) return null;
|
||||
return new ParcelableCardEntity(card, account_id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(name);
|
||||
dest.writeTypedArray(values, flags);
|
||||
dest.writeTypedArray(users, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(JSONParcel dest) {
|
||||
dest.writeString("name", name);
|
||||
dest.writeParcelableArray("values", values);
|
||||
dest.writeParcelableArray("users", users);
|
||||
}
|
||||
|
||||
|
||||
public static ParcelableCardEntity fromJSONString(final String json) {
|
||||
if (TextUtils.isEmpty(json)) return null;
|
||||
try {
|
||||
return JSONSerializer.createObject(JSON_CREATOR, new JSONObject(json));
|
||||
} catch (final JSONException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static final class ParcelableValueItem implements TwidereParcelable {
|
||||
|
||||
public static final Parcelable.Creator<ParcelableValueItem> CREATOR = new Parcelable.Creator<ParcelableValueItem>() {
|
||||
@Override
|
||||
public ParcelableValueItem createFromParcel(final Parcel in) {
|
||||
return new ParcelableValueItem(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParcelableValueItem[] newArray(final int size) {
|
||||
return new ParcelableValueItem[size];
|
||||
}
|
||||
};
|
||||
|
||||
public static final JSONParcelable.Creator<ParcelableValueItem> JSON_CREATOR = new JSONParcelable.Creator<ParcelableValueItem>() {
|
||||
@Override
|
||||
public ParcelableValueItem createFromParcel(final JSONParcel in) {
|
||||
return new ParcelableValueItem(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParcelableValueItem[] newArray(final int size) {
|
||||
return new ParcelableValueItem[size];
|
||||
}
|
||||
};
|
||||
public final String name, type;
|
||||
public final Object value;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
this.value = in.readValue(ParcelableValueItem.class.getClassLoader());
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(name);
|
||||
dest.writeString(type);
|
||||
dest.writeValue(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(JSONParcel dest) {
|
||||
dest.writeString("name", name);
|
||||
dest.writeString("type", type);
|
||||
dest.writeObject("value", value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static final class ParcelableUserValue implements TwidereParcelable {
|
||||
|
||||
public static final Parcelable.Creator<ParcelableUserValue> CREATOR = new Parcelable.Creator<ParcelableUserValue>() {
|
||||
@Override
|
||||
public ParcelableUserValue createFromParcel(final Parcel in) {
|
||||
return new ParcelableUserValue(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParcelableUserValue[] newArray(final int size) {
|
||||
return new ParcelableUserValue[size];
|
||||
}
|
||||
};
|
||||
|
||||
public static final JSONParcelable.Creator<ParcelableUserValue> JSON_CREATOR = new JSONParcelable.Creator<ParcelableUserValue>() {
|
||||
@Override
|
||||
public ParcelableUserValue createFromParcel(final JSONParcel in) {
|
||||
return new ParcelableUserValue(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParcelableUserValue[] newArray(final int size) {
|
||||
return new ParcelableUserValue[size];
|
||||
}
|
||||
};
|
||||
public final long id;
|
||||
|
||||
public ParcelableUserValue(JSONParcel in) {
|
||||
this.id = in.readLong("id");
|
||||
}
|
||||
|
||||
public ParcelableUserValue(Parcel in) {
|
||||
this.id = in.readLong();
|
||||
}
|
||||
|
||||
public ParcelableUserValue(UserValue value) {
|
||||
this.id = value.getUserId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeLong(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(JSONParcel dest) {
|
||||
dest.writeLong("id", id);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ParcelableImageValue implements TwidereParcelable {
|
||||
|
||||
public static final Parcelable.Creator<ParcelableImageValue> CREATOR = new Parcelable.Creator<ParcelableImageValue>() {
|
||||
@Override
|
||||
public ParcelableImageValue createFromParcel(final Parcel in) {
|
||||
return new ParcelableImageValue(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParcelableImageValue[] newArray(final int size) {
|
||||
return new ParcelableImageValue[size];
|
||||
}
|
||||
};
|
||||
|
||||
public static final JSONParcelable.Creator<ParcelableImageValue> JSON_CREATOR = new JSONParcelable.Creator<ParcelableImageValue>() {
|
||||
@Override
|
||||
public ParcelableImageValue createFromParcel(final JSONParcel in) {
|
||||
return new ParcelableImageValue(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParcelableImageValue[] newArray(final int size) {
|
||||
return new ParcelableImageValue[size];
|
||||
}
|
||||
};
|
||||
public final int width, height;
|
||||
public final String url;
|
||||
|
||||
public ParcelableImageValue(JSONParcel in) {
|
||||
this.width = in.readInt("width");
|
||||
this.height = in.readInt("height");
|
||||
this.url = in.readString("url");
|
||||
}
|
||||
|
||||
public ParcelableImageValue(Parcel in) {
|
||||
this.width = in.readInt();
|
||||
this.height = in.readInt();
|
||||
this.url = in.readString();
|
||||
}
|
||||
|
||||
public ParcelableImageValue(ImageValue value) {
|
||||
this.width = value.getWidth();
|
||||
this.height = value.getHeight();
|
||||
this.url = value.getUrl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(width);
|
||||
dest.writeInt(height);
|
||||
dest.writeString(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(JSONParcel dest) {
|
||||
dest.writeInt("width", width);
|
||||
dest.writeInt("height", height);
|
||||
dest.writeString("url", url);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import android.database.Cursor;
|
|||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import org.mariotaku.jsonserializer.JSONParcel;
|
||||
import org.mariotaku.jsonserializer.JSONParcelable;
|
||||
|
@ -257,6 +258,15 @@ public class ParcelableUser implements TwidereParcelable, Comparable<ParcelableU
|
|||
return 0;
|
||||
}
|
||||
|
||||
public static ParcelableUser[] fromUsersArray(@Nullable final User[] users, long account_id) {
|
||||
if (users == null) return null;
|
||||
final ParcelableUser[] result = new ParcelableUser[users.length];
|
||||
for (int i = 0, j = users.length; i < j; i++) {
|
||||
result[i] = new ParcelableUser(users[i], account_id);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(final Parcel out, final int flags) {
|
||||
out.writeLong(position);
|
||||
|
|
|
@ -732,6 +732,8 @@ public interface TweetStore {
|
|||
|
||||
public static final String MENTIONS = "mentions";
|
||||
|
||||
public static final String CARD = "card";
|
||||
|
||||
public static final String SORT_ORDER_TIMESTAMP_DESC = STATUS_TIMESTAMP + " DESC";
|
||||
|
||||
public static final String SORT_ORDER_STATUS_ID_DESC = STATUS_ID + " DESC";
|
||||
|
@ -745,14 +747,15 @@ public interface TweetStore {
|
|||
DESCENDENT_REPLY_COUNT, RETWEET_ID, RETWEET_TIMESTAMP, RETWEETED_BY_USER_ID,
|
||||
RETWEETED_BY_USER_NAME, RETWEETED_BY_USER_SCREEN_NAME, RETWEETED_BY_USER_PROFILE_IMAGE,
|
||||
MY_RETWEET_ID, IS_RETWEET, IS_FAVORITE, IS_PROTECTED, IS_VERIFIED, IS_FOLLOWING, IS_GAP,
|
||||
IS_POSSIBLY_SENSITIVE, MEDIA, FIRST_MEDIA, MENTIONS};
|
||||
IS_POSSIBLY_SENSITIVE, MEDIA, FIRST_MEDIA, MENTIONS, CARD};
|
||||
|
||||
public static final String[] TYPES = new String[]{TYPE_PRIMARY_KEY, TYPE_INT, TYPE_INT,
|
||||
TYPE_INT, TYPE_INT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT,
|
||||
TYPE_INT, TYPE_INT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_INT, TYPE_INT,
|
||||
TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_TEXT, TYPE_TEXT,
|
||||
TYPE_TEXT, TYPE_INT, TYPE_BOOLEAN, TYPE_BOOLEAN, TYPE_BOOLEAN, TYPE_BOOLEAN,
|
||||
TYPE_BOOLEAN, TYPE_BOOLEAN, TYPE_BOOLEAN, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT};
|
||||
TYPE_BOOLEAN, TYPE_BOOLEAN, TYPE_BOOLEAN, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT,
|
||||
TYPE_TEXT};
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@ import android.os.Looper;
|
|||
import android.os.ParcelFileDescriptor;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.support.v4.app.NotificationCompat.Action;
|
||||
import android.text.Html;
|
||||
import android.util.Log;
|
||||
|
||||
|
@ -64,9 +65,11 @@ import org.mariotaku.twidere.model.SupportTabSpec;
|
|||
import org.mariotaku.twidere.model.UnreadItem;
|
||||
import org.mariotaku.twidere.provider.TweetStore.Accounts;
|
||||
import org.mariotaku.twidere.provider.TweetStore.DirectMessages;
|
||||
import org.mariotaku.twidere.provider.TweetStore.Drafts;
|
||||
import org.mariotaku.twidere.provider.TweetStore.Preferences;
|
||||
import org.mariotaku.twidere.provider.TweetStore.Statuses;
|
||||
import org.mariotaku.twidere.provider.TweetStore.UnreadCounts;
|
||||
import org.mariotaku.twidere.service.BackgroundOperationService;
|
||||
import org.mariotaku.twidere.util.ArrayUtils;
|
||||
import org.mariotaku.twidere.util.CustomTabUtils;
|
||||
import org.mariotaku.twidere.util.HtmlEscapeHelper;
|
||||
|
@ -184,7 +187,7 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
if (result > 0) {
|
||||
onDatabaseUpdated(tableId, uri);
|
||||
}
|
||||
onNewItemsInserted(uri, values);
|
||||
onNewItemsInserted(uri, tableId, values);
|
||||
return result;
|
||||
} catch (final SQLException e) {
|
||||
throw new IllegalStateException(e);
|
||||
|
@ -266,7 +269,7 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
rowId = mDatabaseWrapper.insert(table, null, values);
|
||||
}
|
||||
onDatabaseUpdated(tableId, uri);
|
||||
onNewItemsInserted(uri, values);
|
||||
onNewItemsInserted(uri, tableId, values);
|
||||
return Uri.withAppendedPath(uri, String.valueOf(rowId));
|
||||
} catch (final SQLException e) {
|
||||
throw new IllegalStateException(e);
|
||||
|
@ -1092,13 +1095,13 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
notifyContentObserver(getNotificationUri(tableId, uri));
|
||||
}
|
||||
|
||||
private void onNewItemsInserted(final Uri uri, final ContentValues... values) {
|
||||
if (uri == null || values == null || values.length == 0) return;
|
||||
preloadImages(values);
|
||||
private void onNewItemsInserted(final Uri uri, final int tableId, final ContentValues... valuesArray) {
|
||||
if (uri == null || valuesArray == null || valuesArray.length == 0) return;
|
||||
preloadImages(valuesArray);
|
||||
if (!uri.getBooleanQueryParameter(QUERY_PARAM_NOTIFY, true)) return;
|
||||
switch (getTableId(uri)) {
|
||||
switch (tableId) {
|
||||
case TABLE_ID_STATUSES: {
|
||||
final int notifiedCount = notifyStatusesInserted(values);
|
||||
final int notifiedCount = notifyStatusesInserted(valuesArray);
|
||||
final List<ParcelableStatus> items = new ArrayList<ParcelableStatus>(mNewStatuses);
|
||||
Collections.sort(items);
|
||||
final AccountPreferences[] prefs = AccountPreferences.getNotificationEnabledPreferences(getContext(),
|
||||
|
@ -1118,7 +1121,7 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
case TABLE_ID_MENTIONS: {
|
||||
final AccountPreferences[] prefs = AccountPreferences.getNotificationEnabledPreferences(getContext(),
|
||||
getAccountIds(getContext()));
|
||||
final int notifiedCount = notifyMentionsInserted(prefs, values);
|
||||
final int notifiedCount = notifyMentionsInserted(prefs, valuesArray);
|
||||
final List<ParcelableStatus> items = new ArrayList<ParcelableStatus>(mNewMentions);
|
||||
Collections.sort(items);
|
||||
for (final AccountPreferences pref : prefs) {
|
||||
|
@ -1134,8 +1137,8 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
break;
|
||||
}
|
||||
case TABLE_ID_DIRECT_MESSAGES_INBOX: {
|
||||
final int notifiedCount = notifyIncomingMessagesInserted(values);
|
||||
final List<ParcelableDirectMessage> items = new ArrayList<ParcelableDirectMessage>(mNewMessages);
|
||||
final int notifiedCount = notifyIncomingMessagesInserted(valuesArray);
|
||||
final List<ParcelableDirectMessage> items = new ArrayList<>(mNewMessages);
|
||||
Collections.sort(items);
|
||||
final AccountPreferences[] prefs = AccountPreferences.getNotificationEnabledPreferences(getContext(),
|
||||
getAccountIds(getContext()));
|
||||
|
@ -1149,9 +1152,32 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
|||
notifyUnreadCountChanged(NOTIFICATION_ID_DIRECT_MESSAGES);
|
||||
break;
|
||||
}
|
||||
case TABLE_ID_DRAFTS: {
|
||||
for (ContentValues values : valuesArray) {
|
||||
displayNewDraftNotification(values);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void displayNewDraftNotification(ContentValues values) {
|
||||
final Context context = getContext();
|
||||
final NotificationManager nm = getNotificationManager();
|
||||
final NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
|
||||
builder.setTicker(context.getString(R.string.draft_saved));
|
||||
builder.setContentTitle(context.getString(R.string.draft_saved));
|
||||
builder.setContentText(values.getAsString(Drafts.TEXT));
|
||||
builder.setSmallIcon(R.drawable.ic_stat_info);
|
||||
final Intent service = new Intent(context, BackgroundOperationService.class);
|
||||
service.setAction(INTENT_ACTION_DISCARD_DRAFT);
|
||||
final PendingIntent discardIntent = PendingIntent.getService(context, 0, service, 0);
|
||||
final Action.Builder actionBuilder = new Action.Builder(R.drawable.ic_action_delete,
|
||||
context.getString(R.string.discard), discardIntent);
|
||||
builder.addAction(actionBuilder.build());
|
||||
nm.notify(16, builder.build());
|
||||
}
|
||||
|
||||
private void preloadImages(final ContentValues... values) {
|
||||
if (values == null) return;
|
||||
for (final ContentValues v : values) {
|
||||
|
|
|
@ -265,35 +265,39 @@ public final class ContentValuesCreator implements TwidereConstants {
|
|||
values.put(Statuses.ACCOUNT_ID, accountId);
|
||||
values.put(Statuses.STATUS_ID, orig.getId());
|
||||
values.put(Statuses.STATUS_TIMESTAMP, orig.getCreatedAt().getTime());
|
||||
values.put(Statuses.MY_RETWEET_ID, orig.getCurrentUserRetweet());
|
||||
final boolean isRetweet = orig.isRetweet();
|
||||
final Status status;
|
||||
final Status retweetedStatus = isRetweet ? orig.getRetweetedStatus() : null;
|
||||
if (retweetedStatus != null) {
|
||||
final User retweetUser = orig.getUser();
|
||||
final long retweetedById = retweetUser.getId();
|
||||
values.put(Statuses.RETWEET_ID, retweetedStatus.getId());
|
||||
values.put(Statuses.RETWEET_TIMESTAMP, retweetedStatus.getCreatedAt().getTime());
|
||||
values.put(Statuses.RETWEETED_BY_USER_ID, retweetUser.getId());
|
||||
values.put(Statuses.RETWEETED_BY_USER_ID, retweetedById);
|
||||
values.put(Statuses.RETWEETED_BY_USER_NAME, retweetUser.getName());
|
||||
values.put(Statuses.RETWEETED_BY_USER_SCREEN_NAME, retweetUser.getScreenName());
|
||||
values.put(Statuses.RETWEETED_BY_USER_PROFILE_IMAGE, ParseUtils.parseString(retweetUser.getProfileImageUrlHttps()));
|
||||
if (retweetedById == accountId) {
|
||||
values.put(Statuses.MY_RETWEET_ID, orig.getId());
|
||||
} else {
|
||||
values.put(Statuses.MY_RETWEET_ID, orig.getCurrentUserRetweet());
|
||||
}
|
||||
status = retweetedStatus;
|
||||
} else {
|
||||
values.put(Statuses.MY_RETWEET_ID, orig.getCurrentUserRetweet());
|
||||
status = orig;
|
||||
}
|
||||
final User user = status.getUser();
|
||||
if (user != null) {
|
||||
final long userId = user.getId();
|
||||
final String profileImageUrl = ParseUtils.parseString(user.getProfileImageUrlHttps());
|
||||
final String name = user.getName(), screenName = user.getScreenName();
|
||||
values.put(Statuses.USER_ID, userId);
|
||||
values.put(Statuses.USER_NAME, name);
|
||||
values.put(Statuses.USER_SCREEN_NAME, screenName);
|
||||
values.put(Statuses.IS_PROTECTED, user.isProtected());
|
||||
values.put(Statuses.IS_VERIFIED, user.isVerified());
|
||||
values.put(Statuses.USER_PROFILE_IMAGE_URL, profileImageUrl);
|
||||
values.put(CachedUsers.IS_FOLLOWING, user.isFollowing());
|
||||
}
|
||||
final long userId = user.getId();
|
||||
final String profileImageUrl = ParseUtils.parseString(user.getProfileImageUrlHttps());
|
||||
final String name = user.getName(), screenName = user.getScreenName();
|
||||
values.put(Statuses.USER_ID, userId);
|
||||
values.put(Statuses.USER_NAME, name);
|
||||
values.put(Statuses.USER_SCREEN_NAME, screenName);
|
||||
values.put(Statuses.IS_PROTECTED, user.isProtected());
|
||||
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);
|
||||
values.put(Statuses.TEXT_HTML, text_html);
|
||||
values.put(Statuses.TEXT_PLAIN, status.getText());
|
||||
|
|
|
@ -101,6 +101,12 @@ import android.widget.ListView;
|
|||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.android.youtube.player.YouTubeInitializationResult;
|
||||
import com.google.android.youtube.player.YouTubePlayer;
|
||||
import com.google.android.youtube.player.YouTubePlayer.OnInitializedListener;
|
||||
import com.google.android.youtube.player.YouTubePlayer.Provider;
|
||||
import com.google.android.youtube.player.YouTubePlayerSupportFragment;
|
||||
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.json.JSONException;
|
||||
import org.mariotaku.gallery3d.ImageViewerGLActivity;
|
||||
|
@ -160,6 +166,8 @@ import org.mariotaku.twidere.model.ParcelableAccount.ParcelableCredentials;
|
|||
import org.mariotaku.twidere.model.ParcelableDirectMessage;
|
||||
import org.mariotaku.twidere.model.ParcelableLocation;
|
||||
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
import org.mariotaku.twidere.model.ParcelableStatus.ParcelableCardEntity;
|
||||
import org.mariotaku.twidere.model.ParcelableStatus.ParcelableCardEntity.ParcelableValueItem;
|
||||
import org.mariotaku.twidere.model.ParcelableUser;
|
||||
import org.mariotaku.twidere.model.ParcelableUserList;
|
||||
import org.mariotaku.twidere.model.TwidereParcelable;
|
||||
|
@ -189,6 +197,7 @@ import org.mariotaku.twidere.util.content.ContentResolverUtils;
|
|||
import org.mariotaku.twidere.util.menu.TwidereMenuInfo;
|
||||
import org.mariotaku.twidere.util.net.TwidereHostResolverFactory;
|
||||
import org.mariotaku.twidere.util.net.TwidereHttpClientFactory;
|
||||
import org.mariotaku.twidere.view.ShapedImageView;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
|
@ -2074,6 +2083,22 @@ public final class Utils implements Constants, TwitterConstants {
|
|||
return url;
|
||||
}
|
||||
|
||||
public static int getProfileImageStyle(String style) {
|
||||
if (VALUE_PROFILE_IMAGE_STYLE_SQUARE.equalsIgnoreCase(style)) {
|
||||
return ShapedImageView.SHAPE_RECTANGLE;
|
||||
}
|
||||
return ShapedImageView.SHAPE_CIRCLE;
|
||||
}
|
||||
|
||||
public static int getMediaPreviewStyle(String style) {
|
||||
if (VALUE_MEDIA_PREVIEW_STYLE_CROP.equalsIgnoreCase(style)) {
|
||||
return VALUE_MEDIA_PREVIEW_STYLE_CODE_CROP;
|
||||
} else if (VALUE_MEDIA_PREVIEW_STYLE_SCALE.equalsIgnoreCase(style)) {
|
||||
return VALUE_MEDIA_PREVIEW_STYLE_CODE_SCALE;
|
||||
}
|
||||
return VALUE_MEDIA_PREVIEW_STYLE_CODE_NONE;
|
||||
}
|
||||
|
||||
public static Proxy getProxy(final Context context) {
|
||||
if (context == null) return null;
|
||||
final SharedPreferences prefs = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
|
@ -2478,6 +2503,8 @@ public final class Utils implements Constants, TwitterConstants {
|
|||
cb.setHttpConnectionTimeout(connection_timeout);
|
||||
cb.setGZIPEnabled(enableGzip);
|
||||
cb.setIgnoreSSLError(ignoreSslError);
|
||||
cb.setIncludeCards(true);
|
||||
cb.setCardsPlatform("Android-5");
|
||||
if (enableProxy) {
|
||||
final String proxy_host = prefs.getString(KEY_PROXY_HOST, null);
|
||||
final int proxy_port = ParseUtils.parseInt(prefs.getString(KEY_PROXY_PORT, "-1"));
|
||||
|
@ -2649,6 +2676,32 @@ public final class Utils implements Constants, TwitterConstants {
|
|||
return plugged || level / scale > 0.15f;
|
||||
}
|
||||
|
||||
public static boolean isCardSupported(ParcelableCardEntity card) {
|
||||
return card != null && "player".equals(card.name);
|
||||
}
|
||||
|
||||
public static Fragment createTwitterCardFragment(ParcelableCardEntity card) {
|
||||
if ("player".equals(card.name)) {
|
||||
final ParcelableValueItem player_url = ParcelableCardEntity.getValue(card, "player_url");
|
||||
final YouTubePlayerSupportFragment fragment = YouTubePlayerSupportFragment.newInstance();
|
||||
fragment.initialize("AIzaSyCVdCIMFFxdNqHnCPrJ9yKUzoTfs8jhYGc", new OnInitializedListener() {
|
||||
@Override
|
||||
public void onInitializationSuccess(Provider provider, YouTubePlayer player, boolean b) {
|
||||
final String url = (String) player_url.value;
|
||||
final String id = url.substring(url.lastIndexOf('/') + 1);
|
||||
player.cueVideo(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInitializationFailure(Provider provider, YouTubeInitializationResult youTubeInitializationResult) {
|
||||
|
||||
}
|
||||
});
|
||||
return fragment;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean isCompactCards(final Context context) {
|
||||
final SharedPreferences prefs = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
return prefs != null && prefs.getBoolean(KEY_COMPACT_CARDS, false);
|
||||
|
|
|
@ -27,8 +27,10 @@ import android.util.AttributeSet;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ImageView.ScaleType;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.mariotaku.twidere.Constants;
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.model.ParcelableMedia;
|
||||
import org.mariotaku.twidere.util.ImageLoaderWrapper;
|
||||
|
@ -38,11 +40,12 @@ import org.mariotaku.twidere.util.MediaPreviewUtils.OnMediaClickListener;
|
|||
/**
|
||||
* Created by mariotaku on 14/12/17.
|
||||
*/
|
||||
public class CardMediaContainer extends ViewGroup {
|
||||
public class CardMediaContainer extends ViewGroup implements Constants {
|
||||
|
||||
private final int mMaxColumns;
|
||||
private final int mHorizontalSpacing, mVerticalSpacing;
|
||||
private int[] mTempIndices;
|
||||
private int mMediaPreviewStyle;
|
||||
|
||||
public CardMediaContainer(Context context) {
|
||||
this(context, null);
|
||||
|
@ -83,7 +86,7 @@ public class CardMediaContainer extends ViewGroup {
|
|||
final long accountId,
|
||||
final OnMediaClickListener mediaClickListener,
|
||||
final ImageLoadingHandler loadingHandler) {
|
||||
if (mediaArray == null) {
|
||||
if (mediaArray == null || mMediaPreviewStyle == VALUE_MEDIA_PREVIEW_STYLE_CODE_NONE) {
|
||||
for (int i = 0, j = getChildCount(); i < j; i++) {
|
||||
final View child = getChildAt(i);
|
||||
child.setVisibility(GONE);
|
||||
|
@ -95,6 +98,16 @@ public class CardMediaContainer extends ViewGroup {
|
|||
final View child = getChildAt(i);
|
||||
child.setOnClickListener(clickListener);
|
||||
final ImageView imageView = (ImageView) child.findViewById(R.id.media_preview);
|
||||
switch (mMediaPreviewStyle) {
|
||||
case VALUE_MEDIA_PREVIEW_STYLE_CODE_CROP: {
|
||||
imageView.setScaleType(ScaleType.CENTER_CROP);
|
||||
break;
|
||||
}
|
||||
case VALUE_MEDIA_PREVIEW_STYLE_CODE_SCALE: {
|
||||
imageView.setScaleType(ScaleType.CENTER_INSIDE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < k) {
|
||||
final ParcelableMedia media = mediaArray[i];
|
||||
loader.displayPreviewImage(imageView, media.url, loadingHandler);
|
||||
|
@ -117,6 +130,10 @@ public class CardMediaContainer extends ViewGroup {
|
|||
}
|
||||
}
|
||||
|
||||
public void setStyle(int style) {
|
||||
mMediaPreviewStyle = style;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
final int[] childIndices = createChildIndices();
|
||||
|
|
|
@ -100,17 +100,13 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements OnClick
|
|||
|
||||
public void displayStatus(final ParcelableStatus status) {
|
||||
displayStatus(adapter.getContext(), adapter.getImageLoader(),
|
||||
adapter.getImageLoadingHandler(), adapter.getTwitterWrapper(), status);
|
||||
}
|
||||
|
||||
public void displayStatus(final Context context, final ImageLoaderWrapper loader,
|
||||
final ImageLoadingHandler handler, final AsyncTwitterWrapper twitter,
|
||||
final ParcelableStatus status) {
|
||||
displayStatus(context, loader, handler, twitter, status, null);
|
||||
adapter.getImageLoadingHandler(), adapter.getTwitterWrapper(),
|
||||
adapter.getProfileImageStyle(), adapter.getMediaPreviewStyle(), status, null);
|
||||
}
|
||||
|
||||
public void displayStatus(final Context context, final ImageLoaderWrapper loader,
|
||||
final ImageLoadingHandler handler, final AsyncTwitterWrapper twitter,
|
||||
final int profileImageStyle, final int mediaPreviewStyle,
|
||||
@NonNull final ParcelableStatus status,
|
||||
@Nullable final TranslationResult translation) {
|
||||
final ParcelableMedia[] media = status.media;
|
||||
|
@ -145,9 +141,11 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements OnClick
|
|||
|
||||
final int userColor = UserColorNicknameUtils.getUserColor(context, status.user_id);
|
||||
profileImageView.setBorderColor(userColor);
|
||||
profileImageView.setStyle(profileImageStyle);
|
||||
|
||||
loader.displayProfileImage(profileImageView, status.user_profile_image_url);
|
||||
|
||||
mediaPreviewContainer.setStyle(mediaPreviewStyle);
|
||||
mediaPreviewContainer.displayMedia(media, loader, status.account_id, null, handler);
|
||||
if (translation != null) {
|
||||
textView.setText(translation.getText());
|
||||
|
@ -254,10 +252,12 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements OnClick
|
|||
|
||||
final int userColor = UserColorNicknameUtils.getUserColor(context, user_id);
|
||||
profileImageView.setBorderColor(userColor);
|
||||
profileImageView.setStyle(adapter.getProfileImageStyle());
|
||||
|
||||
loader.displayProfileImage(profileImageView, user_profile_image_url);
|
||||
|
||||
final String text_unescaped = cursor.getString(indices.text_unescaped);
|
||||
mediaPreviewContainer.setStyle(adapter.getMediaPreviewStyle());
|
||||
mediaPreviewContainer.displayMedia(media, loader, account_id, null,
|
||||
adapter.getImageLoadingHandler());
|
||||
textView.setText(text_unescaped);
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* 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 twitter4j;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 14/12/31.
|
||||
*/
|
||||
public interface CardEntity extends Serializable {
|
||||
|
||||
String getName();
|
||||
|
||||
User[] gerUsers();
|
||||
|
||||
BindingValue getBindingValue(String key);
|
||||
|
||||
BindingValue[] getBindingValues();
|
||||
|
||||
public interface BindingValue extends Serializable {
|
||||
|
||||
String getName();
|
||||
|
||||
String getType();
|
||||
}
|
||||
|
||||
|
||||
public interface UserValue extends BindingValue {
|
||||
long getUserId();
|
||||
}
|
||||
|
||||
public interface StringValue extends BindingValue {
|
||||
String getValue();
|
||||
}
|
||||
|
||||
public interface ImageValue extends BindingValue {
|
||||
int getWidth();
|
||||
|
||||
int getHeight();
|
||||
|
||||
String getUrl();
|
||||
}
|
||||
}
|
|
@ -168,4 +168,6 @@ public interface Status extends Comparable<Status>, TwitterResponse, ExtendedEnt
|
|||
*/
|
||||
boolean isTruncated();
|
||||
|
||||
CardEntity getCard();
|
||||
|
||||
}
|
||||
|
|
|
@ -16,8 +16,15 @@
|
|||
|
||||
package twitter4j;
|
||||
|
||||
import static twitter4j.http.HttpResponseCode.ENHANCE_YOUR_CLAIM;
|
||||
import static twitter4j.http.HttpResponseCode.SERVICE_UNAVAILABLE;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import twitter4j.auth.AccessToken;
|
||||
import twitter4j.auth.Authorization;
|
||||
import twitter4j.auth.AuthorizationFactory;
|
||||
|
@ -36,485 +43,486 @@ import twitter4j.http.HttpResponseListener;
|
|||
import twitter4j.internal.json.InternalJSONFactory;
|
||||
import twitter4j.internal.json.InternalJSONFactoryImpl;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import static twitter4j.http.HttpResponseCode.ENHANCE_YOUR_CLAIM;
|
||||
import static twitter4j.http.HttpResponseCode.SERVICE_UNAVAILABLE;
|
||||
|
||||
/**
|
||||
* Base class of Twitter / AsyncTwitter / TwitterStream supports OAuth.
|
||||
*
|
||||
*
|
||||
* @author Yusuke Yamamoto - yusuke at mac.com
|
||||
*/
|
||||
abstract class TwitterBaseImpl implements OAuthSupport, HttpResponseListener, TwitterConstants {
|
||||
protected Configuration conf;
|
||||
protected transient String screenName = null;
|
||||
protected transient long id = 0;
|
||||
protected Configuration conf;
|
||||
protected transient String screenName = null;
|
||||
protected transient long id = 0;
|
||||
|
||||
protected transient HttpClientWrapper http;
|
||||
private List<RateLimitStatusListener> rateLimitStatusListeners = new ArrayList<RateLimitStatusListener>(0);
|
||||
protected transient HttpClientWrapper http;
|
||||
private List<RateLimitStatusListener> rateLimitStatusListeners = new ArrayList<RateLimitStatusListener>(0);
|
||||
|
||||
protected InternalJSONFactory factory;
|
||||
protected InternalJSONFactory factory;
|
||||
|
||||
protected Authorization auth;
|
||||
protected Authorization auth;
|
||||
|
||||
/* package */TwitterBaseImpl(final Configuration conf, final Authorization auth) {
|
||||
this.conf = conf;
|
||||
this.auth = auth;
|
||||
init();
|
||||
}
|
||||
/* package */TwitterBaseImpl(final Configuration conf, final Authorization auth) {
|
||||
this.conf = conf;
|
||||
this.auth = auth;
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void addRateLimitStatusListener(final RateLimitStatusListener listener) {
|
||||
rateLimitStatusListeners.add(listener);
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void addRateLimitStatusListener(final RateLimitStatusListener listener) {
|
||||
rateLimitStatusListeners.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof TwitterBaseImpl)) return false;
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof TwitterBaseImpl)) return false;
|
||||
|
||||
final TwitterBaseImpl that = (TwitterBaseImpl) o;
|
||||
final TwitterBaseImpl that = (TwitterBaseImpl) o;
|
||||
|
||||
if (auth != null ? !auth.equals(that.auth) : that.auth != null) return false;
|
||||
if (!conf.equals(that.conf)) return false;
|
||||
if (http != null ? !http.equals(that.http) : that.http != null) return false;
|
||||
if (!rateLimitStatusListeners.equals(that.rateLimitStatusListeners)) return false;
|
||||
if (auth != null ? !auth.equals(that.auth) : that.auth != null) return false;
|
||||
if (!conf.equals(that.conf)) return false;
|
||||
if (http != null ? !http.equals(that.http) : that.http != null) return false;
|
||||
if (!rateLimitStatusListeners.equals(that.rateLimitStatusListeners)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public final Authorization getAuthorization() {
|
||||
return auth;
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public final Authorization getAuthorization() {
|
||||
return auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Configuration getConfiguration() {
|
||||
return conf;
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Configuration getConfiguration() {
|
||||
return conf;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public long getId() throws TwitterException, IllegalStateException {
|
||||
if (!auth.isEnabled())
|
||||
throw new IllegalStateException(
|
||||
"Neither user ID/password combination nor OAuth consumer key/secret combination supplied");
|
||||
if (0 == id) {
|
||||
fillInIDAndScreenName();
|
||||
}
|
||||
// retrieve the screen name if this instance is authenticated with OAuth
|
||||
// or email address
|
||||
return id;
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public long getId() throws TwitterException, IllegalStateException {
|
||||
if (!auth.isEnabled())
|
||||
throw new IllegalStateException(
|
||||
"Neither user ID/password combination nor OAuth consumer key/secret combination supplied");
|
||||
if (0 == id) {
|
||||
fillInIDAndScreenName();
|
||||
}
|
||||
// retrieve the screen name if this instance is authenticated with OAuth
|
||||
// or email address
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc} Basic authenticated instance of this class will try
|
||||
* acquiring an AccessToken using xAuth.<br>
|
||||
* In order to get access acquire AccessToken using xAuth, you must apply by
|
||||
* sending an email to <a href="mailto:api@twitter.com">api@twitter.com</a>
|
||||
* all other applications will receive an HTTP 401 error. Web-based
|
||||
* applications will not be granted access, except on a temporary basis for
|
||||
* when they are converting from basic-authentication support to full OAuth
|
||||
* support.<br>
|
||||
* Storage of Twitter usernames and passwords is forbidden. By using xAuth,
|
||||
* you are required to store only access tokens and access token secrets. If
|
||||
* the access token expires or is expunged by a user, you must ask for their
|
||||
* login and password again before exchanging the credentials for an access
|
||||
* token.
|
||||
*
|
||||
* @throws TwitterException When Twitter service or network is unavailable,
|
||||
* when the user has not authorized, or when the client
|
||||
* application is not permitted to use xAuth
|
||||
* @see <a href="https://dev.twitter.com/docs/oauth/xauth">xAuth | Twitter
|
||||
* Developers</a>
|
||||
*/
|
||||
@Override
|
||||
public synchronized AccessToken getOAuthAccessToken() throws TwitterException {
|
||||
Authorization auth = getAuthorization();
|
||||
AccessToken oauthAccessToken;
|
||||
if (auth instanceof BasicAuthorization) {
|
||||
final BasicAuthorization basicAuth = (BasicAuthorization) auth;
|
||||
auth = AuthorizationFactory.getInstance(conf);
|
||||
if (auth instanceof OAuthAuthorization) {
|
||||
this.auth = auth;
|
||||
final OAuthAuthorization oauthAuth = (OAuthAuthorization) auth;
|
||||
oauthAccessToken = oauthAuth.getOAuthAccessToken(basicAuth.getUserId(), basicAuth.getPassword());
|
||||
} else
|
||||
throw new IllegalStateException("consumer key / secret combination not supplied.");
|
||||
} else {
|
||||
if (auth instanceof XAuthAuthorization) {
|
||||
final XAuthAuthorization xauth = (XAuthAuthorization) auth;
|
||||
this.auth = xauth;
|
||||
final OAuthAuthorization oauthAuth = new OAuthAuthorization(conf);
|
||||
oauthAuth.setOAuthConsumer(xauth.getConsumerKey(), xauth.getConsumerSecret());
|
||||
oauthAccessToken = oauthAuth.getOAuthAccessToken(xauth.getUserId(), xauth.getPassword());
|
||||
} else {
|
||||
oauthAccessToken = getOAuth().getOAuthAccessToken();
|
||||
}
|
||||
}
|
||||
screenName = oauthAccessToken.getScreenName();
|
||||
id = oauthAccessToken.getUserId();
|
||||
return oauthAccessToken;
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc} Basic authenticated instance of this class will try
|
||||
* acquiring an AccessToken using xAuth.<br>
|
||||
* In order to get access acquire AccessToken using xAuth, you must apply by
|
||||
* sending an email to <a href="mailto:api@twitter.com">api@twitter.com</a>
|
||||
* all other applications will receive an HTTP 401 error. Web-based
|
||||
* applications will not be granted access, except on a temporary basis for
|
||||
* when they are converting from basic-authentication support to full OAuth
|
||||
* support.<br>
|
||||
* Storage of Twitter usernames and passwords is forbidden. By using xAuth,
|
||||
* you are required to store only access tokens and access token secrets. If
|
||||
* the access token expires or is expunged by a user, you must ask for their
|
||||
* login and password again before exchanging the credentials for an access
|
||||
* token.
|
||||
*
|
||||
* @throws TwitterException When Twitter service or network is unavailable,
|
||||
* when the user has not authorized, or when the client
|
||||
* application is not permitted to use xAuth
|
||||
* @see <a href="https://dev.twitter.com/docs/oauth/xauth">xAuth | Twitter
|
||||
* Developers</a>
|
||||
*/
|
||||
@Override
|
||||
public synchronized AccessToken getOAuthAccessToken() throws TwitterException {
|
||||
Authorization auth = getAuthorization();
|
||||
AccessToken oauthAccessToken;
|
||||
if (auth instanceof BasicAuthorization) {
|
||||
final BasicAuthorization basicAuth = (BasicAuthorization) auth;
|
||||
auth = AuthorizationFactory.getInstance(conf);
|
||||
if (auth instanceof OAuthAuthorization) {
|
||||
this.auth = auth;
|
||||
final OAuthAuthorization oauthAuth = (OAuthAuthorization) auth;
|
||||
oauthAccessToken = oauthAuth.getOAuthAccessToken(basicAuth.getUserId(), basicAuth.getPassword());
|
||||
} else
|
||||
throw new IllegalStateException("consumer key / secret combination not supplied.");
|
||||
} else {
|
||||
if (auth instanceof XAuthAuthorization) {
|
||||
final XAuthAuthorization xauth = (XAuthAuthorization) auth;
|
||||
this.auth = xauth;
|
||||
final OAuthAuthorization oauthAuth = new OAuthAuthorization(conf);
|
||||
oauthAuth.setOAuthConsumer(xauth.getConsumerKey(), xauth.getConsumerSecret());
|
||||
oauthAccessToken = oauthAuth.getOAuthAccessToken(xauth.getUserId(), xauth.getPassword());
|
||||
} else {
|
||||
oauthAccessToken = getOAuth().getOAuthAccessToken();
|
||||
}
|
||||
}
|
||||
screenName = oauthAccessToken.getScreenName();
|
||||
id = oauthAccessToken.getUserId();
|
||||
return oauthAccessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @throws IllegalStateException when AccessToken has already been retrieved
|
||||
* or set
|
||||
*/
|
||||
@Override
|
||||
public synchronized AccessToken getOAuthAccessToken(final RequestToken requestToken) throws TwitterException {
|
||||
final OAuthSupport oauth = getOAuth();
|
||||
final AccessToken oauthAccessToken = oauth.getOAuthAccessToken(requestToken);
|
||||
screenName = oauthAccessToken.getScreenName();
|
||||
return oauthAccessToken;
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @throws IllegalStateException when AccessToken has already been retrieved
|
||||
* or set
|
||||
*/
|
||||
@Override
|
||||
public synchronized AccessToken getOAuthAccessToken(final RequestToken requestToken) throws TwitterException {
|
||||
final OAuthSupport oauth = getOAuth();
|
||||
final AccessToken oauthAccessToken = oauth.getOAuthAccessToken(requestToken);
|
||||
screenName = oauthAccessToken.getScreenName();
|
||||
return oauthAccessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @throws IllegalStateException when AccessToken has already been retrieved
|
||||
* or set
|
||||
*/
|
||||
@Override
|
||||
public synchronized AccessToken getOAuthAccessToken(final RequestToken requestToken, final String oauthVerifier)
|
||||
throws TwitterException {
|
||||
return getOAuth().getOAuthAccessToken(requestToken, oauthVerifier);
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @throws IllegalStateException when AccessToken has already been retrieved
|
||||
* or set
|
||||
*/
|
||||
@Override
|
||||
public synchronized AccessToken getOAuthAccessToken(final RequestToken requestToken, final String oauthVerifier)
|
||||
throws TwitterException {
|
||||
return getOAuth().getOAuthAccessToken(requestToken, oauthVerifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @throws IllegalStateException when AccessToken has already been retrieved
|
||||
* or set
|
||||
*/
|
||||
@Override
|
||||
public synchronized AccessToken getOAuthAccessToken(final String oauthVerifier) throws TwitterException {
|
||||
final AccessToken oauthAccessToken = getOAuth().getOAuthAccessToken(oauthVerifier);
|
||||
screenName = oauthAccessToken.getScreenName();
|
||||
return oauthAccessToken;
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @throws IllegalStateException when AccessToken has already been retrieved
|
||||
* or set
|
||||
*/
|
||||
@Override
|
||||
public synchronized AccessToken getOAuthAccessToken(final String oauthVerifier) throws TwitterException {
|
||||
final AccessToken oauthAccessToken = getOAuth().getOAuthAccessToken(oauthVerifier);
|
||||
screenName = oauthAccessToken.getScreenName();
|
||||
return oauthAccessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public synchronized AccessToken getOAuthAccessToken(final String screenName, final String password)
|
||||
throws TwitterException {
|
||||
return getOAuth().getOAuthAccessToken(screenName, password);
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public synchronized AccessToken getOAuthAccessToken(final String screenName, final String password)
|
||||
throws TwitterException {
|
||||
return getOAuth().getOAuthAccessToken(screenName, password);
|
||||
}
|
||||
|
||||
/* OAuth support methods */
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public RequestToken getOAuthRequestToken() throws TwitterException {
|
||||
return getOAuthRequestToken(null);
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public RequestToken getOAuthRequestToken() throws TwitterException {
|
||||
return getOAuthRequestToken(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public RequestToken getOAuthRequestToken(final String callbackUrl) throws TwitterException {
|
||||
return getOAuth().getOAuthRequestToken(callbackUrl);
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public RequestToken getOAuthRequestToken(final String callbackUrl) throws TwitterException {
|
||||
return getOAuth().getOAuthRequestToken(callbackUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public RequestToken getOAuthRequestToken(final String callbackUrl, final String xAuthAccessType)
|
||||
throws TwitterException {
|
||||
return getOAuth().getOAuthRequestToken(callbackUrl, xAuthAccessType);
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public RequestToken getOAuthRequestToken(final String callbackUrl, final String xAuthAccessType)
|
||||
throws TwitterException {
|
||||
return getOAuth().getOAuthRequestToken(callbackUrl, xAuthAccessType);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public String getScreenName() throws TwitterException, IllegalStateException {
|
||||
if (!auth.isEnabled())
|
||||
throw new IllegalStateException(
|
||||
"Neither user ID/password combination nor OAuth consumer key/secret combination supplied");
|
||||
if (null == screenName) {
|
||||
if (auth instanceof BasicAuthorization) {
|
||||
screenName = ((BasicAuthorization) auth).getUserId();
|
||||
if (-1 != screenName.indexOf("@")) {
|
||||
screenName = null;
|
||||
}
|
||||
}
|
||||
if (null == screenName) {
|
||||
// retrieve the screen name if this instance is authenticated
|
||||
// with OAuth or email address
|
||||
fillInIDAndScreenName();
|
||||
}
|
||||
}
|
||||
return screenName;
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public String getScreenName() throws TwitterException, IllegalStateException {
|
||||
if (!auth.isEnabled())
|
||||
throw new IllegalStateException(
|
||||
"Neither user ID/password combination nor OAuth consumer key/secret combination supplied");
|
||||
if (null == screenName) {
|
||||
if (auth instanceof BasicAuthorization) {
|
||||
screenName = ((BasicAuthorization) auth).getUserId();
|
||||
if (-1 != screenName.indexOf("@")) {
|
||||
screenName = null;
|
||||
}
|
||||
}
|
||||
if (null == screenName) {
|
||||
// retrieve the screen name if this instance is authenticated
|
||||
// with OAuth or email address
|
||||
fillInIDAndScreenName();
|
||||
}
|
||||
}
|
||||
return screenName;
|
||||
}
|
||||
|
||||
// methods declared in OAuthSupport interface
|
||||
// methods declared in OAuthSupport interface
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = conf.hashCode();
|
||||
result = 31 * result + (http != null ? http.hashCode() : 0);
|
||||
result = 31 * result + rateLimitStatusListeners.hashCode();
|
||||
result = 31 * result + (auth != null ? auth.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = conf.hashCode();
|
||||
result = 31 * result + (http != null ? http.hashCode() : 0);
|
||||
result = 31 * result + rateLimitStatusListeners.hashCode();
|
||||
result = 31 * result + (auth != null ? auth.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void httpResponseReceived(final HttpResponseEvent event) {
|
||||
if (rateLimitStatusListeners.size() != 0) {
|
||||
final HttpResponse res = event.getResponse();
|
||||
final TwitterException te = event.getTwitterException();
|
||||
RateLimitStatus rateLimitStatus;
|
||||
int statusCode;
|
||||
if (te != null) {
|
||||
rateLimitStatus = te.getRateLimitStatus();
|
||||
statusCode = te.getStatusCode();
|
||||
} else {
|
||||
rateLimitStatus = InternalJSONFactoryImpl.createRateLimitStatusFromResponseHeader(res);
|
||||
statusCode = res.getStatusCode();
|
||||
}
|
||||
if (rateLimitStatus != null) {
|
||||
final RateLimitStatusEvent statusEvent = new RateLimitStatusEvent(this, rateLimitStatus,
|
||||
event.isAuthenticated());
|
||||
if (statusCode == ENHANCE_YOUR_CLAIM || statusCode == SERVICE_UNAVAILABLE) {
|
||||
// EXCEEDED_RATE_LIMIT_QUOTA is returned by Rest API
|
||||
// SERVICE_UNAVAILABLE is returned by Search API
|
||||
for (final RateLimitStatusListener listener : rateLimitStatusListeners) {
|
||||
listener.onRateLimitStatus(statusEvent);
|
||||
listener.onRateLimitReached(statusEvent);
|
||||
}
|
||||
} else {
|
||||
for (final RateLimitStatusListener listener : rateLimitStatusListeners) {
|
||||
listener.onRateLimitStatus(statusEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void httpResponseReceived(final HttpResponseEvent event) {
|
||||
if (rateLimitStatusListeners.size() != 0) {
|
||||
final HttpResponse res = event.getResponse();
|
||||
final TwitterException te = event.getTwitterException();
|
||||
RateLimitStatus rateLimitStatus;
|
||||
int statusCode;
|
||||
if (te != null) {
|
||||
rateLimitStatus = te.getRateLimitStatus();
|
||||
statusCode = te.getStatusCode();
|
||||
} else {
|
||||
rateLimitStatus = InternalJSONFactoryImpl.createRateLimitStatusFromResponseHeader(res);
|
||||
statusCode = res.getStatusCode();
|
||||
}
|
||||
if (rateLimitStatus != null) {
|
||||
final RateLimitStatusEvent statusEvent = new RateLimitStatusEvent(this, rateLimitStatus,
|
||||
event.isAuthenticated());
|
||||
if (statusCode == ENHANCE_YOUR_CLAIM || statusCode == SERVICE_UNAVAILABLE) {
|
||||
// EXCEEDED_RATE_LIMIT_QUOTA is returned by Rest API
|
||||
// SERVICE_UNAVAILABLE is returned by Search API
|
||||
for (final RateLimitStatusListener listener : rateLimitStatusListeners) {
|
||||
listener.onRateLimitStatus(statusEvent);
|
||||
listener.onRateLimitReached(statusEvent);
|
||||
}
|
||||
} else {
|
||||
for (final RateLimitStatusListener listener : rateLimitStatusListeners) {
|
||||
listener.onRateLimitStatus(statusEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public synchronized void setOAuthAccessToken(final AccessToken accessToken) {
|
||||
getOAuth().setOAuthAccessToken(accessToken);
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public synchronized void setOAuthAccessToken(final AccessToken accessToken) {
|
||||
getOAuth().setOAuthAccessToken(accessToken);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public synchronized void setOAuthConsumer(final String consumerKey, final String consumerSecret) {
|
||||
if (null == consumerKey) throw new NullPointerException("consumer key is null");
|
||||
if (null == consumerSecret) throw new NullPointerException("consumer secret is null");
|
||||
if (auth instanceof NullAuthorization) {
|
||||
final OAuthAuthorization oauth = new OAuthAuthorization(conf);
|
||||
oauth.setOAuthConsumer(consumerKey, consumerSecret);
|
||||
auth = oauth;
|
||||
} else if (auth instanceof BasicAuthorization) {
|
||||
final XAuthAuthorization xauth = new XAuthAuthorization((BasicAuthorization) auth);
|
||||
xauth.setOAuthConsumer(consumerKey, consumerSecret);
|
||||
auth = xauth;
|
||||
} else if (auth instanceof OAuthAuthorization)
|
||||
throw new IllegalStateException("consumer key/secret pair already set.");
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public synchronized void setOAuthConsumer(final String consumerKey, final String consumerSecret) {
|
||||
if (null == consumerKey) throw new NullPointerException("consumer key is null");
|
||||
if (null == consumerSecret) throw new NullPointerException("consumer secret is null");
|
||||
if (auth instanceof NullAuthorization) {
|
||||
final OAuthAuthorization oauth = new OAuthAuthorization(conf);
|
||||
oauth.setOAuthConsumer(consumerKey, consumerSecret);
|
||||
auth = oauth;
|
||||
} else if (auth instanceof BasicAuthorization) {
|
||||
final XAuthAuthorization xauth = new XAuthAuthorization((BasicAuthorization) auth);
|
||||
xauth.setOAuthConsumer(consumerKey, consumerSecret);
|
||||
auth = xauth;
|
||||
} else if (auth instanceof OAuthAuthorization)
|
||||
throw new IllegalStateException("consumer key/secret pair already set.");
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void shutdown() {
|
||||
if (http != null) {
|
||||
http.shutdown();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void shutdown() {
|
||||
if (http != null) {
|
||||
http.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TwitterBase{" + "conf=" + conf + ", http=" + http + ", rateLimitStatusListeners="
|
||||
+ rateLimitStatusListeners + ", auth=" + auth + '}';
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TwitterBase{" + "conf=" + conf + ", http=" + http + ", rateLimitStatusListeners="
|
||||
+ rateLimitStatusListeners + ", auth=" + auth + '}';
|
||||
}
|
||||
|
||||
protected void addParameterToList(final List<HttpParameter> params, final String paramName, final Boolean param) {
|
||||
if (param != null) {
|
||||
params.add(new HttpParameter(paramName, param));
|
||||
}
|
||||
}
|
||||
protected void addParameterToList(final List<HttpParameter> params, final String paramName, final Boolean param) {
|
||||
if (param != null) {
|
||||
params.add(new HttpParameter(paramName, param));
|
||||
}
|
||||
}
|
||||
|
||||
protected void addParameterToList(final List<HttpParameter> params, final String paramName, final Double param) {
|
||||
if (param != null) {
|
||||
params.add(new HttpParameter(paramName, param));
|
||||
}
|
||||
}
|
||||
protected void addParameterToList(final List<HttpParameter> params, final String paramName, final Double param) {
|
||||
if (param != null) {
|
||||
params.add(new HttpParameter(paramName, param));
|
||||
}
|
||||
}
|
||||
|
||||
protected void addParameterToList(final List<HttpParameter> params, final String paramName, final Integer param) {
|
||||
if (param != null) {
|
||||
params.add(new HttpParameter(paramName, param));
|
||||
}
|
||||
}
|
||||
protected void addParameterToList(final List<HttpParameter> params, final String paramName, final Integer param) {
|
||||
if (param != null) {
|
||||
params.add(new HttpParameter(paramName, param));
|
||||
}
|
||||
}
|
||||
|
||||
protected void addParameterToList(final List<HttpParameter> params, final String paramName, final String param) {
|
||||
if (param != null) {
|
||||
params.add(new HttpParameter(paramName, param));
|
||||
}
|
||||
}
|
||||
protected void addParameterToList(final List<HttpParameter> params, final String paramName, final String param) {
|
||||
if (param != null) {
|
||||
params.add(new HttpParameter(paramName, param));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the existence, and the type of the specified file.
|
||||
*
|
||||
* @param image image to be uploaded
|
||||
* @throws TwitterException when the specified file is not found
|
||||
* (FileNotFoundException will be nested) , or when the
|
||||
* specified file object is not representing a file(IOException
|
||||
* will be nested).
|
||||
*/
|
||||
protected void checkFileValidity(final File image) throws TwitterException {
|
||||
if (!image.exists()) // noinspection ThrowableInstanceNeverThrown
|
||||
throw new TwitterException(new FileNotFoundException(image + " is not found."));
|
||||
if (!image.isFile()) // noinspection ThrowableInstanceNeverThrown
|
||||
throw new TwitterException(new IOException(image + " is not a file."));
|
||||
}
|
||||
/**
|
||||
* Check the existence, and the type of the specified file.
|
||||
*
|
||||
* @param image image to be uploaded
|
||||
* @throws TwitterException when the specified file is not found
|
||||
* (FileNotFoundException will be nested) , or when the
|
||||
* specified file object is not representing a file(IOException
|
||||
* will be nested).
|
||||
*/
|
||||
protected void checkFileValidity(final File image) throws TwitterException {
|
||||
if (!image.exists()) // noinspection ThrowableInstanceNeverThrown
|
||||
throw new TwitterException(new FileNotFoundException(image + " is not found."));
|
||||
if (!image.isFile()) // noinspection ThrowableInstanceNeverThrown
|
||||
throw new TwitterException(new IOException(image + " is not a file."));
|
||||
}
|
||||
|
||||
protected final void ensureAuthorizationEnabled() {
|
||||
if (!auth.isEnabled())
|
||||
throw new IllegalStateException(
|
||||
"Authentication credentials are missing. See http://twitter4j.org/configuration.html for the detail.");
|
||||
}
|
||||
protected final void ensureAuthorizationEnabled() {
|
||||
if (!auth.isEnabled())
|
||||
throw new IllegalStateException(
|
||||
"Authentication credentials are missing. See http://twitter4j.org/configuration.html for the detail.");
|
||||
}
|
||||
|
||||
protected final void ensureOAuthEnabled() {
|
||||
if (!(auth instanceof OAuthAuthorization))
|
||||
throw new IllegalStateException(
|
||||
"OAuth required. Authentication credentials are missing. See http://twitter4j.org/configuration.html for the detail.");
|
||||
}
|
||||
protected final void ensureOAuthEnabled() {
|
||||
if (!(auth instanceof OAuthAuthorization))
|
||||
throw new IllegalStateException(
|
||||
"OAuth required. Authentication credentials are missing. See http://twitter4j.org/configuration.html for the detail.");
|
||||
}
|
||||
|
||||
protected User fillInIDAndScreenName() throws TwitterException {
|
||||
ensureAuthorizationEnabled();
|
||||
final HttpParameter[] params = { new HttpParameter("include_entities", conf.isIncludeEntitiesEnabled()) };
|
||||
final User user = factory.createUser(http.get(conf.getRestBaseURL() + ENDPOINT_ACCOUNT_VERIFY_CREDENTIALS,
|
||||
conf.getSigningRestBaseURL() + ENDPOINT_ACCOUNT_VERIFY_CREDENTIALS, params, auth));
|
||||
screenName = user.getScreenName();
|
||||
id = user.getId();
|
||||
return user;
|
||||
}
|
||||
protected User fillInIDAndScreenName() throws TwitterException {
|
||||
ensureAuthorizationEnabled();
|
||||
final HttpParameter[] params = {new HttpParameter("include_entities", conf.isIncludeEntitiesEnabled())};
|
||||
final User user = factory.createUser(http.get(conf.getRestBaseURL() + ENDPOINT_ACCOUNT_VERIFY_CREDENTIALS,
|
||||
conf.getSigningRestBaseURL() + ENDPOINT_ACCOUNT_VERIFY_CREDENTIALS, params, auth));
|
||||
screenName = user.getScreenName();
|
||||
id = user.getId();
|
||||
return user;
|
||||
}
|
||||
|
||||
protected HttpResponse get(final String url, final String sign_url, final HttpParameter... parameters)
|
||||
throws TwitterException {
|
||||
// intercept HTTP call for monitoring purposes
|
||||
HttpResponse response = null;
|
||||
final long start = System.currentTimeMillis();
|
||||
try {
|
||||
response = http.get(url, sign_url, parameters, auth);
|
||||
} finally {
|
||||
final long elapsedTime = System.currentTimeMillis() - start;
|
||||
TwitterAPIMonitor.getInstance().methodCalled(url, elapsedTime, isOk(response));
|
||||
}
|
||||
return response;
|
||||
}
|
||||
protected HttpResponse get(final String url, final String sign_url, final HttpParameter... parameters)
|
||||
throws TwitterException {
|
||||
// intercept HTTP call for monitoring purposes
|
||||
HttpResponse response = null;
|
||||
final long start = System.currentTimeMillis();
|
||||
try {
|
||||
response = http.get(url, sign_url, parameters, auth);
|
||||
} finally {
|
||||
final long elapsedTime = System.currentTimeMillis() - start;
|
||||
TwitterAPIMonitor.getInstance().methodCalled(url, elapsedTime, isOk(response));
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
protected boolean isOk(final HttpResponse response) {
|
||||
return response != null && response.getStatusCode() < 300;
|
||||
}
|
||||
protected boolean isOk(final HttpResponse response) {
|
||||
return response != null && response.getStatusCode() < 300;
|
||||
}
|
||||
|
||||
protected HttpParameter[] mergeParameters(final HttpParameter[] params1, final HttpParameter... params2) {
|
||||
if (params1 != null && params2 != null) {
|
||||
final HttpParameter[] params = new HttpParameter[params1.length + params2.length];
|
||||
System.arraycopy(params1, 0, params, 0, params1.length);
|
||||
System.arraycopy(params2, 0, params, params1.length, params2.length);
|
||||
return params;
|
||||
}
|
||||
if (null == params1 && null == params2) return new HttpParameter[0];
|
||||
if (params1 != null)
|
||||
return params1;
|
||||
else
|
||||
return params2;
|
||||
}
|
||||
protected HttpParameter[] mergeParameters(final Paging paging, final HttpParameter... params2) {
|
||||
if (paging == null) {
|
||||
return params2;
|
||||
}
|
||||
return mergeParameters(paging.asPostParameterArray(), params2);
|
||||
}
|
||||
|
||||
protected HttpResponse post(final String url, final String sign_url, final HttpParameter... parameters)
|
||||
throws TwitterException {
|
||||
// intercept HTTP call for monitoring purposes
|
||||
HttpResponse response = null;
|
||||
final long start = System.currentTimeMillis();
|
||||
try {
|
||||
response = http.post(url, sign_url, parameters, auth);
|
||||
} finally {
|
||||
final long elapsedTime = System.currentTimeMillis() - start;
|
||||
TwitterAPIMonitor.getInstance().methodCalled(url, elapsedTime, isOk(response));
|
||||
}
|
||||
return response;
|
||||
}
|
||||
protected HttpParameter[] mergeParameters(final HttpParameter[] params1, final HttpParameter... params2) {
|
||||
if (params1 != null && params2 != null) {
|
||||
final HttpParameter[] params = new HttpParameter[params1.length + params2.length];
|
||||
System.arraycopy(params1, 0, params, 0, params1.length);
|
||||
System.arraycopy(params2, 0, params, params1.length, params2.length);
|
||||
return params;
|
||||
}
|
||||
if (null == params1 && null == params2) return new HttpParameter[0];
|
||||
if (params1 != null)
|
||||
return params1;
|
||||
else
|
||||
return params2;
|
||||
}
|
||||
|
||||
protected void setFactory() {
|
||||
factory = new InternalJSONFactoryImpl(conf);
|
||||
}
|
||||
protected HttpResponse post(final String url, final String sign_url, final HttpParameter... parameters)
|
||||
throws TwitterException {
|
||||
// intercept HTTP call for monitoring purposes
|
||||
HttpResponse response = null;
|
||||
final long start = System.currentTimeMillis();
|
||||
try {
|
||||
response = http.post(url, sign_url, parameters, auth);
|
||||
} finally {
|
||||
final long elapsedTime = System.currentTimeMillis() - start;
|
||||
TwitterAPIMonitor.getInstance().methodCalled(url, elapsedTime, isOk(response));
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
private OAuthSupport getOAuth() {
|
||||
if (!(auth instanceof OAuthSupport))
|
||||
throw new IllegalStateException("OAuth consumer key/secret combination not supplied");
|
||||
return (OAuthSupport) auth;
|
||||
}
|
||||
protected void setFactory() {
|
||||
factory = new InternalJSONFactoryImpl(conf);
|
||||
}
|
||||
|
||||
private void init() {
|
||||
if (null == auth) {
|
||||
// try to populate OAuthAuthorization if available in the
|
||||
// configuration
|
||||
final String consumerKey = conf.getOAuthConsumerKey();
|
||||
final String consumerSecret = conf.getOAuthConsumerSecret();
|
||||
// try to find oauth tokens in the configuration
|
||||
if (consumerKey != null && consumerSecret != null) {
|
||||
final OAuthAuthorization oauth = new OAuthAuthorization(conf);
|
||||
final String accessToken = conf.getOAuthAccessToken();
|
||||
final String accessTokenSecret = conf.getOAuthAccessTokenSecret();
|
||||
if (accessToken != null && accessTokenSecret != null) {
|
||||
oauth.setOAuthAccessToken(new AccessToken(accessToken, accessTokenSecret));
|
||||
}
|
||||
auth = oauth;
|
||||
} else {
|
||||
auth = NullAuthorization.getInstance();
|
||||
}
|
||||
}
|
||||
http = new HttpClientWrapper(conf);
|
||||
http.setHttpResponseListener(this);
|
||||
setFactory();
|
||||
}
|
||||
private OAuthSupport getOAuth() {
|
||||
if (!(auth instanceof OAuthSupport))
|
||||
throw new IllegalStateException("OAuth consumer key/secret combination not supplied");
|
||||
return (OAuthSupport) auth;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void readObject(final ObjectInputStream stream) throws IOException, ClassNotFoundException {
|
||||
conf = (Configuration) stream.readObject();
|
||||
auth = (Authorization) stream.readObject();
|
||||
rateLimitStatusListeners = (List<RateLimitStatusListener>) stream.readObject();
|
||||
http = new HttpClientWrapper(conf);
|
||||
http.setHttpResponseListener(this);
|
||||
setFactory();
|
||||
}
|
||||
private void init() {
|
||||
if (null == auth) {
|
||||
// try to populate OAuthAuthorization if available in the
|
||||
// configuration
|
||||
final String consumerKey = conf.getOAuthConsumerKey();
|
||||
final String consumerSecret = conf.getOAuthConsumerSecret();
|
||||
// try to find oauth tokens in the configuration
|
||||
if (consumerKey != null && consumerSecret != null) {
|
||||
final OAuthAuthorization oauth = new OAuthAuthorization(conf);
|
||||
final String accessToken = conf.getOAuthAccessToken();
|
||||
final String accessTokenSecret = conf.getOAuthAccessTokenSecret();
|
||||
if (accessToken != null && accessTokenSecret != null) {
|
||||
oauth.setOAuthAccessToken(new AccessToken(accessToken, accessTokenSecret));
|
||||
}
|
||||
auth = oauth;
|
||||
} else {
|
||||
auth = NullAuthorization.getInstance();
|
||||
}
|
||||
}
|
||||
http = new HttpClientWrapper(conf);
|
||||
http.setHttpResponseListener(this);
|
||||
setFactory();
|
||||
}
|
||||
|
||||
private void writeObject(final ObjectOutputStream out) throws IOException {
|
||||
out.writeObject(conf);
|
||||
out.writeObject(auth);
|
||||
final List<RateLimitStatusListener> serializableRateLimitStatusListeners = new ArrayList<RateLimitStatusListener>(
|
||||
0);
|
||||
for (final RateLimitStatusListener listener : rateLimitStatusListeners) {
|
||||
if (listener instanceof Serializable) {
|
||||
serializableRateLimitStatusListeners.add(listener);
|
||||
}
|
||||
}
|
||||
out.writeObject(serializableRateLimitStatusListeners);
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
private void readObject(final ObjectInputStream stream) throws IOException, ClassNotFoundException {
|
||||
conf = (Configuration) stream.readObject();
|
||||
auth = (Authorization) stream.readObject();
|
||||
rateLimitStatusListeners = (List<RateLimitStatusListener>) stream.readObject();
|
||||
http = new HttpClientWrapper(conf);
|
||||
http.setHttpResponseListener(this);
|
||||
setFactory();
|
||||
}
|
||||
|
||||
private void writeObject(final ObjectOutputStream out) throws IOException {
|
||||
out.writeObject(conf);
|
||||
out.writeObject(auth);
|
||||
final List<RateLimitStatusListener> serializableRateLimitStatusListeners = new ArrayList<RateLimitStatusListener>(
|
||||
0);
|
||||
for (final RateLimitStatusListener listener : rateLimitStatusListeners) {
|
||||
if (listener instanceof Serializable) {
|
||||
serializableRateLimitStatusListeners.add(listener);
|
||||
}
|
||||
}
|
||||
out.writeObject(serializableRateLimitStatusListeners);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,14 +46,12 @@ import static twitter4j.http.HttpParameter.getParameterArray;
|
|||
final class TwitterImpl extends TwitterBaseImpl implements Twitter {
|
||||
|
||||
private final HttpParameter INCLUDE_ENTITIES;
|
||||
|
||||
private final HttpParameter INCLUDE_RTS;
|
||||
|
||||
private final HttpParameter INCLUDE_MY_RETWEET;
|
||||
|
||||
private final HttpParameter INCLUDE_REPLY_COUNT;
|
||||
|
||||
private final HttpParameter INCLUDE_DESCENDENT_REPLY_COUNT;
|
||||
private final HttpParameter INCLUDE_CARDS;
|
||||
private final HttpParameter CARDS_PLATFORM;
|
||||
|
||||
/* package */
|
||||
TwitterImpl(final Configuration conf, final Authorization auth) {
|
||||
|
@ -63,6 +61,8 @@ final class TwitterImpl extends TwitterBaseImpl implements Twitter {
|
|||
INCLUDE_MY_RETWEET = new HttpParameter("include_my_retweet", 1);
|
||||
INCLUDE_REPLY_COUNT = new HttpParameter("include_reply_count", conf.isIncludeReplyCountEnabled());
|
||||
INCLUDE_DESCENDENT_REPLY_COUNT = new HttpParameter("include_descendent_reply_count", conf.isIncludeDescendentReplyCountEnabled());
|
||||
INCLUDE_CARDS = new HttpParameter("include_cards", conf.isIncludeCardsEnabled());
|
||||
CARDS_PLATFORM = new HttpParameter("cards_platform", conf.getCardsPlatform());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -485,15 +485,16 @@ final class TwitterImpl extends TwitterBaseImpl implements Twitter {
|
|||
ensureAuthorizationEnabled();
|
||||
return factory.createDirectMessageList(get(conf.getRestBaseURL() + ENDPOINT_DIRECT_MESSAGES,
|
||||
conf.getSigningRestBaseURL() + ENDPOINT_DIRECT_MESSAGES,
|
||||
mergeParameters(paging != null ? paging.asPostParameterArray() : null, INCLUDE_ENTITIES)));
|
||||
mergeParameters(paging, INCLUDE_ENTITIES)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseList<Status> getFavorites() throws TwitterException {
|
||||
ensureAuthorizationEnabled();
|
||||
return factory.createStatusList(get(conf.getRestBaseURL() + ENDPOINT_FAVORITES_LIST,
|
||||
conf.getSigningRestBaseURL() + ENDPOINT_FAVORITES_LIST, INCLUDE_ENTITIES,
|
||||
INCLUDE_REPLY_COUNT, INCLUDE_DESCENDENT_REPLY_COUNT));
|
||||
final String url = conf.getRestBaseURL() + ENDPOINT_FAVORITES_LIST;
|
||||
final String signUrl = conf.getSigningRestBaseURL() + ENDPOINT_FAVORITES_LIST;
|
||||
return factory.createStatusList(get(url, signUrl, INCLUDE_ENTITIES, INCLUDE_REPLY_COUNT,
|
||||
INCLUDE_DESCENDENT_REPLY_COUNT, INCLUDE_CARDS, CARDS_PLATFORM));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -502,7 +503,8 @@ final class TwitterImpl extends TwitterBaseImpl implements Twitter {
|
|||
final String url = conf.getRestBaseURL() + ENDPOINT_FAVORITES_LIST;
|
||||
final String signUrl = conf.getSigningRestBaseURL() + ENDPOINT_FAVORITES_LIST;
|
||||
return factory.createStatusList(get(url, signUrl, new HttpParameter("user_id", userId),
|
||||
INCLUDE_ENTITIES, INCLUDE_REPLY_COUNT, INCLUDE_DESCENDENT_REPLY_COUNT));
|
||||
INCLUDE_ENTITIES, INCLUDE_REPLY_COUNT, INCLUDE_DESCENDENT_REPLY_COUNT,
|
||||
INCLUDE_CARDS, CARDS_PLATFORM));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -510,9 +512,9 @@ final class TwitterImpl extends TwitterBaseImpl implements Twitter {
|
|||
ensureAuthorizationEnabled();
|
||||
final String url = conf.getRestBaseURL() + ENDPOINT_FAVORITES_LIST;
|
||||
final String signUrl = conf.getSigningRestBaseURL() + ENDPOINT_FAVORITES_LIST;
|
||||
return factory.createStatusList(get(url, signUrl, mergeParameters(paging.asPostParameterArray(),
|
||||
return factory.createStatusList(get(url, signUrl, mergeParameters(paging,
|
||||
new HttpParameter("user_id", userId), INCLUDE_ENTITIES, INCLUDE_REPLY_COUNT,
|
||||
INCLUDE_DESCENDENT_REPLY_COUNT)));
|
||||
INCLUDE_DESCENDENT_REPLY_COUNT, INCLUDE_CARDS, CARDS_PLATFORM)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -520,9 +522,8 @@ final class TwitterImpl extends TwitterBaseImpl implements Twitter {
|
|||
ensureAuthorizationEnabled();
|
||||
final String url = conf.getRestBaseURL() + ENDPOINT_FAVORITES_LIST;
|
||||
final String signUrl = conf.getSigningRestBaseURL() + ENDPOINT_FAVORITES_LIST;
|
||||
return factory.createStatusList(get(url, signUrl, mergeParameters(
|
||||
paging != null ? paging.asPostParameterArray() : null,
|
||||
INCLUDE_ENTITIES, INCLUDE_REPLY_COUNT, INCLUDE_DESCENDENT_REPLY_COUNT)));
|
||||
return factory.createStatusList(get(url, signUrl, mergeParameters(paging, INCLUDE_ENTITIES,
|
||||
INCLUDE_REPLY_COUNT, INCLUDE_DESCENDENT_REPLY_COUNT, INCLUDE_CARDS, CARDS_PLATFORM)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -531,7 +532,8 @@ final class TwitterImpl extends TwitterBaseImpl implements Twitter {
|
|||
final String url = conf.getRestBaseURL() + ENDPOINT_FAVORITES_LIST;
|
||||
final String signUrl = conf.getSigningRestBaseURL() + ENDPOINT_FAVORITES_LIST;
|
||||
return factory.createStatusList(get(url, signUrl, new HttpParameter("screen_name", screenName),
|
||||
INCLUDE_ENTITIES, INCLUDE_REPLY_COUNT, INCLUDE_DESCENDENT_REPLY_COUNT));
|
||||
INCLUDE_ENTITIES, INCLUDE_REPLY_COUNT, INCLUDE_DESCENDENT_REPLY_COUNT, INCLUDE_CARDS,
|
||||
CARDS_PLATFORM));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -541,7 +543,7 @@ final class TwitterImpl extends TwitterBaseImpl implements Twitter {
|
|||
final String signUrl = conf.getSigningRestBaseURL() + ENDPOINT_FAVORITES_LIST;
|
||||
return factory.createStatusList(get(url, signUrl, mergeParameters(paging.asPostParameterArray(),
|
||||
new HttpParameter("screen_name", screenName), INCLUDE_ENTITIES, INCLUDE_REPLY_COUNT,
|
||||
INCLUDE_DESCENDENT_REPLY_COUNT)));
|
||||
INCLUDE_DESCENDENT_REPLY_COUNT, INCLUDE_CARDS, CARDS_PLATFORM)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -649,6 +651,8 @@ final class TwitterImpl extends TwitterBaseImpl implements Twitter {
|
|||
paramsList.add(INCLUDE_MY_RETWEET);
|
||||
paramsList.add(INCLUDE_REPLY_COUNT);
|
||||
paramsList.add(INCLUDE_DESCENDENT_REPLY_COUNT);
|
||||
paramsList.add(INCLUDE_CARDS);
|
||||
paramsList.add(CARDS_PLATFORM);
|
||||
if (paging != null) {
|
||||
paramsList.addAll(paging.asPostParameterList());
|
||||
}
|
||||
|
@ -761,6 +765,8 @@ final class TwitterImpl extends TwitterBaseImpl implements Twitter {
|
|||
paramsList.add(INCLUDE_REPLY_COUNT);
|
||||
paramsList.add(INCLUDE_DESCENDENT_REPLY_COUNT);
|
||||
paramsList.add(INCLUDE_MY_RETWEET);
|
||||
paramsList.add(INCLUDE_CARDS);
|
||||
paramsList.add(CARDS_PLATFORM);
|
||||
if (paging != null) {
|
||||
paramsList.addAll(paging.asPostParameterList());
|
||||
}
|
||||
|
@ -1170,6 +1176,8 @@ final class TwitterImpl extends TwitterBaseImpl implements Twitter {
|
|||
paramsList.add(INCLUDE_REPLY_COUNT);
|
||||
paramsList.add(INCLUDE_DESCENDENT_REPLY_COUNT);
|
||||
paramsList.add(INCLUDE_MY_RETWEET);
|
||||
paramsList.add(INCLUDE_CARDS);
|
||||
paramsList.add(CARDS_PLATFORM);
|
||||
paramsList.add(new HttpParameter("user_id", userId));
|
||||
if (paging != null) {
|
||||
paramsList.addAll(paging.asPostParameterList());
|
||||
|
|
|
@ -26,6 +26,8 @@ import twitter4j.http.HttpClientWrapperConfiguration;
|
|||
public interface Configuration extends HttpClientConfiguration, HttpClientWrapperConfiguration,
|
||||
AuthorizationConfiguration {
|
||||
|
||||
String getCardsPlatform();
|
||||
|
||||
String getClientName();
|
||||
|
||||
String getClientURL();
|
||||
|
@ -62,6 +64,8 @@ public interface Configuration extends HttpClientConfiguration, HttpClientWrappe
|
|||
|
||||
boolean isDebugEnabled();
|
||||
|
||||
boolean isIncludeCardsEnabled();
|
||||
|
||||
boolean isIncludeEntitiesEnabled();
|
||||
|
||||
boolean isIncludeRTsEnabled();
|
||||
|
|
|
@ -101,6 +101,8 @@ class ConfigurationBase implements TwitterConstants, Configuration {
|
|||
Map<String, String> requestHeaders;
|
||||
|
||||
private static final List<ConfigurationBase> instances = new ArrayList<ConfigurationBase>();
|
||||
private boolean includeCards;
|
||||
private String cardsPlatform;
|
||||
|
||||
protected ConfigurationBase() {
|
||||
setDebug(false);
|
||||
|
@ -257,6 +259,10 @@ class ConfigurationBase implements TwitterConstants, Configuration {
|
|||
return true;
|
||||
}
|
||||
|
||||
public String getCardsPlatform() {
|
||||
return cardsPlatform;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getClientName() {
|
||||
return clientName;
|
||||
|
@ -498,6 +504,11 @@ class ConfigurationBase implements TwitterConstants, Configuration {
|
|||
return debug;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIncludeCardsEnabled() {
|
||||
return includeCards;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGZIPEnabled() {
|
||||
return gzipEnabled;
|
||||
|
@ -548,6 +559,14 @@ class ConfigurationBase implements TwitterConstants, Configuration {
|
|||
return includeTwitterClientHeader;
|
||||
}
|
||||
|
||||
public void setCardsPlatform(String cardsPlatform) {
|
||||
this.cardsPlatform = cardsPlatform;
|
||||
}
|
||||
|
||||
public void setIncludeCards(boolean includeCards) {
|
||||
this.includeCards = includeCards;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ConfigurationBase{debug=" + debug + ", userAgent=" + userAgent + ", user=" + user + ", password="
|
||||
|
|
|
@ -76,7 +76,8 @@ public final class ConfigurationBuilder {
|
|||
configuration.setSigningUploadBaseURL(conf.getSigningUploadBaseURL());
|
||||
configuration.setUser(conf.getUser());
|
||||
configuration.setUseSSL(conf.isSSLEnabled());
|
||||
|
||||
configuration.setIncludeCards(conf.isIncludeCardsEnabled());
|
||||
configuration.setCardsPlatform(conf.getCardsPlatform());
|
||||
}
|
||||
|
||||
public Configuration build() {
|
||||
|
@ -318,6 +319,19 @@ public final class ConfigurationBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public ConfigurationBuilder setIncludeCards(final boolean includeCards) {
|
||||
checkNotBuilt();
|
||||
configuration.setIncludeCards(includeCards);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public ConfigurationBuilder setCardsPlatform(final String cardsPlatform) {
|
||||
checkNotBuilt();
|
||||
configuration.setCardsPlatform(cardsPlatform);
|
||||
return this;
|
||||
}
|
||||
|
||||
private void checkNotBuilt() {
|
||||
if (configuration == null)
|
||||
throw new IllegalStateException("Cannot use this builder any longer, build() has already been called");
|
||||
|
|
|
@ -0,0 +1,220 @@
|
|||
/*
|
||||
* 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 twitter4j.internal.json;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import twitter4j.CardEntity;
|
||||
import twitter4j.TwitterException;
|
||||
import twitter4j.User;
|
||||
import twitter4j.internal.util.InternalParseUtil;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 14/12/31.
|
||||
*/
|
||||
public class CardEntityJSONImpl implements CardEntity {
|
||||
|
||||
private final String name;
|
||||
private final Map<String, BindingValue> bindingValues;
|
||||
private final User[] users;
|
||||
|
||||
public CardEntityJSONImpl(JSONObject json) throws JSONException, TwitterException {
|
||||
this.name = json.getString("name");
|
||||
this.bindingValues = BindingValueImpl.valuesOf(json.getJSONObject("binding_values"));
|
||||
if (!json.isNull("users")) {
|
||||
final JSONObject usersJSON = json.getJSONObject("users");
|
||||
final Iterator<String> keys = usersJSON.keys();
|
||||
this.users = new UserJSONImpl[usersJSON.length()];
|
||||
int idx = 0;
|
||||
while (keys.hasNext()) {
|
||||
users[idx++] = new UserJSONImpl(usersJSON.getJSONObject(keys.next()));
|
||||
}
|
||||
} else {
|
||||
users = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public User[] gerUsers() {
|
||||
return users;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BindingValue getBindingValue(String name) {
|
||||
return bindingValues.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BindingValue[] getBindingValues() {
|
||||
return bindingValues.values().toArray(new BindingValue[bindingValues.size()]);
|
||||
}
|
||||
|
||||
|
||||
public static abstract class BindingValueImpl implements BindingValue {
|
||||
protected final String name, type;
|
||||
|
||||
BindingValueImpl(String name, JSONObject json) throws JSONException {
|
||||
this.name = name;
|
||||
this.type = json.getString("type");
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
private static BindingValue valueOf(String name, JSONObject json) throws JSONException {
|
||||
final String type = json.optString("type");
|
||||
if ("STRING".equals(type)) {
|
||||
return new StringValueImpl(name, json);
|
||||
} else if ("IMAGE".equals(type)) {
|
||||
return new ImageValueImpl(name, json);
|
||||
} else if ("USER".equals(type)) {
|
||||
return new UserValueImpl(name, json);
|
||||
}
|
||||
throw new UnsupportedOperationException(String.format("Unsupported type %s", type));
|
||||
}
|
||||
|
||||
private static HashMap<String, BindingValue> valuesOf(JSONObject json) throws JSONException {
|
||||
final Iterator<String> keys = json.keys();
|
||||
final HashMap<String, BindingValue> values = new HashMap<>();
|
||||
while (keys.hasNext()) {
|
||||
String key = keys.next();
|
||||
values.put(key, valueOf(key, json.getJSONObject(key)));
|
||||
}
|
||||
return values;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ImageValueImpl extends BindingValueImpl implements ImageValue {
|
||||
|
||||
private final int width, height;
|
||||
private final String url;
|
||||
|
||||
ImageValueImpl(String name, JSONObject json) throws JSONException {
|
||||
super(name, json);
|
||||
final JSONObject imageValue = json.getJSONObject("image_value");
|
||||
this.width = imageValue.getInt("width");
|
||||
this.height = imageValue.getInt("height");
|
||||
this.url = imageValue.getString("url");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ImageValueImpl{" +
|
||||
"name='" + name + '\'' +
|
||||
"width=" + width +
|
||||
", height=" + height +
|
||||
", url='" + url + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
private static final class StringValueImpl extends BindingValueImpl implements StringValue {
|
||||
|
||||
private final String value;
|
||||
|
||||
StringValueImpl(String name, JSONObject json) throws JSONException {
|
||||
super(name, json);
|
||||
this.value = json.getString("string_value");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "StringValueImpl{" +
|
||||
"name='" + name + '\'' +
|
||||
"value='" + value + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private static final class UserValueImpl extends BindingValueImpl implements UserValue {
|
||||
|
||||
private final long userId;
|
||||
|
||||
UserValueImpl(String name, JSONObject json) throws JSONException {
|
||||
super(name, json);
|
||||
final JSONObject userValue = json.getJSONObject("user_value");
|
||||
this.userId = InternalParseUtil.getLong("id_str", userValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UserValueImpl{" +
|
||||
"name='" + name + '\'' +
|
||||
"userId='" + userId + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CardEntityJSONImpl{" +
|
||||
"name='" + name + '\'' +
|
||||
", bindingValues=" + bindingValues +
|
||||
", users=" + Arrays.toString(users) +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -23,6 +23,7 @@ import org.json.JSONObject;
|
|||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
|
||||
import twitter4j.CardEntity;
|
||||
import twitter4j.GeoLocation;
|
||||
import twitter4j.HashtagEntity;
|
||||
import twitter4j.MediaEntity;
|
||||
|
@ -72,6 +73,7 @@ final class StatusJSONImpl extends TwitterResponseImpl implements Status {
|
|||
private Place place = null;
|
||||
private long retweetCount;
|
||||
private long favoriteCount;
|
||||
private CardEntity cardEntity;
|
||||
|
||||
public long getReplyCount() {
|
||||
return replyCount;
|
||||
|
@ -332,6 +334,11 @@ final class StatusJSONImpl extends TwitterResponseImpl implements Status {
|
|||
return isTruncated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CardEntity getCard() {
|
||||
return cardEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "StatusJSONImpl{createdAt=" + createdAt + ", id=" + id + ", text=" + text + ", rawText=" + rawText
|
||||
|
@ -470,6 +477,13 @@ final class StatusJSONImpl extends TwitterResponseImpl implements Status {
|
|||
logger.warn("failed to parse current_user_retweet:" + json);
|
||||
}
|
||||
}
|
||||
if (!json.isNull("card")) {
|
||||
try {
|
||||
cardEntity = new CardEntityJSONImpl(json.getJSONObject("card"));
|
||||
} catch (JSONException jsone) {
|
||||
throw new TwitterException(jsone);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* package */
|
||||
|
|
|
@ -21,8 +21,10 @@
|
|||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="wrap_content"
|
||||
>
|
||||
|
||||
<android.support.v7.widget.CardView
|
||||
android:id="@+id/card"
|
||||
|
@ -168,6 +170,12 @@
|
|||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:textIsSelectable="true"/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/twitter_card"
|
||||
android:layout_width="match_parent"
|
||||
android:minHeight="200dp"
|
||||
android:layout_height="wrap_content"></FrameLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/location_container"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -236,7 +244,8 @@
|
|||
android:layout_marginRight="@dimen/element_spacing_small"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:textAppearanceSmall"
|
||||
android:textColor="?android:textColorPrimary"/>
|
||||
android:textColor="?android:textColorPrimary"
|
||||
tools:text="255"/>
|
||||
|
||||
<org.mariotaku.twidere.view.themed.ThemedTextView
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -265,7 +274,8 @@
|
|||
android:layout_marginRight="@dimen/element_spacing_small"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:textAppearanceSmall"
|
||||
android:textColor="?android:textColorPrimary"/>
|
||||
android:textColor="?android:textColorPrimary"
|
||||
tools:text="255"/>
|
||||
|
||||
<org.mariotaku.twidere.view.themed.ThemedTextView
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -294,7 +304,8 @@
|
|||
android:layout_marginRight="@dimen/element_spacing_small"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:textAppearanceSmall"
|
||||
android:textColor="?android:textColorPrimary"/>
|
||||
android:textColor="?android:textColorPrimary"
|
||||
tools:text="255"/>
|
||||
|
||||
<org.mariotaku.twidere.view.themed.ThemedTextView
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
@ -137,13 +137,15 @@
|
|||
<item>@string/card_highlight_option_line</item>
|
||||
<item>@string/none</item>
|
||||
</string-array>
|
||||
<string-array name="values_image_preview_scale_type">
|
||||
<item>CENTER_CROP</item>
|
||||
<item>FIT_CENTER</item>
|
||||
<string-array name="values_media_preview_style">
|
||||
<item>crop</item>
|
||||
<item>scale</item>
|
||||
<item>none</item>
|
||||
</string-array>
|
||||
<string-array name="entries_image_preview_scale_type">
|
||||
<item>@string/image_preview_scale_type_crop</item>
|
||||
<item>@string/image_preview_scale_type_fit_center</item>
|
||||
<string-array name="entries_media_preview_style">
|
||||
<item>@string/crop</item>
|
||||
<item>@string/scale</item>
|
||||
<item>@string/none</item>
|
||||
</string-array>
|
||||
<string-array name="entries_image_sources">
|
||||
<item>@string/from_camera</item>
|
||||
|
@ -153,5 +155,15 @@
|
|||
<item>camera</item>
|
||||
<item>gallery</item>
|
||||
</string-array>
|
||||
<string-array name="values_profile_image_style">
|
||||
<item>round</item>
|
||||
<item>square</item>
|
||||
</string-array>
|
||||
<string-array name="entries_profile_image_style">
|
||||
<item>@string/round</item>
|
||||
<item>@string/square</item>
|
||||
</string-array>
|
||||
|
||||
<string name="crop">Crop</string>
|
||||
<string name="scale">Scale</string>
|
||||
</resources>
|
|
@ -692,5 +692,12 @@
|
|||
<string name="size">Size</string>
|
||||
<string name="just_now">Just now</string>
|
||||
<string name="requested">Requested</string>
|
||||
<string name="round">Round</string>
|
||||
<string name="square">Square</string>
|
||||
<string name="profile_image_style">Profile image style</string>
|
||||
<string name="default_profile_image_style">round</string>
|
||||
<string name="media_preview_style">Media preview style</string>
|
||||
<string name="draft_saved">Draft saved</string>
|
||||
<string name="open_twitter_links">Open Twitter links</string>
|
||||
|
||||
</resources>
|
|
@ -21,27 +21,7 @@
|
|||
android:order="23"
|
||||
android:summary="@string/nickname_only_summary"
|
||||
android:title="@string/nickname_only"/>
|
||||
<org.mariotaku.twidere.preference.AutoFixCheckBoxPreference
|
||||
android:defaultValue="true"
|
||||
android:key="display_profile_image"
|
||||
android:order="24"
|
||||
android:summary="@string/image_load_summary"
|
||||
android:title="@string/display_profile_image"/>
|
||||
<org.mariotaku.twidere.preference.AutoFixCheckBoxPreference
|
||||
android:defaultValue="false"
|
||||
android:key="display_image_preview"
|
||||
android:order="25"
|
||||
android:summary="@string/image_load_summary"
|
||||
android:title="@string/display_image_preview"/>
|
||||
|
||||
<org.mariotaku.twidere.preference.AutoFixListPreference
|
||||
android:defaultValue="CENTER_CROP"
|
||||
android:entries="@array/entries_image_preview_scale_type"
|
||||
android:entryValues="@array/values_image_preview_scale_type"
|
||||
android:key="image_preview_scale_type"
|
||||
android:order="26"
|
||||
android:summary="%s"
|
||||
android:title="@string/image_preview_scale_type"/>
|
||||
|
||||
<org.mariotaku.twidere.preference.LinkHighlightPreference
|
||||
android:defaultValue="none"
|
||||
|
|
|
@ -38,12 +38,25 @@
|
|||
android:key="fast_scroll_thumb"
|
||||
android:title="@string/fast_scroll_thumb"/>
|
||||
|
||||
<org.mariotaku.twidere.preference.AutoInvalidateListPreference
|
||||
<org.mariotaku.twidere.preference.SummaryListPreference
|
||||
android:defaultValue="@string/default_tab_display_option"
|
||||
android:entries="@array/entries_tab_display_option"
|
||||
android:entryValues="@array/values_tab_display_option"
|
||||
android:key="tab_display_option"
|
||||
android:summary="%s"
|
||||
android:title="@string/tab_display_option"/>
|
||||
|
||||
<org.mariotaku.twidere.preference.SummaryListPreference
|
||||
android:defaultValue="@string/default_profile_image_style"
|
||||
android:entries="@array/entries_profile_image_style"
|
||||
android:entryValues="@array/values_profile_image_style"
|
||||
android:key="profile_image_style"
|
||||
android:title="@string/profile_image_style"/>
|
||||
|
||||
<org.mariotaku.twidere.preference.SummaryListPreference
|
||||
android:defaultValue="crop"
|
||||
android:entries="@array/entries_media_preview_style"
|
||||
android:entryValues="@array/values_media_preview_style"
|
||||
android:key="media_preview_style"
|
||||
android:title="@string/media_preview_style"/>
|
||||
|
||||
</PreferenceScreen>
|
|
@ -18,7 +18,7 @@
|
|||
<org.mariotaku.twidere.preference.ComponentStatePreference
|
||||
android:name="org.mariotaku.twidere.activity.TwitterLinkHandlerActivity"
|
||||
android:key="twitter_link_handler"
|
||||
android:title="@string/twitter_link_handler"/>
|
||||
android:title="@string/open_twitter_links"/>
|
||||
|
||||
<org.mariotaku.twidere.preference.ComponentStatePreference
|
||||
android:name="org.mariotaku.twidere.activity.AssistLauncherActivity"
|
||||
|
@ -26,13 +26,12 @@
|
|||
android:summary="@string/compose_now_summary"
|
||||
android:title="@string/compose_now"/>
|
||||
|
||||
<org.mariotaku.twidere.preference.AutoInvalidateListPreference
|
||||
<org.mariotaku.twidere.preference.SummaryListPreference
|
||||
android:defaultValue="compose"
|
||||
android:dependency="compose_now"
|
||||
android:entries="@array/entries_compose_now_action"
|
||||
android:entryValues="@array/values_compose_now_action"
|
||||
android:key="compose_now_action"
|
||||
android:summary="%s"
|
||||
android:title="@string/compose_now_action"/>
|
||||
|
||||
<Preference
|
||||
|
|
Loading…
Reference in New Issue