8 Commits

Author SHA1 Message Date
Imran Remtulla
89e2fc247f Add trailingKey support to GeneratedFormTextField, fix add/search button state with Row layout, include _urlValid in trailingKey hash (#3107) 2026-07-19 15:23:51 +01:00
Imran Remtulla
05dd135665 Unify form input styling: global borderless filled theme, rename Settings* components to generic names, merge settings_widgets.dart into ui_widgets.dart, convert SegmentedButtons to DropdownMenus, add per-app checkbox bulk update dialog, compact SliverAppBars, inline trailing icon buttons, newline-terminated error messages for breathing room, ConnectedCard defaults to zero padding (#3107, #3100) 2026-07-17 21:33:26 +01:00
Imran Remtulla
0f251fd64b Fix bugs, inconsistencies, dead code, and unsafe patterns in form components
- textInputType: dynamic -> TextInputType? (type safety, was crash-prone)
- GeneratedFormDropdown: add required and helpUrl fields, render help suffix
  icon and required indicator matching text field behavior
- Dropdown null fallback: preserve current selection instead of silently
  picking first option
- add_app.dart: remove redundant cloneFormItems (getter already returns clones)
- Remove unused _formKey and Form wrapper (validation done manually)
- validateTextField: add type-check guard before unsafe cast
- add_app.dart: remove dead resetUserInputAfter parameter and code
- _buildSubForm: fix variable shadowing (values -> subValues)
2026-07-08 02:52:39 +01:00
Imran Remtulla
10b3af22cc fix: squash 18 bugs, dead code, and code quality issues across the codebase
- Fix rethrowOrWrapError to preserve original stack traces and populate
  null stacks on unexpected ObtainiumError instances
- Fix MultiAppMultiError.message returning empty string (use toString())
- Fix getDefaultValuesFromFormItems returning '' for bool-typed switches
  and subforms (use ?? false and ?? [] respectively)
- Fix GeneratedFormSubForm.ensureType returning val unchanged
- Fix main_fdroid.dart async-without-await (unhandled Future errors)
- Fix InstallResult conflating null/'already installed' (code 3) with
  'cancelled' — add InstallOutcome.alreadyInstalled
- Fix external installer ignoring split APKs (only used first path)
- Replace direct LogsProvider() instantiation in settings.dart with
  context.read<LogsProvider>()
- Replace 7 ad-hoc SourceProvider() instances across pages with
  context.read<SourceProvider>() or constructor injection
- Remove ExportSchema.credentials dead field (never populated)
- Remove redundant double .abs() in DownloadNotification ID calculation
- Remove redundant overrideName double-check in AppInMemory.name getter
- Remove unnecessary '!= true' anti-pattern in auto-export check
- Replace 4 throwaway UpdateNotification([]).id calls with named constant
  updateNotificationId
- Add notification ID named constants (updateNotificationId, etc.)
- Deduplicate _showImportError / showImportError in import_export.dart
- Fix _readFileBytes dangling ByteData (use ByteData.sublistView
  instead of ByteData.view)
- Fix apps.dart missing setState after pruning stale selectedAppIds
2026-07-03 09:19:27 +01:00
Imran Remtulla
e15abd627c fix: remove dead code in _resolveAppId, rename generateRandomNumber, use sourceIdentifier over runtimeType, and fix slider tile positional radii in settings 2026-07-02 16:15:21 +01:00
Imran Remtulla
4b0c5405df fix: resolve 30+ bugs, safety issues, and code quality problems across the codebase
HIGH severity fixes:
- Fix indexOf -> startsWith for URL scheme detection to prevent corrupting
  non-http URLs (source_provider.dart)
- Fix OOM risk: use XFile(path) instead of readAsBytes() for large APKs
  (apps_provider_install.dart)
- Fix GeneratedFormSwitch.ensureType returning String instead of bool,
  causing runtime _CastError (generated_form_model.dart)
- Fix initForm() called during build() triggering parent setState by moving
  init to didUpdateWidget + postFrameCallback (generated_form_renderer.dart)
- Fix CI sed no-op: update regex to match actual signingConfig pattern in
  build.gradle.kts (release.yml)
- Fix build.sh auto git push on no-args: require explicit arg to sync+build
- Pin all git dependencies to commit SHAs instead of mutable branches

MEDIUM severity fixes:
- Sequence background service start/stop calls to prevent races (main.dart)
- Move loadSystemFont() from build() to init to prevent visible font flash
- Prevent concurrent bgUpdateCheck calls in onRepeatEvent with guard flag
- Extend download retry to SocketException and TimeoutException
- Cap install permission loop at 10 attempts to prevent infinite hang
- Remove dead unused headers variable causing double bcrypt hash (coolapk.dart)
- Remove HTTP 304 from redirect status check (huaweiappgallery.dart)
- Guard result.files.single against empty file picker results (import_export.dart)
- Add error logging to linkFn catch block (add_app.dart)
- Disable continue button when no download URL available (app_detail_widgets.dart)
- Fix DEVELOPER_GUIDE.md: list all git-pinned deps, correct android_package_manager

LOW severity fixes:
- Use 'final' instead of 'late' for FDroid field (izzyondroid.dart)
- Use stable 'name' instead of runtime-type sourceIdentifier (neutroncode.dart)
- Fix typo: finalUrlKey -> urlDataKey (uptodown.dart)
- Fix aptoide constructor field order for consistency
- Remove dead app?.app == null condition (app.dart)
- Reuse SourceProvider instance instead of throwaway (apps.dart)
- Support descending sort for 'as added' column (app_list_tile.dart)
- Remove SDK >= 31 guard causing layout shift for material-you option (settings.dart)
- Secure standardize.mjs: atomic write-then-rename, Object.hasOwn, error handling
- Add flutter_launcher_icons to dev_dependencies
2026-07-02 15:53:06 +01:00
Imran Remtulla
cf3caa2872 fix: squash bugs, remove dead code, deduplicate, improve error handling and naming
HIGH SEVERITY:
- Check HTTP status code before streaming download body to avoid wasted bandwidth
- Only clean up .part files in old-download cleanup, not legitimate APKs
- Fix getDefaultValuesFromFormItems crash on empty form item lists (reduce -> fold)
- Guard hosts list index access with firstOrNull / .first to prevent RangeError
- Clean up extracted APK directory on disk when package info is null
- Add 5-minute timeout to foreground busy-wait loop
- Fix isEnglish() false positive by falling back to false instead of tr('and')=='and'
- Use dart-define APP_VERSION from build.sh instead of hardcoded kPackageVersion

MEDIUM SEVERITY:
- Fix GitHub /latest endpoint URL reconstruction (split/join corrupting query params)
- Add try-catch for corrupt JSON in categories getter
- Check arch-filtered APK list emptiness and throw NoAPKError if empty
- Cache combinedAppSpecificSettingFormItems per AppSource instance
- Replace fragile didUpdateWidget condition with setEquals
- Replace putIfAbsent with direct assignment in _resetEntrySelections
- Remove double notify() call in import path (saveApps already calls notify)
- Added unawaited wrapper for async log calls in rethrowOrWrapError

LOW SEVERITY:
- Remove unused Logger? field from AppsProvider
- Remove redundant _obtainium prefix from private constants
- Remove redundant recursive:true on File.deleteSync
- Remove redundant .toList() copy on Uint8List write
- Make sourceUrl final (use const obtainiumUrl)
- Remove duplicated _updateSourceNote inline in add_app.dart build()
- Fix logs clear message showing literal 'null'
- Remove duplicate // ignore: implementation_imports comment
2026-07-02 13:25:29 +01:00
Imran
f85d9206c7 Rearchitect (#3002)
* architecture: consolidate and simplify

- Collapse 14 directories into 4 (app_sources, components, pages, providers)
- Replace DI container with inline construction in main.dart
- Fold page controllers back into their pages (one file per screen)
- Merge small files into their natural homes (removing 40 files)
- Standardize error handling across all 28 app sources (rethrowOrWrapError)
- Make App immutable with copyWith() replacing deepCopy()
- Replace globalNavigatorKey with go_router
- Add error boundaries, source health monitor, typed settings
- Eliminate all silent catch blocks
- Add tests and CI pipeline
- Extend lint rules

97 files → 56 files. 0 errors, 4/4 tests passing.

* fix: remove unused go_router, restore internal navigation

- Drop go_router (ShellRoute broke tab switching and disabled the
  tablet/TV two-pane layout); revert to MaterialApp + navigatorKey
- Move appNavigatorKey into main.dart; delete router.dart
- Remove HomePage.child branch so the internal switcher drives the UI
- Fix dead 'Restart' button in the error fallback screen
- Remove TypedSettings []= mutation backdoor
- Persist clamped preferredApkIndex to the in-memory app map
- Use settings.getBool('trackOnly') instead of raw map access

* fix: remove dead rethrowOrWrapError, add missing import, update stale comments and docs

* fix: satisfy lint rules, wrap fire-and-forget futures, drop unused CI

- Fix use_build_context_synchronously via mounted/context.mounted guards
- Wrap deliberate fire-and-forget futures in unawaited()
- Document static app-lifetime event bus for close_sinks
- Apply dart format and dart fix across the codebase
- Drop avoid_catches_without_on_clauses (noisy in source scrapers)
- Remove test.yml CI workflow
- Rename test/services to test/providers

* fix: show real HTTP error messages, remove source health monitor and dead event-bus code

- Bypass deferred localization for HTTP_ERROR so the real reason phrase/status is shown instead of a generic 'unexpected error'
- Remove SourceHealthMonitor entirely (per-instance state made it ineffective for background checks)
- Simplify save-notification bus to StreamController<void>; drop unused AppRepositoryEvent/AppRepositoryEventType and events getter
- Scrub stale docs (SourceHealthMonitor, event type, deleted test.yml workflow)

* fix: preserve installedVersion on import, correct stale theme doc reference

* fix: type logger as Logger?, simplify ErrorWidget builder, document _sentinel, resolve TextDirection conflict

- Change dynamic logger to Logger? in AppsProvider for type safety (the
  field was unused but the contract should be explicit).
- Replace MaterialApp wrapper in ErrorWidget.builder with a minimal
  Directionality + Scaffold; MaterialApp is wasteful for a one-shot
  error screen.
- Add a doc comment explaining the _sentinel pattern used by
  App.copyWith to distinguish unset from explicitly-null nullable fields.
- Hide TextDirection from easy_localization (which re-exports intl's
  conflicting TextDirection enum that lacks ltr/rtl) so the Flutter
  dart:ui TextDirection.ltr resolves correctly.

* fix: register SourceForge, restore Palestine banner, drop dead code and tests

- Register the implemented SourceForge source in _buildSources() so the
  README's supported-sources list is accurate.
- Restore the Support Palestine banner in README.md (unintentionally removed).
- Remove unused ConfigProvider, CredentialHealth, getCredentialHealth, and
  the never-injected _configProvider path from settings_provider.
- Remove unit tests and their test-only dev dependencies.
2026-07-02 01:58:45 +01:00