diff options
| author | Danilo M. <danix@danix.xyz> | 2026-10-22 11:39:34 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-10-22 11:39:34 +0200 |
| commit | 1ffa52946d8de76806b0b467ccd60f4b2fe57683 (patch) | |
| tree | 52892e10f178225edd51bdd3b5c174c7e3de2513 /app/src/main/java/mygram/droid/FolderActivity.java | |
| parent | 40b12e5b4cd6a4352e37cd1b6e85b1da10624436 (diff) | |
| download | mygram-droid-1ffa52946d8de76806b0b467ccd60f4b2fe57683.tar.gz mygram-droid-1ffa52946d8de76806b0b467ccd60f4b2fe57683.zip | |
Lazy-load folder content in random page order
A folder with several thousand posts took ~10 s to open because
FolderActivity and the Home row OK handler fetched every page before
showing anything. Pages are now fetched one at a time in a shuffled page
order (each page shuffled locally), the grid shows after the first page,
and the viewer shares the list and pager so it keeps paging the folder.
Reels use the same generic pager. Not a full shuffle: neighbours within
a page stay together.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'app/src/main/java/mygram/droid/FolderActivity.java')
| -rw-r--r-- | app/src/main/java/mygram/droid/FolderActivity.java | 82 |
1 files changed, 74 insertions, 8 deletions
diff --git a/app/src/main/java/mygram/droid/FolderActivity.java b/app/src/main/java/mygram/droid/FolderActivity.java index 10a9940..c7002c5 100644 --- a/app/src/main/java/mygram/droid/FolderActivity.java +++ b/app/src/main/java/mygram/droid/FolderActivity.java @@ -23,18 +23,27 @@ import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.LinearLayout; import android.widget.TextView; +import android.widget.Toast; +import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; -import java.util.Collections; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; -/** One folder as a grid, shuffled once per open. */ +/** One folder as a grid, paged in lazily in random page order. */ public final class FolderActivity extends Activity { private FrameLayout content; private RecyclerView grid; + private final List<Post> posts = new ArrayList<>(); + private final List<TileAdapter.Tile> tiles = new ArrayList<>(); + private Callable<List<Post>> more; + private boolean loading; static void open(Context c, Api.Folder f) { - c.startActivity(new Intent(c, FolderActivity.class).putExtra("slug", f.slug).putExtra("name", f.name)); + c.startActivity(new Intent(c, FolderActivity.class).putExtra("slug", f.slug).putExtra("name", f.name) + .putExtra("count", f.count)); } @Override @@ -49,19 +58,76 @@ public final class FolderActivity extends Activity { column.addView(content, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0, 1)); setContentView(column); show(Ui.text(this, "Loading…", 18)); - Api.async(() -> Api.folderPosts(getIntent().getStringExtra("slug")), posts -> { - Collections.shuffle(posts); - grid = Ui.grid(this, Ui.postTiles(this, posts), Ui.POST_W, Ui.POST_H, 6); + more = Api.folderPages(getIntent().getStringExtra("slug"), getIntent().getIntExtra("count", 0)); + loading = true; + Api.async(more, page -> { + loading = false; + if (isDestroyed()) + return; + append(page); + if (page.isEmpty()) { + show(Ui.text(this, "Nothing to show", 18)); + return; + } + grid = Ui.grid(this, tiles, Ui.POST_W, Ui.POST_H, 6); + grid.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrolled(RecyclerView rv, int dx, int dy) { + loadMore(); + } + }); show(grid); grid.post(grid::requestFocus); // after layout - }, e -> show(Ui.text(this, "Cannot load folder: " + e.getMessage(), 18))); + }, e -> { + loading = false; + show(Ui.text(this, "Cannot load folder: " + e.getMessage(), 18)); + }); + } + + /** Loads the next page when the last visible tile is within 12 of the end. */ + private void loadMore() { + if (more == null || loading || grid == null) + return; + if (((GridLayoutManager) grid.getLayoutManager()).findLastVisibleItemPosition() < tiles.size() - 12) + return; + loading = true; + Api.async(more, page -> { + loading = false; + if (isDestroyed()) + return; + if (page.isEmpty()) + more = null; + append(page); + }, e -> { + loading = false; + if (!isDestroyed()) + Toast.makeText(this, "Cannot load more: " + e.getMessage(), Toast.LENGTH_SHORT).show(); + }); + } + + /** Pages from one pager never overlap, so no id check is needed here. */ + private void append(List<Post> page) { + posts.addAll(page); + addTiles(); + } + + private void addTiles() { + int old = tiles.size(); + for (int i = old; i < posts.size(); i++) { + int start = i; + tiles.add(TileAdapter.post(posts.get(i), () -> Playlist.open(this, posts, start, more))); + } + if (grid != null && tiles.size() > old) + grid.getAdapter().notifyItemRangeInserted(old, tiles.size() - old); } @Override protected void onResume() { super.onResume(); - if (grid != null && grid.getAdapter() != null) + if (grid != null && grid.getAdapter() != null) { + addTiles(); // the viewer may have appended to the shared list grid.getAdapter().notifyItemRangeChanged(0, grid.getAdapter().getItemCount()); + } } private void show(android.view.View v) { |
