29 Commits

Author SHA1 Message Date
Imran Remtulla
e68087b558 Reduce padding/spacing for ToggleTile and GeneratedForm in modal dialogs
- Add optional  parameter to ToggleTile (default false)
- Add optional  parameter to GeneratedForm (default false)
- GeneratedFormModal now passes  to its inner GeneratedForm
- Set  on direct AlertDialog + GeneratedForm in import_export.dart
- Reduce non-tile mode row spacing from 24 to 8
2026-07-19 23:26:01 +01:00
Imran Remtulla
9e2719a8c0 Restrict highlight setting to version/changelog label only; use custom _VersionLabel widget instead of HighlightableButton; revert HighlightableButton to original behaviour; fix 'Download release assets' button with plain TextButton (#2039) 2026-07-19 17:23:06 +01:00
Imran Remtulla
b74e1bf966 Unify ToggleTile: strip inner CardTile, replace _FormSwitchRow, zero tileMode padding, simplify _fieldTile to ConnectedCard (#3107) 2026-07-17 21:43:53 +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
78cc9042be Replace bulky SliverAppBar.large headers with compact SliverAppBar; add 3-way action banner setting (All/Updates/None); skip confirmation dialog for update-only banner clicks; replace all-or-nothing obtain dialog toggles with per-app checkbox list (#3107, #3100) 2026-07-17 12:16:02 +01:00
Imran Remtulla
4de395454f - Removed tabbed UI (#3059, #3069)
- Improved update check UI performance (#3043)
- Improved app list loading UI (#2666)
- Other minor UI tweaks
- Improve install result detection for external installers in foreground
2026-07-15 00:10:39 +01:00
Imran Remtulla
6ae36c41ff Add disable-swipe setting and always-use-phone-layout option (#3039)(#3045). Pin app-detail actions bar to bottom of scroll (#3044). Fix settings scroll on wide/trackpad devices (#3046). Fix TV navigation regressions across all dialogs, text fields, search bar, radio picker, and app list checkboxes (#3053). Deduplicate TV text-field focus pattern into public TvTextFieldFocus widget. 2026-07-12 04:21:36 +01:00
Imran Remtulla
be71f33123 Extract shared code between settings and add-app form pages
A. Tile wrapper: Replace inline Material in tileMode form loop with
   SettingsTile — eliminates duplicate shape/clip/color wiring.

B. Haptic helper: Extract hapticSwitchOnChanged() shared between
   _FormSwitchRow and SettingsToggleRow.

C. Tile joining: Use shapeSettingsTiles() in tileMode form loop instead
   of inline isFirst/isLast/positionalTileShape logic.

D. ConnectedCard -> SettingsTile delegation: ConnectedCard now delegates
   to SettingsTile internally, unifying the tile rendering path (switches
   from standard rounded corners to RoundedSuperellipseBorder).

Dependency clean-up:
- Move showHelpDialog from ui_widgets to settings_widgets to break
  circular import (ui_widgets now imports settings_widgets for D).
- Remove unused theme.dart and ui_widgets imports from form renderer.
2026-07-08 02:22:51 +01:00
Imran Remtulla
63b0151f9c Fix settings toggle horizontal padding and ConnectedCard vertical padding
- SettingsToggleRow: contentPadding horizontal 8 -> 12, matching default
  SettingsTile padding so toggle labels align with other settings text
- ConnectedCard: default padding EdgeInsets.all(16) ->
  EdgeInsets.symmetric(horizontal: 16, vertical: 20) for more breathing room
  around text fields and buttons inside cards
2026-07-08 02:00:22 +01:00
Imran Remtulla
4ca365fa36 fix: consistent form input styling and translation at render time
- SettingsToggleRow: remove full-row tap ink, unify both paths to
  non-tappable ListTile + Switch in trailing. Matches _FormSwitchRow
  in generated forms — only the Switch itself is interactive.
- ActionListTile: add optional borderRadius param for ListTile.shape
  to match container card corners for proper ink clipping.
- LinkText: add InkWell borderRadius (circular 4) to contain splash.
- Replace raw Material in add_app source note card with ConnectedCard.
- Replace raw Card in ExportSection with ConnectedCard.
- Add ListTile.shape (connectedTileBigRadius) to color picker and
  external installer tiles for matching ink clipping.
- Standardize SettingsTile paddings: remove horizontal 8px overrides
  on install method, external installer, group-by, and manual BG check
  tiles — use default horizontal 12px. Theme/sort order keep 16px.
- GeneratedForm labels now always call tr() at render time (7 locations)
  preventing stale/raw translation keys when the item cache is built
  before locale initialization or persists across locale changes.
- Remove unused SwitchListTile import (now unused in SettingsToggleRow).
2026-07-07 23:10:20 +01:00
Imran Remtulla
7d6ad09910 feat: expressive Add FAB, broader haptics, and progress-spinner consistency
- Use an extended (icon + label) FAB for the primary Add action in the
  bottom layout; keep a compact FAB in the navigation rail so it fits.
- Add tactile feedback (respecting the existing setting) to interactions
  that lacked it: download cancel buttons, Add/more/view FABs, list-tile
  update and swipe install/remove, settings segmented buttons, and all
  settings toggles (centralized in SettingsToggleRow).
- Drop manual strokeWidth overrides so inline spinners inherit the themed
  Material 3 look.
2026-07-02 21:41:34 +01:00
Imran Remtulla
c2aac8885a feat: per-download cancel button and download size display
Add a cancel button for in-progress downloads (in the app list tile, the
detail page, and the download notification) and surface download sizes:
the expected size before starting (best-effort probe) and live
received/total progress in the UI and notification.

- Route notification Cancel taps via the FLN background isolate to the main
  isolate (IsolateNameServer/SendPort); gated off for background-isolate
  downloads whose cancel token isn't reachable.
- Share per-app download state (progress + bytes) across AppInMemory copies
  so UI listeners keep updating after saveApps replaces the map entry.
- Treat cancellations silently and keep the .part file for later resume.
2026-07-02 21:03:58 +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
Imran Remtulla
6d8dfe33a8 chore: standardize code quality, logging, docs, and dependencies
- Replace print/debugPrint with LogsProvider across 11 files
- Convert all Future.ignore() to unawaited() across 7 files
- Fix import ordering (dart: first) in apps_provider, source_provider, coolapk
- Remove unnecessary late keywords (apps, githubstars)
- Add const where applicable (EdgeInsets, TextStyle)
- Standardize mounted → context.mounted across StatefulWidget pages
- Reduce pickedSource! null assertions in add_app (14→2)
- Break up 320-line _fetchReleaseDetails into 5 methods in github.dart
- Extract share callbacks from bottom sheet in apps.dart
- Replace Provider.of with context.read in ui_widgets
- Remove unused dart:ui import, fix clampDouble usage
- Add TypeError catch in App.fromJson() for corrupt JSON
- Preserve original error details in 8 catch blocks
- Remove redundant lint ignores (unnecessary_non_null_assertion, invalid_return_type)
- Update DEVELOPER_GUIDE for theme.dart, app_info_dialog, logging, naming
- Upgrade cross_file transitive dependency
2026-07-01 12:33:26 +01:00
Imran Remtulla
3c0bca53a0 refactor: fix bugs, deduplicate code, remove dead code, improve naming, clean comments
Bugs fixed:
- Null assertion crash in _downloadAppForInstall unexpected download types
- Null assertion crash in bgUpdateCheck on missing Map keys
- Silently swallowed network errors during foreground update checks
- SettingsProvider state desync between AppsProvider and widget tree
- Jenkins regex matching any host instead of only Jenkins servers
- GitHubStars bypassing authentication tokens and proxy settings
- Aptoide/Uptodown subdomain regex requiring 2+ subdomain segments
- undoGHProxyMod constructing 'https://null/' prefix when unconfigured
- Negative hashCode used as Android notification IDs
- farsroid.dart force-unwrap on nullable Response.request
- vivoappstore.dart replaceAll/replaceFirst and unencoded URL params
- apkmirror.dart getAppNames missing bounds checks
- apkcombo.dart empty catch on DateFormat.parse
- rustore.dart useless inner catch/rethrow

Code deduplication & simplification:
- Extracted AppSource.buildMergedSettings() helper (3 sites)
- Extracted AppInMemory.needsRefreshBeforeDownload getter (2 sites)
- Extracted AppSource.fallbackToOlderReleasesFormItem static getter (5 sources)
- Extracted AppSource.rethrowOrWrapError() helper (3 sources)
- Added AppSource.changeLogPageIsStandardUrl flag (3 sources → 0 overrides)
- Removed HttpClientMixin, moved getRequestHeaders onto AppSource
- 17+ app sources using standardizeUrlWithRegex() consistently
- neutroncode.dart: 50-line switch → const map lookup
- import_export filter simplified to single-expression lambda

Dead code removed:
- 151-line buildRepoRenameWarning() method in app.dart (never called)
- Redundant condition installedOnly && nonInstalledOnly
- Dead ternary branch in getApp()
- Redundant if(valid) guard in generated_form_modal onPressed
- Redundant message = '' in AppsRemovedNotification
- Duplicated // ignore: comment
- DirectAPKLink/RockMods unused scraping for track-only

Naming improvements:
- fdroid → isFdroidBuild, MyTaskHandler → BackgroundUpdateTaskHandler
- pm → packageManager, AppNames → AppIdentity
- findExistingUpdates → findAppIdsWithPendingUpdates
- endOfGetAppChanges → postProcessApp
- someValueChanged → notifyFormChange
- _isNumeric → _isDigit, _maxChangeLogBytes → _maxChangeLogCodeUnits
- customDateParse → formatDateForParsing
- LogLevels → LogLevel

Comment cleanup:
- Removed 20+ noise/obvious comments across 10 files
- Shortened verbose doc comments (bgUpdateCheck 15→6 lines)
- Fixed ALL-CAPS section headers in apps_provider_lifecycle
- Fixed @param Javadoc → Dart doc style
- Removed empty/blind comments
- Cleaned unprofessional wording ('pacify')
- Shortened verbose block comments in custom_app_bar, ui_shapes, motion

Performance:
- Cached SourceProvider() in app.dart (was per-build) and home.dart (was per-deep-link)
- home.dart: context.read → context.watch for reactive page transitions

- code changes: 47 files, +263/-512 lines
2026-06-30 22:26:21 +01:00
Imran Remtulla
8eb2f092c2 Refactor: fix bugs, extract helpers, improve code structure
Bugs fixed:
- hashListOfLists double-hashing (sha256.hex.hashCode losing 224 bits)
- undrained HTTP response streams in downloadFile/checkETagHeader
- destructive useMaterialYou setter (removed unused getter/setter)
- 5 bare .endsWith('.apk') replaced with AppSource.isApkOrContainerFile
- fire-and-forget async IIFE in AppsProvider constructor missing error handling

Refactors:
- Extracted appJSONCompatibilityModifiers into 6 named sub-migration helpers
- Split bgUpdateCheck: extracted _bgRunUpdateCheck helper (~170 lines)
- Moved showMessage/showError from custom_errors.dart to components/ui_widgets.dart
- Replaced 'source is! HTML && source is! SourceForge' with AppSource.suppressStandardVersionExtraction flag
- Extracted buildObtainiumTheme to new lib/theme.dart
- Cleaned up BG workaround TODO, verbose comments, docs errors
2026-06-30 17:44:55 +01:00
Imran Remtulla
39bb256ef7 Fix bugs, deduplicate code, and refactor for readability
Bug fixes:
- App.deepCopy() properly deep-copies apkUrls (shared mutable reference)
- Fix notification ID collision (SilentUpdateAttempt now uses ID 4, not 3)
- Fix GitLab regex char class bug (word boundaries don't work in [])
- Replace DateTime.parse with tryParse to handle invalid GitHub dates
- Fix Huawei AppGallery replaceAll fragility (use hosts[1] directly)
- Replace apps.update with explicit containsKey checks
- Make GitHub rate-limit epoch fallback dynamic (was hardcoded to 2027)
- Fix null-date release sort stability
- Fix undoGHProxyMod replaceFirst to use startsWith+substring
- Fix colourSchemeMode/useMaterialYou dual-key desync

Refactoring:
- Add AppInMemory.copyWith() to eliminate repeated construction sites
- Replace MapEntry<bool, String>? with VersionComparison class
- Extract _buildUpdateMessage() helper for notification message generation
- Extract _migrateAppToHTML() to unify 4 repeated HTML source migrations
- Split settings page build into _buildUpdatesSection/_buildAppearanceSection
- Extract _handleShizukuToggle() from inline switch handler
- Extract _waitForConcurrentDownload() from 222-line downloadFile()
- Extract _runBGInstallMode() from 298-line bgUpdateCheck()
- Unify moveStrToEnd functions with generic _moveToEnd<T>()

Shared utilities:
- Add AppSource.stripLastPathSegment() (replaces 4 occurrences)
- Add AppSource.tryInferAppIdFromLastPathSegment() (deduplicates 7 sources)
- Add sourceIdentifier getter (replaces runtimeType.toString() pattern)
- Add ActionListTile shared widget (replaces _actionTile/optionTile duplication)

Comment fixes: typo corrections, clarify intent, remove redundant comments
2026-06-30 16:23:57 +01:00
Imran Remtulla
7a15172d2a chore: readability/maintainability pass across entire codebase
Phase 1 — quick wins:
- Fix 4 flutter_analyze lint issues
- Remove dead code (incrementCountCommand, noAPKFound, duplicate date parse)
- Standardize comment style (remove outlier emoji)

Phase 2 — bug fixes:
- Fix inverted parallel-downloads logic in downloadAppAssets
- Replace unsafe int.parse/DateTime.parse with tryParse in scraped/user input
- Fix _reloadIfBgSaved to clear timestamp on failure (was stuck-in-loop)

Phase 3 — source deduplication:
- Migrate 8 hand-rolled standardizeURL regexes to base-class standardizeUrlWithRegex
- Route githubstars.dart through sourceRequest instead of raw http.get

Phase 4 — structural refactors:
- Extract caption/fieldTile/colorPickerDialog/footer from 735-line settings build()
- Fix void async anti-pattern on uninstallApp -> Future<void>

Phase 5 — docs:
- Remove fabricated config_keys.dart/AppConfigKey references from developer guide
- Correct/trim README troubleshooting section
2026-06-30 14:30:21 +01:00
Imran Remtulla
3579891889 fix: source robustness, APKCombo, download-progress UI, and perf
App sources:
- Harden sources against malformed/changed responses (null, parse, index
  and empty-version guards): rustore, tencent, apkmirror, gitlab, aptoide,
  fdroid(repo), sourcehut, huaweiappgallery, itchio, izzyondroid,
  telegramapp, uptodown, vivoappstore, etc.
- APKCombo: fix and enable (issue #341) - unwrap "/r2?u=" links to the
  signed Cloudflare R2 URL, drop the Host header that 403'd the R2
  download, take one build per variant, and parse the release date;
  register the source.
- Remove orphaned Mullvad source (never registered).
- F-Droid version-regex filter selects the newest match; fix Jenkins
  changelog link; GitLab reuses one GitHub helper instance; GitHubStars
  reuses one GitHub instance.

UI / behaviour:
- Fix download progress bar never updating on the app detail page and the
  apps list (provider select on an in-place-mutated AppInMemory never
  fired a rebuild).
- Fix single-category gradient crash, dead "installing" tile state, silent
  swipe-install errors, deep-link dedup, mounted/context guards in
  import/export and add-app, and ExportSection future caching.
- generated_form: GeneratedFormSwitch.disabled is now applied; clone()
  preserves disabled and autoCompleteOptions.

Performance:
- Cache SettingsProvider.categories (was rebuilding a Map + re-parsing JSON
  on every access, over-rebuilding category selectors).
- Memoize the flattened combined form items used by the per-app JSON
  migration at load.

Tooling / config:
- build.sh: set -euo pipefail; make the --build-id=none workaround
  idempotent and glob-safe.
- pubspec: branch-track git dependencies.
- Remove unused config_keys.dart (consolidate on raw setting keys).
2026-06-29 15:04:30 +01:00
Imran Remtulla
0bae4251cd fix: bugs, performance, and code quality improvements across codebase
- Fix GitHub rate limit time calculation (was ignoring current time)
- Fix HTTP client leaks on redirect exhaustion and early download returns
- Drain StreamedResponse before closing client in checkETagHeader
- Fix null assertion crash in checkUpdate when app ID not found
- Remove duplicate null check in getObtainiumHttpError
- Replace empty catch blocks with typed exceptions and comments
- Fix potential null dereference in AppFilePicker and CategorySelector
- Fix category sort comparator transitivity violation for null values
- Call LogsProvider.close() on app dispose (was never called)
- Replace print() with debugPrint() for consistency
- Replace sync I/O with async variants (readAsString, writeAsString, rename, list, stat)
- Convert installedAppsData list scan to O(1) map lookup in loadApps
- Pre-group apps by category to avoid O(n*m) per-category scans
- Use Set for alreadyAddedUrls to enable O(1) contains lookups
- Add sourceType cache to AppInMemory to avoid re-detecting source on filter
- Use context.select instead of context.watch to reduce unnecessary rebuilds
- Extract interval slider to dedicated widget to avoid full settings page rebuilds
- Extract _FormSwitchRow to prevent switch rebuilds on text field changes
- Add cacheWidth/cacheHeight to AppIcon image decoding
- Batch URL import with concurrency limit of 4 instead of sequential
- Guard auto-export timer callback with _disposed check
- Defer _lastBackgroundSave clear until loadApps completes
- Simplify findExistingUpdates complex nested logic
- Refactor 7 app sources to use standardizeUrlWithRegex helper
- Replace 25+ magic numbers with named constants
- Clean up late keyword on immutable fields in App and APKDetails
2026-06-29 11:04:26 +01:00
Imran Remtulla
e436405a1c robustness + perf: defend against OOM, crashes, rebuild amplification, and stale state
- apps_provider_install: stream-decompress gzip tarballs >64MB to temp file
  instead of loading into memory; async readAsBytes for APK sharing
- html.dart: null-guard res.request.url fallback; cap intermediate link
  depth at 10
- github.dart: null-check regex matches before .start/.end assertions
- home.dart: use context.select for isTV to avoid full-shell rebuilds on
  every settings change
- app_list_tile.dart: replace MediaQuery.sizeOf with LayoutBuilder;
  guard category gradient division-by-zero for single-category apps
- add_app.dart: cache FutureBuilder future so it does not re-fetch on
  every rebuild
- import_export.dart: add didUpdateWidget to SelectionModal to reset
  stale entrySelections when parent rebuilds with new entries
- generated_form.dart: dispose old TextEditingControllers before re-init
- logs_provider.dart: make db connection static (shared across instances);
  add close() method
- fdroid.dart: guard changelog substring against UTF-16 surrogate splits
- ui_widgets.dart: await Clipboard.setData; change showConfirmDialog
  content from Object? to Widget?; use consistent TextButton type in
  HighlightableButton; add semanticLabel to EmptyState icon
- app.dart: await _getUpdate in RefreshIndicator; show loading spinner
  in WebView instead of empty Container
- analysis_options.yaml: enable stricter lint rules
2026-06-29 01:48:46 +01:00
Imran Remtulla
4aa84c35c1 UX/a11y: settings loading state, APK-origin opt-out, link/swatch semantics
- Settings: show a loading spinner instead of a blank screen while prefs load
- APK-origin warning dialog: add a "don't show again" checkbox (sets
  hideAPKOriginWarning) so the choice isn't buried in settings
- Accessibility: announce LinkText as a link; exclude decorative AppIcon images
  from semantics; mark category color swatches as selectable buttons with their
  selected state; expose the category long-press-to-edit via a tooltip and a
  semantic long-press action
- Settings: extract the ~85-line update-interval slider tile into
  _buildIntervalSliderTile to shrink the build() method
2026-06-28 17:56:18 +01:00
Imran Remtulla
72dd2cddf0 Decompose large build() methods, optimize providers, fix bugs, and improve accessibility
- Extract the god build() methods in the apps/app/add_app pages into focused, named helper methods
- Memoize AppSource instances and SettingsProvider platform calls; drop a duplicate source-config lookup
- Batch loadApps notifications, replace the busy-wait with a Completer lock, and debounce auto-export
- Add a compatVersion stamp so already-migrated apps skip one-time legacy migrations
- Only rebuild on integer download-progress changes; harden list/detail cache signatures with Object.hashAll
- Fix dead select-all branches, add mounted guards, and clone source-owned form items to avoid mutation leaks
- Expose swipe install/remove and icon long-press to screen readers; add a list progress bar and URL copy tooltip
- Move flutter_lints to dev_dependencies and apply dart format across the tree
2026-06-28 03:40:45 +01:00
Imran Remtulla
f2cba12b20 Add showHelpDialog helper and dedup about/help dialogs
Extract the repeated about/help AlertDialog into showHelpDialog(context, title, content) and rewire the generated_form field-help and settings toggle-help buttons to it.
2026-06-25 22:29:52 +01:00
Imran Remtulla
34195d488c Add showConfirmDialog helper and dedup two confirm dialogs
Extract a reusable showConfirmDialog(context, title, content, ...) -> Future<bool> and rewire the mass-mark and mark-updated yes/no dialogs to it. Behavior-preserving: the dialog is identical and the action runs on confirm.
2026-06-25 22:13:45 +01:00
Imran Remtulla
a73267e1b7 Add reusable ConnectedCard for connected-tile pattern
Replaces ~11 hand-rolled Material(positionalTileShape/squircle) cards across the app detail page (sections + repo-rename) and apps page (category segments, update banner, filter dialog) with a single ConnectedCard widget; both pages no longer depend on ui_shapes directly.
2026-06-25 21:07:44 +01:00
Imran Remtulla
0d22c9d119 Extract reusable components and relocate dialogs
- Move AppFilePicker/APKOriginWarningDialog out of apps_provider into components/app_dialogs.dart
- Add reusable EmptyState, LinkText, and copyToClipboard to ui_widgets; rewire apps/home/app pages
- SourceProvider.getSource: build the source list once per call instead of up to 3x
2026-06-25 20:59:37 +01:00
Imran Remtulla
21e826f7fc Code quality, performance, accessibility, and lint cleanup
- Extract AppListTile/AppListCategorySection from apps.dart build()
- Memoize filter/sort/reorder pipeline; debounce search
- Cache app-detail deepCopy; lazy-init detail WebView
- Shared AppIcon widget; squircle icons, semantics, and tooltips for a11y
- Fix two-pane/wide-layout content widths
- Remove dead expressive_fab_menu.dart; rename directAPKLink.dart -> direct_apk_link.dart
- Resolve full analyzer backlog (112 -> 0); make intl a direct dependency
2026-06-25 20:41:33 +01:00
Imran Remtulla
16b334c5b0 M3E updates 2026-06-25 13:01:35 +01:00