diff --git a/twidere.component.twitter4j/src/main/java/org/mariotaku/twidere/api/twitter/model/impl/PageableResponseListWrapper.java b/twidere.component.twitter4j/src/main/java/org/mariotaku/twidere/api/twitter/model/impl/PageableResponseListWrapper.java index 0e7c2fef1..3471c9ee5 100644 --- a/twidere.component.twitter4j/src/main/java/org/mariotaku/twidere/api/twitter/model/impl/PageableResponseListWrapper.java +++ b/twidere.component.twitter4j/src/main/java/org/mariotaku/twidere/api/twitter/model/impl/PageableResponseListWrapper.java @@ -26,7 +26,6 @@ import org.mariotaku.twidere.api.twitter.TwitterConverter; import java.lang.reflect.Type; import java.util.ArrayList; -import java.util.Collection; import twitter4j.PageableResponseList; import twitter4j.Status; @@ -50,8 +49,8 @@ public class PageableResponseListWrapper extends TwitterResponseImpl implements @JsonField(name = "statuses") ArrayList statuses; - @JsonField(name = "user_lists") - ArrayList userLists; + @JsonField(name = "lists") + ArrayList userLists; @Override public PageableResponseList getWrapped(Object extra) { diff --git a/twidere.component.twitter4j/src/main/java/twitter4j/UserList.java b/twidere.component.twitter4j/src/main/java/twitter4j/UserList.java index 2b29f4d27..47023a1c8 100644 --- a/twidere.component.twitter4j/src/main/java/twitter4j/UserList.java +++ b/twidere.component.twitter4j/src/main/java/twitter4j/UserList.java @@ -53,7 +53,13 @@ public interface UserList extends Comparable, TwitterResponse { boolean isFollowing(); enum Mode { - PUBLIC, PRIVATE; + PUBLIC("public"), PRIVATE("private"); + + private final String mode; + + Mode(String mode) { + this.mode = mode; + } public static Mode parse(String str) { switch (str) { @@ -65,5 +71,8 @@ public interface UserList extends Comparable, TwitterResponse { throw new UnsupportedOperationException(); } + public String getMode() { + return mode; + } } } diff --git a/twidere.component.twitter4j/src/main/java/twitter4j/UserListUpdate.java b/twidere.component.twitter4j/src/main/java/twitter4j/UserListUpdate.java index 5e8c89c3a..359d5f9e7 100644 --- a/twidere.component.twitter4j/src/main/java/twitter4j/UserListUpdate.java +++ b/twidere.component.twitter4j/src/main/java/twitter4j/UserListUpdate.java @@ -34,7 +34,7 @@ public class UserListUpdate extends SimpleValueMap { put("name", name); } - public void setPublic(boolean isPublic) { - put("public", String.valueOf(isPublic)); + public void setMode(UserList.Mode mode) { + put("mode", mode.getMode()); } } diff --git a/twidere.component.twitter4j/src/main/java/twitter4j/api/ListsResources.java b/twidere.component.twitter4j/src/main/java/twitter4j/api/ListsResources.java index 9229c6c92..048cea220 100644 --- a/twidere.component.twitter4j/src/main/java/twitter4j/api/ListsResources.java +++ b/twidere.component.twitter4j/src/main/java/twitter4j/api/ListsResources.java @@ -19,7 +19,10 @@ package twitter4j.api; +import org.mariotaku.simplerestapi.http.BodyType; import org.mariotaku.simplerestapi.method.GET; +import org.mariotaku.simplerestapi.method.POST; +import org.mariotaku.simplerestapi.param.Body; import org.mariotaku.simplerestapi.param.Form; import org.mariotaku.simplerestapi.param.Query; @@ -36,39 +39,53 @@ import twitter4j.UserListUpdate; * @author Joern Huxhorn - jhuxhorn at googlemail.com */ public interface ListsResources { - UserList addUserListMember(long listId, long userId) throws TwitterException; + @POST("/lists/members/create.json") + @Body(BodyType.FORM) + UserList addUserListMember(@Query("list_id") long listId, @Query("user_id") long userId) throws TwitterException; - UserList addUserListMember(long listId, String userScreenName) throws TwitterException; + @POST("/lists/members/create.json") + @Body(BodyType.FORM) + UserList addUserListMember(@Query("list_id") long listId, @Query("screen_name") String userScreenName) throws TwitterException; - UserList addUserListMembers(long listId, long[] userIds) throws TwitterException; + @POST("/lists/members/create_all.json") + @Body(BodyType.FORM) + UserList addUserListMembers(@Form("list_id") long listId, @Form("user_id") long[] userIds) throws TwitterException; - UserList addUserListMembers(long listId, String[] screenNames) throws TwitterException; + @POST("/lists/members/create_all.json") + @Body(BodyType.FORM) + UserList addUserListMembers(@Form("list_id") long listId, @Form("screen_name") String[] screenNames) throws TwitterException; - UserList createUserList(String listName, boolean isPublicList, String description) throws TwitterException; + @POST("/lists/create.json") + @Body(BodyType.FORM) + UserList createUserList(@Form UserListUpdate update) throws TwitterException; - UserList createUserListSubscription(long listId) throws TwitterException; + UserList createUserListSubscription(@Query("list_id") long listId) throws TwitterException; - UserList deleteUserListMember(long listId, long userId) throws TwitterException; + UserList deleteUserListMember(@Query("list_id") long listId, @Query("user_id") long userId) throws TwitterException; - UserList deleteUserListMember(long listId, String screenName) throws TwitterException; + UserList deleteUserListMember(@Query("list_id") long listId, String screenName) throws TwitterException; - UserList deleteUserListMembers(long listId, long[] userIds) throws TwitterException; + UserList deleteUserListMembers(@Query("list_id") long listId, long[] userIds) throws TwitterException; - UserList deleteUserListMembers(long listId, String[] screenNames) throws TwitterException; + UserList deleteUserListMembers(@Query("list_id") long listId, String[] screenNames) throws TwitterException; - UserList destroyUserList(long listId) throws TwitterException; + UserList destroyUserList(@Query("list_id") long listId) throws TwitterException; - UserList destroyUserListSubscription(long listId) throws TwitterException; + UserList destroyUserListSubscription(@Query("list_id") long listId) throws TwitterException; - PageableResponseList getUserListMembers(long listId, Paging paging) throws TwitterException; + @GET("/lists/members.json") + PageableResponseList getUserListMembers(@Query("list_id") long listId, @Query Paging paging) throws TwitterException; - PageableResponseList getUserListMembers(String slug, long ownerId, Paging paging) + @GET("/lists/members.json") + PageableResponseList getUserListMembers(@Query("slug") String slug, @Query("owner_id") long ownerId, @Query Paging paging) throws TwitterException; - PageableResponseList getUserListMembers(String slug, String ownerScreenName, Paging paging) + @GET("/lists/members.json") + PageableResponseList getUserListMembers(@Query("slug") String slug, @Query("owner_screen_name") String ownerScreenName, @Query Paging paging) throws TwitterException; - PageableResponseList getUserListMemberships(long cursor) throws TwitterException; + @GET("/lists/memberships.json") + PageableResponseList getUserListMemberships(@Query Paging paging) throws TwitterException; @GET("/lists/memberships.json") PageableResponseList getUserListMemberships(@Query("user_id") long listMemberId, @Query Paging paging) throws TwitterException; @@ -81,14 +98,18 @@ public interface ListsResources { PageableResponseList getUserListMemberships(@Query("screen_name") String listMemberScreenName, @Query Paging paging) throws TwitterException; - PageableResponseList getUserListMemberships(String listMemberScreenName, long cursor, + @GET("/lists/ownerships.json") + PageableResponseList getUserListMemberships(@Query("screen_name") String listMemberScreenName, @Query Paging paging, boolean filterToOwnedLists) throws TwitterException; - PageableResponseList getUserListOwnerships(long cursor) throws TwitterException; + @GET("/lists/ownerships.json") + PageableResponseList getUserListOwnerships(@Query Paging paging) throws TwitterException; - PageableResponseList getUserListOwnerships(long listMemberId, long cursor) throws TwitterException; + @GET("/lists/ownerships.json") + PageableResponseList getUserListOwnerships(@Query("user_id") long listMemberId, @Query Paging paging) throws TwitterException; - PageableResponseList getUserListOwnerships(String listMemberScreenName, long cursor) + @GET("/lists/ownerships.json") + PageableResponseList getUserListOwnerships(@Query("screen_name") String listMemberScreenName, @Query Paging paging) throws TwitterException; @GET("/lists/list.json") @@ -101,10 +122,10 @@ public interface ListsResources { ResponseList getUserListStatuses(@Query("list_id") long listId, @Query Paging paging) throws TwitterException; @GET("/lists/statuses.json") - ResponseList getUserListStatuses(@Query("list_id") String slug, @Query("owner_id") long ownerId, @Query Paging paging) throws TwitterException; + ResponseList getUserListStatuses(@Query("slug") String slug, @Query("owner_id") long ownerId, @Query Paging paging) throws TwitterException; @GET("/lists/statuses.json") - ResponseList getUserListStatuses(@Query("list_id") String slug, @Query("owner_screen_name") String ownerScreenName, @Query Paging paging) + ResponseList getUserListStatuses(@Query("slug") String slug, @Query("owner_screen_name") String ownerScreenName, @Query Paging paging) throws TwitterException; @GET("/lists/subscribers.json") @@ -127,15 +148,16 @@ public interface ListsResources { PageableResponseList getUserListSubscriptions(@Query("user_id") long userId, long cursor) throws TwitterException; - UserList showUserList(long listId) throws TwitterException; + @GET("/lists/show.json") + UserList showUserList(@Query("list_id") long listId) throws TwitterException; - UserList showUserList(String slug, long ownerId) throws TwitterException; + @GET("/lists/show.json") + UserList showUserList(@Query("slug") String slug, @Query("owner_id") long ownerId) throws TwitterException; - UserList showUserList(String slug, String ownerScreenName) throws TwitterException; - - User showUserListMembership(long listId, long userId) throws TwitterException; - - User showUserListSubscription(long listId, long userId) throws TwitterException; + @GET("/lists/show.json") + UserList showUserList(@Query("slug") String slug, @Query("owner_screen_name") String ownerScreenName) throws TwitterException; + @POST("/lists/update.json") + @Body(BodyType.FORM) UserList updateUserList(@Query("list_id") long listId, @Form UserListUpdate update) throws TwitterException; } diff --git a/twidere.component.twitter4j/src/main/java/twitter4j/api/UsersResources.java b/twidere.component.twitter4j/src/main/java/twitter4j/api/UsersResources.java index daeb5fa04..da1e8c886 100644 --- a/twidere.component.twitter4j/src/main/java/twitter4j/api/UsersResources.java +++ b/twidere.component.twitter4j/src/main/java/twitter4j/api/UsersResources.java @@ -40,9 +40,6 @@ import twitter4j.SettingsUpdate; import twitter4j.TwitterException; import twitter4j.User; -/** - * @author Joern Huxhorn - jhuxhorn at googlemail.com - */ public interface UsersResources { @POST("/blocks/create.json") diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/CreateUserListDialogFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/CreateUserListDialogFragment.java index 33524a17a..bceb026ed 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/CreateUserListDialogFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/CreateUserListDialogFragment.java @@ -28,73 +28,76 @@ import android.support.annotation.NonNull; import android.view.LayoutInflater; import android.view.View; import android.widget.CheckBox; -import android.widget.EditText; + +import com.rengwuxian.materialedittext.MaterialEditText; import org.mariotaku.twidere.R; +import org.mariotaku.twidere.text.validator.UserListNameValidator; import org.mariotaku.twidere.util.AsyncTwitterWrapper; import org.mariotaku.twidere.util.ParseUtils; import org.mariotaku.twidere.util.ThemeUtils; public class CreateUserListDialogFragment extends BaseSupportDialogFragment implements DialogInterface.OnClickListener { - private EditText mEditName, mEditDescription; - private CheckBox mPublicCheckBox; - private String mName, mDescription; - private long mAccountId; - private long mListId; - private boolean mIsPublic = true; - private AsyncTwitterWrapper mTwitterWrapper; + private MaterialEditText mEditName, mEditDescription; + private CheckBox mPublicCheckBox; + private String mName, mDescription; + private long mAccountId; + private long mListId; + private boolean mIsPublic = true; + private AsyncTwitterWrapper mTwitterWrapper; - @Override - public void onClick(final DialogInterface dialog, final int which) { - if (mAccountId <= 0) return; - switch (which) { - case DialogInterface.BUTTON_POSITIVE: { - mName = ParseUtils.parseString(mEditName.getText()); - mDescription = ParseUtils.parseString(mEditDescription.getText()); - mIsPublic = mPublicCheckBox.isChecked(); - if (mName == null || mName.length() <= 0) return; - mTwitterWrapper.createUserListAsync(mAccountId, mName, mIsPublic, mDescription); - break; - } - } - - } - - @NonNull @Override - public Dialog onCreateDialog(final Bundle savedInstanceState) { - mTwitterWrapper = getApplication().getTwitterWrapper(); - final Bundle bundle = savedInstanceState == null ? getArguments() : savedInstanceState; - mAccountId = bundle != null ? bundle.getLong(EXTRA_ACCOUNT_ID, -1) : -1; - final Context wrapped = ThemeUtils.getDialogThemedContext(getActivity()); - final AlertDialog.Builder builder = new AlertDialog.Builder(wrapped); - final View view = LayoutInflater.from(wrapped).inflate(R.layout.dialog_user_list_detail_editor, null); - builder.setView(view); - mEditName = (EditText) view.findViewById(R.id.name); - mEditDescription = (EditText) view.findViewById(R.id.description); - mPublicCheckBox = (CheckBox) view.findViewById(R.id.is_public); - if (mName != null) { - mEditName.setText(mName); - } - if (mDescription != null) { - mEditDescription.setText(mDescription); - } - mPublicCheckBox.setChecked(mIsPublic); - builder.setTitle(R.string.new_user_list); - builder.setPositiveButton(android.R.string.ok, this); - builder.setNegativeButton(android.R.string.cancel, this); - return builder.create(); - } + public void onClick(final DialogInterface dialog, final int which) { + if (mAccountId <= 0) return; + switch (which) { + case DialogInterface.BUTTON_POSITIVE: { + mName = ParseUtils.parseString(mEditName.getText()); + mDescription = ParseUtils.parseString(mEditDescription.getText()); + mIsPublic = mPublicCheckBox.isChecked(); + if (mName == null || mName.length() <= 0) return; + mTwitterWrapper.createUserListAsync(mAccountId, mName, mIsPublic, mDescription); + break; + } + } - @Override - public void onSaveInstanceState(final Bundle outState) { - outState.putLong(EXTRA_ACCOUNT_ID, mAccountId); - outState.putLong(EXTRA_LIST_ID, mListId); - outState.putString(EXTRA_LIST_NAME, mName); - outState.putString(EXTRA_DESCRIPTION, mDescription); - outState.putBoolean(EXTRA_IS_PUBLIC, mIsPublic); - super.onSaveInstanceState(outState); - } + } + + @NonNull + @Override + public Dialog onCreateDialog(final Bundle savedInstanceState) { + mTwitterWrapper = getApplication().getTwitterWrapper(); + final Bundle bundle = savedInstanceState == null ? getArguments() : savedInstanceState; + mAccountId = bundle != null ? bundle.getLong(EXTRA_ACCOUNT_ID, -1) : -1; + final Context wrapped = ThemeUtils.getDialogThemedContext(getActivity()); + final AlertDialog.Builder builder = new AlertDialog.Builder(wrapped); + final View view = LayoutInflater.from(wrapped).inflate(R.layout.dialog_user_list_detail_editor, null); + builder.setView(view); + mEditName = (MaterialEditText) view.findViewById(R.id.name); + mEditName.addValidator(new UserListNameValidator(getString(R.string.invalid_list_name))); + mEditDescription = (MaterialEditText) view.findViewById(R.id.description); + mPublicCheckBox = (CheckBox) view.findViewById(R.id.is_public); + if (mName != null) { + mEditName.setText(mName); + } + if (mDescription != null) { + mEditDescription.setText(mDescription); + } + mPublicCheckBox.setChecked(mIsPublic); + builder.setTitle(R.string.new_user_list); + builder.setPositiveButton(android.R.string.ok, this); + builder.setNegativeButton(android.R.string.cancel, this); + return builder.create(); + } + + @Override + public void onSaveInstanceState(final Bundle outState) { + outState.putLong(EXTRA_ACCOUNT_ID, mAccountId); + outState.putLong(EXTRA_LIST_ID, mListId); + outState.putString(EXTRA_LIST_NAME, mName); + outState.putString(EXTRA_DESCRIPTION, mDescription); + outState.putBoolean(EXTRA_IS_PUBLIC, mIsPublic); + super.onSaveInstanceState(outState); + } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/UserListFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/UserListFragment.java index 829e44ae9..043d8aff3 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/UserListFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/UserListFragment.java @@ -54,6 +54,8 @@ import android.view.ViewGroup; import android.widget.CheckBox; import android.widget.EditText; +import com.rengwuxian.materialedittext.MaterialEditText; + import org.mariotaku.twidere.R; import org.mariotaku.twidere.activity.iface.IThemedActivity; import org.mariotaku.twidere.activity.support.AccountSelectorActivity; @@ -67,6 +69,7 @@ import org.mariotaku.twidere.graphic.EmptyDrawable; import org.mariotaku.twidere.model.ParcelableUser; import org.mariotaku.twidere.model.ParcelableUserList; import org.mariotaku.twidere.model.SingleResponse; +import org.mariotaku.twidere.text.validator.UserListNameValidator; import org.mariotaku.twidere.util.AsyncTwitterWrapper; import org.mariotaku.twidere.util.LinkCreator; import org.mariotaku.twidere.util.MediaLoaderWrapper; @@ -87,7 +90,6 @@ import twitter4j.UserListUpdate; import static org.mariotaku.twidere.util.MenuUtils.setMenuItemAvailability; import static org.mariotaku.twidere.util.Utils.addIntentToMenu; -import static org.mariotaku.twidere.util.TwitterAPIUtils.getTwitterInstance; import static org.mariotaku.twidere.util.Utils.openUserListDetails; import static org.mariotaku.twidere.util.Utils.openUserProfile; @@ -458,7 +460,7 @@ public class UserListFragment extends BaseSupportFragment implements OnClickList public static class EditUserListDialogFragment extends BaseSupportDialogFragment implements DialogInterface.OnClickListener { - private EditText mEditName, mEditDescription; + private MaterialEditText mEditName, mEditDescription; private CheckBox mPublicCheckBox; private String mName, mDescription; private long mAccountId; @@ -476,7 +478,7 @@ public class UserListFragment extends BaseSupportFragment implements OnClickList mIsPublic = mPublicCheckBox.isChecked(); if (mName == null || mName.length() <= 0) return; final UserListUpdate update = new UserListUpdate(); - update.setPublic(mIsPublic); + update.setMode(mIsPublic ? UserList.Mode.PUBLIC : UserList.Mode.PRIVATE); update.setName(mName); update.setDescription(mDescription); mTwitterWrapper.updateUserListDetails(mAccountId, mListId, update); @@ -500,8 +502,9 @@ public class UserListFragment extends BaseSupportFragment implements OnClickList final AlertDialog.Builder builder = new AlertDialog.Builder(wrapped); final View view = LayoutInflater.from(wrapped).inflate(R.layout.dialog_user_list_detail_editor, null); builder.setView(view); - mEditName = (EditText) view.findViewById(R.id.name); - mEditDescription = (EditText) view.findViewById(R.id.description); + mEditName = (MaterialEditText) view.findViewById(R.id.name); + mEditName.addValidator(new UserListNameValidator(getString(R.string.invalid_list_name))); + mEditDescription = (MaterialEditText) view.findViewById(R.id.description); mPublicCheckBox = (CheckBox) view.findViewById(R.id.is_public); if (mName != null) { mEditName.setText(mName); diff --git a/twidere/src/main/java/org/mariotaku/twidere/text/validator/UserListNameValidator.java b/twidere/src/main/java/org/mariotaku/twidere/text/validator/UserListNameValidator.java new file mode 100644 index 000000000..b118afb84 --- /dev/null +++ b/twidere/src/main/java/org/mariotaku/twidere/text/validator/UserListNameValidator.java @@ -0,0 +1,44 @@ +/* + * Twidere - Twitter client for Android + * + * Copyright (C) 2012-2015 Mariotaku Lee + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.mariotaku.twidere.text.validator; + +import android.support.annotation.NonNull; + +import com.rengwuxian.materialedittext.validation.METValidator; + +/** + * Created by mariotaku on 15/5/8. + */ +public class UserListNameValidator extends METValidator { + public UserListNameValidator(@NonNull String errorMessage) { + super(errorMessage); + } + + @Override + public boolean isValid(@NonNull CharSequence text, boolean isEmpty) { + if (isEmpty) return false; + for (int i = 0, j = text.length(); i < j; i++) { + final char ch = text.charAt(i); + if (i == 0 && !Character.isLetter(ch)) return false; + if (!Character.isLetterOrDigit(ch) && ch != '-' && ch != '_') return false; + } + return true; + } +} diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/AsyncTwitterWrapper.java b/twidere/src/main/java/org/mariotaku/twidere/util/AsyncTwitterWrapper.java index 901391b30..6a357337d 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/AsyncTwitterWrapper.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/AsyncTwitterWrapper.java @@ -1172,7 +1172,11 @@ public class AsyncTwitterWrapper extends TwitterWrapper { final Twitter twitter = TwitterAPIUtils.getTwitterInstance(mContext, account_id, false); if (twitter == null || list_name == null) return SingleResponse.getInstance(); try { - final UserList list = twitter.createUserList(list_name, is_public, description); + final UserListUpdate userListUpdate = new UserListUpdate(); + userListUpdate.setName(list_name); + userListUpdate.setMode(is_public ? UserList.Mode.PUBLIC : UserList.Mode.PRIVATE); + userListUpdate.setDescription(description); + final UserList list = twitter.createUserList(userListUpdate); return SingleResponse.getInstance(list, null); } catch (final TwitterException e) { return SingleResponse.getInstance(null, e); diff --git a/twidere/src/main/res/layout/dialog_user_list_detail_editor.xml b/twidere/src/main/res/layout/dialog_user_list_detail_editor.xml index 9935e8239..d79ad10e0 100644 --- a/twidere/src/main/res/layout/dialog_user_list_detail_editor.xml +++ b/twidere/src/main/res/layout/dialog_user_list_detail_editor.xml @@ -36,7 +36,7 @@ app:met_baseColor="?android:textColorPrimary" app:met_floatingLabel="normal" app:met_floatingLabelText="@string/name" - app:met_maxCharacters="20" /> + app:met_maxCharacters="25" /> Twidere will restart to apply settings. Don\'t restart List details + Must start with a letter and can consist only letters, numbers, \"-\", or \"_\". \ No newline at end of file