renamed and merged activities, added new endpoints, bug fix, gradle update

This commit is contained in:
nuclearfog 2022-07-10 18:44:53 +02:00
parent 2ea606daeb
commit edab6b8852
No known key found for this signature in database
GPG Key ID: AA0271FBE406DB98
30 changed files with 556 additions and 375 deletions

View File

@ -6,7 +6,7 @@ plugins {
android {
compileSdkVersion 32
buildToolsVersion '32.0.0'
buildToolsVersion '33.0.0'
defaultConfig {
applicationId 'org.nuclearfog.twidda'

View File

@ -57,7 +57,7 @@
</activity>
<activity
android:name=".ui.activities.SearchPage"
android:name=".ui.activities.SearchActivity"
android:screenOrientation="portrait"
android:theme="@style/AppTheme" />
@ -77,7 +77,7 @@
android:theme="@style/TransparencyDim" />
<activity
android:name=".ui.activities.AppSettings"
android:name=".ui.activities.SettingsActivity"
android:screenOrientation="portrait"
android:theme="@style/AppTheme" />
@ -102,7 +102,7 @@
android:theme="@style/AppTheme" />
<activity
android:name=".ui.activities.DirectMessage"
android:name=".ui.activities.MessageActivity"
android:screenOrientation="portrait"
android:theme="@style/AppTheme" />
@ -123,7 +123,7 @@
android:windowSoftInputMode="stateHidden" />
<activity
android:name=".ui.activities.Userlists"
android:name=".ui.activities.UserlistsActivity"
android:screenOrientation="portrait"
android:theme="@style/AppTheme" />
@ -143,7 +143,7 @@
android:theme="@style/AppTheme" />
<activity
android:name=".ui.activities.UserExclude"
android:name=".ui.activities.UsersActivity"
android:screenOrientation="portrait"
android:theme="@style/AppTheme" />

View File

@ -12,12 +12,13 @@ import android.widget.TextView;
import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.database.GlobalSettings;
import org.nuclearfog.twidda.ui.activities.SettingsActivity;
/**
* Spinner Adapter for font settings
*
* @author nuclearfog
* @see org.nuclearfog.twidda.ui.activities.AppSettings
* @see SettingsActivity
*/
public class FontAdapter extends BaseAdapter {

View File

@ -10,12 +10,17 @@ import static org.nuclearfog.twidda.ui.fragments.TweetFragment.TWEET_FRAG_MENT;
import static org.nuclearfog.twidda.ui.fragments.TweetFragment.TWEET_FRAG_SEARCH;
import static org.nuclearfog.twidda.ui.fragments.TweetFragment.TWEET_FRAG_TWEETS;
import static org.nuclearfog.twidda.ui.fragments.UserFragment.KEY_FRAG_DEL_USER;
import static org.nuclearfog.twidda.ui.fragments.UserFragment.KEY_FRAG_USER_ID;
import static org.nuclearfog.twidda.ui.fragments.UserFragment.KEY_FRAG_USER_ID_ALL;
import static org.nuclearfog.twidda.ui.fragments.UserFragment.KEY_FRAG_USER_MODE;
import static org.nuclearfog.twidda.ui.fragments.UserFragment.KEY_FRAG_USER_SEARCH;
import static org.nuclearfog.twidda.ui.fragments.UserFragment.USER_FRAG_BLOCKS;
import static org.nuclearfog.twidda.ui.fragments.UserFragment.USER_FRAG_FAVORIT;
import static org.nuclearfog.twidda.ui.fragments.UserFragment.USER_FRAG_FOLLOWER_REQUEST;
import static org.nuclearfog.twidda.ui.fragments.UserFragment.USER_FRAG_FOLLOWING_REQUEST;
import static org.nuclearfog.twidda.ui.fragments.UserFragment.USER_FRAG_FRIENDS;
import static org.nuclearfog.twidda.ui.fragments.UserFragment.USER_FRAG_LISTS;
import static org.nuclearfog.twidda.ui.fragments.UserFragment.USER_FRAG_MUTES;
import static org.nuclearfog.twidda.ui.fragments.UserFragment.USER_FRAG_RETWEET;
import static org.nuclearfog.twidda.ui.fragments.UserFragment.USER_FRAG_SEARCH;
import static org.nuclearfog.twidda.ui.fragments.UserFragment.USER_FRAG_SUBSCR;
import static org.nuclearfog.twidda.ui.fragments.UserListFragment.KEY_FRAG_LIST_LIST_TYPE;
@ -186,8 +191,8 @@ public class FragmentAdapter extends FragmentStatePagerAdapter {
tweetParam.putInt(KEY_FRAG_TWEET_MODE, TWEET_FRAG_LIST);
userParam.putInt(KEY_FRAG_USER_MODE, USER_FRAG_LISTS);
userParam.putBoolean(KEY_FRAG_DEL_USER, ownerOfList);
userParam.putLong(KEY_FRAG_USER_ID, listId);
subscrParam.putLong(KEY_FRAG_USER_ID, listId);
userParam.putLong(KEY_FRAG_USER_ID_ALL, listId);
subscrParam.putLong(KEY_FRAG_USER_ID_ALL, listId);
subscrParam.putInt(KEY_FRAG_USER_MODE, USER_FRAG_SUBSCR);
fragments = new ListFragment[3];
fragments[0] = new TweetFragment();
@ -216,6 +221,79 @@ public class FragmentAdapter extends FragmentStatePagerAdapter {
notifyDataSetChanged();
}
/**
* setup adapter to show follow requesting users
*/
public void setupFollowRequestPage() {
Bundle paramFollowing = new Bundle();
Bundle paramFollower = new Bundle();
paramFollowing.putInt(KEY_FRAG_USER_MODE, USER_FRAG_FOLLOWING_REQUEST);
paramFollower.putInt(KEY_FRAG_USER_MODE, USER_FRAG_FOLLOWER_REQUEST);
fragments = new ListFragment[2];
fragments[0] = new UserFragment();
fragments[1] = new UserFragment();
fragments[0].setArguments(paramFollowing);
fragments[1].setArguments(paramFollower);
notifyDataSetChanged();
}
/**
* setup adapter to show "following" of an user
*
* @param userId ID of the user
*/
public void setupFollowingPage(long userId) {
Bundle userParam = new Bundle();
userParam.putInt(KEY_FRAG_USER_MODE, USER_FRAG_FOLLOWING_REQUEST);
userParam.putLong(KEY_FRAG_USER_ID_ALL, userId);
userParam.putInt(KEY_FRAG_USER_MODE, USER_FRAG_FRIENDS);
fragments = new ListFragment[1];
fragments[0] = new UserFragment();
fragments[0].setArguments(userParam);
notifyDataSetChanged();
}
/**
* setup adapter to show "follower" of an user
*
* @param userId ID of the user
*/
public void setupFollowerPage(long userId) {
Bundle userParam = new Bundle();
userParam.putInt(KEY_FRAG_USER_MODE, USER_FRAG_FOLLOWER_REQUEST);
userParam.putLong(KEY_FRAG_USER_ID_ALL, userId);
userParam.putInt(KEY_FRAG_USER_MODE, USER_FRAG_FRIENDS);
fragments = new ListFragment[1];
fragments[0] = new UserFragment();
fragments[0].setArguments(userParam);
notifyDataSetChanged();
}
/**
* setup adapter to show users retweeting a tweet
* @param tweetId
*/
public void setupRetweeterPage(long tweetId) {
Bundle userParam = new Bundle();
userParam.putInt(KEY_FRAG_USER_MODE, USER_FRAG_RETWEET);
userParam.putLong(KEY_FRAG_USER_ID_ALL, tweetId);
fragments = new ListFragment[1];
fragments[0] = new UserFragment();
fragments[0].setArguments(userParam);
notifyDataSetChanged();
}
public void setFavoriterPage(long tweetId) {
Bundle userParam = new Bundle();
userParam.putInt(KEY_FRAG_USER_MODE, USER_FRAG_FAVORIT);
userParam.putLong(KEY_FRAG_USER_ID_ALL, tweetId);
fragments = new ListFragment[1];
fragments[0] = new UserFragment();
fragments[0].setArguments(userParam);
notifyDataSetChanged();
}
/**
* called when app settings change
*/

View File

@ -12,6 +12,7 @@ import androidx.annotation.MainThread;
import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.database.GlobalSettings;
import org.nuclearfog.twidda.model.Location;
import org.nuclearfog.twidda.ui.activities.SettingsActivity;
import java.util.ArrayList;
import java.util.List;
@ -20,7 +21,7 @@ import java.util.List;
* Adapter class for Location selection spinner
*
* @author nuclearfog
* @see org.nuclearfog.twidda.ui.activities.AppSettings
* @see SettingsActivity
*/
public class LocationAdapter extends BaseAdapter {

View File

@ -10,6 +10,7 @@ import android.widget.TextView;
import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.database.GlobalSettings;
import org.nuclearfog.twidda.ui.activities.SettingsActivity;
import java.util.Locale;
@ -17,7 +18,7 @@ import java.util.Locale;
* list adapter to show font scales
*
* @author nuclearfog
* @see org.nuclearfog.twidda.ui.activities.AppSettings
* @see SettingsActivity
*/
public class ScaleAdapter extends BaseAdapter {

View File

@ -43,6 +43,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@ -71,40 +72,51 @@ import okio.Okio;
*/
public class Twitter implements GlobalSettings.SettingsListener {
// API parameters
private static final String OAUTH = "1.0";
public static final String SIGNATURE_ALG = "HMAC-SHA256";
private static final String JSON = ".json";
// API addresses
private static final String API = "https://api.twitter.com/";
private static final String UPLOAD = "https://upload.twitter.com/";
private static final String DOWNLOAD = "https://ton.twitter.com/";
private static final String AUTHENTICATE = API + "oauth/authenticate";
public static final String REQUEST_URL = AUTHENTICATE + "?oauth_token=";
// authentication endpoints
public static final String AUTHENTICATE = API + "oauth/authenticate";
private static final String REQUEST_TOKEN = API + "oauth/request_token";
private static final String OAUTH_VERIFIER = API + "oauth/access_token";
private static final String CREDENTIALS = API + "1.1/account/verify_credentials.json";
private static final String USER_LOOKUP = API + "1.1/users/show.json";
private static final String USER_FOLLOWING = API + "1.1/friends/list.json";
private static final String USER_FOLLOWER = API + "1.1/followers/list.json";
private static final String USER_SEARCH = API + "1.1/users/search.json";
private static final String USER_LIST_MEMBER = API + "1.1/lists/members.json";
private static final String USER_LIST_SUBSCRIBER = API + "1.1/lists/subscribers.json";
private static final String BLOCK_LIST = API + "1.1/blocks/list.json";
private static final String BLOCK_ID_LIST = API + "1.1/blocks/ids.json";
private static final String MUTES_LIST = API + "1.1/mutes/users/list.json";
private static final String SHOW_TWEET = API + "1.1/statuses/show.json";
private static final String SHOW_HOME = API + "1.1/statuses/home_timeline.json";
private static final String SHOW_MENTIONS = API + "1.1/statuses/mentions_timeline.json";
private static final String USER_TIMELINE = API + "1.1/statuses/user_timeline.json";
private static final String USER_FAVORITS = API + "1.1/favorites/list.json";
// user ID endpoints
private static final String IDS_BLOCKED_USERS = API + "1.1/blocks/ids.json";
private static final String IDS_MUTED_USERS = API + "1.1/mutes/users/ids.json";
// user endpoints
private static final String USERS_MUTES = API + "1.1/mutes/users/list.json";
private static final String USER_FOLLOW = API + "1.1/friendships/create.json";
private static final String USER_UNFOLLOW = API + "1.1/friendships/destroy.json";
private static final String USER_BLOCK = API + "1.1/blocks/create.json";
private static final String USER_UNBLOCK = API + "1.1/blocks/destroy.json";
private static final String USER_MUTE = API + "1.1/mutes/users/create.json";
private static final String USER_UNMUTE = API + "1.1/mutes/users/destroy.json";
private static final String USER_LOOKUP = API + "1.1/users/show.json";
private static final String USERS_FOLLOWING = API + "1.1/friends/list.json";
private static final String USERS_FOLLOWER = API + "1.1/followers/list.json";
private static final String USERS_SEARCH = API + "1.1/users/search.json";
private static final String USERS_LIST_MEMBER = API + "1.1/lists/members.json";
private static final String USERS_LIST_SUBSCRIBER = API + "1.1/lists/subscribers.json";
private static final String USERS_LOOKUP = API + "1.1/users/lookup.json";
private static final String USERS_BLOCKED_LIST = API + "1.1/blocks/list.json";
private static final String USERS_FOLLOW_INCOMING = API + "1.1/friendships/incoming.json";
private static final String USERS_FOLLOW_OUTGOING = API + "1.1/friendships/outgoing.json";
// tweet endpoints
private static final String TWEETS_HOME_TIMELINE = API + "1.1/statuses/home_timeline.json";
private static final String TWEETS_MENTIONS = API + "1.1/statuses/mentions_timeline.json";
private static final String TWEETS_USER = API + "1.1/statuses/user_timeline.json";
private static final String TWEETS_USER_FAVORITS = API + "1.1/favorites/list.json";
private static final String TWEETS_LIST = API + "1.1/lists/statuses.json";
private static final String TWEET_LOOKUP = API + "1.1/statuses/show.json";
private static final String TWEET_SEARCH = API + "1.1/search/tweets.json";
private static final String TWEET_FAVORITE = API + "1.1/favorites/create.json";
private static final String TWEET_UNFAVORITE = API + "1.1/favorites/destroy.json";
@ -113,8 +125,8 @@ public class Twitter implements GlobalSettings.SettingsListener {
private static final String TWEET_UPLOAD = API + "1.1/statuses/update.json";
private static final String TWEET_DELETE = API + "1.1/statuses/destroy/";
private static final String TWEET_UNI = API + "2/tweets/";
private static final String TRENDS = API + "1.1/trends/place.json";
private static final String LOCATIONS = API + "1.1/trends/available.json";
// userlist endpoints
private static final String USERLIST_SHOW = API + "1.1/lists/show.json";
private static final String USERLIST_FOLLOW = API + "1.1/lists/subscribers/create.json";
private static final String USERLIST_UNFOLLOW = API + "1.1/lists/subscribers/destroy.json";
@ -125,19 +137,29 @@ public class Twitter implements GlobalSettings.SettingsListener {
private static final String USERLIST_MEMBERSHIP = API + "1.1/lists/memberships.json";
private static final String USERLIST_ADD_USER = API + "1.1/lists/members/create.json";
private static final String USERLIST_DEL_USER = API + "1.1/lists/members/destroy.json";
private static final String RELATION = API + "1.1/friendships/show.json";
// directmessage endpoints
private static final String DIRECTMESSAGE = API + "1.1/direct_messages/events/list.json";
private static final String DIRECTMESSAGE_CREATE = API + "1.1/direct_messages/events/new.json";
private static final String DIRECTMESSAGE_DELETE = API + "1.1/direct_messages/events/destroy.json";
private static final String MEDIA_UPLOAD = UPLOAD + "1.1/media/upload.json";
// profile update endpoints
private static final String PROFILE_UPDATE = API + "1.1/account/update_profile.json";
private static final String PROFILE_UPDATE_IMAGE = API + "1.1/account/update_profile_image.json";
private static final String PROFILE_UPDATE_BANNER = API + "1.1/account/update_profile_banner.json";
// other endpoints
private static final String TRENDS = API + "1.1/trends/place.json";
private static final String LOCATIONS = API + "1.1/trends/available.json";
private static final String RELATION = API + "1.1/friendships/show.json";
private static final String MEDIA_UPLOAD = UPLOAD + "1.1/media/upload.json";
private static final MediaType TYPE_STREAM = MediaType.parse("application/octet-stream");
private static final MediaType TYPE_JSON = MediaType.parse("application/json");
private static final MediaType TYPE_TEXT = MediaType.parse("text/plain");
private static final String JSON = ".json";
/**
* To upload big files like videos, files must be chunked in segments.
* Twitter can handle up to 1000 segments with max 5MB.
@ -300,6 +322,55 @@ public class Twitter implements GlobalSettings.SettingsListener {
return getUser1(USER_LOOKUP, params);
}
/**
* search for users matching a search string
*
* @param search search string
* @param page page of the search results
* @return list of users
*/
public Users searchUsers(String search, long page) throws TwitterException {
// search endpoint only supports pages parameter
long currentPage = page > 0 ? page : 1;
long nextPage = currentPage + 1;
List<String> params = new ArrayList<>();
params.add("q=" + StringTools.encode(search));
params.add("page=" + currentPage);
Users result = getUsers1(USERS_SEARCH, params);
// notice that there are no more results
// if result size is less than the requested size
if (result.size() < settings.getListSize())
nextPage = 0;
if (settings.filterResults())
filterUsers(result);
result.setPrevCursor(currentPage - 1);
result.setNextCursor(nextPage);
return result;
}
/**
* get users retweeting a tweet
*
* @param tweetId ID of the tweet
* @return user list
*/
public Users getRetweetingUsers(long tweetId) throws TwitterException {
String endpoint = TWEET_UNI + tweetId + "/retweeted_by";
return getUsers2(endpoint);
}
/**
* get users liking a tweet
*
* @param tweetId ID of the tweet
* @return user list
*/
public Users getLikingUsers(long tweetId) throws TwitterException {
String endpoint = TWEET_UNI + tweetId + "/liking_users";
return getUsers2(endpoint);
}
/**
* create a list of users a specified user is following
*
@ -311,7 +382,7 @@ public class Twitter implements GlobalSettings.SettingsListener {
List<String> params = new ArrayList<>();
params.add("user_id=" + userId);
params.add("cursor=" + cursor);
return getUsers1(USER_FOLLOWING, params);
return getUsers1(USERS_FOLLOWING, params);
}
/**
@ -325,7 +396,7 @@ public class Twitter implements GlobalSettings.SettingsListener {
List<String> params = new ArrayList<>();
params.add("user_id=" + userId);
params.add("cursor=" + cursor);
return getUsers1(USER_FOLLOWER, params);
return getUsers1(USERS_FOLLOWER, params);
}
/**
@ -339,7 +410,7 @@ public class Twitter implements GlobalSettings.SettingsListener {
List<String> params = new ArrayList<>();
params.add("list_id=" + listId);
params.add("cursor=" + cursor);
Users result = getUsers1(USER_LIST_MEMBER, params);
Users result = getUsers1(USERS_LIST_MEMBER, params);
// fix API returns zero previous_cursor when the end of the list is reached
// override previous cursor
if (cursor == -1L)
@ -360,7 +431,7 @@ public class Twitter implements GlobalSettings.SettingsListener {
List<String> params = new ArrayList<>();
params.add("list_id=" + listId);
params.add("cursor=" + cursor);
Users result = getUsers1(USER_LIST_SUBSCRIBER, params);
Users result = getUsers1(USERS_LIST_SUBSCRIBER, params);
// fix API returns zero previous_cursor when the end of the list is reached
// override previous cursor
if (cursor == -1L)
@ -370,6 +441,54 @@ public class Twitter implements GlobalSettings.SettingsListener {
return result;
}
/**
* get block list of the current user
*
* @param cursor cursor value used to parse the list
* @return list of users
*/
public Users getBlockedUsers(long cursor) throws TwitterException {
List<String> params = new ArrayList<>();
params.add("cursor=" + cursor);
return getUsers1(USERS_BLOCKED_LIST, params);
}
/**
* get mute list of the current user
*
* @param cursor cursor value used to parse the list
* @return list of users
*/
public Users getMutedUsers(long cursor) throws TwitterException {
List<String> params = new ArrayList<>();
params.add("cursor=" + cursor);
return getUsers1(USERS_MUTES, params);
}
/**
* return a list of the 100 recent users requesting a follow
*
* @param cursor cursor value used to parse the list
* @return list of users
*/
public Users getIncomingFollowRequests(long cursor) throws TwitterException {
long[] ids = getUserIDs(USERS_FOLLOW_INCOMING, cursor);
// remove last array entry (cursor) from ID list
return getUsers1(Arrays.copyOf(ids, ids.length - 1));
}
/**
* return a list of the recent 100 users with pending follow requests
*
* @param cursor cursor value used to parse the list
* @return list of users
*/
public Users getOutgoingFollowRequests(long cursor) throws TwitterException {
long[] ids = getUserIDs(USERS_FOLLOW_OUTGOING, cursor);
// remove last array entry (cursor) from ID list
return getUsers1(Arrays.copyOf(ids, ids.length - 1));
}
/**
* get relationship information to an user
*
@ -418,18 +537,6 @@ public class Twitter implements GlobalSettings.SettingsListener {
return getUser1(USER_UNFOLLOW, params);
}
/**
* get block list of the current user
*
* @param cursor cursor value used to parse the list
* @return list of users
*/
public Users getBlockedUsers(long cursor) throws TwitterException {
List<String> params = new ArrayList<>();
params.add("cursor=" + cursor);
return getUsers1(BLOCK_LIST, params);
}
/**
* block specific user
*
@ -472,18 +579,6 @@ public class Twitter implements GlobalSettings.SettingsListener {
return getUser1(USER_UNBLOCK, params);
}
/**
* get mute list of the current user
*
* @param cursor cursor value used to parse the list
* @return list of users
*/
public Users getMutedUsers(long cursor) throws TwitterException {
List<String> params = new ArrayList<>();
params.add("cursor=" + cursor);
return getUsers1(MUTES_LIST, params);
}
/**
* mute specific user
*
@ -522,28 +617,6 @@ public class Twitter implements GlobalSettings.SettingsListener {
return getUser1(USER_UNMUTE, params);
}
/**
* get users retweeting a tweet
*
* @param tweetId ID of the tweet
* @return user list
*/
public Users getRetweetingUsers(long tweetId) throws TwitterException {
String endpoint = TWEET_UNI + tweetId + "/retweeted_by";
return getUsers2(endpoint);
}
/**
* get users liking a tweet
*
* @param tweetId ID of the tweet
* @return user list
*/
public Users getLikingUsers(long tweetId) throws TwitterException {
String endpoint = TWEET_UNI + tweetId + "/liking_users";
return getUsers2(endpoint);
}
/**
* search tweets matching a search string
*
@ -566,33 +639,6 @@ public class Twitter implements GlobalSettings.SettingsListener {
return result;
}
/**
* search for users matching a search string
*
* @param search search string
* @param page page of the search results
* @return list of users
*/
public Users searchUsers(String search, long page) throws TwitterException {
// search endpoint only supports pages parameter
long currentPage = page > 0 ? page : 1;
long nextPage = currentPage + 1;
List<String> params = new ArrayList<>();
params.add("q=" + StringTools.encode(search));
params.add("page=" + currentPage);
Users result = getUsers1(USER_SEARCH, params);
// notice that there are no more results
// if result size is less than the requested size
if (result.size() < settings.getListSize())
nextPage = 0;
if (settings.filterResults())
filterUsers(result);
result.setPrevCursor(currentPage - 1);
result.setNextCursor(nextPage);
return result;
}
/**
* get location trends
*
@ -660,7 +706,7 @@ public class Twitter implements GlobalSettings.SettingsListener {
params.add("since_id=" + minId);
if (maxId > 0)
params.add("max_id=" + maxId);
return getTweets1(SHOW_HOME, params);
return getTweets1(TWEETS_HOME_TIMELINE, params);
}
/**
@ -676,7 +722,7 @@ public class Twitter implements GlobalSettings.SettingsListener {
params.add("since_id=" + minId);
if (maxId > 1)
params.add("max_id=" + maxId);
return getTweets1(SHOW_MENTIONS, params);
return getTweets1(TWEETS_MENTIONS, params);
}
/**
@ -694,7 +740,7 @@ public class Twitter implements GlobalSettings.SettingsListener {
if (maxId > 1)
params.add("max_id=" + maxId);
params.add("user_id=" + userId);
return getTweets1(USER_TIMELINE, params);
return getTweets1(TWEETS_USER, params);
}
/**
@ -712,7 +758,7 @@ public class Twitter implements GlobalSettings.SettingsListener {
if (maxId > 1)
params.add("max_id=" + maxId);
params.add("screen_name=" + StringTools.encode(screen_name));
return getTweets1(USER_TIMELINE, params);
return getTweets1(TWEETS_USER, params);
}
/**
@ -730,7 +776,7 @@ public class Twitter implements GlobalSettings.SettingsListener {
if (maxId > 1)
params.add("max_id=" + maxId);
params.add("user_id=" + userId);
return getTweets1(USER_FAVORITS, params);
return getTweets1(TWEETS_USER_FAVORITS, params);
}
/**
@ -748,7 +794,7 @@ public class Twitter implements GlobalSettings.SettingsListener {
if (maxId > 1)
params.add("max_id=" + maxId);
params.add("screen_name=" + StringTools.encode(screen_name));
return getTweets1(USER_FAVORITS, params);
return getTweets1(TWEETS_USER_FAVORITS, params);
}
/**
@ -811,7 +857,7 @@ public class Twitter implements GlobalSettings.SettingsListener {
public Tweet showTweet(long tweetId) throws TwitterException {
List<String> params = new ArrayList<>();
params.add("id=" + tweetId);
return getTweet1(SHOW_TWEET, params);
return getTweet1(TWEET_LOOKUP, params);
}
/**
@ -1331,34 +1377,29 @@ public class Twitter implements GlobalSettings.SettingsListener {
* @return list of IDs
*/
public List<Long> getIdBlocklist() throws TwitterException {
try {
long cursor = -1;
List<Long> result = new ArrayList<>(100);
// the API returns up to 5000 blocked user IDs
// but for bigger lists, we have to parse the whole list
for (int i = 0; i < 10 && cursor != 0; i++) {
List<String> params = new ArrayList<>();
params.add("cursor=" + cursor);
Response response = get(BLOCK_ID_LIST, params);
if (response.body() != null && response.code() == 200) {
JSONObject json = new JSONObject(response.body().string());
JSONArray idArray = json.getJSONArray("ids");
cursor = Long.parseLong(json.optString("next_cursor_str", "0"));
for (int pos = 0; pos < idArray.length(); pos++) {
result.add(idArray.getLong(pos));
}
} else {
throw new TwitterException(response);
}
// Note: the API returns up to 5000 user IDs
// but for bigger lists, we have to parse the whole list
Set<Long> result = new TreeSet<>();
// add blocked user IDs
long cursor = -1;
for (int i = 0; i < 10 && cursor != 0; i++) {
long[] ids = getUserIDs(IDS_BLOCKED_USERS, cursor);
for (int pos = 0; pos < ids.length - 2; pos++) {
result.add(ids[pos]);
}
return result;
} catch (IOException err) {
throw new TwitterException(err);
} catch (JSONException err) {
throw new TwitterException(err);
} catch (NumberFormatException err) {
throw new TwitterException(err);
cursor = ids[ids.length - 1];
}
// add muted user IDs
cursor = -1;
for (int i = 0; i < 10 && cursor != 0; i++) {
long[] ids = getUserIDs(IDS_MUTED_USERS, cursor);
for (int pos = 0; pos < ids.length - 2; pos++) {
result.add(ids[pos]);
}
cursor = ids[ids.length - 1];
}
return new ArrayList<>(result);
}
/**
@ -1413,7 +1454,7 @@ public class Twitter implements GlobalSettings.SettingsListener {
params.add(TweetV1.INCL_RT_ID);
params.add(TweetV1.INCL_ENTITIES);
Response response;
if (endpoint.equals(SHOW_TWEET)) {
if (endpoint.equals(TWEET_LOOKUP)) {
response = get(endpoint, params);
} else {
response = post(endpoint, params);
@ -1438,6 +1479,59 @@ public class Twitter implements GlobalSettings.SettingsListener {
}
}
/**
* returns an array of user IDs from a given endpoint
*
* @param endpoint Endpoint where to get the user IDs
* @param cursor cursor value to parse the ID pages
* @return an array of user IDs + the list cursor on the last array index
*/
private long[] getUserIDs(String endpoint, long cursor) throws TwitterException {
try {
List<String> params = new ArrayList<>();
params.add("cursor=" + cursor);
Response response = get(endpoint, params);
if (response.body() != null && response.code() == 200) {
JSONObject json = new JSONObject(response.body().string());
JSONArray idArray = json.getJSONArray("ids");
cursor = Long.parseLong(json.optString("next_cursor_str", "0"));
long[] result = new long[idArray.length() + 1];
for (int pos = 0; pos < idArray.length(); pos++) {
result[pos] = idArray.getLong(pos);
}
result[result.length - 1] = cursor;
return result;
} else {
throw new TwitterException(response);
}
} catch (IOException err) {
throw new TwitterException(err);
} catch (JSONException err) {
throw new TwitterException(err);
} catch (NumberFormatException err) {
throw new TwitterException(err);
}
}
/**
* lookup a list of user IDs
*
* @param ids User IDs
* @return a list of users
*/
private Users getUsers1(long[] ids) throws TwitterException {
List<String> params = new ArrayList<>();
if (ids.length > 0) {
StringBuilder idBuf = new StringBuilder("user_id=");
for (long id : ids) {
idBuf.append(id).append("%2C");
}
params.add(idBuf.substring(0,idBuf.length() - 3));
return getUsers1(USERS_LOOKUP, params);
}
return new Users(0L, 0L);
}
/**
* create a list of users using API v 1.1
*
@ -1447,12 +1541,17 @@ public class Twitter implements GlobalSettings.SettingsListener {
*/
private Users getUsers1(String endpoint, List<String> params) throws TwitterException {
try {
params.add("count=" + settings.getListSize());
params.add("skip_status=true");
Response response = get(endpoint, params);
Response response;
if (USERS_LOOKUP.equals(endpoint)) {
response = post(endpoint, params);
} else {
params.add("skip_status=true");
params.add("count=" + settings.getListSize());
response = get(endpoint, params);
}
if (response.body() != null && response.code() == 200) {
String jsonResult = response.body().string();
if (endpoint.equals(USER_SEARCH)) // convert to JSON object
if (!jsonResult.startsWith("{\"users\":")) // convert to users JSON object
jsonResult = "{\"users\":" + jsonResult + '}';
JSONObject json = new JSONObject(jsonResult);
JSONArray array = json.getJSONArray("users");

View File

@ -1,13 +1,13 @@
package org.nuclearfog.twidda.backend.async;
import static org.nuclearfog.twidda.ui.activities.SearchPage.KEY_SEARCH_QUERY;
import static org.nuclearfog.twidda.ui.activities.SearchActivity.KEY_SEARCH_QUERY;
import static org.nuclearfog.twidda.ui.activities.TweetActivity.KEY_TWEET_ID;
import static org.nuclearfog.twidda.ui.activities.TweetActivity.KEY_TWEET_NAME;
import static org.nuclearfog.twidda.ui.activities.TweetEditor.KEY_TWEETPOPUP_TEXT;
import static org.nuclearfog.twidda.ui.activities.UserProfile.KEY_PROFILE_DATA;
import static org.nuclearfog.twidda.ui.activities.UserProfile.KEY_PROFILE_DISABLE_RELOAD;
import static org.nuclearfog.twidda.ui.activities.UserlistActivity.KEY_LIST_ID;
import static org.nuclearfog.twidda.ui.activities.Userlists.KEY_USERLIST_OWNER_NAME;
import static org.nuclearfog.twidda.ui.activities.UserlistsActivity.KEY_USERLIST_OWNER_NAME;
import android.app.Activity;
import android.net.Uri;
@ -19,14 +19,14 @@ import androidx.annotation.NonNull;
import org.nuclearfog.twidda.backend.api.Twitter;
import org.nuclearfog.twidda.backend.api.TwitterException;
import org.nuclearfog.twidda.model.User;
import org.nuclearfog.twidda.ui.activities.DirectMessage;
import org.nuclearfog.twidda.ui.activities.MessageActivity;
import org.nuclearfog.twidda.ui.activities.MainActivity;
import org.nuclearfog.twidda.ui.activities.SearchPage;
import org.nuclearfog.twidda.ui.activities.SearchActivity;
import org.nuclearfog.twidda.ui.activities.TweetActivity;
import org.nuclearfog.twidda.ui.activities.TweetEditor;
import org.nuclearfog.twidda.ui.activities.UserProfile;
import org.nuclearfog.twidda.ui.activities.UserlistActivity;
import org.nuclearfog.twidda.ui.activities.Userlists;
import org.nuclearfog.twidda.ui.activities.UserlistsActivity;
import java.lang.ref.WeakReference;
import java.util.regex.Pattern;
@ -85,7 +85,7 @@ public class LinkLoader extends AsyncTask<Uri, Void, LinkLoader.DataHolder> {
}
// open directmessage page
else if (path.equals("messages")) {
dataHolder = new DataHolder(data, DirectMessage.class);
dataHolder = new DataHolder(data, MessageActivity.class);
}
// open twitter search
else if (path.equals("search")) {
@ -93,7 +93,7 @@ public class LinkLoader extends AsyncTask<Uri, Void, LinkLoader.DataHolder> {
String search = link.getQueryParameter("q");
if (search != null) {
data.putString(KEY_SEARCH_QUERY, search);
dataHolder = new DataHolder(data, SearchPage.class);
dataHolder = new DataHolder(data, SearchActivity.class);
}
}
}
@ -118,7 +118,7 @@ public class LinkLoader extends AsyncTask<Uri, Void, LinkLoader.DataHolder> {
else if (path.startsWith("hashtag/")) {
String search = '#' + path.substring(8);
data.putString(KEY_SEARCH_QUERY, search);
dataHolder = new DataHolder(data, SearchPage.class);
dataHolder = new DataHolder(data, SearchActivity.class);
}
// open an userlist
else if (USERLIST_PATH.matcher(path).matches()) {
@ -147,7 +147,7 @@ public class LinkLoader extends AsyncTask<Uri, Void, LinkLoader.DataHolder> {
// show userlists
else if (USERLISTS_PATH.matcher(path).matches()) {
data.putString(KEY_USERLIST_OWNER_NAME, username);
dataHolder = new DataHolder(data, Userlists.class);
dataHolder = new DataHolder(data, UserlistsActivity.class);
}
}
}

View File

@ -5,7 +5,7 @@ import android.os.AsyncTask;
import org.nuclearfog.twidda.backend.api.Twitter;
import org.nuclearfog.twidda.backend.api.TwitterException;
import org.nuclearfog.twidda.model.Location;
import org.nuclearfog.twidda.ui.activities.AppSettings;
import org.nuclearfog.twidda.ui.activities.SettingsActivity;
import java.lang.ref.WeakReference;
import java.util.List;
@ -14,16 +14,16 @@ import java.util.List;
* Background task to load location information used by twitter such as location names and world ID's
*
* @author nuclearfog
* @see AppSettings
* @see SettingsActivity
*/
public class LocationLoader extends AsyncTask<Void, Void, List<Location>> {
private TwitterException twException;
private WeakReference<AppSettings> weakRef;
private WeakReference<SettingsActivity> weakRef;
private Twitter twitter;
public LocationLoader(AppSettings activity) {
public LocationLoader(SettingsActivity activity) {
super();
weakRef = new WeakReference<>(activity);
twitter = Twitter.get(activity);
@ -43,7 +43,7 @@ public class LocationLoader extends AsyncTask<Void, Void, List<Location>> {
@Override
protected void onPostExecute(List<Location> locations) {
AppSettings activity = weakRef.get();
SettingsActivity activity = weakRef.get();
if (activity != null) {
if (locations != null) {
activity.setLocationData(locations);

View File

@ -9,13 +9,13 @@ import org.nuclearfog.twidda.backend.api.TwitterException;
import org.nuclearfog.twidda.database.AppDatabase;
import org.nuclearfog.twidda.database.FilterDatabase;
import org.nuclearfog.twidda.model.User;
import org.nuclearfog.twidda.ui.activities.UserExclude;
import org.nuclearfog.twidda.ui.activities.UsersActivity;
import java.lang.ref.WeakReference;
import java.util.List;
/**
* Backend of {@link UserExclude}
* Backend of {@link UsersActivity}
* performs user mute or block actions and stores a list of IDs with blocked/muted users
* This list is used to filter search results
*
@ -42,14 +42,14 @@ public class UserExcludeLoader extends AsyncTask<String, Void, Void> {
@Nullable
private TwitterException err;
private WeakReference<UserExclude> weakRef;
private WeakReference<UsersActivity> weakRef;
private FilterDatabase filterDatabase;
private AppDatabase appDatabase;
private Twitter twitter;
private Mode mode;
public UserExcludeLoader(UserExclude activity, Mode mode) {
public UserExcludeLoader(UsersActivity activity, Mode mode) {
super();
twitter = Twitter.get(activity);
appDatabase = new AppDatabase(activity);
@ -87,7 +87,7 @@ public class UserExcludeLoader extends AsyncTask<String, Void, Void> {
@Override
protected void onPostExecute(Void v) {
UserExclude activity = weakRef.get();
UsersActivity activity = weakRef.get();
if (activity != null) {
if (err == null) {
activity.onSuccess(mode);

View File

@ -61,6 +61,10 @@ public class UserLoader extends AsyncTask<Long, Void, Users> {
* load a list of muted users
*/
MUTE,
FOLLOWING_REQ,
FOLLOWER_REQ,
}
@Nullable
@ -121,6 +125,11 @@ public class UserLoader extends AsyncTask<Long, Void, Users> {
case MUTE:
return mTwitter.getMutedUsers(cursor);
case FOLLOWER_REQ:
return mTwitter.getIncomingFollowRequests(cursor);
case FOLLOWING_REQ:
return mTwitter.getOutgoingFollowRequests(cursor);
}
} catch (TwitterException twException) {
this.twException = twException;

View File

@ -119,7 +119,7 @@ public class LoginActivity extends AppCompatActivity implements OnClickListener
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
if (item.getItemId() == R.id.login_setting) {
Intent settings = new Intent(this, AppSettings.class);
Intent settings = new Intent(this, SettingsActivity.class);
startActivity(settings);
} else if (item.getItemId() == R.id.login_select_account) {
Intent accountManager = new Intent(this, AccountActivity.class);
@ -206,7 +206,7 @@ public class LoginActivity extends AppCompatActivity implements OnClickListener
private void connect() {
String link = Twitter.REQUEST_URL + requestToken;
String link = Twitter.AUTHENTICATE + "?oauth_token=";
Intent loginIntent = new Intent(ACTION_VIEW, Uri.parse(link));
try {
startActivity(loginIntent);

View File

@ -1,6 +1,6 @@
package org.nuclearfog.twidda.ui.activities;
import static org.nuclearfog.twidda.ui.activities.SearchPage.KEY_SEARCH_QUERY;
import static org.nuclearfog.twidda.ui.activities.SearchActivity.KEY_SEARCH_QUERY;
import static org.nuclearfog.twidda.ui.activities.UserProfile.KEY_PROFILE_ID;
import android.app.Dialog;
@ -56,7 +56,7 @@ public class MainActivity extends AppCompatActivity implements OnTabSelectedList
private static final int REQUEST_ACCOUNT_CHANGE = 0x345;
/**
* Request code to start {@link AppSettings}
* Request code to start {@link SettingsActivity}
*/
private static final int REQUEST_APP_SETTINGS = 0x54AD;
@ -157,7 +157,7 @@ public class MainActivity extends AppCompatActivity implements OnTabSelectedList
AppStyles.setTheme(root, settings.getBackgroundColor());
AppStyles.setTabIcons(tabLayout, settings, R.array.home_tab_icons);
// check if an account was removed
if (returnCode == AppSettings.RETURN_APP_LOGOUT) {
if (returnCode == SettingsActivity.RETURN_APP_LOGOUT) {
// clear old login fragments
adapter.clear();
pager.setAdapter(adapter);
@ -236,7 +236,7 @@ public class MainActivity extends AppCompatActivity implements OnTabSelectedList
}
// open app settings
else if (item.getItemId() == R.id.action_settings) {
Intent settings = new Intent(this, AppSettings.class);
Intent settings = new Intent(this, SettingsActivity.class);
startActivityForResult(settings, REQUEST_APP_SETTINGS);
}
// theme expanded search view
@ -265,8 +265,8 @@ public class MainActivity extends AppCompatActivity implements OnTabSelectedList
@Override
public boolean onQueryTextSubmit(String s) {
if (s.length() <= SearchPage.SEARCH_STR_MAX_LEN && !s.contains(":") && !s.contains("$")) {
Intent search = new Intent(this, SearchPage.class);
if (s.length() <= SearchActivity.SEARCH_STR_MAX_LEN && !s.contains(":") && !s.contains("$")) {
Intent search = new Intent(this, SearchActivity.class);
search.putExtra(KEY_SEARCH_QUERY, s);
startActivity(search);
} else {

View File

@ -23,7 +23,7 @@ import org.nuclearfog.twidda.ui.fragments.MessageFragment;
*
* @author nuclearfog
*/
public class DirectMessage extends AppCompatActivity {
public class MessageActivity extends AppCompatActivity {
private GlobalSettings settings;

View File

@ -33,7 +33,7 @@ import org.nuclearfog.twidda.database.GlobalSettings;
*
* @author nuclearfog
*/
public class SearchPage extends AppCompatActivity implements OnTabSelectedListener, OnQueryTextListener {
public class SearchActivity extends AppCompatActivity implements OnTabSelectedListener, OnQueryTextListener {
/**
* Key for the search query, required
@ -133,8 +133,8 @@ public class SearchPage extends AppCompatActivity implements OnTabSelectedListen
@Override
public boolean onQueryTextSubmit(String s) {
if (s.length() <= SearchPage.SEARCH_STR_MAX_LEN && !s.contains(":") && !s.contains("$")) {
Intent search = new Intent(this, SearchPage.class);
if (s.length() <= SearchActivity.SEARCH_STR_MAX_LEN && !s.contains(":") && !s.contains("$")) {
Intent search = new Intent(this, SearchActivity.class);
search.putExtra(KEY_SEARCH_QUERY, s);
startActivity(search);
} else {

View File

@ -66,7 +66,7 @@ import java.util.regex.Matcher;
*
* @author nuclearfog
*/
public class AppSettings extends AppCompatActivity implements OnClickListener, OnDismissListener, OnSeekBarChangeListener,
public class SettingsActivity extends AppCompatActivity implements OnClickListener, OnDismissListener, OnSeekBarChangeListener,
OnCheckedChangeListener, OnItemSelectedListener, OnConfirmListener, OnColorChangedListener {
/**

View File

@ -6,13 +6,13 @@ import static android.view.View.OnClickListener;
import static android.view.View.OnLongClickListener;
import static android.view.View.VISIBLE;
import static android.widget.Toast.LENGTH_SHORT;
import static org.nuclearfog.twidda.ui.activities.SearchPage.KEY_SEARCH_QUERY;
import static org.nuclearfog.twidda.ui.activities.SearchActivity.KEY_SEARCH_QUERY;
import static org.nuclearfog.twidda.ui.activities.TweetEditor.KEY_TWEETPOPUP_REPLYID;
import static org.nuclearfog.twidda.ui.activities.TweetEditor.KEY_TWEETPOPUP_TEXT;
import static org.nuclearfog.twidda.ui.activities.UserDetail.KEY_USERDETAIL_ID;
import static org.nuclearfog.twidda.ui.activities.UserDetail.KEY_USERDETAIL_MODE;
import static org.nuclearfog.twidda.ui.activities.UserDetail.USERLIST_FAVORIT;
import static org.nuclearfog.twidda.ui.activities.UserDetail.USERLIST_RETWEETS;
import static org.nuclearfog.twidda.ui.activities.UsersActivity.KEY_USERDETAIL_ID;
import static org.nuclearfog.twidda.ui.activities.UsersActivity.KEY_USERDETAIL_MODE;
import static org.nuclearfog.twidda.ui.activities.UsersActivity.USERLIST_FAVORIT;
import static org.nuclearfog.twidda.ui.activities.UsersActivity.USERLIST_RETWEETS;
import static org.nuclearfog.twidda.ui.fragments.TweetFragment.KEY_FRAG_TWEET_ID;
import static org.nuclearfog.twidda.ui.fragments.TweetFragment.KEY_FRAG_TWEET_MODE;
import static org.nuclearfog.twidda.ui.fragments.TweetFragment.KEY_FRAG_TWEET_SEARCH;
@ -405,14 +405,14 @@ public class TweetActivity extends AppCompatActivity implements OnClickListener,
}
// show user retweeting this tweet
else if (v.getId() == R.id.tweet_retweet) {
Intent userList = new Intent(this, UserDetail.class);
Intent userList = new Intent(this, UsersActivity.class);
userList.putExtra(KEY_USERDETAIL_ID, clickedTweet.getId());
userList.putExtra(KEY_USERDETAIL_MODE, USERLIST_RETWEETS);
startActivity(userList);
}
// show user favoriting this tweet
else if (v.getId() == R.id.tweet_favorite) {
Intent userList = new Intent(this, UserDetail.class);
Intent userList = new Intent(this, UsersActivity.class);
userList.putExtra(KEY_USERDETAIL_ID, clickedTweet.getId());
userList.putExtra(KEY_USERDETAIL_MODE, USERLIST_FAVORIT);
startActivity(userList);
@ -539,7 +539,7 @@ public class TweetActivity extends AppCompatActivity implements OnClickListener,
@Override
public void onTagClick(String tag) {
Intent intent = new Intent(this, SearchPage.class);
Intent intent = new Intent(this, SearchActivity.class);
intent.putExtra(KEY_SEARCH_QUERY, tag);
startActivity(intent);
}

View File

@ -1,128 +0,0 @@
package org.nuclearfog.twidda.ui.activities;
import static org.nuclearfog.twidda.ui.fragments.UserFragment.KEY_FRAG_USER_ID;
import static org.nuclearfog.twidda.ui.fragments.UserFragment.KEY_FRAG_USER_MODE;
import static org.nuclearfog.twidda.ui.fragments.UserFragment.USER_FRAG_FAVORIT;
import static org.nuclearfog.twidda.ui.fragments.UserFragment.USER_FRAG_FOLLOWS;
import static org.nuclearfog.twidda.ui.fragments.UserFragment.USER_FRAG_FRIENDS;
import static org.nuclearfog.twidda.ui.fragments.UserFragment.USER_FRAG_RETWEET;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.ViewGroup;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.FragmentTransaction;
import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.database.GlobalSettings;
import org.nuclearfog.twidda.ui.fragments.UserFragment;
/**
* Activity to show a list of twitter users
*
* @author nuclearfog
*/
public class UserDetail extends AppCompatActivity {
/**
* type of users to get from twitter
* {@link #USERLIST_FRIENDS}, {@link #USERLIST_FOLLOWER}, {@link #USERLIST_RETWEETS}
*/
public static final String KEY_USERDETAIL_MODE = "userlist_mode";
/**
* ID of a userlist, an user or a tweet to get the users from
*/
public static final String KEY_USERDETAIL_ID = "userlist_id";
/**
* friends of an user, requires user ID
*/
public static final int USERLIST_FRIENDS = 0xDF893242;
/**
* follower of an user, requires user ID
*/
public static final int USERLIST_FOLLOWER = 0xA89F5968;
/**
* user retweeting a tweet, requires tweet ID
*/
public static final int USERLIST_RETWEETS = 0x19F582E;
/**
* user favoriting/liking a tweet, requires tweet ID
*/
public static final int USERLIST_FAVORIT = 0x9bcc3f99;
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(AppStyles.setFontScale(newBase));
}
@Override
protected void onCreate(@Nullable Bundle b) {
super.onCreate(b);
setContentView(R.layout.page_fragment);
ViewGroup root = findViewById(R.id.fragment_root);
Toolbar toolbar = findViewById(R.id.fragment_toolbar);
// get parameter
Intent data = getIntent();
int mode = data.getIntExtra(KEY_USERDETAIL_MODE, 0);
long id = data.getLongExtra(KEY_USERDETAIL_ID, -1);
GlobalSettings settings = GlobalSettings.getInstance(this);
Bundle param = new Bundle();
switch (mode) {
case USERLIST_FRIENDS:
// set fragment parameter
param.putLong(KEY_FRAG_USER_ID, id);
param.putInt(KEY_FRAG_USER_MODE, USER_FRAG_FRIENDS);
// set toolbar title
toolbar.setTitle(R.string.userlist_following);
break;
case USERLIST_FOLLOWER:
// set fragment parameter
param.putLong(KEY_FRAG_USER_ID, id);
param.putInt(KEY_FRAG_USER_MODE, USER_FRAG_FOLLOWS);
// set toolbar title
toolbar.setTitle(R.string.userlist_follower);
break;
case USERLIST_RETWEETS:
// set fragment parameter
param.putLong(KEY_FRAG_USER_ID, id);
param.putInt(KEY_FRAG_USER_MODE, USER_FRAG_RETWEET);
// set toolbar title
toolbar.setTitle(R.string.toolbar_userlist_retweet);
break;
case USERLIST_FAVORIT:
// set fragment parameter
param.putLong(KEY_FRAG_USER_ID, id);
param.putInt(KEY_FRAG_USER_MODE, USER_FRAG_FAVORIT);
int title = settings.likeEnabled() ? R.string.toolbar_tweet_liker : R.string.toolbar_tweet_favoriter;
// set toolbar title
toolbar.setTitle(title);
break;
}
// insert fragment into view
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, UserFragment.class, param, "");
fragmentTransaction.commit();
// set toolbar
setSupportActionBar(toolbar);
// style activity
AppStyles.setTheme(root, settings.getBackgroundColor());
}
}

View File

@ -16,16 +16,18 @@ import static org.nuclearfog.twidda.backend.async.UserAction.Action.PROFILE_DB;
import static org.nuclearfog.twidda.backend.async.UserAction.Action.PROFILE_lOAD;
import static org.nuclearfog.twidda.database.GlobalSettings.PROFILE_IMG_HIGH_RES;
import static org.nuclearfog.twidda.ui.activities.MessageEditor.KEY_DM_PREFIX;
import static org.nuclearfog.twidda.ui.activities.SearchPage.KEY_SEARCH_QUERY;
import static org.nuclearfog.twidda.ui.activities.SearchActivity.KEY_SEARCH_QUERY;
import static org.nuclearfog.twidda.ui.activities.TweetActivity.KEY_TWEET_ID;
import static org.nuclearfog.twidda.ui.activities.TweetActivity.KEY_TWEET_NAME;
import static org.nuclearfog.twidda.ui.activities.TweetActivity.LINK_PATTERN;
import static org.nuclearfog.twidda.ui.activities.TweetEditor.KEY_TWEETPOPUP_TEXT;
import static org.nuclearfog.twidda.ui.activities.UserDetail.KEY_USERDETAIL_ID;
import static org.nuclearfog.twidda.ui.activities.UserDetail.KEY_USERDETAIL_MODE;
import static org.nuclearfog.twidda.ui.activities.UserDetail.USERLIST_FOLLOWER;
import static org.nuclearfog.twidda.ui.activities.UserDetail.USERLIST_FRIENDS;
import static org.nuclearfog.twidda.ui.activities.Userlists.KEY_USERLIST_OWNER_ID;
import static org.nuclearfog.twidda.ui.activities.UsersActivity.KEY_USERDETAIL_ID;
import static org.nuclearfog.twidda.ui.activities.UsersActivity.KEY_USERDETAIL_MODE;
import static org.nuclearfog.twidda.ui.activities.UsersActivity.USERLIST_EXCLUDED_USERS;
import static org.nuclearfog.twidda.ui.activities.UsersActivity.USERLIST_FOLLOWER;
import static org.nuclearfog.twidda.ui.activities.UsersActivity.USERLIST_FRIENDS;
import static org.nuclearfog.twidda.ui.activities.UserlistsActivity.KEY_USERLIST_OWNER_ID;
import static org.nuclearfog.twidda.ui.activities.UsersActivity.USERLIST_REQUESTS;
import android.content.ActivityNotFoundException;
import android.content.Context;
@ -295,7 +297,9 @@ public class UserProfile extends AppCompatActivity implements OnClickListener, O
}
if (user.isCurrentUser() || !user.isProtected()) {
MenuItem listItem = m.findItem(R.id.profile_lists);
MenuItem requestItem = m.findItem(R.id.profile_requests);
listItem.setVisible(true);
requestItem.setVisible(true);
}
if (user.isCurrentUser()) {
MenuItem dmIcon = m.findItem(R.id.profile_message);
@ -397,7 +401,7 @@ public class UserProfile extends AppCompatActivity implements OnClickListener, O
else if (item.getItemId() == R.id.profile_message) {
Intent dmPage;
if (user.isCurrentUser()) {
dmPage = new Intent(this, DirectMessage.class);
dmPage = new Intent(this, MessageActivity.class);
} else {
dmPage = new Intent(this, MessageEditor.class);
dmPage.putExtra(KEY_DM_PREFIX, user.getScreenname());
@ -406,14 +410,21 @@ public class UserProfile extends AppCompatActivity implements OnClickListener, O
}
// open users list
else if (item.getItemId() == R.id.profile_lists) {
Intent listPage = new Intent(this, Userlists.class);
Intent listPage = new Intent(this, UserlistsActivity.class);
listPage.putExtra(KEY_USERLIST_OWNER_ID, user.getId());
startActivity(listPage);
}
// open mute/block list
else if (item.getItemId() == R.id.profile_block_mute) {
Intent userExclude = new Intent(this, UserExclude.class);
startActivity(userExclude);
Intent usersIntent = new Intent(this, UsersActivity.class);
usersIntent.putExtra(KEY_USERDETAIL_MODE, USERLIST_EXCLUDED_USERS);
startActivity(usersIntent);
}
// open request list
else if (item.getItemId() == R.id.profile_requests) {
Intent usersIntent = new Intent(this, UsersActivity.class);
usersIntent.putExtra(KEY_USERDETAIL_MODE, USERLIST_REQUESTS);
startActivity(usersIntent);
}
}
return super.onOptionsItemSelected(item);
@ -435,7 +446,7 @@ public class UserProfile extends AppCompatActivity implements OnClickListener, O
@Override
public void onTagClick(String text) {
Intent intent = new Intent(this, SearchPage.class);
Intent intent = new Intent(this, SearchActivity.class);
intent.putExtra(KEY_SEARCH_QUERY, text);
startActivity(intent);
}
@ -482,10 +493,10 @@ public class UserProfile extends AppCompatActivity implements OnClickListener, O
if (v.getId() == R.id.following) {
if (user != null && relation != null) {
if (!user.isProtected() || user.isCurrentUser() || relation.isFollowing()) {
Intent following = new Intent(this, UserDetail.class);
following.putExtra(KEY_USERDETAIL_ID, user.getId());
following.putExtra(KEY_USERDETAIL_MODE, USERLIST_FRIENDS);
startActivity(following);
Intent usersIntent = new Intent(this, UsersActivity.class);
usersIntent.putExtra(KEY_USERDETAIL_ID, user.getId());
usersIntent.putExtra(KEY_USERDETAIL_MODE, USERLIST_FRIENDS);
startActivity(usersIntent);
}
}
}
@ -493,10 +504,10 @@ public class UserProfile extends AppCompatActivity implements OnClickListener, O
else if (v.getId() == R.id.follower) {
if (user != null && relation != null) {
if (!user.isProtected() || user.isCurrentUser() || relation.isFollowing()) {
Intent follower = new Intent(this, UserDetail.class);
follower.putExtra(KEY_USERDETAIL_ID, user.getId());
follower.putExtra(KEY_USERDETAIL_MODE, USERLIST_FOLLOWER);
startActivity(follower);
Intent usersIntent = new Intent(this, UsersActivity.class);
usersIntent.putExtra(KEY_USERDETAIL_ID, user.getId());
usersIntent.putExtra(KEY_USERDETAIL_MODE, USERLIST_FOLLOWER);
startActivity(usersIntent);
}
}
}

View File

@ -21,11 +21,11 @@ import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.database.GlobalSettings;
/**
* Activity to show user lists of a twitter user
* Activity to show userlists of a twitter user
*
* @author nuclearfog
*/
public class Userlists extends AppCompatActivity implements TabLayout.OnTabSelectedListener {
public class UserlistsActivity extends AppCompatActivity implements TabLayout.OnTabSelectedListener {
/**
* Key for the ID the list owner

View File

@ -32,11 +32,49 @@ import org.nuclearfog.twidda.backend.utils.ErrorHandler;
import org.nuclearfog.twidda.database.GlobalSettings;
/**
* Activity to show block and mute list of the current user
* todo
*
* @author nuclearfog
*/
public class UserExclude extends AppCompatActivity implements OnTabSelectedListener, OnQueryTextListener {
public class UsersActivity extends AppCompatActivity implements OnTabSelectedListener, OnQueryTextListener {
/**
* type of users to get from twitter
* {@link #USERLIST_FRIENDS}, {@link #USERLIST_FOLLOWER}, {@link #USERLIST_RETWEETS}
*/
public static final String KEY_USERDETAIL_MODE = "userlist_mode";
/**
* ID of a userlist, an user or a tweet to get the users from
*/
public static final String KEY_USERDETAIL_ID = "userlist_id";
/**
* friends of an user, requires user ID
*/
public static final int USERLIST_FRIENDS = 0xDF893242;
/**
* follower of an user, requires user ID
*/
public static final int USERLIST_FOLLOWER = 0xA89F5968;
/**
* user retweeting a tweet, requires tweet ID
*/
public static final int USERLIST_RETWEETS = 0x19F582E;
/**
* user favoriting/liking a tweet, requires tweet ID
*/
public static final int USERLIST_FAVORIT = 0x9bcc3f99;
/**
* setup list to show excluded (muted, blocked) users
*/
public static final int USERLIST_EXCLUDED_USERS = 0x896a786;
public static final int USERLIST_REQUESTS = 0x0948693;
private GlobalSettings settings;
private UserExcludeLoader userExclTask;
@ -61,42 +99,75 @@ public class UserExclude extends AppCompatActivity implements OnTabSelectedListe
FragmentAdapter adapter = new FragmentAdapter(getSupportFragmentManager());
pager.setAdapter(adapter);
pager.setOffscreenPageLimit(2);
adapter.setupMuteBlockPage();
tablayout.setupWithViewPager(pager);
tablayout.addOnTabSelectedListener(this);
toolbar.setTitle("");
int mode = getIntent().getIntExtra(KEY_USERDETAIL_MODE, 0);
long id = getIntent().getLongExtra(KEY_USERDETAIL_ID, -1);
switch (mode) {
case USERLIST_FRIENDS:
adapter.setupFollowingPage(id);
pager.setOffscreenPageLimit(1);
toolbar.setTitle(R.string.userlist_following);
break;
case USERLIST_FOLLOWER:
adapter.setupFollowerPage(id);
pager.setOffscreenPageLimit(1);
toolbar.setTitle(R.string.userlist_follower);
break;
case USERLIST_RETWEETS:
adapter.setupRetweeterPage(id);
pager.setOffscreenPageLimit(1);
toolbar.setTitle(R.string.toolbar_userlist_retweet);
break;
case USERLIST_FAVORIT:
int title = settings.likeEnabled() ? R.string.toolbar_tweet_liker : R.string.toolbar_tweet_favoriter;
adapter.setFavoriterPage(id);
pager.setOffscreenPageLimit(1);
toolbar.setTitle(title);
break;
case USERLIST_EXCLUDED_USERS:
adapter.setupMuteBlockPage();
pager.setOffscreenPageLimit(2);
toolbar.setTitle("");
break;
case USERLIST_REQUESTS:
adapter.setupFollowRequestPage();
pager.setOffscreenPageLimit(2);
toolbar.setTitle("");
break;
}
setSupportActionBar(toolbar);
settings = GlobalSettings.getInstance(this);
AppStyles.setTheme(root, settings.getBackgroundColor());
AppStyles.setTabIcons(tablayout, settings, R.array.user_exclude_icons);
}
@Override
public boolean onCreateOptionsMenu(Menu m) {
getMenuInflater().inflate(R.menu.excludelist, m);
MenuItem search = m.findItem(R.id.menu_exclude_user);
SearchView searchView = (SearchView) search.getActionView();
searchView.setOnQueryTextListener(this);
AppStyles.setTheme(searchView, Color.TRANSPARENT);
AppStyles.setMenuIconColor(m, settings.getIconColor());
AppStyles.setOverflowIcon(toolbar, settings.getIconColor());
return super.onCreateOptionsMenu(m);
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
if (item.getItemId() == R.id.menu_exclude_refresh) {
if (userExclTask == null || userExclTask.getStatus() != RUNNING) {
Toast.makeText(this, R.string.info_refreshing_exclude_list, Toast.LENGTH_SHORT).show();
userExclTask = new UserExcludeLoader(this, REFRESH);
userExclTask.execute();
}
}
return super.onOptionsItemSelected(item);
int mode = getIntent().getIntExtra(KEY_USERDETAIL_MODE, 0);
if (mode == USERLIST_EXCLUDED_USERS) {
getMenuInflater().inflate(R.menu.excludelist, m);
MenuItem search = m.findItem(R.id.menu_exclude_user);
SearchView searchView = (SearchView) search.getActionView();
searchView.setOnQueryTextListener(this);
AppStyles.setTheme(searchView, Color.TRANSPARENT);
AppStyles.setMenuIconColor(m, settings.getIconColor());
AppStyles.setOverflowIcon(toolbar, settings.getIconColor());
return super.onCreateOptionsMenu(m);
}// todo add icons
return false;
}
@ -114,6 +185,19 @@ public class UserExclude extends AppCompatActivity implements OnTabSelectedListe
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
if (item.getItemId() == R.id.menu_exclude_refresh) {
if (userExclTask == null || userExclTask.getStatus() != RUNNING) {
Toast.makeText(this, R.string.info_refreshing_exclude_list, Toast.LENGTH_SHORT).show();
userExclTask = new UserExcludeLoader(this, REFRESH);
userExclTask.execute();
}
}
return super.onOptionsItemSelected(item);
}
@Override
public void onTabSelected(Tab tab) {
// reset menu

View File

@ -3,7 +3,7 @@ package org.nuclearfog.twidda.ui.fragments;
import static android.os.AsyncTask.Status.RUNNING;
import static android.widget.Toast.LENGTH_SHORT;
import static org.nuclearfog.twidda.ui.activities.MessageEditor.KEY_DM_PREFIX;
import static org.nuclearfog.twidda.ui.activities.SearchPage.KEY_SEARCH_QUERY;
import static org.nuclearfog.twidda.ui.activities.SearchActivity.KEY_SEARCH_QUERY;
import static org.nuclearfog.twidda.ui.activities.TweetActivity.KEY_TWEET_ID;
import static org.nuclearfog.twidda.ui.activities.TweetActivity.KEY_TWEET_NAME;
import static org.nuclearfog.twidda.ui.activities.TweetActivity.LINK_PATTERN;
@ -28,7 +28,7 @@ import org.nuclearfog.twidda.backend.utils.ErrorHandler;
import org.nuclearfog.twidda.model.DirectMessage;
import org.nuclearfog.twidda.ui.activities.ImageViewer;
import org.nuclearfog.twidda.ui.activities.MessageEditor;
import org.nuclearfog.twidda.ui.activities.SearchPage;
import org.nuclearfog.twidda.ui.activities.SearchActivity;
import org.nuclearfog.twidda.ui.activities.TweetActivity;
import org.nuclearfog.twidda.ui.activities.UserProfile;
import org.nuclearfog.twidda.ui.dialogs.ConfirmDialog;
@ -96,7 +96,7 @@ public class MessageFragment extends ListFragment implements OnMessageClickListe
@Override
public void onTagClick(String tag) {
if (!isRefreshing()) {
Intent intent = new Intent(requireContext(), SearchPage.class);
Intent intent = new Intent(requireContext(), SearchActivity.class);
intent.putExtra(KEY_SEARCH_QUERY, tag);
startActivity(intent);
}

View File

@ -1,7 +1,7 @@
package org.nuclearfog.twidda.ui.fragments;
import static android.os.AsyncTask.Status.RUNNING;
import static org.nuclearfog.twidda.ui.activities.SearchPage.KEY_SEARCH_QUERY;
import static org.nuclearfog.twidda.ui.activities.SearchActivity.KEY_SEARCH_QUERY;
import android.content.Intent;
import android.os.Bundle;
@ -15,7 +15,7 @@ import org.nuclearfog.twidda.adapter.TrendAdapter.TrendClickListener;
import org.nuclearfog.twidda.backend.async.TrendLoader;
import org.nuclearfog.twidda.backend.utils.ErrorHandler;
import org.nuclearfog.twidda.model.Trend;
import org.nuclearfog.twidda.ui.activities.SearchPage;
import org.nuclearfog.twidda.ui.activities.SearchActivity;
import java.util.List;
@ -76,7 +76,7 @@ public class TrendFragment extends ListFragment implements TrendClickListener {
@Override
public void onTrendClick(Trend trend) {
if (!isRefreshing()) {
Intent intent = new Intent(requireContext(), SearchPage.class);
Intent intent = new Intent(requireContext(), SearchActivity.class);
String name = trend.getName();
if (!name.startsWith("#") && !name.startsWith("\"") && !name.endsWith("\""))
name = "\"" + name + "\"";

View File

@ -50,7 +50,7 @@ public class UserFragment extends ListFragment implements UserClickListener,
/**
* key to define user, tweet or list ID
*/
public static final String KEY_FRAG_USER_ID = "user_id";
public static final String KEY_FRAG_USER_ID_ALL = "user_id_all";
/**
* key to enable function to remove users from list
@ -102,6 +102,16 @@ public class UserFragment extends ListFragment implements UserClickListener,
*/
public static final int USER_FRAG_MUTES = 0x5246DC35;
/**
* configuration to show outgoing follow requests
*/
public static final int USER_FRAG_FOLLOWING_REQUEST = 0x89e5255a;
/**
* configuration to show users requesting a follow
*/
public static final int USER_FRAG_FOLLOWER_REQUEST = 0x72544f17;
/**
* Request code to update user information
*/
@ -126,7 +136,7 @@ public class UserFragment extends ListFragment implements UserClickListener,
Bundle param = getArguments();
if (param != null) {
mode = param.getInt(KEY_FRAG_USER_MODE, 0);
id = param.getLong(KEY_FRAG_USER_ID, 0);
id = param.getLong(KEY_FRAG_USER_ID_ALL, 0);
search = param.getString(KEY_FRAG_USER_SEARCH, "");
delUser = param.getBoolean(KEY_FRAG_DEL_USER, false);
}
@ -312,6 +322,16 @@ public class UserFragment extends ListFragment implements UserClickListener,
userTask = new UserLoader(this, Type.MUTE, id, search);
userTask.execute(cursor);
break;
case USER_FRAG_FOLLOWER_REQUEST:
userTask = new UserLoader(this, Type.FOLLOWER_REQ, id, search);
userTask.execute(cursor);
break;
case USER_FRAG_FOLLOWING_REQUEST:
userTask = new UserLoader(this, Type.FOLLOWING_REQ, id, search);
userTask.execute(cursor);
break;
}
if (cursor == NO_CURSOR) {
setRefresh(true);

View File

@ -6,7 +6,7 @@
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.activities.Userlists">
tools:context=".ui.activities.UserlistsActivity">
<androidx.appcompat.widget.Toolbar
android:id="@+id/list_toolbar"

View File

@ -6,7 +6,7 @@
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.activities.SearchPage">
tools:context=".ui.activities.SearchActivity">
<androidx.appcompat.widget.Toolbar
android:id="@+id/search_toolbar"

View File

@ -8,7 +8,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
tools:context=".ui.activities.AppSettings">
tools:context=".ui.activities.SettingsActivity">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar_setting"

View File

@ -6,7 +6,7 @@
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.activities.UserExclude">
tools:context=".ui.activities.UsersActivity">
<androidx.appcompat.widget.Toolbar
android:id="@+id/userexclude_toolbar"

View File

@ -31,6 +31,10 @@
android:id="@+id/profile_lists"
android:visible="false"
android:title="@string/menu_goto_lists" />
<item
android:id="@+id/profile_requests"
android:visible="false"
android:title="@string/menu_follow_requests" />
<item
android:id="@+id/profile_block_mute"
android:visible="false"

View File

@ -119,6 +119,7 @@
<string name="menu_tweet_unhide">unhide</string>
<string name="menu_tweet_open_browser">open in browser</string>
<string name="menu_mute_user">mute</string>
<string name="menu_follow_requests">requests</string>
<string name="menu_edit_profile">edit profile</string>
<string name="menu_edit_save">save</string>
<string name="menu_add_user">add user to list</string>