66import android .widget .ArrayAdapter ;
77import android .widget .Button ;
88import android .widget .ImageButton ;
9+ import android .widget .ProgressBar ;
910import android .widget .Spinner ;
1011import android .widget .TextView ;
1112import android .widget .Toast ;
@@ -37,6 +38,7 @@ public class ManageModsFragment extends Fragment {
3738
3839 private ImageButton mFilterButton ;
3940 private ImageButton mRefreshButton ;
41+ private ProgressBar mUpdateProgress ;
4042 private InstalledModAdapter mAdapter ;
4143
4244 public ManageModsFragment () {
@@ -48,14 +50,15 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat
4850 ImageButton backButton = view .findViewById (R .id .manage_mods_back );
4951 mFilterButton = view .findViewById (R .id .manage_mods_filter );
5052 mRefreshButton = view .findViewById (R .id .manage_mods_refresh );
53+ mUpdateProgress = view .findViewById (R .id .manage_mods_update_progress );
5154 ImageButton addButton = view .findViewById (R .id .manage_mods_add );
5255 TextView title = view .findViewById (R .id .manage_mods_title );
5356 RecyclerView recycler = view .findViewById (R .id .manage_mods_recycler );
5457 View emptyState = view .findViewById (R .id .manage_mods_empty );
5558
5659 backButton .setOnClickListener (v -> requireActivity ().onBackPressed ());
5760 mFilterButton .setOnClickListener (v -> showFilterDialog ());
58- mRefreshButton .setOnClickListener (v -> runUpdateCheck ());
61+ mRefreshButton .setOnClickListener (v -> runUpdateCheck (false ));
5962 addButton .setOnClickListener (v -> openModSearch ());
6063
6164 String profileName = getCurrentProfileName ();
@@ -81,19 +84,24 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat
8184 recycler .setLayoutManager (new LinearLayoutManager (requireContext ()));
8285 recycler .setAdapter (mAdapter );
8386
84- // Update checking is opt-in: only runs when the user taps the refresh
85- // button (see mRefreshButton's listener above). Auto-checking here used
86- // to fire a network call per mod the instant this screen opened, which
87- // also fought with the initial icon-resolution pass and made icons
88- // flash to the placeholder glyph.
87+ // Auto-check for updates as soon as the screen opens, in addition to
88+ // the manual refresh button. Silent (no "checking…" toast, and no
89+ // "set a filter first" toast) since this fires automatically — if
90+ // there's no filter set yet, it just quietly does nothing until the
91+ // user configures one and hits refresh manually.
92+ runUpdateCheck (true );
8993 }
9094
9195 /**
9296 * Runs the Modrinth update check across all installed mods for this instance.
93- * Only ever triggered by the user tapping the refresh button — update
94- * checking is fully opt-in, never automatic.
97+ * Triggered automatically when the screen opens (silent = true) and manually
98+ * via the refresh button (silent = false).
99+ *
100+ * @param silent when true, skips the "checking…"/"set a filter first" toasts —
101+ * used for the automatic on-open check so it doesn't nag the
102+ * user if they haven't configured a version/loader filter yet.
95103 */
96- private void runUpdateCheck () {
104+ private void runUpdateCheck (boolean silent ) {
97105 if (mAdapter == null ) return ;
98106
99107 String profileKey = getCurrentProfileKey ();
@@ -103,17 +111,31 @@ private void runUpdateCheck() {
103111 String loader = prefs .getString (KEY_LOADER + profileKey , "" );
104112
105113 if (version .isEmpty () && loader .isEmpty ()) {
106- Toast .makeText (requireContext (),
107- R .string .mod_update_no_filter , Toast .LENGTH_SHORT ).show ();
114+ if (!silent ) {
115+ Toast .makeText (requireContext (),
116+ R .string .mod_update_no_filter , Toast .LENGTH_SHORT ).show ();
117+ }
108118 return ;
109119 }
110120
111121 mAdapter .setFilter (version , loader );
112122
123+ // While checking: hide the refresh button and show just a spinner in
124+ // its place. No per-mod update button appears until its own check
125+ // resolves, so this spinner is the only thing indicating progress.
113126 mRefreshButton .setEnabled (false );
114- Toast .makeText (requireContext (), R .string .mod_update_checking , Toast .LENGTH_SHORT ).show ();
127+ mRefreshButton .setVisibility (View .GONE );
128+ if (mUpdateProgress != null ) mUpdateProgress .setVisibility (View .VISIBLE );
129+
130+ if (!silent ) {
131+ Toast .makeText (requireContext (), R .string .mod_update_checking , Toast .LENGTH_SHORT ).show ();
132+ }
115133
116- mAdapter .checkForUpdates (() -> mRefreshButton .setEnabled (true ));
134+ mAdapter .checkForUpdates (() -> {
135+ mRefreshButton .setEnabled (true );
136+ mRefreshButton .setVisibility (View .VISIBLE );
137+ if (mUpdateProgress != null ) mUpdateProgress .setVisibility (View .GONE );
138+ });
117139 }
118140
119141 // ── Filter dialog ────────────────────────────────────────────────────────
0 commit comments