added user list editor

This commit is contained in:
nuclearfog 2020-10-18 19:51:43 +02:00
parent 8ab05e9c9f
commit bd77de011d
No known key found for this signature in database
GPG Key ID: D5490E4A81F97B14
13 changed files with 383 additions and 2 deletions

View File

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

View File

@ -109,6 +109,11 @@
android:screenOrientation="portrait"
android:theme="@style/AppTheme" />
<activity
android:name=".activity.ListPopup"
android:screenOrientation="portrait"
android:theme="@style/Transparency" />
</application>
</manifest>

View File

@ -0,0 +1,106 @@
package org.nuclearfog.twidda.activity;
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.Toast;
import androidx.appcompat.app.AppCompatActivity;
import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.backend.UserListUpdater;
import org.nuclearfog.twidda.backend.engine.EngineException;
import org.nuclearfog.twidda.backend.holder.ListHolder;
import org.nuclearfog.twidda.backend.utils.ErrorHandler;
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.TwitterList.RET_LIST_CREATED;
public class ListPopup extends AppCompatActivity implements OnClickListener {
public static final String KEY_LIST_ID = "list_id";
public static final String KEY_LIST_TITLE = "list_title";
public static final String KEY_LIST_DESCR = "list_description";
public static final String KEY_LIST_VISIB = "list_visibility";
private UserListUpdater updaterAsync;
private EditText title, description;
private CompoundButton visibility;
private View progressCircle;
@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);
visibility = findViewById(R.id.list_edit_public_sw);
progressCircle = findViewById(R.id.list_popup_loading);
GlobalSettings settings = GlobalSettings.getInstance(this);
root.setBackgroundColor(settings.getPopupColor());
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));
}
update.setOnClickListener(this);
}
@Override
public void onClick(View view) {
if (view.getId() == R.id.userlist_create_list) {
String titleStr = title.getText().toString();
String descrStr = description.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);
} else {
mHolder = new ListHolder(titleStr, descrStr, isPublic);
}
updaterAsync = new UserListUpdater(this);
updaterAsync.execute(mHolder);
}
}
}
public void startLoading() {
progressCircle.setVisibility(VISIBLE);
}
public void onSuccess() {
Bundle extras = getIntent().getExtras();
if (extras != null && extras.containsKey(KEY_LIST_ID)) {
Toast.makeText(this, R.string.info_list_updated, Toast.LENGTH_SHORT).show();
} else {
// if no list ID is defined, it's a new list
Toast.makeText(this, R.string.info_list_created, Toast.LENGTH_SHORT).show();
setResult(RET_LIST_CREATED);
}
finish();
}
public void onError(EngineException err) {
if (err != null)
ErrorHandler.handleFailure(this, err);
progressCircle.setVisibility(INVISIBLE);
}
}

View File

@ -1,8 +1,12 @@
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 androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
@ -18,6 +22,8 @@ import org.nuclearfog.twidda.database.GlobalSettings;
*/
public class TwitterList extends AppCompatActivity {
public static final int REQ_CREATE_LIST = 1;
public static final int RET_LIST_CREATED = 2;
public static final String KEY_USERLIST_OWNER_ID = "userlist-owner-id";
public static final String KEY_USERLIST_OWNER_NAME = "userlist-owner-name";
@ -50,4 +56,19 @@ public class TwitterList extends AppCompatActivity {
}
}
}
@Override
public boolean onCreateOptionsMenu(Menu m) {
getMenuInflater().inflate(R.menu.lists, m);
return super.onCreateOptionsMenu(m);
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
if (item.getItemId() == R.id.list_create) {
Intent createList = new Intent(this, ListPopup.class);
startActivityForResult(createList, REQ_CREATE_LIST);
}
return super.onOptionsItemSelected(item);
}
}

View File

@ -0,0 +1,60 @@
package org.nuclearfog.twidda.backend;
import android.os.AsyncTask;
import androidx.annotation.Nullable;
import org.nuclearfog.twidda.activity.ListPopup;
import org.nuclearfog.twidda.backend.engine.EngineException;
import org.nuclearfog.twidda.backend.engine.TwitterEngine;
import org.nuclearfog.twidda.backend.holder.ListHolder;
import java.lang.ref.WeakReference;
public class UserListUpdater extends AsyncTask<ListHolder, Void, Boolean> {
private final WeakReference<ListPopup> callback;
@Nullable
private EngineException err;
private final TwitterEngine mTwitter;
public UserListUpdater(ListPopup activity) {
super();
callback = new WeakReference<>(activity);
mTwitter = TwitterEngine.getInstance(activity);
}
@Override
protected void onPreExecute() {
if (callback.get() != null) {
callback.get().startLoading();
}
}
@Override
protected Boolean doInBackground(ListHolder... listHolders) {
try {
mTwitter.updateUserList(listHolders[0]);
return true;
} catch (EngineException err) {
this.err = err;
}
return false;
}
@Override
protected void onPostExecute(Boolean success) {
if (callback.get() != null) {
if (success) {
callback.get().onSuccess();
} else {
callback.get().onError(err);
}
}
}
}

View File

