aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/src/main/java/mygram/droid/FolderActivity.java2
-rw-r--r--app/src/main/java/mygram/droid/HomeRows.java10
-rw-r--r--app/src/main/java/mygram/droid/MainActivity.java59
3 files changed, 54 insertions, 17 deletions
diff --git a/app/src/main/java/mygram/droid/FolderActivity.java b/app/src/main/java/mygram/droid/FolderActivity.java
index 8da2533..10a9940 100644
--- a/app/src/main/java/mygram/droid/FolderActivity.java
+++ b/app/src/main/java/mygram/droid/FolderActivity.java
@@ -53,7 +53,7 @@ public final class FolderActivity extends Activity {
Collections.shuffle(posts);
grid = Ui.grid(this, Ui.postTiles(this, posts), Ui.POST_W, Ui.POST_H, 6);
show(grid);
- grid.requestFocus();
+ grid.post(grid::requestFocus); // after layout
}, e -> show(Ui.text(this, "Cannot load folder: " + e.getMessage(), 18)));
}
diff --git a/app/src/main/java/mygram/droid/HomeRows.java b/app/src/main/java/mygram/droid/HomeRows.java
index ed638b6..e4abeb5 100644
--- a/app/src/main/java/mygram/droid/HomeRows.java
+++ b/app/src/main/java/mygram/droid/HomeRows.java
@@ -37,11 +37,14 @@ final class HomeRows extends RecyclerView.Adapter<HomeRows.Row> {
static final class Row extends RecyclerView.ViewHolder {
final TextView title;
final RecyclerView tiles;
+ /** Backing list of the row's one adapter: rebinds refill it instead of replacing the adapter. */
+ final List<TileAdapter.Tile> list = new ArrayList<>();
Row(LinearLayout v, TextView title, RecyclerView tiles) {
super(v);
this.title = title;
this.tiles = tiles;
+ tiles.setAdapter(new TileAdapter(list, Ui.POST_W, Ui.POST_H));
}
}
@@ -80,17 +83,18 @@ final class HomeRows extends RecyclerView.Adapter<HomeRows.Row> {
samples.put(f.slug, posts); // marks it loading, so it is fetched once
Api.async(() -> Api.folderSample(f, SAMPLE), p -> {
samples.put(f.slug, p);
- notifyItemChanged(folders.indexOf(f));
+ notifyItemChanged(folders.indexOf(f), Boolean.TRUE); // payload: keep the holder, so focus stays
}, e -> {
// the row keeps only its Continue tile
});
}
- List<TileAdapter.Tile> tiles = new ArrayList<>();
+ List<TileAdapter.Tile> tiles = row.list;
+ tiles.clear();
for (Post p : posts)
tiles.add(TileAdapter.post(p, () -> open(f, p)));
tiles.add(new TileAdapter.Tile(null, "Continue", R.drawable.ic_arrow_forward, -1,
() -> FolderActivity.open(activity, f)));
- row.tiles.setAdapter(new TileAdapter(tiles, Ui.POST_W, Ui.POST_H));
+ row.tiles.getAdapter().notifyDataSetChanged();
}
@Override
diff --git a/app/src/main/java/mygram/droid/MainActivity.java b/app/src/main/java/mygram/droid/MainActivity.java
index 6f8d76d..7578f05 100644
--- a/app/src/main/java/mygram/droid/MainActivity.java
+++ b/app/src/main/java/mygram/droid/MainActivity.java
@@ -59,7 +59,8 @@ public final class MainActivity extends Activity {
private RecyclerView homeList;
private HomeRows homeRows;
private int tab = HOME;
- private boolean ready;
+ private boolean ready, resumed, homeLoading;
+ private ImageView logo;
@Override
protected void onCreate(Bundle state) {
@@ -98,11 +99,9 @@ public final class MainActivity extends Activity {
bar.setGravity(Gravity.CENTER_VERTICAL);
int p = Ui.dp(this, 16);
bar.setPadding(p * 2, p, p * 2, 0);
- LinearLayout logo = Ui.iconButton(this, R.drawable.ic_home, "Home", v -> show(HOME));
- // Foldergram's logo is AGPLv3: loaded from the instance, never bundled.
- Glide.with(this).load(Api.resolve(Prefs.server(), "/icon-192.png")).error(R.drawable.ic_home)
- .into((ImageView) logo.getChildAt(0));
- bar.addView(logo);
+ LinearLayout home = Ui.iconButton(this, R.drawable.ic_home, "Home", v -> show(HOME));
+ logo = (ImageView) home.getChildAt(0);
+ bar.addView(home);
bar.addView(new Space(this), new LinearLayout.LayoutParams(0, 1, 1));
bar.addView(Ui.iconButton(this, R.drawable.ic_reels, "Reels", v -> Playlist.openReels(this)));
bar.addView(Ui.iconButton(this, R.drawable.ic_favorite, "Liked", v -> show(LIKED)));
@@ -121,12 +120,19 @@ public final class MainActivity extends Activity {
Likes.load();
return Api.randomFeed();
}, posts -> {
+ if (isDestroyed())
+ return;
ready = true;
+ // Foldergram's logo is AGPLv3: loaded from the instance after login, never bundled.
+ Glide.with(this).load(Api.resolve(Prefs.server(), "/icon-192.png")).error(R.drawable.ic_home).into(logo);
backgrounds = posts;
handler.removeCallbacks(rotate);
rotateBackground();
show(tab);
- }, this::failed);
+ }, e -> {
+ if (!isDestroyed())
+ failed(e);
+ });
}
private void failed(Exception e) {
@@ -151,20 +157,31 @@ public final class MainActivity extends Activity {
return;
}
message("Loading…");
+ if (homeLoading)
+ return; // the request in flight shows the list when it lands
+ homeLoading = true;
Api.async(Api::folders, folders -> {
+ homeLoading = false;
homeRows = new HomeRows(this, folders);
homeList = Ui.list(this, RecyclerView.VERTICAL);
homeList.setAdapter(homeRows);
if (tab == HOME)
setContent(homeList);
- }, this::failed);
+ }, e -> {
+ homeLoading = false;
+ if (tab == t)
+ failed(e);
+ });
} else if (t == LIKED) {
message("Loading…");
Api.async(Api::likes, posts -> {
if (tab == LIKED)
setContent(posts.isEmpty() ? centered("No liked posts yet")
: Ui.grid(this, Ui.postTiles(this, posts), Ui.POST_W, Ui.POST_H, 6));
- }, this::failed);
+ }, e -> {
+ if (tab == t)
+ failed(e);
+ });
} else {
message("Loading…");
Api.async(Api::folders, folders -> {
@@ -175,13 +192,17 @@ public final class MainActivity extends Activity {
tiles.add(new TileAdapter.Tile(f.avatarUrl, f.name, R.drawable.ic_folder, -1,
() -> FolderActivity.open(this, f)));
setContent(Ui.grid(this, tiles, 160, 160, 5));
- }, this::failed);
+ }, e -> {
+ if (tab == t)
+ failed(e);
+ });
}
}
@Override
protected void onResume() {
super.onResume();
+ resumed = true;
if (!ready)
return;
handler.removeCallbacks(rotate);
@@ -195,7 +216,14 @@ public final class MainActivity extends Activity {
@Override
protected void onPause() {
super.onPause();
+ resumed = false;
+ handler.removeCallbacks(rotate);
+ }
+
+ @Override
+ protected void onDestroy() {
handler.removeCallbacks(rotate);
+ super.onDestroy();
}
private void rotateBackground() {
@@ -204,6 +232,7 @@ public final class MainActivity extends Activity {
Post p = backgrounds.get(ThreadLocalRandom.current().nextInt(backgrounds.size()));
// Never pass the old drawable as a Glide placeholder: Glide may recycle its bitmap.
ImageView back = layers[1 - front], top = layers[front];
+ back.animate().cancel();
back.setAlpha(0f);
back.bringToFront();
Glide.with(this).load(p.media.get(0).thumbnailUrl).listener(new RequestListener<Drawable>() {
@@ -215,12 +244,16 @@ public final class MainActivity extends Activity {
@Override
public boolean onResourceReady(Drawable d, Object model, Target<Drawable> target, DataSource source,
boolean first) {
- back.animate().alpha(1f).setDuration(1500).withEndAction(() -> Glide.with(top).clear(top)).start();
+ front = 1 - front; // only now, so a failed load leaves the old layer on top
+ back.animate().alpha(1f).setDuration(1500).withEndAction(() -> {
+ if (!isDestroyed())
+ Glide.with(top).clear(top);
+ }).start();
return false;
}
}).into(back);
- front = 1 - front;
- handler.postDelayed(rotate, Prefs.backgroundSeconds() * 1000L);
+ if (resumed)
+ handler.postDelayed(rotate, Prefs.backgroundSeconds() * 1000L);
}
private void message(String s) {