diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index ebf19a46..d423681d 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -271,13 +271,11 @@ jobs:
MACOS_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
run: |
- # Create temporary keychain
KEYCHAIN_PATH=$RUNNER_TEMP/build.keychain
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
- # Import certificate to keychain
CERTIFICATE_PATH=$RUNNER_TEMP/certificate.p12
echo "$MACOS_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH
security import $CERTIFICATE_PATH -k $KEYCHAIN_PATH -P "$MACOS_CERTIFICATE_PASSWORD" -T /usr/bin/codesign
diff --git a/.gitignore b/.gitignore
index 99f47ebb..9b6ba5b0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,9 +18,7 @@ migrate_working_dir/
*.iws
.idea/
-# The .vscode folder contains launch configuration and tasks you configure in
-# VS Code which you may wish to be included in version control, so this line
-# is commented out by default.
+# Keep .vscode/ available for contributors' local configuration.
#.vscode/
# Flutter/Dart/Pub related
diff --git a/.maestro/regression_flows/03_tv_library_focus.yaml b/.maestro/regression_flows/03_tv_library_focus.yaml
index 4951eb75..15c0b4c5 100644
--- a/.maestro/regression_flows/03_tv_library_focus.yaml
+++ b/.maestro/regression_flows/03_tv_library_focus.yaml
@@ -22,8 +22,8 @@ tags:
- pressKey: "Remote Dpad Up"
- pressKey: "Remote Dpad Right"
- pressKey: "Remote Dpad Right"
-# The grid row must be matchable before the sort sheet opens, otherwise the
-# occlusion assertion below would pass for the wrong reason.
+# Wait for the row before opening the sheet so occlusion is tested against the
+# grid, not an absent or stale match.
- extendedWaitUntil:
visible: "(?s).*Alpha Archive.*"
timeout: 15000
@@ -31,9 +31,8 @@ tags:
- extendedWaitUntil:
visible: "Title"
timeout: 10000
-# The host renders the grid, the barrier, and the sheet in one Stack and never
-# unmounts the grid, so before 8e1904dd wrapped the barrier in BlockSemantics
-# an occluded row still read as visible to accessibility and to Maestro.
+# The grid remains mounted under the Stack; BlockSemantics is required for
+# occluded rows to disappear from Maestro's accessibility tree.
- assertNotVisible: "(?s).*Alpha Archive.*"
- pressKey: "Remote Dpad Center"
- pressKey: "Remote Dpad Left"
diff --git a/.maestro/regression_flows/04_tv_player_keys.yaml b/.maestro/regression_flows/04_tv_player_keys.yaml
index c9335d46..f6a99b17 100644
--- a/.maestro/regression_flows/04_tv_player_keys.yaml
+++ b/.maestro/regression_flows/04_tv_player_keys.yaml
@@ -16,13 +16,9 @@ tags:
visible: "(?s)^(Play|Resume).*$"
commands:
- pressKey: "Remote Dpad Center"
-# The TV player opens with its chrome down so the OSD and timebar never sit
-# over the opening seconds of the picture (#1765), so the Pause button can no
-# longer stand in for "the player has finished loading". Wait for the detail
-# screen to go first: the labelled spinner is necessarily up the moment the
-# player route owns the frame, and it only clears once playback reports its
-# first frame or gives up, so this can never advance before the media opens.
-# A give-up lands on the transport assertions below, which is where it belongs.
+# TV playback starts with chrome hidden (#1765), so wait for its loading label
+# rather than treating the Pause button as readiness. A failed open reaches the
+# transport assertions below.
- extendedWaitUntil:
notVisible: "Overview"
timeout: 30000
@@ -30,18 +26,14 @@ tags:
notVisible: "Loading video"
timeout: 30000
- assertNotVisible: "(?s)^(Play|Pause)$"
-# Hardware transport keys drive playback without raising the chrome (#1676):
-# the player answers with a centred disc (pause) or a side readout (seek), never the
-# full chrome, so subtitles stay readable.
-# Pause first — it also freezes the clip, so the seek assertions below cannot
-# race the end of a short fixture item.
+# Transport keys keep chrome hidden (#1676); pause first so seeks cannot race
+# the end of this short fixture.
- pressKey: "Remote Media Play Pause"
- extendedWaitUntil:
visible: "Paused"
timeout: 10000
- assertNotVisible: "(?s)^Play$"
-# D-pad seeking reports through the skip badge, never the scrub bar, and
-# consecutive presses in one direction stack into a running total.
+# D-pad seeks use the cumulative skip badge, not the scrub bar.
- pressKey: "Remote Dpad Right"
- extendedWaitUntil:
visible: "(?s)^Seek forward 10 seconds$"
@@ -56,7 +48,7 @@ tags:
visible: "Playing"
timeout: 10000
- assertNotVisible: "(?s)^Pause$"
-# Select stays the deliberate way to bring the chrome back.
+# Select is the explicit way to restore the chrome.
- pressKey: "Remote Dpad Center"
- extendedWaitUntil:
visible: "(?s)^(Play|Pause)$"
diff --git a/.maestro/regression_flows/05_tv_next_episode_back.yaml b/.maestro/regression_flows/05_tv_next_episode_back.yaml
index 1069c8c5..8ae56194 100644
--- a/.maestro/regression_flows/05_tv_next_episode_back.yaml
+++ b/.maestro/regression_flows/05_tv_next_episode_back.yaml
@@ -7,10 +7,8 @@ tags:
- playback
---
- runFlow: ../subflows/onboard_jellyfin_tv.yaml
-# Reach Search with the D-pad, the way 10_tv_settings_navigation.yaml does. A
-# tap here flips InputModeTracker into pointer mode, which collapses the rail
-# to icons and leaves no "Search" label to hit — and a percentage coordinate
-# does not survive the jump from a phone in forced TV mode to a 4K television.
+# Reach Search by D-pad: taps switch to pointer mode and hide the TV rail label,
+# while percentage coordinates are not portable across TV sizes.
- pressKey: "Remote Dpad Left"
- extendedWaitUntil:
visible: "Search"
@@ -38,11 +36,8 @@ tags:
- waitForAnimationToEnd:
timeout: 5000
- tapOn: "(?s)^Play S1E1$"
-# The TV player opens with its chrome down (#1765), so the Pause button can no
-# longer stand in for "the player has finished loading". Wait for the detail
-# screen to go first: the labelled spinner is necessarily up the moment the
-# player route owns the frame, and it only clears once playback reports its
-# first frame or gives up, so this can never advance before the media opens.
+# The player starts with chrome hidden (#1765); wait for its loading label
+# rather than using Pause as readiness.
- extendedWaitUntil:
notVisible: "(?s)^Play S1E1$"
timeout: 30000
@@ -51,9 +46,7 @@ tags:
timeout: 30000
- pressKey: "Remote Media Fast Forward"
- pressKey: "Remote Media Fast Forward"
-# Gate on the prompt's own Cancel action, the label the iOS branch below taps.
-# "Next Episode" is the credits skip button at this point in the episode, so
-# waiting on it would let Back fire before the prompt ever opened.
+# Wait for Cancel, not Next Episode (the credits-skip action), before pressing Back.
- extendedWaitUntil:
visible: "(?s)^Cancel$"
timeout: 20000
diff --git a/.maestro/regression_flows/06_playback_recovery.yaml b/.maestro/regression_flows/06_playback_recovery.yaml
index 8cbc5fcb..cbcb3ba7 100644
--- a/.maestro/regression_flows/06_playback_recovery.yaml
+++ b/.maestro/regression_flows/06_playback_recovery.yaml
@@ -8,10 +8,8 @@ tags:
---
- runFlow: ../subflows/onboard_jellyfin.yaml
- tapOn: "(?s)^Libraries.*"
-# Every seeded alphabet title carries the same dateadded, so which of them the
-# "Recently Added" rail returns is not stable across scans. This flow only
-# needs some playable movie, so accept any of them rather than pinning one and
-# failing whenever the tie-break lands elsewhere.
+# All seeded titles share dateadded, so accept any playable Recently Added movie
+# instead of relying on an unstable tie-break.
- extendedWaitUntil:
visible: "(?s).*(?:Alpha Archive|Bravo Beacon|Charlie Circuit|Delta Drive|Echo Engine|Foxtrot Frame|Gamma Garden|Hotel Horizon|India Index|Juliet Junction|Kilo Key|Lima Loop|Mike Matrix|November Node|Oscar Orbit|Papa Pipeline|Quebec Queue|Romeo Relay|Sierra Signal|Tango Track|Uniform Update|Victor View|Whiskey Widget|Xray XML|Yankee Yield|Zulu Zone).*, movie, .*"
timeout: 15000
diff --git a/.maestro/regression_flows/07_sheet_back_dismiss.yaml b/.maestro/regression_flows/07_sheet_back_dismiss.yaml
index d9c09782..4612a881 100644
--- a/.maestro/regression_flows/07_sheet_back_dismiss.yaml
+++ b/.maestro/regression_flows/07_sheet_back_dismiss.yaml
@@ -7,20 +7,9 @@ tags:
- settings
- sheets
---
-# Guards 8e1904dd and c48cbf70 together.
-#
-# On a phone, Settings is a pushed route. Before c48cbf70 it carried no
-# OverlaySheetHost, so Manage Libraries fell back to showModalBottomSheet and a
-# single Back tore down the sheet *and* Settings. Before 8e1904dd the host
-# answered the platform pop with a TV-only dedup marker that could already be
-# spent, stranding the sheet open with no way out. Either defect fails the
-# "Manage Libraries is still there after one Back" assertion below.
-#
-# The same commit blocks semantics behind the barrier, so the occlusion
-# assertions pin that an open sheet actually hides the rows underneath.
-# Pristine state on purpose. The TV regressions in the same CI group leave
-# "Force TV mode" enabled, and this flow asserts the handheld Settings route,
-# so it must not inherit whichever layout the previous flow left behind.
+# Guards 8e1904dd and c48cbf70: phone Settings must host the sheet so one Back
+# dismisses only the sheet, while BlockSemantics hides rows behind the barrier.
+# Start clean because preceding TV flows may leave Force TV mode enabled.
- runFlow: ../subflows/onboard_jellyfin.yaml
- runFlow: ../subflows/open_settings.yaml
- assertVisible: "(?s)^Services.*"
@@ -29,10 +18,8 @@ tags:
- extendedWaitUntil:
visible: "Maestro Movies"
timeout: 15000
-# The barrier swallows every pointer event, so the rows behind it must leave
-# the semantics tree too. Without BlockSemantics an occluded row still reads as
-# visible and a tap on it lands on the barrier instead. "Manage Libraries" is
-# excluded on purpose: it is also the sheet's own title.
+# The barrier removes covered rows from semantics; the sheet title remains
+# visible because it belongs to the sheet.
- assertNotVisible: "(?s)^Services.*"
- assertNotVisible: "(?s)^Video Playback.*"
- assertNotVisible: "(?s)^Appearance.*"
@@ -41,15 +28,13 @@ tags:
- waitForAnimationToEnd:
timeout: 3000
- assertNotVisible: "Maestro Movies"
-# One Back closed only the sheet: Settings is still the current route.
- extendedWaitUntil:
visible: "(?s)^Manage Libraries.*"
timeout: 10000
- assertVisible: "(?s)^Services.*"
- assertVisible: "(?s)^Video Playback.*"
- assertNotVisible: "Discover"
-# Reopening proves the host did not strand the one-shot dedup marker: a second
-# dismissal has to work exactly like the first.
+# Reopening verifies the one-shot pop deduplication marker was not stranded.
- tapOn: "(?s)^Manage Libraries.*"
- extendedWaitUntil:
visible: "Maestro Movies"
diff --git a/.maestro/regression_flows/08_track_choice_survives_pending_pass.yaml b/.maestro/regression_flows/08_track_choice_survives_pending_pass.yaml
index 79ce2958..f5820fc2 100644
--- a/.maestro/regression_flows/08_track_choice_survives_pending_pass.yaml
+++ b/.maestro/regression_flows/08_track_choice_survives_pending_pass.yaml
@@ -7,20 +7,10 @@ tags:
- playback
- subtitles
---
-# Guards 468d6804. When a source advertises tracks the native list has not
-# produced yet, TrackManager arms an automatic selection pass with a 5s first
-# attempt and a 25s deadline. A user pick made inside that window used to only
-# persist the preference, leaving the pass armed, so the choice snapped back to
-# the server/profile preferred track up to ~30s later. The pick now retires the
-# pending pass, and the wait below is long enough to outlive both timers.
-#
-# Fixture: Codec H264 EAC3 Multisub advertises three E-AC-3 audio streams
-# (Hindi and Japanese flagged default, English not) and 36 SRT subtitle
-# streams, so both picks below are genuine changes away from the automatic one.
-# Pristine state on purpose, for two reasons: the TV regressions in the same
-# CI group leave "Force TV mode" enabled, and a remembered track selection
-# from an earlier run would pre-select the very rows this flow picks, making
-# every assertion below vacuous.
+# Guards 468d6804: a user pick must retire TrackManager's pending automatic
+# selection pass, or the server preference can overwrite it up to 30s later.
+# The codec fixture supplies non-default audio and subtitle choices, and clean
+# state prevents remembered selections from making the assertions vacuous.
- runFlow: ../subflows/onboard_jellyfin.yaml
- runFlow:
file: ../subflows/open_codec_sample.yaml
diff --git a/.maestro/regression_flows/09_language_picker_locales.yaml b/.maestro/regression_flows/09_language_picker_locales.yaml
index ff2fd96b..0db1d4bf 100644
--- a/.maestro/regression_flows/09_language_picker_locales.yaml
+++ b/.maestro/regression_flows/09_language_picker_locales.yaml
@@ -7,16 +7,9 @@ tags:
- settings
- i18n
---
-# Guards 7677d159 and 100d7729. AppLocale is switched over exhaustively in
-# appearance_settings_screen.dart, so a missing arm is a compile error, but a
-# locale whose JSON never reached the generator ships a picker entry that falls
-# back to English. Selecting Turkish and reading root-level navigation labels
-# proves the generated locale is wired end to end.
-#
-# This flow mutates a persisted pref, and the app language decides every
-# selector after the tap, so it starts from a cleared install rather than
-# ensure_onboarded: a run that dies mid-flow must not leave the next flow
-# hunting for English strings in a Turkish tree.
+# Guards 7677d159 and 100d7729: selecting Turkish and reading root navigation
+# labels proves the generated locale is wired end to end. Start clean because
+# the language preference persists and affects every later selector.
- runFlow: ../subflows/onboard_jellyfin.yaml
- runFlow: ../subflows/open_settings.yaml
- tapOn: "(?s)^Appearance.*"
@@ -54,9 +47,7 @@ tags:
- assertVisible: "Keşfet"
- assertNotVisible: "(?s)^Libraries.*"
- assertNotVisible: "Discover"
-# Walk back through the Turkish tree and restore English. The pref outlives a
-# plain launchApp, so leaving the device in Turkish would break every later
-# flow in the suite.
+# Restore English before leaving the device; the locale preference outlives launchApp.
- repeat:
times: 3
while:
diff --git a/.maestro/regression_flows/10_tv_settings_navigation.yaml b/.maestro/regression_flows/10_tv_settings_navigation.yaml
index 1b1f532d..5c450de3 100644
--- a/.maestro/regression_flows/10_tv_settings_navigation.yaml
+++ b/.maestro/regression_flows/10_tv_settings_navigation.yaml
@@ -7,21 +7,11 @@ tags:
- tv
- settings
---
-# Guards ef310459 and the Apple-only gates touched by 6c14049e, and pins TV
-# settings navigation generally.
-#
-# It deliberately does NOT guard the 15b54e2e density change. That commit took
-# every settings row from ~80dp to ~61dp, but the rows below the fold stay in
-# the semantics tree either way, so this flow passes identically on both sides
-# of it — measured, not assumed. A real guard would need a pixel `height`
-# assertion, and Maestro has no DPR-relative form, so pinning one here would
-# only hold for the box it was written on. Row geometry belongs to
-# test/widgets/setting_tile_test.dart.
-#
-# Every step uses D-pad keys, never taps. InputModeTracker flips to pointer
-# mode on the first touch event and the TV number spinner only builds in
-# keyboard mode, so a single tapOn anywhere above would silently swap the
-# spinner for a plain text field.
+# Guards ef310459 and the Apple-only gates touched by 6c14049e.
+# This flow intentionally does not pin 15b54e2e's row density: semantics stay
+# stable across that change, and Maestro has no DPR-relative height assertion.
+# Use D-pad only; a tap switches InputModeTracker to pointer mode and removes
+# the TV number spinner.
- runFlow: ../subflows/onboard_jellyfin_tv_device.yaml
- pressKey: "Remote Dpad Left"
- extendedWaitUntil:
diff --git a/.maestro/subflows/ensure_onboarded.yaml b/.maestro/subflows/ensure_onboarded.yaml
index 5eb9c0c8..3b210a65 100644
--- a/.maestro/subflows/ensure_onboarded.yaml
+++ b/.maestro/subflows/ensure_onboarded.yaml
@@ -1,20 +1,10 @@
appId: com.edde746.plezy
---
-# Reach a signed-in Home without paying for onboarding that already happened.
-#
-# `onboard_jellyfin.yaml` clears app state and retypes the server URL and
-# credentials, which measures ~59s per flow on a Pixel 7 and dominates every
-# flow that only needs "signed in, on Home". A plain `launchApp` keeps stored
-# data and cold-starts straight back to Home, which measures ~16s.
-#
-# The guard keeps each flow runnable on its own: when no session is stored --
-# a fresh install, or a run after the logout flow -- "Discover" is absent and
-# this falls through to the real onboarding. Flows that must prove onboarding
-# itself, or that need pristine state, keep calling onboard_jellyfin.yaml.
+# Reach a signed-in Home without repeating onboarding. A plain launch preserves
+# stored state (~16s versus ~59s for retyping credentials); fall back to full
+# onboarding when no session exists so each flow remains runnable alone.
- launchApp
-# Settle on a known screen first. Branching straight off `launchApp` races the
-# splash: "Discover" has not rendered yet, the guard reads it as absent, and
-# every flow pays for a full re-onboarding it did not need.
+# Wait for the splash to resolve before deciding whether onboarding is needed.
- extendedWaitUntil:
visible: "(?s)^(?:Discover|Sign in with Plex|Connect to Jellyfin|Wait).*"
timeout: 30000
diff --git a/.maestro/subflows/onboard_jellyfin.yaml b/.maestro/subflows/onboard_jellyfin.yaml
index 62810d19..cd87bbd2 100644
--- a/.maestro/subflows/onboard_jellyfin.yaml
+++ b/.maestro/subflows/onboard_jellyfin.yaml
@@ -10,10 +10,8 @@ appId: com.edde746.plezy
- extendedWaitUntil:
visible: "(?s)^(?:Connect to Jellyfin|Wait).*"
timeout: 30000
- # A miss on `tapOn ... optional: true` still runs Maestro's full element
- # search before giving up, which measured 3s here and 7.8s for "Sign in"
- # on every onboarding. These taps normally find nothing, so gate them on
- # a single visibility check instead.
+# Optional taps still pay Maestro's full search cost when they miss; guard them
+# with one visibility check instead.
- runFlow:
when:
visible: "Wait"
diff --git a/.maestro/subflows/onboard_jellyfin_tv_device.yaml b/.maestro/subflows/onboard_jellyfin_tv_device.yaml
index b61da160..b4317cb9 100644
--- a/.maestro/subflows/onboard_jellyfin_tv_device.yaml
+++ b/.maestro/subflows/onboard_jellyfin_tv_device.yaml
@@ -1,12 +1,7 @@
appId: com.edde746.plezy
---
-# Onboarding for a device that already reports itself as a TV.
-#
-# `onboard_jellyfin_tv.yaml` exists for the phone emulator CI runs on: it
-# onboards through the handheld layout and then walks Settings to flip
-# "Force TV mode". A real Android TV box takes the TV layout from the first
-# frame, so that walk has no handheld chrome to tap and the toggle would only
-# re-assert what PlatformDetector already reports.
+# Onboard a device that reports itself as a TV; unlike the phone flow, it starts
+# in TV layout and needs no Force TV mode walk.
- retry:
maxRetries: 1
commands:
@@ -32,9 +27,8 @@ appId: com.edde746.plezy
- tapOn: "(?s)Server URLs.*"
- inputText: ${JELLYFIN_URL}
- tapOn: "Find server"
-# A TV-sized layout offers Quick Connect first because typing on a remote is
-# slow. The code path needs a second device to approve, so fall back to the
-# username form the phone flow already uses.
+# Quick Connect is awkward on a remote and needs another device, so use the
+# username form as fallback.
- extendedWaitUntil:
visible: "(?s)^(?:Username|Cancel)$"
timeout: 30000
diff --git a/.maestro/subflows/open_codec_sample.yaml b/.maestro/subflows/open_codec_sample.yaml
index 7bae2124..fafd1e49 100644
--- a/.maestro/subflows/open_codec_sample.yaml
+++ b/.maestro/subflows/open_codec_sample.yaml
@@ -17,10 +17,8 @@ appId: com.edde746.plezy
platform: Android
commands:
- hideKeyboard
-# A card announces its watch state three ways, and the codec samples keep a
-# resume position on the server once any earlier flow has played them, so the
-# partial form has to be accepted for this subflow to be re-runnable against a
-# fixture container that is not thrown away between suites.
+# Codec cards retain watch state and resume position between flows, so accept
+# any valid watch-state label to keep this subflow rerunnable.
- extendedWaitUntil:
visible: "(?s)^${SAMPLE_TITLE}, movie, (?:watched|unwatched|[0-9]+ percent watched)$"
timeout: 15000
diff --git a/.maestro/subflows/open_settings.yaml b/.maestro/subflows/open_settings.yaml
index 00bc0449..249ce78a 100644
--- a/.maestro/subflows/open_settings.yaml
+++ b/.maestro/subflows/open_settings.yaml
@@ -1,11 +1,7 @@
appId: com.edde746.plezy
---
-# Reach Settings from a signed-in Home on a phone layout.
-#
-# The profile menu is itself an overlay sheet on the MainScreen host, so a tap
-# issued while the previous route is still settling opens nothing. The guarded
-# repeat re-opens the menu instead of failing the flow, matching the pattern
-# already used by flows/07_profiles_settings.yaml.
+# Reach phone Settings from signed-in Home. The profile menu is an overlay
+# sheet; retry while the previous route settles.
- extendedWaitUntil:
visible: "Discover"
timeout: 30000
diff --git a/analysis_options.yaml b/analysis_options.yaml
index 57755a26..c6b3ff7d 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -15,8 +15,7 @@ linter:
prefer_final_in_for_each: true
avoid_print: true
-# Do not register DCL as an analyzer plugin: its analyzer 10 integration crashes
-# on Linux. CI invokes the supported check-unused commands explicitly.
+# DCL's analyzer 10 plugin crashes on Linux; CI runs check-unused commands directly.
dart_code_linter:
rules-exclude:
- "test/**"
@@ -27,7 +26,7 @@ dart_code_linter:
- package:dart_code_linter/presets/recommended.yaml
rules:
- # --- Flutter rules (on top of recommended) ---
+ # Flutter-specific rules.
- avoid-border-all
- avoid-shrink-wrap-in-lists
- avoid-expanded-as-spacer
@@ -37,7 +36,7 @@ dart_code_linter:
- prefer-define-hero-tag
- use-setstate-synchronously
- # --- Additional useful Dart rules ---
+ # Additional Dart rules.
- avoid-cascade-after-if-null
- avoid-collection-methods-with-unrelated-types
- avoid-unnecessary-type-assertions
@@ -48,7 +47,7 @@ dart_code_linter:
- prefer-enums-by-name
- prefer-commenting-analyzer-ignores
- # --- Disable noisy rules from recommended preset ---
+ # Disabled noisy rules.
- no-magic-number: false
- avoid-dynamic: false
- format-comment: false
diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts
index c7ba7ea5..5b33b40f 100644
--- a/android/app/build.gradle.kts
+++ b/android/app/build.gradle.kts
@@ -336,8 +336,6 @@ android {
defaultConfig {
applicationId = "com.edde746.plezy"
- // You can update the following values to match your application needs.
- // For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = 25 // Fire OS 6.x (API 25); overrides libmpv-android's minSdk=26
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 0f1db247..22ab1946 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -9,17 +9,14 @@
-
-
-
@@ -30,15 +27,11 @@
-
-
-
-
-
-
@@ -88,7 +76,6 @@
-
-