completed hashtag page, renamed classes, code cleanup, layout fix, bug fix

This commit is contained in:
nuclearfog 2023-09-26 22:11:53 +02:00
parent ccd697e97f
commit 774e3fa056
No known key found for this signature in database
GPG Key ID: 03488A185C476379
32 changed files with 338 additions and 341 deletions

View File

@ -21,7 +21,7 @@ import org.nuclearfog.twidda.model.Relation;
import org.nuclearfog.twidda.model.ScheduledStatus;
import org.nuclearfog.twidda.model.Status;
import org.nuclearfog.twidda.model.Translation;
import org.nuclearfog.twidda.model.Trend;
import org.nuclearfog.twidda.model.Hashtag;
import org.nuclearfog.twidda.model.User;
import org.nuclearfog.twidda.model.UserList;
import org.nuclearfog.twidda.model.WebPush;
@ -303,7 +303,7 @@ public interface Connection {
* @param name hashtag name
* @return hashtag information
*/
Trend showHashtag(String name) throws ConnectionException;
Hashtag showHashtag(String name) throws ConnectionException;
/**
* follow hashtag by name
@ -311,7 +311,7 @@ public interface Connection {
* @param name name of the hashtag
* @return updated hashtag information
*/
Trend followHashtag(String name) throws ConnectionException;
Hashtag followHashtag(String name) throws ConnectionException;
/**
* unfollow hashtag by name
@ -319,7 +319,21 @@ public interface Connection {
* @param name name of the hashtag
* @return updated hashtag information
*/
Trend unfollowHashtag(String name) throws ConnectionException;
Hashtag unfollowHashtag(String name) throws ConnectionException;
/**
*
* @param name name of the hashtag
* @return updated hashtag information
*/
Hashtag featureHashtag(String name) throws ConnectionException;
/**
*
* @param name name of the hashtag
* @return updated hashtag information
*/
Hashtag unfeatureHashtag(String name) throws ConnectionException;
/**
* show current user's home timeline
@ -641,13 +655,6 @@ public interface Connection {
*/
Poll votePoll(Poll poll, int[] selection) throws ConnectionException;
/**
* returns a list of blocked user IDs
*
* @return list of IDs
*/
List<Long> getIdBlocklist() throws ConnectionException;
/**
* returns used filter
*

View File

@ -25,7 +25,7 @@ import org.nuclearfog.twidda.backend.api.mastodon.impl.MastodonPush;
import org.nuclearfog.twidda.backend.api.mastodon.impl.MastodonRelation;
import org.nuclearfog.twidda.backend.api.mastodon.impl.MastodonStatus;
import org.nuclearfog.twidda.backend.api.mastodon.impl.MastodonTranslation;
import org.nuclearfog.twidda.backend.api.mastodon.impl.MastodonTrend;
import org.nuclearfog.twidda.backend.api.mastodon.impl.MastodonHashtag;
import org.nuclearfog.twidda.backend.api.mastodon.impl.MastodonUser;
import org.nuclearfog.twidda.backend.api.mastodon.impl.ScheduledMastodonStatus;
import org.nuclearfog.twidda.backend.helper.ConnectionResult;
@ -51,7 +51,7 @@ import org.nuclearfog.twidda.model.Relation;
import org.nuclearfog.twidda.model.ScheduledStatus;
import org.nuclearfog.twidda.model.Status;
import org.nuclearfog.twidda.model.Translation;
import org.nuclearfog.twidda.model.Trend;
import org.nuclearfog.twidda.model.Hashtag;
import org.nuclearfog.twidda.model.User;
import org.nuclearfog.twidda.model.UserList;
import org.nuclearfog.twidda.model.WebPush;
@ -126,7 +126,7 @@ public class Mastodon implements Connection {
private static final String ENDPOINT_HASHTAG_TIMELINE = "/api/v1/timelines/tag/";
private static final String ENDPOINT_HASHTAG_FOLLOWING = "/api/v1/followed_tags";
private static final String ENDPOINT_HASHTAG_FEATURE = "/api/v1/featured_tags";
private static final String ENDPOINT_HASHTAG_GET = "/api/v1/tags/";
private static final String ENDPOINT_HASHTAG = "/api/v1/tags/";
private static final String ENDPOINT_USER_TIMELINE = "/api/v1/accounts/";
private static final String ENDPOINT_USER_FAVORITS = "/api/v1/favourites";
private static final String ENDPOINT_TRENDS = "/api/v1/trends/tags";
@ -491,11 +491,11 @@ public class Mastodon implements Connection {
@Override
public Trend showHashtag(String name) throws ConnectionException {
public Hashtag showHashtag(String name) throws ConnectionException {
try {
if (name.startsWith("#"))
name = name.substring(1);
return createTrend(get(ENDPOINT_HASHTAG_GET + StringUtils.encode(name), new ArrayList<>()));
return createTag(get(ENDPOINT_HASHTAG + StringUtils.encode(name), new ArrayList<>()));
} catch (IOException e) {
throw new MastodonException(e);
}
@ -503,11 +503,11 @@ public class Mastodon implements Connection {
@Override
public Trend followHashtag(String name) throws ConnectionException {
public Hashtag followHashtag(String name) throws ConnectionException {
try {
if (name.startsWith("#"))
name = name.substring(1);
return createTrend(post(ENDPOINT_HASHTAG_GET + StringUtils.encode(name) + "/follow", new ArrayList<>()));
return createTag(post(ENDPOINT_HASHTAG + StringUtils.encode(name) + "/follow", new ArrayList<>()));
} catch (IOException e) {
throw new MastodonException(e);
}
@ -515,11 +515,39 @@ public class Mastodon implements Connection {
@Override
public Trend unfollowHashtag(String name) throws ConnectionException {
public Hashtag unfollowHashtag(String name) throws ConnectionException {
try {
if (name.startsWith("#"))
name = name.substring(1);
return createTrend(post(ENDPOINT_HASHTAG_GET + StringUtils.encode(name) + "/unfollow", new ArrayList<>()));
return createTag(post(ENDPOINT_HASHTAG + StringUtils.encode(name) + "/unfollow", new ArrayList<>()));
} catch (IOException e) {
throw new MastodonException(e);
}
}
@Override
public Hashtag featureHashtag(String name) throws ConnectionException {
try {
if (name.startsWith("#"))
name = name.substring(1);
List<String> params = new ArrayList<>();
params.add("name=" + StringUtils.encode(name));
return createTag(post(ENDPOINT_HASHTAG_FEATURE, params));
} catch (IOException e) {
throw new MastodonException(e);
}
}
@Override
public Hashtag unfeatureHashtag(String name) throws ConnectionException {
try {
if (name.startsWith("#"))
name = name.substring(1);
List<String> params = new ArrayList<>();
params.add("name=" + StringUtils.encode(name));
return createTag(delete(ENDPOINT_HASHTAG_FEATURE, params));
} catch (IOException e) {
throw new MastodonException(e);
}
@ -1001,12 +1029,6 @@ public class Mastodon implements Connection {
}
@Override
public List<Long> getIdBlocklist() throws MastodonException {
throw new MastodonException("not supported!");
}
@Override
public Filters getFilter() throws ConnectionException {
try {
@ -1444,7 +1466,7 @@ public class Mastodon implements Connection {
long[] cursors = getCursors(response);
Trends result = new Trends(cursors[0], cursors[1]);
for (int i = 0; i < jsonArray.length(); i++) {
result.add(new MastodonTrend(jsonArray.getJSONObject(i)));
result.add(new MastodonHashtag(jsonArray.getJSONObject(i)));
}
Collections.sort(result);
return result;
@ -1649,12 +1671,12 @@ public class Mastodon implements Connection {
* @param response response from a trend endpoint
* @return trend information
*/
private Trend createTrend(Response response) throws MastodonException {
private Hashtag createTag(Response response) throws MastodonException {
try {
ResponseBody body = response.body();
if (response.code() == 200 && body != null) {
JSONObject json = new JSONObject(body.string());
return new MastodonTrend(json);
return new MastodonHashtag(json);
}
throw new MastodonException(response);
} catch (IOException | JSONException e) {

View File

@ -6,14 +6,14 @@ import androidx.annotation.Nullable;
import org.json.JSONArray;
import org.json.JSONObject;
import org.nuclearfog.twidda.model.Location;
import org.nuclearfog.twidda.model.Trend;
import org.nuclearfog.twidda.model.Hashtag;
/**
* Trend implementation used for Mastodon API
* Hashtag implementation used by Mastodon API
*
* @author nuclearfog
*/
public class MastodonTrend implements Trend {
public class MastodonHashtag implements Hashtag {
private static final long serialVersionUID = 4328931229081239280L;
@ -24,7 +24,7 @@ public class MastodonTrend implements Trend {
/**
* @param json trend json object
*/
public MastodonTrend(JSONObject json) {
public MastodonHashtag(JSONObject json) {
JSONArray history = json.optJSONArray("history");
name = '#' + json.optString("name", "");
following = json.optBoolean("following", false);
@ -33,6 +33,8 @@ public class MastodonTrend implements Trend {
if (latest != null) {
popularity = latest.optInt("uses", 0);
}
} else {
popularity = json.optInt("statuses_count", 0);
}
}
@ -69,10 +71,10 @@ public class MastodonTrend implements Trend {
@Override
public boolean equals(@Nullable Object obj) {
if (!(obj instanceof Trend))
if (!(obj instanceof Hashtag))
return false;
Trend trend = (Trend) obj;
return getName().equals(trend.getName()) && getLocationId() == trend.getLocationId();
Hashtag hashtag = (Hashtag) obj;
return getName().equals(hashtag.getName()) && getLocationId() == hashtag.getLocationId();
}

View File

@ -8,7 +8,7 @@ import androidx.annotation.Nullable;
import org.nuclearfog.twidda.backend.api.Connection;
import org.nuclearfog.twidda.backend.api.ConnectionException;
import org.nuclearfog.twidda.backend.api.ConnectionManager;
import org.nuclearfog.twidda.model.Trend;
import org.nuclearfog.twidda.model.Hashtag;
/**
* Async loader for hashtag follow/unfollow action
@ -32,7 +32,7 @@ public class HashtagAction extends AsyncExecutor<HashtagAction.HashtagParam, Has
try {
switch (param.mode) {
case HashtagParam.LOAD:
Trend result = connection.showHashtag(param.name);
Hashtag result = connection.showHashtag(param.name);
return new HashtagResult(HashtagResult.LOAD, result, null);
case HashtagParam.FOLLOW:
@ -43,6 +43,14 @@ public class HashtagAction extends AsyncExecutor<HashtagAction.HashtagParam, Has
result = connection.unfollowHashtag(param.name);
return new HashtagResult(HashtagResult.UNFOLLOW, result, null);
case HashtagParam.FEATURE:
result = connection.featureHashtag(param.name);
return new HashtagResult(HashtagResult.FEATURE, result, null);
case HashtagParam.UNFEATURE:
result = connection.unfeatureHashtag(param.name);
return new HashtagResult(HashtagResult.UNFEATURE, result, null);
default:
return null;
}
@ -59,11 +67,13 @@ public class HashtagAction extends AsyncExecutor<HashtagAction.HashtagParam, Has
public static final int LOAD = 1;
public static final int FOLLOW = 2;
public static final int UNFOLLOW = 3;
public static final int FEATURE = 4;
public static final int UNFEATURE = 5;
final String name;
final int mode;
public HashtagParam(String name, int mode) {
public HashtagParam(int mode, String name) {
this.name = name;
this.mode = mode;
}
@ -75,19 +85,21 @@ public class HashtagAction extends AsyncExecutor<HashtagAction.HashtagParam, Has
public static class HashtagResult {
public static final int ERROR = -1;
public static final int LOAD = 4;
public static final int FOLLOW = 5;
public static final int UNFOLLOW = 6;
public static final int LOAD = 10;
public static final int FOLLOW = 11;
public static final int UNFOLLOW = 12;
public static final int FEATURE = 13;
public static final int UNFEATURE = 14;
@Nullable
public final ConnectionException exception;
@Nullable
public final Trend trend;
public final Hashtag hashtag;
public final int mode;
HashtagResult(int mode, @Nullable Trend trend, @Nullable ConnectionException exception) {
HashtagResult(int mode, @Nullable Hashtag hashtag, @Nullable ConnectionException exception) {
this.exception = exception;
this.trend = trend;
this.hashtag = hashtag;
this.mode = mode;
}
}

View File

@ -51,7 +51,6 @@ public class RelationLoader extends AsyncExecutor<RelationLoader.RelationParam,
case RelationParam.BLOCK:
relation = connection.blockUser(param.id);
db.muteUser(param.id, true);
db.saveUserToFilterlist(param.id);
return new RelationResult(RelationResult.BLOCK, relation);
case RelationParam.UNBLOCK:
@ -59,7 +58,6 @@ public class RelationLoader extends AsyncExecutor<RelationLoader.RelationParam,
// remove from exclude list only if user is not muted
if (!relation.isMuted()) {
db.muteUser(param.id, false);
db.removeUserFromFilterlist(param.id);
}
return new RelationResult(RelationResult.UNBLOCK, relation);
@ -73,7 +71,6 @@ public class RelationLoader extends AsyncExecutor<RelationLoader.RelationParam,
// remove from exclude list only if user is not blocked
if (!relation.isBlocked()) {
db.muteUser(param.id, false);
db.removeUserFromFilterlist(param.id);
}
return new RelationResult(RelationResult.UNMUTE, relation);

View File

@ -12,16 +12,13 @@ import org.nuclearfog.twidda.database.AppDatabase;
import org.nuclearfog.twidda.model.Relation;
import org.nuclearfog.twidda.ui.activities.UsersActivity;
import java.util.List;
/**
* 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
* used to block/mute users/domains
*
* @author nuclearfog
*/
public class UserFilterLoader extends AsyncExecutor<UserFilterLoader.FilterParam, UserFilterLoader.FilterResult> {
public class UserFilterAction extends AsyncExecutor<UserFilterAction.FilterParam, UserFilterAction.FilterResult> {
private Connection connection;
private AppDatabase db;
@ -29,7 +26,7 @@ public class UserFilterLoader extends AsyncExecutor<UserFilterLoader.FilterParam
/**
*
*/
public UserFilterLoader(Context context) {
public UserFilterAction(Context context) {
connection = ConnectionManager.getDefaultConnection(context);
db = new AppDatabase(context);
}
@ -39,11 +36,6 @@ public class UserFilterLoader extends AsyncExecutor<UserFilterLoader.FilterParam
protected FilterResult doInBackground(@NonNull FilterParam param) {
try {
switch (param.mode) {
case FilterParam.RELOAD:
List<Long> ids = connection.getIdBlocklist();
db.saveFilterlist(ids);
return new FilterResult(FilterResult.RELOAD, null);
case FilterParam.MUTE_USER:
Relation relation = connection.muteUser(param.name);
db.muteUser(relation.getId(), true);
@ -71,7 +63,6 @@ public class UserFilterLoader extends AsyncExecutor<UserFilterLoader.FilterParam
*/
public static class FilterParam {
public static final int RELOAD = 1;
public static final int MUTE_USER = 2;
public static final int BLOCK_USER = 3;
public static final int BLOCK_DOMAIN = 4;
@ -96,7 +87,6 @@ public class UserFilterLoader extends AsyncExecutor<UserFilterLoader.FilterParam
public static class FilterResult {
public static final int ERROR = -1;
public static final int RELOAD = 5;
public static final int MUTE_USER = 6;
public static final int BLOCK_USER = 7;
public static final int BLOCK_DOMAIN = 8;

View File

@ -19,8 +19,7 @@ import org.nuclearfog.twidda.database.DatabaseAdapter.NotificationTable;
import org.nuclearfog.twidda.database.DatabaseAdapter.PollTable;
import org.nuclearfog.twidda.database.DatabaseAdapter.StatusRegisterTable;
import org.nuclearfog.twidda.database.DatabaseAdapter.StatusTable;
import org.nuclearfog.twidda.database.DatabaseAdapter.TrendTable;
import org.nuclearfog.twidda.database.DatabaseAdapter.UserExcludeTable;
import org.nuclearfog.twidda.database.DatabaseAdapter.HashtagTable;
import org.nuclearfog.twidda.database.DatabaseAdapter.UserRegisterTable;
import org.nuclearfog.twidda.database.DatabaseAdapter.UserTable;
import org.nuclearfog.twidda.database.impl.DatabaseAccount;
@ -31,7 +30,7 @@ import org.nuclearfog.twidda.database.impl.DatabaseMedia;
import org.nuclearfog.twidda.database.impl.DatabaseNotification;
import org.nuclearfog.twidda.database.impl.DatabasePoll;
import org.nuclearfog.twidda.database.impl.DatabaseStatus;
import org.nuclearfog.twidda.database.impl.DatabaseTrend;
import org.nuclearfog.twidda.database.impl.DatabaseHashtag;
import org.nuclearfog.twidda.database.impl.DatabaseUser;
import org.nuclearfog.twidda.model.Account;
import org.nuclearfog.twidda.model.Emoji;
@ -41,7 +40,7 @@ import org.nuclearfog.twidda.model.Media;
import org.nuclearfog.twidda.model.Notification;
import org.nuclearfog.twidda.model.Poll;
import org.nuclearfog.twidda.model.Status;
import org.nuclearfog.twidda.model.Trend;
import org.nuclearfog.twidda.model.Hashtag;
import org.nuclearfog.twidda.model.User;
import org.nuclearfog.twidda.model.lists.Accounts;
import org.nuclearfog.twidda.model.lists.Notifications;
@ -305,7 +304,7 @@ public class AppDatabase {
/**
* select trends from trend table with given world ID
*/
private static final String TREND_SELECT = TrendTable.ID + "=?";
private static final String TREND_SELECT = HashtagTable.ID + "=?";
/**
* select status from status table matching ID
@ -372,16 +371,6 @@ public class AppDatabase {
*/
private static final String[] STATUS_REG_COLUMN = {StatusRegisterTable.REGISTER};
/**
* 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 FILTER_SELECT = LIST_SELECT + " AND " + UserExcludeTable.USER + "=?";
/**
* default sort order for logins
*/
@ -536,47 +525,23 @@ public class AppDatabase {
}
}
/**
* create a new filterlist containing user IDs
*
* @param ids list of user IDs
*/
public void saveFilterlist(List<Long> ids) {
synchronized (LOCK) {
long homeId = settings.getLogin().getId();
String[] args = {Long.toString(homeId)};
SQLiteDatabase db = adapter.getDbWrite();
db.delete(UserExcludeTable.NAME, LIST_SELECT, args);
if (!ids.isEmpty()) {
for (long id : ids) {
ContentValues column = new ContentValues(2);
column.put(UserExcludeTable.USER, id);
column.put(UserExcludeTable.OWNER, homeId);
db.insert(UserExcludeTable.NAME, null, column);
}
}
adapter.commit();
}
}
/**
* store location specific trends
*
* @param trends List of Trends
* @param hashtags List of Trends
*/
public void saveTrends(List<Trend> trends) {
public void saveTrends(List<Hashtag> hashtags) {
synchronized (LOCK) {
String[] args = {Long.toString(settings.getTrendLocation().getId())};
SQLiteDatabase db = adapter.getDbWrite();
db.delete(TrendTable.NAME, TREND_SELECT, args);
for (Trend trend : trends) {
db.delete(HashtagTable.NAME, TREND_SELECT, args);
for (Hashtag hashtag : hashtags) {
ContentValues column = new ContentValues(4);
column.put(TrendTable.ID, trend.getLocationId());
column.put(TrendTable.VOL, trend.getPopularity());
column.put(TrendTable.TREND, trend.getName());
column.put(TrendTable.INDEX, trend.getRank());
db.insert(TrendTable.NAME, null, column);
column.put(HashtagTable.ID, hashtag.getLocationId());
column.put(HashtagTable.VOL, hashtag.getPopularity());
column.put(HashtagTable.TREND, hashtag.getName());
column.put(HashtagTable.INDEX, hashtag.getRank());
db.insert(HashtagTable.NAME, null, column);
}
adapter.commit();
}
@ -679,22 +644,6 @@ public class AppDatabase {
}
}
/**
* add user to the exclude database
*
* @param userId ID of the user
*/
public void saveUserToFilterlist(long userId) {
synchronized (LOCK) {
SQLiteDatabase db = adapter.getDbWrite();
ContentValues column = new ContentValues(2);
column.put(UserExcludeTable.USER, userId);
column.put(UserExcludeTable.OWNER, settings.getLogin().getId());
db.insert(UserExcludeTable.NAME, null, column);
adapter.commit();
}
}
/**
* save emojis to database
*
@ -830,11 +779,11 @@ public class AppDatabase {
synchronized (LOCK) {
String[] args = {Long.toString(settings.getTrendLocation().getId())};
SQLiteDatabase db = adapter.getDbRead();
Cursor cursor = db.query(TrendTable.NAME, DatabaseTrend.COLUMNS, TREND_SELECT, args, null, null, null);
Cursor cursor = db.query(HashtagTable.NAME, DatabaseHashtag.COLUMNS, TREND_SELECT, args, null, null, null);
Trends trends = new Trends();
if (cursor.moveToFirst()) {
do {
trends.add(new DatabaseTrend(cursor));
trends.add(new DatabaseHashtag(cursor));
} while (cursor.moveToNext());
}
cursor.close();
@ -1069,20 +1018,6 @@ public class AppDatabase {
}
}
/**
* remove user from the exclude database
*
* @param userId ID of the user
*/
public void removeUserFromFilterlist(long userId) {
synchronized (LOCK) {
String[] args = {Long.toString(settings.getLogin().getId()), Long.toString(userId)};
SQLiteDatabase db = adapter.getDbWrite();
db.delete(UserExcludeTable.NAME, FILTER_SELECT, args);
adapter.commit();
}
}
/**
* check if status exists in database
*
@ -1170,10 +1105,9 @@ public class AppDatabase {
db.delete(StatusTable.NAME, null, null);
db.delete(FavoriteTable.NAME, null, null);
db.delete(BookmarkTable.NAME, null, null);
db.delete(TrendTable.NAME, null, null);
db.delete(HashtagTable.NAME, null, null);
db.delete(StatusRegisterTable.NAME, null, null);
db.delete(UserRegisterTable.NAME, null, null);
db.delete(UserExcludeTable.NAME, null, null);
db.delete(NotificationTable.NAME, null, null);
db.delete(MediaTable.NAME, null, null);
db.delete(LocationTable.NAME, null, null);

View File

@ -76,11 +76,11 @@ public class DatabaseAdapter {
* SQL query to create a table for trend information
*/
private static final String TABLE_TRENDS = "CREATE TABLE IF NOT EXISTS "
+ TrendTable.NAME + "("
+ TrendTable.ID + " INTEGER,"
+ TrendTable.INDEX + " INTEGER,"
+ TrendTable.VOL + " INTEGER,"
+ TrendTable.TREND + " TEXT);";
+ HashtagTable.NAME + "("
+ HashtagTable.ID + " INTEGER,"
+ HashtagTable.INDEX + " INTEGER,"
+ HashtagTable.VOL + " INTEGER,"
+ HashtagTable.TREND + " TEXT);";
/**
* SQL query to create a table for user logins
@ -186,14 +186,6 @@ public class DatabaseAdapter {
+ BookmarkTable.OWNER + " INTEGER,"
+ BookmarkTable.STATUS + " INTEGER);";
/**
* SQL query to create user blocklist table
*/
private static final String TABLE_USER_BLOCKLIST = "CREATE TABLE IF NOT EXISTS "
+ UserExcludeTable.NAME + "("
+ UserExcludeTable.OWNER + " INTEGER,"
+ UserExcludeTable.USER + " INTEGER);";
/**
* SQL query to create instance table
*/
@ -343,7 +335,6 @@ public class DatabaseAdapter {
db.execSQL(TABLE_BOOKMARKS);
db.execSQL(TABLE_TRENDS);
db.execSQL(TABLE_ACCOUNTS);
db.execSQL(TABLE_USER_BLOCKLIST);
db.execSQL(TABLE_STATUS_REGISTER);
db.execSQL(TABLE_USER_REGISTER);
db.execSQL(TABLE_NOTIFICATION);
@ -704,19 +695,19 @@ public class DatabaseAdapter {
/**
* table for trends and trending hashtags
*/
public interface TrendTable {
public interface HashtagTable {
/**
* table name
*/
String NAME = "trend";
/**
* Location ID of the trend
* Location ID
*/
String ID = "woeID";
/**
* rank of the trend
* rank of the hashtag
*/
String INDEX = "trendpos";
@ -726,7 +717,7 @@ public class DatabaseAdapter {
String VOL = "vol";
/**
* name of the trend
* hashtag name
*/
String TREND = "trendname";
}
@ -848,26 +839,6 @@ public class DatabaseAdapter {
String REGISTER = "userRegister";
}
/**
* table for user filter list
*/
public interface UserExcludeTable {
/**
* table name
*/
String NAME = "userExclude";
/**
* owner ID of the list
*/
String OWNER = "listOwner";
/**
* user ID to filter
*/
String USER = "userID";
}
/**
* table for notifications
*/

View File

@ -5,15 +5,15 @@ import android.database.Cursor;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.nuclearfog.twidda.database.DatabaseAdapter.TrendTable;
import org.nuclearfog.twidda.model.Trend;
import org.nuclearfog.twidda.database.DatabaseAdapter.HashtagTable;
import org.nuclearfog.twidda.model.Hashtag;
/**
* database implementation for a trend
* database implementation of a hashtag
*
* @author nuclearfog
*/
public class DatabaseTrend implements Trend, TrendTable {
public class DatabaseHashtag implements Hashtag, HashtagTable {
private static final long serialVersionUID = 1799880502954768985L;
@ -30,7 +30,7 @@ public class DatabaseTrend implements Trend, TrendTable {
/**
* @param cursor database cursor using this {@link #COLUMNS} projection
*/
public DatabaseTrend(Cursor cursor) {
public DatabaseHashtag(Cursor cursor) {
String name = cursor.getString(0);
popularity = cursor.getInt(1);
rank = cursor.getInt(2);
@ -73,10 +73,10 @@ public class DatabaseTrend implements Trend, TrendTable {
@Override
public boolean equals(@Nullable Object obj) {
if (!(obj instanceof Trend))
if (!(obj instanceof Hashtag))
return false;
Trend trend = (Trend) obj;
return getName().equals(trend.getName()) && getLocationId() == trend.getLocationId();
Hashtag hashtag = (Hashtag) obj;
return getName().equals(hashtag.getName()) && getLocationId() == hashtag.getLocationId();
}

View File

@ -7,7 +7,7 @@ import java.io.Serializable;
*
* @author nuclearfog
*/
public interface Trend extends Serializable, Comparable<Trend> {
public interface Hashtag extends Serializable, Comparable<Hashtag> {
/**
* @return trend name
@ -36,15 +36,15 @@ public interface Trend extends Serializable, Comparable<Trend> {
@Override
default int compareTo(Trend trend) {
if (getRank() > 0 && trend.getRank() > 0)
return Integer.compare(getRank(), trend.getRank());
if (trend.getPopularity() > 0 && getPopularity() > 0)
return Integer.compare(trend.getPopularity(), getPopularity());
if (trend.getPopularity() > 0)
default int compareTo(Hashtag hashtag) {
if (getRank() > 0 && hashtag.getRank() > 0)
return Integer.compare(getRank(), hashtag.getRank());
if (hashtag.getPopularity() > 0 && getPopularity() > 0)
return Integer.compare(hashtag.getPopularity(), getPopularity());
if (hashtag.getPopularity() > 0)
return 1;
if (getPopularity() > 0)
return -1;
return String.CASE_INSENSITIVE_ORDER.compare(getName(), trend.getName());
return String.CASE_INSENSITIVE_ORDER.compare(getName(), hashtag.getName());
}
}

View File

@ -3,7 +3,7 @@ package org.nuclearfog.twidda.model.lists;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.nuclearfog.twidda.model.Trend;
import org.nuclearfog.twidda.model.Hashtag;
import java.util.LinkedList;
@ -12,7 +12,7 @@ import java.util.LinkedList;
*
* @author nuclearfog
*/
public class Trends extends LinkedList<Trend> {
public class Trends extends LinkedList<Hashtag> {
private static final long serialVersionUID = 7646437787602696292L;
@ -49,7 +49,7 @@ public class Trends extends LinkedList<Trend> {
*/
@Nullable
@Override
public Trend get(int index) {
public Hashtag get(int index) {
return super.get(index);
}

View File

@ -1,23 +1,42 @@
package org.nuclearfog.twidda.ui.activities;
import android.graphics.Color;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar;
import androidx.viewpager2.widget.ViewPager2;
import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.backend.async.AsyncExecutor.AsyncCallback;
import org.nuclearfog.twidda.backend.async.HashtagAction;
import org.nuclearfog.twidda.backend.async.HashtagAction.HashtagParam;
import org.nuclearfog.twidda.backend.async.HashtagAction.HashtagResult;
import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.config.GlobalSettings;
import org.nuclearfog.twidda.ui.adapter.viewpager.HashtagAdapter;
import org.nuclearfog.twidda.ui.views.TabSelector;
import org.nuclearfog.twidda.ui.views.TabSelector.OnTabSelectedListener;
/**
* Activity class used to show hashtag following/featuring
*
* @author nuclearfog
*/
public class HashtagActivity extends AppCompatActivity {
public class HashtagActivity extends AppCompatActivity implements SearchView.OnQueryTextListener, OnTabSelectedListener, AsyncCallback<HashtagResult> {
private GlobalSettings settings;
private HashtagAction hashtagAction;
private HashtagAdapter adapter;
private ViewPager2 viewPager;
@Override
@ -26,16 +45,95 @@ public class HashtagActivity extends AppCompatActivity {
setContentView(R.layout.page_hashtag);
ViewGroup root = findViewById(R.id.page_hashtag_root);
Toolbar toolbar = findViewById(R.id.page_hashtag_toolbar);
TabSelector tabSelector = findViewById(R.id.page_hashtag_tab);
ViewPager2 viewPager = findViewById(R.id.page_hashtag_pager);
viewPager = findViewById(R.id.page_hashtag_pager);
HashtagAdapter adapter = new HashtagAdapter(this);
hashtagAction = new HashtagAction(this);
settings = GlobalSettings.get(this);
adapter = new HashtagAdapter(this);
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(2);
tabSelector.addTabIcons(R.array.userlist_hashtag_icons);
tabSelector.addTabLabels(R.array.hashtag_labels);
toolbar.setTitle("");
setSupportActionBar(toolbar);
AppStyles.setTheme(root);
tabSelector.addOnTabSelectedListener(this);
}
@Override
public boolean onCreateOptionsMenu(@NonNull Menu menu) {
getMenuInflater().inflate(R.menu.hashtags, menu);
MenuItem search = menu.findItem(R.id.menu_hashtag_add);
SearchView searchView = (SearchView) search.getActionView();
searchView.setQueryHint(getString(R.string.menu_hashtag_add));
searchView.setOnQueryTextListener(this);
AppStyles.setTheme(searchView, Color.TRANSPARENT);
AppStyles.setMenuIconColor(menu, settings.getIconColor());
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem search = menu.findItem(R.id.menu_hashtag_add);
search.collapseActionView();
return true;
}
@Override
public boolean onQueryTextSubmit(String query) {
if (hashtagAction.isIdle()) {
if (viewPager.getCurrentItem() == 0) {
HashtagParam param = new HashtagParam(HashtagParam.FOLLOW, query);
hashtagAction.execute(param, this);
return true;
} else if (viewPager.getCurrentItem() == 1) {
HashtagParam param = new HashtagParam(HashtagParam.FEATURE, query);
hashtagAction.execute(param, this);
return true;
}
}
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
return false;
}
@Override
public void onResult(@NonNull HashtagResult result) {
switch (result.mode) {
case HashtagResult.FEATURE:
Toast.makeText(getApplicationContext(), R.string.info_hashtag_featured, Toast.LENGTH_SHORT).show();
adapter.notifySettingsChanged();
invalidateOptionsMenu();
break;
case HashtagResult.FOLLOW:
Toast.makeText(getApplicationContext(), R.string.info_hashtag_followed, Toast.LENGTH_SHORT).show();
adapter.notifySettingsChanged();
invalidateOptionsMenu();
break;
case HashtagResult.ERROR:
break;
}
}
@Override
public void onTabSelected(int oldPosition) {
adapter.scrollToTop(oldPosition);
// reset menu
invalidateOptionsMenu();
}
}

View File

@ -27,7 +27,7 @@ import org.nuclearfog.twidda.backend.async.HashtagAction.HashtagResult;
import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.backend.utils.ErrorUtils;
import org.nuclearfog.twidda.config.GlobalSettings;
import org.nuclearfog.twidda.model.Trend;
import org.nuclearfog.twidda.model.Hashtag;
import org.nuclearfog.twidda.ui.adapter.viewpager.SearchAdapter;
import org.nuclearfog.twidda.ui.views.TabSelector;
import org.nuclearfog.twidda.ui.views.TabSelector.OnTabSelectedListener;
@ -49,7 +49,7 @@ public class SearchActivity extends AppCompatActivity implements OnClickListener
/**
* key to add trend information to search for
* value type is {@link Trend}
* value type is {@link Hashtag}
*/
public static final String KEY_DATA = "trend_data";
@ -66,7 +66,7 @@ public class SearchActivity extends AppCompatActivity implements OnClickListener
private String search = "";
@Nullable
private Trend trend;
private Hashtag hashtag;
@Override
@ -90,13 +90,13 @@ public class SearchActivity extends AppCompatActivity implements OnClickListener
String query = getIntent().getStringExtra(KEY_QUERY);
Serializable data = getIntent().getSerializableExtra(KEY_DATA);
if (data instanceof Trend) {
trend = (Trend) data;
search = trend.getName();
if (data instanceof Hashtag) {
hashtag = (Hashtag) data;
search = hashtag.getName();
} else if (query != null) {
search = query;
if (search.startsWith("#") && search.matches("\\S+")) {
HashtagParam param = new HashtagParam(search, HashtagParam.LOAD);
HashtagParam param = new HashtagParam(HashtagParam.LOAD, search);
hashtagAction.execute(param, this);
}
}
@ -124,9 +124,9 @@ public class SearchActivity extends AppCompatActivity implements OnClickListener
if (viewPager.getCurrentItem() > 0) {
viewPager.setCurrentItem(0);
} else {
if (trend != null) {
if (hashtag != null) {
Intent intent = new Intent();
intent.putExtra(KEY_DATA, trend);
intent.putExtra(KEY_DATA, hashtag);
setResult(RETURN_TREND, intent);
}
super.onBackPressed();
@ -146,15 +146,15 @@ public class SearchActivity extends AppCompatActivity implements OnClickListener
getMenuInflater().inflate(R.menu.search, menu);
MenuItem searchItem = menu.findItem(R.id.new_search);
MenuItem searchFilter = menu.findItem(R.id.search_filter);
MenuItem hashtag = menu.findItem(R.id.search_hashtag);
MenuItem menuHashtag = menu.findItem(R.id.search_hashtag);
SearchView searchView = (SearchView) searchItem.getActionView();
boolean enableSearchFilter = settings.getLogin().getConfiguration().filterEnabled();
searchFilter.setVisible(enableSearchFilter);
searchFilter.setChecked(settings.filterResults() & enableSearchFilter);
searchView.setQueryHint(search);
if (trend != null && trend.getName().startsWith("#")) {
hashtag.setVisible(true);
if (hashtag != null && hashtag.getName().startsWith("#")) {
menuHashtag.setVisible(true);
}
// set theme
AppStyles.setTheme(searchView, Color.TRANSPARENT);
@ -168,13 +168,13 @@ public class SearchActivity extends AppCompatActivity implements OnClickListener
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem hashtag = menu.findItem(R.id.search_hashtag);
MenuItem menuHashtag = menu.findItem(R.id.search_hashtag);
// set menu option depending on trend follow status
if (trend != null) {
if (trend.following()) {
hashtag.setTitle(R.string.menu_hashtag_unfollow);
if (hashtag != null) {
if (hashtag.following()) {
menuHashtag.setTitle(R.string.menu_hashtag_unfollow);
} else {
hashtag.setTitle(R.string.menu_hashtag_follow);
menuHashtag.setTitle(R.string.menu_hashtag_follow);
}
}
return super.onPrepareOptionsMenu(menu);
@ -206,12 +206,12 @@ public class SearchActivity extends AppCompatActivity implements OnClickListener
}
// follow/unfollow hashtag
else if (item.getItemId() == R.id.search_hashtag) {
if (trend != null && hashtagAction.isIdle()) {
if (hashtag != null && hashtagAction.isIdle()) {
HashtagParam param;
if (trend.following())
param = new HashtagParam(trend.getName(), HashtagParam.UNFOLLOW);
if (hashtag.following())
param = new HashtagParam(HashtagParam.UNFOLLOW, hashtag.getName());
else
param = new HashtagParam(trend.getName(), HashtagParam.FOLLOW);
param = new HashtagParam(HashtagParam.FOLLOW, hashtag.getName());
hashtagAction.execute(param, this);
}
}
@ -259,8 +259,8 @@ public class SearchActivity extends AppCompatActivity implements OnClickListener
@Override
public void onResult(@NonNull HashtagResult result) {
if (result.trend != null) {
this.trend = result.trend;
if (result.hashtag != null) {
this.hashtag = result.hashtag;
invalidateMenu();
}
switch (result.mode) {

View File

@ -125,13 +125,16 @@ public class UserlistActivity extends AppCompatActivity implements ActivityResul
toolbar.setTitle(userList.getTitle());
toolbar.setSubtitle(userList.getDescription());
adapter = new UserlistAdapter(this, userList);
viewPager.setAdapter(adapter);
if (adapter.getItemCount() == 2) {
tabSelector.addTabIcons(R.array.list_tab_icons);
} else if (adapter.getItemCount() == 3) {
tabSelector.addTabIcons(R.array.list_subscriber_tab_icons);
}
}
viewPager.setOffscreenPageLimit(3);
viewPager.setAdapter(adapter);
setSupportActionBar(toolbar);
AppStyles.setTheme(root);
tabSelector.addTabIcons(R.array.list_tab_icons);
tabSelector.addOnTabSelectedListener(this);
}

View File

@ -44,8 +44,6 @@ public class UserlistsActivity extends AppCompatActivity implements ActivityResu
private GlobalSettings settings;
private ViewPager2 viewPager;
private boolean isHome = false;
@Override
protected void attachBaseContext(Context newBase) {
@ -68,7 +66,6 @@ public class UserlistsActivity extends AppCompatActivity implements ActivityResu
setSupportActionBar(toolbar);
long ownerId = getIntent().getLongExtra(KEY_ID, 0L);
isHome = ownerId == settings.getLogin().getId();
adapter = new UserListsAdapter(this, ownerId);
viewPager.setAdapter(adapter);
@ -102,8 +99,6 @@ public class UserlistsActivity extends AppCompatActivity implements ActivityResu
@Override
public boolean onCreateOptionsMenu(@NonNull Menu m) {
getMenuInflater().inflate(R.menu.lists, m);
m.findItem(R.id.list_create).setVisible(isHome);
m.findItem(R.id.list_blocklists).setVisible(isHome);
AppStyles.setMenuIconColor(m, settings.getIconColor());
return super.onCreateOptionsMenu(m);
}

View File

@ -20,9 +20,9 @@ import androidx.viewpager2.widget.ViewPager2;
import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.backend.async.AsyncExecutor.AsyncCallback;
import org.nuclearfog.twidda.backend.async.UserFilterLoader;
import org.nuclearfog.twidda.backend.async.UserFilterLoader.FilterParam;
import org.nuclearfog.twidda.backend.async.UserFilterLoader.FilterResult;
import org.nuclearfog.twidda.backend.async.UserFilterAction;
import org.nuclearfog.twidda.backend.async.UserFilterAction.FilterParam;
import org.nuclearfog.twidda.backend.async.UserFilterAction.FilterResult;
import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.backend.utils.ErrorUtils;
import org.nuclearfog.twidda.config.GlobalSettings;
@ -92,10 +92,9 @@ public class UsersActivity extends AppCompatActivity implements OnTabSelectedLis
private static final Pattern USERNAME_PATTERN = Pattern.compile("@?\\w+(@\\w+\\.\\w+)?");
private GlobalSettings settings;
private UserFilterLoader filterLoader;
private UserFilterAction filterLoader;
private UserAdapter adapter;
private Toolbar toolbar;
private TabSelector tabSelector;
private ViewPager2 viewPager;
@ -113,11 +112,11 @@ public class UsersActivity extends AppCompatActivity implements OnTabSelectedLis
super.onCreate(savedInst);
setContentView(R.layout.page_users);
ViewGroup root = findViewById(R.id.page_users_root);
toolbar = findViewById(R.id.page_users_toolbar);
Toolbar toolbar = findViewById(R.id.page_users_toolbar);
tabSelector = findViewById(R.id.page_exclude_tab);
viewPager = findViewById(R.id.page_users_pager);
filterLoader = new UserFilterLoader(this);
filterLoader = new UserFilterAction(this);
settings = GlobalSettings.get(this);
viewPager.setOffscreenPageLimit(3);
@ -195,15 +194,12 @@ public class UsersActivity extends AppCompatActivity implements OnTabSelectedLis
@Override
public boolean onCreateOptionsMenu(@NonNull Menu m) {
if (mode == USERS_EXCLUDED) {
getMenuInflater().inflate(R.menu.excludelist, m);
MenuItem search = m.findItem(R.id.menu_exclude_user);
MenuItem refresh = m.findItem(R.id.menu_exclude_refresh);
getMenuInflater().inflate(R.menu.users, m);
MenuItem search = m.findItem(R.id.menu_user_add);
SearchView searchView = (SearchView) search.getActionView();
refresh.setVisible(settings.getLogin().getConfiguration().filterlistEnabled());
searchView.setOnQueryTextListener(this);
AppStyles.setTheme(searchView, Color.TRANSPARENT);
AppStyles.setMenuIconColor(m, settings.getIconColor());
AppStyles.setOverflowIcon(toolbar, settings.getIconColor());
return true;
}
return super.onCreateOptionsMenu(m);
@ -213,16 +209,13 @@ public class UsersActivity extends AppCompatActivity implements OnTabSelectedLis
@Override
public boolean onPrepareOptionsMenu(Menu m) {
if (mode == USERS_EXCLUDED) {
SearchView searchView = (SearchView) m.findItem(R.id.menu_exclude_user).getActionView();
SearchView searchView = (SearchView) m.findItem(R.id.menu_user_add).getActionView();
if (viewPager.getCurrentItem() == 0) {
String hint = getString(R.string.menu_hint_mute_user);
searchView.setQueryHint(hint);
searchView.setQueryHint(getString(R.string.menu_hint_mute_user));
} else if (viewPager.getCurrentItem() == 1) {
String hint = getString(R.string.menu_hint_block_user);
searchView.setQueryHint(hint);
searchView.setQueryHint(getString(R.string.menu_hint_block_user));
} else if (viewPager.getCurrentItem() == 2) {
String hint = getString(R.string.menu_hint_block_domain);
searchView.setQueryHint(hint);
searchView.setQueryHint(getString(R.string.menu_hint_block_domain));
}
return true;
}
@ -230,20 +223,6 @@ public class UsersActivity extends AppCompatActivity implements OnTabSelectedLis
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
if (item.getItemId() == R.id.menu_exclude_refresh) {
if (filterLoader.isIdle()) {
Toast.makeText(getApplicationContext(), R.string.info_refreshing_exclude_list, Toast.LENGTH_SHORT).show();
FilterParam param = new FilterParam(FilterParam.RELOAD);
filterLoader.execute(param, this);
}
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onTabSelected(int oldPosition) {
adapter.scrollToTop(oldPosition);
@ -302,10 +281,6 @@ public class UsersActivity extends AppCompatActivity implements OnTabSelectedLis
invalidateOptionsMenu();
break;
case FilterResult.RELOAD:
Toast.makeText(getApplicationContext(), R.string.info_exclude_list_updated, Toast.LENGTH_SHORT).show();
break;
default:
case FilterResult.ERROR:
ErrorUtils.showErrorMessage(getApplicationContext(), result.exception);

View File

@ -6,7 +6,7 @@ import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView.Adapter;
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
import org.nuclearfog.twidda.model.Trend;
import org.nuclearfog.twidda.model.Hashtag;
import org.nuclearfog.twidda.model.lists.Trends;
import org.nuclearfog.twidda.ui.adapter.recyclerview.holder.OnHolderClickListener;
import org.nuclearfog.twidda.ui.adapter.recyclerview.holder.PlaceHolder;
@ -73,9 +73,9 @@ public class TrendAdapter extends Adapter<ViewHolder> implements OnHolderClickLi
public void onBindViewHolder(@NonNull ViewHolder vh, int index) {
if (vh instanceof TrendHolder) {
TrendHolder holder = (TrendHolder) vh;
Trend trend = items.get(index);
if (trend != null) {
holder.setContent(trend, index);
Hashtag hashtag = items.get(index);
if (hashtag != null) {
holder.setContent(hashtag, index);
}
} else if (vh instanceof PlaceHolder) {
PlaceHolder placeHolder = (PlaceHolder) vh;
@ -138,10 +138,10 @@ public class TrendAdapter extends Adapter<ViewHolder> implements OnHolderClickLi
/**
* remove item from adapter
*
* @param trend item to remove
* @param hashtag item to remove
*/
public void removeItem(Trend trend) {
int index = items.indexOf(trend);
public void removeItem(Hashtag hashtag) {
int index = items.indexOf(hashtag);
if (index >= 0) {
items.remove(index);
notifyItemRemoved(index);
@ -184,9 +184,9 @@ public class TrendAdapter extends Adapter<ViewHolder> implements OnHolderClickLi
/**
* called when a trend item is clicked
*
* @param trend trend name
* @param hashtag trend name
*/
void onTrendClick(Trend trend);
void onTrendClick(Hashtag hashtag);
boolean onPlaceholderClick(long cursor, int index);

View File

@ -16,7 +16,7 @@ import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.backend.utils.StringUtils;
import org.nuclearfog.twidda.config.GlobalSettings;
import org.nuclearfog.twidda.model.Trend;
import org.nuclearfog.twidda.model.Hashtag;
/**
* ViewHolder for a trend item
@ -61,15 +61,15 @@ public class TrendHolder extends ViewHolder implements OnClickListener {
/**
* set view content
*
* @param trend content information
* @param hashtag content information
* @param index index of the item
*/
public void setContent(Trend trend, int index) {
public void setContent(Hashtag hashtag, int index) {
rank.setText(index + 1 + ".");
name.setText(trend.getName());
if (trend.getPopularity() > 0) {
name.setText(hashtag.getName());
if (hashtag.getPopularity() > 0) {
Resources resources = vol.getResources();
String trendVol = StringUtils.NUMBER_FORMAT.format(trend.getPopularity()) + resources.getString(R.string.trend_range);
String trendVol = StringUtils.NUMBER_FORMAT.format(hashtag.getPopularity()) + resources.getString(R.string.trend_range);
vol.setText(trendVol);
vol.setVisibility(View.VISIBLE);
} else {

View File

@ -16,7 +16,7 @@ import org.nuclearfog.twidda.backend.async.TrendLoader;
import org.nuclearfog.twidda.backend.async.TrendLoader.TrendParameter;
import org.nuclearfog.twidda.backend.async.TrendLoader.TrendResult;
import org.nuclearfog.twidda.backend.utils.ErrorUtils;
import org.nuclearfog.twidda.model.Trend;
import org.nuclearfog.twidda.model.Hashtag;
import org.nuclearfog.twidda.model.lists.Trends;
import org.nuclearfog.twidda.ui.activities.SearchActivity;
import org.nuclearfog.twidda.ui.adapter.recyclerview.TrendAdapter;
@ -137,8 +137,8 @@ public class HashtagFragment extends ListFragment implements TrendClickListener,
if (result.getResultCode() == SearchActivity.RETURN_TREND) {
if (result.getData() != null) {
Serializable data = result.getData().getSerializableExtra(SearchActivity.KEY_DATA);
if (data instanceof Trend) {
Trend update = (Trend) data;
if (data instanceof Hashtag) {
Hashtag update = (Hashtag) data;
// remove hashtag if unfollowed
if (mode == MODE_FOLLOW && !update.following()) {
adapter.removeItem(update);
@ -150,15 +150,15 @@ public class HashtagFragment extends ListFragment implements TrendClickListener,
@Override
public void onTrendClick(Trend trend) {
public void onTrendClick(Hashtag hashtag) {
if (!isRefreshing()) {
Intent intent = new Intent(requireContext(), SearchActivity.class);
String name = trend.getName();
String name = hashtag.getName();
if (!name.startsWith("#") && !name.startsWith("\"") && !name.endsWith("\"")) {
name = "\"" + name + "\"";
intent.putExtra(SearchActivity.KEY_QUERY, name);
} else {
intent.putExtra(SearchActivity.KEY_DATA, trend);
intent.putExtra(SearchActivity.KEY_DATA, hashtag);
}
activityResultLauncher.launch(intent);
}

View File

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="20dp"
android:width="20dp"
android:viewportHeight="512"
android:viewportWidth="512">
<path
android:fillColor="#FFFFFF"
android:pathData="M411.826,289.391c0,86.061 -69.766,155.826 -155.826,155.826s-155.826,-69.766 -155.826,-155.826S169.939,133.565 256,133.565v66.783l100.174,-100.174L256,0v66.783c-122.943,0 -222.609,99.665 -222.609,222.609S133.057,512 256,512s222.609,-99.665 222.609,-222.609H411.826z" />
</vector>

View File

@ -7,8 +7,7 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center">
android:orientation="horizontal">
<TextView
android:id="@+id/item_domain_name"
@ -17,7 +16,7 @@
android:layout_margin="@dimen/item_domain_layout_margin"
android:textSize="@dimen/item_domain_text_size"
android:layout_weight="1"
android:lines="1" />
android:maxLines="2" />
<ImageButton
android:id="@+id/item_domain_delete"

View File

@ -18,7 +18,7 @@
android:id="@+id/listdetail_tab"
android:layout_width="match_parent"
android:layout_height="@dimen/tabselector_height"
app:viewpager="@id/page_hashtag_pager" />
app:viewpager="@id/listdetail_pager" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/listdetail_pager"

View File

@ -67,6 +67,7 @@
android:inputType="textMultiLine"
app:layout_constraintStart_toStartOf="@id/userlist_popup_background"
app:layout_constraintTop_toBottomOf="@id/list_edit_title"
app:layout_constraintBottom_toTopOf="@id/userlist_create_list"
app:layout_constraintEnd_toEndOf="@id/userlist_popup_background" />
<Button
@ -75,10 +76,10 @@
android:layout_height="@dimen/userlist_button_height"
android:paddingLeft="@dimen/userlist_button_padding"
android:paddingRight="@dimen/userlist_button_padding"
android:layout_marginEnd="@dimen/popup_userlist_background_margin"
android:layout_margin="@dimen/popup_userlist_background_margin"
android:text="@string/userlist_create"
app:layout_constraintStart_toStartOf="@id/userlist_popup_background"
app:layout_constraintTop_toBottomOf="@id/list_edit_descr"
app:layout_constraintBottom_toBottomOf="@id/userlist_popup_background"
app:layout_constraintEnd_toEndOf="@id/userlist_popup_background"
app:layout_constraintHorizontal_weight="3"
style="@style/FeedbackButton" />

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_hashtag_add"
android:title="@string/menu_hashtag_add"
android:icon="@drawable/plus"
app:actionViewClass="androidx.appcompat.widget.SearchView"
app:showAsAction="ifRoom|collapseActionView" />
</menu>

View File

@ -6,11 +6,9 @@
android:id="@+id/list_create"
android:icon="@drawable/new_list"
android:title="@string/menu_create_list"
android:visible="false"
app:showAsAction="always" />
<item
android:id="@+id/list_blocklists"
android:title="@string/menu_excluded_users"
android:visible="false" />
android:title="@string/menu_excluded_users" />
</menu>

View File

@ -13,20 +13,19 @@
android:id="@+id/menu_navigator_account"
android:title="@string/menu_select_account" />
<item
android:id="@+id/menu_navigator_filter"
android:title="@string/menu_open_filter" />
<item
android:id="@+id/menu_navigator_lists"
android:title="@string/menu_goto_lists" />
<item
android:id="@+id/menu_navigator_status"
android:title="@string/menu_status" />
<item
android:id="@+id/menu_navigator_hashtag"
android:title="@string/menu_hashtags" />
<item
android:id="@+id/menu_navigator_filter"
android:title="@string/menu_open_filter" />
<item
android:id="@+id/menu_navigator_status"
android:title="@string/menu_status" />
</menu>

View File

@ -3,16 +3,10 @@
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/menu_exclude_user"
android:id="@+id/menu_user_add"
android:title="@string/menu_exclude_user"
android:icon="@drawable/plus"
app:actionViewClass="androidx.appcompat.widget.SearchView"
app:showAsAction="ifRoom|collapseActionView" />
<item
android:id="@+id/menu_exclude_refresh"
android:title="@string/menu_refresh_exclude"
android:icon="@drawable/refresh"
app:showAsAction="ifRoom" />
</menu>

View File

@ -196,7 +196,7 @@
<string name="confirm_warning">Warnung</string>
<string name="confirm_proxy_bypass">Das Öffnen des Links umgeht die eingestellte Proxy-Verbindung. Fortsetzen?</string>
<string name="confirm_remove_account">Account aus der Liste entfernen?</string>
<string name="menu_select_account">Logins</string>
<string name="menu_select_account">Accounts</string>
<string name="menu_add_account">Account hinzufügen</string>
<string name="settings_rt_icon_color">Repost</string>
<string name="settings_follow_req_color">Anfrage Icon</string>
@ -211,9 +211,6 @@
<string name="menu_exclude_user">Nutzer ausschließen</string>
<string name="menu_search_filter">Ergebnisse filtern</string>
<string name="menu_hint_block_domain">domain.namen eingeben</string>
<string name="menu_refresh_exclude">Filterliste aktualisieren</string>
<string name="info_refreshing_exclude_list">aktualisiere Filterliste</string>
<string name="info_exclude_list_updated">Filterliste aktualisiert!</string>
<string name="menu_licenses">Lizenzen</string>
<string name="info_permission_write">Schreibrechte werden benötigt um Bilder zu speichern.</string>
<string name="info_permission_read">Leserechte werden benötigt um Bilder und Videos einzufügen.</string>

View File

@ -37,8 +37,6 @@
<string name="info_status_removed">Se eliminó el estado</string>
<string name="info_status_sent">Se compartió el estado</string>
<string name="info_location_pending">Solicitando ubicación, por favor espera</string>
<string name="info_refreshing_exclude_list">Actualizando la lista de exclusión</string>
<string name="info_exclude_list_updated">¡Se actualizó la lista de exclusión!</string>
<string name="info_permission_read">Se necesita permiso de lectura para acceder a imágenes y videos</string>
<string name="info_permission_location">Se necesita permiso de ubicación solo para adjuntar ubicación al estado</string>
<string name="info_permission_write">Se usa el permiso de escritura para guardar imágenes.</string>
@ -144,7 +142,6 @@
<string name="menu_hint_mute_user">Ingresa @nombre a silenciar</string>
<string name="menu_hint_block_user">Ingresa @nombre a bloquear</string>
<string name="menu_hint_block_domain">Ingresa nombre de dominio</string>
<string name="menu_refresh_exclude">Actualizar lista de exclusión</string>
<string name="menu_select_account">Accesos</string>
<string name="menu_add_account">Agregar cuenta</string>
<string name="menu_status_copy_text">Texto</string>

View File

@ -22,6 +22,11 @@
<integer-array name="list_tab_icons">
<item>@drawable/list</item>
<item>@drawable/user</item>
</integer-array>
<integer-array name="list_subscriber_tab_icons">
<item>@drawable/list</item>
<item>@drawable/user</item>
<item>@drawable/subscriber</item>
</integer-array>
@ -62,7 +67,6 @@
<integer-array name="userlist_tab_icons">
<item>@drawable/following</item>
<item>@drawable/follower</item>
</integer-array>
<integer-array name="userlist_hashtag_icons">

View File

@ -310,8 +310,8 @@
<!--dimens of item_domain.xml-->
<dimen name="item_domain_layout_margin">8dp</dimen>
<dimen name="item_domain_text_size">20sp</dimen>
<dimen name="item_domain_button_size">36dp</dimen>
<dimen name="item_domain_button_padding">7dp</dimen>
<dimen name="item_domain_button_size">20sp</dimen>
<dimen name="item_domain_button_padding">1dp</dimen>
<!--dimens of item_filter.xml-->
<dimen name="item_filter_title_textsize">18sp</dimen>

View File

@ -51,8 +51,6 @@
<string name="info_status_removed">Status removed</string>
<string name="info_status_sent">Status shared</string>
<string name="info_location_pending">requesting location, please wait</string>
<string name="info_refreshing_exclude_list">refreshing exclude list</string>
<string name="info_exclude_list_updated">exclude list updated!</string>
<string name="info_permission_read">Read permission needed to access images and videos.</string>
<string name="info_permission_location">Location permission only needed to attach location to a status</string>
<string name="info_permission_write">Write permission used to store images.</string>
@ -69,9 +67,7 @@
<string name="info_missing_host">please enter correct hostname</string>
<string name="info_database_cleared">Database cleared</string>
<string name="info_notification_dismiss">Notification dismissed</string>
<string name="info_hashtag_unfollowed">hashtag unfollowed</string>
<string name="info_domain_removed">domain removed from the list</string>
<string name="info_hashtag_followed">hashtag followed</string>
<string name="info_domain_blocked">domain blocked!</string>
<string name="info_webpush_update_progress">updating push configuration</string>
<string name="info_webpush_update">Push configuration updated</string>
@ -79,6 +75,9 @@
<string name="info_filter_updated">Filter updated</string>
<string name="info_filter_removed">Filter removed</string>
<string name="info_user_reported">User reported</string>
<string name="info_hashtag_featured">Hashtag featured</string>
<string name="info_hashtag_followed">Hashtag followed</string>
<string name="info_hashtag_unfollowed">Hashtag unfollowed</string>
<string name="info_status_reported">Status reported</string>
<string name="info_error">Error</string>
@ -165,12 +164,12 @@
<string name="menu_user_unblock">unblock</string>
<string name="menu_excluded_users">Blocklists</string>
<string name="menu_exclude_user">exclude user</string>
<string name="menu_hashtag_add">add hashtag</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>
<string name="menu_hint_block_domain">enter domain.name</string>
<string name="menu_refresh_exclude">refresh exclude list</string>
<string name="menu_select_account">Logins</string>
<string name="menu_select_account">Accounts</string>
<string name="menu_add_account">add account</string>
<string name="menu_status_copy_text">Text</string>
<string name="menu_media_link">Media link</string>