Development Rule: Always create a new pre-release tag (e.g., bump to v1.4.3-pre, v1.4.4-pre) when pushing a new commit and build. Never overwrite or re-tag the same pre-release version.
Stable Release Rule: After every stable release, as the final step (after setting the GitHub release description and deleting old releases), rewrite the repository README.md to accurately reflect the current feature set — all built-in repos, all features, all settings, and any UI/flow changes made since the previous stable.
Commit: a5776a1 (README) | Tag: v2.2.0 | Branch: main
What changed: Stable release promoting v2.1.7-pre through v2.1.9-pre. Steam ISO export moved to manual FileDownload button; ISO duplicate skip; game name sanitization for MediaStore/ISO creation. README rewritten to reflect all v2.2.0 state.
Files touched: README.md
Commit: 6fdc856 | Tag: v2.1.9-pre | Branch: main
What changed: Removed automatic ISO writing from loadSteamGames() — it was running SteamRepository.fetch() + MediaStore ops on every navigation, causing sluggishness. Added exportSteamIsos() ViewModel function and a FileDownload icon button in My Games top bar (disabled when no Steam games loaded). ISOs only written when user taps the button.
Files touched: viewmodel/MainViewModel.kt, ui/screens/MyGamesScreen.kt, MainActivity.kt
Commit: e426780 | Tag: v2.1.8-pre | Branch: main
What changed: Sanitize filename chars [/\:*?"<>|] → _ before MediaStore query/insert. Fixes Counter-Strike: Source (and any game with : in the name) creating a new ISO on every launch — old code queried with : but MediaStore stored _, so existence check always failed.
Files touched: data/GameRepository.kt
Commit: 0bc8725 | Tag: v2.1.7-pre | Branch: main
What changed: writeIsoToFrontEnd() now queries MediaStore first and skips writing if the ISO already exists. Fixes Counter-Strike_ Source (1).iso, (2).iso, etc. accumulating in Downloads/front end/ on every launch. Root cause: old delete()+insert() pattern — MediaStore delete() removes catalog entry but not the physical file, so insert() auto-renamed on collision.
Files touched: data/GameRepository.kt
Commit: (README/docs commit) | Tag: v2.1.6 | Branch: main
What changed: Stable release combining v2.1.4-pre (auto-select GameHub app on startup) and v2.1.5-pre (Steam ISO files written automatically). README rewritten to reflect all current features.
Files touched: README.md, PROGRESS_LOG.md
Commit: a364fcf | Tag: v2.1.5-pre | Branch: main
What changed: After scanning Steam games in loadSteamGames(), fetches each game's display name (custom override → Steam Store API → App ID fallback) and calls writeIsoToFrontEnd(name, appId). ISOs land in Downloads/front end/ as <Game Name>.iso containing the Steam App ID — same location and format as imported game ISOs.
Files touched: viewmodel/MainViewModel.kt
Commit: 765cc67 | Tag: v2.1.4-pre | Branch: main
refreshAppList()now auto-selects the first app with a stored data URI on startup- Steam games load immediately without manual app selection, matching imported games behavior
app/src/main/java/com/banner/inject/viewmodel/MainViewModel.kt
Commit: 3794a0d (fix) + e22b112 (feat) | Tag: v2.1.3-pre | Branch: main
- Removed auto-scan of virtual_containers for local games
- New
ImportedGameRepositorystores imports as JSON in SharedPrefs GameRepository:writeIsoToFrontEnd()/deleteIsoFromFrontEnd()via MediaStore → Downloads/front end/- My Games tab always shows Imported Games section (no app selection needed)
- FAB (+ button) opens "Add Imported Game" dialog: Game Name + Local ID
- On add: writes
<name>.isoto Downloads/front end/ + saves entry - On remove: deletes entry + deletes .iso from Downloads
- Steam Games section still requires selecting a GameHub app
- UiState:
games/isLoadingGames→importedGames+steamGames/isLoadingSteam
app/src/main/java/com/banner/inject/data/ImportedGameRepository.kt(new)app/src/main/java/com/banner/inject/data/GameRepository.ktapp/src/main/java/com/banner/inject/viewmodel/MainViewModel.ktapp/src/main/java/com/banner/inject/ui/screens/MyGamesScreen.ktapp/src/main/java/com/banner/inject/MainActivity.kt
Commit: 3447657 | Tag: v2.1.1-pre | Branch: main
scanLocalGames()now includes ALL directories invirtual_containers/— previously only dirs namedlocal*were picked up, silently dropping most imported games
app/src/main/java/com/banner/inject/data/GameRepository.kt
[stable] — v2.1.0 — Landscape rail, GameNative source, PACK_JSON, My Downloads auto-refresh (2026-03-16)
Commit: 5b0acf3 (code) + 1e69e85 (README) | Tag: v2.1.0 | Branch: main
- GameNative added as 9th built-in source (GAMENATIVE_MANIFEST format)
- Download button moved to top of file detail sheet (no longer cut off in landscape)
- 5 sources switched to PACK_JSON (raw JSON, no GitHub API): StevenMXZ GPU Drivers, Arihany WCPHub, K11MCH1, freedreno Turnip CI, MTR
- Nightlies by The412Banner source switched to PACK_JSON (nightlies_components.json)
- Landscape NavigationRail — tabs move to left-side rail in landscape orientation
- My Downloads auto-refreshes (prune + reload) every time the tab is opened
- README rewritten to reflect all current features and 9 built-in sources
data/RemoteSourceRepository.ktui/screens/DownloadScreen.kt,RemoteSourceSheet.ktui/screens/MainTabRow.kt,MainActivity.ktui/screens/DownloadManagerScreen.ktui/screens/AddRepoDialog.ktREADME.md
Commit: ca43b07 | Tag: v2.0.7-pre | Branch: main
- My Downloads tab now auto-refreshes (prunes stale records + reloads list) every time the tab is opened
- Uses
LaunchedEffect(Unit)inDownloadManagerScreen— fires on each composition when tab becomes active
app/src/main/java/com/banner/inject/ui/screens/DownloadManagerScreen.kt
Commit: a5b5a6d | Tag: v2.0.6-pre | Branch: main
- "Nightlies by The412Banner" built-in source switched from
GITHUB_RELEASES_WCP(GitHub Releases API) toPACK_JSONformat - URL changed to
https://raw.githubusercontent.com/The412Banner/Nightlies/refs/heads/main/nightlies_components.json - Filter list updated to match pack.json type strings:
DXVK,VKD3D,FEXCore,Box64,WOWBox64
app/src/main/java/com/banner/inject/data/RemoteSourceRepository.kt
Commit: 2fc715a | Tag: v2.0.5-pre | Branch: main
- Fix: added missing
import androidx.compose.runtime.Composableneeded for@Composable () -> Unitlambda type inMainActivity
Commit: 62f90d1 | Tag: v2.0.4-pre | Branch: main
- Landscape orientation now shows a
NavigationRailon the left side instead of the topScrollableTabRow MainTabRowreturns early (empty) whenLocalIsLandscapeis true — no tab row rendered in landscapeLandscapeNavRailcomposable added toMainTabRow.kt—NavigationRailwith icon + label per tab, badge on Download tab, vertically centered- Tab icons: Inject=Build, Download=Download, Managers=Checklist, Games=SportsEsports
LocalIsLandscapeCompositionLocal added — provided byMainActivity, read byMainTabRowMainActivitydetects orientation viaLocalConfiguration.current.orientation; in landscape wraps screen inRow { LandscapeNavRail + Box(weight=1f) { screen } }- Portrait layout unchanged —
ScrollableTabRowin topBar as before
app/src/main/java/com/banner/inject/ui/screens/MainTabRow.ktapp/src/main/java/com/banner/inject/MainActivity.kt
Commit: 3a1c76d | Tag: v2.0.3-pre | Branch: main
- New
PACK_JSONSourceFormat for flat[{type, verName, remoteUrl}]files — bypasses GitHub API rate limit fetchPackJson()— fetches and filters by type; mapsGpuDriver→ GPU DriverscacheAllPackJson()— fetches once, populates all type bucketsdiscoverTypesPACK_JSON case — reads uniquetypevalues from array- Wired into
fetchFromSource,refreshAllCache(primary + extra endpoint blocks) - Sources switched from
api.github.comto raw JSON:- StevenMXZ GPU Drivers extra →
Nightlies/stevenmxz_drivers.json - Arihany WCPHub → Arihany
pack.json(raw), extra endpoint removed - AdrenoToolsDrivers (K11MCH1) →
Nightlies/kimchi_drivers.json - freedreno Turnip CI (whitebelyash) →
Nightlies/white_drivers.json - MaxesTechReview (MTR) →
Nightlies/mtr_drivers.json
- StevenMXZ GPU Drivers extra →
data/RemoteSourceRepository.kt
Commit: b4ffdb9 | Tag: v2.0.2-pre | Branch: main
- Download button (and progress indicator) moved to top of component detail ModalBottomSheet in both Download Components screens
- Previously the button was at the bottom and got cut off in landscape mode
- New order: title → download button → chips → metadata → release notes
ui/screens/DownloadScreen.ktui/screens/RemoteSourceSheet.kt
Commit: 1e3662a | Tag: v2.0.1-pre | Branch: main
- Added GameNative as a built-in source (9th built-in repo)
- New
GAMENATIVE_MANIFESTSourceFormat foritems.driver/dxvk/proton/fexcore/wowbox64JSON fetchGameNativeManifest()— fetches items for a single componentType; mapsdriverkey →GPU DriverscacheAllGameNativeManifest()— fetches once, populates all category bucketsdiscoverTypes()— GAMENATIVE_MANIFEST case reads manifest keys, normalisesdriver→GPU DriversautoDetectFormat()— detects gamenative manifest URL before raw.githubusercontent.com fallback
data/RemoteSourceRepository.ktui/screens/AddRepoDialog.kt
Commit: 21c3717 (code) + 9bc85c1 (README) | Tag: v2.0.0 | Branch: main
- Export repo list: FileDownload icon in Download Components source list header — writes
bci-repos.jsontoDownloads/BannersComponentInjector/via MediaStore; includes custom sources, hidden defaults, source order - Import repo list: FileUpload icon opens JSON file picker; preview dialog shows incoming custom repos, hidden built-ins, order info; Merge (default) vs Replace; applies on confirm
data/RemoteSourceRepository.kt—RepoListImport,exportRepoListJson(),parseRepoListJson(),applyRepoListImport(),parseRemoteSourceObject()helperui/screens/DownloadScreen.kt— import launcher, state vars, export/import buttons, preview dialog,exportRepoListToDownloads()suspend funREADME.md— Export/Import sections added
Commit: 21c3717 | Tag: v1.9.8-pre | Branch: main
- Export repo list: FileDownload icon in Download Components source list header — writes
bci-repos.jsontoDownloads/BannersComponentInjector/via MediaStore (overwrites existing); includes custom sources, hidden defaults, source order - Import repo list: FileUpload icon opens JSON file picker; preview dialog shows incoming custom repos, hidden built-ins, order info; Merge (default, add new only) vs Replace (swap all custom sources); applies on confirm
- Refactored
getCustomSources()to use sharedparseRemoteSourceObject()helper reused by newparseRepoListJson()
data/RemoteSourceRepository.kt—RepoListImportdata class,exportRepoListJson(),parseRepoListJson(),applyRepoListImport(),parseRemoteSourceObject()helperui/screens/DownloadScreen.kt— import launcher, state vars, export/import buttons, preview dialog,exportRepoListToDownloads()suspend fun
Commit: 0c1886e (code) + 1af1fb3 (README) | Tag: v1.9.7 | Branch: main
- "Remove from list" — hides local game, folder untouched, persists in SharedPrefs
- "Remove and delete folder" — SAF delete of virtual_containers// + ISO stub; confirmation dialog
data/GameRepository.kt,viewmodel/MainViewModel.kt,ui/screens/MyGamesScreen.kt,MainActivity.ktREADME.md— updated My Games section + Features bullets
Commit: b90fe2b | Tag: v1.9.6-pre | Branch: main
- "Remove from list" — hides a local game without touching the filesystem; hidden IDs stored in SharedPrefs, filtered on every scan (persists across restarts)
- "Remove and delete folder" — deletes
virtual_containers/<gameId>/via SAF + removes<gameId>.isostub; protected by confirmation dialog with spinner - Both options appear only on local game cards, separated from Edit/Reset by a divider
- Solves the GameHub leftover virtual container problem (GH uninstalls game but leaves the folder)
data/GameRepository.kt—deleteLocalGameFolder()viewmodel/MainViewModel.kt—hideLocalGame(),deleteLocalGameFolder(), hidden IDs prefs, filter inloadGames()ui/screens/MyGamesScreen.kt— new menu items, confirmation dialog, new callbacksMainActivity.kt—onHideGame+onDeleteGamewired to ViewModel
Commit: 09d81cd (code) + e2ace95 (README) | Tag: v1.9.5 | Branch: main
- My Games tab: launch GameHub games; browse local + Steam games; offline Steam metadata; edit cards; ISO creator
- Single
data/grant — one SAF permission covers components, virtual containers, and shadercache - Show My Games Tab toggle in Settings (hidden by default)
- Fix: disk I/O off main thread — cover art no longer stuck in loading state (v1.9.2)
- Fix: search thumbnails always fetch fresh from CDN; portrait → header fallback chain (v1.9.3)
- New-component dot badge on Download tab (fingerprint-based; clears on tab open) (v1.9.4)
- "NEW" chip on individual source/repo cards when that source has unseen items (v1.9.5)
data/RemoteSourceRepository.kt,ui/screens/MainTabRow.kt,MainActivity.ktui/screens/DownloadScreen.kt,ui/screens/MyGamesScreen.ktREADME.md— rewritten for v1.9.5
Commit: 8f392b7 | Tag: v1.9.5-pre | Branch: main
- "NEW" chip shown on individual source/repo cards in the Download Components screen when that specific source has new items (i.e. items not yet seen on a previous launch)
- Chip uses
primaryContainerbackground andonPrimaryContainertext; 9sp bold "NEW" label getNewSourceNames()added toRemoteSourceRepository— derives set of source names with unacknowledged fingerprints; same prefs as the tab-level badge
data/RemoteSourceRepository.kt—getNewSourceNames()ui/screens/DownloadScreen.kt—remember { repo.getNewSourceNames() }, "NEW" chip in source card
Commit: a35fa37 | Tag: v1.9.4-pre | Branch: main
- On app launch, background
refreshAllCache+ fingerprint comparison detects new items in any source - Primary-color dot badge appears on "Download Components" tab when sources have items newer than the last visit
- Badge clears + snapshot saved when user opens the Download tab
- First-run: baseline established silently — no phantom badge on fresh install
data/RemoteSourceRepository.kt—currentFingerprints(),hasNewItems(),markAllAsSeen(), prefs storageui/screens/MainTabRow.kt—LocalHasNewDownloadsCompositionLocal, dot badge in tab labelMainActivity.kt—hasNewDownloadsstate, background LaunchedEffect, tab-switch LaunchedEffect, CompositionLocalProvider
Commit: 2920f59 | Tag: v1.9.3-pre | Branch: main
- Fix: search result thumbnails in Edit Game sheet never loaded — old code used
error={}(renders nothing), Coil cached 404 responses for apps without portrait cover art - New
SearchResultThumbnailcomposable: disk cache disabled, trieslibrary_600x900.jpg→ falls back toheader.jpg→ fallback icon
ui/screens/MyGamesScreen.kt
Commit: d8593f9 | Tag: v1.9.2-pre | Branch: main
- Fix: cover thumbnails in Edit Game → Search Steam results were stuck in loading state since v1.9.1-pre added disk cache
- Root cause: synchronous SharedPreferences + JSON reads on main thread blocked Coil's image callbacks
SteamGameCardnow loads info entirely viaLaunchedEffect+fetch()(off main thread); removed disk I/O fromremember{}LaunchedEffect(games)now batches override reads onDispatchers.IObefore applying to state map
ui/screens/MyGamesScreen.kt
Commit: 96ab8e2 | Tag: v1.9.1-pre | Branch: main
- My Games tab: local imports + Steam games, card metadata, hamburger edit, Steam search, ISO creator, offline metadata persistence
- Single SAF grant at
<package>/datacovers components + all game folders - Show My Games Tab toggle in Settings (default off)
- All beta builds (b2–b10) merged to main and beta releases deleted
Commit: c6c9277 | Tag: beta-v1.9.1-b8 | Branch: beta
- Single SAF grant at
Android/data/<pkg>replaces 3 separate grants ComponentRepository.navigateToComponents(dataRoot)—files/usr/home/components/GameRepository.navigateToVirtualContainers(dataRoot)—files/usr/home/virtual_containers/GameRepository.navigateToShadercache(dataRoot)—files/Steam/steamapps/shadercache/MainViewModel: singledata_uri_<pkg>pref key;hasDataAccess();loadComponents()/loadGames()both navigate from data root;revokeAccessalso clears games app;createIsoFilesnavigates to virtual_containersMyGamesScreen: one folder picker,hasDataAccess,onAccessGranted/onRevokeAccess, dialogs showAndroid/data/<pkg>path;GamesAppCardshows single "Access Granted" chipAppListScreen: grant guide updated — "navigate to Android/data/"MainActivity:onAccessGrantedroutes to sharedvm.grantAccess()⚠️ Existing grants invalidated — users must re-grant atdata/level
data/ComponentRepository.ktdata/GameRepository.ktviewmodel/MainViewModel.ktui/screens/MyGamesScreen.ktui/screens/AppListScreen.ktMainActivity.kt
Commit: 37d2bcd | Tag: beta-v1.9.1-b7 | Branch: beta
- Added "Show My Games Tab" Switch in Settings → General section (default OFF)
LocalShowGamesTabCompositionLocal in MainTabRow drives tab visibilityMainTabRowfilters GAMES tab from visible tabs when toggle is OFFMainActivity: declaresshowMyGamesTabmutableStateOf (readsbci_settingsprefs), wraps content inCompositionLocalProvider(LocalShowGamesTab provides showMyGamesTab), addsLaunchedEffectfallback (if tab hidden while on GAMES → switch to INJECT), wires toggle to all 5 SettingsSheet call sitesAppListScreen+ComponentListScreen: accept and forwardshowMyGamesTab/onShowMyGamesTabChanged
MainActivity.ktui/screens/AppListScreen.ktui/screens/HomeScreen.ktui/screens/MainTabRow.kt(CompositionLocal declared here)ui/screens/SettingsSheet.kt
Commit: 86e3989 (code) / 2a64101 (docs) | Tag: v1.9.0
- From My Downloads button in ComponentDetailSheet
- Inject into GameHub button in DownloadManagerScreen (two-step app→component picker, Done/Error snackbar)
- Light mode / Dark mode toggle in Settings → Appearance
- AMOLED black checkbox (disabled when Dynamic Color on)
- Dynamic Color (Material You) toggle — Android 12+; hides accent picker, disables AMOLED
- In-app changelog in update dialog (scrollable, max 180dp) and Settings update card (max 150dp)
- Update dialog size fix (fillMaxSize → fillMaxWidth)
- Markdown stripping in all changelog Text composables
- AMOLED disabled with subtitle when Dynamic Color is on
- All BCI UI and data source files (multiple screens)
- README.md — full rewrite for v1.9.0
[pre-release] — v1.8.9-pre — Polish fixes: inject feedback, AMOLED+DynColor, markdown strip (2026-03-11)
Commit: 86e3989 | Tag: v1.8.9-pre
- Inject feedback: DownloadManagerScreen shows Done/Error snackbar after inject via
opStateLaunchedEffect;hadRecentInjectgate prevents false positives from unrelated state changes - AMOLED + Dynamic Color: AMOLED checkbox is disabled when Dynamic Color is on (
amoledEnabled = isDarkMode && !isDynamicColor); shows "Not available with Dynamic Color" subtitle - Markdown stripping: changelog text in both the SettingsSheet update card and MainActivity launch-time AlertDialog now runs through
stripMarkdown()— removes#,**,*,`, converts-/+bullets to•, strips blockquotes
ui/screens/DownloadManagerScreen.kt— inject result snackbar via LaunchedEffect(opState)ui/screens/SettingsSheet.kt— applystripMarkdown()to changelog TextMainActivity.kt— applystripMarkdown()to changelog Text in AlertDialog (already done in previous commit, no further change)
Commit: 3d458a8 | Tag: v1.8.8-pre
- Fix: Update dialog during download was huge —
Modifier.fillMaxSize()on the progress column changed tofillMaxWidth(); also fixedSpacer.width→Spacer.height - Changelog in update dialog: scrollable "What's new" section (max 180dp) shown in the launch-time AlertDialog between version line and buttons, pulled from the GitHub release body
- Changelog in Settings update card: same section (max 150dp) shown in
UpdateState.Availablecard in Settings → Updates UpdateRepository.ReleaseInfonow includesbody: String?parsed from GitHub API
data/UpdateRepository.kt— addedbody: String?toReleaseInfoMainActivity.kt— fixed dialog size, added changelog + importsui/screens/SettingsSheet.kt— added changelog to Available card + imports
Commit: 0224bec | Tag: v1.8.7-pre
- Dark Mode toggle in Appearance settings — switches between full light and dark schemes
- AMOLED Black checkbox (only active when dark mode is on) — true black (
#000000) background +#111111surface variant; text brightened to#EEEEEE/#CCCCCCfor contrast - Dynamic Color toggle (Android 12+ only) — uses Material You wallpaper-derived scheme; grayed out with note on Android 11 and below; accent picker hidden while active
- Light mode color scheme —
lightColorSchemebuilt from accent, auto-darkens overly bright accents for white-surface readability - Tertiary color added to both dark and light schemes (
#66BB6A/#388E3C) — fixes downloaded checkmark rendering in all modes
ui/theme/ThemePrefs.kt— load/save fordark_mode,amoled_mode,dynamic_colorui/theme/Theme.kt—buildDarkScheme(amoled),buildLightScheme(), updatedBannersComponentInjectorThemesignatureui/screens/SettingsSheet.kt— Display Mode card + Material You card; 6 new params with defaults; accent picker conditional on dynamic color offui/screens/AppListScreen.kt— 6 new theme params forwarded to SettingsSheetui/screens/HomeScreen.kt— sameMainActivity.kt— 3 new state vars wired to theme + all 4 SettingsSheet call sites
Commit: 426f1c7 | Tag: v1.8.6-pre
- Feature 1 – "From My Downloads" in ComponentDetailSheet (Inject tab):
- New
FilledTonalButton"From My Downloads" between Local File and Online Source - Opens
MyDownloadsPickerbottom sheet listing all previously downloaded files (newest-first) - Shows source, type, size per item; resolves SAF or MediaStore URI and injects
- Integrated into the no-backup warning flow (refactored pending source tracking to
ReplaceSourceenum)
- New
- Feature 2 – "Inject into GameHub" button in My Downloads tab:
SystemUpdateAlticon button on each file in the type→file list- Opens
InjectPickerSheet: Step 1 = pick accessible GameHub app, Step 2 = load & pick component - Loading indicator while components are fetched; back button to return to app selection
- Snackbar feedback on injection start
MainViewModel.getComponentsForApp(): new suspend function loads components for any app without touching main UI state
ui/screens/ComponentDetailSheet.kt— ReplaceSource enum, From My Downloads button, MyDownloadsPicker composable, resolveDownloadUri helperui/screens/DownloadManagerScreen.kt— new params (apps/onGetComponentsForApp/onInjectInto), Inject button per file, InjectPickerSheet composable, resolveManagerDownloadUri helperviewmodel/MainViewModel.kt— getComponentsForApp() suspend funMainActivity.kt— wires apps/onGetComponentsForApp/onInjectInto to DownloadManagerScreen
Commit: 8f9b765 (code) | 3e85a4d (docs) | Tag: v1.8.5
- Custom app entries (+ button in Inject tab)
- Multi-install dropdown picker for same-group variants
- GameHub label detection (excludes real apps sharing package names)
- Report Issue / Feedback button in Settings → Utilities
- Clickable URLs in release notes (DownloadScreen + RemoteSourceSheet)
- Check for updates on launch toggle (Settings → Updates)
- Bug fix: null safety for
DocumentFile.listFiles()in ComponentRepository + BackupManager (9 call sites)
- All code changes from v1.8.1-pre through v1.8.4-pre
- README.md rewritten to reflect all v1.8.5 features
Commit: 28a21b2 | Tag: v1.8.4-pre
ComponentRepository: added null safety (?./?: emptyList()) on everylistFiles()call —scanComponentDirs,collectFilesRecursively,replaceWithWcp(clear step),restoreComponent(clear step),deleteRecursivelyextensionBackupManager: same null safety applied tolistAllBackups,copyDocumentToDownloads,copyDocumentToDocumentFile,collectDocumentFiles,countFilesInDoc- Prevents NPE crashes when SAF provider returns null on low-storage, permission edge cases, or provider failures
app/src/main/java/com/banner/inject/data/ComponentRepository.ktapp/src/main/java/com/banner/inject/data/BackupManager.kt
Commit: 1bc62b3 | Tag: v1.8.3-pre
SettingsSheet: new "Check for updates on launch"Switchrow in Updates section; pref keyupdate_check_on_launch, defaultfalse; separated from Include pre-releases byHorizontalDividerMainActivity:LaunchedEffect(Unit)reads pref; if enabled, callsUpdateRepository.fetchLatestRelease(includePreReleases); if update found, setslaunchUpdateReleasestateAlertDialogshown whenlaunchUpdateRelease != null: shows tag name, installed version, Download & Install withmutableFloatStateOfprogress %, View on GitHub, Not Now; non-dismissible while downloading
app/src/main/java/com/banner/inject/MainActivity.ktapp/src/main/java/com/banner/inject/ui/screens/SettingsSheet.kt
Commit: 1899e0b | Tag: v1.8.2-pre
LinkedTextcomposable added toDownloadScreen.kt(accessible across the package): detects URLs viaandroid.util.Patterns.WEB_URL, buildsAnnotatedStringwithSpanStyle(primary color + underline), opens viaACTION_VIEWon tap viaClickableText- Release notes
Text()replaced withLinkedText()inDownloadScreen.ktdetail sheet - Release notes
Text()replaced withLinkedText()inRemoteSourceSheet.ktdetail sheet
app/src/main/java/com/banner/inject/ui/screens/DownloadScreen.ktapp/src/main/java/com/banner/inject/ui/screens/RemoteSourceSheet.kt
Commit: 939f9f5 | Tag: v1.8.1-pre
- Added "Report Issue / Feedback"
OutlinedButtonto Settings → Utilities section - Opens
https://github.com/The412Banner/BannersComponentInjector/issuesviaACTION_VIEWintent - Uses
Icons.Default.BugReporticon
app/src/main/java/com/banner/inject/ui/screens/SettingsSheet.kt
[stable] — v1.8.0 — Stable release: custom app entries, multi-install picker, GameHub label detection (2026-03-10)
Commit: f052d60 (code) | b8413fb (docs) | Tag: v1.8.0
- Custom app entries — + button in Inject tab top bar;
AddCustomAppDialog(name + package name, duplicate check); trash icon with confirm dialog to remove;KnownApp.isCustom;addCustomApp()/removeCustomApp()/loadCustomApps()/saveCustomApps()in ViewModel; persisted as JSON in SharedPreferences - Multi-installed variant picker —
GameHubApp.installedPackages;DropdownMenuinAppCardwhen multiple packages from the same group are installed; per-package Access badge; each variant stores its own independent SAF URI;hasAccessForPackage()in ViewModel - GameHub label detection —
isLikelyGameHub()helper; borrowed package names (com.tencent.ig, com.mihoyo.genshinimpact, com.antutu., com.ludashi.) verified against app display label; real apps excluded - README.md fully rewritten
app/src/main/java/com/banner/inject/model/Models.ktapp/src/main/java/com/banner/inject/viewmodel/MainViewModel.ktapp/src/main/java/com/banner/inject/ui/screens/AppListScreen.ktapp/src/main/java/com/banner/inject/MainActivity.ktREADME.md
[pre-release] — v1.7.3-pre — Fix: real apps with borrowed package names excluded from GameHub list (2026-03-10)
Commit: f052d60 | Tag: v1.7.3-pre
isLikelyGameHub(pm, packageName, isCustom): new helper inMainViewModel- Packages with "gamehub" in name → always trusted
- Custom apps → always trusted
- Borrowed package names (e.g.
com.tencent.ig,com.mihoyo.genshinimpact,com.antutu.*,com.ludashi.*) → label checked for "GameHub" or "Game Hub" - Real apps (PUBG Mobile, Genshin Impact, AnTuTu, etc.) fail the label check and are excluded
refreshAppList():installedPkgsfilter now callsisLikelyGameHub()after detecting install
app/src/main/java/com/banner/inject/viewmodel/MainViewModel.kt
Commit: 5017718 | Tag: v1.7.2-pre
GameHubApp: addedinstalledPackages: List<String>— all packages from the group that are actually installedrefreshAppList(): collects ALL installed packages per group (not just first); custom apps get their own package ininstalledPackagesgrantAccess(): stores URI only foractivePackage(not all group members) — independent URIs per variantselectApp(): prioritizesactivePackageURI, falls back to any in grouphasAccessForPackage(pkg): Boolean: new ViewModel function for per-package access checkAppCard:onMultiPackageSelectcallback +hasAccessForPackageparam;DropdownMenuwith per-package Access badges wheninstalledPackages.size > 1;ArrowDropDownicon; subtitle shows "N variants installed — tap to select"AppListScreen: passeshasAccessForPackagelambda; buildseffectiveAppwith correctactivePackageandhasAccesson dropdown selectionMainActivity: wireshasAccessForPackage
app/src/main/java/com/banner/inject/model/Models.ktapp/src/main/java/com/banner/inject/viewmodel/MainViewModel.ktapp/src/main/java/com/banner/inject/ui/screens/AppListScreen.ktapp/src/main/java/com/banner/inject/MainActivity.kt
Commit: e6f6d12 | Tag: v1.7.1-pre
KnownApp: addedisCustom: Boolean = falseflagMainViewModel:addCustomApp(),removeCustomApp(),loadCustomApps(),saveCustomApps()— JSON persistence inbci_prefsunder"custom_gamehub_apps"keyrefreshAppList(): mergesKNOWN_GAMEHUB_APPS + loadCustomApps(); custom apps forced toisInstalled = trueso card is always tappable (Android 11+ blocks package visibility for unknown packages)AppListScreen:+(AddCircleOutline) button in top bar;AddCustomAppDialog(name + package name fields, duplicate check); trash icon on custom app cards; delete confirm dialog; two new callbacksonAddCustomApp/onRemoveCustomAppMainActivity: wired new callbacks to ViewModel
app/src/main/java/com/banner/inject/model/Models.ktapp/src/main/java/com/banner/inject/viewmodel/MainViewModel.ktapp/src/main/java/com/banner/inject/ui/screens/AppListScreen.ktapp/src/main/java/com/banner/inject/MainActivity.kt
[stable] — v1.7.0 — Stable release: GPU Drivers, release tags, repo ordering, edit dialog improvements (2026-03-10)
Commit: f277636 (code) | afbe90d (docs) | Tag: v1.7.0
- GPU Drivers unified category — Turnip, Adreno, Qualcomm, Mesa files combined into single "GPU Drivers" category across all sources;
GPU_DRIVER_TYPEconstant;normalizeGpuTypes()helper - FEX/FEXCore filename bridge — files named
fex-*.wcpvisible underfexcoretype and vice versa - Nightlies by The412Banner built-in source — 8th built-in; GITHUB_RELEASES_WCP format
- HUB Emulators (T3st31) built-in source — 7th built-in; RANKING_EMULATORS_JSON format
- Release tag browsing —
RemoteSource.releaseTagsfield;discoverReleaseTags();fetchGithubReleaseByTag()returns all assets any file type;typesToShowappends enabled release tags - Edit dialog — full merged type list — union of configured + discovered types; "new" badge on newly found; existing types never lost
- Edit dialog — Additional Releases section — separate section below divider; individual GitHub release names listed; each can be toggled independently; Select All / Deselect All
- Repo reordering — Move Up / Move Down in each repo's hamburger menu; order persisted in SharedPreferences
source_order - README.md fully rewritten to reflect all current features
app/src/main/java/com/banner/inject/data/RemoteSourceRepository.ktapp/src/main/java/com/banner/inject/ui/screens/EditRepoDialog.ktapp/src/main/java/com/banner/inject/ui/screens/DownloadScreen.ktapp/src/main/java/com/banner/inject/ui/screens/RemoteSourceSheet.ktREADME.md
[pre-release] — v1.6.8-pre — Opt-in individual GitHub releases as browseable categories (2026-03-10)
Commit: 29473bf | Tag: v1.6.8-pre
RemoteSource.releaseTags: List<String>— new field for user-opted release name categoriesgetCustomSources/saveCustomSources: serialize/deserializereleaseTagsdiscoverReleaseTags(source): fetches all release names from GITHUB_RELEASES_* URLsfetchGithubReleaseByTag(url, tag, sourceName): returns ALL assets from matching release (any file type)fetchFromSource: routes tofetchGithubReleaseByTagwhencomponentType in source.releaseTagsrefreshAllCache: also cachesreleaseTagsentriesEditRepoDialog: new "Additional Releases" section (below divider); parallel discovery on open; pre-checks saved tags; "new" label on newly discovered; Select All / Deselect All per section; save persists toreleaseTagsDownloadScreen+RemoteSourceSheet:typesToShowappendssource.releaseTagsafter component types
app/src/main/java/com/banner/inject/data/RemoteSourceRepository.ktapp/src/main/java/com/banner/inject/ui/screens/EditRepoDialog.ktapp/src/main/java/com/banner/inject/ui/screens/DownloadScreen.ktapp/src/main/java/com/banner/inject/ui/screens/RemoteSourceSheet.kt
Commit: 2fe41bc | Tag: v1.6.7-pre
typesToShow= union ofsource.supportedTypes(first, pre-checked) +discoveredTypes(appended, unchecked by default)- Currently-configured types never silently dropped when discovery partially fails
- Newly discovered types labelled "new" in primary color so user knows they're additional
- Save logic filters
typesToShow(not justdiscoveredTypes) so nothing is lost - "No types detected" message only shows when
typesToShowis truly empty - Select All / Deselect All operate on the full merged list
app/src/main/java/com/banner/inject/ui/screens/EditRepoDialog.kt
Commit: 575231d | Tag: v1.6.6-pre
saveSourceOrder(orderedNames)/getSourceOrder()persist order in SharedPreferences (source_orderkey, newline-separated names)getAllSources()applies saved order; unknown names go at endremoveSource()removes the source name from saved orderrestoreDefaultSources()also clearssource_orderso defaults revert to natural order- DownloadScreen + RemoteSourceSheet:
items()→itemsIndexed(); Move Up and Move Down added at top of each repo's hamburger menu (disabled at list boundaries); list reloads immediately after each move
app/src/main/java/com/banner/inject/data/RemoteSourceRepository.ktapp/src/main/java/com/banner/inject/ui/screens/DownloadScreen.ktapp/src/main/java/com/banner/inject/ui/screens/RemoteSourceSheet.kt
Commit: 2ba1b2e | Tag: v1.6.5-pre
GPU_DRIVER_TYPE = "GPU Drivers"andGPU_DRIVER_KEYWORDS = [turnip, adreno, qualcomm, mesa]constants added to companion object- All GPU driver source
supportedTypesandextraEndpoints.typesupdated to use "GPU Drivers" instead of individual keywords normalizeGpuTypes()helper collapses any GPU keyword list into a single "GPU Drivers" entryfetchFromSource: routes "GPU Drivers" to the correct extra endpoint; passes blank filterKeyword to TURNIP formatfetchWcpJson: matches any GPU keyword when componentType is GPU DriversfetchGithubReleasesWcp: gpuMatch condition — matches any GPU keyword file for GPU Drivers typefetchRankingEmulators: skips manifestDrivers for GPU Drivers; accepts all Drivers-category assets matching any GPU keywordrefreshAllCache: TURNIP primary + extra endpoint — GPU Drivers gets full unfiltered item listcacheAllRankingEmulators: GPU driver assets cached under single "GPU Drivers" bucket instead of per-keyworddiscoverTypes: "mesa" added to knownTypes; TURNIP returns["GPU Drivers"]; WCP/ZIP applynormalizeGpuTypes(); RANKING appends "GPU Drivers" if any GPU keyword asset foundcomponentTypesin DownloadScreen and RemoteSourceSheet updated (removed turnip/adreno/qualcomm, added GPU_DRIVER_TYPE)
app/src/main/java/com/banner/inject/data/RemoteSourceRepository.ktapp/src/main/java/com/banner/inject/ui/screens/DownloadScreen.ktapp/src/main/java/com/banner/inject/ui/screens/RemoteSourceSheet.kt
Commit: 0be72a5 | Tag: v1.6.4-pre
- Added "Nightlies by The412Banner" as 8th built-in source (
GITHUB_RELEASES_WCP)- URL:
https://api.github.com/repos/The412Banner/Nightlies/releases - Types: dxvk, vkd3d, fex, fexcore, box64
- URL:
fetchGithubReleasesWcp: fex/fexcore bridge — when componentType is "fexcore", also matches assets containing "fex" in the name (and vice versa). Fixes FEX-named WCP files not showing under fexcore component folders.discoverTypes(GITHUB_RELEASES_WCP): same bridge applied — scanning releases with "fex"-named assets now surfaces both "fex" and "fexcore" as available types.
app/src/main/java/com/banner/inject/data/RemoteSourceRepository.kt
[pre-release] — v1.6.3-pre — HUB Emulators (T3st31) built-in source + RANKING_EMULATORS_JSON format (2026-03-09)
Commit: f277636 (docs: c439587) | Tag: v1.6.3-pre
- New
SourceFormat.RANKING_EMULATORS_JSONfor sites serving arankings.json fetchRankingEmulators(): WCP types frommanifestDriverssection; GPU driver types fromresults[Drivers]assets filtered by keywordcacheAllRankingEmulators(): fetches JSON once, caches all types in one passdiscoverTypes(): reads manifestDrivers keys + scans Drivers assets for turnip/adreno/qualcommDownloadScreen+RemoteSourceSheet: triggerdiscoverTypesfor RANKING_EMULATORS_JSON (same path as GITHUB_REPO_CONTENTS)AddRepoDialog.autoDetectFormat: detectst3st31.github.ioorrankings.jsonURLs- HUB Emulators (T3st31) added as 7th default built-in source
app/src/main/java/com/banner/inject/data/RemoteSourceRepository.ktapp/src/main/java/com/banner/inject/ui/screens/DownloadScreen.ktapp/src/main/java/com/banner/inject/ui/screens/RemoteSourceSheet.ktapp/src/main/java/com/banner/inject/ui/screens/AddRepoDialog.kt
[pre-release] — v1.6.2-pre — Fix Qualcomm/non-turnip assets hidden by filename filter (2026-03-09)
Commit: 43f4888 | Tag: v1.6.2-pre
fetchTurnipReleasesgains optionalfilterKeywordparam; when set, filters assets by keyword; when empty, returns all assetsfetchFromSourcepassescomponentTypeas the keyword — direct browse now correctly shows only matching assets per typerefreshAllCache(TURNIP format, primary + extraEndpoints): fetches all assets once unfiltered, then filters per type before caching- Root cause: previously everything was filtered to "turnip" keyword regardless of selected type, so Qualcomm-named assets were silently dropped
app/src/main/java/com/banner/inject/data/RemoteSourceRepository.kt
Commit: a29802e | Tag: v1.6.1-pre
- Added "qualcomm" to all GPU-driver repo
supportedTypes(StevenMXZ, Arihany, K11MCH1, freedreno Turnip CI) and their extraEndpoints - Added "qualcomm" to
knownTypesandGITHUB_RELEASES_TURNIPdefault type return inRemoteSourceRepository - Added "qualcomm" to
componentTypesfallback list inDownloadScreenandRemoteSourceSheet
app/src/main/java/com/banner/inject/data/RemoteSourceRepository.ktapp/src/main/java/com/banner/inject/ui/screens/DownloadScreen.ktapp/src/main/java/com/banner/inject/ui/screens/RemoteSourceSheet.kt
[stable] — v1.6.0 — Cross-repo search, batch downloads, detail sheets, pull-to-refresh, parity (2026-03-09)
Commit: cd38edd | Tag: v1.6.0
- Parallel + streaming component scanner with live progress counter
- Pull-to-refresh on Inject tab component list
- Cross-repo search (always-visible) in Download Components tab
- File sizes shown on download items
- Release Notes (GitHub release body) in file detail sheets
- Tap-to-detail: file cards open detail sheet before downloading (both tabs)
- Batch multi-select downloads with parallel execution and skip-already-downloaded
- Verify Downloads / pull-to-refresh on My Downloads tab (prunes stale records)
- Parity: Inject → Online Sources now has hamburger repo menu + tap-to-detail + cross-repo search, matching Download Components tab
- README.md (rewritten), PROGRESS_LOG.md
ui/screens/HomeScreen.kt,ui/screens/DownloadScreen.kt,ui/screens/DownloadManagerScreen.kt,ui/screens/RemoteSourceSheet.ktdata/RemoteSourceRepository.kt,viewmodel/MainViewModel.kt,data/ComponentRepository.kt
[pre-release] — v1.5.13-pre — Parity: hamburger menu + tap-to-detail in RemoteSourceSheet (2026-03-09)
Commit: 6e4f85a | Tag: v1.5.13-pre
- RemoteSourceSheet repo cards: replaced plain Delete button with
MoreVerthamburger dropdown matching DownloadScreen — "Open in Browser", "Edit Repository", "Remove Repository" - RemoteSourceSheet file cards (step 3): tap now opens detail sheet instead of immediate download; shows name, source/type chips, published date+size, scrollable "Release Notes", "Download & Replace" button
- RemoteSourceSheet search results: same — tap opens detail sheet instead of immediate download
- Imports added:
Intent,LocalContext,rememberScrollState,verticalScroll,MoreVert,OpenInBrowser,Edit,Download,CheckCircle - Implements PARITY RULE: all features from Download Components tab now mirrored in Inject → Online Sources
app/src/main/java/com/banner/inject/ui/screens/RemoteSourceSheet.kt
Commit: e1345bf | Tag: v1.5.12-pre2
- Swipe-down pull-to-refresh in My Downloads runs
pruneStaleDownloadRecords, refreshesdownloadslist, shows snackbar if stale records removed (silent if all up to date) - Uses
PullToRefreshContainer+rememberPullToRefreshStatefrommaterial3.pulltorefresh; content wrapped inBoxwithnestedScroll - Fix:
LaunchedEffectmoved aftervar downloadsdeclaration to avoid "Unresolved reference" compile error
app/src/main/java/com/banner/inject/ui/screens/DownloadManagerScreen.kt
[pre-release] — v1.5.11-pre — Description field, tap-to-detail, verify downloads in My Downloads (2026-03-09)
Commit: a66f8e4 | Tag: v1.5.11-pre
RemoteItem.description: new nullable field; populated from GitHub releasebodyfor GITHUB_RELEASES_WCP/ZIP/TURNIP; null for WCP JSON and GITHUB_REPO_CONTENTS (no description available in those formats)- Tap-to-detail in Download Components tab: tapping a file opens a
ModalBottomSheetdetail sheet showing file name, source+type chips, published date+size, scrollable "Release Notes" section (if description non-null), then a "Download to Device" button; same for cross-repo search results - Verify Downloads moved from Download Components header → My Downloads top bar; pruning now also refreshes
downloadsstate live - Removed
isVerifyingstate from DownloadScreen;SearchContentrefactored to drop all download logic (now takesonShowDetailcallback only)
app/src/main/java/com/banner/inject/data/RemoteSourceRepository.ktapp/src/main/java/com/banner/inject/ui/screens/DownloadScreen.ktapp/src/main/java/com/banner/inject/ui/screens/DownloadManagerScreen.kt
Commit: 19f1194 | Tag: v1.5.10-pre
- Verify Downloads (
CloudSyncicon button) in Download Components tab header, next to Refresh All RemoteSourceRepository.pruneStaleDownloadRecords(context: Context): Int: checks each download record's URI against the actual filesystem; removes stale records; returns count removedcontent://URIs verified viaContentResolver.query()(row count == 0 → stale); file/path URIs viaFile.exists()- Snackbar: "Removed X stale download record(s)" or "All download records are up to date"
- Spinner shown while running; disabled while downloading/loading
app/src/main/java/com/banner/inject/data/RemoteSourceRepository.ktapp/src/main/java/com/banner/inject/ui/screens/DownloadScreen.kt
[pre-release] — v1.5.9-pre5 — Cross-repo search at step 1 of online sources (Inject tab) (2026-03-09)
Commit: c9a56e8 | Tag: v1.5.9-pre5
- Cross-repo search at step 1 of RemoteSourceSheet: search field at the top of the "Select Online Repository" screen, before any repo is chosen
LaunchedEffect(searchQuery)triggersrepo.refreshAllCache(sources, componentTypes)if cache is cold- When query is non-empty, shows
RemoteSourceRepository.searchCache(query)results instead of repo list - Result cards show file name + source name + component type; tapping downloads to temp and calls
onDownloadAndReplace - Back handler: clears
searchQuerybefore navigating; if already empty, navigates back normally - Removed file-level filter that was added at step 3 in pre4
app/src/main/java/com/banner/inject/ui/screens/RemoteSourceSheet.kt
Commit: fa44359 | Tag: v1.5.9-pre4
- Search/filter bar in RemoteSourceSheet file list (step 3): filter field above the file list when browsing online sources to replace a component in the Inject tab
- Filters files by
displayNameas you type (case-insensitive, trims whitespace) displayedItems = sortedItems.filter { ... }— respects current sort order- Back button clears
fileSearchQuerybefore navigating up to type selection - Removed incorrectly placed search bar from local component list (
HomeScreen)
app/src/main/java/com/banner/inject/ui/screens/RemoteSourceSheet.ktapp/src/main/java/com/banner/inject/ui/screens/HomeScreen.kt(reverted pre3 search bar)
Commit: 32326dc | Tag: v1.5.9-pre3
- Search/filter bar on Inject tab: always-visible
OutlinedTextFieldin the top bar (below tab row) inComponentListScreen - Filters the component list by folder name as you type (case-insensitive, trims whitespace)
- Count label updates to "X of Y components" when a filter is active
- No-match empty state with
SearchOfficon and "No components match …" message - Hint text ("Tap a component to backup or replace its contents") hidden while search query is active
app/src/main/java/com/banner/inject/ui/screens/HomeScreen.kt
Commit: 055d75a | Tag: v1.5.9-pre2
- Moved the cross-repo search field from a collapsible icon to an always-visible
OutlinedTextFieldabove the repo list inDownloadScreen - Search field is visible at all times (not just in search mode)
- Pressing Back clears search query before closing
app/src/main/java/com/banner/inject/ui/screens/DownloadScreen.kt
Commit: 5398adb | Tag: v1.5.9-pre
- Cross-repo search in the Download Components tab: search field in top bar searches across all cached repositories
RemoteSourceRepository.searchCache(query): case-insensitive search across all cached items, returns grouped results by source+type- Auto-caches all repos in background when search query is entered and cache is empty
SearchContentcomposable: shows spinner while caching, groups results by repo/type, "no results" stateBackHandlerclears search query on back press when search is active
app/src/main/java/com/banner/inject/ui/screens/DownloadScreen.ktapp/src/main/java/com/banner/inject/data/RemoteSourceRepository.kt
Commit: 4566160 | Tag: v1.5.8-pre-2
- Fixed build failure:
PullToRefreshContainerandrememberPullToRefreshStateare inandroidx.compose.material3.pulltorefreshsub-package, not covered bymaterial3.*wildcard — added explicit imports to all screens using pull-to-refresh
app/src/main/java/com/banner/inject/ui/screens/HomeScreen.kt- (other screens using PullToRefresh)
[pre-release] — v1.5.8-pre — Pull-to-refresh, batch downloads, file sizes, download resume (2026-03-09)
Commit: 5983c12 | Tag: v1.5.8-pre
- Pull-to-refresh on Inject tab component list (
ComponentListScreen) using Material3PullToRefreshContainer - Batch downloads on Download tab: multi-select mode with checkboxes; "Download X files" button downloads all selected in parallel
- File sizes on download items: size shown in subtitle (from GitHub API
sizefield) - Download resume: skips already-downloaded files in batch mode (checks
isDownloaded)
app/src/main/java/com/banner/inject/ui/screens/HomeScreen.ktapp/src/main/java/com/banner/inject/ui/screens/DownloadScreen.ktapp/src/main/java/com/banner/inject/data/RemoteSourceRepository.kt
Commit: f55d647 | Tag: v1.5.7-pre
- Live loading counter: component list shows "Loading X / Y components..." with a small spinner while scanning
ComponentListScreengainstotalComponentCount+loadedComponentCountparameters- Scan emits each component as it's found (streaming) so the list populates progressively
app/src/main/java/com/banner/inject/ui/screens/HomeScreen.ktapp/src/main/java/com/banner/inject/viewmodel/MainViewModel.ktapp/src/main/java/com/banner/inject/data/ComponentRepository.kt
Commit: fbfcd9f | Tag: v1.5.6-pre
- Parallel scanning: component folder scans now run concurrently with a semaphore to limit parallelism and avoid ANR
- Significantly faster load times on large component trees
app/src/main/java/com/banner/inject/data/ComponentRepository.kt
Commit: 11ca506 | Tag: v1.5.5
- Edit Repository (rename, URL, type selection with auto-detect)
- GITHUB_REPO_CONTENTS format (plain GitHub repo URL → folder structure)
- MTR (MaxesTechReview) uses GITHUB_REPO_CONTENTS; plain github.com URL stored
- Merged composite repos: StevenMXZ and Arihany each one card covering WCP + Turnip/Adreno
- ExtraEndpoint system replacing secondaryUrl/Format/Types — supports N extra URLs
- Multi-URL custom repos in AddRepoDialog: dynamic URL fields (add/remove), auto-detect + type discovery per URL
RemoteSourceRepository.kt,DownloadScreen.kt,RemoteSourceSheet.kt,AddRepoDialog.kt,EditRepoDialog.kt(new)
Commit: 11ca506 | Tag: v1.5.4-pre-5
RemoteSource.secondaryUrl/Format/Typesreplaced withextraEndpoints: List<ExtraEndpoint>supporting N extra URLsExtraEndpointdata class: url + format + types- Built-in StevenMXZ and Arihany migrated to
extraEndpoints fetchFromSource: routes to first ExtraEndpoint matching the typerefreshAllCache: iterates all ExtraEndpoints and fetches each with its formatdiscoverTypes: composite short-circuits tosupportedTypessaveCustomSources/getCustomSources: serialize/deserializeextraEndpointsin JSONAddRepoDialog: rewritten with dynamic URL fields; "Add another URL" button / "−" remove button; single URL = simple source; multiple URLs = format-detect + discoverTypes per URL, primary + extras built automatically; takesrepoparam for discoverTypes callsDownloadScreen+RemoteSourceSheet: passrepo =to AddRepoDialog
app/src/main/java/com/banner/inject/data/RemoteSourceRepository.ktapp/src/main/java/com/banner/inject/ui/screens/AddRepoDialog.ktapp/src/main/java/com/banner/inject/ui/screens/DownloadScreen.ktapp/src/main/java/com/banner/inject/ui/screens/RemoteSourceSheet.kt
Commit: 4ea7547 | Tag: v1.5.4-pre-4
RemoteSourcegainssecondaryUrl,secondaryFormat,secondaryTypesfields for composite sources- StevenMXZ merged with Adreno-Tools-Drivers (StevenMXZ) → one entry: WCP JSON for WCP types + GITHUB_RELEASES_ZIP for turnip/adreno
- Arihany WCPHub merged with Arihany WCPHub (Turnip) → one entry: GITHUB_RELEASES_WCP for WCP types + GITHUB_RELEASES_TURNIP for turnip/adreno
- Default sources reduced from 8 to 6
fetchFromSource: routes tosecondaryUrl/secondaryFormatwhencomponentType in secondaryTypesrefreshAllCache: fetches primary and secondary groups separately with their correct formatsdiscoverTypes: composite sources short-circuit tosupportedTypes(no network scan)
app/src/main/java/com/banner/inject/data/RemoteSourceRepository.kt
Commit: 79bb8f4 | Tag: v1.5.4-pre-3
- MTR default source URL changed to
https://github.com/maxjivi05/Components(plain GitHub URL) - Added
normalizeContentsUrl()private helper inRemoteSourceRepository: convertsgithub.com/{owner}/{repo}to API/contentsURL before any network call — both plain and API URLs work forGITHUB_REPO_CONTENTSsources fetchGithubRepoContents()anddiscoverTypes()GITHUB_REPO_CONTENTS branch both usenormalizeContentsUrl()
app/src/main/java/com/banner/inject/data/RemoteSourceRepository.kt
Commit: e8e7de3 | Tag: v1.5.4-pre-2
RemoteSourceRepository.fetchGithubRepoContents(): fetches{url}/{folderName}via GitHub Contents API; returns.wcp/.zipfiles asRemoteItemlist usingdownload_url;publishedAt = null(no dates from Contents API)- MTR default source already set to
GITHUB_REPO_CONTENTSformat pointing atapi.github.com/repos/maxjivi05/Components/contents discoverTypes()GITHUB_REPO_CONTENTS branch: lists non-hidden directories from repo root with original casing (for correct API paths)refreshAllCache()GITHUB_REPO_CONTENTS branch: discovers folders then fetches eachDownloadScreen+RemoteSourceSheet: addeddynamicTypes/isLoadingTypesstate +LaunchedEffect(selectedSource)that auto-callsdiscoverTypes()for Contents-format repos; shows "Detecting types..." spinner;typesToShowuses dynamic folder names for that formatAddRepoDialog.sanitizeUrl(): plaingithub.com/{owner}/{repo}→api.github.com/repos/{owner}/{repo}/contentsAddRepoDialog.autoDetectFormat(): returnsGITHUB_REPO_CONTENTSwhen URL ends with/contents(no extra network call needed)
app/src/main/java/com/banner/inject/data/RemoteSourceRepository.ktapp/src/main/java/com/banner/inject/ui/screens/DownloadScreen.ktapp/src/main/java/com/banner/inject/ui/screens/RemoteSourceSheet.ktapp/src/main/java/com/banner/inject/ui/screens/AddRepoDialog.kt
Commit: b050609 | Tag: v1.5.4-pre
- Edit Repository option added to each repo card's hamburger menu in Download Components tab
EditRepoDialog(new file): name + URL fields; auto-detects types from the live repo on open; checkboxes for each discovered type pre-checked per current config; ⟳ refresh button re-detects with updated URL; Select All / Deselect All shortcutsRemoteSourceRepository.discoverTypes(): fetches repo once, extracts unique types — WCP JSON usestypefield, GitHub Releases scans asset names against known types list, Turnip always returns["turnip","adreno"]RemoteSourceRepository.editSource(): in-place update for custom sources; for defaults, marks original removed and saves edited version as custom
app/src/main/java/com/banner/inject/data/RemoteSourceRepository.ktapp/src/main/java/com/banner/inject/ui/screens/DownloadScreen.ktapp/src/main/java/com/banner/inject/ui/screens/EditRepoDialog.kt(new)
Commit: 819ceba | Tag: v1.5.3
- Wine & Proton component categories in Download screen and injection wizard
- Upload dates on file items (from GitHub published_at; WCP JSON sources have none)
- Auto-sort newest first by default; Sort button dropdown (Newest First, Oldest First, Name A→Z, Name Z→A)
- All files modified across v1.5.1-pre → v1.5.2-pre-2 (see individual pre-release entries below)
Commit: 32d9afb | Tag: v1.5.2-pre-2
- Component file lists default to newest first (by
publishedAtdescending; items with no date fall to bottom) - Sort button (
Icons.Default.Sort) appears in the breadcrumb header when at the file list step in bothDownloadScreenandRemoteSourceSheet - Dropdown offers 4 options with active checkmark: Newest First, Oldest First, Name A→Z, Name Z→A
SortOrderenum declared at package level inDownloadScreen.kt, shared withRemoteSourceSheet- Sorting is
remember(currentItems, sortOrder)— instant, no re-fetch - Fix: added explicit
SortandCheckicon imports toRemoteSourceSheet.kt(it uses per-icon imports, not wildcard)
app/src/main/java/com/banner/inject/ui/screens/DownloadScreen.ktapp/src/main/java/com/banner/inject/ui/screens/RemoteSourceSheet.kt
Commit: 7613e24 | Tag: v1.5.1-pre
- Wine & Proton categories: added "wine" and "proton" to the
componentTypeslist inDownloadScreenandRemoteSourceSheet. All WCP/GitHub-WCP sources (StevenMXZ, Arihany WCPHub, Xnick417x, MTR) now include these types insupportedTypes. - Upload dates on file items:
RemoteItemgains a nullablepublishedAt: String?field ("YYYY-MM-DD"). Extracted frompublished_atin GitHub API responses forfetchTurnipReleases,fetchGithubReleasesWcp, andfetchGithubReleasesZip. WCP JSON sources have no date field — stays null. Shown in the subtitle of each file card: "Uploaded YYYY-MM-DD · Tap to download".
app/src/main/java/com/banner/inject/data/RemoteSourceRepository.ktapp/src/main/java/com/banner/inject/ui/screens/DownloadScreen.ktapp/src/main/java/com/banner/inject/ui/screens/RemoteSourceSheet.kt
Commit: 31f1603 | Tag: v1.5.0
- Native device back button support
- Hamburger menu on repo cards (Open in Browser + Remove Repository)
- Refresh All button with in-memory API caching
- MaxesTechReview (MTR) built-in repo + Drivers component category
- Organized download folder structure:
Downloads/BannersComponentInjector/{Repo}/{Type}/ - Already-downloaded indicator on file items
- My Downloads tab: browse by repo → type → file; delete records + Clear All
- Backups folder inside My Downloads tab
- Settings > Storage: custom Downloads Location + custom Backups Location (SAF)
- All other pre-release improvements (v1.4.1-pre through v1.4.7-pre)
- All files modified across v1.4.1-pre → v1.4.7-pre (see individual pre-release entries)
Commit: b72f3b6 | Tag: v1.4.7-pre
- Settings > Storage (new section): two configurable save locations.
- Downloads Location: default (MediaStore
Downloads/BannersComponentInjector/…) or user-selected SAF folder via system file picker. - Backups Location: same choice for component backups.
- Downloads Location: default (MediaStore
- Each row shows the current path, "Select Folder" / "Change" button, and "Use Default" reset button when custom is active.
- SAF folder picker uses
ActivityResultContracts.OpenDocumentTree(); takes persistable URI permission so access survives reboots. saveToDownloads()readscustom_downloads_uripref and writes to SAFDocumentFiletree when set (repo/type subfolders), falling back to MediaStore default.BackupManager: all operations (hasBackup,deleteBackup,backupFromDocumentFile,listAllBackupFiles,listAllBackups) branch on custom vs. default; custom path usesDocumentFiletree traversal instead of MediaStore queries.
app/src/main/java/com/banner/inject/ui/screens/SettingsSheet.ktapp/src/main/java/com/banner/inject/ui/screens/DownloadScreen.ktapp/src/main/java/com/banner/inject/data/BackupManager.kt
Commit: 37dfc74 | Tag: v1.4.6-pre
- Backups moved into My Downloads tab: top-level "Backups" folder card appears at root of My Downloads list; tapping navigates into a full backup browser showing file count + size per backup, with per-backup delete support.
- Removed standalone Backup
IconButtonfromDownloadManagerScreentop bar. BackHandlerupdated to handleshowingBackupsstate (Backups → root pop).- Separate confirmation dialogs for deleting a backup vs a download record.
MainTab.MANAGERSwhen branch inMainActivitynow passesonListBackups/onDeleteBackupdirectly toDownloadManagerScreen— noBackupManagerSheetmodal on that tab.- INJECT tab and Download Components tab retain their existing
BackupManagerSheetmodals.
app/src/main/java/com/banner/inject/ui/screens/DownloadManagerScreen.ktapp/src/main/java/com/banner/inject/MainActivity.kt
Commit: fda7879 | Tag: v1.4.5-pre-2
- Hamburger menu on repo cards: replaced inline browser + delete
IconButtons with a singleMoreVertthat opens aDropdownMenuwith "Open in Browser" and "Remove Repository". - Downloaded indicator: file list shows
CheckCircleicon + "Already downloaded" subtitle for previously saved items. Updates immediately after download; persists via SharedPreferences. - My Downloads tab (
DownloadManagerScreen): new third tab — repo → type → file drill-down. Each file card shows name, size, date, and a delete button. "Clear All" in top bar. Empty state when no downloads exist. - Download record tracking added to
RemoteSourceRepository:DownloadedFiledata class,recordDownload(),removeDownloadRecord(),getAllDownloads(),isDownloaded()(O(1) companionConcurrentHashSet).sanitizeFolderName()moved to companion.saveToDownloads()now returnsPair<String?, Long>(URI + file size).
app/src/main/java/com/banner/inject/data/RemoteSourceRepository.ktapp/src/main/java/com/banner/inject/ui/screens/DownloadScreen.ktapp/src/main/java/com/banner/inject/ui/screens/DownloadManagerScreen.kt(new)app/src/main/java/com/banner/inject/model/Models.ktapp/src/main/java/com/banner/inject/MainActivity.kt
Commit: 18a3a46 | Tag: v1.4.4-pre
- Downloads now land in
Downloads/BannersComponentInjector/{RepoName}/{ComponentType}/{file}instead of a flatDownloads/subfolder. sanitizeFolderName()helper strips filesystem-unsafe characters (/ \ : * ? " < > |) from repo and type names before using them as folder names.- Both MediaStore path and legacy fallback use the same structure.
app/src/main/java/com/banner/inject/ui/screens/DownloadScreen.kt
Commit: f54e027 | Tag: v1.4.3-pre
- Added MaxesTechReview (MTR) as a built-in default source (
WCP_JSON) usinghttps://raw.githubusercontent.com/maxjivi05/Components/main/contents.json. Supported types: dxvk, vkd3d, box64, fex, fexcore, drivers. - Added "drivers" to the global
componentTypeslist in bothDownloadScreenandRemoteSourceSheet, since MTR labels his GPU/turnip components as "drivers" rather than "turnip"/"adreno".
app/src/main/java/com/banner/inject/data/RemoteSourceRepository.ktapp/src/main/java/com/banner/inject/ui/screens/DownloadScreen.ktapp/src/main/java/com/banner/inject/ui/screens/RemoteSourceSheet.kt
Commit: 7904d4b | Tag: v1.4.2-pre
- Open in Browser: Each source card in the Download tab now has a browser icon button. Tapping it opens the repo's GitHub page (API/raw URLs are auto-converted to
github.comlinks). - Refresh All Button: A refresh icon in the source list header fetches all sources × all supported types in parallel and populates the cache. Shows a spinner while running; snackbars on completion. TURNIP/ZIP sources are fetched once and stored under all their supported types to avoid redundant API calls.
- API Result Caching: Results stored in a
ConcurrentHashMap(companion object, lives for the app session). After the first browse or a manual refresh, re-entering any source/type returns instantly from cache with no network hit.
app/src/main/java/com/banner/inject/data/RemoteSourceRepository.ktapp/src/main/java/com/banner/inject/ui/screens/DownloadScreen.kt
Commit: 504b7a2 | Tag: v1.4.1-pre
- Device Back Button Interception: Added Jetpack Compose
BackHandlerto both the full-screen "Download Components" tab (DownloadScreen) and the "Select Online Source" injection sheet (RemoteSourceSheet). - Intuitive Navigation: Pressing the physical/swipe back button steps back through navigation state (file list → type selection → source selection) rather than immediately closing the app or sheet. Disabled during active downloads.
app/src/main/java/com/banner/inject/ui/screens/DownloadScreen.ktapp/src/main/java/com/banner/inject/ui/screens/RemoteSourceSheet.kt
Tag: v1.4.0
- Official stable release promoting all v1.3.1-pre through v1.3.6-pre features.
- Global Tab Navigation: Transformed the primary UX by introducing a
TabRowat the top of the app toolbar present at all times. Users can easily switch between "Inject Components" (the existing flow) and the new "Download Components" tab. - Dedicated Download Screen: Replicated the remote sources drill-down wizard as a permanent, full-screen UI. Users can browse online repositories, select component types, and directly download
.wcpor.zipfiles to their device's Downloads folder for later use. - Custom Repositories: Users can now add their own custom online repositories directly within the app.
- Smart Auto-Detection: Removed the confusing "Format" dropdown when adding a repo. The app now automatically fetches the URL in the background, inspects its JSON, and intelligently detects if it's a
WCP_JSON,GITHUB_RELEASES_WCP,GITHUB_RELEASES_TURNIP, or standardGITHUB_RELEASES_ZIP. Automatically converts standard GitHub release links into proper API endpoints. - Universal Deletion: Users can remove any repository from their list, including the built-in defaults (e.g., Arihany, StevenMXZ). Includes a safety confirmation dialog to prevent accidental deletions.
- Restore Defaults: Added a "Restore Default Repositories" button to easily recover the original built-in sources.
- Default Start Tab Setting: Added a "General" section to settings to choose whether the app opens to the "Inject Components" or "Download Components" tab by default upon launch.
- Settings Reorganization: Appearance options (Theme & Accent Color) have been moved into a dedicated sub-menu within Settings to reduce clutter.
Tag: v1.3.0
- Official stable release promoting all v1.2.1-pre through v1.2.9-pre features.
- GameHub Lite
emuready.gamehub.litepackage support. - Fixed two online sources wizard back-navigation crashes (job cancellation + LazyColumn NPE race).
- Added StevenMXZ Adreno-Tools-Drivers, whitebelyash freedreno_turnip-CI sources.
- Replaced broken Arihany JSON with two entries from
Arihany/WinlatorWCPHubGitHub releases. - Stable signing keystore — APKs update over previous v1.2.6+ installs.
- In-app update checker with Download & Install (streams APK, progress bar, system installer).
- Settings available on all screens as a full-screen scrollable page.
- Full theme customization: 8 preset swatches + HSV color wheel + hex input.
- "Don't ask again" on backup warning + Settings toggle to re-enable.
Tag: v1.2.9-pre
- Full-screen Settings: replaced
ModalBottomSheetwith a full-screenScaffold+LazyColumn. All sections (About, Appearance, Prompts, Updates, utilities) are scrollable and never cut off. Back arrow + device back button dismiss.BackHandlerintercepts device back. - In-app update download: when an update is available, user can now tap "Download & Install" to stream the APK directly into the app's cache dir, with a live
LinearProgressIndicator+ percentage. On completion,FileProvider+ACTION_VIEWhands it to the system installer — no browser needed. - "View on GitHub" remains as an outlined button alongside Download & Install.
- Download is cancellable mid-stream; pressing Cancel returns to the "Update available" state (restores
UpdateState.Available). UpdateState.Downloading(progress, release)added;UpdateState.Availablenow shows inline card with buttons instead of an AlertDialog.UpdateRepositorygainsdownloadApk()(streams withensureActive()for cancellation) andinstallApk()(FileProvider intent).AndroidManifest.xml: addedREQUEST_INSTALL_PACKAGESpermission +FileProviderprovider declaration.res/xml/file_paths.xml(new): exposes<cache-path>for FileProvider.
ui/screens/SettingsSheet.ktdata/UpdateRepository.ktAndroidManifest.xmlres/xml/file_paths.xml(new)
Tag: v1.2.8-pre-3
- "Don't ask again" checkbox added to the No Backup Found dialog in
ComponentDetailSheet. When checked + Replace Anyway, savesskip_backup_warning=truetobci_settingsSharedPreferences; future replaces bypass the dialog. - Settings → Prompts section (new): toggle Warn before replacing without a backup to re-enable or suppress the dialog. Inverts the
skip_backup_warningpref. - HSV Color Wheel replaces the plain hex input for custom accent color in Settings → Appearance:
- 240 dp circular disc drawn with
SweepGradient(hue) +RadialGradient(saturation) + black overlay (brightness). - Tap or drag the disc to pick hue + saturation; white/black thumb shows selection.
- Brightness
Sliderbelow the disc controls the value channel; saves on drag end. - Hex field remains as secondary input with Apply button.
- Live theme preview while dragging;
LaunchedEffect(color)syncs external preset changes back to wheel state.
- 240 dp circular disc drawn with
- Fix notes: Two compile errors caught by CI —
awaitFirstDown/awaitPointerEventhave wrong import paths (solved by switching todetectDragGestures/detectTapGestures); Kotlin resolvedcolor = android.graphics.Color.argb(...)insideapply {}as the outer composableval color: Colorparameter instead ofPaint.color— fixed withdarkPaint.color = ...direct assignment.
ui/screens/ComponentDetailSheet.ktui/screens/SettingsSheet.kt
Tag: v1.2.7-pre
- Settings cog added to ComponentListScreen top bar (was only on AppListScreen before).
SettingsSheetextracted to its own file (SettingsSheet.kt) shared by both screens.- Appearance section added to Settings:
- 8 preset accent color swatches (Orange default, Blue, Purple, Green, Red, Teal, Pink, Amber).
- Custom swatch opens a hex input field (
#RRGGBB) with live preview and validation. - Color persisted in SharedPreferences, restored on launch.
- Full theme dynamically derived from accent color (container, secondary, onPrimary all auto-computed).
onPrimaryswitches black/white based on luminance for readable text on any accent.
- Fixed
parseHexto useFloatcomponents instead ofInt(compile bug caught pre-push).
ui/theme/ThemePrefs.kt(new)ui/theme/Theme.ktui/screens/SettingsSheet.kt(new)ui/screens/AppListScreen.ktui/screens/HomeScreen.ktMainActivity.kt
Tag: v1.2.6-pre
- Stable keystore (
app/keystore.jks) committed to repo. All builds now signed with the same key — APKs are installable as updates over previous v1.2.6-pre+ builds without uninstalling first. - CI now passes
-PversionNamefrom the git tag to Gradle so each APK embeds the correct version string. - In-app update checker added to Settings sheet:
- "Check for Updates" button — hits GitHub releases API, compares latest vs installed.
- "Include pre-releases" toggle (off by default, persisted in SharedPreferences).
- Inline "up to date" message or dialog showing installed vs available version with "Open GitHub Release" button.
app/keystore.jks(new)app/build.gradle.kts.github/workflows/release.ymldata/UpdateRepository.kt(new)ui/screens/AppListScreen.kt
Tag: v1.2.5-pre
- Replaced the failing
arihany/wcp-jsonJSON endpoint with two entries fromArihany/WinlatorWCPHubGitHub releases. - Arihany WCPHub (
GITHUB_RELEASES_WCP) → dxvk, vkd3d, box64, fex, fexcore. Covers DXVK (6 variants), VKD3D-Proton, FEXCore + nightly, BOX64-Bionic + nightly, WOWBOX64 + nightly, WINE. - Arihany WCPHub (Turnip) (
GITHUB_RELEASES_TURNIP) → turnip, adreno.
data/RemoteSourceRepository.kt
[pre-release] — v1.2.4-pre — Add StevenMXZ Adreno-Tools-Drivers + whitebelyash freedreno_turnip-CI sources (2026-03-08)
Tag: v1.2.4-pre
- New
GITHUB_RELEASES_ZIPsource format: fetches all.zipassets from GitHub releases (no name filter). - Added Adreno Tools Drivers (StevenMXZ) —
StevenMXZ/Adreno-Tools-DriversviaGITHUB_RELEASES_ZIP. - Added freedreno Turnip CI (whitebelyash) —
whitebelyash/freedreno_turnip-CIviaGITHUB_RELEASES_TURNIP. - Both sources scoped to
turnip/adrenocomponent types.
data/RemoteSourceRepository.kt
[pre-release] — v1.2.3-pre — Fix NPE crash (LazyColumn snapshot race) in online sources wizard (2026-03-08)
Tag: v1.2.3-pre
- Fixed NPE crash at RemoteSourceSheet.kt:219 (
items!!in LazyColumn) caused by a Compose snapshot race condition. - The
items != nullwhen-branch condition evaluated as true, but LazyColumn's lazy content lambda ran after a concurrent state write setitems = null. - Fix: replaced
items != null ->withelse ->, captureditemsinto a localval currentItems, and usereturn@Columnif it's null to exit cleanly.
ui/screens/RemoteSourceSheet.kt
Tag: v1.2.2-pre
- Fixed crash/stuck-spinner when pressing Back during or after component-type selection in the online sources wizard.
- Back button now cancels the active fetch job and resets
isLoading = falseimmediately. selectedSourceis captured as a local val before launching the coroutine to avoid stale MutableState reads.itemsis cleared to null before each new fetch begins.
ui/screens/RemoteSourceSheet.kt
Tag: v1.2.1-pre
- App Detection: Updated GameHub Lite detection to include the
emuready.gamehub.litepackage name alongsidegamehub.lite, and updated its display name to "GameHub (Lite)".
Tag: v1.2.0
- Official stable release promoting all v1.1.1-pre through v1.1.9-pre features.
- Performance: Massive speedup to component list loading using highly optimized raw
ContentResolverqueries (SafFastScanner). - Remote Sources: Built a complete multi-step drilldown wizard allowing users to fetch components directly from online repositories (StevenMXZ, Arihany, Xnick417x, AdrenoToolsDrivers) and generic GitHub Release APIs.
- UX: Added clear replacement notes in the UI to remember what a component was last replaced with.
Tag: v1.1.9-pre
- UX Overhaul: Replaced the flat remote components list with a multi-step drilldown wizard.
- Step 1: Users first select which online repository they want to browse (e.g., StevenMXZ, AdrenoToolsDrivers).
- Step 2: Users select the component type they are looking for (e.g., DXVK, Box64, Turnip). This allows users to browse and install any component type, regardless of which component folder they are currently editing.
- Step 3: Users are presented with the strictly filtered list of WCPs/ZIPs for that exact type from that specific repository.
- Navigation: Added a dynamic header with a back button and breadcrumbs so users can easily navigate back up the wizard steps.
Tag: v1.1.8-pre
- Smart Filtering: Remote sources now strictly filter their returned lists based on the active component folder. If you open
dxvk, you will only seedxvkpackages. If you openbox64, you will only seebox64packages, removing clutter and preventing accidental incorrect installations.
Tag: v1.1.7-pre
- Remote Sources: Added support for a new format
GITHUB_RELEASES_WCP. This allows users or developers to add standard GitHub repository release APIs to thedefaultSourceslist. The app will automatically scan the release assets for.wcpfiles and filter them based on the active component type.
Tag: v1.1.6-pre
- Remote Sources: Added
Xnick417x(Winlator-Bionic-Nightly-wcp) to the list of default remote repositories for broader component coverage.
Tag: v1.1.5-pre
- Multi-Source Integration: The app now supports fetching components from multiple remote sources concurrently.
- Component Type Scoping: Sources can be configured to only trigger for specific component folders (e.g., Turnip sources only trigger for
turniporadrenofolders). - Source Attribution: The remote list UI now clearly indicates which repository a file is originating from (e.g., "From: StevenMXZ" or "From: Arihany").
Tag: v1.1.4-pre
- Remote Sources: Updated the default WCP JSON repository from
arihany/wcp-jsontoStevenMXZ/Winlator-Contentsto access a different catalog of components.
Tag: v1.1.3-pre
- Performance Optimization: Dramatically sped up the initial load time of the component list.
- Custom Scanner: Bypassed the slow Android
DocumentFilerecursive wrappers by introducingSafFastScanner, which performs highly optimized, rawContentResolverqueries to calculate file counts and sizes natively across directory trees.
Tag: v1.1.2-pre
- Remote Replacement: Users can now replace components by downloading them directly from online sources instead of requiring a local WCP file.
- Remote Sources: Added integration with
arihany/wcp-jsonfor standard components and GitHub Releases for Turnip GPU drivers. - UI Update:
ComponentDetailSheetnow features two options for replacement: "Select Local File" and "Select Online Source". - Downloader UI: A new bottom sheet (
RemoteSourceSheet) displays available remote files with their versions and shows real-time progress during downloads.
Tag: v1.1.1-pre
- Component Info: The component list now displays a note indicating what a component was replaced with after a successful WCP import.
- State Persistence: Replacement notes are saved to
SharedPreferencesso they persist across app restarts and are cleared when a component is restored to its backup.
Tag: v1.1.0
- Official stable release promoting v1.0.1-pre through v1.0.3-pre features.
- External Backups: Backups now land in
Downloads/BannersComponentInjector/<componentName>/instead of app-private internal storage, usingMediaStore.DownloadsAPI. - Backup Manager: Centralized Backup Manager accessible from the AppList top bar, Settings sheet, and ComponentList top bar.
- Settings Sheet: Added a new Settings cog to the AppListScreen top bar to show the app version and provide an "Open Downloads Folder" shortcut.