added direct message delete function

added direct message clickable tags
This commit is contained in:
NudeDude 2018-09-21 21:58:38 +02:00
parent 7bb4db9402
commit 516054a0ed
13 changed files with 212 additions and 72 deletions

View File

@ -3,6 +3,8 @@ package org.nuclearfog.twidda.adapter;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.text.Spanned;
import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -12,6 +14,8 @@ import android.widget.TextView;
import com.squareup.picasso.Picasso;
import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.backend.clickable.Tagger;
import org.nuclearfog.twidda.backend.clickable.Tagger.OnTagClickListener;
import org.nuclearfog.twidda.backend.listitems.Message;
import java.text.SimpleDateFormat;
@ -24,8 +28,11 @@ public class MessageAdapter extends RecyclerView.Adapter<MessageAdapter.MessageH
private List<Message> messages;
private OnItemSelected mListener;
private boolean loadImage = true;
private int color = 0xFFFFFFFF;
private int highlight;
private int fontColor = 0xFFFFFFFF;
public MessageAdapter(OnItemSelected listener) {
@ -49,8 +56,9 @@ public class MessageAdapter extends RecyclerView.Adapter<MessageAdapter.MessageH
}
public void setColor(int color) {
this.color = color;
public void setColor(int fontColor, int highlight) {
this.fontColor = fontColor;
this.highlight = highlight;
}
@ -69,31 +77,42 @@ public class MessageAdapter extends RecyclerView.Adapter<MessageAdapter.MessageH
@NonNull
@Override
public MessageHolder onCreateViewHolder(@NonNull final ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_dm, parent, false);
v.setOnClickListener(new View.OnClickListener() {
LayoutInflater inf = LayoutInflater.from(parent.getContext());
final View view = inf.inflate(R.layout.item_dm, parent, false);
view.findViewById(R.id.dm_answer).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
RecyclerView rv = (RecyclerView) parent;
int position = rv.getChildLayoutPosition(v);
mListener.onSelected(position);
int position = rv.getChildLayoutPosition(view);
mListener.onAnswer(position);
}
});
return new MessageHolder(v);
view.findViewById(R.id.dm_delete).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
RecyclerView rv = (RecyclerView) parent;
int position = rv.getChildLayoutPosition(view);
mListener.onDelete(position);
}
});
return new MessageHolder(view);
}
@Override
public void onBindViewHolder(@NonNull MessageHolder vh, int index) {
Message message = messages.get(index);
vh.message.setText(message.message);
Spanned text = Tagger.makeText(message.message, highlight, mListener);
vh.message.setMovementMethod(LinkMovementMethod.getInstance());
vh.message.setText(text);
vh.username.setText(message.sender.username);
vh.screenname.setText(message.sender.screenname);
vh.createdAt.setText(stringTime(message.time));
vh.message.setTextColor(color);
vh.username.setTextColor(color);
vh.screenname.setTextColor(color);
vh.createdAt.setTextColor(color);
vh.message.setTextColor(fontColor);
vh.username.setTextColor(fontColor);
vh.screenname.setTextColor(fontColor);
vh.createdAt.setTextColor(fontColor);
if (loadImage)
Picasso.get().load(message.sender.profileImg + "_mini").into(vh.profile_img);
@ -125,8 +144,10 @@ public class MessageAdapter extends RecyclerView.Adapter<MessageAdapter.MessageH
}
public interface OnItemSelected {
void onSelected(int pos);
public interface OnItemSelected extends OnTagClickListener {
void onAnswer(int pos);
void onDelete(int pos);
}

View File

@ -18,7 +18,11 @@ import java.util.List;
import twitter4j.TwitterException;
public class MessageLoader extends AsyncTask<Void, Void, Boolean> {
public class MessageLoader extends AsyncTask<Long, Void, Long> {
public static final long LOAD = 0;
public static final long DELETE = 1;
private static final long FAIL = -1;
private WeakReference<DirectMessage> ui;
private MessageAdapter mAdapter;
@ -40,41 +44,49 @@ public class MessageLoader extends AsyncTask<Void, Void, Boolean> {
@Override
protected Boolean doInBackground(Void... param) {
protected Long doInBackground(Long... param) {
final long MODE = param[0];
try {
if (mAdapter.getItemCount() > 0) {
message = twitter.getMessages();
mData.storeMessage(message);
message = mData.getMessages();
} else {
message = mData.getMessages();
if (message.isEmpty()) {
if (MODE == LOAD) {
if (mAdapter.getItemCount() > 0) {
message = twitter.getMessages();
mData.storeMessage(message);
message = mData.getMessages();
} else {
message = mData.getMessages();
if (message.isEmpty()) {
message = twitter.getMessages();
mData.storeMessage(message);
}
}
} else if (MODE == DELETE) {
twitter.deleteMessage(param[1]);
mData.deleteDm(param[1]);
message = mData.getMessages();
}
} catch (TwitterException err) {
returnCode = err.getErrorCode();
errorMsg += err.getMessage();
return false;
return FAIL;
} catch (Exception err) {
errorMsg += err.getMessage();
Log.e("Direct Message", errorMsg);
err.printStackTrace();
return false;
return FAIL;
}
return true;
return MODE;
}
@Override
protected void onPostExecute(Boolean success) {
protected void onPostExecute(Long mode) {
if (ui.get() == null) return;
if (success) {
if (mode == LOAD || mode == DELETE) {
mAdapter.setData(message);
mAdapter.notifyDataSetChanged();
} else {
} else if (mode == FAIL) {
switch (returnCode) {
case 420:
Toast.makeText(ui.get(), R.string.rate_limit_exceeded, Toast.LENGTH_SHORT).show();

View File

@ -81,10 +81,12 @@ public class TwitterEngine {
return mTwitter;
}
public static void destroyInstance() {
mTwitter = null;
}
/**
* Request Registration Website
*
@ -99,6 +101,7 @@ public class TwitterEngine {
return redirectionUrl;
}
/**
* Get Access-Token, store and initialize Twitter
*
@ -117,6 +120,7 @@ public class TwitterEngine {
}
}
/**
* Initialize Twitter with Accesstoken
*
@ -154,6 +158,7 @@ public class TwitterEngine {
return convertStatusList(homeTweets);
}
/**
* Get Mention Tweets
*
@ -167,6 +172,7 @@ public class TwitterEngine {
return convertStatusList(mentions);
}
/**
* Get Tweet search result
*
@ -185,6 +191,7 @@ public class TwitterEngine {
return convertStatusList(results);
}
/**
* Get Trending Hashtags
*
@ -203,6 +210,7 @@ public class TwitterEngine {
return result;
}
/**
* Get User search result
*
@ -214,6 +222,7 @@ public class TwitterEngine {
return convertUserList(twitter.searchUsers(search, -1));
}
/**
* Get User Tweets
*
@ -228,6 +237,7 @@ public class TwitterEngine {
return convertStatusList(result);
}
/**
* Get User Favs
*
@ -242,6 +252,7 @@ public class TwitterEngine {
return convertStatusList(favorits);
}
/**
* Get User Context
*
@ -253,6 +264,7 @@ public class TwitterEngine {
return getUser(twitter.showUser(id));
}
/**
* Efficient Access of Connection Information
*
@ -271,6 +283,7 @@ public class TwitterEngine {
return connection;
}
/**
* Switch following User
*
@ -286,6 +299,7 @@ public class TwitterEngine {
}
}
/**
* Switch blocking User
*
@ -301,6 +315,7 @@ public class TwitterEngine {
}
}
/**
* Switch muting User
*
@ -316,6 +331,7 @@ public class TwitterEngine {
}
}
/**
* get Following User List
*
@ -328,6 +344,7 @@ public class TwitterEngine {
return convertUserList(twitter.lookupUsers(userIDs.getIDs()));
}
/**
* get Follower
*
@ -340,6 +357,7 @@ public class TwitterEngine {
return convertUserList(twitter.lookupUsers(userIDs.getIDs()));
}
/**
* Send Tweet
*
@ -354,6 +372,7 @@ public class TwitterEngine {
twitter.tweets().updateStatus(mStatus);
}
/**
* Send Tweet
*
@ -381,6 +400,7 @@ public class TwitterEngine {
twitter.tweets().updateStatus(mStatus);
}
/**
* Get Tweet
*
@ -400,6 +420,7 @@ public class TwitterEngine {
}
}
/**
* Get Answer Tweets
*
@ -423,6 +444,7 @@ public class TwitterEngine {
return convertStatusList(answers);
}
/**
* Retweet Action
*
@ -445,6 +467,7 @@ public class TwitterEngine {
tweet.replyID, tweet.embedded, tweet.retweetId, !tweet.retweeted, tweet.favorized);
}
/**
* Favorite Action
*
@ -466,6 +489,16 @@ public class TwitterEngine {
tweet.replyID, tweet.embedded, tweet.retweetId, tweet.retweeted, !tweet.favorized);
}
/**
* @param id Tweet ID
* @throws TwitterException if Access is unavailable
*/
public void deleteTweet(long id) throws TwitterException {
twitter.destroyStatus(id);
}
/**
* Get User who retweeted a Tweet
*
@ -486,6 +519,7 @@ public class TwitterEngine {
}
}
/**
* get list of Direct Messages
*
@ -501,6 +535,7 @@ public class TwitterEngine {
return result;
}
/**
* Send direct message
*
@ -521,6 +556,17 @@ public class TwitterEngine {
}
/**
* Delete Direct Message
*
* @param id Message ID
* @throws TwitterException if Access is unavailable
*/
public void deleteMessage(long id) throws TwitterException {
twitter.destroyDirectMessage(id);
}
/**
* convert #twitter4j.User to TwitterUser List
*
@ -543,6 +589,7 @@ public class TwitterEngine {
return result;
}
/**
* convert #twitter4j.Status to Tweet List
*
@ -573,6 +620,7 @@ public class TwitterEngine {
return result;
}
/**
* @param status twitter4j.Status
* @param retweetedStat embedded Status
@ -598,6 +646,7 @@ public class TwitterEngine {
retweetedStat, status.getCurrentUserRetweetId(), status.isRetweeted(), status.isFavorited());
}
/**
* @param user Twitter4J User
* @return User item
@ -610,6 +659,7 @@ public class TwitterEngine {
user.getFriendsCount(), user.getFollowersCount());
}
/**
* @param dm Twitter4J directmessage
* @return dm item
@ -629,14 +679,6 @@ public class TwitterEngine {
}
/**
* @param id Tweet ID
* @throws TwitterException if Access is unavailable
*/
public void deleteTweet(long id) throws TwitterException {
twitter.destroyStatus(id);
}
/**
* @param status Twitter4J status
* @return Array of Medialinks

View File

@ -56,6 +56,6 @@ public abstract class Tagger {
public interface OnTagClickListener {
void onClick(String text);
void onClick(String tag);
}
}

View File

@ -406,6 +406,18 @@ public class DatabaseAdapter {
commit(db);
}
/**
* Delete Direct Message
*
* @param id Direct Message ID
*/
public void deleteDm(long id) {
SQLiteDatabase db = dataHelper.getWritableDatabase();
db.beginTransaction();
db.delete("message", "messageID=" + id, null);
commit(db);
}
/**
* Load trend List
*

View File

@ -131,7 +131,7 @@ public class AppSettings extends AppCompatActivity implements OnClickListener,
case R.id.logout:
new Builder(this)
.setMessage(R.string.should_log_lout)
.setMessage(R.string.confirm_log_lout)
.setNegativeButton(R.string.no_confirm, null)
.setPositiveButton(R.string.yes_confirm, new DialogInterface.OnClickListener() {
@Override

View File

@ -1,9 +1,11 @@
package org.nuclearfog.twidda.window;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener;
import android.support.v7.app.AlertDialog.Builder;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
@ -16,7 +18,7 @@ import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.adapter.MessageAdapter;
import org.nuclearfog.twidda.adapter.MessageAdapter.OnItemSelected;
import org.nuclearfog.twidda.backend.MessageLoader;
import org.nuclearfog.twidda.backend.listitems.TwitterUser;
import org.nuclearfog.twidda.backend.listitems.Message;
import org.nuclearfog.twidda.database.GlobalSettings;
import static android.os.AsyncTask.Status.RUNNING;
@ -26,9 +28,10 @@ import static android.os.AsyncTask.Status.RUNNING;
*
* @see MessageLoader
*/
public class DirectMessage extends AppCompatActivity implements OnItemSelected, OnRefreshListener {
public class DirectMessage extends AppCompatActivity implements OnRefreshListener, OnItemSelected {
private MessageLoader mLoader;
private MessageAdapter mAdapter;
private SwipeRefreshLayout refresh;
private GlobalSettings settings;
private RecyclerView dmList;
@ -60,14 +63,13 @@ public class DirectMessage extends AppCompatActivity implements OnItemSelected,
protected void onStart() {
super.onStart();
if (mLoader == null) {
MessageAdapter mAdapter = new MessageAdapter(this);
mAdapter.setColor(settings.getFontColor());
mAdapter = new MessageAdapter(this);
mAdapter.setColor(settings.getFontColor(), settings.getHighlightColor());
mAdapter.setImageLoad(settings.loadImages());
dmList.setAdapter(mAdapter);
refresh.setRefreshing(true);
mLoader = new MessageLoader(this);
mLoader.execute();
mLoader.execute(MessageLoader.LOAD);
}
}
@ -103,20 +105,47 @@ public class DirectMessage extends AppCompatActivity implements OnItemSelected,
@Override
public void onSelected(int index) {
MessageAdapter mAdapter = (MessageAdapter) dmList.getAdapter();
public void onAnswer(int index) {
if (mAdapter != null && !refresh.isRefreshing()) {
TwitterUser sender = mAdapter.getData().get(index).sender;
Message message = mAdapter.getData().get(index);
Intent sendDm = new Intent(this, MessagePopup.class);
sendDm.putExtra("username", sender.screenname);
sendDm.putExtra("username", message.sender.screenname);
startActivity(sendDm);
}
}
@Override
public void onDelete(int index) {
if (mLoader != null && mLoader.getStatus() != RUNNING) {
if (mAdapter != null && !refresh.isRefreshing()) {
Message message = mAdapter.getData().get(index);
final long messageId = message.messageId;
new Builder(this).setMessage(R.string.confirm_delete_dm)
.setNegativeButton(R.string.no_confirm, null)
.setPositiveButton(R.string.yes_confirm, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
mLoader = new MessageLoader(DirectMessage.this);
mLoader.execute(MessageLoader.DELETE, messageId);
}
}).show();
}
}
}
@Override
public void onClick(String tag) {
Intent intent = new Intent(this, SearchPage.class);
intent.putExtra("search", tag);
startActivity(intent);
}
@Override
public void onRefresh() {
mLoader = new MessageLoader(this);
mLoader.execute();
mLoader.execute(MessageLoader.LOAD);
}
}

View File

@ -8,7 +8,7 @@ import android.net.Uri;
import android.os.Bundle;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AlertDialog.Builder;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
@ -145,7 +145,7 @@ public class TweetDetail extends AppCompatActivity implements OnClickListener,
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.delete_tweet:
AlertDialog.Builder deleteDialog = new AlertDialog.Builder(this);
Builder deleteDialog = new Builder(this);
deleteDialog.setMessage(R.string.delete_tweet);
deleteDialog.setPositiveButton(R.string.yes_confirm, new DialogInterface.OnClickListener() {
@Override
@ -224,8 +224,6 @@ public class TweetDetail extends AppCompatActivity implements OnClickListener,
@Override
public void onClick(String text) {
Intent intent = new Intent(this, SearchPage.class);
if (text.startsWith("#"))
intent.putExtra("Addition", text);
intent.putExtra("search", text);
startActivity(intent);
}

View File

@ -169,7 +169,7 @@ public class TweetPopup extends AppCompatActivity implements OnClickListener {
private void showClosingMsg() {
if (!addition.equals(tweet.getText().toString()) || imgIndex > 0) {
Builder closeDialog = new Builder(this);
closeDialog.setMessage(R.string.should_cancel_tweet);
closeDialog.setMessage(R.string.confirm_cancel_tweet);
closeDialog.setNegativeButton(R.string.no_confirm, null);
closeDialog.setPositiveButton(R.string.yes_confirm, new DialogInterface.OnClickListener() {
@Override

View File

@ -204,7 +204,7 @@ public class UserProfile extends AppCompatActivity implements OnRefreshListener,
if (!isFollowing) {
mProfile.execute(userId, ProfileLoader.ACTION_FOLLOW);
} else {
new Builder(this).setMessage(R.string.should_unfollow)
new Builder(this).setMessage(R.string.confirm_unfollow)
.setNegativeButton(R.string.no_confirm, null)
.setPositiveButton(R.string.yes_confirm, new DialogInterface.OnClickListener() {
@Override
@ -221,7 +221,7 @@ public class UserProfile extends AppCompatActivity implements OnRefreshListener,
if (isBlocked) {
mProfile.execute(userId, ProfileLoader.ACTION_BLOCK);
} else {
new Builder(this).setMessage(R.string.should_block)
new Builder(this).setMessage(R.string.confirm_block)
.setNegativeButton(R.string.no_confirm, null)
.setPositiveButton(R.string.yes_confirm, new DialogInterface.OnClickListener() {
@Override
@ -326,8 +326,6 @@ public class UserProfile extends AppCompatActivity implements OnRefreshListener,
@Override
public void onClick(String text) {
Intent intent = new Intent(this, SearchPage.class);
if (text.startsWith("#"))
intent.putExtra("Addition", text);
intent.putExtra("search", text);
startActivity(intent);
}

View File

@ -76,10 +76,32 @@
android:id="@+id/dm_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:autoLink="web"
android:linksClickable="true" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:id="@+id/dm_answer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
android:text="@string/answer"
android:textSize="12sp" />
<TextView
android:id="@+id/dm_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/delete_dm"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>

View File

@ -3,8 +3,6 @@
<string name="font">Schrift</string>
<string name="highlight">Hervorhebung</string>
<string name="verify">verifiziert</string>
<string name="yes_confirm">Ja</string>
<string name="no_confirm">Nein</string>
<string name="fullimg">Großbild</string>
<string name="profile_locked">Privat</string>
<string name="load_factor">Anzahl Tweets</string>
@ -26,7 +24,6 @@
<string name="retweet">Retweet</string>
<string name="favorite">favorisieren</string>
<string name="background">Hintergrund</string>
<string name="should_cancel_tweet">Tweet verwerfen?</string>
<string name="delete_tweet">Tweet löschen?</string>
<string name="connection_failed">Verbindung fehlgeschlagen</string>
<string name="enter_pin">PIN eingeben!</string>
@ -66,8 +63,14 @@
<string name="error_sending_dm">Fehler beim Senden der Direktnachricht!</string>
<string name="empty_tweet">Tweet leer!</string>
<string name="logout">ausloggen</string>
<string name="should_log_lout">ausloggen?</string>
<string name="should_unfollow">User entfolgen?</string>
<string name="should_block">user sperren?</string>
<string name="pin_verification_failed">PIN verifizierung fehlgeschlagen!</string>
<string name="answer">Antworten</string>
<string name="delete_dm">löschen..</string>
<string name="yes_confirm">Ja</string>
<string name="no_confirm">Nein</string>
<string name="confirm_cancel_tweet">Tweet verwerfen?</string>
<string name="confirm_log_lout">ausloggen?</string>
<string name="confirm_unfollow">User entfolgen?</string>
<string name="confirm_block">user sperren?</string>
<string name="confirm_delete_dm">Nachricht löschen?</string>
</resources>

View File

@ -15,8 +15,6 @@
<string name="popup" translatable="false">Popup</string>
<string name="highlight">Highlight</string>
<string name="verify">verified</string>
<string name="yes_confirm">Yes</string>
<string name="no_confirm">No</string>
<string name="fullimg">big image</string>
<string name="profile_locked">locked</string>
<string name="load_factor">tweet count</string>
@ -34,7 +32,6 @@
<string name="image">load images</string>
<string name="delete_database">delete database</string>
<string name="search">search</string>
<string name="should_cancel_tweet">cancel tweet?</string>
<string name="delete_tweet">delete tweet?</string>
<string name="connection_failed">connection failed</string>
<string name="enter_pin">Enter PIN</string>
@ -74,8 +71,14 @@
<string name="error_sending_dm">error while sending direct message!</string>
<string name="empty_tweet">empty tweet!</string>
<string name="logout">log out!</string>
<string name="should_log_lout">log out?</string>
<string name="should_unfollow">unfollow user?</string>
<string name="should_block">block user?</string>
<string name="pin_verification_failed">PIN verification failed!</string>
<string name="answer">answer</string>
<string name="delete_dm">delete..</string>
<string name="yes_confirm">Yes</string>
<string name="no_confirm">No</string>
<string name="confirm_unfollow">unfollow user?</string>
<string name="confirm_delete_dm">delete message?</string>
<string name="confirm_block">block user?</string>
<string name="confirm_log_lout">log out?</string>
<string name="confirm_cancel_tweet">cancel tweet?</string>
</resources>