added list delete function

added confirm dialogs
This commit is contained in:
nuclearfog 2020-01-11 11:47:30 +01:00
parent 2c00ea6514
commit a03eea1f85
No known key found for this signature in database
GPG Key ID: ED35E22099354A64
11 changed files with 156 additions and 27 deletions

View File

@ -8,8 +8,8 @@ android {
applicationId 'org.nuclearfog.twidda' applicationId 'org.nuclearfog.twidda'
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 29 targetSdkVersion 29
versionCode 9 versionCode 10
versionName '1.7.1' versionName '1.7.2'
vectorDrawables.useSupportLibrary true vectorDrawables.useSupportLibrary true
} }
@ -44,5 +44,5 @@ dependencies {
implementation 'com.squareup.picasso:picasso:2.71828' implementation 'com.squareup.picasso:picasso:2.71828'
implementation 'com.github.QuadFlask:colorpicker:0.0.13' implementation 'com.github.QuadFlask:colorpicker:0.0.13'
implementation 'com.github.nuclearfog:ZoomView:1.0.2' implementation 'com.github.nuclearfog:ZoomView:1.0.2'
implementation 'com.github.nuclearfog:Tagger:01c1ae0' implementation 'com.github.nuclearfog:Tagger:2.0'
} }

View File

@ -26,7 +26,7 @@ import java.text.NumberFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static android.view.View.INVISIBLE; import static android.view.View.GONE;
import static android.view.View.VISIBLE; import static android.view.View.VISIBLE;
import static androidx.recyclerview.widget.RecyclerView.NO_POSITION; import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
@ -64,6 +64,20 @@ public class ListAdapter extends Adapter<ListAdapter.ListHolder> {
} }
@MainThread
public void removeItem(long id) {
int pos = -1;
for (int index = 0; index < data.size() && pos < 0; index++) {
if (data.get(index).getId() == id) {
data.remove(index);
pos = index;
}
}
if (pos != -1)
notifyItemRemoved(pos);
}
@Override @Override
public int getItemCount() { public int getItemCount() {
return data.size(); return data.size();
@ -108,6 +122,17 @@ public class ListAdapter extends Adapter<ListAdapter.ListHolder> {
} }
} }
}); });
vh.deleteList.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (listener.get() != null) {
int position = vh.getLayoutPosition();
if (position != NO_POSITION) {
listener.get().onClick(data.get(position), ListClickListener.Action.DELETE);
}
}
}
});
vh.subscriberCount.setOnClickListener(new OnClickListener() { vh.subscriberCount.setOnClickListener(new OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
@ -150,10 +175,13 @@ public class ListAdapter extends Adapter<ListAdapter.ListHolder> {
vh.followList.setText(R.string.unfollow); vh.followList.setText(R.string.unfollow);
else else
vh.followList.setText(R.string.follow); vh.followList.setText(R.string.follow);
if (item.enableFollow()) if (item.isListOwner()) {
vh.followList.setVisibility(VISIBLE); vh.followList.setVisibility(VISIBLE);
else vh.deleteList.setVisibility(GONE);
vh.followList.setVisibility(INVISIBLE); } else {
vh.followList.setVisibility(GONE);
vh.deleteList.setVisibility(VISIBLE);
}
if (item.isPrivate()) if (item.isPrivate())
vh.title.setCompoundDrawablesWithIntrinsicBounds(R.drawable.lock, 0, 0, 0); vh.title.setCompoundDrawablesWithIntrinsicBounds(R.drawable.lock, 0, 0, 0);
else else
@ -163,7 +191,7 @@ public class ListAdapter extends Adapter<ListAdapter.ListHolder> {
class ListHolder extends ViewHolder { class ListHolder extends ViewHolder {
final ImageView pb_image; final ImageView pb_image;
final Button followList; final Button followList, deleteList;
final TextView title, ownername, description, createdAt; final TextView title, ownername, description, createdAt;
final TextView memberCount, subscriberCount; final TextView memberCount, subscriberCount;
@ -171,6 +199,7 @@ public class ListAdapter extends Adapter<ListAdapter.ListHolder> {
super(v); super(v);
pb_image = v.findViewById(R.id.list_owner_profile); pb_image = v.findViewById(R.id.list_owner_profile);
followList = v.findViewById(R.id.list_follow); followList = v.findViewById(R.id.list_follow);
deleteList = v.findViewById(R.id.list_delete);
title = v.findViewById(R.id.list_title); title = v.findViewById(R.id.list_title);
ownername = v.findViewById(R.id.list_ownername); ownername = v.findViewById(R.id.list_ownername);
description = v.findViewById(R.id.list_description); description = v.findViewById(R.id.list_description);
@ -187,7 +216,8 @@ public class ListAdapter extends Adapter<ListAdapter.ListHolder> {
PROFILE, PROFILE,
FOLLOW, FOLLOW,
SUBSCRIBER, SUBSCRIBER,
MEMBER MEMBER,
DELETE
} }
void onClick(TwitterList listItem, Action action); void onClick(TwitterList listItem, Action action);

View File

@ -22,6 +22,7 @@ public class ListLoader extends AsyncTask<Long, Void, List<TwitterList>> {
public enum Action { public enum Action {
LOAD, LOAD,
FOLLOW, FOLLOW,
DELETE
} }
@Nullable @Nullable
@ -46,18 +47,23 @@ public class ListLoader extends AsyncTask<Long, Void, List<TwitterList>> {
@Override @Override
protected List<TwitterList> doInBackground(Long[] param) { protected List<TwitterList> doInBackground(Long[] param) {
List<TwitterList> result;
try { try {
switch (action) { switch (action) {
case LOAD: case LOAD:
return mTwitter.getUserList(param[0]); result = mTwitter.getUserList(param[0]);
return result;
case FOLLOW: case FOLLOW:
TwitterList list = mTwitter.followUserList(param[0]); result = new ArrayList<>(1);
List<TwitterList> result = new ArrayList<>(1); result.add(mTwitter.followUserList(param[0]));
result.add(list); return result;
case DELETE:
result = new ArrayList<>(1);
result.add(mTwitter.deleteUserList(param[0]));
return result; return result;
} }
} catch (TwitterEngine.EngineException twException) { } catch (TwitterEngine.EngineException twException) {
this.twException = twException; this.twException = twException;
} }
@ -81,6 +87,12 @@ public class ListLoader extends AsyncTask<Long, Void, List<TwitterList>> {
else else
Toast.makeText(ui.get().getContext(), R.string.info_unfollowed, LENGTH_SHORT).show(); Toast.makeText(ui.get().getContext(), R.string.info_unfollowed, LENGTH_SHORT).show();
break; break;
case DELETE:
list = result.get(0);
adapter.removeItem(list.getId());
Toast.makeText(ui.get().getContext(), R.string.info_list_removed, LENGTH_SHORT).show();
break;
} }
} }
if (twException != null) if (twException != null)

View File

@ -57,8 +57,10 @@ public class MessageLoader extends AsyncTask<Long, Void, List<Message>> {
switch (mode) { switch (mode) {
case DB: case DB:
List<Message> messages = db.getMessages(); List<Message> messages = db.getMessages();
if (messages.isEmpty()) if (messages.isEmpty()) {
messages = mTwitter.getMessages(); messages = mTwitter.getMessages();
db.storeMessage(messages);
}
return messages; return messages;
case LOAD: case LOAD:

View File

@ -803,6 +803,20 @@ public class TwitterEngine {
} }
} }
/**
* Delete User list
*
* @param listId ID of the list
* @return List information
* @throws EngineException if access is unavailable
*/
TwitterList deleteUserList(long listId) throws EngineException {
try {
return new TwitterList(twitter.destroyUserList(listId), twitterID);
} catch (TwitterException err) {
throw new EngineException(err);
}
}
/** /**
* Get subscriber of a user list * Get subscriber of a user list

View File

@ -17,7 +17,7 @@ public class TwitterList {
private final TwitterUser owner; private final TwitterUser owner;
private final boolean isPrivate; private final boolean isPrivate;
private final boolean isFollowing; private final boolean isFollowing;
private final boolean enableFollow; private final boolean isOwner;
private final int memberCount; private final int memberCount;
private final int subscriberCnt; private final int subscriberCnt;
@ -30,7 +30,7 @@ public class TwitterList {
isPrivate = !list.isPublic(); isPrivate = !list.isPublic();
memberCount = list.getMemberCount(); memberCount = list.getMemberCount();
subscriberCnt = list.getSubscriberCount(); subscriberCnt = list.getSubscriberCount();
enableFollow = homeId != owner.getId(); isOwner = homeId != owner.getId();
this.isFollowing = isFollowing; this.isFollowing = isFollowing;
} }
@ -120,12 +120,12 @@ public class TwitterList {
} }
/** /**
* return if current user can follow list * check if list is owned by current user
* *
* @return true if user can follow list * @return true if current user is owner
*/ */
public boolean enableFollow() { public boolean isListOwner() {
return enableFollow; return isOwner;
} }

View File

@ -1,6 +1,7 @@
package org.nuclearfog.twidda.fragment; package org.nuclearfog.twidda.fragment;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -8,12 +9,14 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog.Builder;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener;
import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.activity.ListDetail; import org.nuclearfog.twidda.activity.ListDetail;
import org.nuclearfog.twidda.activity.UserDetail; import org.nuclearfog.twidda.activity.UserDetail;
import org.nuclearfog.twidda.activity.UserProfile; import org.nuclearfog.twidda.activity.UserProfile;
@ -31,6 +34,7 @@ import static org.nuclearfog.twidda.activity.UserDetail.KEY_USERDETAIL_ID;
import static org.nuclearfog.twidda.activity.UserDetail.KEY_USERDETAIL_MODE; import static org.nuclearfog.twidda.activity.UserDetail.KEY_USERDETAIL_MODE;
import static org.nuclearfog.twidda.activity.UserDetail.UserType.SUBSCRIBER; import static org.nuclearfog.twidda.activity.UserDetail.UserType.SUBSCRIBER;
import static org.nuclearfog.twidda.activity.UserProfile.KEY_PROFILE_ID; import static org.nuclearfog.twidda.activity.UserProfile.KEY_PROFILE_ID;
import static org.nuclearfog.twidda.backend.ListLoader.Action.DELETE;
import static org.nuclearfog.twidda.backend.ListLoader.Action.FOLLOW; import static org.nuclearfog.twidda.backend.ListLoader.Action.FOLLOW;
import static org.nuclearfog.twidda.backend.ListLoader.Action.LOAD; import static org.nuclearfog.twidda.backend.ListLoader.Action.LOAD;
@ -92,7 +96,7 @@ public class ListFragment extends Fragment implements OnRefreshListener, ListCli
@Override @Override
public void onClick(TwitterList listItem, Action action) { public void onClick(final TwitterList listItem, Action action) {
if (!reloadLayout.isRefreshing()) { if (!reloadLayout.isRefreshing()) {
switch (action) { switch (action) {
case PROFILE: case PROFILE:
@ -102,7 +106,21 @@ public class ListFragment extends Fragment implements OnRefreshListener, ListCli
break; break;
case FOLLOW: case FOLLOW:
if (listTask != null && listTask.getStatus() != RUNNING) { if (listItem.isFollowing()) {
if (getContext() != null) {
Builder confirmDialog = new Builder(getContext());
confirmDialog.setMessage(R.string.confirm_unfollow_list);
confirmDialog.setNegativeButton(R.string.no_confirm, null);
confirmDialog.setPositiveButton(R.string.yes_confirm, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
listTask = new ListLoader(ListFragment.this, FOLLOW);
listTask.execute(listItem.getId());
}
});
confirmDialog.show();
}
} else {
listTask = new ListLoader(this, FOLLOW); listTask = new ListLoader(this, FOLLOW);
listTask.execute(listItem.getId()); listTask.execute(listItem.getId());
} }
@ -121,6 +139,22 @@ public class ListFragment extends Fragment implements OnRefreshListener, ListCli
list.putExtra(KEY_LISTDETAIL_NAME, listItem.getTitle()); list.putExtra(KEY_LISTDETAIL_NAME, listItem.getTitle());
startActivity(list); startActivity(list);
break; break;
case DELETE:
if (getContext() != null) {
Builder confirmDialog = new Builder(getContext());
confirmDialog.setMessage(R.string.confirm_delete_list);
confirmDialog.setNegativeButton(R.string.no_confirm, null);
confirmDialog.setPositiveButton(R.string.yes_confirm, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
listTask = new ListLoader(ListFragment.this, DELETE);
listTask.execute(listItem.getId());
}
});
confirmDialog.show();
}
break;
} }
} }
} }

View File

@ -1,6 +1,7 @@
package org.nuclearfog.twidda.fragment; package org.nuclearfog.twidda.fragment;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
@ -10,6 +11,7 @@ import android.view.ViewGroup;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog.Builder;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
@ -34,7 +36,6 @@ import static org.nuclearfog.twidda.activity.MessagePopup.KEY_DM_PREFIX;
import static org.nuclearfog.twidda.activity.SearchPage.KEY_SEARCH_QUERY; import static org.nuclearfog.twidda.activity.SearchPage.KEY_SEARCH_QUERY;
import static org.nuclearfog.twidda.activity.UserProfile.KEY_PROFILE_ID; import static org.nuclearfog.twidda.activity.UserProfile.KEY_PROFILE_ID;
public class MessageFragment extends Fragment implements OnRefreshListener, OnItemSelected { public class MessageFragment extends Fragment implements OnRefreshListener, OnItemSelected {
private MessageLoader messageTask; private MessageLoader messageTask;
@ -107,7 +108,7 @@ public class MessageFragment extends Fragment implements OnRefreshListener, OnIt
@Override @Override
public void onClick(Message message, Action action) { public void onClick(final Message message, Action action) {
if (reload != null && !reload.isRefreshing()) { if (reload != null && !reload.isRefreshing()) {
switch (action) { switch (action) {
case ANSWER: case ANSWER:
@ -117,8 +118,19 @@ public class MessageFragment extends Fragment implements OnRefreshListener, OnIt
break; break;
case DELETE: case DELETE:
messageTask = new MessageLoader(this, Mode.DEL); if (getContext() != null) {
messageTask.execute(message.getId()); Builder confirmDialog = new Builder(getContext());
confirmDialog.setMessage(R.string.confirm_delete_message);
confirmDialog.setNegativeButton(R.string.no_confirm, null);
confirmDialog.setPositiveButton(R.string.yes_confirm, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
messageTask = new MessageLoader(MessageFragment.this, Mode.DEL);
messageTask.execute(message.getId());
}
});
confirmDialog.show();
}
break; break;
case PROFILE: case PROFILE:

View File

@ -127,6 +127,21 @@
android:singleLine="true" android:singleLine="true"
android:text="@string/follow" android:text="@string/follow"
android:textSize="12sp" /> android:textSize="12sp" />
<Button
android:id="@+id/list_delete"
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="0dp"
android:layout_height="@dimen/list_button_height"
android:layout_margin="@dimen/listitem_margin"
android:layout_weight="1"
android:background="@drawable/button"
android:drawablePadding="@dimen/padding_drawable"
android:singleLine="true"
android:text="@string/delete_list"
android:textSize="12sp"
android:visibility="gone" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>

View File

@ -142,4 +142,9 @@
<string name="error_no_card_app">Keine Karten App gefunden!</string> <string name="error_no_card_app">Keine Karten App gefunden!</string>
<string name="error_no_media_app">Keine Galerie App gefunden!</string> <string name="error_no_media_app">Keine Galerie App gefunden!</string>
<string name="error_wrong_ip">Falsche IP Adresse!</string> <string name="error_wrong_ip">Falsche IP Adresse!</string>
<string name="info_list_removed">Liste gelöscht!</string>
<string name="delete_list">Liste löschen</string>
<string name="confirm_delete_list">Listelöschen?</string>
<string name="confirm_delete_message">Nachricht löschen?</string>
<string name="confirm_unfollow_list">Liste entfolgen?</string>
</resources> </resources>

View File

@ -143,4 +143,9 @@
<string name="error_no_card_app">No card app installed!</string> <string name="error_no_card_app">No card app installed!</string>
<string name="error_no_media_app">No media app found!</string> <string name="error_no_media_app">No media app found!</string>
<string name="error_wrong_ip">wrong IP address!</string> <string name="error_wrong_ip">wrong IP address!</string>
<string name="info_list_removed">List removed!</string>
<string name="delete_list">delete list</string>
<string name="confirm_delete_list">Delete list?</string>
<string name="confirm_delete_message">Delete message?</string>
<string name="confirm_unfollow_list">Unfollow list?</string>
</resources> </resources>