added user exclude database, added search filtering, bug fix

Signed-off-by: nuclearfog <hatespirit666@gmail.com>
This commit is contained in:
nuclearfog 2021-08-29 00:20:45 +02:00
parent 90bfa02f74
commit 26077be39a
No known key found for this signature in database
GPG Key ID: AA0271FBE406DB98
13 changed files with 556 additions and 39 deletions

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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);
}
}
}
}

View File

@ -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;
}
}

View File

@ -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";
}
}

View File

@ -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();
}
}

View File

@ -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, "");

View 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>

View File

@ -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>

View File

@ -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>

View File

@ -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>