@ -7,6 +7,7 @@ import android.graphics.BitmapFactory;
import androidx.annotation.Nullable;
import org.nuclearfog.twidda.BuildConfig;
import org.nuclearfog.twidda.backend.holder.ListHolder;
import org.nuclearfog.twidda.backend.holder.MessageHolder;
import org.nuclearfog.twidda.backend.holder.TweetHolder;
import org.nuclearfog.twidda.backend.holder.TwitterUserList;
@ -1058,6 +1059,23 @@ public class TwitterEngine {
}
}
/**
* creates an user list
*
* @param list holder for list information
* @throws EngineException if access is unavailable
*/
public void updateUserList(ListHolder list) throws EngineException {
try {
if (list.exists()) {
twitter.updateUserList(list.getId(), list.getTitle(), list.isPublic(), list.getDescription());
} else {
twitter.createUserList(list.getTitle(), list.isPublic(), list.getDescription());
}
} catch (TwitterException err) {
throw new EngineException(err);
}
}
/**
* convert #twitter4j.User to TwitterUser List

View File

@ -0,0 +1,45 @@
package org.nuclearfog.twidda.backend.holder;
public class ListHolder {
public static final long NEW_LIST = -1;
private long listId;
private final String title;
private final String description;
private final boolean isPublic;
public ListHolder(String title, String description, boolean isPublic, long listId) {
this(title, description, isPublic);
this.listId = listId;
}
public ListHolder(String title, String description, boolean isPublic) {
this.title = title;
this.description = description;
this.isPublic = isPublic;
this.listId = NEW_LIST;
}
public long getId() {
return listId;
}
public String getTitle() {
return title;
}
public String getDescription() {
return description;
}
public boolean isPublic() {
return isPublic;
}
public boolean exists() {
return listId != -1;
}
}

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="M19.4,9H16V5.6C16,5 15.6,5 15,5s-1,0 -1,0.6V9h-3.4C10,9 10,9.4 10,10s0,1 0.6,1H14v3.4c0,0.6 0.4,0.6 1,0.6s1,0 1,-0.6V11h3.4c0.6,0 0.6,-0.4 0.6,-1S20,9 19.4,9zM7.4,9H0.6C0,9 0,9.4 0,10s0,1 0.6,1h6.8C8,11 8,10.6 8,10S8,9 7.4,9zM7.4,14H0.6C0,14 0,14.4 0,15s0,1 0.6,1h6.8C8,16 8,15.6 8,15S8,14 7.4,14zM7.4,4H0.6C0,4 0,4.4 0,5s0,1 0.6,1h6.8C8,6 8,5.6 8,5S8,4 7.4,4z" />
</vector>

View File

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
style="@style/PopupCardView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/list_popup_root">
<ProgressBar
android:id="@+id/list_popup_loading"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="invisible" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="@dimen/tweetpopup_margin_layout">
<EditText
android:id="@+id/list_edit_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/userlist_edittext_margin"
android:autofillHints="@string/userlist_enter_title"
android:background="@android:color/transparent"
android:ems="10"
android:hint="@string/userlist_enter_title"
android:inputType="textPersonName"
android:singleLine="true" />
<EditText
android:id="@+id/list_edit_descr"
android:layout_width="@dimen/userlist_descr_width"
android:layout_height="@dimen/userlist_descr_height"
android:autofillHints="@string/userlist_enter_descr"
android:background="@android:color/transparent"
android:ems="10"
android:gravity="top"
android:hint="@string/userlist_enter_descr"
android:inputType="textPersonName" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="@dimen/userlist_layout_margin"
android:gravity="end"
android:orientation="horizontal">
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/list_edit_public_sw"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/userlist_public_sel"
app:switchPadding="@dimen/userlist_switch_padding" />
<Button
android:id="@+id/userlist_create_list"
android:layout_width="wrap_content"
android:layout_height="@dimen/userlist_button_height"
android:layout_weight="1"
android:background="@drawable/button"
android:paddingLeft="@dimen/userlist_button_padding"
android:paddingRight="@dimen/userlist_button_padding"
android:text="@string/userlist_create" />
</LinearLayout>
</LinearLayout>
</FrameLayout>
</androidx.cardview.widget.CardView>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/list_create"
android:icon="@drawable/new_list"
android:title="@string/menu_new_list"
app:showAsAction="always" />
</menu>

View File

@ -155,4 +155,12 @@
<string name="info_fetching_link">öffne Twitter login Seite</string>
<string name="info_login_to_twitter">Melde in Twitter an</string>
<string name="info_twitter_login_link">Zum Anmelden bitte Link anklicken</string>
<string name="menu_new_list">neue Liste erstellen</string>
<string name="userlist_public_sel">öffentlich</string>
<string name="userlist_enter_title">Titel eingeben</string>
<string name="userlist_enter_descr">Beschreibung</string>
<string name="userlist_create">Liste erstellen</string>
<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>
</resources>

View File

@ -187,4 +187,13 @@
<dimen name="loginpopup_text_padding">20dp</dimen>
<dimen name="loginpopup_text_margin">5dp</dimen>
<!--dimen of dialog_userlist.xml-->
<dimen name="userlist_descr_height">200dp</dimen>
<dimen name="userlist_descr_width">300dp</dimen>
<dimen name="userlist_switch_padding">5dp</dimen>
<dimen name="userlist_button_height">20dp</dimen>
<dimen name="userlist_layout_margin">10dp</dimen>
<dimen name="userlist_button_padding">5dp</dimen>
<dimen name="userlist_edittext_margin">5dp</dimen>
</resources>

View File

@ -161,4 +161,12 @@
<string name="info_fetching_link">opening twitter login site</string>
<string name="info_login_to_twitter">login to Twitter</string>
<string name="info_twitter_login_link">Please click the link below to login</string>
<string name="menu_new_list">create new list</string>
<string name="userlist_public_sel">public</string>
<string name="userlist_enter_title">Enter list title</string>
<string name="userlist_enter_descr">Enter list description</string>
<string name="userlist_create">Create list</string>
<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>
</resources>