Skip to content

Feat/misc#97

Merged
MaxJubayerYT merged 9 commits into
v3_openjdkfrom
feat/misc
Jul 8, 2026
Merged

Feat/misc#97
MaxJubayerYT merged 9 commits into
v3_openjdkfrom
feat/misc

Conversation

@MaxJubayerYT

Copy link
Copy Markdown
Member

No description provided.

…con-only update button

- ManageModsFragment: run update check automatically when the screen
  opens (silent, no toasts) in addition to the manual refresh button
  tap. While a check is in flight, hide the refresh icon and show a
  ProgressBar in its place instead.
- fragment_manage_mods.xml: add manage_mods_update_progress ProgressBar
  next to the refresh button, gone by default.
- item_installed_mod.xml: replace the text Update MineButton with a
  plain ImageButton using ic_export_mrpack, styled like the other row
  icon buttons. Still hidden until an update is available.
- InstalledModAdapter: ModViewHolder.update field type changed from
  Button to ImageButton to match the new layout; bind logic unchanged.
…oading

- item_installed_mod.xml: add installed_mod_update_progress ProgressBar
  in the same slot as installed_mod_update, gone by default.
- InstalledModAdapter: add ModEntry.isUpdating flag. applyUpdate() sets
  it true and rebinds before the download starts, then clears it (on
  both success and failure) and rebinds again once done. bind() now
  shows the spinner and hides the update button while isUpdating is
  true, otherwise falls back to the existing update-button/hidden
  logic. Guard applyUpdate() against re-entry while already updating.
Old and new jar were replaced with two independent, unchecked
File.delete()/renameTo() calls. When the file name changes between
versions, these are separate filesystem entries; if delete() of the
old jar transiently failed (e.g. briefly held open by an icon/name
resolution read) the failure was silently ignored and the new file
still got created, leaving both jars on disk as a duplicate on next
scan. Same-name updates never showed this because renameTo() onto an
existing path atomically replaces it, masking the ignored delete
failure.

Added a shared replaceModFile() helper used by both applyUpdate() and
applySwitchVersion(): renames the new file into place first, then
explicitly deletes the old one (skipped when the name didn't change,
since rename already replaced it), retrying the delete a few times
with backoff before giving up and logging a warning.
CurseforgeApi.getModDetails() only filtered a mod's file list by MC
version, so the version dropdown mixed in files built for every
loader (Fabric/Forge/Quilt/NeoForge) even when a specific loader was
selected in the filters. CurseForge doesn't give a file its own loader
field — the loader name is just another string in the same
'gameVersions' array as the MC version tags (e.g. ['1.20.1',
'Fabric']) — so it was being ignored entirely.

Added a filterLoader parameter to getModDetails(), matched
case-insensitively against that same array, and wired it through from
ModsSearchFragment the same way the existing Modrinth path already
does.
…m API key

Two new options under Experimental settings:
- disableCurseforgeApi (SwitchPreferenceCompat): when on, CurseForge is
  skipped entirely — mod/modpack search, per-mod version lookups, and
  the CurseForge icon-resolution fallback in InstalledModAdapter all
  fall back to Modrinth only (or no-op for the icon fallback, which has
  no Modrinth equivalent). CurseForge's API is noticeably slower than
  Modrinth's, so this trades old pre-Modrinth Forge mod coverage for
  speed.
- curseforgeApiKeyOverride (EditTextPreference): lets the user supply
  their own CurseForge API key instead of the bundled one, which is
  shared across every install of the app and can get rate-limited.

LauncherPreferences: added PREF_DISABLE_CURSEFORGE_API,
PREF_CURSEFORGE_API_KEY_OVERRIDE, and a resolveCurseforgeApiKey(ctx)
helper that returns the user's key when set, else the bundled default.

CommonApi: new CommonApi(key, disableCurseforge) overload excludes
CurseForge from searchMod()'s fan-out when disabled, while still
constructing the instance so modpack-zip import (which needs to
recognize a CurseForge manifest.json) keeps working.

Wired through ModsSearchFragment (individual mod search/install),
SearchModFragment (modpack search), InstalledModAdapter (icon
fallback), and LauncherActivity (modpack import).
…t to Modrinth

New 'Search source' spinner in the shared search filter dialog
(dialog_mod_filters.xml), used by both the mod installer
(ModsSearchFragment) and the modpack installer (SearchModFragment).
Lets you pick Modrinth, CurseForge, or Both per search instead of
always querying both.

- SearchFilters.engine (new field) defaults to Constants.ENGINE_MODRINTH
  — Modrinth is now the default engine instead of always searching both.
- CommonApi gained per-api source tracking (mModpackApiSources) and an
  isEngineIncluded() check in searchMod(), so only the engine(s) picked
  in the filter dialog are actually queried for a given search.
- When 'Disable CurseForge' is on in experimental settings, the engine
  spinner collapses to a single, disabled 'Modrinth' entry — picking
  CurseForge or Both would otherwise silently return no results.
- Simplified both fragments' displayFilterDialog(): the engine, loader,
  and version fields now share one apply-button listener instead of
  being split across duplicated branches.
Manage Mods reuses dialog_mod_filters.xml (for its version/loader
update-check filter), which now also carries the Modrinth/CurseForge/
Both engine picker added for the search screens. That picker doesn't
apply here — Manage Mods filters already-installed mods, it doesn't
run a search against an engine — so hide both the label and the
spinner when this dialog is shown from ManageModsFragment.
…alled

The 'install dependencies' dialog listed every dependency the selected
Modrinth version declared, with no check against what's already in the
mods folder — so reinstalling/updating a mod with common deps (Fabric
API, Cloth Config, etc.) nagged you to 'install' something already
there, matched only against the exact same version's own hash, not
any installed version of the dependency itself.

Added getInstalledModrinthProjectIds(): bulk-hashes every jar in the
mods folder and resolves them against Modrinth's version_files
endpoint in one request to get each installed jar's project id.
handleInstallation() now filters the dependency list against that set
before prompting — already-installed deps are silently dropped, and if
that empties the list entirely, the dialog is skipped altogether and
the mod downloads directly, same as the no-dependencies case.

(CurseForge-sourced mods don't populate versionDependencyIds at all
today, so this only affects the Modrinth dependency-resolution path —
consistent with the existing 'no deps' short-circuit already only
applying there.)
…t twice

openPane()/openPaneFragment() always pushed a new back-stack entry on
the right pane's child FragmentManager, even when the fragment being
opened was already the one on screen. A quick double-tap on the same
trigger (instance row, settings gear, etc.) therefore stacked two
identical entries, and Back had to be pressed twice to actually get
back to the pane's home screen — the first press just popped the
duplicate back to itself.

Added isTagAlreadyOnTop(), checked at the top of both navigation
helpers: if the requested tag is already the top back-stack entry,
the tap is a no-op instead of pushing a duplicate.
@MaxJubayerYT MaxJubayerYT merged commit 81897bc into v3_openjdk Jul 8, 2026
1 check passed
@MaxJubayerYT MaxJubayerYT deleted the feat/misc branch July 11, 2026 06:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant