mirror of
https://github.com/nuclearfog/Shitter.git
synced 2025-01-01 04:17:21 +01:00
added user exclude database, added search filtering, bug fix
Signed-off-by: nuclearfog <hatespirit666@gmail.com>
This commit is contained in:
parent
90bfa02f74
commit
26077be39a
@ -1,5 +1,17 @@
|
||||
package org.nuclearfog.twidda.activity;
|
||||
|
||||
import static android.os.AsyncTask.Status.RUNNING;
|
||||
import static org.nuclearfog.twidda.activity.ListEditor.KEY_LIST_EDITOR_DATA;
|
||||
import static org.nuclearfog.twidda.backend.ListAction.Action.DELETE;
|
||||
import static org.nuclearfog.twidda.backend.ListAction.Action.FOLLOW;
|
||||
import static org.nuclearfog.twidda.backend.ListAction.Action.LOAD;
|
||||
import static org.nuclearfog.twidda.backend.ListAction.Action.UNFOLLOW;
|
||||
import static org.nuclearfog.twidda.backend.ListManager.Action.ADD_USER;
|
||||
import static org.nuclearfog.twidda.fragment.UserListFragment.RESULT_REMOVED_LIST_ID;
|
||||
import static org.nuclearfog.twidda.fragment.UserListFragment.RESULT_UPDATE_LIST;
|
||||
import static org.nuclearfog.twidda.fragment.UserListFragment.RETURN_LIST_REMOVED;
|
||||
import static org.nuclearfog.twidda.fragment.UserListFragment.RETURN_LIST_UPDATED;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
@ -37,18 +49,6 @@ import org.nuclearfog.twidda.dialog.ConfirmDialog.OnConfirmListener;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static android.os.AsyncTask.Status.RUNNING;
|
||||
import static org.nuclearfog.twidda.activity.ListEditor.KEY_LIST_EDITOR_DATA;
|
||||
import static org.nuclearfog.twidda.backend.ListAction.Action.DELETE;
|
||||
import static org.nuclearfog.twidda.backend.ListAction.Action.FOLLOW;
|
||||
import static org.nuclearfog.twidda.backend.ListAction.Action.LOAD;
|
||||
import static org.nuclearfog.twidda.backend.ListAction.Action.UNFOLLOW;
|
||||
import static org.nuclearfog.twidda.backend.ListManager.Action.ADD_USER;
|
||||
import static org.nuclearfog.twidda.fragment.UserListFragment.RESULT_REMOVED_LIST_ID;
|
||||
import static org.nuclearfog.twidda.fragment.UserListFragment.RESULT_UPDATE_LIST;
|
||||
import static org.nuclearfog.twidda.fragment.UserListFragment.RETURN_LIST_REMOVED;
|
||||
import static org.nuclearfog.twidda.fragment.UserListFragment.RETURN_LIST_UPDATED;
|
||||
|
||||
/**
|
||||
* Activity to show an user list, members and tweets
|
||||
*
|
||||
@ -312,6 +312,7 @@ public class ListDetail extends AppCompatActivity implements OnTabSelectedListen
|
||||
info = '@' + info;
|
||||
info += getString(R.string.info_user_added_to_list);
|
||||
Toast.makeText(this, info, Toast.LENGTH_SHORT).show();
|
||||
invalidateOptionsMenu();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
package org.nuclearfog.twidda.activity;
|
||||
|
||||
import static org.nuclearfog.twidda.activity.TweetEditor.KEY_TWEETPOPUP_TEXT;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
@ -25,8 +27,6 @@ import org.nuclearfog.twidda.adapter.FragmentAdapter;
|
||||
import org.nuclearfog.twidda.backend.utils.AppStyles;
|
||||
import org.nuclearfog.twidda.database.GlobalSettings;
|
||||
|
||||
import static org.nuclearfog.twidda.activity.TweetEditor.KEY_TWEETPOPUP_TEXT;
|
||||
|
||||
/**
|
||||
* Twitter search Activity
|
||||
*
|
||||
@ -88,7 +88,9 @@ public class SearchPage extends AppCompatActivity implements OnTabSelectedListen
|
||||
getMenuInflater().inflate(R.menu.search, m);
|
||||
AppStyles.setMenuIconColor(m, settings.getIconColor());
|
||||
MenuItem searchItem = m.findItem(R.id.new_search);
|
||||
MenuItem searchFilter = m.findItem(R.id.search_filter);
|
||||
SearchView searchView = (SearchView) searchItem.getActionView();
|
||||
searchFilter.setChecked(settings.filterResults());
|
||||
AppStyles.setTheme(settings, searchView);
|
||||
searchView.setQueryHint(search);
|
||||
searchView.setOnQueryTextListener(this);
|
||||
@ -110,6 +112,12 @@ public class SearchPage extends AppCompatActivity implements OnTabSelectedListen
|
||||
SearchView searchView = (SearchView) item.getActionView();
|
||||
AppStyles.setTheme(settings, searchView, Color.TRANSPARENT);
|
||||
}
|
||||
// enable/disable search filter
|
||||
else if (item.getItemId() == R.id.search_filter) {
|
||||
boolean enable = !item.isChecked();
|
||||
settings.setFilterResults(enable);
|
||||
item.setChecked(enable);
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,19 @@
|
||||
package org.nuclearfog.twidda.activity;
|
||||
|
||||
import static org.nuclearfog.twidda.backend.UserExcludeLoader.Mode.BLOCK_USER;
|
||||
import static org.nuclearfog.twidda.backend.UserExcludeLoader.Mode.MUTE_USER;
|
||||
import static org.nuclearfog.twidda.backend.UserExcludeLoader.Mode.REFRESH;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.SearchView;
|
||||
import androidx.appcompat.widget.SearchView.OnQueryTextListener;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
@ -13,13 +23,24 @@ import com.google.android.material.tabs.TabLayout.Tab;
|
||||
|
||||
import org.nuclearfog.twidda.R;
|
||||
import org.nuclearfog.twidda.adapter.FragmentAdapter;
|
||||
import org.nuclearfog.twidda.backend.UserExcludeLoader;
|
||||
import org.nuclearfog.twidda.backend.engine.EngineException;
|
||||
import org.nuclearfog.twidda.backend.utils.AppStyles;
|
||||
import org.nuclearfog.twidda.backend.utils.ErrorHandler;
|
||||
import org.nuclearfog.twidda.database.GlobalSettings;
|
||||
|
||||
/**
|
||||
* Activity to show block and mute list of the current user
|
||||
*
|
||||
* @author nuclearfog
|
||||
*/
|
||||
public class UserExclude extends AppCompatActivity implements OnTabSelectedListener {
|
||||
public class UserExclude extends AppCompatActivity implements OnTabSelectedListener, OnQueryTextListener {
|
||||
|
||||
private GlobalSettings settings;
|
||||
private UserExcludeLoader userExclTask;
|
||||
|
||||
private Toolbar toolbar;
|
||||
private TabLayout tablayout;
|
||||
|
||||
|
||||
@Override
|
||||
@ -27,12 +48,10 @@ public class UserExclude extends AppCompatActivity implements OnTabSelectedListe
|
||||
super.onCreate(savedInst);
|
||||
setContentView(R.layout.page_user_exclude);
|
||||
View root = findViewById(R.id.userexclude_root);
|
||||
Toolbar toolbar = findViewById(R.id.userexclude_toolbar);
|
||||
TabLayout tablayout = findViewById(R.id.userexclude_tab);
|
||||
toolbar = findViewById(R.id.userexclude_toolbar);
|
||||
tablayout = findViewById(R.id.userexclude_tab);
|
||||
ViewPager pager = findViewById(R.id.userexclude_pager);
|
||||
|
||||
GlobalSettings settings = GlobalSettings.getInstance(this);
|
||||
|
||||
FragmentAdapter adapter = new FragmentAdapter(getSupportFragmentManager());
|
||||
pager.setAdapter(adapter);
|
||||
pager.setOffscreenPageLimit(2);
|
||||
@ -40,30 +59,115 @@ public class UserExclude extends AppCompatActivity implements OnTabSelectedListe
|
||||
tablayout.setupWithViewPager(pager);
|
||||
tablayout.addOnTabSelectedListener(this);
|
||||
|
||||
toolbar.setTitle("");
|
||||
setSupportActionBar(toolbar);
|
||||
settings = GlobalSettings.getInstance(this);
|
||||
AppStyles.setTheme(settings, root);
|
||||
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.setMenuIconColor(m, settings.getIconColor());
|
||||
AppStyles.setOverflowIcon(toolbar, settings.getIconColor());
|
||||
return super.onCreateOptionsMenu(m);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(Menu m) {
|
||||
SearchView searchView = (SearchView) m.findItem(R.id.menu_exclude_user).getActionView();
|
||||
if (tablayout.getSelectedTabPosition() == 0) {
|
||||
String hint = getString(R.string.menu_hint_mute_user);
|
||||
searchView.setQueryHint(hint);
|
||||
} else if (tablayout.getSelectedTabPosition() == 1) {
|
||||
String hint = getString(R.string.menu_hint_block_user);
|
||||
searchView.setQueryHint(hint);
|
||||
}
|
||||
return super.onPrepareOptionsMenu(m);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
if (userExclTask == null) {
|
||||
userExclTask = new UserExcludeLoader(this, "");
|
||||
userExclTask.execute(REFRESH);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onTabSelected(Tab tab) {
|
||||
|
||||
invalidateOptionsMenu();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onTabUnselected(Tab tab) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onTabReselected(Tab tab) {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onQueryTextSubmit(String query) {
|
||||
if (userExclTask == null || userExclTask.getStatus() != AsyncTask.Status.RUNNING) {
|
||||
userExclTask = new UserExcludeLoader(this, query);
|
||||
if (tablayout.getSelectedTabPosition() == 0) {
|
||||
userExclTask.execute(MUTE_USER);
|
||||
return true;
|
||||
}
|
||||
if (tablayout.getSelectedTabPosition() == 1) {
|
||||
userExclTask.execute(BLOCK_USER);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onQueryTextChange(String newText) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* called from {@link UserExcludeLoader} if task finished successfully
|
||||
*/
|
||||
public void onSuccess(UserExcludeLoader.Mode mode) {
|
||||
switch (mode) {
|
||||
case MUTE_USER:
|
||||
Toast.makeText(this, R.string.info_user_muted, Toast.LENGTH_SHORT).show();
|
||||
invalidateOptionsMenu();
|
||||
break;
|
||||
|
||||
case BLOCK_USER:
|
||||
Toast.makeText(this, R.string.info_user_blocked, Toast.LENGTH_SHORT).show();
|
||||
invalidateOptionsMenu();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* called from {@link UserExcludeLoader} if an error occurs
|
||||
*/
|
||||
public void onError(EngineException err) {
|
||||
ErrorHandler.handleFailure(this, err);
|
||||
}
|
||||
}
|
@ -8,6 +8,7 @@ import org.nuclearfog.twidda.backend.engine.TwitterEngine;
|
||||
import org.nuclearfog.twidda.backend.model.Relation;
|
||||
import org.nuclearfog.twidda.backend.model.User;
|
||||
import org.nuclearfog.twidda.database.AppDatabase;
|
||||
import org.nuclearfog.twidda.database.ExcludeDatabase;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
@ -60,6 +61,7 @@ public class UserAction extends AsyncTask<UserAction.Action, User, Relation> {
|
||||
private EngineException twException;
|
||||
private WeakReference<UserProfile> callback;
|
||||
private TwitterEngine mTwitter;
|
||||
private ExcludeDatabase excludeDb;
|
||||
private AppDatabase db;
|
||||
private long userId;
|
||||
|
||||
@ -71,6 +73,7 @@ public class UserAction extends AsyncTask<UserAction.Action, User, Relation> {
|
||||
super();
|
||||
this.callback = new WeakReference<>(callback);
|
||||
mTwitter = TwitterEngine.getInstance(callback);
|
||||
excludeDb = ExcludeDatabase.getInstance(callback);
|
||||
db = new AppDatabase(callback);
|
||||
this.userId = userId;
|
||||
}
|
||||
@ -117,24 +120,28 @@ public class UserAction extends AsyncTask<UserAction.Action, User, Relation> {
|
||||
user = mTwitter.blockUser(userId);
|
||||
publishProgress(user);
|
||||
db.muteUser(userId, true);
|
||||
excludeDb.addUser(userId);
|
||||
break;
|
||||
|
||||
case ACTION_UNBLOCK:
|
||||
user = mTwitter.unblockUser(userId);
|
||||
publishProgress(user);
|
||||
db.muteUser(userId, false);
|
||||
excludeDb.removeUser(userId);
|
||||
break;
|
||||
|
||||
case ACTION_MUTE:
|
||||
user = mTwitter.muteUser(userId);
|
||||
publishProgress(user);
|
||||
db.muteUser(userId, true);
|
||||
excludeDb.addUser(userId);
|
||||
break;
|
||||
|
||||
case ACTION_UNMUTE:
|
||||
user = mTwitter.unmuteUser(userId);
|
||||
publishProgress(user);
|
||||
db.muteUser(userId, false);
|
||||
excludeDb.removeUser(userId);
|
||||
break;
|
||||
}
|
||||
return mTwitter.getConnection(userId);
|
||||
|
@ -0,0 +1,81 @@
|
||||
package org.nuclearfog.twidda.backend;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.nuclearfog.twidda.activity.UserExclude;
|
||||
import org.nuclearfog.twidda.backend.engine.EngineException;
|
||||
import org.nuclearfog.twidda.backend.engine.TwitterEngine;
|
||||
import org.nuclearfog.twidda.database.ExcludeDatabase;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Backend of {@link UserExclude}
|
||||
* performs user mute or block actions and exports block list to database
|
||||
*
|
||||
* @author nuclearfog
|
||||
*/
|
||||
public class UserExcludeLoader extends AsyncTask<UserExcludeLoader.Mode, Void, UserExcludeLoader.Mode> {
|
||||
|
||||
public enum Mode {
|
||||
REFRESH,
|
||||
MUTE_USER,
|
||||
BLOCK_USER
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private EngineException err;
|
||||
private WeakReference<UserExclude> callback;
|
||||
private ExcludeDatabase excludeDatabase;
|
||||
private TwitterEngine mTwitter;
|
||||
private String name;
|
||||
|
||||
|
||||
public UserExcludeLoader(UserExclude callback, String name) {
|
||||
super();
|
||||
mTwitter = TwitterEngine.getInstance(callback);
|
||||
excludeDatabase = ExcludeDatabase.getInstance(callback);
|
||||
this.callback = new WeakReference<>(callback);
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Mode doInBackground(Mode... mode) {
|
||||
try {
|
||||
switch (mode[0]) {
|
||||
case REFRESH:
|
||||
List<Long> ids = mTwitter.getExcludedUserIDs();
|
||||
excludeDatabase.setExcludeList(ids);
|
||||
break;
|
||||
|
||||
case MUTE_USER:
|
||||
mTwitter.muteUser(name);
|
||||
break;
|
||||
|
||||
case BLOCK_USER:
|
||||
mTwitter.blockUser(name);
|
||||
break;
|
||||
}
|
||||
} catch (EngineException err) {
|
||||
this.err = err;
|
||||
}
|
||||
return mode[0];
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Mode mode) {
|
||||
UserExclude activity = callback.get();
|
||||
if (activity != null) {
|
||||
if (err == null) {
|
||||
activity.onSuccess(mode);
|
||||
} else {
|
||||
activity.onError(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -20,6 +20,7 @@ import org.nuclearfog.twidda.backend.model.Tweet;
|
||||
import org.nuclearfog.twidda.backend.model.TwitterList;
|
||||
import org.nuclearfog.twidda.backend.model.User;
|
||||
import org.nuclearfog.twidda.database.AccountDatabase;
|
||||
import org.nuclearfog.twidda.database.ExcludeDatabase;
|
||||
import org.nuclearfog.twidda.database.GlobalSettings;
|
||||
|
||||
import java.io.File;
|
||||
@ -32,6 +33,8 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import io.michaelrocks.paranoid.Obfuscate;
|
||||
import twitter4j.DirectMessage;
|
||||
@ -67,6 +70,7 @@ public class TwitterEngine {
|
||||
private RequestToken reqToken;
|
||||
private GlobalSettings settings;
|
||||
private AccountDatabase accountDB;
|
||||
private ExcludeDatabase excludeDB;
|
||||
private Twitter twitter;
|
||||
|
||||
private boolean isInitialized = false;
|
||||
@ -121,6 +125,7 @@ public class TwitterEngine {
|
||||
// initialize database and settings
|
||||
mTwitter.settings = GlobalSettings.getInstance(context);
|
||||
mTwitter.accountDB = AccountDatabase.getInstance(context);
|
||||
mTwitter.excludeDB = ExcludeDatabase.getInstance(context);
|
||||
// check if already logged in
|
||||
if (mTwitter.settings.isLoggedIn()) {
|
||||
// init login access
|
||||
@ -259,6 +264,8 @@ public class TwitterEngine {
|
||||
q.setMaxId(maxId - 1);
|
||||
QueryResult result = twitter.search(q);
|
||||
List<Status> results = result.getTweets();
|
||||
if (settings.filterResults())
|
||||
return convertStatusListFiltered(results);
|
||||
return convertStatusList(results);
|
||||
} catch (Exception err) {
|
||||
throw new EngineException(err);
|
||||
@ -312,14 +319,20 @@ public class TwitterEngine {
|
||||
*/
|
||||
public UserList searchUsers(String search, long cursor) throws EngineException {
|
||||
try {
|
||||
List<User> users;
|
||||
int currentPage = 1;
|
||||
if (cursor > 0)
|
||||
currentPage = (int) cursor;
|
||||
long prevPage = currentPage - 1;
|
||||
long nextPage = currentPage + 1;
|
||||
List<User> users = convertUserList(twitter.searchUsers(search, currentPage));
|
||||
if (users.size() < 20)
|
||||
if (settings.filterResults()) {
|
||||
users = convertUserListFiltered(twitter.searchUsers(search, currentPage));
|
||||
} else {
|
||||
users = convertUserList(twitter.searchUsers(search, currentPage));
|
||||
}
|
||||
if (users.size() < 20) {
|
||||
nextPage = 0;
|
||||
}
|
||||
UserList result = new UserList(prevPage, nextPage);
|
||||
result.addAll(users);
|
||||
return result;
|
||||
@ -483,6 +496,8 @@ public class TwitterEngine {
|
||||
*/
|
||||
public void blockUser(String name) throws EngineException {
|
||||
try {
|
||||
if (!name.startsWith("@"))
|
||||
name = '@' + name;
|
||||
twitter.createBlock(name);
|
||||
} catch (Exception err) {
|
||||
throw new EngineException(err);
|
||||
@ -527,6 +542,8 @@ public class TwitterEngine {
|
||||
*/
|
||||
public void muteUser(String name) throws EngineException {
|
||||
try {
|
||||
if (!name.startsWith("@"))
|
||||
name = '@' + name;
|
||||
twitter.createMute(name);
|
||||
} catch (Exception err) {
|
||||
throw new EngineException(err);
|
||||
@ -627,6 +644,29 @@ public class TwitterEngine {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get a list of blocked/muted user IDs
|
||||
*
|
||||
* @return list of user IDs
|
||||
* @throws EngineException if twitter service is unavailable
|
||||
*/
|
||||
public List<Long> getExcludedUserIDs() throws EngineException {
|
||||
try {
|
||||
IDs[] ids = new IDs[2];
|
||||
ids[0] = twitter.getBlocksIDs();
|
||||
ids[1] = twitter.getBlocksIDs();
|
||||
Set<Long> idSet = new TreeSet<>();
|
||||
for (IDs id : ids) {
|
||||
for (long userId : id.getIDs()) {
|
||||
idSet.add(userId);
|
||||
}
|
||||
}
|
||||
return new ArrayList<>(idSet);
|
||||
} catch (TwitterException err) {
|
||||
throw new EngineException(err);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* send tweet
|
||||
*
|
||||
@ -695,6 +735,8 @@ public class TwitterEngine {
|
||||
answers.add(reply);
|
||||
}
|
||||
}
|
||||
if (settings.filterResults())
|
||||
return convertStatusListFiltered(answers);
|
||||
return convertStatusList(answers);
|
||||
} catch (Exception err) {
|
||||
throw new EngineException(err);
|
||||
@ -1213,17 +1255,35 @@ public class TwitterEngine {
|
||||
}
|
||||
|
||||
/**
|
||||
* convert #twitter4j.User to User List
|
||||
* convert {@link twitter4j.User} to User List
|
||||
*
|
||||
* @param users Twitter4J user List
|
||||
* @return User
|
||||
*/
|
||||
private List<User> convertUserList(List<twitter4j.User> users) throws TwitterException {
|
||||
long id = twitter.getId();
|
||||
ArrayList<User> result = new ArrayList<>();
|
||||
result.ensureCapacity(users.size());
|
||||
for (twitter4j.User user : users) {
|
||||
User item = new User(user, twitter.getId());
|
||||
result.add(item);
|
||||
result.add(new User(user, id));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* convert {@link twitter4j.User} to User List and filter excluded users
|
||||
*
|
||||
* @param users Twitter4J user List
|
||||
* @return User
|
||||
*/
|
||||
private List<User> convertUserListFiltered(List<twitter4j.User> users) throws TwitterException {
|
||||
long id = twitter.getId();
|
||||
Set<Long> exclude = excludeDB.getExcludeSet();
|
||||
List<User> result = new LinkedList<>();
|
||||
for (twitter4j.User user : users) {
|
||||
if (!exclude.contains(user.getId())) {
|
||||
result.add(new User(user, id));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -1246,7 +1306,7 @@ public class TwitterEngine {
|
||||
}
|
||||
|
||||
/**
|
||||
* convert #twitter4j.Status to Tweet List
|
||||
* convert {@link twitter4j.Status} to Tweet List
|
||||
*
|
||||
* @param statuses Twitter4J status List
|
||||
* @return TwitterStatus
|
||||
@ -1254,8 +1314,27 @@ public class TwitterEngine {
|
||||
private List<Tweet> convertStatusList(List<Status> statuses) throws TwitterException {
|
||||
ArrayList<Tweet> result = new ArrayList<>();
|
||||
result.ensureCapacity(statuses.size());
|
||||
long id = twitter.getId();
|
||||
for (Status status : statuses)
|
||||
result.add(new Tweet(status, twitter.getId()));
|
||||
result.add(new Tweet(status, id));
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* convert {@link twitter4j.Status} to Tweet List and filter tweet from excluded users
|
||||
*
|
||||
* @param statuses Twitter4J status List
|
||||
* @return TwitterStatus
|
||||
*/
|
||||
private List<Tweet> convertStatusListFiltered(List<Status> statuses) throws TwitterException {
|
||||
List<Tweet> result = new LinkedList<>();
|
||||
long id = twitter.getId();
|
||||
Set<Long> exclude = excludeDB.getExcludeSet();
|
||||
for (Status status : statuses) {
|
||||
if (!exclude.contains(status.getUser().getId())) {
|
||||
result.add(new Tweet(status, id));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
package org.nuclearfog.twidda.database;
|
||||
|
||||
import static android.content.Context.MODE_PRIVATE;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
|
||||
@ -7,8 +9,6 @@ import androidx.annotation.NonNull;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import static android.content.Context.MODE_PRIVATE;
|
||||
|
||||
/**
|
||||
* This class creates and manages SQLite table versions
|
||||
*
|
||||
@ -133,6 +133,14 @@ public class DatabaseAdapter {
|
||||
+ AccountTable.KEY1 + " TEXT,"
|
||||
+ AccountTable.KEY2 + " TEXT);";
|
||||
|
||||
/**
|
||||
* SQL query to create user exclude table
|
||||
*/
|
||||
private static final String TABLE_USER_EXCLUDE = "CREATE TABLE IF NOT EXISTS "
|
||||
+ UserExcludeTable.NAME + "("
|
||||
+ UserExcludeTable.OWNER + " INTEGER,"
|
||||
+ UserExcludeTable.ID + " INTEGER);";
|
||||
|
||||
/**
|
||||
* table index for tweet table
|
||||
*/
|
||||
@ -266,6 +274,7 @@ public class DatabaseAdapter {
|
||||
db.execSQL(TABLE_TRENDS);
|
||||
db.execSQL(TABLE_MESSAGES);
|
||||
db.execSQL(TABLE_LOGINS);
|
||||
db.execSQL(TABLE_USER_EXCLUDE);
|
||||
db.execSQL(TABLE_TWEET_REGISTER);
|
||||
db.execSQL(TABLE_USER_REGISTER);
|
||||
// create index
|
||||
@ -610,4 +619,24 @@ public class DatabaseAdapter {
|
||||
*/
|
||||
String REGISTER = "userRegister";
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public interface UserExcludeTable {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
String NAME = "userExclude";
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
String OWNER = "listOwner";
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
String ID = "userID";
|
||||
}
|
||||
}
|
@ -0,0 +1,155 @@
|
||||
package org.nuclearfog.twidda.database;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
|
||||
import org.nuclearfog.twidda.database.DatabaseAdapter.UserExcludeTable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
* Database class of the user exclude list
|
||||
*
|
||||
* @author nuclearfog
|
||||
*/
|
||||
public class ExcludeDatabase {
|
||||
|
||||
/**
|
||||
* selection to get the exclude list of the current user
|
||||
*/
|
||||
private static final String LIST_SELECT = UserExcludeTable.OWNER + "=?";
|
||||
|
||||
/**
|
||||
* selection to get a column
|
||||
*/
|
||||
private static final String COLUMN_SELECT = LIST_SELECT + " AND " + UserExcludeTable.ID + "=?";
|
||||
|
||||
/**
|
||||
* column to fetch from the database
|
||||
*/
|
||||
private static final String[] LIST_ID_COL = {UserExcludeTable.ID};
|
||||
|
||||
|
||||
private static final ExcludeDatabase INSTANCE = new ExcludeDatabase();
|
||||
private DatabaseAdapter dataHelper;
|
||||
private GlobalSettings settings;
|
||||
|
||||
|
||||
private ExcludeDatabase() {
|
||||
}
|
||||
|
||||
/**
|
||||
* get singleton instance
|
||||
*
|
||||
* @param context activity context
|
||||
* @return instance of this class
|
||||
*/
|
||||
public static ExcludeDatabase getInstance(Context context) {
|
||||
if (INSTANCE.dataHelper == null) {
|
||||
INSTANCE.dataHelper = DatabaseAdapter.getInstance(context.getApplicationContext());
|
||||
INSTANCE.settings = GlobalSettings.getInstance(context);
|
||||
}
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* replace exclude list with a new version
|
||||
*
|
||||
* @param ids list of user IDs
|
||||
*/
|
||||
public void setExcludeList(List<Long> ids) {
|
||||
long homeId = settings.getCurrentUserId();
|
||||
String[] args = {Long.toString(homeId)};
|
||||
SQLiteDatabase db = getDbWrite();
|
||||
|
||||
db.delete(UserExcludeTable.NAME, LIST_SELECT, args);
|
||||
for (long id : ids) {
|
||||
ContentValues column = new ContentValues(2);
|
||||
column.put(UserExcludeTable.ID, id);
|
||||
column.put(UserExcludeTable.OWNER, homeId);
|
||||
db.insert(UserExcludeTable.NAME, null, column);
|
||||
}
|
||||
commit(db);
|
||||
}
|
||||
|
||||
/**
|
||||
* return current users exclude set containing user IDs
|
||||
*
|
||||
* @return a set of user IDs
|
||||
*/
|
||||
public Set<Long> getExcludeSet() {
|
||||
String[] args = {Long.toString(settings.getCurrentUserId())};
|
||||
SQLiteDatabase db = getDbRead();
|
||||
Cursor cursor = db.query(UserExcludeTable.NAME, LIST_ID_COL, LIST_SELECT, args, null, null, null, null);
|
||||
|
||||
Set<Long> result = new TreeSet<>();
|
||||
if (cursor.moveToFirst()) {
|
||||
do {
|
||||
long id = cursor.getLong(0);
|
||||
result.add(id);
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
cursor.close();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* add user to the exclude database
|
||||
*
|
||||
* @param userId ID of the user
|
||||
*/
|
||||
public void addUser(long userId) {
|
||||
SQLiteDatabase db = getDbWrite();
|
||||
ContentValues column = new ContentValues(2);
|
||||
column.put(UserExcludeTable.ID, userId);
|
||||
column.put(UserExcludeTable.OWNER, settings.getCurrentUserId());
|
||||
db.insert(UserExcludeTable.NAME, null, column);
|
||||
commit(db);
|
||||
}
|
||||
|
||||
/**
|
||||
* remove user from the exclude database
|
||||
*
|
||||
* @param userId ID of the user
|
||||
*/
|
||||
public void removeUser(long userId) {
|
||||
String[] args = {Long.toString(settings.getCurrentUserId()), Long.toString(userId)};
|
||||
SQLiteDatabase db = getDbWrite();
|
||||
db.delete(UserExcludeTable.NAME, COLUMN_SELECT, args);
|
||||
commit(db);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get SQLite instance for reading database
|
||||
*
|
||||
* @return SQLite instance
|
||||
*/
|
||||
private synchronized SQLiteDatabase getDbRead() {
|
||||
return dataHelper.getDatabase();
|
||||
}
|
||||
|
||||
/**
|
||||
* GET SQLite instance for writing database
|
||||
*
|
||||
* @return SQLite instance
|
||||
*/
|
||||
private synchronized SQLiteDatabase getDbWrite() {
|
||||
SQLiteDatabase db = dataHelper.getDatabase();
|
||||
db.beginTransaction();
|
||||
return db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit changes and close Database
|
||||
*
|
||||
* @param db database instance
|
||||
*/
|
||||
private synchronized void commit(SQLiteDatabase db) {
|
||||
db.setTransactionSuccessful();
|
||||
db.endTransaction();
|
||||
}
|
||||
}
|
@ -1,5 +1,12 @@
|
||||
package org.nuclearfog.twidda.database;
|
||||
|
||||
import static android.content.Context.MODE_PRIVATE;
|
||||
import static android.graphics.Typeface.DEFAULT;
|
||||
import static android.graphics.Typeface.MONOSPACE;
|
||||
import static android.graphics.Typeface.NORMAL;
|
||||
import static android.graphics.Typeface.SANS_SERIF;
|
||||
import static android.graphics.Typeface.SERIF;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.Editor;
|
||||
@ -11,13 +18,6 @@ import androidx.annotation.NonNull;
|
||||
|
||||
import org.nuclearfog.twidda.backend.model.TrendLocation;
|
||||
|
||||
import static android.content.Context.MODE_PRIVATE;
|
||||
import static android.graphics.Typeface.DEFAULT;
|
||||
import static android.graphics.Typeface.MONOSPACE;
|
||||
import static android.graphics.Typeface.NORMAL;
|
||||
import static android.graphics.Typeface.SANS_SERIF;
|
||||
import static android.graphics.Typeface.SERIF;
|
||||
|
||||
/**
|
||||
* This class manages app settings
|
||||
*
|
||||
@ -91,6 +91,7 @@ public class GlobalSettings {
|
||||
private static final String TREND_LOC = "location";
|
||||
private static final String TREND_ID = "world_id";
|
||||
private static final String LINK_PREVIEW = "link_preview";
|
||||
private static final String FILTER_RESULTS = "filter_results";
|
||||
private static final String CUSTOM_CONSUMER_KEY_SET = "custom_api_keys";
|
||||
private static final String CUSTOM_CONSUMER_KEY_1 = "api_key1";
|
||||
private static final String CUSTOM_CONSUMER_KEY_2 = "api_key2";
|
||||
@ -135,6 +136,7 @@ public class GlobalSettings {
|
||||
private boolean customAPIKey;
|
||||
private boolean toolbarOverlap;
|
||||
private boolean linkPreview;
|
||||
private boolean filterResults;
|
||||
private int background_color;
|
||||
private int font_color;
|
||||
private int highlight_color;
|
||||
@ -449,14 +451,16 @@ public class GlobalSettings {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* check if linke preview is enabled
|
||||
*/
|
||||
public boolean linkPreviewEnabled() {
|
||||
return linkPreview;
|
||||
}
|
||||
|
||||
/**
|
||||
* enable/disable link preview
|
||||
*
|
||||
* @param enable true enables link preview
|
||||
*/
|
||||
public void setLinkPreview(boolean enable) {
|
||||
linkPreview = enable;
|
||||
@ -466,6 +470,28 @@ public class GlobalSettings {
|
||||
edit.apply();
|
||||
}
|
||||
|
||||
/**
|
||||
* check if search filter is enabled
|
||||
*
|
||||
* @return true if search filter is enabled
|
||||
*/
|
||||
public boolean filterResults() {
|
||||
return filterResults;
|
||||
}
|
||||
|
||||
/**
|
||||
* enable/disable search filter
|
||||
*
|
||||
* @param enable true to enable search filter
|
||||
*/
|
||||
public void setFilterResults(boolean enable) {
|
||||
filterResults = enable;
|
||||
|
||||
Editor edit = settings.edit();
|
||||
edit.putBoolean(FILTER_RESULTS, enable);
|
||||
edit.apply();
|
||||
}
|
||||
|
||||
/**
|
||||
* sets image quality
|
||||
*
|
||||
@ -893,6 +919,7 @@ public class GlobalSettings {
|
||||
hqImages = settings.getBoolean(IMAGE_QUALITY, false);
|
||||
toolbarOverlap = settings.getBoolean(PROFILE_OVERLAP, true);
|
||||
linkPreview = settings.getBoolean(LINK_PREVIEW, false);
|
||||
filterResults = settings.getBoolean(FILTER_RESULTS, true);
|
||||
customAPIKey = settings.getBoolean(CUSTOM_CONSUMER_KEY_SET, false);
|
||||
proxyHost = settings.getString(PROXY_ADDR, "");
|
||||
proxyPort = settings.getString(PROXY_PORT, "");
|
||||
|
12
app/src/main/res/menu/excludelist.xml
Normal file
12
app/src/main/res/menu/excludelist.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_exclude_user"
|
||||
android:title="@string/menu_exclude_user"
|
||||
android:icon="@drawable/add_user"
|
||||
app:actionViewClass="androidx.appcompat.widget.SearchView"
|
||||
app:showAsAction="ifRoom|collapseActionView" />
|
||||
|
||||
</menu>
|
@ -15,4 +15,9 @@
|
||||
android:title="@string/menu_tweet"
|
||||
app:showAsAction="always" />
|
||||
|
||||
<item
|
||||
android:id="@+id/search_filter"
|
||||
android:title="@string/menu_search_filter"
|
||||
android:checkable="true" />
|
||||
|
||||
</menu>
|
@ -207,4 +207,9 @@
|
||||
<string name="settings_follow_color">Follow Icon</string>
|
||||
<string name="settings_enable_toolbar_overlap">Kompakte Profilansicht</string>
|
||||
<string name="account_user_unnamed">\'unbenannt\'</string>
|
||||
<string name="menu_excluded_users">Blocklisten</string>
|
||||
<string name="menu_hint_mute_user">\@Name stummschalten</string>
|
||||
<string name="menu_hint_block_user">\@Name blockieren</string>
|
||||
<string name="menu_exclude_user">Nutzer ausschließen</string>
|
||||
<string name="menu_search_filter">Ergebnisse filtern</string>
|
||||
</resources>
|
@ -218,7 +218,11 @@
|
||||
<string name="menu_unfollow_list">unfollow list</string>
|
||||
<string name="menu_user_unfollow">unfollow</string>
|
||||
<string name="menu_user_unblock">unblock</string>
|
||||
<string name="menu_excluded_users">Block/Mute list</string>
|
||||
<string name="menu_excluded_users">Block lists</string>
|
||||
<string name="menu_exclude_user">exclude user</string>
|
||||
<string name="menu_search_filter">filter results</string>
|
||||
<string name="menu_hint_mute_user">enter @name to mute</string>
|
||||
<string name="menu_hint_block_user">enter @name to block</string>
|
||||
|
||||
<!--dialog strings-->
|
||||
<string name="dialog_button_yes">Yes</string>
|
||||
|
Loading…
Reference in New Issue
Block a user