added new endpoint, added reply hide option, renamed database methods, added comments

This commit is contained in:
nuclearfog 2022-05-13 22:34:49 +02:00
parent 5ac3ce9c38
commit 6d7eb16191
No known key found for this signature in database
GPG Key ID: AA0271FBE406DB98
12 changed files with 240 additions and 95 deletions

View File

@ -70,6 +70,7 @@ public class Twitter implements GlobalSettings.SettingsListener {
public static final String SIGNATURE_ALG = "HMAC-SHA256";
private static final String OAUTH = "1.0";
private static final String JSON = ".json";
private static final String API = "https://api.twitter.com/";
private static final String UPLOAD = "https://upload.twitter.com/";
private static final String DOWNLOAD = "https://ton.twitter.com/";
@ -106,6 +107,7 @@ public class Twitter implements GlobalSettings.SettingsListener {
private static final String TWEET_UNRETWEET = API + "1.1/statuses/unretweet/";
private static final String TWEET_UPLOAD = API + "1.1/statuses/update.json";
private static final String TWEET_DELETE = API + "1.1/statuses/destroy/";
private static final String TWEET_HIDE = API + "2/tweets/";
private static final String TRENDS = API + "1.1/trends/place.json";
private static final String LOCATIONS = API + "1.1/trends/available.json";
private static final String USERLIST_SHOW = API + "1.1/lists/show.json";
@ -827,7 +829,7 @@ public class Twitter implements GlobalSettings.SettingsListener {
* @return updated tweet
*/
public Tweet retweetTweet(long tweetId) throws TwitterException {
TweetV1 result = getTweet1(TWEET_RETWEET + tweetId + ".json", new ArrayList<>(2));
TweetV1 result = getTweet1(TWEET_RETWEET + tweetId + JSON, new ArrayList<>(2));
result.setRetweet(true);
return result;
}
@ -839,18 +841,44 @@ public class Twitter implements GlobalSettings.SettingsListener {
* @return updated tweet
*/
public Tweet unretweetTweet(long tweetId) throws TwitterException {
TweetV1 result = getTweet1(TWEET_UNRETWEET + tweetId + ".json", new ArrayList<>(2));
TweetV1 result = getTweet1(TWEET_UNRETWEET + tweetId + JSON, new ArrayList<>(2));
result.setRetweet(false);
return result;
}
/**
* hides reply of the own tweet
*
* @param tweetId ID of the tweet
* @param hide true to hide reply
*/
public void hideReply(long tweetId, boolean hide) throws TwitterException {
try {
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\"hidden\":" + hide + "}");
Response response = put(TWEET_HIDE + tweetId + "/hidden", new ArrayList<>(2), body);
if (response.body() != null && response.code() == 200) {
JSONObject json = new JSONObject(response.body().string());
if (json.getJSONObject("data").getBoolean("hidden") == hide) {
return; // successfull if result equals request
}
}
throw new TwitterException(response);
} catch (IOException e) {
throw new TwitterException(e);
} catch (JSONException e) {
throw new TwitterException(e);
}
}
/**
* remove tweet of the authenticating user
*
* @param tweetId tweet ID
*/
public void deleteTweet(long tweetId) throws TwitterException {
getTweet1(TWEET_DELETE + tweetId + ".json", new ArrayList<>(2));
getTweet1(TWEET_DELETE + tweetId + JSON, new ArrayList<>(2));
}
/**
@ -1680,6 +1708,19 @@ public class Twitter implements GlobalSettings.SettingsListener {
return client.newCall(request).execute();
}
/**
* create and call PUT endpoint
*
* @param endpoint endpoint url
* @return http response
*/
private Response put(String endpoint, List<String> params, RequestBody body)throws IOException {
String authHeader = buildHeader("PUT", endpoint, params);
String url = appendParams(endpoint, params);
Request request = new Request.Builder().url(url).addHeader("Authorization", authHeader).put(body).build();
return client.newCall(request).execute();
}
/**
* create and call GET endpoint
*

View File

@ -69,7 +69,7 @@ public class TweetV1 implements Tweet {
author = new UserV1(json.getJSONObject("user"), twitterId);
id = Long.parseLong(json.optString("id_str", "-1"));
replyId = json.optLong("in_reply_to_status_id", -1);
replyUserId = json.optLong("in_reply_to_status_id", -1);
replyUserId = json.optLong("in_reply_to_user_id", -1);
retweetCount = json.optInt("retweet_count");
favoriteCount = json.optInt("favorite_count");
isFavorited = json.optBoolean("favorited");
@ -212,6 +212,11 @@ public class TweetV1 implements Tweet {
return coordinates;
}
@Override
public boolean isHidden() {
return false;
}
@Override
public boolean equals(@Nullable Object obj) {
if (!(obj instanceof Tweet))

View File

@ -49,6 +49,14 @@ public class TweetAction extends AsyncTask<Void, Tweet, Void> {
* remove tweet from favorites
*/
UNFAVORITE,
/**
* hide reply
*/
HIDE,
/**
* unhide reply
*/
UNHIDE,
/**
* delete own tweet
*/
@ -85,7 +93,7 @@ public class TweetAction extends AsyncTask<Void, Tweet, Void> {
try {
switch (action) {
case LD_DB:
Tweet tweet = db.getStatus(tweetId);
Tweet tweet = db.getTweet(tweetId);
if (tweet != null) {
publishProgress(tweet);
}
@ -94,35 +102,35 @@ public class TweetAction extends AsyncTask<Void, Tweet, Void> {
tweet = twitter.showTweet(tweetId);
//tweet = mTwitter.getStatus(tweetId);
publishProgress(tweet);
if (db.containStatus(tweetId)) {
if (db.containsTweet(tweetId)) {
// update tweet if there is a database entry
db.updateStatus(tweet);
db.updateTweet(tweet);
}
break;
case DELETE:
twitter.deleteTweet(tweetId);
db.removeStatus(tweetId);
db.removeTweet(tweetId);
// removing retweet reference to this tweet
if (retweetId > 0)
db.removeStatus(retweetId);
db.removeTweet(retweetId);
break;
case RETWEET:
tweet = twitter.retweetTweet(tweetId);
publishProgress(tweet);
db.updateStatus(tweet);
db.updateTweet(tweet);
break;
case UNRETWEET:
tweet = twitter.unretweetTweet(tweetId);
publishProgress(tweet);
db.updateStatus(tweet);
db.updateTweet(tweet);
// removing retweet reference to this tweet
if (retweetId > 0)
db.removeStatus(retweetId);
db.removeTweet(retweetId);
else
db.removeStatus(tweetId);
db.removeTweet(tweetId);
break;
case FAVORITE:
@ -136,11 +144,21 @@ public class TweetAction extends AsyncTask<Void, Tweet, Void> {
publishProgress(tweet);
db.removeFavorite(tweet);
break;
case HIDE:
twitter.hideReply(tweetId, true);
db.hideReply(tweetId, true);
break;
case UNHIDE:
twitter.hideReply(tweetId, false);
db.hideReply(tweetId, false);
break;
}
} catch (TwitterException twException) {
this.twException = twException;
if (twException.getErrorType() == ErrorHandler.TwitterError.RESOURCE_NOT_FOUND) {
db.removeStatus(tweetId);
db.removeTweet(tweetId);
}
}
return null;
@ -161,7 +179,7 @@ public class TweetAction extends AsyncTask<Void, Tweet, Void> {
TweetActivity activity = weakRef.get();
if (activity != null) {
if (twException == null) {
activity.onAction(action, tweetId);
activity.OnSuccess(action, tweetId);
} else {
activity.onError(twException, tweetId);
}

View File

@ -170,21 +170,21 @@ public class TweetLoader extends AsyncTask<Long, Void, List<Tweet>> {
break;
case REPLIES_OFFLINE:
tweets = db.getAnswers(id);
tweets = db.getTweetReplies(id);
break;
case REPLIES:
if (sinceId == 0 && maxId == 0) {
tweets = db.getAnswers(id);
tweets = db.getTweetReplies(id);
if (tweets.isEmpty()) {
tweets = twitter.getTweetReplies(search, id, sinceId, maxId);
if (!tweets.isEmpty() && db.containStatus(id)) {
if (!tweets.isEmpty() && db.containsTweet(id)) {
db.storeReplies(tweets);
}
}
} else if (sinceId > 0) {
tweets = twitter.getTweetReplies(search, id, sinceId, maxId);
if (!tweets.isEmpty() && db.containStatus(id)) {
if (!tweets.isEmpty() && db.containsTweet(id)) {
db.storeReplies(tweets);
}
} else if (maxId > 1) {

View File

@ -51,6 +51,7 @@ public class AppDatabase {
public static final int MEDIA_VIDEO_MASK = 2 << 6; // tweet contains a video
public static final int MEDIA_ANGIF_MASK = 3 << 6; // tweet contains an animation
public static final int MEDIA_SENS_MASK = 1 << 8; // tweet contains sensitive media
public static final int HIDDEN_MASK = 1 << 9; // tweet is hidden
// user status bits
public static final int VER_MASK = 1; // user is verified
@ -134,11 +135,12 @@ public class AppDatabase {
/**
* SQL query to get replies of a tweet specified by a tweet ID
*/
static final String ANSWER_QUERY = "SELECT * FROM " + TWEET_TABLE
static final String REPLY_QUERY = "SELECT * FROM " + TWEET_TABLE
+ " WHERE " + TweetTable.NAME + "." + TweetTable.REPLYTWEET + "=?"
+ " AND " + TweetRegisterTable.NAME + "." + TweetRegisterTable.OWNER + "=?"
+ " AND " + UserRegisterTable.NAME + "." + UserRegisterTable.OWNER + "=?"
+ " AND " + TweetRegisterTable.NAME + "." + TweetRegisterTable.REGISTER + "&" + RPL_MASK + " IS NOT 0"
+ " AND " + TweetRegisterTable.NAME + "." + TweetRegisterTable.REGISTER + "&" + HIDDEN_MASK + " IS 0"
+ " AND " + UserRegisterTable.NAME + "." + UserRegisterTable.REGISTER + "&" + EXCL_USR + " IS 0"
+ " ORDER BY " + TweetTable.ID + " DESC LIMIT ?";
@ -259,7 +261,7 @@ public class AppDatabase {
public void storeHomeTimeline(List<Tweet> home) {
SQLiteDatabase db = getDbWrite();
for (Tweet tweet : home)
storeStatus(tweet, HOM_MASK, db);
storeTweet(tweet, HOM_MASK, db);
commit(db);
}
@ -271,7 +273,7 @@ public class AppDatabase {
public void storeMentions(List<Tweet> mentions) {
SQLiteDatabase db = getDbWrite();
for (Tweet tweet : mentions)
storeStatus(tweet, MEN_MASK, db);
storeTweet(tweet, MEN_MASK, db);
commit(db);
}
@ -283,7 +285,7 @@ public class AppDatabase {
public void storeUserTweets(List<Tweet> stats) {
SQLiteDatabase db = getDbWrite();
for (Tweet tweet : stats)
storeStatus(tweet, UTW_MASK, db);
storeTweet(tweet, UTW_MASK, db);
commit(db);
}
@ -297,7 +299,7 @@ public class AppDatabase {
SQLiteDatabase db = getDbWrite();
removeOldFavorites(db, ownerId);
for (Tweet tweet : fav) {
storeStatus(tweet, 0, db);
storeTweet(tweet, 0, db);
storeFavorite(tweet.getId(), ownerId, db);
}
commit(db);
@ -311,7 +313,7 @@ public class AppDatabase {
public void storeReplies(List<Tweet> replies) {
SQLiteDatabase db = getDbWrite();
for (Tweet tweet : replies)
storeStatus(tweet, RPL_MASK, db);
storeTweet(tweet, RPL_MASK, db);
commit(db);
}
@ -345,7 +347,7 @@ public class AppDatabase {
if (tweet.getEmbeddedTweet() != null)
tweet = tweet.getEmbeddedTweet();
SQLiteDatabase db = getDbWrite();
storeStatus(tweet, 0, db);
storeTweet(tweet, 0, db);
storeFavorite(tweet.getId(), homeId, db);
commit(db);
}
@ -376,7 +378,7 @@ public class AppDatabase {
Cursor cursor = db.rawQuery(HOME_QUERY, args);
if (cursor.moveToFirst()) {
do {
Tweet tweet = getStatus(cursor);
Tweet tweet = getTweet(cursor);
tweetList.add(tweet);
} while (cursor.moveToNext());
}
@ -398,7 +400,7 @@ public class AppDatabase {
Cursor cursor = db.rawQuery(MENTION_QUERY, args);
if (cursor.moveToFirst()) {
do {
Tweet tweet = getStatus(cursor);
Tweet tweet = getTweet(cursor);
tweetList.add(tweet);
} while (cursor.moveToNext());
}
@ -421,7 +423,7 @@ public class AppDatabase {
Cursor cursor = db.rawQuery(USERTWEET_QUERY, args);
if (cursor.moveToFirst()) {
do {
Tweet tweet = getStatus(cursor);
Tweet tweet = getTweet(cursor);
tweetList.add(tweet);
} while (cursor.moveToNext());
}
@ -444,7 +446,7 @@ public class AppDatabase {
Cursor cursor = db.rawQuery(USERFAVORIT_QUERY, args);
if (cursor.moveToFirst()) {
do {
Tweet tweet = getStatus(cursor);
Tweet tweet = getTweet(cursor);
tweetList.add(tweet);
} while (cursor.moveToNext());
}
@ -465,13 +467,13 @@ public class AppDatabase {
}
/**
* load status
* get tweet from database
*
* @param tweetId tweet ID
* @return tweet or null if not found
*/
@Nullable
public Tweet getStatus(long tweetId) {
public Tweet getTweet(long tweetId) {
String homeStr = Long.toString(homeId);
String[] args = {Long.toString(tweetId), homeStr, homeStr};
@ -479,27 +481,27 @@ public class AppDatabase {
Tweet result = null;
Cursor cursor = db.rawQuery(SINGLE_TWEET_QUERY, args);
if (cursor.moveToFirst())
result = getStatus(cursor);
result = getTweet(cursor);
cursor.close();
return result;
}
/**
* get tweet answers
* get tweet replies
*
* @param tweetId Tweet ID
* @return list of tweet answers
* @return list of tweets
*/
public List<Tweet> getAnswers(long tweetId) {
public List<Tweet> getTweetReplies(long tweetId) {
String homeStr = Long.toString(homeId);
String[] args = {Long.toString(tweetId), homeStr, homeStr, Integer.toString(limit)};
SQLiteDatabase db = getDbRead();
List<Tweet> tweetList = new LinkedList<>();
Cursor cursor = db.rawQuery(ANSWER_QUERY, args);
Cursor cursor = db.rawQuery(REPLY_QUERY, args);
if (cursor.moveToFirst()) {
do {
Tweet tweet = getStatus(cursor);
Tweet tweet = getTweet(cursor);
tweetList.add(tweet);
} while (cursor.moveToNext());
}
@ -508,24 +510,24 @@ public class AppDatabase {
}
/**
* update status and author information
* update tweet and author information
*
* @param tweet Tweet
*/
public void updateStatus(Tweet tweet) {
public void updateTweet(Tweet tweet) {
SQLiteDatabase db = getDbWrite();
updateStatus(tweet, db);
updateTweet(tweet, db);
if (tweet.getEmbeddedTweet() != null)
updateStatus(tweet.getEmbeddedTweet(), db);
updateTweet(tweet.getEmbeddedTweet(), db);
commit(db);
}
/**
* remove status
* remove tweet from database
*
* @param tweetId Tweet ID
*/
public void removeStatus(long tweetId) {
public void removeTweet(long tweetId) {
String[] args = {Long.toString(tweetId)};
SQLiteDatabase db = getDbWrite();
@ -535,7 +537,29 @@ public class AppDatabase {
}
/**
* remove status from favorites
* hide or unhide tweet reply
*
* @param replyId ID of the reply
* @param hide true to hide this tweet
*/
public void hideReply(long replyId, boolean hide) {
String[] args = {Long.toString(replyId), Long.toString(homeId)};
SQLiteDatabase db = getDbWrite();
int register = getTweetRegister(db, replyId);
if (hide)
register |= HIDDEN_MASK;
else
register &= ~HIDDEN_MASK;
ContentValues values = new ContentValues(3);
values.put(TweetRegisterTable.REGISTER, register);
db.update(TweetRegisterTable.NAME, values, TWEET_REG_SELECT, args);
commit(db);
}
/**
* remove tweet from favorites
*
* @param tweet Tweet to remove from the favorites
*/
@ -633,9 +657,9 @@ public class AppDatabase {
* @param id Tweet ID
* @return true if found
*/
public boolean containStatus(long id) {
public boolean containsTweet(long id) {
SQLiteDatabase db = getDbRead();
return containStatus(id, db);
return tweetExists(id, db);
}
/**
@ -662,11 +686,11 @@ public class AppDatabase {
* @param cursor cursor containing tweet informations
* @return tweet instance
*/
private Tweet getStatus(Cursor cursor) {
private Tweet getTweet(Cursor cursor) {
TweetImpl result = new TweetImpl(cursor, homeId);
// check if there is an embedded tweet
if (result.getEmbeddedTweetId() > 1)
result.addEmbeddedTweet(getStatus(result.getEmbeddedTweetId()));
result.addEmbeddedTweet(getTweet(result.getEmbeddedTweetId()));
return result;
}
@ -739,61 +763,61 @@ public class AppDatabase {
* save tweet into database
*
* @param tweet Tweet information
* @param statusRegister predefined status register or zero if there isn't one
* @param tweetFlags predefined tweet status register or zero if there isn't one
* @param db SQLite database
*/
private void storeStatus(Tweet tweet, int statusRegister, SQLiteDatabase db) {
private void storeTweet(Tweet tweet, int tweetFlags, SQLiteDatabase db) {
User user = tweet.getAuthor();
Tweet rtStat = tweet.getEmbeddedTweet();
long rtId = -1L;
if (rtStat != null) {
storeStatus(rtStat, 0, db);
storeTweet(rtStat, 0, db);
rtId = rtStat.getId();
}
statusRegister |= getTweetRegister(db, tweet.getId());
tweetFlags |= getTweetRegister(db, tweet.getId());
if (tweet.isFavorited()) {
statusRegister |= FAV_MASK;
tweetFlags |= FAV_MASK;
} else {
statusRegister &= ~FAV_MASK;
tweetFlags &= ~FAV_MASK;
}
if (tweet.isRetweeted()) {
statusRegister |= RTW_MASK;
tweetFlags |= RTW_MASK;
} else {
statusRegister &= ~RTW_MASK;
tweetFlags &= ~RTW_MASK;
}
if (tweet.isSensitive()) {
statusRegister |= MEDIA_SENS_MASK;
tweetFlags |= MEDIA_SENS_MASK;
} else {
statusRegister &= ~MEDIA_SENS_MASK;
tweetFlags &= ~MEDIA_SENS_MASK;
}
if (Tweet.MEDIA_PHOTO.equals(tweet.getMediaType())) {
statusRegister |= MEDIA_IMAGE_MASK;
tweetFlags |= MEDIA_IMAGE_MASK;
} else if (Tweet.MEDIA_VIDEO.equals(tweet.getMediaType())) {
statusRegister |= MEDIA_VIDEO_MASK;
tweetFlags |= MEDIA_VIDEO_MASK;
} else if (Tweet.MEDIA_GIF.equals(tweet.getMediaType())) {
statusRegister |= MEDIA_ANGIF_MASK;
tweetFlags |= MEDIA_ANGIF_MASK;
}
ContentValues status = new ContentValues(16);
status.put(TweetTable.MEDIA, getMediaLinks(tweet));
status.put(TweetTable.ID, tweet.getId());
status.put(TweetTable.USER, user.getId());
status.put(TweetTable.SINCE, tweet.getTimestamp());
status.put(TweetTable.TWEET, tweet.getText());
status.put(TweetTable.EMBEDDED, rtId);
status.put(TweetTable.SOURCE, tweet.getSource());
status.put(TweetTable.REPLYTWEET, tweet.getRepliedTweetId());
status.put(TweetTable.RETWEET, tweet.getRetweetCount());
status.put(TweetTable.FAVORITE, tweet.getFavoriteCount());
status.put(TweetTable.REPLYUSER, tweet.getRepliedUserId());
status.put(TweetTable.PLACE, tweet.getLocationName());
status.put(TweetTable.COORDINATE, tweet.getLocationCoordinates());
status.put(TweetTable.REPLYUSER, tweet.getRepliedUserId());
status.put(TweetTable.REPLYNAME, tweet.getReplyName());
ContentValues tweetUpdate = new ContentValues(16);
tweetUpdate.put(TweetTable.MEDIA, getMediaLinks(tweet));
tweetUpdate.put(TweetTable.ID, tweet.getId());
tweetUpdate.put(TweetTable.USER, user.getId());
tweetUpdate.put(TweetTable.SINCE, tweet.getTimestamp());
tweetUpdate.put(TweetTable.TWEET, tweet.getText());
tweetUpdate.put(TweetTable.EMBEDDED, rtId);
tweetUpdate.put(TweetTable.SOURCE, tweet.getSource());
tweetUpdate.put(TweetTable.REPLYTWEET, tweet.getRepliedTweetId());
tweetUpdate.put(TweetTable.RETWEET, tweet.getRetweetCount());
tweetUpdate.put(TweetTable.FAVORITE, tweet.getFavoriteCount());
tweetUpdate.put(TweetTable.REPLYUSER, tweet.getRepliedUserId());
tweetUpdate.put(TweetTable.PLACE, tweet.getLocationName());
tweetUpdate.put(TweetTable.COORDINATE, tweet.getLocationCoordinates());
tweetUpdate.put(TweetTable.REPLYUSER, tweet.getRepliedUserId());
tweetUpdate.put(TweetTable.REPLYNAME, tweet.getReplyName());
db.insertWithOnConflict(TweetTable.NAME, "", status, CONFLICT_REPLACE);
db.insertWithOnConflict(TweetTable.NAME, "", tweetUpdate, CONFLICT_REPLACE);
storeUser(user, db, CONFLICT_IGNORE);
setTweetRegister(db, tweet, statusRegister);
setTweetRegister(db, tweet, tweetFlags);
}
/**
@ -802,7 +826,7 @@ public class AppDatabase {
* @param tweet update of the tweet
* @param db database instance
*/
private void updateStatus(Tweet tweet, SQLiteDatabase db) {
private void updateTweet(Tweet tweet, SQLiteDatabase db) {
String[] tweetIdArg = {Long.toString(tweet.getId())};
String[] userIdArg = {Long.toString(tweet.getAuthor().getId())};
@ -888,7 +912,7 @@ public class AppDatabase {
}
/**
* get status register of a tweet or zero if tweet was not found
* get tweet register of a tweet or zero if tweet was not found
*
* @param db database instance
* @param tweetID ID of the tweet
@ -906,7 +930,7 @@ public class AppDatabase {
}
/**
* set status register of a tweet. if an entry exists, update it
* set tweet register of a tweet. if an entry exists, update it
*
* @param db database instance
* @param tweet Tweet
@ -915,9 +939,7 @@ public class AppDatabase {
public void setTweetRegister(SQLiteDatabase db, Tweet tweet, int register) {
String[] args = {Long.toString(tweet.getId()), Long.toString(homeId)};
ContentValues values = new ContentValues(3);
values.put(TweetRegisterTable.ID, tweet.getId());
values.put(TweetRegisterTable.OWNER, homeId);
ContentValues values = new ContentValues(2);
values.put(TweetRegisterTable.REGISTER, register);
values.put(TweetRegisterTable.RETWEETUSER, tweet.getMyRetweetId());
@ -975,7 +997,7 @@ public class AppDatabase {
* @param db database instance
* @return true if found
*/
private boolean containStatus(long id, SQLiteDatabase db) {
private boolean tweetExists(long id, SQLiteDatabase db) {
String[] args = {Long.toString(id)};
Cursor c = db.query(TweetTable.NAME, null, TWEET_SELECT, args, null, null, SINGLE_ITEM);

View File

@ -555,7 +555,7 @@ public class DatabaseAdapter {
String REGISTER = "tweetRegister";
/**
*
* ID of the retweet of the current user (if exists)
*/
String RETWEETUSER = "retweeterID";
}

View File

@ -1,6 +1,7 @@
package org.nuclearfog.twidda.database.impl;
import static org.nuclearfog.twidda.database.AppDatabase.FAV_MASK;
import static org.nuclearfog.twidda.database.AppDatabase.HIDDEN_MASK;
import static org.nuclearfog.twidda.database.AppDatabase.MEDIA_ANGIF_MASK;
import static org.nuclearfog.twidda.database.AppDatabase.MEDIA_IMAGE_MASK;
import static org.nuclearfog.twidda.database.AppDatabase.MEDIA_SENS_MASK;
@ -21,7 +22,7 @@ import org.nuclearfog.twidda.model.User;
import java.util.regex.Pattern;
/**
* Tweet implementation for database
* Implementation of a database tweet
*
* @author nuclearfog
*/
@ -53,6 +54,7 @@ public class TweetImpl implements Tweet {
private boolean retweeted;
private boolean favorited;
private boolean sensitive;
private boolean isHidden;
public TweetImpl(Cursor cursor, long currentUserId) {
@ -75,6 +77,7 @@ public class TweetImpl implements Tweet {
favorited = (tweetRegister & FAV_MASK) != 0;
retweeted = (tweetRegister & RTW_MASK) != 0;
sensitive = (tweetRegister & MEDIA_SENS_MASK) != 0;
isHidden = (tweetRegister & HIDDEN_MASK) != 0;
if (!linkStr.isEmpty())
mediaLinks = SEPARATOR.split(linkStr);
userMentions = StringTools.getUserMentions(text, author.getScreenname());
@ -195,6 +198,11 @@ public class TweetImpl implements Tweet {
return locationCoordinates;
}
@Override
public boolean isHidden() {
return isHidden;
}
@Override
public boolean equals(@Nullable Object obj) {
if (!(obj instanceof Tweet))

View File

@ -126,6 +126,11 @@ public interface Tweet extends Serializable {
*/
boolean isFavorited();
/**
* @return true if tweet is hidden by current user
*/
boolean isHidden();
/**
* @return name of the location if attached
*/

View File

@ -133,6 +133,8 @@ public class TweetActivity extends AppCompatActivity implements OnClickListener,
@Nullable
private Tweet tweet;
private boolean hidden;
@Override
protected void attachBaseContext(Context newBase) {
@ -175,6 +177,7 @@ public class TweetActivity extends AppCompatActivity implements OnClickListener,
} else {
username = tweet.getAuthor().getScreenname();
tweetId = tweet.getId();
hidden = tweet.isHidden();
}
} else {
username = getIntent().getStringExtra(KEY_TWEET_NAME);
@ -278,17 +281,26 @@ public class TweetActivity extends AppCompatActivity implements OnClickListener,
if (tweet == null)
return super.onPrepareOptionsMenu(m);
MenuItem deleteItem = m.findItem(R.id.menu_tweet_delete);
MenuItem copyItem = m.findItem(R.id.menu_tweet_copy);
SubMenu copyMenu = copyItem.getSubMenu();
MenuItem optDelete = m.findItem(R.id.menu_tweet_delete);
MenuItem optHide = m.findItem(R.id.menu_tweet_hide);
MenuItem optCopy = m.findItem(R.id.menu_tweet_copy);
SubMenu copyMenu = optCopy.getSubMenu();
Tweet currentTweet = tweet;
if (tweet.getEmbeddedTweet() != null) {
currentTweet = tweet.getEmbeddedTweet();
}
if (currentTweet.getRepliedUserId() == settings.getCurrentUserId()
&& currentTweet.getAuthor().getId() != settings.getCurrentUserId()) {
optHide.setVisible(true);
if (hidden) {
optHide.setTitle(R.string.menu_tweet_unhide);
} else {
optHide.setTitle(R.string.menu_tweet_hide);
}
}
// enable delete option only if current user owns tweets
deleteItem.setVisible(currentTweet.getAuthor().isCurrentUser());
optDelete.setVisible(currentTweet.getAuthor().isCurrentUser());
// add media link items
// check if menu doesn't contain media links already
@ -317,6 +329,15 @@ public class TweetActivity extends AppCompatActivity implements OnClickListener,
if (item.getItemId() == R.id.menu_tweet_delete) {
deleteDialog.show(DialogType.TWEET_DELETE);
}
// hide tweet
else if (item.getItemId() == R.id.menu_tweet_hide) {
if (hidden) {
statusAsync = new TweetAction(this, Action.UNHIDE, tweet.getId(), -1L);
} else {
statusAsync = new TweetAction(this, Action.HIDE, tweet.getId(), -1L);
}
statusAsync.execute();
}
// get tweet link
else if (item.getItemId() == R.id.menu_tweet_browser) {
String username = author.getScreenname().substring(1);
@ -671,7 +692,7 @@ public class TweetActivity extends AppCompatActivity implements OnClickListener,
* @param action action type
* @param tweetId ID of the tweet
*/
public void onAction(Action action, long tweetId) {
public void OnSuccess(Action action, long tweetId) {
switch (action) {
case RETWEET:
Toast.makeText(this, R.string.info_tweet_retweeted, LENGTH_SHORT).show();
@ -695,6 +716,18 @@ public class TweetActivity extends AppCompatActivity implements OnClickListener,
Toast.makeText(this, R.string.info_tweet_unfavored, LENGTH_SHORT).show();
break;
case HIDE:
hidden = true;
invalidateOptionsMenu();
Toast.makeText(this, R.string.info_reply_hidden, LENGTH_SHORT).show();
break;
case UNHIDE:
hidden = false;
invalidateOptionsMenu();
Toast.makeText(this, R.string.info_reply_unhidden, LENGTH_SHORT).show();
break;
case DELETE:
Toast.makeText(this, R.string.info_tweet_removed, LENGTH_SHORT).show();
Intent returnData = new Intent();

View File

@ -23,6 +23,11 @@
</item>
<item
android:id="@+id/menu_tweet_hide"
android:title="@string/menu_tweet_hide"
android:visible="false" />
<item
android:id="@+id/menu_tweet_delete"
android:title="@string/menu_tweet_delete"

View File

@ -230,4 +230,8 @@
<string name="menu_media_link">Medienlink</string>
<string name="info_tweet_text_copied">Tweet Text kopiert</string>
<string name="info_tweet_medialink_copied">Medienlink kopiert</string>
<string name="menu_tweet_hide">Antwort ausblenden</string>
<string name="menu_tweet_unhide">Antwort einblenden</string>
<string name="info_reply_hidden">Antwort wurde ausgeblendet</string>
<string name="info_reply_unhidden">Antwort wurde eingeblendet</string>
</resources>

View File

@ -28,6 +28,8 @@
<string name="info_tweet_unfavored">Tweet removed from favorites</string>
<string name="info_tweet_liked">Tweet liked</string>
<string name="info_tweet_unliked">Tweet unliked</string>
<string name="info_reply_hidden">Reply is hidden</string>
<string name="info_reply_unhidden">Reply is visible</string>
<string name="info_user_muted">User muted</string>
<string name="info_user_unmuted">User unmuted</string>
<string name="info_dm_send">Directmessage sent</string>
@ -112,6 +114,8 @@
<string name="menu_unmute_user">unmute</string>
<string name="menu_follow_requested">follow requested</string>
<string name="menu_tweet_delete">delete</string>
<string name="menu_tweet_hide">hide</string>
<string name="menu_tweet_unhide">unhide</string>
<string name="menu_tweet_open_browser">open in browser</string>
<string name="menu_mute_user">mute</string>
<string name="menu_edit_profile">edit profile</string>