improve cache
This commit is contained in:
parent
550187afc5
commit
03bf06b6a0
|
@ -76,8 +76,8 @@ public class QuickLoad {
|
|||
* @param timeLineType - Timeline.TimeLineEnum
|
||||
* @return boolean
|
||||
*/
|
||||
private static boolean cannotBeStored(Timeline.TimeLineEnum timeLineType) {
|
||||
return timeLineType != Timeline.TimeLineEnum.HOME && timeLineType != Timeline.TimeLineEnum.LOCAL && timeLineType != Timeline.TimeLineEnum.PUBLIC && timeLineType != Timeline.TimeLineEnum.REMOTE && timeLineType != Timeline.TimeLineEnum.LIST && timeLineType != Timeline.TimeLineEnum.TAG;
|
||||
public static boolean cannotBeStored(Timeline.TimeLineEnum timeLineType) {
|
||||
return timeLineType != Timeline.TimeLineEnum.LOCAL && timeLineType != Timeline.TimeLineEnum.PUBLIC && timeLineType != Timeline.TimeLineEnum.REMOTE && timeLineType != Timeline.TimeLineEnum.LIST && timeLineType != Timeline.TimeLineEnum.TAG;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -27,6 +27,7 @@ import java.util.Collections;
|
|||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import app.fedilab.android.activities.MainActivity;
|
||||
import app.fedilab.android.client.entities.api.Pagination;
|
||||
import app.fedilab.android.client.entities.api.Status;
|
||||
import app.fedilab.android.client.entities.api.Statuses;
|
||||
|
@ -44,8 +45,10 @@ public class StatusCache {
|
|||
public String user_id;
|
||||
@SerializedName("instance")
|
||||
public String instance;
|
||||
@SerializedName("slug")
|
||||
public String slug;
|
||||
@SerializedName("type")
|
||||
public CacheEnum type;
|
||||
public Timeline.TimeLineEnum type;
|
||||
@SerializedName("status_id")
|
||||
public String status_id;
|
||||
@SerializedName("status")
|
||||
|
@ -104,16 +107,17 @@ public class StatusCache {
|
|||
* @return long - db id
|
||||
* @throws DBException exception with database
|
||||
*/
|
||||
public long insertOrUpdate(StatusCache statusCache) throws DBException {
|
||||
public long insertOrUpdate(StatusCache statusCache, String slug) throws DBException {
|
||||
if (db == null) {
|
||||
throw new DBException("db is null. Wrong initialization.");
|
||||
}
|
||||
statusCache.slug = slug;
|
||||
boolean exists = statusExist(statusCache);
|
||||
long idReturned;
|
||||
if (exists) {
|
||||
idReturned = updateStatus(statusCache);
|
||||
} else {
|
||||
idReturned = insertStatus(statusCache);
|
||||
idReturned = insertStatus(statusCache, slug);
|
||||
}
|
||||
return idReturned;
|
||||
}
|
||||
|
@ -155,6 +159,27 @@ public class StatusCache {
|
|||
return (count > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a status exists in db
|
||||
*
|
||||
* @param status Status {@link Status}
|
||||
* @return boolean - StatusCache exists
|
||||
* @throws DBException Exception
|
||||
*/
|
||||
public boolean statusExist(Status status) throws DBException {
|
||||
if (db == null) {
|
||||
throw new DBException("db is null. Wrong initialization.");
|
||||
}
|
||||
Cursor mCount = db.rawQuery("select count(*) from " + Sqlite.TABLE_STATUS_CACHE
|
||||
+ " where " + Sqlite.COL_STATUS_ID + " = '" + status.id + "'"
|
||||
+ " AND " + Sqlite.COL_INSTANCE + " = '" + MainActivity.currentInstance + "'"
|
||||
+ " AND " + Sqlite.COL_USER_ID + "= '" + MainActivity.currentUserID + "'", null);
|
||||
mCount.moveToFirst();
|
||||
int count = mCount.getInt(0);
|
||||
mCount.close();
|
||||
return (count > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a status in db
|
||||
*
|
||||
|
@ -162,14 +187,14 @@ public class StatusCache {
|
|||
* @return long - db id
|
||||
* @throws DBException exception with database
|
||||
*/
|
||||
private long insertStatus(StatusCache statusCache) throws DBException {
|
||||
private long insertStatus(StatusCache statusCache, String slug) throws DBException {
|
||||
if (db == null) {
|
||||
throw new DBException("db is null. Wrong initialization.");
|
||||
}
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(Sqlite.COL_USER_ID, statusCache.user_id);
|
||||
values.put(Sqlite.COL_INSTANCE, statusCache.instance);
|
||||
values.put(Sqlite.COL_TYPE, statusCache.type.getValue());
|
||||
values.put(Sqlite.COL_SLUG, statusCache.slug);
|
||||
values.put(Sqlite.COL_STATUS_ID, statusCache.status_id);
|
||||
values.put(Sqlite.COL_STATUS, mastodonStatusToStringStorage(statusCache.status));
|
||||
values.put(Sqlite.COL_CREATED_AT, Helper.dateToString(new Date()));
|
||||
|
@ -195,9 +220,6 @@ public class StatusCache {
|
|||
}
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(Sqlite.COL_USER_ID, statusCache.user_id);
|
||||
if (statusCache.type != null) {
|
||||
values.put(Sqlite.COL_TYPE, statusCache.type.getValue());
|
||||
}
|
||||
values.put(Sqlite.COL_STATUS_ID, statusCache.status_id);
|
||||
values.put(Sqlite.COL_STATUS, mastodonStatusToStringStorage(statusCache.status));
|
||||
values.put(Sqlite.COL_UPDATED_AT, Helper.dateToString(new Date()));
|
||||
|
@ -274,10 +296,63 @@ public class StatusCache {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get newest status for a timeline
|
||||
*
|
||||
* @param slug String - slug for the timeline (it's a unique string value for a timeline)
|
||||
* @param instance String - instance
|
||||
* @param user_id String - us
|
||||
* @return Statuses
|
||||
* @throws DBException - throws a db exception
|
||||
*/
|
||||
public Status getNewestStatus(String slug, String instance, String user_id) throws DBException {
|
||||
if (db == null) {
|
||||
throw new DBException("db is null. Wrong initialization.");
|
||||
}
|
||||
String selection = Sqlite.COL_INSTANCE + "='" + instance + "' AND " + Sqlite.COL_USER_ID + "= '" + user_id + "' AND " + Sqlite.COL_SLUG + "= '" + slug + "'";
|
||||
try {
|
||||
Cursor c = db.query(Sqlite.TABLE_STATUS_CACHE, null, selection, null, null, null, Sqlite.COL_STATUS_ID + " DESC", "1");
|
||||
Statuses statuses = createStatusReply(cursorToListOfStatuses(c));
|
||||
if (statuses.statuses != null && statuses.statuses.size() > 0) {
|
||||
return statuses.statuses.get(0);
|
||||
} else return null;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get oldest status for a timeline
|
||||
*
|
||||
* @param slug String - slug for the timeline (it's a unique string value for a timeline)
|
||||
* @param instance String - instance
|
||||
* @param user_id String - us
|
||||
* @return Statuses
|
||||
* @throws DBException - throws a db exception
|
||||
*/
|
||||
public Status getOldestStatus(String slug, String instance, String user_id) throws DBException {
|
||||
if (db == null) {
|
||||
throw new DBException("db is null. Wrong initialization.");
|
||||
}
|
||||
String selection = Sqlite.COL_INSTANCE + "='" + instance + "' AND " + Sqlite.COL_USER_ID + "= '" + user_id + "' AND " + Sqlite.COL_SLUG + "= '" + slug + "'";
|
||||
try {
|
||||
Cursor c = db.query(Sqlite.TABLE_STATUS_CACHE, null, selection, null, null, null, Sqlite.COL_STATUS_ID + " ASC", "1");
|
||||
Statuses statuses = createStatusReply(cursorToListOfStatuses(c));
|
||||
if (statuses.statuses != null && statuses.statuses.size() > 0) {
|
||||
return statuses.statuses.get(0);
|
||||
} else return null;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get paginated statuses from db
|
||||
*
|
||||
* @param type CacheEnum - not used yet but will allow to extend cache to other timelines
|
||||
* @param slug String - slug for the timeline (it's a unique string value for a timeline)
|
||||
* @param instance String - instance
|
||||
* @param user_id String - us
|
||||
* @param max_id String - status having max id
|
||||
|
@ -285,12 +360,12 @@ public class StatusCache {
|
|||
* @return Statuses
|
||||
* @throws DBException - throws a db exception
|
||||
*/
|
||||
public Statuses geStatuses(CacheEnum type, String instance, String user_id, String max_id, String min_id, String since_id) throws DBException {
|
||||
public Statuses geStatuses(String slug, String instance, String user_id, String max_id, String min_id, String since_id) throws DBException {
|
||||
if (db == null) {
|
||||
throw new DBException("db is null. Wrong initialization.");
|
||||
}
|
||||
String order = " DESC";
|
||||
String selection = Sqlite.COL_INSTANCE + "='" + instance + "' AND " + Sqlite.COL_USER_ID + "= '" + user_id + "'";
|
||||
String selection = Sqlite.COL_INSTANCE + "='" + instance + "' AND " + Sqlite.COL_USER_ID + "= '" + user_id + "' AND " + Sqlite.COL_SLUG + "= '" + slug + "'";
|
||||
String limit = String.valueOf(MastodonHelper.statusesPerCall(context));
|
||||
if (min_id != null) {
|
||||
selection += "AND " + Sqlite.COL_STATUS_ID + " > '" + min_id + "'";
|
||||
|
@ -310,16 +385,70 @@ public class StatusCache {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get statuses from db
|
||||
*
|
||||
* @return Statuses
|
||||
* @throws DBException - throws a db exception
|
||||
*/
|
||||
public Status getTopFetchMore(String slug, String instance, String user_id, String status_id) throws DBException {
|
||||
if (db == null) {
|
||||
throw new DBException("db is null. Wrong initialization.");
|
||||
}
|
||||
String selection = Sqlite.COL_INSTANCE + "='" + instance + "' AND "
|
||||
+ Sqlite.COL_USER_ID + "= '" + user_id + "' AND "
|
||||
+ Sqlite.COL_SLUG + "= '" + slug + "' AND "
|
||||
+ Sqlite.COL_STATUS_ID + " > '" + status_id + "'";
|
||||
try {
|
||||
Cursor c = db.query(Sqlite.TABLE_STATUS_CACHE, null, selection, null, null, null, Sqlite.COL_STATUS_ID + " ASC", "1");
|
||||
if (c != null && c.getCount() > 0) {
|
||||
return convertCursorToStatus(c);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param type CacheEnum - not used yet but will allow to extend cache to other timelines
|
||||
* Get statuses from db
|
||||
*
|
||||
* @param statusCache StatusCache - status in cache to compare
|
||||
* @return Statuses
|
||||
* @throws DBException - throws a db exception
|
||||
*/
|
||||
public Status getBottomFetchMore(String slug, String instance, String user_id, String status_id) throws DBException {
|
||||
if (db == null) {
|
||||
throw new DBException("db is null. Wrong initialization.");
|
||||
}
|
||||
String selection = Sqlite.COL_INSTANCE + "='" + instance + "' AND "
|
||||
+ Sqlite.COL_USER_ID + "= '" + user_id + "' AND "
|
||||
+ Sqlite.COL_SLUG + "= '" + slug + "' AND "
|
||||
+ Sqlite.COL_STATUS_ID + " < '" + status_id + "'";
|
||||
try {
|
||||
Cursor c = db.query(Sqlite.TABLE_STATUS_CACHE, null, selection, null, null, null, Sqlite.COL_STATUS_ID + " DESC", "1");
|
||||
if (c != null && c.getCount() > 0) {
|
||||
return convertCursorToStatus(c);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param slug String - slug for the timeline (it's a unique string value for a timeline)
|
||||
* @param instance String - instance
|
||||
* @param user_id String - us
|
||||
* @param search String search
|
||||
* @return - List<Status>
|
||||
* @throws DBException exception
|
||||
*/
|
||||
public List<Status> searchStatus(CacheEnum type, String instance, String user_id, String search) throws DBException {
|
||||
public List<Status> searchStatus(String slug, String instance, String user_id, String search) throws DBException {
|
||||
if (db == null) {
|
||||
throw new DBException("db is null. Wrong initialization.");
|
||||
}
|
||||
|
@ -343,6 +472,22 @@ public class StatusCache {
|
|||
return reply;
|
||||
}
|
||||
|
||||
public enum order {
|
||||
@SerializedName("ASC")
|
||||
ASC("ASC"),
|
||||
@SerializedName("DESC")
|
||||
DESC("DESC");
|
||||
private final String value;
|
||||
|
||||
order(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int count(BaseAccount account) throws DBException {
|
||||
if (db == null) {
|
||||
|
@ -412,17 +557,4 @@ public class StatusCache {
|
|||
return restoreStatusFromString(serializedStatus);
|
||||
}
|
||||
|
||||
public enum CacheEnum {
|
||||
@SerializedName("HOME")
|
||||
HOME("HOME");
|
||||
private final String value;
|
||||
|
||||
CacheEnum(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ import android.database.sqlite.SQLiteOpenHelper;
|
|||
public class Sqlite extends SQLiteOpenHelper {
|
||||
|
||||
|
||||
public static final int DB_VERSION = 5;
|
||||
public static final int DB_VERSION = 6;
|
||||
public static final String DB_NAME = "fedilab_db";
|
||||
|
||||
//Table of owned accounts
|
||||
|
@ -111,6 +111,7 @@ public class Sqlite extends SQLiteOpenHelper {
|
|||
+ COL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
|
||||
+ COL_USER_ID + " TEXT NOT NULL, " + COL_INSTANCE + " TEXT NOT NULL, "
|
||||
+ COL_TYPE + " TEXT NOT NULL, "
|
||||
+ COL_SLUG + " TEXT, "
|
||||
+ COL_STATUS_ID + " TEXT NOT NULL, "
|
||||
+ COL_STATUS + " TEXT NOT NULL, "
|
||||
+ COL_CREATED_AT + " TEXT NOT NULL,"
|
||||
|
@ -202,7 +203,6 @@ public class Sqlite extends SQLiteOpenHelper {
|
|||
db.execSQL(CREATE_TABLE_STATUS_DRAFT);
|
||||
db.execSQL(CREATE_TABLE_PINNED_TIMELINES);
|
||||
db.execSQL(CREATE_TABLE_SCHEDULE_BOOST);
|
||||
db.execSQL(CREATE_TABLE_QUICK_LOAD);
|
||||
db.execSQL(CREATE_TABLE_BOTTOM_MENU);
|
||||
db.execSQL(CREATE_DOMAINS_TRACKING);
|
||||
}
|
||||
|
@ -223,6 +223,10 @@ public class Sqlite extends SQLiteOpenHelper {
|
|||
db.execSQL("ALTER TABLE " + TABLE_USER_ACCOUNT + " ADD COLUMN " + COL_ADMIN + " INTEGER NOT NULL DEFAULT 0");
|
||||
case 4:
|
||||
db.execSQL(CREATE_DOMAINS_TRACKING);
|
||||
case 5:
|
||||
db.execSQL("ALTER TABLE " + TABLE_STATUS_CACHE + " ADD COLUMN " + COL_SLUG + " TEXT");
|
||||
db.execSQL("DELETE FROM " + TABLE_STATUS_CACHE);
|
||||
db.execSQL("DROP TABLE IF EXISTS " + TABLE_QUICK_LOAD);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -44,7 +44,6 @@ import app.fedilab.android.BaseMainActivity;
|
|||
import app.fedilab.android.R;
|
||||
import app.fedilab.android.client.entities.api.Account;
|
||||
import app.fedilab.android.client.entities.api.Attachment;
|
||||
import app.fedilab.android.client.entities.api.Marker;
|
||||
import app.fedilab.android.client.entities.api.Pagination;
|
||||
import app.fedilab.android.client.entities.api.Status;
|
||||
import app.fedilab.android.client.entities.api.Statuses;
|
||||
|
@ -127,7 +126,6 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
|
|||
}
|
||||
}
|
||||
};
|
||||
private List<String> markers;
|
||||
private String list_id;
|
||||
private TagTimeline tagTimeline;
|
||||
private LinearLayoutManager mLayoutManager;
|
||||
|
@ -251,8 +249,6 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
|
|||
|
||||
binding.loader.setVisibility(View.VISIBLE);
|
||||
binding.recyclerView.setVisibility(View.GONE);
|
||||
//Markers for home and notifications to get last read ones
|
||||
markers = new ArrayList<>();
|
||||
max_id = statusReport != null ? statusReport.id : null;
|
||||
flagLoading = false;
|
||||
router(null);
|
||||
|
@ -557,7 +553,12 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
|
|||
if (statuses != null && statuses.size() > position) {
|
||||
try {
|
||||
Status status = statuses.get(position);
|
||||
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity());
|
||||
SharedPreferences.Editor editor = sharedpreferences.edit();
|
||||
editor.putString(getString(R.string.SET_HOME_INNER_MARKER) + BaseMainActivity.currentUserID + BaseMainActivity.currentInstance, status.id);
|
||||
editor.apply();
|
||||
timelinesVM.addMarker(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, status.id, null);
|
||||
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
@ -579,6 +580,66 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Router for timelines
|
||||
*
|
||||
* @param direction - DIRECTION null if first call, then is set to TOP or BOTTOM depending of scroll
|
||||
*/
|
||||
private void routeCommon(DIRECTION direction, boolean fetchingMissing) {
|
||||
if (binding == null || getActivity() == null || !isAdded()) {
|
||||
return;
|
||||
}
|
||||
//Initialize with default params
|
||||
TimelinesVM.TimelineParams timelineParams = new TimelinesVM.TimelineParams(timelineType, direction, ident);
|
||||
timelineParams.limit = MastodonHelper.statusesPerCall(requireActivity());
|
||||
timelineParams.maxId = fetchingMissing ? max_id_fetch_more : max_id;
|
||||
timelineParams.minId = fetchingMissing ? min_id_fetch_more : min_id;
|
||||
timelineParams.fetchingMissing = fetchingMissing;
|
||||
switch (timelineType) {
|
||||
case LOCAL:
|
||||
timelineParams.local = true;
|
||||
timelineParams.remote = false;
|
||||
break;
|
||||
case PUBLIC:
|
||||
timelineParams.local = false;
|
||||
timelineParams.remote = true;
|
||||
break;
|
||||
case LIST:
|
||||
timelineParams.listId = list_id;
|
||||
break;
|
||||
case TAG:
|
||||
if (tagTimeline == null) {
|
||||
tagTimeline = new TagTimeline();
|
||||
tagTimeline.name = search;
|
||||
}
|
||||
timelineParams.onlyMedia = timelineType == Timeline.TimeLineEnum.ART;
|
||||
timelineParams.none = tagTimeline.none;
|
||||
timelineParams.all = tagTimeline.all;
|
||||
timelineParams.any = tagTimeline.any;
|
||||
timelineParams.hashtagTrim = tagTimeline.name;
|
||||
break;
|
||||
}
|
||||
if (direction == null) {
|
||||
timelinesVM.getTimeline(timelineParams)
|
||||
.observe(getViewLifecycleOwner(), this::initializeStatusesCommonView);
|
||||
} else if (direction == DIRECTION.BOTTOM) {
|
||||
timelinesVM.getTimeline(timelineParams)
|
||||
.observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.BOTTOM, fetchingMissing));
|
||||
} else if (direction == DIRECTION.TOP) {
|
||||
timelinesVM.getTimeline(timelineParams)
|
||||
.observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.TOP, fetchingMissing));
|
||||
} else if (direction == DIRECTION.REFRESH || direction == DIRECTION.SCROLL_TOP) {
|
||||
timelinesVM.getTimeline(timelineParams)
|
||||
.observe(getViewLifecycleOwner(), statusesRefresh -> {
|
||||
if (statusAdapter != null) {
|
||||
dealWithPagination(statusesRefresh, direction, true);
|
||||
} else {
|
||||
initializeStatusesCommonView(statusesRefresh);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Router for timelines
|
||||
*
|
||||
|
@ -589,17 +650,26 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
|
|||
if (binding == null || getActivity() == null || !isAdded()) {
|
||||
return;
|
||||
}
|
||||
boolean nitterInstance = timelineType == Timeline.TimeLineEnum.REMOTE && pinnedTimeline != null && pinnedTimeline.remoteInstance.type == RemoteInstance.InstanceType.NITTER;
|
||||
QuickLoad quickLoad = new QuickLoad(requireActivity()).getSavedValue(BaseMainActivity.currentUserID, BaseMainActivity.currentInstance, timelineType, ident);
|
||||
boolean nitterInstance = false;
|
||||
//For remote instance, we check if it's a Nitter timeline
|
||||
if (timelineType == Timeline.TimeLineEnum.REMOTE) {
|
||||
nitterInstance = pinnedTimeline != null && pinnedTimeline.remoteInstance.type == RemoteInstance.InstanceType.NITTER;
|
||||
}
|
||||
QuickLoad quickLoad = null;
|
||||
//For timelines that can be stored we check if there is a stored TL in db
|
||||
//HOME TL, is excluded and should use its own cache
|
||||
if (!QuickLoad.cannotBeStored(timelineType)) {
|
||||
quickLoad = new QuickLoad(requireActivity()).getSavedValue(BaseMainActivity.currentUserID, BaseMainActivity.currentInstance, timelineType, ident);
|
||||
}
|
||||
if (!nitterInstance && !fetchingMissing && !binding.swipeContainer.isRefreshing() && direction == null && quickLoad != null && quickLoad.statuses != null && quickLoad.statuses.size() > 0) {
|
||||
Statuses statuses = new Statuses();
|
||||
statuses.statuses = quickLoad.statuses;
|
||||
statuses.pagination = new Pagination();
|
||||
statuses.pagination.max_id = quickLoad.statuses.get(quickLoad.statuses.size() - 1).id;
|
||||
statuses.pagination.min_id = quickLoad.statuses.get(0).id;
|
||||
|
||||
Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||
Runnable myRunnable = () -> initializeStatusesCommonView(statuses, quickLoad.position);
|
||||
QuickLoad finalQuickLoad = quickLoad;
|
||||
Runnable myRunnable = () -> initializeStatusesCommonView(statuses, finalQuickLoad.position);
|
||||
mainHandler.post(myRunnable);
|
||||
} else {
|
||||
Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||
|
@ -610,49 +680,12 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
|
|||
// --- HOME TIMELINE ---
|
||||
if (timelineType == Timeline.TimeLineEnum.HOME) {
|
||||
//for more visibility it's done through loadHomeStrategy method
|
||||
loadHomeStrategy(direction, fetchingMissing);
|
||||
routeCommon(direction, fetchingMissing);
|
||||
} else if (timelineType == Timeline.TimeLineEnum.LOCAL) { //LOCAL TIMELINE
|
||||
if (direction == null) {
|
||||
timelinesVM.getPublic(BaseMainActivity.currentToken, BaseMainActivity.currentInstance, true, false, false, null, null, null, MastodonHelper.statusesPerCall(requireActivity()))
|
||||
.observe(getViewLifecycleOwner(), this::initializeStatusesCommonView);
|
||||
} else if (direction == DIRECTION.BOTTOM) {
|
||||
timelinesVM.getPublic(BaseMainActivity.currentToken, BaseMainActivity.currentInstance, true, false, false, fetchingMissing ? max_id_fetch_more : max_id, null, null, MastodonHelper.statusesPerCall(requireActivity()))
|
||||
.observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.BOTTOM, fetchingMissing));
|
||||
} else if (direction == DIRECTION.TOP) {
|
||||
timelinesVM.getPublic(BaseMainActivity.currentToken, BaseMainActivity.currentInstance, true, false, false, null, null, fetchingMissing ? min_id_fetch_more : min_id, MastodonHelper.statusesPerCall(requireActivity()))
|
||||
.observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.TOP, fetchingMissing));
|
||||
} else if (direction == DIRECTION.REFRESH || direction == DIRECTION.SCROLL_TOP) {
|
||||
timelinesVM.getPublic(BaseMainActivity.currentToken, BaseMainActivity.currentInstance, true, false, false, null, null, null, MastodonHelper.statusesPerCall(requireActivity()))
|
||||
.observe(getViewLifecycleOwner(), statusesRefresh -> {
|
||||
if (statusAdapter != null) {
|
||||
dealWithPagination(statusesRefresh, direction, true);
|
||||
} else {
|
||||
initializeStatusesCommonView(statusesRefresh);
|
||||
}
|
||||
});
|
||||
}
|
||||
routeCommon(direction, fetchingMissing);
|
||||
} else if (timelineType == Timeline.TimeLineEnum.PUBLIC) { //PUBLIC TIMELINE
|
||||
if (direction == null) {
|
||||
timelinesVM.getPublic(BaseMainActivity.currentToken, BaseMainActivity.currentInstance, false, true, false, null, null, null, MastodonHelper.statusesPerCall(requireActivity()))
|
||||
.observe(getViewLifecycleOwner(), this::initializeStatusesCommonView);
|
||||
} else if (direction == DIRECTION.BOTTOM) {
|
||||
timelinesVM.getPublic(BaseMainActivity.currentToken, BaseMainActivity.currentInstance, false, true, false, fetchingMissing ? max_id_fetch_more : max_id, null, null, MastodonHelper.statusesPerCall(requireActivity()))
|
||||
.observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.BOTTOM, fetchingMissing));
|
||||
} else if (direction == DIRECTION.TOP) {
|
||||
timelinesVM.getPublic(BaseMainActivity.currentToken, BaseMainActivity.currentInstance, false, true, false, null, null, fetchingMissing ? min_id_fetch_more : min_id, MastodonHelper.statusesPerCall(requireActivity()))
|
||||
.observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.TOP, fetchingMissing));
|
||||
} else if (direction == DIRECTION.REFRESH || direction == DIRECTION.SCROLL_TOP) {
|
||||
timelinesVM.getPublic(BaseMainActivity.currentToken, BaseMainActivity.currentInstance, false, true, false, null, null, null, MastodonHelper.statusesPerCall(requireActivity()))
|
||||
.observe(getViewLifecycleOwner(), statusesRefresh -> {
|
||||
if (statusAdapter != null) {
|
||||
dealWithPagination(statusesRefresh, direction, true);
|
||||
} else {
|
||||
initializeStatusesCommonView(statusesRefresh);
|
||||
}
|
||||
});
|
||||
}
|
||||
routeCommon(direction, fetchingMissing);
|
||||
} else if (timelineType == Timeline.TimeLineEnum.REMOTE) { //REMOTE TIMELINE
|
||||
|
||||
//NITTER TIMELINES
|
||||
if (pinnedTimeline != null && pinnedTimeline.remoteInstance.type == RemoteInstance.InstanceType.NITTER) {
|
||||
if (direction == null) {
|
||||
|
@ -718,70 +751,12 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
|
|||
});
|
||||
}
|
||||
} else { //Other remote timelines
|
||||
if (direction == null) {
|
||||
timelinesVM.getPublic(null, remoteInstance, true, false, false, null, null, null, MastodonHelper.statusesPerCall(requireActivity()))
|
||||
.observe(getViewLifecycleOwner(), this::initializeStatusesCommonView);
|
||||
} else if (direction == DIRECTION.BOTTOM) {
|
||||
timelinesVM.getPublic(null, remoteInstance, true, false, false, fetchingMissing ? max_id_fetch_more : max_id, null, null, MastodonHelper.statusesPerCall(requireActivity()))
|
||||
.observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.BOTTOM, fetchingMissing));
|
||||
} else if (direction == DIRECTION.TOP) {
|
||||
timelinesVM.getPublic(null, remoteInstance, true, false, false, null, null, fetchingMissing ? min_id_fetch_more : min_id, MastodonHelper.statusesPerCall(requireActivity()))
|
||||
.observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.TOP, fetchingMissing));
|
||||
} else if (direction == DIRECTION.REFRESH || direction == DIRECTION.SCROLL_TOP) {
|
||||
timelinesVM.getPublic(null, remoteInstance, true, false, false, null, null, null, MastodonHelper.statusesPerCall(requireActivity()))
|
||||
.observe(getViewLifecycleOwner(), statusesRefresh -> {
|
||||
if (statusAdapter != null) {
|
||||
dealWithPagination(statusesRefresh, direction, true);
|
||||
} else {
|
||||
initializeStatusesCommonView(statusesRefresh);
|
||||
}
|
||||
});
|
||||
}
|
||||
routeCommon(direction, fetchingMissing);
|
||||
}
|
||||
} else if (timelineType == Timeline.TimeLineEnum.LIST) { //LIST TIMELINE
|
||||
if (direction == null) {
|
||||
timelinesVM.getList(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, list_id, null, null, null, MastodonHelper.statusesPerCall(requireActivity()))
|
||||
.observe(getViewLifecycleOwner(), this::initializeStatusesCommonView);
|
||||
} else if (direction == DIRECTION.BOTTOM) {
|
||||
timelinesVM.getList(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, list_id, fetchingMissing ? max_id_fetch_more : max_id, null, null, MastodonHelper.statusesPerCall(requireActivity()))
|
||||
.observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.BOTTOM, fetchingMissing));
|
||||
} else if (direction == DIRECTION.TOP) {
|
||||
timelinesVM.getList(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, list_id, null, null, fetchingMissing ? min_id_fetch_more : min_id, MastodonHelper.statusesPerCall(requireActivity()))
|
||||
.observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.TOP, fetchingMissing));
|
||||
} else if (direction == DIRECTION.REFRESH || direction == DIRECTION.SCROLL_TOP) {
|
||||
timelinesVM.getList(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, list_id, null, null, null, MastodonHelper.statusesPerCall(requireActivity()))
|
||||
.observe(getViewLifecycleOwner(), statusesRefresh -> {
|
||||
if (statusAdapter != null) {
|
||||
dealWithPagination(statusesRefresh, direction, true);
|
||||
} else {
|
||||
initializeStatusesCommonView(statusesRefresh);
|
||||
}
|
||||
});
|
||||
}
|
||||
routeCommon(direction, fetchingMissing);
|
||||
} else if (timelineType == Timeline.TimeLineEnum.TAG || timelineType == Timeline.TimeLineEnum.ART) { //TAG TIMELINE
|
||||
if (tagTimeline == null) {
|
||||
tagTimeline = new TagTimeline();
|
||||
tagTimeline.name = search;
|
||||
}
|
||||
if (direction == null) {
|
||||
timelinesVM.getHashTag(BaseMainActivity.currentToken, BaseMainActivity.currentInstance, tagTimeline.name, false, tagTimeline.isART, tagTimeline.all, tagTimeline.any, tagTimeline.none, null, null, null, MastodonHelper.statusesPerCall(requireActivity()))
|
||||
.observe(getViewLifecycleOwner(), this::initializeStatusesCommonView);
|
||||
} else if (direction == DIRECTION.BOTTOM) {
|
||||
timelinesVM.getHashTag(BaseMainActivity.currentToken, BaseMainActivity.currentInstance, tagTimeline.name, false, tagTimeline.isART, tagTimeline.all, tagTimeline.any, tagTimeline.none, fetchingMissing ? max_id_fetch_more : max_id, null, null, MastodonHelper.statusesPerCall(requireActivity()))
|
||||
.observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.BOTTOM, fetchingMissing));
|
||||
} else if (direction == DIRECTION.TOP) {
|
||||
timelinesVM.getHashTag(BaseMainActivity.currentToken, BaseMainActivity.currentInstance, tagTimeline.name, false, tagTimeline.isART, tagTimeline.all, tagTimeline.any, tagTimeline.none, null, null, fetchingMissing ? min_id_fetch_more : min_id, MastodonHelper.statusesPerCall(requireActivity()))
|
||||
.observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.TOP, fetchingMissing));
|
||||
} else if (direction == DIRECTION.REFRESH || direction == DIRECTION.SCROLL_TOP) {
|
||||
timelinesVM.getHashTag(BaseMainActivity.currentToken, BaseMainActivity.currentInstance, tagTimeline.name, false, tagTimeline.isART, tagTimeline.all, tagTimeline.any, tagTimeline.none, null, null, null, MastodonHelper.statusesPerCall(requireActivity()))
|
||||
.observe(getViewLifecycleOwner(), statusesRefresh -> {
|
||||
if (statusAdapter != null) {
|
||||
dealWithPagination(statusesRefresh, direction, true);
|
||||
} else {
|
||||
initializeStatusesCommonView(statusesRefresh);
|
||||
}
|
||||
});
|
||||
}
|
||||
routeCommon(direction, fetchingMissing);
|
||||
} else if (timelineType == Timeline.TimeLineEnum.ACCOUNT_TIMELINE) { //PROFILE TIMELINES
|
||||
if (direction == null) {
|
||||
if (show_pinned) {
|
||||
|
@ -875,110 +850,6 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Load home timeline strategy
|
||||
*
|
||||
* @param direction - DIRECTION enum
|
||||
*/
|
||||
private void loadHomeStrategy(DIRECTION direction, boolean fetchingMissing) {
|
||||
//When no direction is provided, it means it's the first call
|
||||
if (direction == null && !fetchingMissing) {
|
||||
//Two ways, depending of the Internet connection
|
||||
//Connection is available toots are loaded remotely
|
||||
if (networkAvailable == BaseMainActivity.status.CONNECTED) {
|
||||
boolean fetchMarker = false;
|
||||
if (markers.isEmpty()) {
|
||||
markers.add("home");
|
||||
fetchMarker = true;
|
||||
}
|
||||
//We search for marker only once - It should not be fetched again when pull to refresh
|
||||
if (fetchMarker && !binding.swipeContainer.isRefreshing()) {
|
||||
//Search for last position
|
||||
timelinesVM.getMarker(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, markers).observe(getViewLifecycleOwner(), marker -> {
|
||||
if (marker != null) {
|
||||
Marker.MarkerContent markerContent = marker.home;
|
||||
if (markerContent != null) {
|
||||
max_id = markerContent.last_read_id;
|
||||
min_id = markerContent.last_read_id;
|
||||
} else {
|
||||
max_id = null;
|
||||
}
|
||||
} else {
|
||||
max_id = null;
|
||||
}
|
||||
timelinesVM.getHome(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, BaseMainActivity.currentUserID, false, max_id, null, null, MastodonHelper.statusesPerCall(requireActivity()), false)
|
||||
.observe(getViewLifecycleOwner(), this::initializeStatusesCommonView);
|
||||
});
|
||||
} else {
|
||||
timelinesVM.getHome(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, BaseMainActivity.currentUserID, false, max_id, null, null, MastodonHelper.statusesPerCall(requireActivity()), false)
|
||||
.observe(getViewLifecycleOwner(), this::initializeStatusesCommonView);
|
||||
}
|
||||
|
||||
} else {
|
||||
timelinesVM.getHomeCache(BaseMainActivity.currentInstance, BaseMainActivity.currentUserID, null, null, null)
|
||||
.observe(getViewLifecycleOwner(), cachedStatus -> {
|
||||
if (cachedStatus != null && cachedStatus.statuses != null) {
|
||||
initializeStatusesCommonView(cachedStatus);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
} else if (direction == DIRECTION.BOTTOM) {
|
||||
if (!fetchingMissing) {
|
||||
if (networkAvailable == BaseMainActivity.status.CONNECTED) {
|
||||
//We first if we get results from cache
|
||||
timelinesVM.getHomeCache(BaseMainActivity.currentInstance, BaseMainActivity.currentUserID, max_id, null, null)
|
||||
.observe(getViewLifecycleOwner(), statusesBottomCache -> {
|
||||
if (statusesBottomCache != null && statusesBottomCache.statuses != null && statusesBottomCache.statuses.size() > 0) {
|
||||
dealWithPagination(statusesBottomCache, DIRECTION.BOTTOM, false);
|
||||
} else { // If not, we fetch remotely
|
||||
timelinesVM.getHome(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, BaseMainActivity.currentUserID, false, max_id, null, null, MastodonHelper.statusesPerCall(requireActivity()), false)
|
||||
.observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.BOTTOM, false));
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
timelinesVM.getHomeCache(BaseMainActivity.currentInstance, BaseMainActivity.currentUserID, max_id, null, null)
|
||||
.observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.BOTTOM, false));
|
||||
}
|
||||
} else {
|
||||
timelinesVM.getHome(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, BaseMainActivity.currentUserID, true, max_id_fetch_more, null, null, MastodonHelper.statusesPerCall(requireActivity()), false)
|
||||
.observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.BOTTOM, true));
|
||||
}
|
||||
} else if (direction == DIRECTION.TOP) {
|
||||
if (!fetchingMissing) {
|
||||
if (networkAvailable == BaseMainActivity.status.CONNECTED) {
|
||||
timelinesVM.getHomeCache(BaseMainActivity.currentInstance, BaseMainActivity.currentUserID, null, min_id, null)
|
||||
.observe(getViewLifecycleOwner(), statusesTopCache -> {
|
||||
if (statusesTopCache != null && statusesTopCache.statuses != null && statusesTopCache.statuses.size() > 0) {
|
||||
dealWithPagination(statusesTopCache, DIRECTION.TOP, false);
|
||||
} else {
|
||||
timelinesVM.getHome(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, BaseMainActivity.currentUserID, false, null, null, min_id, MastodonHelper.statusesPerCall(requireActivity()), false)
|
||||
.observe(getViewLifecycleOwner(), statusesTop -> dealWithPagination(statusesTop, DIRECTION.TOP, false));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
timelinesVM.getHomeCache(BaseMainActivity.currentInstance, BaseMainActivity.currentUserID, null, min_id, null)
|
||||
.observe(getViewLifecycleOwner(), statusesTop -> dealWithPagination(statusesTop, DIRECTION.TOP, false));
|
||||
}
|
||||
} else {
|
||||
timelinesVM.getHome(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, BaseMainActivity.currentUserID, true, null, null, min_id_fetch_more, MastodonHelper.statusesPerCall(requireActivity()), false)
|
||||
.observe(getViewLifecycleOwner(), statusesTop -> dealWithPagination(statusesTop, DIRECTION.TOP, true));
|
||||
}
|
||||
|
||||
} else if (direction == DIRECTION.REFRESH || direction == DIRECTION.SCROLL_TOP) {
|
||||
timelinesVM.getHome(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, BaseMainActivity.currentUserID, true, null, null, null, MastodonHelper.statusesPerCall(requireActivity()), false)
|
||||
.observe(getViewLifecycleOwner(), statusRefresh -> {
|
||||
if (statusAdapter != null) {
|
||||
dealWithPagination(statusRefresh, direction, true);
|
||||
} else {
|
||||
initializeStatusesCommonView(statusRefresh);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Refresh status in list
|
||||
|
|
|
@ -22,6 +22,7 @@ import android.os.Handler;
|
|||
import android.os.Looper;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.lifecycle.AndroidViewModel;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
|
@ -32,6 +33,7 @@ import java.util.List;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import app.fedilab.android.R;
|
||||
import app.fedilab.android.activities.MainActivity;
|
||||
import app.fedilab.android.client.endpoints.MastodonTimelinesService;
|
||||
import app.fedilab.android.client.entities.api.Account;
|
||||
import app.fedilab.android.client.entities.api.Conversation;
|
||||
|
@ -45,6 +47,7 @@ import app.fedilab.android.client.entities.api.Tag;
|
|||
import app.fedilab.android.client.entities.app.BaseAccount;
|
||||
import app.fedilab.android.client.entities.app.StatusCache;
|
||||
import app.fedilab.android.client.entities.app.StatusDraft;
|
||||
import app.fedilab.android.client.entities.app.Timeline;
|
||||
import app.fedilab.android.client.entities.misskey.MisskeyNote;
|
||||
import app.fedilab.android.client.entities.nitter.Nitter;
|
||||
import app.fedilab.android.client.entities.peertube.PeertubeVideo;
|
||||
|
@ -52,6 +55,7 @@ import app.fedilab.android.exception.DBException;
|
|||
import app.fedilab.android.helper.Helper;
|
||||
import app.fedilab.android.helper.MastodonHelper;
|
||||
import app.fedilab.android.helper.TimelineHelper;
|
||||
import app.fedilab.android.ui.fragment.timeline.FragmentMastodonTimeline;
|
||||
import okhttp3.OkHttpClient;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Response;
|
||||
|
@ -162,50 +166,6 @@ public class TimelinesVM extends AndroidViewModel {
|
|||
return tagListMutableLiveData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public timeline
|
||||
*
|
||||
* @param local Show only local statuses? Defaults to false.
|
||||
* @param remote Show only remote statuses? Defaults to false.
|
||||
* @param onlyMedia Show only statuses with media attached? Defaults to false.
|
||||
* @param maxId Return results older than this id
|
||||
* @param sinceId Return results newer than this id
|
||||
* @param minId Return results immediately newer than this id
|
||||
* @param limit Maximum number of results to return. Defaults to 20.
|
||||
* @return {@link LiveData} containing a {@link Statuses}
|
||||
*/
|
||||
public LiveData<Statuses> getPublic(String token, @NonNull String instance,
|
||||
Boolean local,
|
||||
Boolean remote,
|
||||
Boolean onlyMedia,
|
||||
String maxId,
|
||||
String sinceId,
|
||||
String minId,
|
||||
Integer limit) {
|
||||
MastodonTimelinesService mastodonTimelinesService = init(instance);
|
||||
statusesMutableLiveData = new MutableLiveData<>();
|
||||
new Thread(() -> {
|
||||
Call<List<Status>> publicTlCall = mastodonTimelinesService.getPublic(token, local, remote, onlyMedia, maxId, sinceId, minId, limit);
|
||||
Statuses statuses = new Statuses();
|
||||
if (publicTlCall != null) {
|
||||
try {
|
||||
Response<List<Status>> publicTlResponse = publicTlCall.execute();
|
||||
if (publicTlResponse.isSuccessful()) {
|
||||
List<Status> notFilteredStatuses = publicTlResponse.body();
|
||||
statuses.statuses = TimelineHelper.filterStatus(getApplication(), notFilteredStatuses, TimelineHelper.FilterTimeLineType.PUBLIC);
|
||||
statuses.pagination = MastodonHelper.getPagination(publicTlResponse.headers());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||
Runnable myRunnable = () -> statusesMutableLiveData.setValue(statuses);
|
||||
mainHandler.post(myRunnable);
|
||||
}).start();
|
||||
return statusesMutableLiveData;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Public timeline for Nitter
|
||||
|
@ -382,96 +342,65 @@ public class TimelinesVM extends AndroidViewModel {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* View public statuses containing the given hashtag.
|
||||
*
|
||||
* @param hashtag Content of a #hashtag, not including # symbol.
|
||||
* @param local If true, return only local statuses. Defaults to false.
|
||||
* @param onlyMedia If true, return only statuses with media attachments. Defaults to false.
|
||||
* @param maxId Return results older than this ID.
|
||||
* @param sinceId Return results newer than this ID.
|
||||
* @param minId Return results immediately newer than this ID.
|
||||
* @param limit Maximum number of results to return. Defaults to 20.
|
||||
* @return {@link LiveData} containing a {@link Statuses}
|
||||
*/
|
||||
public LiveData<Statuses> getHashTag(String token, @NonNull String instance,
|
||||
@NonNull String hashtag,
|
||||
boolean local,
|
||||
boolean onlyMedia,
|
||||
List<String> all,
|
||||
List<String> any,
|
||||
List<String> none,
|
||||
String maxId,
|
||||
String sinceId,
|
||||
String minId,
|
||||
int limit) {
|
||||
public LiveData<Statuses> getTimeline(TimelineParams timelineParams) {
|
||||
|
||||
statusesMutableLiveData = new MutableLiveData<>();
|
||||
MastodonTimelinesService mastodonTimelinesService = init(instance);
|
||||
MastodonTimelinesService mastodonTimelinesService = init(timelineParams.instance);
|
||||
new Thread(() -> {
|
||||
Statuses statuses = new Statuses();
|
||||
String hashtagTrim = hashtag.replaceAll("\\#", "");
|
||||
Call<List<Status>> hashTagTlCall = mastodonTimelinesService.getHashTag(token, hashtagTrim, local, onlyMedia, all, any, none, maxId, sinceId, minId, limit);
|
||||
if (hashTagTlCall != null) {
|
||||
try {
|
||||
Response<List<Status>> hashTagTlResponse = hashTagTlCall.execute();
|
||||
if (hashTagTlResponse.isSuccessful()) {
|
||||
List<Status> notFilteredStatuses = hashTagTlResponse.body();
|
||||
statuses.statuses = TimelineHelper.filterStatus(getApplication().getApplicationContext(), notFilteredStatuses, TimelineHelper.FilterTimeLineType.PUBLIC);
|
||||
statuses.pagination = MastodonHelper.getPagination(hashTagTlResponse.headers());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
Call<List<Status>> timelineCall = null;
|
||||
switch (timelineParams.type) {
|
||||
case HOME:
|
||||
timelineCall = mastodonTimelinesService.getHome(timelineParams.token, timelineParams.maxId, timelineParams.sinceId, timelineParams.minId, timelineParams.limit, timelineParams.local);
|
||||
break;
|
||||
case LOCAL:
|
||||
timelineCall = mastodonTimelinesService.getPublic(timelineParams.token, true, false, timelineParams.onlyMedia, timelineParams.maxId, timelineParams.sinceId, timelineParams.minId, timelineParams.limit);
|
||||
break;
|
||||
case PUBLIC:
|
||||
timelineCall = mastodonTimelinesService.getPublic(timelineParams.token, false, true, timelineParams.onlyMedia, timelineParams.maxId, timelineParams.sinceId, timelineParams.minId, timelineParams.limit);
|
||||
break;
|
||||
case TAG:
|
||||
timelineCall = mastodonTimelinesService.getHashTag(timelineParams.token, timelineParams.hashtagTrim, timelineParams.local, timelineParams.onlyMedia, timelineParams.all, timelineParams.any, timelineParams.none, timelineParams.maxId, timelineParams.sinceId, timelineParams.minId, timelineParams.limit);
|
||||
break;
|
||||
case LIST:
|
||||
timelineCall = mastodonTimelinesService.getList(timelineParams.token, timelineParams.listId, timelineParams.maxId, timelineParams.sinceId, timelineParams.minId, timelineParams.limit);
|
||||
break;
|
||||
}
|
||||
Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||
Runnable myRunnable = () -> statusesMutableLiveData.setValue(statuses);
|
||||
mainHandler.post(myRunnable);
|
||||
}).start();
|
||||
|
||||
return statusesMutableLiveData;
|
||||
}
|
||||
|
||||
/**
|
||||
* View statuses from followed users.
|
||||
*
|
||||
* @param maxId Return results older than id
|
||||
* @param sinceId Return results newer than id
|
||||
* @param minId Return results immediately newer than id
|
||||
* @param limit Maximum number of results to return. Defaults to 20.
|
||||
* @param local Return only local statuses?
|
||||
* @return {@link LiveData} containing a {@link Statuses}
|
||||
*/
|
||||
public LiveData<Statuses> getHome(@NonNull String instance, String token,
|
||||
String userId,
|
||||
boolean fetchingMissing,
|
||||
String maxId,
|
||||
String sinceId,
|
||||
String minId,
|
||||
int limit,
|
||||
boolean local) {
|
||||
statusesMutableLiveData = new MutableLiveData<>();
|
||||
MastodonTimelinesService mastodonTimelinesService = init(instance);
|
||||
new Thread(() -> {
|
||||
Statuses statuses = new Statuses();
|
||||
Call<List<Status>> homeTlCall = mastodonTimelinesService.getHome(token, maxId, sinceId, minId, limit, local);
|
||||
if (homeTlCall != null) {
|
||||
if (timelineCall != null) {
|
||||
try {
|
||||
Response<List<Status>> homeTlResponse = homeTlCall.execute();
|
||||
if (homeTlResponse.isSuccessful()) {
|
||||
List<Status> notFilteredStatuses = homeTlResponse.body();
|
||||
statuses.statuses = TimelineHelper.filterStatus(getApplication().getApplicationContext(), notFilteredStatuses, TimelineHelper.FilterTimeLineType.HOME);
|
||||
statuses.pagination = MastodonHelper.getPagination(homeTlResponse.headers());
|
||||
if (!fetchingMissing) {
|
||||
Response<List<Status>> timelineResponse = timelineCall.execute();
|
||||
if (timelineResponse.isSuccessful()) {
|
||||
List<Status> statusList = timelineResponse.body();
|
||||
statuses.statuses = TimelineHelper.filterStatus(getApplication().getApplicationContext(), statusList, TimelineHelper.FilterTimeLineType.PUBLIC);
|
||||
statuses.pagination = MastodonHelper.getPagination(timelineResponse.headers());
|
||||
if (statusList != null && statusList.size() > 0) {
|
||||
if (timelineParams.direction == FragmentMastodonTimeline.DIRECTION.REFRESH || timelineParams.direction == FragmentMastodonTimeline.DIRECTION.SCROLL_TOP) {
|
||||
Status newestStatus = new StatusCache(getApplication().getApplicationContext()).getNewestStatus(timelineParams.slug, timelineParams.instance, timelineParams.userId);
|
||||
//When refreshing/scrolling to TOP, if last statuses fetched has a greater id from newest in cache, there is potential hole
|
||||
if (newestStatus != null && statusList.get(statusList.size() - 1).id.compareToIgnoreCase(newestStatus.id) > 0) {
|
||||
statusList.get(statusList.size() - 1).isFetchMore = true;
|
||||
}
|
||||
} else if (timelineParams.direction == FragmentMastodonTimeline.DIRECTION.TOP && timelineParams.fetchingMissing) {
|
||||
Status topStatus = new StatusCache(getApplication().getApplicationContext()).getTopFetchMore(timelineParams.slug, timelineParams.instance, timelineParams.slug, statusList.get(0).id);
|
||||
if (topStatus != null && statusList.get(0).id.compareToIgnoreCase(topStatus.id) < 0) {
|
||||
statusList.get(0).isFetchMore = true;
|
||||
}
|
||||
} else if (timelineParams.direction == FragmentMastodonTimeline.DIRECTION.BOTTOM && timelineParams.fetchingMissing) {
|
||||
Status bottomStatus = new StatusCache(getApplication().getApplicationContext()).getBottomFetchMore(timelineParams.slug, timelineParams.instance, timelineParams.slug, statusList.get(0).id);
|
||||
if (bottomStatus != null && statusList.get(statusList.size() - 1).id.compareToIgnoreCase(bottomStatus.id) > 0) {
|
||||
statusList.get(statusList.size() - 1).isFetchMore = true;
|
||||
}
|
||||
}
|
||||
for (Status status : statuses.statuses) {
|
||||
StatusCache statusCacheDAO = new StatusCache(getApplication().getApplicationContext());
|
||||
StatusCache statusCache = new StatusCache();
|
||||
statusCache.instance = instance;
|
||||
statusCache.user_id = userId;
|
||||
statusCache.instance = timelineParams.instance;
|
||||
statusCache.user_id = timelineParams.userId;
|
||||
statusCache.status = status;
|
||||
statusCache.type = StatusCache.CacheEnum.HOME;
|
||||
statusCache.type = timelineParams.type;
|
||||
statusCache.status_id = status.id;
|
||||
try {
|
||||
statusCacheDAO.insertOrUpdate(statusCache);
|
||||
statusCacheDAO.insertOrUpdate(statusCache, timelineParams.slug);
|
||||
} catch (DBException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -486,32 +415,18 @@ public class TimelinesVM extends AndroidViewModel {
|
|||
Runnable myRunnable = () -> statusesMutableLiveData.setValue(statuses);
|
||||
mainHandler.post(myRunnable);
|
||||
}).start();
|
||||
|
||||
return statusesMutableLiveData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get home status from cache
|
||||
*
|
||||
* @param instance String - instance
|
||||
* @param user_id String - user id
|
||||
* @param maxId String - max id
|
||||
* @param minId String - min id
|
||||
* @return LiveData<Statuses>
|
||||
*/
|
||||
public LiveData<Statuses> getHomeCache(@NonNull String instance, String user_id,
|
||||
String maxId,
|
||||
String minId,
|
||||
String sinceId) {
|
||||
public LiveData<Statuses> getTimelineCache(TimelineParams timelineParams) {
|
||||
statusesMutableLiveData = new MutableLiveData<>();
|
||||
new Thread(() -> {
|
||||
StatusCache statusCacheDAO = new StatusCache(getApplication().getApplicationContext());
|
||||
Statuses statuses = null;
|
||||
try {
|
||||
statuses = statusCacheDAO.geStatuses(StatusCache.CacheEnum.HOME, instance, user_id, maxId, minId, sinceId);
|
||||
|
||||
statuses = statusCacheDAO.geStatuses(timelineParams.slug, timelineParams.instance, timelineParams.userId, timelineParams.maxId, timelineParams.minId, timelineParams.sinceId);
|
||||
if (statuses != null) {
|
||||
statuses.statuses = TimelineHelper.filterStatus(getApplication().getApplicationContext(), statuses.statuses, TimelineHelper.FilterTimeLineType.HOME);
|
||||
TimelineHelper.filterStatus(getApplication().getApplicationContext(), statuses.statuses, TimelineHelper.FilterTimeLineType.HOME);
|
||||
if (statuses.statuses != null && statuses.statuses.size() > 0) {
|
||||
statuses.pagination = new Pagination();
|
||||
statuses.pagination.min_id = statuses.statuses.get(0).id;
|
||||
|
@ -529,6 +444,42 @@ public class TimelinesVM extends AndroidViewModel {
|
|||
return statusesMutableLiveData;
|
||||
}
|
||||
|
||||
public static class TimelineParams {
|
||||
|
||||
public FragmentMastodonTimeline.DIRECTION direction;
|
||||
public String instance;
|
||||
public String token;
|
||||
public Timeline.TimeLineEnum type;
|
||||
public String slug;
|
||||
public String userId;
|
||||
public Boolean remote;
|
||||
public Boolean onlyMedia;
|
||||
public String hashtagTrim;
|
||||
public List<String> all;
|
||||
public List<String> any;
|
||||
public List<String> none;
|
||||
public String listId;
|
||||
public Boolean fetchingMissing;
|
||||
public String maxId;
|
||||
public String sinceId;
|
||||
public String minId;
|
||||
public int limit = 40;
|
||||
public Boolean local;
|
||||
|
||||
public TimelineParams(@NonNull Timeline.TimeLineEnum type, @Nullable FragmentMastodonTimeline.DIRECTION direction, @Nullable String ident) {
|
||||
if (type != Timeline.TimeLineEnum.REMOTE) {
|
||||
instance = MainActivity.currentInstance;
|
||||
token = MainActivity.currentToken;
|
||||
userId = MainActivity.currentUserID;
|
||||
}
|
||||
String key = type.getValue();
|
||||
if (ident != null) {
|
||||
key += "|" + ident;
|
||||
}
|
||||
slug = key;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get user drafts
|
||||
|
@ -553,45 +504,6 @@ public class TimelinesVM extends AndroidViewModel {
|
|||
return statusDraftListMutableLiveData;
|
||||
}
|
||||
|
||||
/**
|
||||
* View statuses in the given list timeline.
|
||||
*
|
||||
* @param listId Local ID of the list in the database.
|
||||
* @param maxId Return results older than this ID.
|
||||
* @param sinceId Return results newer than this ID.
|
||||
* @param minId Return results immediately newer than this ID.
|
||||
* @param limit Maximum number of results to return. Defaults to 20.Return results older than this ID.
|
||||
* @return {@link LiveData} containing a {@link Statuses}
|
||||
*/
|
||||
public LiveData<Statuses> getList(@NonNull String instance, String token,
|
||||
@NonNull String listId,
|
||||
String maxId,
|
||||
String sinceId,
|
||||
String minId,
|
||||
int limit) {
|
||||
statusesMutableLiveData = new MutableLiveData<>();
|
||||
MastodonTimelinesService mastodonTimelinesService = init(instance);
|
||||
new Thread(() -> {
|
||||
Statuses statuses = new Statuses();
|
||||
Call<List<Status>> listTlCall = mastodonTimelinesService.getList(token, listId, maxId, sinceId, minId, limit);
|
||||
if (listTlCall != null) {
|
||||
try {
|
||||
Response<List<Status>> listTlResponse = listTlCall.execute();
|
||||
if (listTlResponse.isSuccessful()) {
|
||||
statuses.statuses = listTlResponse.body();
|
||||
statuses.pagination = MastodonHelper.getPagination(listTlResponse.headers());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||
Runnable myRunnable = () -> statusesMutableLiveData.setValue(statuses);
|
||||
mainHandler.post(myRunnable);
|
||||
}).start();
|
||||
|
||||
return statusesMutableLiveData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show conversations
|
||||
|
|
|
@ -906,6 +906,8 @@
|
|||
<string name="SET_DISPLAY_BOOKMARK" translatable="false">SET_DISPLAY_BOOKMARK</string>
|
||||
<string name="SET_NOTIF_VALIDATION_FAV" translatable="false">SET_NOTIF_VALIDATION_FAV</string>
|
||||
<string name="SET_DISPLAY_COUNTER_FAV_BOOST" translatable="false">SET_DISPLAY_COUNTER_FAV_BOOST</string>
|
||||
<string name="SET_HOME_INNER_MARKER" translatable="false">SET_HOME_INNER_MARKER</string>
|
||||
|
||||
<string name="SET_NOTIF_SILENT" translatable="false">SET_NOTIF_SILENT</string>
|
||||
<string name="SET_EXPAND_CW" translatable="false">SET_EXPAND_CW</string>
|
||||
<string name="SET_DISPLAY_ALL_NOTIFICATIONS_TYPE" translatable="false">SET_DISPLAY_ALL_NOTIFICATIONS_TYPE</string>
|
||||
|
|
Loading…
Reference in New Issue