added list editor, bug fix

This commit is contained in:
nuclearfog 2020-10-20 19:24:35 +02:00
parent 2d0b074c65
commit 892ada2dfa
No known key found for this signature in database
GPG Key ID: D5490E4A81F97B14
12 changed files with 192 additions and 67 deletions

View File

@ -20,8 +20,8 @@
<map>
<entry key="assetSourceType" value="FILE" />
<entry key="autoMirrored" value="true" />
<entry key="outputName" value="new_list" />
<entry key="sourceFile" value="$USER_HOME$/Dokumente/Rest/Entypo SVG/add-to-list.svg" />
<entry key="outputName" value="edit_list" />
<entry key="sourceFile" value="$USER_HOME$/Dokumente/Rest/Entypo SVG/new-message.svg" />
</map>
</option>
</PersistentState>

View File

@ -1,11 +1,13 @@
package org.nuclearfog.twidda.activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SearchView;
@ -22,10 +24,15 @@ import org.nuclearfog.twidda.adapter.FragmentAdapter;
import org.nuclearfog.twidda.backend.UserListManager;
import org.nuclearfog.twidda.backend.UserListManager.ListManagerCallback;
import org.nuclearfog.twidda.backend.engine.EngineException;
import org.nuclearfog.twidda.backend.utils.ErrorHandler;
import org.nuclearfog.twidda.backend.utils.FontTool;
import org.nuclearfog.twidda.database.GlobalSettings;
import static android.os.AsyncTask.Status.RUNNING;
import static org.nuclearfog.twidda.activity.ListPopup.KEY_LIST_DESCR;
import static org.nuclearfog.twidda.activity.ListPopup.KEY_LIST_ID;
import static org.nuclearfog.twidda.activity.ListPopup.KEY_LIST_TITLE;
import static org.nuclearfog.twidda.activity.ListPopup.KEY_LIST_VISIB;
import static org.nuclearfog.twidda.backend.UserListManager.Action.ADD_USER;
/**
@ -48,18 +55,45 @@ public class ListDetail extends AppCompatActivity implements OnTabSelectedListen
*/
public static final String KEY_LISTDETAIL_DESCR = "list-descr";
/**
* Key for the list description
*/
public static final String KEY_LISTDETAIL_VISIB = "list-visibility";
/**
* Key to check if this list is owned by the current user
*/
public static final String KEY_CURRENT_USER_OWNS = "list-owner";
/**
* Request code for list editing
*/
public static final int REQ_LIST_CHANGE = 1;
/**
* Return code when this list was sucessfully changed
*/
public static final int RET_LIST_CHANGED = 2;
private UserListManager listAsync;
private FragmentAdapter adapter;
// Views
private TabLayout tablayout;
private ViewPager pager;
private Toolbar toolbar;
// list information
private long listId;
private String title, description;
private boolean isPublic, belongsToCurrentUser;
@Override
protected void onCreate(@Nullable Bundle b) {
super.onCreate(b);
setContentView(R.layout.page_listdetail);
View root = findViewById(R.id.listdetail_root);
Toolbar toolbar = findViewById(R.id.listdetail_toolbar);
toolbar = findViewById(R.id.listdetail_toolbar);
tablayout = findViewById(R.id.listdetail_tab);
pager = findViewById(R.id.listdetail_pager);
@ -74,11 +108,13 @@ public class ListDetail extends AppCompatActivity implements OnTabSelectedListen
tablayout.addOnTabSelectedListener(this);
Bundle param = getIntent().getExtras();
if (param != null && param.containsKey(KEY_LISTDETAIL_ID)) {
long id = param.getLong(KEY_LISTDETAIL_ID);
String title = param.getString(KEY_LISTDETAIL_TITLE, "");
String subTitle = param.getString(KEY_LISTDETAIL_DESCR, "");
adapter.setupListContentPage(id);
if (param != null) {
listId = param.getLong(KEY_LISTDETAIL_ID);
title = param.getString(KEY_LISTDETAIL_TITLE);
description = param.getString(KEY_LISTDETAIL_DESCR);
isPublic = param.getBoolean(KEY_LISTDETAIL_VISIB);
belongsToCurrentUser = param.getBoolean(KEY_CURRENT_USER_OWNS, false);
adapter.setupListContentPage(listId);
Tab tlTab = tablayout.getTabAt(0);
Tab trTab = tablayout.getTabAt(1);
if (tlTab != null && trTab != null) {
@ -86,7 +122,7 @@ public class ListDetail extends AppCompatActivity implements OnTabSelectedListen
trTab.setIcon(R.drawable.user);
}
toolbar.setTitle(title);
toolbar.setSubtitle(subTitle);
toolbar.setSubtitle(description);
setSupportActionBar(toolbar);
}
FontTool.setViewFontAndColor(settings, root);
@ -96,22 +132,42 @@ public class ListDetail extends AppCompatActivity implements OnTabSelectedListen
@Override
public boolean onCreateOptionsMenu(Menu m) {
getMenuInflater().inflate(R.menu.userlist, m);
MenuItem search = m.findItem(R.id.add_user);
MenuItem search = m.findItem(R.id.menu_list_add_user);
MenuItem editList = m.findItem(R.id.menu_list_edit);
SearchView searchUser = (SearchView) search.getActionView();
searchUser.setQueryHint(getString(R.string.list_add_user));
if (belongsToCurrentUser) {
searchUser.setQueryHint(getString(R.string.menu_add_user));
searchUser.setOnQueryTextListener(this);
} else {
editList.setVisible(false);
search.setVisible(false);
}
return super.onCreateOptionsMenu(m);
}
@Override
public boolean onPrepareOptionsMenu(Menu m) {
MenuItem search = m.findItem(R.id.add_user);
MenuItem search = m.findItem(R.id.menu_list_add_user);
search.collapseActionView();
return super.onPrepareOptionsMenu(m);
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
if (item.getItemId() == R.id.menu_list_edit) {
Intent editList = new Intent(this, ListPopup.class);
editList.putExtra(KEY_LIST_ID, listId);
editList.putExtra(KEY_LIST_TITLE, title);
editList.putExtra(KEY_LIST_DESCR, description);
editList.putExtra(KEY_LIST_VISIB, isPublic);
startActivityForResult(editList, REQ_LIST_CHANGE);
}
return super.onOptionsItemSelected(item);
}
@Override
public void onBackPressed() {
if (tablayout.getSelectedTabPosition() > 0) {
@ -122,6 +178,20 @@ public class ListDetail extends AppCompatActivity implements OnTabSelectedListen
}
@Override
public void onActivityResult(int reqCode, int returnCode, @Nullable Intent data) {
if (reqCode == REQ_LIST_CHANGE && returnCode == RET_LIST_CHANGED && data != null) {
// refresh list information
title = data.getStringExtra(KEY_LISTDETAIL_TITLE);
description = data.getStringExtra(KEY_LISTDETAIL_DESCR);
isPublic = data.getBooleanExtra(KEY_LISTDETAIL_VISIB, false);
toolbar.setTitle(title);
toolbar.setSubtitle(description);
}
super.onActivityResult(reqCode, returnCode, data);
}
@Override
public void onTabSelected(Tab tab) {
}
@ -141,14 +211,10 @@ public class ListDetail extends AppCompatActivity implements OnTabSelectedListen
@Override
public boolean onQueryTextSubmit(String query) {
if (listAsync == null || listAsync.getStatus() != RUNNING) {
Bundle param = getIntent().getExtras();
if (param != null && param.containsKey(KEY_LISTDETAIL_ID)) {
long id = param.getLong(KEY_LISTDETAIL_ID);
Toast.makeText(this, R.string.info_adding_user_to_list, Toast.LENGTH_SHORT).show();
listAsync = new UserListManager(id, ADD_USER, getApplicationContext(), this);
listAsync = new UserListManager(listId, ADD_USER, getApplicationContext(), this);
listAsync.execute(query);
}
}
return true;
}
@ -169,5 +235,6 @@ public class ListDetail extends AppCompatActivity implements OnTabSelectedListen
@Override
public void onFailure(EngineException err) {
ErrorHandler.handleFailure(this, err);
}
}

View File

@ -1,12 +1,14 @@
package org.nuclearfog.twidda.activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.Nullable;
@ -24,6 +26,11 @@ import org.nuclearfog.twidda.database.GlobalSettings;
import static android.os.AsyncTask.Status.RUNNING;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
import static org.nuclearfog.twidda.activity.ListDetail.KEY_LISTDETAIL_DESCR;
import static org.nuclearfog.twidda.activity.ListDetail.KEY_LISTDETAIL_ID;
import static org.nuclearfog.twidda.activity.ListDetail.KEY_LISTDETAIL_TITLE;
import static org.nuclearfog.twidda.activity.ListDetail.KEY_LISTDETAIL_VISIB;
import static org.nuclearfog.twidda.activity.ListDetail.RET_LIST_CHANGED;
import static org.nuclearfog.twidda.activity.TwitterList.RET_LIST_CREATED;
/**
@ -52,19 +59,25 @@ public class ListPopup extends AppCompatActivity implements OnClickListener {
public static final String KEY_LIST_VISIB = "list_visibility";
private UserListUpdater updaterAsync;
private EditText title, description;
private EditText titleInput, subTitleInput;
private CompoundButton visibility;
private View progressCircle;
private long listId = -1;
private String title = "";
private String description = "";
private boolean isPublic = false;
@Override
protected void onCreate(Bundle b) {
super.onCreate(b);
setContentView(R.layout.popup_userlist);
View root = findViewById(R.id.list_popup_root);
Button update = findViewById(R.id.userlist_create_list);
title = findViewById(R.id.list_edit_title);
description = findViewById(R.id.list_edit_descr);
Button updateButton = findViewById(R.id.userlist_create_list);
TextView popupTitle = findViewById(R.id.popup_list_title);
titleInput = findViewById(R.id.list_edit_title);
subTitleInput = findViewById(R.id.list_edit_descr);
visibility = findViewById(R.id.list_edit_public_sw);
progressCircle = findViewById(R.id.list_popup_loading);
@ -73,24 +86,26 @@ public class ListPopup extends AppCompatActivity implements OnClickListener {
FontTool.setViewFont(settings, root);
Bundle extras = getIntent().getExtras();
if (extras != null) {
title.setText(extras.getString(KEY_LIST_TITLE, ""));
description.setText(extras.getString(KEY_LIST_DESCR, ""));
visibility.setChecked(extras.getBoolean(KEY_LIST_VISIB, true));
listId = extras.getLong(KEY_LIST_ID, -1);
title = extras.getString(KEY_LIST_TITLE, "");
description = extras.getString(KEY_LIST_DESCR, "");
isPublic = extras.getBoolean(KEY_LIST_VISIB);
}
update.setOnClickListener(this);
titleInput.setText(title);
subTitleInput.setText(description);
visibility.setChecked(isPublic);
if (listId > 0) {
popupTitle.setText(R.string.edit_list);
updateButton.setText(R.string.update_list);
}
updateButton.setOnClickListener(this);
}
@Override
public void onBackPressed() {
Bundle extras = getIntent().getExtras();
String titleStr = "";
String descrStr = "";
if (extras != null) {
titleStr = extras.getString(KEY_LIST_TITLE, titleStr);
descrStr = extras.getString(KEY_LIST_DESCR, descrStr);
}
if (titleStr.equals(title.getText().toString()) && descrStr.equals(description.getText().toString())) {
if (titleInput.getText().toString().equals(title)
&& subTitleInput.getText().toString().equals(description)) {
super.onBackPressed();
} else {
Builder alertDialog = new Builder(this, R.style.ConfirmDialog);
@ -110,18 +125,18 @@ public class ListPopup extends AppCompatActivity implements OnClickListener {
@Override
public void onClick(View view) {
if (view.getId() == R.id.userlist_create_list) {
String titleStr = title.getText().toString();
String descrStr = description.getText().toString();
String titleStr = titleInput.getText().toString();
String descrStr = subTitleInput.getText().toString();
boolean isPublic = visibility.isChecked();
if (titleStr.trim().isEmpty() || descrStr.trim().isEmpty()) {
Toast.makeText(this, R.string.userlist_error_empty_text, Toast.LENGTH_SHORT).show();
} else if (updaterAsync == null || updaterAsync.getStatus() != RUNNING) {
Bundle extras = getIntent().getExtras();
ListHolder mHolder;
if (extras != null && extras.containsKey(KEY_LIST_ID)) {
long id = extras.getLong(KEY_LIST_ID);
mHolder = new ListHolder(titleStr, descrStr, isPublic, id);
if (listId > 0) {
// update existing list
mHolder = new ListHolder(titleStr, descrStr, isPublic, listId);
} else {
// create new one
mHolder = new ListHolder(titleStr, descrStr, isPublic);
}
updaterAsync = new UserListUpdater(this);
@ -139,11 +154,18 @@ public class ListPopup extends AppCompatActivity implements OnClickListener {
/**
* called when a list was updated successfully
*
* @param result updated list data
*/
public void onSuccess() {
Bundle extras = getIntent().getExtras();
if (extras != null && extras.containsKey(KEY_LIST_ID)) {
public void onSuccess(ListHolder result) {
if (listId > 0) {
Toast.makeText(this, R.string.info_list_updated, Toast.LENGTH_SHORT).show();
Intent resultIntent = new Intent();
resultIntent.putExtra(KEY_LISTDETAIL_ID, result.getId());
resultIntent.putExtra(KEY_LISTDETAIL_TITLE, result.getTitle());
resultIntent.putExtra(KEY_LISTDETAIL_DESCR, result.getDescription());
resultIntent.putExtra(KEY_LISTDETAIL_VISIB, result.isPublic());
setResult(RET_LIST_CHANGED, resultIntent);
} else {
// it's a new list, if no list ID is defined
Toast.makeText(this, R.string.info_list_created, Toast.LENGTH_SHORT).show();

View File

@ -32,10 +32,15 @@ public class TwitterList extends AppCompatActivity {
*/
public static final int RET_LIST_CREATED = 2;
/**
* return code for {@link ListPopup} if list was updated
*/
public static final int RET_LIST_UPDATED = 3;
/**
* Key to set up if the current user owns the lists
*/
public static final String KEY_USERLIST_HOME_LIST = "userlist-home";
public static final String KEY_CURRENT_USER_OWNS = "userlist-current-user-owns-list";
/**
* Key for the ID the list owner
@ -93,7 +98,7 @@ public class TwitterList extends AppCompatActivity {
public boolean onCreateOptionsMenu(Menu m) {
getMenuInflater().inflate(R.menu.lists, m);
Bundle param = getIntent().getExtras();
if (param != null && param.getBoolean(KEY_USERLIST_HOME_LIST, false)) {
if (param != null && param.getBoolean(KEY_CURRENT_USER_OWNS, false)) {
m.findItem(R.id.list_create).setVisible(true);
}
return super.onCreateOptionsMenu(m);

View File

@ -60,7 +60,7 @@ import static org.nuclearfog.twidda.activity.TweetActivity.KEY_TWEET_ID;
import static org.nuclearfog.twidda.activity.TweetActivity.KEY_TWEET_NAME;
import static org.nuclearfog.twidda.activity.TweetActivity.LINK_PATTERN;
import static org.nuclearfog.twidda.activity.TweetPopup.KEY_TWEETPOPUP_TEXT;
import static org.nuclearfog.twidda.activity.TwitterList.KEY_USERLIST_HOME_LIST;
import static org.nuclearfog.twidda.activity.TwitterList.KEY_CURRENT_USER_OWNS;
import static org.nuclearfog.twidda.activity.TwitterList.KEY_USERLIST_OWNER_ID;
import static org.nuclearfog.twidda.activity.UserDetail.KEY_USERDETAIL_ID;
import static org.nuclearfog.twidda.activity.UserDetail.KEY_USERDETAIL_MODE;
@ -361,7 +361,7 @@ public class UserProfile extends AppCompatActivity implements OnClickListener,
case R.id.profile_lists:
Intent listPage = new Intent(this, TwitterList.class);
listPage.putExtra(KEY_USERLIST_HOME_LIST, user.getId() == settings.getUserId());
listPage.putExtra(KEY_CURRENT_USER_OWNS, user.getId() == settings.getUserId());
listPage.putExtra(KEY_USERLIST_OWNER_ID, user.getId());
startActivity(listPage);
break;

View File

@ -15,7 +15,7 @@ import java.lang.ref.WeakReference;
* This class creates and updates user lists
* Backend for {@link ListPopup}
*/
public class UserListUpdater extends AsyncTask<ListHolder, Void, Boolean> {
public class UserListUpdater extends AsyncTask<ListHolder, Void, ListHolder> {
@Nullable
@ -40,22 +40,23 @@ public class UserListUpdater extends AsyncTask<ListHolder, Void, Boolean> {
@Override
protected Boolean doInBackground(ListHolder... listHolders) {
protected ListHolder doInBackground(ListHolder... listHolders) {
try {
mTwitter.updateUserList(listHolders[0]);
return true;
ListHolder mList = listHolders[0];
mTwitter.updateUserList(mList);
return mList;
} catch (EngineException err) {
this.err = err;
}
return false;
return null;
}
@Override
protected void onPostExecute(Boolean success) {
protected void onPostExecute(ListHolder result) {
if (callback.get() != null) {
if (success) {
callback.get().onSuccess();
if (result != null) {
callback.get().onSuccess(result);
} else {
callback.get().onError(err);
}

View File

@ -34,9 +34,11 @@ import java.util.List;
import static android.os.AsyncTask.Status.FINISHED;
import static android.os.AsyncTask.Status.RUNNING;
import static org.nuclearfog.twidda.activity.ListDetail.KEY_CURRENT_USER_OWNS;
import static org.nuclearfog.twidda.activity.ListDetail.KEY_LISTDETAIL_DESCR;
import static org.nuclearfog.twidda.activity.ListDetail.KEY_LISTDETAIL_ID;
import static org.nuclearfog.twidda.activity.ListDetail.KEY_LISTDETAIL_TITLE;
import static org.nuclearfog.twidda.activity.ListDetail.KEY_LISTDETAIL_VISIB;
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.USERLIST_SUBSCRBR;
@ -54,6 +56,7 @@ public class ListFragment extends Fragment implements OnRefreshListener, ListCli
public static final String KEY_FRAG_LIST_OWNER_NAME = "list_owner_name";
private TwitterListLoader listTask;
private GlobalSettings settings;
private SwipeRefreshLayout reloadLayout;
private RecyclerView list;
@ -63,7 +66,7 @@ public class ListFragment extends Fragment implements OnRefreshListener, ListCli
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup parent, @Nullable Bundle param) {
Context context = inflater.getContext();
GlobalSettings settings = GlobalSettings.getInstance(context);
settings = GlobalSettings.getInstance(context);
adapter = new ListAdapter(this, settings);
list = new RecyclerView(inflater.getContext());
@ -141,11 +144,15 @@ public class ListFragment extends Fragment implements OnRefreshListener, ListCli
break;
case MEMBER:
Intent list = new Intent(getContext(), ListDetail.class);
list.putExtra(KEY_LISTDETAIL_ID, listItem.getId());
list.putExtra(KEY_LISTDETAIL_TITLE, listItem.getTitle());
list.putExtra(KEY_LISTDETAIL_DESCR, listItem.getDescription());
startActivity(list);
Intent detailedList = new Intent(getContext(), ListDetail.class);
Bundle param = getArguments();
if (param.getLong(KEY_FRAG_LIST_OWNER_ID, -1) == settings.getUserId())
detailedList.putExtra(KEY_CURRENT_USER_OWNS, true);
detailedList.putExtra(KEY_LISTDETAIL_ID, listItem.getId());
detailedList.putExtra(KEY_LISTDETAIL_TITLE, listItem.getTitle());
detailedList.putExtra(KEY_LISTDETAIL_DESCR, listItem.getDescription());
detailedList.putExtra(KEY_LISTDETAIL_VISIB, !listItem.isPrivate());
startActivity(detailedList);
break;
case DELETE:

View File

@ -0,0 +1,10 @@
<vector android:autoMirrored="true"
android:height="20dp"
android:viewportHeight="20"
android:viewportWidth="20"
android:width="20dp"
xmlns:android="http://schemas.android.com/apk/res/android">
<path
android:fillColor="#FFFFFF"
android:pathData="M18.174,1.826c-1.102,-1.102 -2.082,-0.777 -2.082,-0.777L7.453,9.681L6,14l4.317,-1.454l8.634,-8.638C18.951,3.908 19.275,2.928 18.174,1.826zM10.605,11.605l-0.471,0.47l-1.473,0.5c-0.104,-0.24 -0.234,-0.477 -0.498,-0.74c-0.264,-0.264 -0.5,-0.394 -0.74,-0.498l0.5,-1.473l0.471,-0.47c0,0 0.776,-0.089 1.537,0.673C10.693,10.828 10.605,11.605 10.605,11.605zM16,17H3V4h5l2,-2H3C1.9,2 1,2.9 1,4v13c0,1.1 0.9,2 2,2h13c1.1,0 2,-0.9 2,-2v-7l-2,2V17z" />
</vector>

View File

@ -26,6 +26,7 @@
android:padding="@dimen/tweetpopup_margin_layout">
<TextView
android:id="@+id/popup_list_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/userlist_edittext_margin"
@ -69,6 +70,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:singleLine="true"
android:text="@string/userlist_public_sel"
app:switchPadding="@dimen/userlist_switch_padding" />
@ -80,6 +82,7 @@
android:background="@drawable/button"
android:paddingLeft="@dimen/userlist_button_padding"
android:paddingRight="@dimen/userlist_button_padding"
android:singleLine="true"
android:text="@string/userlist_create" />
</LinearLayout>

View File

@ -3,10 +3,16 @@
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/add_user"
android:title="@string/list_add_user"
android:id="@+id/menu_list_add_user"
android:title="@string/menu_add_user"
android:icon="@drawable/follow"
app:actionViewClass="androidx.appcompat.widget.SearchView"
app:showAsAction="ifRoom|collapseActionView" />
<item
android:id="@+id/menu_list_edit"
android:title="@string/edit_list"
android:icon="@drawable/edit_list"
app:showAsAction="ifRoom" />
</menu>

View File

@ -163,8 +163,10 @@
<string name="userlist_error_empty_text">Title und Beschreibung dürfen nicht leer sein!</string>
<string name="info_list_updated">Liste wurde aktualisiert</string>
<string name="info_list_created">Liste wurde erstellt</string>
<string name="list_add_user">Nutzer hinzufügen</string>
<string name="menu_add_user">Nutzer hinzufügen</string>
<string name="info_adding_user_to_list">Füge Nutzer zur Liste hinzu</string>
<string name="info_user_added_to_list">Nutzer wurde zur Liste hinzugefügt</string>
<string name="userlist_create_new_list">Neue Liste erstellen</string>
<string name="edit_list">Liste bearbeiten</string>
<string name="update_list">Liste aktualisieren</string>
</resources>

View File

@ -169,8 +169,10 @@
<string name="userlist_error_empty_text">Title and description must be set!</string>
<string name="info_list_updated">Userlist updated</string>
<string name="info_list_created">Userlist created</string>
<string name="list_add_user">add user to list</string>
<string name="menu_add_user">add user to list</string>
<string name="info_adding_user_to_list">Adding user to list</string>
<string name="info_user_added_to_list">User added to list</string>
<string name="userlist_create_new_list">Create a new userlist</string>
<string name="edit_list">Edit list</string>
<string name="update_list">update list</string>
</resources>