added hashtag remove button, database update, translation update, bug fix
This commit is contained in:
parent
774e3fa056
commit
fb90a7d99e
|
@ -330,10 +330,10 @@ public interface Connection {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param name name of the hashtag
|
* @param id of the featured hashtag
|
||||||
* @return updated hashtag information
|
* @return updated hashtag information
|
||||||
*/
|
*/
|
||||||
Hashtag unfeatureHashtag(String name) throws ConnectionException;
|
Hashtag unfeatureHashtag(long id) throws ConnectionException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* show current user's home timeline
|
* show current user's home timeline
|
||||||
|
|
|
@ -541,13 +541,9 @@ public class Mastodon implements Connection {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Hashtag unfeatureHashtag(String name) throws ConnectionException {
|
public Hashtag unfeatureHashtag(long id) throws ConnectionException {
|
||||||
try {
|
try {
|
||||||
if (name.startsWith("#"))
|
return createTag(delete(ENDPOINT_HASHTAG_FEATURE + "/" + id, new ArrayList<>()));
|
||||||
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) {
|
} catch (IOException e) {
|
||||||
throw new MastodonException(e);
|
throw new MastodonException(e);
|
||||||
}
|
}
|
||||||
|
@ -1466,7 +1462,9 @@ public class Mastodon implements Connection {
|
||||||
long[] cursors = getCursors(response);
|
long[] cursors = getCursors(response);
|
||||||
Trends result = new Trends(cursors[0], cursors[1]);
|
Trends result = new Trends(cursors[0], cursors[1]);
|
||||||
for (int i = 0; i < jsonArray.length(); i++) {
|
for (int i = 0; i < jsonArray.length(); i++) {
|
||||||
result.add(new MastodonHashtag(jsonArray.getJSONObject(i)));
|
MastodonHashtag item = new MastodonHashtag(jsonArray.getJSONObject(i));
|
||||||
|
item.setRank(i + 1);
|
||||||
|
result.add(item);
|
||||||
}
|
}
|
||||||
Collections.sort(result);
|
Collections.sort(result);
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -5,8 +5,8 @@ import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.nuclearfog.twidda.model.Location;
|
|
||||||
import org.nuclearfog.twidda.model.Hashtag;
|
import org.nuclearfog.twidda.model.Hashtag;
|
||||||
|
import org.nuclearfog.twidda.model.Location;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hashtag implementation used by Mastodon API
|
* Hashtag implementation used by Mastodon API
|
||||||
|
@ -20,12 +20,15 @@ public class MastodonHashtag implements Hashtag {
|
||||||
private int popularity;
|
private int popularity;
|
||||||
private String name;
|
private String name;
|
||||||
private boolean following;
|
private boolean following;
|
||||||
|
private long id;
|
||||||
|
private int rank;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param json trend json object
|
* @param json trend json object
|
||||||
*/
|
*/
|
||||||
public MastodonHashtag(JSONObject json) {
|
public MastodonHashtag(JSONObject json) {
|
||||||
JSONArray history = json.optJSONArray("history");
|
JSONArray history = json.optJSONArray("history");
|
||||||
|
String idStr = json.optString("id", "0");
|
||||||
name = '#' + json.optString("name", "");
|
name = '#' + json.optString("name", "");
|
||||||
following = json.optBoolean("following", false);
|
following = json.optBoolean("following", false);
|
||||||
if (history != null && history.length() > 0) {
|
if (history != null && history.length() > 0) {
|
||||||
|
@ -36,6 +39,17 @@ public class MastodonHashtag implements Hashtag {
|
||||||
} else {
|
} else {
|
||||||
popularity = json.optInt("statuses_count", 0);
|
popularity = json.optInt("statuses_count", 0);
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
id = Long.parseLong(idStr);
|
||||||
|
} catch (NumberFormatException exception) {
|
||||||
|
// proceed without ID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -53,7 +67,7 @@ public class MastodonHashtag implements Hashtag {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getRank() {
|
public int getRank() {
|
||||||
return -1;
|
return rank;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -68,6 +82,13 @@ public class MastodonHashtag implements Hashtag {
|
||||||
return following;
|
return following;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void setRank(int rank) {
|
||||||
|
this.rank = rank;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(@Nullable Object obj) {
|
public boolean equals(@Nullable Object obj) {
|
||||||
|
|
|
@ -15,7 +15,7 @@ import org.nuclearfog.twidda.model.Hashtag;
|
||||||
*
|
*
|
||||||
* @author nuclearfog
|
* @author nuclearfog
|
||||||
*/
|
*/
|
||||||
public class HashtagAction extends AsyncExecutor<HashtagAction.HashtagParam, HashtagAction.HashtagResult> {
|
public class HashtagAction extends AsyncExecutor<HashtagAction.HashtagActionParam, HashtagAction.HashtagActionResult> {
|
||||||
|
|
||||||
private Connection connection;
|
private Connection connection;
|
||||||
|
|
||||||
|
@ -28,41 +28,41 @@ public class HashtagAction extends AsyncExecutor<HashtagAction.HashtagParam, Has
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected HashtagResult doInBackground(@NonNull HashtagParam param) {
|
protected HashtagActionResult doInBackground(@NonNull HashtagActionParam param) {
|
||||||
try {
|
try {
|
||||||
switch (param.mode) {
|
switch (param.mode) {
|
||||||
case HashtagParam.LOAD:
|
case HashtagActionParam.LOAD:
|
||||||
Hashtag result = connection.showHashtag(param.name);
|
Hashtag result = connection.showHashtag(param.name);
|
||||||
return new HashtagResult(HashtagResult.LOAD, result, null);
|
return new HashtagActionResult(HashtagActionResult.LOAD, result, null);
|
||||||
|
|
||||||
case HashtagParam.FOLLOW:
|
case HashtagActionParam.FOLLOW:
|
||||||
result = connection.followHashtag(param.name);
|
result = connection.followHashtag(param.name);
|
||||||
return new HashtagResult(HashtagResult.FOLLOW, result, null);
|
return new HashtagActionResult(HashtagActionResult.FOLLOW, result, null);
|
||||||
|
|
||||||
case HashtagParam.UNFOLLOW:
|
case HashtagActionParam.UNFOLLOW:
|
||||||
result = connection.unfollowHashtag(param.name);
|
result = connection.unfollowHashtag(param.name);
|
||||||
return new HashtagResult(HashtagResult.UNFOLLOW, result, null);
|
return new HashtagActionResult(HashtagActionResult.UNFOLLOW, result, null);
|
||||||
|
|
||||||
case HashtagParam.FEATURE:
|
case HashtagActionParam.FEATURE:
|
||||||
result = connection.featureHashtag(param.name);
|
result = connection.featureHashtag(param.name);
|
||||||
return new HashtagResult(HashtagResult.FEATURE, result, null);
|
return new HashtagActionResult(HashtagActionResult.FEATURE, result, null);
|
||||||
|
|
||||||
case HashtagParam.UNFEATURE:
|
case HashtagActionParam.UNFEATURE:
|
||||||
result = connection.unfeatureHashtag(param.name);
|
result = connection.unfeatureHashtag(param.id);
|
||||||
return new HashtagResult(HashtagResult.UNFEATURE, result, null);
|
return new HashtagActionResult(HashtagActionResult.UNFEATURE, result, null);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
} catch (ConnectionException exception) {
|
} catch (ConnectionException exception) {
|
||||||
return new HashtagResult(HashtagResult.ERROR, null, exception);
|
return new HashtagActionResult(HashtagActionResult.ERROR, null, exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public static class HashtagParam {
|
public static class HashtagActionParam {
|
||||||
|
|
||||||
public static final int LOAD = 1;
|
public static final int LOAD = 1;
|
||||||
public static final int FOLLOW = 2;
|
public static final int FOLLOW = 2;
|
||||||
|
@ -72,17 +72,25 @@ public class HashtagAction extends AsyncExecutor<HashtagAction.HashtagParam, Has
|
||||||
|
|
||||||
final String name;
|
final String name;
|
||||||
final int mode;
|
final int mode;
|
||||||
|
final long id;
|
||||||
|
|
||||||
public HashtagParam(int mode, String name) {
|
public HashtagActionParam(int mode, String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.mode = mode;
|
this.mode = mode;
|
||||||
|
id = 0L;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashtagActionParam(int mode, String name, long id) {
|
||||||
|
this.name = name;
|
||||||
|
this.mode = mode;
|
||||||
|
this.id = id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public static class HashtagResult {
|
public static class HashtagActionResult {
|
||||||
|
|
||||||
public static final int ERROR = -1;
|
public static final int ERROR = -1;
|
||||||
public static final int LOAD = 10;
|
public static final int LOAD = 10;
|
||||||
|
@ -97,7 +105,7 @@ public class HashtagAction extends AsyncExecutor<HashtagAction.HashtagParam, Has
|
||||||
public final Hashtag hashtag;
|
public final Hashtag hashtag;
|
||||||
public final int mode;
|
public final int mode;
|
||||||
|
|
||||||
HashtagResult(int mode, @Nullable Hashtag hashtag, @Nullable ConnectionException exception) {
|
HashtagActionResult(int mode, @Nullable Hashtag hashtag, @Nullable ConnectionException exception) {
|
||||||
this.exception = exception;
|
this.exception = exception;
|
||||||
this.hashtag = hashtag;
|
this.hashtag = hashtag;
|
||||||
this.mode = mode;
|
this.mode = mode;
|
||||||
|
|
|
@ -18,7 +18,7 @@ import org.nuclearfog.twidda.ui.fragments.HashtagFragment;
|
||||||
* @author nuclearfog
|
* @author nuclearfog
|
||||||
* @see HashtagFragment
|
* @see HashtagFragment
|
||||||
*/
|
*/
|
||||||
public class TrendLoader extends AsyncExecutor<TrendLoader.TrendParameter, TrendLoader.TrendResult> {
|
public class HashtagLoader extends AsyncExecutor<HashtagLoader.HashtagLoaderParam, HashtagLoader.HashtagLoaderResult> {
|
||||||
|
|
||||||
private Connection connection;
|
private Connection connection;
|
||||||
private AppDatabase db;
|
private AppDatabase db;
|
||||||
|
@ -26,52 +26,52 @@ public class TrendLoader extends AsyncExecutor<TrendLoader.TrendParameter, Trend
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public TrendLoader(Context context) {
|
public HashtagLoader(Context context) {
|
||||||
connection = ConnectionManager.getDefaultConnection(context);
|
connection = ConnectionManager.getDefaultConnection(context);
|
||||||
db = new AppDatabase(context);
|
db = new AppDatabase(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected TrendResult doInBackground(@NonNull TrendParameter param) {
|
protected HashtagLoaderResult doInBackground(@NonNull HashtagLoaderParam param) {
|
||||||
try {
|
try {
|
||||||
switch (param.mode) {
|
switch (param.mode) {
|
||||||
case TrendParameter.POPULAR_OFFLINE:
|
case HashtagLoaderParam.POPULAR_OFFLINE:
|
||||||
Trends trends = db.getTrends();
|
Trends trends = db.getTrends();
|
||||||
if (!trends.isEmpty()) {
|
if (!trends.isEmpty()) {
|
||||||
return new TrendResult(TrendResult.POPULAR, trends, param.index, null);
|
return new HashtagLoaderResult(HashtagLoaderResult.POPULAR, trends, param.index, null);
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
|
|
||||||
case TrendParameter.POPULAR_ONLINE:
|
case HashtagLoaderParam.POPULAR_ONLINE:
|
||||||
trends = connection.getTrends();
|
trends = connection.getTrends();
|
||||||
db.saveTrends(trends);
|
db.saveTrends(trends);
|
||||||
return new TrendResult(TrendResult.POPULAR, trends, param.index, null);
|
return new HashtagLoaderResult(HashtagLoaderResult.POPULAR, trends, param.index, null);
|
||||||
|
|
||||||
case TrendParameter.SEARCH:
|
case HashtagLoaderParam.SEARCH:
|
||||||
trends = connection.searchHashtags(param.trend);
|
trends = connection.searchHashtags(param.trend);
|
||||||
return new TrendResult(TrendResult.SEARCH, trends, param.index, null);
|
return new HashtagLoaderResult(HashtagLoaderResult.SEARCH, trends, param.index, null);
|
||||||
|
|
||||||
case TrendParameter.FOLLOWING:
|
case HashtagLoaderParam.FOLLOWING:
|
||||||
trends = connection.showHashtagFollowing(param.cursor);
|
trends = connection.showHashtagFollowing(param.cursor);
|
||||||
return new TrendResult(TrendResult.FOLLOWING, trends, param.index, null);
|
return new HashtagLoaderResult(HashtagLoaderResult.FOLLOWING, trends, param.index, null);
|
||||||
|
|
||||||
case TrendParameter.FEATURING:
|
case HashtagLoaderParam.FEATURING:
|
||||||
trends = connection.showHashtagFeaturing();
|
trends = connection.showHashtagFeaturing();
|
||||||
return new TrendResult(TrendResult.FEATURING, trends, param.index, null);
|
return new HashtagLoaderResult(HashtagLoaderResult.FEATURING, trends, param.index, null);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
} catch (ConnectionException exception) {
|
} catch (ConnectionException exception) {
|
||||||
return new TrendResult(TrendResult.ERROR, null, param.index, exception);
|
return new HashtagLoaderResult(HashtagLoaderResult.ERROR, null, param.index, exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public static class TrendParameter {
|
public static class HashtagLoaderParam {
|
||||||
|
|
||||||
public static final int POPULAR_OFFLINE = 1;
|
public static final int POPULAR_OFFLINE = 1;
|
||||||
public static final int POPULAR_ONLINE = 2;
|
public static final int POPULAR_ONLINE = 2;
|
||||||
|
@ -86,7 +86,7 @@ public class TrendLoader extends AsyncExecutor<TrendLoader.TrendParameter, Trend
|
||||||
final int index;
|
final int index;
|
||||||
final long cursor;
|
final long cursor;
|
||||||
|
|
||||||
public TrendParameter(int mode, int index, String trend, long cursor) {
|
public HashtagLoaderParam(int mode, int index, String trend, long cursor) {
|
||||||
this.mode = mode;
|
this.mode = mode;
|
||||||
this.trend = trend;
|
this.trend = trend;
|
||||||
this.index = index;
|
this.index = index;
|
||||||
|
@ -97,7 +97,7 @@ public class TrendLoader extends AsyncExecutor<TrendLoader.TrendParameter, Trend
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public static class TrendResult {
|
public static class HashtagLoaderResult {
|
||||||
|
|
||||||
public static final int ERROR = -1;
|
public static final int ERROR = -1;
|
||||||
public static final int POPULAR = 20;
|
public static final int POPULAR = 20;
|
||||||
|
@ -112,7 +112,7 @@ public class TrendLoader extends AsyncExecutor<TrendLoader.TrendParameter, Trend
|
||||||
@Nullable
|
@Nullable
|
||||||
public final ConnectionException exception;
|
public final ConnectionException exception;
|
||||||
|
|
||||||
TrendResult(int mode, @Nullable Trends trends, int index, @Nullable ConnectionException exception) {
|
HashtagLoaderResult(int mode, @Nullable Trends trends, int index, @Nullable ConnectionException exception) {
|
||||||
this.trends = trends;
|
this.trends = trends;
|
||||||
this.exception = exception;
|
this.exception = exception;
|
||||||
this.index = index;
|
this.index = index;
|
|
@ -304,7 +304,7 @@ public class AppDatabase {
|
||||||
/**
|
/**
|
||||||
* select trends from trend table with given world ID
|
* select trends from trend table with given world ID
|
||||||
*/
|
*/
|
||||||
private static final String TREND_SELECT = HashtagTable.ID + "=?";
|
private static final String TREND_SELECT = HashtagTable.LOCATION + "=?";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* select status from status table matching ID
|
* select status from status table matching ID
|
||||||
|
@ -537,10 +537,11 @@ public class AppDatabase {
|
||||||
db.delete(HashtagTable.NAME, TREND_SELECT, args);
|
db.delete(HashtagTable.NAME, TREND_SELECT, args);
|
||||||
for (Hashtag hashtag : hashtags) {
|
for (Hashtag hashtag : hashtags) {
|
||||||
ContentValues column = new ContentValues(4);
|
ContentValues column = new ContentValues(4);
|
||||||
column.put(HashtagTable.ID, hashtag.getLocationId());
|
column.put(HashtagTable.LOCATION, hashtag.getLocationId());
|
||||||
column.put(HashtagTable.VOL, hashtag.getPopularity());
|
column.put(HashtagTable.VOL, hashtag.getPopularity());
|
||||||
column.put(HashtagTable.TREND, hashtag.getName());
|
column.put(HashtagTable.TREND, hashtag.getName());
|
||||||
column.put(HashtagTable.INDEX, hashtag.getRank());
|
column.put(HashtagTable.INDEX, hashtag.getRank());
|
||||||
|
column.put(HashtagTable.ID, hashtag.getId());
|
||||||
db.insert(HashtagTable.NAME, null, column);
|
db.insert(HashtagTable.NAME, null, column);
|
||||||
}
|
}
|
||||||
adapter.commit();
|
adapter.commit();
|
||||||
|
|
|
@ -20,7 +20,7 @@ public class DatabaseAdapter {
|
||||||
/**
|
/**
|
||||||
* database version
|
* database version
|
||||||
*/
|
*/
|
||||||
private static final int DB_VERSION = 20;
|
private static final int DB_VERSION = 21;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* database file name
|
* database file name
|
||||||
|
@ -78,6 +78,7 @@ public class DatabaseAdapter {
|
||||||
private static final String TABLE_TRENDS = "CREATE TABLE IF NOT EXISTS "
|
private static final String TABLE_TRENDS = "CREATE TABLE IF NOT EXISTS "
|
||||||
+ HashtagTable.NAME + "("
|
+ HashtagTable.NAME + "("
|
||||||
+ HashtagTable.ID + " INTEGER,"
|
+ HashtagTable.ID + " INTEGER,"
|
||||||
|
+ HashtagTable.LOCATION + " INTEGER,"
|
||||||
+ HashtagTable.INDEX + " INTEGER,"
|
+ HashtagTable.INDEX + " INTEGER,"
|
||||||
+ HashtagTable.VOL + " INTEGER,"
|
+ HashtagTable.VOL + " INTEGER,"
|
||||||
+ HashtagTable.TREND + " TEXT);";
|
+ HashtagTable.TREND + " TEXT);";
|
||||||
|
@ -306,6 +307,11 @@ public class DatabaseAdapter {
|
||||||
*/
|
*/
|
||||||
private static final String UPDATE_MEDIA_ADD_BLUR_HASH = "ALTER TABLE " + MediaTable.NAME + " ADD " + MediaTable.BLUR + " TEXT;";
|
private static final String UPDATE_MEDIA_ADD_BLUR_HASH = "ALTER TABLE " + MediaTable.NAME + " ADD " + MediaTable.BLUR + " TEXT;";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* add mediatable description
|
||||||
|
*/
|
||||||
|
private static final String UPDATE_HASHTAG_ADD_ID = "ALTER TABLE " + HashtagTable.NAME + " ADD " + HashtagTable.ID + " INTEGER;";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* singleton instance
|
* singleton instance
|
||||||
*/
|
*/
|
||||||
|
@ -407,9 +413,13 @@ public class DatabaseAdapter {
|
||||||
db.execSQL(UPDATE_MEDIA_ADD_BLUR_HASH);
|
db.execSQL(UPDATE_MEDIA_ADD_BLUR_HASH);
|
||||||
db.setVersion(19);
|
db.setVersion(19);
|
||||||
}
|
}
|
||||||
if (db.getVersion() < DB_VERSION) {
|
if (db.getVersion() < 20) {
|
||||||
db.delete(EmojiTable.NAME, null, null);
|
db.delete(EmojiTable.NAME, null, null);
|
||||||
db.execSQL(TABLE_EMOJI);
|
db.execSQL(TABLE_EMOJI);
|
||||||
|
db.setVersion(20);
|
||||||
|
}
|
||||||
|
if (db.getVersion() < DB_VERSION) {
|
||||||
|
db.execSQL(UPDATE_HASHTAG_ADD_ID);
|
||||||
db.setVersion(DB_VERSION);
|
db.setVersion(DB_VERSION);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -701,10 +711,15 @@ public class DatabaseAdapter {
|
||||||
*/
|
*/
|
||||||
String NAME = "trend";
|
String NAME = "trend";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* id of the hashtag
|
||||||
|
*/
|
||||||
|
String ID = "id";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Location ID
|
* Location ID
|
||||||
*/
|
*/
|
||||||
String ID = "woeID";
|
String LOCATION = "woeID";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* rank of the hashtag
|
* rank of the hashtag
|
||||||
|
|
|
@ -20,12 +20,13 @@ public class DatabaseHashtag implements Hashtag, HashtagTable {
|
||||||
/**
|
/**
|
||||||
* SQLite columns
|
* SQLite columns
|
||||||
*/
|
*/
|
||||||
public static final String[] COLUMNS = {TREND, VOL, INDEX, ID};
|
public static final String[] COLUMNS = {TREND, VOL, INDEX, LOCATION, ID};
|
||||||
|
|
||||||
private String name = "";
|
private String name = "";
|
||||||
private int popularity;
|
private int popularity;
|
||||||
private int rank;
|
private int rank;
|
||||||
private long id;
|
private long id;
|
||||||
|
private long locationId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param cursor database cursor using this {@link #COLUMNS} projection
|
* @param cursor database cursor using this {@link #COLUMNS} projection
|
||||||
|
@ -34,13 +35,20 @@ public class DatabaseHashtag implements Hashtag, HashtagTable {
|
||||||
String name = cursor.getString(0);
|
String name = cursor.getString(0);
|
||||||
popularity = cursor.getInt(1);
|
popularity = cursor.getInt(1);
|
||||||
rank = cursor.getInt(2);
|
rank = cursor.getInt(2);
|
||||||
id = cursor.getLong(3);
|
locationId = cursor.getLong(3);
|
||||||
|
id = cursor.getLong(4);
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
|
@ -49,7 +57,7 @@ public class DatabaseHashtag implements Hashtag, HashtagTable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getLocationId() {
|
public long getLocationId() {
|
||||||
return id;
|
return locationId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -83,6 +91,6 @@ public class DatabaseHashtag implements Hashtag, HashtagTable {
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "name=\"" + getName() + "\"";
|
return "name=\"" + getName() + "\" rank=" + rank;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -10,27 +10,32 @@ import java.io.Serializable;
|
||||||
public interface Hashtag extends Serializable, Comparable<Hashtag> {
|
public interface Hashtag extends Serializable, Comparable<Hashtag> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return trend name
|
* @return hashtag name
|
||||||
*/
|
*/
|
||||||
String getName();
|
String getName();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return ID of the trend location
|
* @return trend ID if any
|
||||||
|
*/
|
||||||
|
long getId();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return hashtag ID
|
||||||
*/
|
*/
|
||||||
long getLocationId();
|
long getLocationId();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return rank of the trend
|
* @return rank of the hashtag if any
|
||||||
*/
|
*/
|
||||||
int getRank();
|
int getRank();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return popularity of the trend
|
* @return popularity of the hashtag
|
||||||
*/
|
*/
|
||||||
int getPopularity();
|
int getPopularity();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if current user follows trend (hashtag)
|
* @return true if current user follows hashtag
|
||||||
*/
|
*/
|
||||||
boolean following();
|
boolean following();
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,8 @@ import androidx.viewpager2.widget.ViewPager2;
|
||||||
import org.nuclearfog.twidda.R;
|
import org.nuclearfog.twidda.R;
|
||||||
import org.nuclearfog.twidda.backend.async.AsyncExecutor.AsyncCallback;
|
import org.nuclearfog.twidda.backend.async.AsyncExecutor.AsyncCallback;
|
||||||
import org.nuclearfog.twidda.backend.async.HashtagAction;
|
import org.nuclearfog.twidda.backend.async.HashtagAction;
|
||||||
import org.nuclearfog.twidda.backend.async.HashtagAction.HashtagParam;
|
import org.nuclearfog.twidda.backend.async.HashtagAction.HashtagActionParam;
|
||||||
import org.nuclearfog.twidda.backend.async.HashtagAction.HashtagResult;
|
import org.nuclearfog.twidda.backend.async.HashtagAction.HashtagActionResult;
|
||||||
import org.nuclearfog.twidda.backend.utils.AppStyles;
|
import org.nuclearfog.twidda.backend.utils.AppStyles;
|
||||||
import org.nuclearfog.twidda.config.GlobalSettings;
|
import org.nuclearfog.twidda.config.GlobalSettings;
|
||||||
import org.nuclearfog.twidda.ui.adapter.viewpager.HashtagAdapter;
|
import org.nuclearfog.twidda.ui.adapter.viewpager.HashtagAdapter;
|
||||||
|
@ -30,7 +30,7 @@ import org.nuclearfog.twidda.ui.views.TabSelector.OnTabSelectedListener;
|
||||||
*
|
*
|
||||||
* @author nuclearfog
|
* @author nuclearfog
|
||||||
*/
|
*/
|
||||||
public class HashtagActivity extends AppCompatActivity implements SearchView.OnQueryTextListener, OnTabSelectedListener, AsyncCallback<HashtagResult> {
|
public class HashtagActivity extends AppCompatActivity implements SearchView.OnQueryTextListener, OnTabSelectedListener, AsyncCallback<HashtagActionResult> {
|
||||||
|
|
||||||
private GlobalSettings settings;
|
private GlobalSettings settings;
|
||||||
private HashtagAction hashtagAction;
|
private HashtagAction hashtagAction;
|
||||||
|
@ -90,11 +90,11 @@ public class HashtagActivity extends AppCompatActivity implements SearchView.OnQ
|
||||||
public boolean onQueryTextSubmit(String query) {
|
public boolean onQueryTextSubmit(String query) {
|
||||||
if (hashtagAction.isIdle()) {
|
if (hashtagAction.isIdle()) {
|
||||||
if (viewPager.getCurrentItem() == 0) {
|
if (viewPager.getCurrentItem() == 0) {
|
||||||
HashtagParam param = new HashtagParam(HashtagParam.FOLLOW, query);
|
HashtagActionParam param = new HashtagActionParam(HashtagActionParam.FOLLOW, query);
|
||||||
hashtagAction.execute(param, this);
|
hashtagAction.execute(param, this);
|
||||||
return true;
|
return true;
|
||||||
} else if (viewPager.getCurrentItem() == 1) {
|
} else if (viewPager.getCurrentItem() == 1) {
|
||||||
HashtagParam param = new HashtagParam(HashtagParam.FEATURE, query);
|
HashtagActionParam param = new HashtagActionParam(HashtagActionParam.FEATURE, query);
|
||||||
hashtagAction.execute(param, this);
|
hashtagAction.execute(param, this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -110,21 +110,21 @@ public class HashtagActivity extends AppCompatActivity implements SearchView.OnQ
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResult(@NonNull HashtagResult result) {
|
public void onResult(@NonNull HashtagActionResult result) {
|
||||||
switch (result.mode) {
|
switch (result.mode) {
|
||||||
case HashtagResult.FEATURE:
|
case HashtagActionResult.FEATURE:
|
||||||
Toast.makeText(getApplicationContext(), R.string.info_hashtag_featured, Toast.LENGTH_SHORT).show();
|
Toast.makeText(getApplicationContext(), R.string.info_hashtag_featured, Toast.LENGTH_SHORT).show();
|
||||||
adapter.notifySettingsChanged();
|
adapter.notifySettingsChanged();
|
||||||
invalidateOptionsMenu();
|
invalidateOptionsMenu();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HashtagResult.FOLLOW:
|
case HashtagActionResult.FOLLOW:
|
||||||
Toast.makeText(getApplicationContext(), R.string.info_hashtag_followed, Toast.LENGTH_SHORT).show();
|
Toast.makeText(getApplicationContext(), R.string.info_hashtag_followed, Toast.LENGTH_SHORT).show();
|
||||||
adapter.notifySettingsChanged();
|
adapter.notifySettingsChanged();
|
||||||
invalidateOptionsMenu();
|
invalidateOptionsMenu();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HashtagResult.ERROR:
|
case HashtagActionResult.ERROR:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,8 +22,8 @@ import androidx.viewpager2.widget.ViewPager2;
|
||||||
import org.nuclearfog.twidda.R;
|
import org.nuclearfog.twidda.R;
|
||||||
import org.nuclearfog.twidda.backend.async.AsyncExecutor.AsyncCallback;
|
import org.nuclearfog.twidda.backend.async.AsyncExecutor.AsyncCallback;
|
||||||
import org.nuclearfog.twidda.backend.async.HashtagAction;
|
import org.nuclearfog.twidda.backend.async.HashtagAction;
|
||||||
import org.nuclearfog.twidda.backend.async.HashtagAction.HashtagParam;
|
import org.nuclearfog.twidda.backend.async.HashtagAction.HashtagActionParam;
|
||||||
import org.nuclearfog.twidda.backend.async.HashtagAction.HashtagResult;
|
import org.nuclearfog.twidda.backend.async.HashtagAction.HashtagActionResult;
|
||||||
import org.nuclearfog.twidda.backend.utils.AppStyles;
|
import org.nuclearfog.twidda.backend.utils.AppStyles;
|
||||||
import org.nuclearfog.twidda.backend.utils.ErrorUtils;
|
import org.nuclearfog.twidda.backend.utils.ErrorUtils;
|
||||||
import org.nuclearfog.twidda.config.GlobalSettings;
|
import org.nuclearfog.twidda.config.GlobalSettings;
|
||||||
|
@ -39,7 +39,7 @@ import java.io.Serializable;
|
||||||
*
|
*
|
||||||
* @author nuclearfog
|
* @author nuclearfog
|
||||||
*/
|
*/
|
||||||
public class SearchActivity extends AppCompatActivity implements OnClickListener, OnTabSelectedListener, OnQueryTextListener, AsyncCallback<HashtagResult> {
|
public class SearchActivity extends AppCompatActivity implements OnClickListener, OnTabSelectedListener, OnQueryTextListener, AsyncCallback<HashtagActionResult> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Key for the search query, required
|
* Key for the search query, required
|
||||||
|
@ -96,7 +96,7 @@ public class SearchActivity extends AppCompatActivity implements OnClickListener
|
||||||
} else if (query != null) {
|
} else if (query != null) {
|
||||||
search = query;
|
search = query;
|
||||||
if (search.startsWith("#") && search.matches("\\S+")) {
|
if (search.startsWith("#") && search.matches("\\S+")) {
|
||||||
HashtagParam param = new HashtagParam(HashtagParam.LOAD, search);
|
HashtagActionParam param = new HashtagActionParam(HashtagActionParam.LOAD, search);
|
||||||
hashtagAction.execute(param, this);
|
hashtagAction.execute(param, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -207,11 +207,11 @@ public class SearchActivity extends AppCompatActivity implements OnClickListener
|
||||||
// follow/unfollow hashtag
|
// follow/unfollow hashtag
|
||||||
else if (item.getItemId() == R.id.search_hashtag) {
|
else if (item.getItemId() == R.id.search_hashtag) {
|
||||||
if (hashtag != null && hashtagAction.isIdle()) {
|
if (hashtag != null && hashtagAction.isIdle()) {
|
||||||
HashtagParam param;
|
HashtagActionParam param;
|
||||||
if (hashtag.following())
|
if (hashtag.following())
|
||||||
param = new HashtagParam(HashtagParam.UNFOLLOW, hashtag.getName());
|
param = new HashtagActionParam(HashtagActionParam.UNFOLLOW, hashtag.getName());
|
||||||
else
|
else
|
||||||
param = new HashtagParam(HashtagParam.FOLLOW, hashtag.getName());
|
param = new HashtagActionParam(HashtagActionParam.FOLLOW, hashtag.getName());
|
||||||
hashtagAction.execute(param, this);
|
hashtagAction.execute(param, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -258,21 +258,21 @@ public class SearchActivity extends AppCompatActivity implements OnClickListener
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResult(@NonNull HashtagResult result) {
|
public void onResult(@NonNull HashtagActionResult result) {
|
||||||
if (result.hashtag != null) {
|
if (result.hashtag != null) {
|
||||||
this.hashtag = result.hashtag;
|
this.hashtag = result.hashtag;
|
||||||
invalidateMenu();
|
invalidateMenu();
|
||||||
}
|
}
|
||||||
switch (result.mode) {
|
switch (result.mode) {
|
||||||
case HashtagResult.FOLLOW:
|
case HashtagActionResult.FOLLOW:
|
||||||
Toast.makeText(getApplicationContext(), R.string.info_hashtag_followed, Toast.LENGTH_SHORT).show();
|
Toast.makeText(getApplicationContext(), R.string.info_hashtag_followed, Toast.LENGTH_SHORT).show();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HashtagResult.UNFOLLOW:
|
case HashtagActionResult.UNFOLLOW:
|
||||||
Toast.makeText(getApplicationContext(), R.string.info_hashtag_unfollowed, Toast.LENGTH_SHORT).show();
|
Toast.makeText(getApplicationContext(), R.string.info_hashtag_unfollowed, Toast.LENGTH_SHORT).show();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HashtagResult.ERROR:
|
case HashtagActionResult.ERROR:
|
||||||
ErrorUtils.showErrorMessage(this, result.exception);
|
ErrorUtils.showErrorMessage(this, result.exception);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import org.nuclearfog.twidda.model.Hashtag;
|
||||||
import org.nuclearfog.twidda.model.lists.Trends;
|
import org.nuclearfog.twidda.model.lists.Trends;
|
||||||
import org.nuclearfog.twidda.ui.adapter.recyclerview.holder.OnHolderClickListener;
|
import org.nuclearfog.twidda.ui.adapter.recyclerview.holder.OnHolderClickListener;
|
||||||
import org.nuclearfog.twidda.ui.adapter.recyclerview.holder.PlaceHolder;
|
import org.nuclearfog.twidda.ui.adapter.recyclerview.holder.PlaceHolder;
|
||||||
import org.nuclearfog.twidda.ui.adapter.recyclerview.holder.TrendHolder;
|
import org.nuclearfog.twidda.ui.adapter.recyclerview.holder.HashtagHolder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* custom {@link androidx.recyclerview.widget.RecyclerView} adapter implementation to show trends
|
* custom {@link androidx.recyclerview.widget.RecyclerView} adapter implementation to show trends
|
||||||
|
@ -18,7 +18,7 @@ import org.nuclearfog.twidda.ui.adapter.recyclerview.holder.TrendHolder;
|
||||||
* @author nuclearfog
|
* @author nuclearfog
|
||||||
* @see org.nuclearfog.twidda.ui.fragments.HashtagFragment
|
* @see org.nuclearfog.twidda.ui.fragments.HashtagFragment
|
||||||
*/
|
*/
|
||||||
public class TrendAdapter extends Adapter<ViewHolder> implements OnHolderClickListener {
|
public class HashtagAdapter extends Adapter<ViewHolder> implements OnHolderClickListener {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "index" used to replace the whole list with new items
|
* "index" used to replace the whole list with new items
|
||||||
|
@ -31,15 +31,16 @@ public class TrendAdapter extends Adapter<ViewHolder> implements OnHolderClickLi
|
||||||
|
|
||||||
private static final int NO_LOADING = -1;
|
private static final int NO_LOADING = -1;
|
||||||
|
|
||||||
private TrendClickListener itemClickListener;
|
private OnHashtagClickListener itemClickListener;
|
||||||
|
|
||||||
private Trends items = new Trends();
|
private Trends items = new Trends();
|
||||||
private int loadingIndex = NO_LOADING;
|
private int loadingIndex = NO_LOADING;
|
||||||
|
private boolean enableDelete = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param itemClickListener Listener for item click
|
* @param itemClickListener Listener for item click
|
||||||
*/
|
*/
|
||||||
public TrendAdapter(TrendClickListener itemClickListener) {
|
public HashtagAdapter(OnHashtagClickListener itemClickListener) {
|
||||||
this.itemClickListener = itemClickListener;
|
this.itemClickListener = itemClickListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +63,7 @@ public class TrendAdapter extends Adapter<ViewHolder> implements OnHolderClickLi
|
||||||
@Override
|
@Override
|
||||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
if (viewType == TYPE_TREND) {
|
if (viewType == TYPE_TREND) {
|
||||||
return new TrendHolder(parent, this);
|
return new HashtagHolder(parent, this, enableDelete);
|
||||||
} else {
|
} else {
|
||||||
return new PlaceHolder(parent, this, false);
|
return new PlaceHolder(parent, this, false);
|
||||||
}
|
}
|
||||||
|
@ -71,8 +72,8 @@ public class TrendAdapter extends Adapter<ViewHolder> implements OnHolderClickLi
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull ViewHolder vh, int index) {
|
public void onBindViewHolder(@NonNull ViewHolder vh, int index) {
|
||||||
if (vh instanceof TrendHolder) {
|
if (vh instanceof HashtagHolder) {
|
||||||
TrendHolder holder = (TrendHolder) vh;
|
HashtagHolder holder = (HashtagHolder) vh;
|
||||||
Hashtag hashtag = items.get(index);
|
Hashtag hashtag = items.get(index);
|
||||||
if (hashtag != null) {
|
if (hashtag != null) {
|
||||||
holder.setContent(hashtag, index);
|
holder.setContent(hashtag, index);
|
||||||
|
@ -86,7 +87,11 @@ public class TrendAdapter extends Adapter<ViewHolder> implements OnHolderClickLi
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onItemClick(int position, int type, int... extras) {
|
public void onItemClick(int position, int type, int... extras) {
|
||||||
itemClickListener.onTrendClick(items.get(position));
|
if (type == HASHTAG_CLICK) {
|
||||||
|
itemClickListener.onHashtagClick(items.get(position), OnHashtagClickListener.SELECT);
|
||||||
|
} else if (type == HASHTAG_REMOVE) {
|
||||||
|
itemClickListener.onHashtagClick(items.get(position), OnHashtagClickListener.REMOVE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -177,18 +182,32 @@ public class TrendAdapter extends Adapter<ViewHolder> implements OnHolderClickLi
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listener for trend list
|
*
|
||||||
*/
|
*/
|
||||||
public interface TrendClickListener {
|
public void enableDelete() {
|
||||||
|
enableDelete = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listener for hashtag list
|
||||||
|
*/
|
||||||
|
public interface OnHashtagClickListener {
|
||||||
|
|
||||||
|
int SELECT = 1;
|
||||||
|
|
||||||
|
int REMOVE = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* called when a trend item is clicked
|
* called when a trend item is clicked
|
||||||
*
|
*
|
||||||
* @param hashtag trend name
|
* @param hashtag trend name
|
||||||
|
* @param action action to take {@link #SELECT,#REMOVE}
|
||||||
*/
|
*/
|
||||||
void onTrendClick(Hashtag hashtag);
|
void onHashtagClick(Hashtag hashtag, int action);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
boolean onPlaceholderClick(long cursor, int index);
|
boolean onPlaceholderClick(long cursor, int index);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -17,26 +17,28 @@ import org.nuclearfog.twidda.backend.utils.AppStyles;
|
||||||
import org.nuclearfog.twidda.backend.utils.StringUtils;
|
import org.nuclearfog.twidda.backend.utils.StringUtils;
|
||||||
import org.nuclearfog.twidda.config.GlobalSettings;
|
import org.nuclearfog.twidda.config.GlobalSettings;
|
||||||
import org.nuclearfog.twidda.model.Hashtag;
|
import org.nuclearfog.twidda.model.Hashtag;
|
||||||
|
import org.nuclearfog.twidda.ui.adapter.recyclerview.HashtagAdapter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ViewHolder for a trend item
|
* ViewHolder for a trend item
|
||||||
*
|
*
|
||||||
* @author nuclearfog
|
* @author nuclearfog
|
||||||
* @see org.nuclearfog.twidda.ui.adapter.recyclerview.TrendAdapter
|
* @see HashtagAdapter
|
||||||
*/
|
*/
|
||||||
public class TrendHolder extends ViewHolder implements OnClickListener {
|
public class HashtagHolder extends ViewHolder implements OnClickListener {
|
||||||
|
|
||||||
private TextView name, rank, vol;
|
private TextView name, rank, vol;
|
||||||
|
|
||||||
private OnHolderClickListener listener;
|
private OnHolderClickListener listener;
|
||||||
|
|
||||||
|
|
||||||
public TrendHolder(ViewGroup parent, OnHolderClickListener listener) {
|
public HashtagHolder(ViewGroup parent, OnHolderClickListener listener, boolean enableRemove) {
|
||||||
super(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_trend, parent, false));
|
super(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_hashtag, parent, false));
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
|
|
||||||
CardView background = (CardView) itemView;
|
CardView background = (CardView) itemView;
|
||||||
ViewGroup container = itemView.findViewById(R.id.item_trend_container);
|
ViewGroup container = itemView.findViewById(R.id.item_trend_container);
|
||||||
|
View btnRemove = itemView.findViewById(R.id.item_trend_delete_button);
|
||||||
rank = itemView.findViewById(R.id.item_trend_rank);
|
rank = itemView.findViewById(R.id.item_trend_rank);
|
||||||
name = itemView.findViewById(R.id.item_trend_name);
|
name = itemView.findViewById(R.id.item_trend_name);
|
||||||
vol = itemView.findViewById(R.id.item_trend_vol);
|
vol = itemView.findViewById(R.id.item_trend_vol);
|
||||||
|
@ -44,16 +46,26 @@ public class TrendHolder extends ViewHolder implements OnClickListener {
|
||||||
GlobalSettings settings = GlobalSettings.get(parent.getContext());
|
GlobalSettings settings = GlobalSettings.get(parent.getContext());
|
||||||
AppStyles.setTheme(container, Color.TRANSPARENT);
|
AppStyles.setTheme(container, Color.TRANSPARENT);
|
||||||
background.setCardBackgroundColor(settings.getCardColor());
|
background.setCardBackgroundColor(settings.getCardColor());
|
||||||
|
if (enableRemove) {
|
||||||
|
btnRemove.setVisibility(View.VISIBLE);
|
||||||
|
} else {
|
||||||
|
btnRemove.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
itemView.setOnClickListener(this);
|
itemView.setOnClickListener(this);
|
||||||
|
btnRemove.setOnClickListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
if (v == itemView) {
|
int position = getLayoutPosition();
|
||||||
int position = getLayoutPosition();
|
if (v.getId() == R.id.item_trend_delete_button) {
|
||||||
if (position != RecyclerView.NO_POSITION) {
|
if (position != RecyclerView.NO_POSITION) {
|
||||||
listener.onItemClick(position, OnHolderClickListener.NO_TYPE);
|
listener.onItemClick(position, OnHolderClickListener.HASHTAG_REMOVE);
|
||||||
|
}
|
||||||
|
} else if (v == itemView) {
|
||||||
|
if (position != RecyclerView.NO_POSITION) {
|
||||||
|
listener.onItemClick(position, OnHolderClickListener.HASHTAG_CLICK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -45,6 +45,10 @@ public interface OnHolderClickListener {
|
||||||
|
|
||||||
int FILTER_REMOVE = 23;
|
int FILTER_REMOVE = 23;
|
||||||
|
|
||||||
|
int HASHTAG_CLICK = 24;
|
||||||
|
|
||||||
|
int HASHTAG_REMOVE = 25;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* called when an item was clicked
|
* called when an item was clicked
|
||||||
*
|
*
|
||||||
|
|
|
@ -84,7 +84,7 @@ public class UserHolder extends ViewHolder implements OnClickListener, AsyncCall
|
||||||
profileImg = itemView.findViewById(R.id.item_user_profile);
|
profileImg = itemView.findViewById(R.id.item_user_profile);
|
||||||
verifyIcon = itemView.findViewById(R.id.item_user_verified);
|
verifyIcon = itemView.findViewById(R.id.item_user_verified);
|
||||||
lockedIcon = itemView.findViewById(R.id.item_user_private);
|
lockedIcon = itemView.findViewById(R.id.item_user_private);
|
||||||
delete = itemView.findViewById(R.id.item_user_delete_buton);
|
delete = itemView.findViewById(R.id.item_user_delete_button);
|
||||||
placeholder = new ColorDrawable(EMPTY_COLOR);
|
placeholder = new ColorDrawable(EMPTY_COLOR);
|
||||||
|
|
||||||
AppStyles.setTheme(container, Color.TRANSPARENT);
|
AppStyles.setTheme(container, Color.TRANSPARENT);
|
||||||
|
|
|
@ -134,6 +134,16 @@ public class ConfirmDialog extends Dialog implements OnClickListener {
|
||||||
*/
|
*/
|
||||||
public static final int CONTINUE_BROWSER = 627;
|
public static final int CONTINUE_BROWSER = 627;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static final int UNFOLLOW_HASHTAG = 628;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static final int UNFEATURE_HASHTAG = 629;
|
||||||
|
|
||||||
|
|
||||||
private TextView title, message, remember_label;
|
private TextView title, message, remember_label;
|
||||||
private Button confirm, cancel;
|
private Button confirm, cancel;
|
||||||
|
@ -275,6 +285,14 @@ public class ConfirmDialog extends Dialog implements OnClickListener {
|
||||||
titleRes = R.string.confirm_warning;
|
titleRes = R.string.confirm_warning;
|
||||||
messageRes = R.string.confirm_proxy_bypass;
|
messageRes = R.string.confirm_proxy_bypass;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case UNFOLLOW_HASHTAG:
|
||||||
|
messageRes = R.string.confirm_hashtag_unfollow;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UNFEATURE_HASHTAG:
|
||||||
|
messageRes = R.string.confirm_hashtag_unfeature;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
// setup title
|
// setup title
|
||||||
title.setVisibility(titleVis);
|
title.setVisibility(titleVis);
|
||||||
|
|
|
@ -3,6 +3,7 @@ package org.nuclearfog.twidda.ui.fragments;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.activity.result.ActivityResult;
|
import androidx.activity.result.ActivityResult;
|
||||||
import androidx.activity.result.ActivityResultCallback;
|
import androidx.activity.result.ActivityResultCallback;
|
||||||
|
@ -11,16 +12,21 @@ import androidx.activity.result.contract.ActivityResultContracts;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.nuclearfog.twidda.R;
|
||||||
import org.nuclearfog.twidda.backend.async.AsyncExecutor.AsyncCallback;
|
import org.nuclearfog.twidda.backend.async.AsyncExecutor.AsyncCallback;
|
||||||
import org.nuclearfog.twidda.backend.async.TrendLoader;
|
import org.nuclearfog.twidda.backend.async.HashtagAction;
|
||||||
import org.nuclearfog.twidda.backend.async.TrendLoader.TrendParameter;
|
import org.nuclearfog.twidda.backend.async.HashtagAction.HashtagActionParam;
|
||||||
import org.nuclearfog.twidda.backend.async.TrendLoader.TrendResult;
|
import org.nuclearfog.twidda.backend.async.HashtagAction.HashtagActionResult;
|
||||||
|
import org.nuclearfog.twidda.backend.async.HashtagLoader;
|
||||||
|
import org.nuclearfog.twidda.backend.async.HashtagLoader.HashtagLoaderParam;
|
||||||
|
import org.nuclearfog.twidda.backend.async.HashtagLoader.HashtagLoaderResult;
|
||||||
import org.nuclearfog.twidda.backend.utils.ErrorUtils;
|
import org.nuclearfog.twidda.backend.utils.ErrorUtils;
|
||||||
import org.nuclearfog.twidda.model.Hashtag;
|
import org.nuclearfog.twidda.model.Hashtag;
|
||||||
import org.nuclearfog.twidda.model.lists.Trends;
|
import org.nuclearfog.twidda.model.lists.Trends;
|
||||||
import org.nuclearfog.twidda.ui.activities.SearchActivity;
|
import org.nuclearfog.twidda.ui.activities.SearchActivity;
|
||||||
import org.nuclearfog.twidda.ui.adapter.recyclerview.TrendAdapter;
|
import org.nuclearfog.twidda.ui.adapter.recyclerview.HashtagAdapter;
|
||||||
import org.nuclearfog.twidda.ui.adapter.recyclerview.TrendAdapter.TrendClickListener;
|
import org.nuclearfog.twidda.ui.adapter.recyclerview.HashtagAdapter.OnHashtagClickListener;
|
||||||
|
import org.nuclearfog.twidda.ui.dialogs.ConfirmDialog;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@ -29,7 +35,7 @@ import java.io.Serializable;
|
||||||
*
|
*
|
||||||
* @author nuclearfog
|
* @author nuclearfog
|
||||||
*/
|
*/
|
||||||
public class HashtagFragment extends ListFragment implements TrendClickListener, AsyncCallback<TrendResult>, ActivityResultCallback<ActivityResult> {
|
public class HashtagFragment extends ListFragment implements OnHashtagClickListener, ActivityResultCallback<ActivityResult>, ConfirmDialog.OnConfirmListener {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* setup fragment to show popular trends of an instance/location
|
* setup fragment to show popular trends of an instance/location
|
||||||
|
@ -72,18 +78,26 @@ public class HashtagFragment extends ListFragment implements TrendClickListener,
|
||||||
|
|
||||||
private ActivityResultLauncher<Intent> activityResultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), this);
|
private ActivityResultLauncher<Intent> activityResultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), this);
|
||||||
|
|
||||||
private TrendLoader trendLoader;
|
private AsyncCallback<HashtagActionResult> hashtagActionCallback = this::onHashtagActionResult;
|
||||||
private TrendAdapter adapter;
|
private AsyncCallback<HashtagLoaderResult> hashtagLoaderCallback = this::onHashtagLoaderResult;
|
||||||
|
|
||||||
|
private HashtagLoader hashtagLoader;
|
||||||
|
private HashtagAction hashtagAction;
|
||||||
|
private HashtagAdapter adapter;
|
||||||
|
private ConfirmDialog confirmDialog;
|
||||||
|
|
||||||
private int mode = 0;
|
private int mode = 0;
|
||||||
private String search = "";
|
private String search = "";
|
||||||
|
private Hashtag selection;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||||
super.onViewCreated(view, savedInstanceState);
|
super.onViewCreated(view, savedInstanceState);
|
||||||
adapter = new TrendAdapter(this);
|
adapter = new HashtagAdapter(this);
|
||||||
trendLoader = new TrendLoader(requireContext());
|
hashtagLoader = new HashtagLoader(requireContext());
|
||||||
|
hashtagAction = new HashtagAction(requireContext());
|
||||||
|
confirmDialog = new ConfirmDialog(requireActivity(), this);
|
||||||
setAdapter(adapter);
|
setAdapter(adapter);
|
||||||
|
|
||||||
Bundle args = getArguments();
|
Bundle args = getArguments();
|
||||||
|
@ -91,15 +105,18 @@ public class HashtagFragment extends ListFragment implements TrendClickListener,
|
||||||
search = args.getString(KEY_SEARCH, "");
|
search = args.getString(KEY_SEARCH, "");
|
||||||
mode = args.getInt(KEY_MODE, 0);
|
mode = args.getInt(KEY_MODE, 0);
|
||||||
}
|
}
|
||||||
|
if (mode == MODE_FOLLOW || mode == MODE_FEATURE) {
|
||||||
|
adapter.enableDelete();
|
||||||
|
}
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
Serializable data = savedInstanceState.getSerializable(KEY_DATA);
|
Serializable data = savedInstanceState.getSerializable(KEY_DATA);
|
||||||
if (data instanceof Trends) {
|
if (data instanceof Trends) {
|
||||||
adapter.addItems((Trends) data, TrendAdapter.CLEAR_LIST);
|
adapter.addItems((Trends) data, HashtagAdapter.CLEAR_LIST);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setRefresh(true);
|
setRefresh(true);
|
||||||
load(TrendParameter.NO_CURSOR, TrendAdapter.CLEAR_LIST);
|
load(HashtagLoaderParam.NO_CURSOR, HashtagAdapter.CLEAR_LIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -112,7 +129,7 @@ public class HashtagFragment extends ListFragment implements TrendClickListener,
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
trendLoader.cancel();
|
hashtagLoader.cancel();
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,15 +137,15 @@ public class HashtagFragment extends ListFragment implements TrendClickListener,
|
||||||
@Override
|
@Override
|
||||||
protected void onReset() {
|
protected void onReset() {
|
||||||
adapter.clear();
|
adapter.clear();
|
||||||
trendLoader = new TrendLoader(requireContext());
|
hashtagLoader = new HashtagLoader(requireContext());
|
||||||
load(TrendParameter.NO_CURSOR, TrendAdapter.CLEAR_LIST);
|
load(HashtagLoaderParam.NO_CURSOR, HashtagAdapter.CLEAR_LIST);
|
||||||
setRefresh(true);
|
setRefresh(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onReload() {
|
protected void onReload() {
|
||||||
load(TrendParameter.NO_CURSOR, TrendAdapter.CLEAR_LIST);
|
load(HashtagLoaderParam.NO_CURSOR, HashtagAdapter.CLEAR_LIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -150,24 +167,35 @@ public class HashtagFragment extends ListFragment implements TrendClickListener,
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTrendClick(Hashtag hashtag) {
|
public void onHashtagClick(Hashtag hashtag, int action) {
|
||||||
if (!isRefreshing()) {
|
if (action == OnHashtagClickListener.SELECT) {
|
||||||
Intent intent = new Intent(requireContext(), SearchActivity.class);
|
if (!isRefreshing()) {
|
||||||
String name = hashtag.getName();
|
Intent intent = new Intent(requireContext(), SearchActivity.class);
|
||||||
if (!name.startsWith("#") && !name.startsWith("\"") && !name.endsWith("\"")) {
|
String name = hashtag.getName();
|
||||||
name = "\"" + name + "\"";
|
if (!name.startsWith("#") && !name.startsWith("\"") && !name.endsWith("\"")) {
|
||||||
intent.putExtra(SearchActivity.KEY_QUERY, name);
|
name = "\"" + name + "\"";
|
||||||
} else {
|
intent.putExtra(SearchActivity.KEY_QUERY, name);
|
||||||
intent.putExtra(SearchActivity.KEY_DATA, hashtag);
|
} else {
|
||||||
|
intent.putExtra(SearchActivity.KEY_DATA, hashtag);
|
||||||
|
}
|
||||||
|
activityResultLauncher.launch(intent);
|
||||||
|
}
|
||||||
|
} else if (action == OnHashtagClickListener.REMOVE) {
|
||||||
|
if (!confirmDialog.isShowing()) {
|
||||||
|
selection = hashtag;
|
||||||
|
if (mode == MODE_FEATURE) {
|
||||||
|
confirmDialog.show(ConfirmDialog.UNFEATURE_HASHTAG);
|
||||||
|
} else if (mode == MODE_FOLLOW) {
|
||||||
|
confirmDialog.show(ConfirmDialog.UNFOLLOW_HASHTAG);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
activityResultLauncher.launch(intent);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onPlaceholderClick(long cursor, int index) {
|
public boolean onPlaceholderClick(long cursor, int index) {
|
||||||
if (trendLoader.isIdle()) {
|
if (hashtagLoader.isIdle()) {
|
||||||
load(cursor, index);
|
load(cursor, index);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -176,8 +204,36 @@ public class HashtagFragment extends ListFragment implements TrendClickListener,
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResult(@NonNull TrendResult result) {
|
public void onConfirm(int type, boolean remember) {
|
||||||
if (result.mode == TrendResult.ERROR) {
|
if (selection != null) {
|
||||||
|
if (type == ConfirmDialog.UNFOLLOW_HASHTAG) {
|
||||||
|
HashtagActionParam param = new HashtagActionParam(HashtagActionParam.UNFOLLOW, selection.getName(), selection.getId());
|
||||||
|
hashtagAction.execute(param, hashtagActionCallback);
|
||||||
|
} else if (type == ConfirmDialog.UNFEATURE_HASHTAG) {
|
||||||
|
HashtagActionParam param = new HashtagActionParam(HashtagActionParam.UNFEATURE, selection.getName(), selection.getId());
|
||||||
|
hashtagAction.execute(param, hashtagActionCallback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* callback for {@link HashtagAction}
|
||||||
|
*/
|
||||||
|
private void onHashtagActionResult(@NonNull HashtagActionResult result) {
|
||||||
|
if (result.mode == HashtagActionResult.UNFEATURE) {
|
||||||
|
Toast.makeText(requireContext(), R.string.info_hashtag_unfeatured, Toast.LENGTH_SHORT).show();
|
||||||
|
adapter.removeItem(result.hashtag);
|
||||||
|
} else if (result.mode == HashtagActionResult.UNFOLLOW) {
|
||||||
|
Toast.makeText(requireContext(), R.string.info_hashtag_unfollowed, Toast.LENGTH_SHORT).show();
|
||||||
|
adapter.removeItem(result.hashtag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* callback for {@link HashtagLoader}
|
||||||
|
*/
|
||||||
|
private void onHashtagLoaderResult(@NonNull HashtagLoaderResult result) {
|
||||||
|
if (result.mode == HashtagLoaderResult.ERROR) {
|
||||||
if (getContext() != null) {
|
if (getContext() != null) {
|
||||||
ErrorUtils.showErrorMessage(getContext(), result.exception);
|
ErrorUtils.showErrorMessage(getContext(), result.exception);
|
||||||
}
|
}
|
||||||
|
@ -192,30 +248,30 @@ public class HashtagFragment extends ListFragment implements TrendClickListener,
|
||||||
* load content into the list
|
* load content into the list
|
||||||
*/
|
*/
|
||||||
private void load(long cursor, int index) {
|
private void load(long cursor, int index) {
|
||||||
TrendParameter param;
|
HashtagLoaderParam param;
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case MODE_POPULAR:
|
case MODE_POPULAR:
|
||||||
if (adapter.isEmpty()) {
|
if (adapter.isEmpty()) {
|
||||||
param = new TrendParameter(TrendParameter.POPULAR_OFFLINE, index, search, cursor);
|
param = new HashtagLoaderParam(HashtagLoaderParam.POPULAR_OFFLINE, index, search, cursor);
|
||||||
} else {
|
} else {
|
||||||
param = new TrendParameter(TrendParameter.POPULAR_ONLINE, index, search, cursor);
|
param = new HashtagLoaderParam(HashtagLoaderParam.POPULAR_ONLINE, index, search, cursor);
|
||||||
}
|
}
|
||||||
trendLoader.execute(param, this);
|
hashtagLoader.execute(param, hashtagLoaderCallback);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MODE_FOLLOW:
|
case MODE_FOLLOW:
|
||||||
param = new TrendParameter(TrendParameter.FOLLOWING, index, search, cursor);
|
param = new HashtagLoaderParam(HashtagLoaderParam.FOLLOWING, index, search, cursor);
|
||||||
trendLoader.execute(param, this);
|
hashtagLoader.execute(param, hashtagLoaderCallback);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MODE_FEATURE:
|
case MODE_FEATURE:
|
||||||
param = new TrendParameter(TrendParameter.FEATURING, index, search, cursor);
|
param = new HashtagLoaderParam(HashtagLoaderParam.FEATURING, index, search, cursor);
|
||||||
trendLoader.execute(param, this);
|
hashtagLoader.execute(param, hashtagLoaderCallback);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MODE_SEARCH:
|
case MODE_SEARCH:
|
||||||
param = new TrendParameter(TrendParameter.SEARCH, index, search, cursor);
|
param = new HashtagLoaderParam(HashtagLoaderParam.SEARCH, index, search, cursor);
|
||||||
trendLoader.execute(param, this);
|
hashtagLoader.execute(param, hashtagLoaderCallback);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,16 +9,16 @@
|
||||||
android:id="@+id/item_trend_container"
|
android:id="@+id/item_trend_container"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:padding="@dimen/trenditem_layout_padding">
|
android:padding="@dimen/item_hashtag_layout_padding">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/item_trend_rank"
|
android:id="@+id/item_trend_rank"
|
||||||
android:layout_width="@dimen/trenditem_textsize_trendindex_width"
|
android:layout_width="@dimen/item_hashtag_textsize_trendindex_width"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="center_vertical|end"
|
android:gravity="center_vertical|end"
|
||||||
android:lines="1"
|
android:lines="1"
|
||||||
android:textAlignment="gravity"
|
android:textAlignment="gravity"
|
||||||
android:textSize="@dimen/trenditem_textsize_trendindex"
|
android:textSize="@dimen/item_hashtag_textsize_trendindex"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:layout_constraintEnd_toStartOf="@id/item_trend_name"
|
app:layout_constraintEnd_toStartOf="@id/item_trend_name"
|
||||||
|
@ -28,28 +28,42 @@
|
||||||
android:id="@+id/item_trend_name"
|
android:id="@+id/item_trend_name"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="@dimen/trenditem_text_margin"
|
android:layout_marginStart="@dimen/item_hashtag_layout_margin"
|
||||||
|
android:layout_marginEnd="@dimen/item_hashtag_layout_margin"
|
||||||
android:lines="1"
|
android:lines="1"
|
||||||
android:textSize="@dimen/trenditem_textsize_trendname"
|
android:textSize="@dimen/item_hashtag_textsize_trendname"
|
||||||
app:layout_constraintStart_toEndOf="@id/item_trend_rank"
|
app:layout_constraintStart_toEndOf="@id/item_trend_rank"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:layout_constraintBottom_toTopOf="@id/item_trend_vol"
|
app:layout_constraintBottom_toTopOf="@id/item_trend_vol"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toStartOf="@id/item_trend_delete_button"
|
||||||
app:layout_constrainedWidth="true" />
|
app:layout_constrainedWidth="true" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/item_trend_vol"
|
android:id="@+id/item_trend_vol"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="@dimen/trenditem_text_margin"
|
android:layout_marginStart="@dimen/item_hashtag_layout_margin"
|
||||||
android:lines="1"
|
android:lines="1"
|
||||||
android:textSize="@dimen/trenditem_textsize_trendvol"
|
android:textSize="@dimen/item_hashtag_textsize_trendvol"
|
||||||
app:layout_constraintStart_toEndOf="@id/item_trend_rank"
|
app:layout_constraintStart_toEndOf="@id/item_trend_rank"
|
||||||
app:layout_constraintTop_toBottomOf="@id/item_trend_name"
|
app:layout_constraintTop_toBottomOf="@id/item_trend_name"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constrainedWidth="false" />
|
app:layout_constrainedWidth="false" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/item_trend_delete_button"
|
||||||
|
android:layout_width="@dimen/item_hashtag_button_size"
|
||||||
|
android:layout_height="@dimen/item_hashtag_button_size"
|
||||||
|
android:visibility="invisible"
|
||||||
|
android:padding="@dimen/item_hashtag_button_padding"
|
||||||
|
android:contentDescription="@string/descr_remove_hashtag"
|
||||||
|
android:scaleType="fitCenter"
|
||||||
|
android:src="@drawable/cross"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
style="@style/RoundButton" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
|
@ -80,7 +80,7 @@
|
||||||
app:layout_constraintStart_toEndOf="@id/item_user_verified"
|
app:layout_constraintStart_toEndOf="@id/item_user_verified"
|
||||||
app:layout_constraintTop_toTopOf="@id/item_user_profile"
|
app:layout_constraintTop_toTopOf="@id/item_user_profile"
|
||||||
app:layout_constraintBottom_toTopOf="@id/item_user_screenname"
|
app:layout_constraintBottom_toTopOf="@id/item_user_screenname"
|
||||||
app:layout_constraintEnd_toStartOf="@id/item_user_delete_buton" />
|
app:layout_constraintEnd_toStartOf="@id/item_user_delete_button" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/item_user_private"
|
android:id="@+id/item_user_private"
|
||||||
|
@ -106,7 +106,7 @@
|
||||||
app:layout_constraintStart_toEndOf="@id/item_user_private"
|
app:layout_constraintStart_toEndOf="@id/item_user_private"
|
||||||
app:layout_constraintTop_toBottomOf="@id/item_user_username"
|
app:layout_constraintTop_toBottomOf="@id/item_user_username"
|
||||||
app:layout_constraintBottom_toTopOf="@id/item_user_following_icon"
|
app:layout_constraintBottom_toTopOf="@id/item_user_following_icon"
|
||||||
app:layout_constraintEnd_toStartOf="@id/item_user_delete_buton" />
|
app:layout_constraintEnd_toStartOf="@id/item_user_delete_button" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/item_user_following_icon"
|
android:id="@+id/item_user_following_icon"
|
||||||
|
@ -157,10 +157,10 @@
|
||||||
app:layout_constraintStart_toEndOf="@id/item_user_follower_icon"
|
app:layout_constraintStart_toEndOf="@id/item_user_follower_icon"
|
||||||
app:layout_constraintTop_toTopOf="@id/item_user_follower_icon"
|
app:layout_constraintTop_toTopOf="@id/item_user_follower_icon"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/item_user_follower_icon"
|
app:layout_constraintBottom_toBottomOf="@id/item_user_follower_icon"
|
||||||
app:layout_constraintEnd_toStartOf="@id/item_user_delete_buton" />
|
app:layout_constraintEnd_toStartOf="@id/item_user_delete_button" />
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/item_user_delete_buton"
|
android:id="@+id/item_user_delete_button"
|
||||||
android:layout_width="@dimen/item_user_button_size"
|
android:layout_width="@dimen/item_user_button_size"
|
||||||
android:layout_height="@dimen/item_user_button_size"
|
android:layout_height="@dimen/item_user_button_size"
|
||||||
android:visibility="invisible"
|
android:visibility="invisible"
|
||||||
|
|
|
@ -209,6 +209,7 @@
|
||||||
<string name="menu_hint_mute_user">\@name stummschalten</string>
|
<string name="menu_hint_mute_user">\@name stummschalten</string>
|
||||||
<string name="menu_hint_block_user">\@name blockieren</string>
|
<string name="menu_hint_block_user">\@name blockieren</string>
|
||||||
<string name="menu_exclude_user">Nutzer ausschließen</string>
|
<string name="menu_exclude_user">Nutzer ausschließen</string>
|
||||||
|
<string name="menu_hashtag_add">Hashtag hinzufügen</string>
|
||||||
<string name="menu_search_filter">Ergebnisse filtern</string>
|
<string name="menu_search_filter">Ergebnisse filtern</string>
|
||||||
<string name="menu_hint_block_domain">domain.namen eingeben</string>
|
<string name="menu_hint_block_domain">domain.namen eingeben</string>
|
||||||
<string name="menu_licenses">Lizenzen</string>
|
<string name="menu_licenses">Lizenzen</string>
|
||||||
|
@ -296,11 +297,13 @@
|
||||||
<string name="error_duration_time_low">Dauer der Umfrage ist zu kurz!</string>
|
<string name="error_duration_time_low">Dauer der Umfrage ist zu kurz!</string>
|
||||||
<string name="error_duration_time_high">Dauer der Umfrage ist zu lang!</string>
|
<string name="error_duration_time_high">Dauer der Umfrage ist zu lang!</string>
|
||||||
<string name="error_poll_option_missing">Umfrageoption darf nicht leer sein!</string>
|
<string name="error_poll_option_missing">Umfrageoption darf nicht leer sein!</string>
|
||||||
|
<string name="menu_hashtags">Hashtags</string>
|
||||||
<string name="menu_hashtag_follow">folge Hashtag</string>
|
<string name="menu_hashtag_follow">folge Hashtag</string>
|
||||||
<string name="menu_hashtag_unfollow">entfolge Hashtag</string>
|
<string name="menu_hashtag_unfollow">entfolge Hashtag</string>
|
||||||
<string name="info_hashtag_unfollowed">Hashtag entfolgt</string>
|
<string name="info_hashtag_unfollowed">Hashtag entfolgt</string>
|
||||||
<string name="info_domain_removed">Domain von der Liste entfernt</string>
|
<string name="info_domain_removed">Domain von der Liste entfernt</string>
|
||||||
<string name="info_hashtag_followed">Hashtag gefolgt</string>
|
<string name="info_hashtag_followed">Hashtag gefolgt</string>
|
||||||
|
<string name="dialog_status_schedule_set">Veröffentlichung planen</string>
|
||||||
<string name="dialog_push_repost">bei Reposts</string>
|
<string name="dialog_push_repost">bei Reposts</string>
|
||||||
<string name="dialog_push_favorite">bei Favorisierung</string>
|
<string name="dialog_push_favorite">bei Favorisierung</string>
|
||||||
<string name="dialog_push_poll_finished">bei beendeten Umfragen</string>
|
<string name="dialog_push_poll_finished">bei beendeten Umfragen</string>
|
||||||
|
@ -354,4 +357,6 @@
|
||||||
<string name="error_empty_filter_title">Filterbezeichnung darf nicht leer sein</string>
|
<string name="error_empty_filter_title">Filterbezeichnung darf nicht leer sein</string>
|
||||||
<string name="error_empty_filter_selection">es muss mindestens ein Filter aktiviert sein</string>
|
<string name="error_empty_filter_selection">es muss mindestens ein Filter aktiviert sein</string>
|
||||||
<string name="dialog_description_title">Medienbeschreibung</string>
|
<string name="dialog_description_title">Medienbeschreibung</string>
|
||||||
|
<string name="descr_remove_hashtag">Hashtag von der Liste entfernen</string>
|
||||||
|
<string name="confirm_hashtag_unfollow">Hashtag entfolgen?</string>
|
||||||
</resources>
|
</resources>
|
|
@ -92,13 +92,15 @@
|
||||||
<dimen name="item_status_indicator_padding">6sp</dimen>
|
<dimen name="item_status_indicator_padding">6sp</dimen>
|
||||||
<dimen name="item_status_indicator_size">26sp</dimen>
|
<dimen name="item_status_indicator_size">26sp</dimen>
|
||||||
|
|
||||||
<!--dimens of item_trend.xml-->
|
<!--dimens of item_hashtag.xml-->
|
||||||
<dimen name="trenditem_layout_padding">5dp</dimen>
|
<dimen name="item_hashtag_layout_padding">5dp</dimen>
|
||||||
<dimen name="trenditem_text_margin">5dp</dimen>
|
<dimen name="item_hashtag_layout_margin">5dp</dimen>
|
||||||
<dimen name="trenditem_textsize_trendindex">20sp</dimen>
|
<dimen name="item_hashtag_button_size">20sp</dimen>
|
||||||
<dimen name="trenditem_textsize_trendname">20sp</dimen>
|
<dimen name="item_hashtag_button_padding">1dp</dimen>
|
||||||
<dimen name="trenditem_textsize_trendvol">14sp</dimen>
|
<dimen name="item_hashtag_textsize_trendindex">20sp</dimen>
|
||||||
<dimen name="trenditem_textsize_trendindex_width">40sp</dimen>
|
<dimen name="item_hashtag_textsize_trendname">20sp</dimen>
|
||||||
|
<dimen name="item_hashtag_textsize_trendvol">14sp</dimen>
|
||||||
|
<dimen name="item_hashtag_textsize_trendindex_width">40sp</dimen>
|
||||||
|
|
||||||
<!--dimens of item_user.xml-->
|
<!--dimens of item_user.xml-->
|
||||||
<dimen name="item_user_image_size">56sp</dimen>
|
<dimen name="item_user_image_size">56sp</dimen>
|
||||||
|
|
|
@ -78,6 +78,7 @@
|
||||||
<string name="info_hashtag_featured">Hashtag featured</string>
|
<string name="info_hashtag_featured">Hashtag featured</string>
|
||||||
<string name="info_hashtag_followed">Hashtag followed</string>
|
<string name="info_hashtag_followed">Hashtag followed</string>
|
||||||
<string name="info_hashtag_unfollowed">Hashtag unfollowed</string>
|
<string name="info_hashtag_unfollowed">Hashtag unfollowed</string>
|
||||||
|
<string name="info_hashtag_unfeatured">Hashtag unfeatured</string>
|
||||||
<string name="info_status_reported">Status reported</string>
|
<string name="info_status_reported">Status reported</string>
|
||||||
<string name="info_error">Error</string>
|
<string name="info_error">Error</string>
|
||||||
|
|
||||||
|
@ -289,6 +290,7 @@
|
||||||
<string name="update_list">update list</string>
|
<string name="update_list">update list</string>
|
||||||
<string name="confirm_remove_user_from_list">remove user from list?</string>
|
<string name="confirm_remove_user_from_list">remove user from list?</string>
|
||||||
<string name="descr_remove_user">remove user from list</string>
|
<string name="descr_remove_user">remove user from list</string>
|
||||||
|
<string name="descr_remove_hashtag">remove hashtag from list</string>
|
||||||
<string name="descr_remove_domain">remove domain from list</string>
|
<string name="descr_remove_domain">remove domain from list</string>
|
||||||
<string name="confirm_unknown_error">unknown error!</string>
|
<string name="confirm_unknown_error">unknown error!</string>
|
||||||
<string name="list_following_indicator">following list</string>
|
<string name="list_following_indicator">following list</string>
|
||||||
|
@ -307,6 +309,8 @@
|
||||||
<string name="confirm_remember">remember choice</string>
|
<string name="confirm_remember">remember choice</string>
|
||||||
<string name="confirm_warning">Warning</string>
|
<string name="confirm_warning">Warning</string>
|
||||||
<string name="confirm_proxy_bypass">Opening an external link would bypass proxy connection. Proceed?</string>
|
<string name="confirm_proxy_bypass">Opening an external link would bypass proxy connection. Proceed?</string>
|
||||||
|
<string name="confirm_hashtag_unfollow">unfollow hashtag?</string>
|
||||||
|
<string name="confirm_hashtag_unfeature">unfeature hashtag?</string>
|
||||||
<string name="confirm_remove_account">remove account from list?</string>
|
<string name="confirm_remove_account">remove account from list?</string>
|
||||||
<string name="confirm_remove_filter">delete filter?</string>
|
<string name="confirm_remove_filter">delete filter?</string>
|
||||||
<string name="account_user_unnamed">\'unnamed\'</string>
|
<string name="account_user_unnamed">\'unnamed\'</string>
|
||||||
|
|
Loading…
Reference in New Issue