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
|
||||
*/
|
||||
Hashtag unfeatureHashtag(String name) throws ConnectionException;
|
||||
Hashtag unfeatureHashtag(long id) throws ConnectionException;
|
||||
|
||||
/**
|
||||
* show current user's home timeline
|
||||
|
|
|
@ -541,13 +541,9 @@ public class Mastodon implements Connection {
|
|||
|
||||
|
||||
@Override
|
||||
public Hashtag unfeatureHashtag(String name) throws ConnectionException {
|
||||
public Hashtag unfeatureHashtag(long id) 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));
|
||||
return createTag(delete(ENDPOINT_HASHTAG_FEATURE + "/" + id, new ArrayList<>()));
|
||||
} catch (IOException e) {
|
||||
throw new MastodonException(e);
|
||||
}
|
||||
|
@ -1466,7 +1462,9 @@ 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 MastodonHashtag(jsonArray.getJSONObject(i)));
|
||||
MastodonHashtag item = new MastodonHashtag(jsonArray.getJSONObject(i));
|
||||
item.setRank(i + 1);
|
||||
result.add(item);
|
||||
}
|
||||
Collections.sort(result);
|
||||
return result;
|
||||
|
|
|
@ -5,8 +5,8 @@ import androidx.annotation.Nullable;
|
|||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.nuclearfog.twidda.model.Location;
|
||||
import org.nuclearfog.twidda.model.Hashtag;
|
||||
import org.nuclearfog.twidda.model.Location;
|
||||
|
||||
/**
|
||||
* Hashtag implementation used by Mastodon API
|
||||
|
@ -20,12 +20,15 @@ public class MastodonHashtag implements Hashtag {
|
|||
private int popularity;
|
||||
private String name;
|
||||
private boolean following;
|
||||
private long id;
|
||||
private int rank;
|
||||
|
||||
/**
|
||||
* @param json trend json object
|
||||
*/
|
||||
public MastodonHashtag(JSONObject json) {
|
||||
JSONArray history = json.optJSONArray("history");
|
||||
String idStr = json.optString("id", "0");
|
||||
name = '#' + json.optString("name", "");
|
||||
following = json.optBoolean("following", false);
|
||||
if (history != null && history.length() > 0) {
|
||||
|
@ -36,6 +39,17 @@ public class MastodonHashtag implements Hashtag {
|
|||
} else {
|
||||
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
|
||||
public int getRank() {
|
||||
return -1;
|
||||
return rank;
|
||||
}
|
||||
|
||||
|
||||
|
@ -68,6 +82,13 @@ public class MastodonHashtag implements Hashtag {
|
|||
return following;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void setRank(int rank) {
|
||||
this.rank = rank;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
|
|
|
@ -15,7 +15,7 @@ import org.nuclearfog.twidda.model.Hashtag;
|
|||
*
|
||||
* @author nuclearfog
|
||||
*/
|
||||
public class HashtagAction extends AsyncExecutor<HashtagAction.HashtagParam, HashtagAction.HashtagResult> {
|
||||
public class HashtagAction extends AsyncExecutor<HashtagAction.HashtagActionParam, HashtagAction.HashtagActionResult> {
|
||||
|
||||
private Connection connection;
|
||||
|
||||
|
@ -28,41 +28,41 @@ public class HashtagAction extends AsyncExecutor<HashtagAction.HashtagParam, Has
|
|||
|
||||
|
||||
@Override
|
||||
protected HashtagResult doInBackground(@NonNull HashtagParam param) {
|
||||
protected HashtagActionResult doInBackground(@NonNull HashtagActionParam param) {
|
||||
try {
|
||||
switch (param.mode) {
|
||||
case HashtagParam.LOAD:
|
||||
case HashtagActionParam.LOAD:
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
return new HashtagResult(HashtagResult.FEATURE, result, null);
|
||||
return new HashtagActionResult(HashtagActionResult.FEATURE, result, null);
|
||||
|
||||
case HashtagParam.UNFEATURE:
|
||||
result = connection.unfeatureHashtag(param.name);
|
||||
return new HashtagResult(HashtagResult.UNFEATURE, result, null);
|
||||
case HashtagActionParam.UNFEATURE:
|
||||
result = connection.unfeatureHashtag(param.id);
|
||||
return new HashtagActionResult(HashtagActionResult.UNFEATURE, result, null);
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
} 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 FOLLOW = 2;
|
||||
|
@ -72,17 +72,25 @@ public class HashtagAction extends AsyncExecutor<HashtagAction.HashtagParam, Has
|
|||
|
||||
final String name;
|
||||
final int mode;
|
||||
final long id;
|
||||
|
||||
public HashtagParam(int mode, String name) {
|
||||
public HashtagActionParam(int mode, String name) {
|
||||
this.name = name;
|
||||
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 LOAD = 10;
|
||||
|
@ -97,7 +105,7 @@ public class HashtagAction extends AsyncExecutor<HashtagAction.HashtagParam, Has
|
|||
public final Hashtag hashtag;
|
||||
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.hashtag = hashtag;
|
||||
this.mode = mode;
|
||||
|
|
|
@ -18,7 +18,7 @@ import org.nuclearfog.twidda.ui.fragments.HashtagFragment;
|
|||
* @author nuclearfog
|
||||
* @see HashtagFragment
|
||||
*/
|
||||
public class TrendLoader extends AsyncExecutor<TrendLoader.TrendParameter, TrendLoader.TrendResult> {
|
||||
public class HashtagLoader extends AsyncExecutor<HashtagLoader.HashtagLoaderParam, HashtagLoader.HashtagLoaderResult> {
|
||||
|
||||
private Connection connection;
|
||||
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);
|
||||
db = new AppDatabase(context);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected TrendResult doInBackground(@NonNull TrendParameter param) {
|
||||
protected HashtagLoaderResult doInBackground(@NonNull HashtagLoaderParam param) {
|
||||
try {
|
||||
switch (param.mode) {
|
||||
case TrendParameter.POPULAR_OFFLINE:
|
||||
case HashtagLoaderParam.POPULAR_OFFLINE:
|
||||
Trends trends = db.getTrends();
|
||||
if (!trends.isEmpty()) {
|
||||
return new TrendResult(TrendResult.POPULAR, trends, param.index, null);
|
||||
return new HashtagLoaderResult(HashtagLoaderResult.POPULAR, trends, param.index, null);
|
||||
}
|
||||
// fall through
|
||||
|
||||
case TrendParameter.POPULAR_ONLINE:
|
||||
case HashtagLoaderParam.POPULAR_ONLINE:
|
||||
trends = connection.getTrends();
|
||||
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);
|
||||
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);
|
||||
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();
|
||||
return new TrendResult(TrendResult.FEATURING, trends, param.index, null);
|
||||
return new HashtagLoaderResult(HashtagLoaderResult.FEATURING, trends, param.index, null);
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
} 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_ONLINE = 2;
|
||||
|
@ -86,7 +86,7 @@ public class TrendLoader extends AsyncExecutor<TrendLoader.TrendParameter, Trend
|
|||
final int index;
|
||||
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.trend = trend;
|
||||
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 POPULAR = 20;
|
||||
|
@ -112,7 +112,7 @@ public class TrendLoader extends AsyncExecutor<TrendLoader.TrendParameter, Trend
|
|||
@Nullable
|
||||
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.exception = exception;
|
||||
this.index = index;
|
|
@ -304,7 +304,7 @@ public class AppDatabase {
|
|||
/**
|
||||
* 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
|
||||
|
@ -537,10 +537,11 @@ public class AppDatabase {
|
|||
db.delete(HashtagTable.NAME, TREND_SELECT, args);
|
||||
for (Hashtag hashtag : hashtags) {
|
||||
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.TREND, hashtag.getName());
|
||||
column.put(HashtagTable.INDEX, hashtag.getRank());
|
||||
column.put(HashtagTable.ID, hashtag.getId());
|
||||
db.insert(HashtagTable.NAME, null, column);
|
||||
}
|
||||
adapter.commit();
|
||||
|
|
|
@ -20,7 +20,7 @@ public class DatabaseAdapter {
|
|||
/**
|
||||
* database version
|
||||
*/
|
||||
private static final int DB_VERSION = 20;
|
||||
private static final int DB_VERSION = 21;
|
||||
|
||||
/**
|
||||
* database file name
|
||||
|
@ -78,6 +78,7 @@ public class DatabaseAdapter {
|
|||
private static final String TABLE_TRENDS = "CREATE TABLE IF NOT EXISTS "
|
||||
+ HashtagTable.NAME + "("
|
||||
+ HashtagTable.ID + " INTEGER,"
|
||||
+ HashtagTable.LOCATION + " INTEGER,"
|
||||
+ HashtagTable.INDEX + " INTEGER,"
|
||||
+ HashtagTable.VOL + " INTEGER,"
|
||||
+ 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;";
|
||||
|
||||
/**
|
||||
* add mediatable description
|
||||
*/
|
||||
private static final String UPDATE_HASHTAG_ADD_ID = "ALTER TABLE " + HashtagTable.NAME + " ADD " + HashtagTable.ID + " INTEGER;";
|
||||
|
||||
/**
|
||||
* singleton instance
|
||||
*/
|
||||
|
@ -407,9 +413,13 @@ public class DatabaseAdapter {
|
|||
db.execSQL(UPDATE_MEDIA_ADD_BLUR_HASH);
|
||||
db.setVersion(19);
|
||||
}
|
||||
if (db.getVersion() < DB_VERSION) {
|
||||
if (db.getVersion() < 20) {
|
||||
db.delete(EmojiTable.NAME, null, null);
|
||||
db.execSQL(TABLE_EMOJI);
|
||||
db.setVersion(20);
|
||||
}
|
||||
if (db.getVersion() < DB_VERSION) {
|
||||
db.execSQL(UPDATE_HASHTAG_ADD_ID);
|
||||
db.setVersion(DB_VERSION);
|
||||
}
|
||||
}
|
||||
|
@ -701,10 +711,15 @@ public class DatabaseAdapter {
|
|||
*/
|
||||
String NAME = "trend";
|
||||
|
||||
/**
|
||||
* id of the hashtag
|
||||
*/
|
||||
String ID = "id";
|
||||
|
||||
/**
|
||||
* Location ID
|
||||
*/
|
||||
String ID = "woeID";
|
||||
String LOCATION = "woeID";
|
||||
|
||||
/**
|
||||
* rank of the hashtag
|
||||
|
|
|
@ -20,12 +20,13 @@ public class DatabaseHashtag implements Hashtag, HashtagTable {
|
|||
/**
|
||||
* 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 int popularity;
|
||||
private int rank;
|
||||
private long id;
|
||||
private long locationId;
|
||||
|
||||
/**
|
||||
* @param cursor database cursor using this {@link #COLUMNS} projection
|
||||
|
@ -34,13 +35,20 @@ public class DatabaseHashtag implements Hashtag, HashtagTable {
|
|||
String name = cursor.getString(0);
|
||||
popularity = cursor.getInt(1);
|
||||
rank = cursor.getInt(2);
|
||||
id = cursor.getLong(3);
|
||||
locationId = cursor.getLong(3);
|
||||
id = cursor.getLong(4);
|
||||
if (name != null) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
|
@ -49,7 +57,7 @@ public class DatabaseHashtag implements Hashtag, HashtagTable {
|
|||
|
||||
@Override
|
||||
public long getLocationId() {
|
||||
return id;
|
||||
return locationId;
|
||||
}
|
||||
|
||||
|
||||
|
@ -83,6 +91,6 @@ public class DatabaseHashtag implements Hashtag, HashtagTable {
|
|||
@NonNull
|
||||
@Override
|
||||
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> {
|
||||
|
||||
/**
|
||||
* @return trend name
|
||||
* @return hashtag name
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* @return ID of the trend location
|
||||
* @return trend ID if any
|
||||
*/
|
||||
long getId();
|
||||
|
||||
/**
|
||||
* @return hashtag ID
|
||||
*/
|
||||
long getLocationId();
|
||||
|
||||
/**
|
||||
* @return rank of the trend
|
||||
* @return rank of the hashtag if any
|
||||
*/
|
||||
int getRank();
|
||||
|
||||
/**
|
||||
* @return popularity of the trend
|
||||
* @return popularity of the hashtag
|
||||
*/
|
||||
int getPopularity();
|
||||
|
||||
/**
|
||||
* @return true if current user follows trend (hashtag)
|
||||
* @return true if current user follows hashtag
|
||||
*/
|
||||
boolean following();
|
||||
|
||||
|
|
|
@ -17,8 +17,8 @@ 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.async.HashtagAction.HashtagActionParam;
|
||||
import org.nuclearfog.twidda.backend.async.HashtagAction.HashtagActionResult;
|
||||
import org.nuclearfog.twidda.backend.utils.AppStyles;
|
||||
import org.nuclearfog.twidda.config.GlobalSettings;
|
||||
import org.nuclearfog.twidda.ui.adapter.viewpager.HashtagAdapter;
|
||||
|
@ -30,7 +30,7 @@ import org.nuclearfog.twidda.ui.views.TabSelector.OnTabSelectedListener;
|
|||
*
|
||||
* @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 HashtagAction hashtagAction;
|
||||
|
@ -90,11 +90,11 @@ public class HashtagActivity extends AppCompatActivity implements SearchView.OnQ
|
|||
public boolean onQueryTextSubmit(String query) {
|
||||
if (hashtagAction.isIdle()) {
|
||||
if (viewPager.getCurrentItem() == 0) {
|
||||
HashtagParam param = new HashtagParam(HashtagParam.FOLLOW, query);
|
||||
HashtagActionParam param = new HashtagActionParam(HashtagActionParam.FOLLOW, query);
|
||||
hashtagAction.execute(param, this);
|
||||
return true;
|
||||
} else if (viewPager.getCurrentItem() == 1) {
|
||||
HashtagParam param = new HashtagParam(HashtagParam.FEATURE, query);
|
||||
HashtagActionParam param = new HashtagActionParam(HashtagActionParam.FEATURE, query);
|
||||
hashtagAction.execute(param, this);
|
||||
return true;
|
||||
}
|
||||
|
@ -110,21 +110,21 @@ public class HashtagActivity extends AppCompatActivity implements SearchView.OnQ
|
|||
|
||||
|
||||
@Override
|
||||
public void onResult(@NonNull HashtagResult result) {
|
||||
public void onResult(@NonNull HashtagActionResult result) {
|
||||
switch (result.mode) {
|
||||
case HashtagResult.FEATURE:
|
||||
case HashtagActionResult.FEATURE:
|
||||
Toast.makeText(getApplicationContext(), R.string.info_hashtag_featured, Toast.LENGTH_SHORT).show();
|
||||
adapter.notifySettingsChanged();
|
||||
invalidateOptionsMenu();
|
||||
break;
|
||||
|
||||
case HashtagResult.FOLLOW:
|
||||
case HashtagActionResult.FOLLOW:
|
||||
Toast.makeText(getApplicationContext(), R.string.info_hashtag_followed, Toast.LENGTH_SHORT).show();
|
||||
adapter.notifySettingsChanged();
|
||||
invalidateOptionsMenu();
|
||||
break;
|
||||
|
||||
case HashtagResult.ERROR:
|
||||
case HashtagActionResult.ERROR:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,8 +22,8 @@ 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.async.HashtagAction.HashtagActionParam;
|
||||
import org.nuclearfog.twidda.backend.async.HashtagAction.HashtagActionResult;
|
||||
import org.nuclearfog.twidda.backend.utils.AppStyles;
|
||||
import org.nuclearfog.twidda.backend.utils.ErrorUtils;
|
||||
import org.nuclearfog.twidda.config.GlobalSettings;
|
||||
|
@ -39,7 +39,7 @@ import java.io.Serializable;
|
|||
*
|
||||
* @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
|
||||
|
@ -96,7 +96,7 @@ public class SearchActivity extends AppCompatActivity implements OnClickListener
|
|||
} else if (query != null) {
|
||||
search = query;
|
||||
if (search.startsWith("#") && search.matches("\\S+")) {
|
||||
HashtagParam param = new HashtagParam(HashtagParam.LOAD, search);
|
||||
HashtagActionParam param = new HashtagActionParam(HashtagActionParam.LOAD, search);
|
||||
hashtagAction.execute(param, this);
|
||||
}
|
||||
}
|
||||
|
@ -207,11 +207,11 @@ public class SearchActivity extends AppCompatActivity implements OnClickListener
|
|||
// follow/unfollow hashtag
|
||||
else if (item.getItemId() == R.id.search_hashtag) {
|
||||
if (hashtag != null && hashtagAction.isIdle()) {
|
||||
HashtagParam param;
|
||||
HashtagActionParam param;
|
||||
if (hashtag.following())
|
||||
param = new HashtagParam(HashtagParam.UNFOLLOW, hashtag.getName());
|
||||
param = new HashtagActionParam(HashtagActionParam.UNFOLLOW, hashtag.getName());
|
||||
else
|
||||
param = new HashtagParam(HashtagParam.FOLLOW, hashtag.getName());
|
||||
param = new HashtagActionParam(HashtagActionParam.FOLLOW, hashtag.getName());
|
||||
hashtagAction.execute(param, this);
|
||||
}
|
||||
}
|
||||
|
@ -258,21 +258,21 @@ public class SearchActivity extends AppCompatActivity implements OnClickListener
|
|||
|
||||
|
||||
@Override
|
||||
public void onResult(@NonNull HashtagResult result) {
|
||||
public void onResult(@NonNull HashtagActionResult result) {
|
||||
if (result.hashtag != null) {
|
||||
this.hashtag = result.hashtag;
|
||||
invalidateMenu();
|
||||
}
|
||||
switch (result.mode) {
|
||||
case HashtagResult.FOLLOW:
|
||||
case HashtagActionResult.FOLLOW:
|
||||
Toast.makeText(getApplicationContext(), R.string.info_hashtag_followed, Toast.LENGTH_SHORT).show();
|
||||
break;
|
||||
|
||||
case HashtagResult.UNFOLLOW:
|
||||
case HashtagActionResult.UNFOLLOW:
|
||||
Toast.makeText(getApplicationContext(), R.string.info_hashtag_unfollowed, Toast.LENGTH_SHORT).show();
|
||||
break;
|
||||
|
||||
case HashtagResult.ERROR:
|
||||
case HashtagActionResult.ERROR:
|
||||
ErrorUtils.showErrorMessage(this, result.exception);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ 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;
|
||||
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
|
||||
|
@ -18,7 +18,7 @@ import org.nuclearfog.twidda.ui.adapter.recyclerview.holder.TrendHolder;
|
|||
* @author nuclearfog
|
||||
* @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
|
||||
|
@ -31,15 +31,16 @@ public class TrendAdapter extends Adapter<ViewHolder> implements OnHolderClickLi
|
|||
|
||||
private static final int NO_LOADING = -1;
|
||||
|
||||
private TrendClickListener itemClickListener;
|
||||
private OnHashtagClickListener itemClickListener;
|
||||
|
||||
private Trends items = new Trends();
|
||||
private int loadingIndex = NO_LOADING;
|
||||
private boolean enableDelete = false;
|
||||
|
||||
/**
|
||||
* @param itemClickListener Listener for item click
|
||||
*/
|
||||
public TrendAdapter(TrendClickListener itemClickListener) {
|
||||
public HashtagAdapter(OnHashtagClickListener itemClickListener) {
|
||||
this.itemClickListener = itemClickListener;
|
||||
}
|
||||
|
||||
|
@ -62,7 +63,7 @@ public class TrendAdapter extends Adapter<ViewHolder> implements OnHolderClickLi
|
|||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
if (viewType == TYPE_TREND) {
|
||||
return new TrendHolder(parent, this);
|
||||
return new HashtagHolder(parent, this, enableDelete);
|
||||
} else {
|
||||
return new PlaceHolder(parent, this, false);
|
||||
}
|
||||
|
@ -71,8 +72,8 @@ public class TrendAdapter extends Adapter<ViewHolder> implements OnHolderClickLi
|
|||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder vh, int index) {
|
||||
if (vh instanceof TrendHolder) {
|
||||
TrendHolder holder = (TrendHolder) vh;
|
||||
if (vh instanceof HashtagHolder) {
|
||||
HashtagHolder holder = (HashtagHolder) vh;
|
||||
Hashtag hashtag = items.get(index);
|
||||
if (hashtag != null) {
|
||||
holder.setContent(hashtag, index);
|
||||
|
@ -86,7 +87,11 @@ public class TrendAdapter extends Adapter<ViewHolder> implements OnHolderClickLi
|
|||
|
||||
@Override
|
||||
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
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
}
|
|
@ -17,26 +17,28 @@ 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.Hashtag;
|
||||
import org.nuclearfog.twidda.ui.adapter.recyclerview.HashtagAdapter;
|
||||
|
||||
/**
|
||||
* ViewHolder for a trend item
|
||||
*
|
||||
* @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 OnHolderClickListener listener;
|
||||
|
||||
|
||||
public TrendHolder(ViewGroup parent, OnHolderClickListener listener) {
|
||||
super(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_trend, parent, false));
|
||||
public HashtagHolder(ViewGroup parent, OnHolderClickListener listener, boolean enableRemove) {
|
||||
super(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_hashtag, parent, false));
|
||||
this.listener = listener;
|
||||
|
||||
CardView background = (CardView) itemView;
|
||||
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);
|
||||
name = itemView.findViewById(R.id.item_trend_name);
|
||||
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());
|
||||
AppStyles.setTheme(container, Color.TRANSPARENT);
|
||||
background.setCardBackgroundColor(settings.getCardColor());
|
||||
if (enableRemove) {
|
||||
btnRemove.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
btnRemove.setVisibility(View.GONE);
|
||||
}
|
||||
itemView.setOnClickListener(this);
|
||||
btnRemove.setOnClickListener(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
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) {
|
||||
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 HASHTAG_CLICK = 24;
|
||||
|
||||
int HASHTAG_REMOVE = 25;
|
||||
|
||||
/**
|
||||
* 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);
|
||||
verifyIcon = itemView.findViewById(R.id.item_user_verified);
|
||||
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);
|
||||
|
||||
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 UNFOLLOW_HASHTAG = 628;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public static final int UNFEATURE_HASHTAG = 629;
|
||||
|
||||
|
||||
private TextView title, message, remember_label;
|
||||
private Button confirm, cancel;
|
||||
|
@ -275,6 +285,14 @@ public class ConfirmDialog extends Dialog implements OnClickListener {
|
|||
titleRes = R.string.confirm_warning;
|
||||
messageRes = R.string.confirm_proxy_bypass;
|
||||
break;
|
||||
|
||||
case UNFOLLOW_HASHTAG:
|
||||
messageRes = R.string.confirm_hashtag_unfollow;
|
||||
break;
|
||||
|
||||
case UNFEATURE_HASHTAG:
|
||||
messageRes = R.string.confirm_hashtag_unfeature;
|
||||
break;
|
||||
}
|
||||
// setup title
|
||||
title.setVisibility(titleVis);
|
||||
|
|
|
@ -3,6 +3,7 @@ package org.nuclearfog.twidda.ui.fragments;
|
|||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.result.ActivityResult;
|
||||
import androidx.activity.result.ActivityResultCallback;
|
||||
|
@ -11,16 +12,21 @@ import androidx.activity.result.contract.ActivityResultContracts;
|
|||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.nuclearfog.twidda.R;
|
||||
import org.nuclearfog.twidda.backend.async.AsyncExecutor.AsyncCallback;
|
||||
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.async.HashtagAction;
|
||||
import org.nuclearfog.twidda.backend.async.HashtagAction.HashtagActionParam;
|
||||
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.model.Hashtag;
|
||||
import org.nuclearfog.twidda.model.lists.Trends;
|
||||
import org.nuclearfog.twidda.ui.activities.SearchActivity;
|
||||
import org.nuclearfog.twidda.ui.adapter.recyclerview.TrendAdapter;
|
||||
import org.nuclearfog.twidda.ui.adapter.recyclerview.TrendAdapter.TrendClickListener;
|
||||
import org.nuclearfog.twidda.ui.adapter.recyclerview.HashtagAdapter;
|
||||
import org.nuclearfog.twidda.ui.adapter.recyclerview.HashtagAdapter.OnHashtagClickListener;
|
||||
import org.nuclearfog.twidda.ui.dialogs.ConfirmDialog;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
@ -29,7 +35,7 @@ import java.io.Serializable;
|
|||
*
|
||||
* @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
|
||||
|
@ -72,18 +78,26 @@ public class HashtagFragment extends ListFragment implements TrendClickListener,
|
|||
|
||||
private ActivityResultLauncher<Intent> activityResultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), this);
|
||||
|
||||
private TrendLoader trendLoader;
|
||||
private TrendAdapter adapter;
|
||||
private AsyncCallback<HashtagActionResult> hashtagActionCallback = this::onHashtagActionResult;
|
||||
private AsyncCallback<HashtagLoaderResult> hashtagLoaderCallback = this::onHashtagLoaderResult;
|
||||
|
||||
private HashtagLoader hashtagLoader;
|
||||
private HashtagAction hashtagAction;
|
||||
private HashtagAdapter adapter;
|
||||
private ConfirmDialog confirmDialog;
|
||||
|
||||
private int mode = 0;
|
||||
private String search = "";
|
||||
private Hashtag selection;
|
||||
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
adapter = new TrendAdapter(this);
|
||||
trendLoader = new TrendLoader(requireContext());
|
||||
adapter = new HashtagAdapter(this);
|
||||
hashtagLoader = new HashtagLoader(requireContext());
|
||||
hashtagAction = new HashtagAction(requireContext());
|
||||
confirmDialog = new ConfirmDialog(requireActivity(), this);
|
||||
setAdapter(adapter);
|
||||
|
||||
Bundle args = getArguments();
|
||||
|
@ -91,15 +105,18 @@ public class HashtagFragment extends ListFragment implements TrendClickListener,
|
|||
search = args.getString(KEY_SEARCH, "");
|
||||
mode = args.getInt(KEY_MODE, 0);
|
||||
}
|
||||
if (mode == MODE_FOLLOW || mode == MODE_FEATURE) {
|
||||
adapter.enableDelete();
|
||||
}
|
||||
if (savedInstanceState != null) {
|
||||
Serializable data = savedInstanceState.getSerializable(KEY_DATA);
|
||||
if (data instanceof Trends) {
|
||||
adapter.addItems((Trends) data, TrendAdapter.CLEAR_LIST);
|
||||
adapter.addItems((Trends) data, HashtagAdapter.CLEAR_LIST);
|
||||
return;
|
||||
}
|
||||
}
|
||||
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
|
||||
public void onDestroy() {
|
||||
trendLoader.cancel();
|
||||
hashtagLoader.cancel();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
|
@ -120,15 +137,15 @@ public class HashtagFragment extends ListFragment implements TrendClickListener,
|
|||
@Override
|
||||
protected void onReset() {
|
||||
adapter.clear();
|
||||
trendLoader = new TrendLoader(requireContext());
|
||||
load(TrendParameter.NO_CURSOR, TrendAdapter.CLEAR_LIST);
|
||||
hashtagLoader = new HashtagLoader(requireContext());
|
||||
load(HashtagLoaderParam.NO_CURSOR, HashtagAdapter.CLEAR_LIST);
|
||||
setRefresh(true);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
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
|
||||
public void onTrendClick(Hashtag hashtag) {
|
||||
if (!isRefreshing()) {
|
||||
Intent intent = new Intent(requireContext(), SearchActivity.class);
|
||||
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, hashtag);
|
||||
public void onHashtagClick(Hashtag hashtag, int action) {
|
||||
if (action == OnHashtagClickListener.SELECT) {
|
||||
if (!isRefreshing()) {
|
||||
Intent intent = new Intent(requireContext(), SearchActivity.class);
|
||||
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, 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
|
||||
public boolean onPlaceholderClick(long cursor, int index) {
|
||||
if (trendLoader.isIdle()) {
|
||||
if (hashtagLoader.isIdle()) {
|
||||
load(cursor, index);
|
||||
return true;
|
||||
}
|
||||
|
@ -176,8 +204,36 @@ public class HashtagFragment extends ListFragment implements TrendClickListener,
|
|||
|
||||
|
||||
@Override
|
||||
public void onResult(@NonNull TrendResult result) {
|
||||
if (result.mode == TrendResult.ERROR) {
|
||||
public void onConfirm(int type, boolean remember) {
|
||||
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) {
|
||||
ErrorUtils.showErrorMessage(getContext(), result.exception);
|
||||
}
|
||||
|
@ -192,30 +248,30 @@ public class HashtagFragment extends ListFragment implements TrendClickListener,
|
|||
* load content into the list
|
||||
*/
|
||||
private void load(long cursor, int index) {
|
||||
TrendParameter param;
|
||||
HashtagLoaderParam param;
|
||||
switch (mode) {
|
||||
case MODE_POPULAR:
|
||||
if (adapter.isEmpty()) {
|
||||
param = new TrendParameter(TrendParameter.POPULAR_OFFLINE, index, search, cursor);
|
||||
param = new HashtagLoaderParam(HashtagLoaderParam.POPULAR_OFFLINE, index, search, cursor);
|
||||
} 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;
|
||||
|
||||
case MODE_FOLLOW:
|
||||
param = new TrendParameter(TrendParameter.FOLLOWING, index, search, cursor);
|
||||
trendLoader.execute(param, this);
|
||||
param = new HashtagLoaderParam(HashtagLoaderParam.FOLLOWING, index, search, cursor);
|
||||
hashtagLoader.execute(param, hashtagLoaderCallback);
|
||||
break;
|
||||
|
||||
case MODE_FEATURE:
|
||||
param = new TrendParameter(TrendParameter.FEATURING, index, search, cursor);
|
||||
trendLoader.execute(param, this);
|
||||
param = new HashtagLoaderParam(HashtagLoaderParam.FEATURING, index, search, cursor);
|
||||
hashtagLoader.execute(param, hashtagLoaderCallback);
|
||||
break;
|
||||
|
||||
case MODE_SEARCH:
|
||||
param = new TrendParameter(TrendParameter.SEARCH, index, search, cursor);
|
||||
trendLoader.execute(param, this);
|
||||
param = new HashtagLoaderParam(HashtagLoaderParam.SEARCH, index, search, cursor);
|
||||
hashtagLoader.execute(param, hashtagLoaderCallback);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,16 +9,16 @@
|
|||
android:id="@+id/item_trend_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="@dimen/trenditem_layout_padding">
|
||||
android:padding="@dimen/item_hashtag_layout_padding">
|
||||
|
||||
<TextView
|
||||
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:gravity="center_vertical|end"
|
||||
android:lines="1"
|
||||
android:textAlignment="gravity"
|
||||
android:textSize="@dimen/trenditem_textsize_trendindex"
|
||||
android:textSize="@dimen/item_hashtag_textsize_trendindex"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/item_trend_name"
|
||||
|
@ -28,28 +28,42 @@
|
|||
android:id="@+id/item_trend_name"
|
||||
android:layout_width="0dp"
|
||||
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:textSize="@dimen/trenditem_textsize_trendname"
|
||||
android:textSize="@dimen/item_hashtag_textsize_trendname"
|
||||
app:layout_constraintStart_toEndOf="@id/item_trend_rank"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
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" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/item_trend_vol"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/trenditem_text_margin"
|
||||
android:layout_marginStart="@dimen/item_hashtag_layout_margin"
|
||||
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_constraintTop_toBottomOf="@id/item_trend_name"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
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.cardview.widget.CardView>
|
|
@ -80,7 +80,7 @@
|
|||
app:layout_constraintStart_toEndOf="@id/item_user_verified"
|
||||
app:layout_constraintTop_toTopOf="@id/item_user_profile"
|
||||
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
|
||||
android:id="@+id/item_user_private"
|
||||
|
@ -106,7 +106,7 @@
|
|||
app:layout_constraintStart_toEndOf="@id/item_user_private"
|
||||
app:layout_constraintTop_toBottomOf="@id/item_user_username"
|
||||
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
|
||||
android:id="@+id/item_user_following_icon"
|
||||
|
@ -157,10 +157,10 @@
|
|||
app:layout_constraintStart_toEndOf="@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_constraintEnd_toStartOf="@id/item_user_delete_buton" />
|
||||
app:layout_constraintEnd_toStartOf="@id/item_user_delete_button" />
|
||||
|
||||
<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_height="@dimen/item_user_button_size"
|
||||
android:visibility="invisible"
|
||||
|
|
|
@ -209,6 +209,7 @@
|
|||
<string name="menu_hint_mute_user">\@name stummschalten</string>
|
||||
<string name="menu_hint_block_user">\@name blockieren</string>
|
||||
<string name="menu_exclude_user">Nutzer ausschließen</string>
|
||||
<string name="menu_hashtag_add">Hashtag hinzufügen</string>
|
||||
<string name="menu_search_filter">Ergebnisse filtern</string>
|
||||
<string name="menu_hint_block_domain">domain.namen eingeben</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_high">Dauer der Umfrage ist zu lang!</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_unfollow">entfolge Hashtag</string>
|
||||
<string name="info_hashtag_unfollowed">Hashtag entfolgt</string>
|
||||
<string name="info_domain_removed">Domain von der Liste entfernt</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_favorite">bei Favorisierung</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_selection">es muss mindestens ein Filter aktiviert sein</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>
|
|
@ -92,13 +92,15 @@
|
|||
<dimen name="item_status_indicator_padding">6sp</dimen>
|
||||
<dimen name="item_status_indicator_size">26sp</dimen>
|
||||
|
||||
<!--dimens of item_trend.xml-->
|
||||
<dimen name="trenditem_layout_padding">5dp</dimen>
|
||||
<dimen name="trenditem_text_margin">5dp</dimen>
|
||||
<dimen name="trenditem_textsize_trendindex">20sp</dimen>
|
||||
<dimen name="trenditem_textsize_trendname">20sp</dimen>
|
||||
<dimen name="trenditem_textsize_trendvol">14sp</dimen>
|
||||
<dimen name="trenditem_textsize_trendindex_width">40sp</dimen>
|
||||
<!--dimens of item_hashtag.xml-->
|
||||
<dimen name="item_hashtag_layout_padding">5dp</dimen>
|
||||
<dimen name="item_hashtag_layout_margin">5dp</dimen>
|
||||
<dimen name="item_hashtag_button_size">20sp</dimen>
|
||||
<dimen name="item_hashtag_button_padding">1dp</dimen>
|
||||
<dimen name="item_hashtag_textsize_trendindex">20sp</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-->
|
||||
<dimen name="item_user_image_size">56sp</dimen>
|
||||
|
|
|
@ -78,6 +78,7 @@
|
|||
<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_hashtag_unfeatured">Hashtag unfeatured</string>
|
||||
<string name="info_status_reported">Status reported</string>
|
||||
<string name="info_error">Error</string>
|
||||
|
||||
|
@ -289,6 +290,7 @@
|
|||
<string name="update_list">update 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_hashtag">remove hashtag from list</string>
|
||||
<string name="descr_remove_domain">remove domain from list</string>
|
||||
<string name="confirm_unknown_error">unknown error!</string>
|
||||
<string name="list_following_indicator">following list</string>
|
||||
|
@ -307,6 +309,8 @@
|
|||
<string name="confirm_remember">remember choice</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_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_filter">delete filter?</string>
|
||||
<string name="account_user_unnamed">\'unnamed\'</string>
|
||||
|
|
Loading…
Reference in New Issue