Skip to content
Open
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
using AndroidX.Core.View;
using AndroidX.Media3.UI;
using CommunityToolkit.Maui.Views;
using View = Android.Views.View;
using Window = Android.Views.Window;

[assembly: UsesPermission(Android.Manifest.Permission.ForegroundServiceMediaPlayback)]
[assembly: UsesPermission(Android.Manifest.Permission.ForegroundService)]
Expand All @@ -23,8 +25,6 @@ public class MauiMediaElement : CoordinatorLayout
readonly RelativeLayout relativeLayout;
readonly PlayerView playerView;

int defaultSystemUiVisibility;
bool isSystemBarVisible;
bool isFullScreen;

#pragma warning disable CS8618 // Non-nullable field is uninitialized. Consider declaring as nullable.
Expand Down Expand Up @@ -78,7 +78,7 @@ protected override void OnVisibilityChanged(Android.Views.View changedView, [Gen
base.OnVisibilityChanged(changedView, visibility);
if (isFullScreen && visibility is ViewStates.Visible)
{
SetSystemBarsVisibility();
SetStatusBarsHidden(isFullScreen);
}
}

Expand Down Expand Up @@ -131,77 +131,33 @@ void OnFullscreenButtonClick(object? sender, PlayerView.FullscreenButtonClickEve
isFullScreen = false;
layout?.RemoveView(relativeLayout);
AddView(relativeLayout);
relativeLayout.Invalidate();
}
// Hide/Show the SystemBars and Status bar
SetSystemBarsVisibility();
SetStatusBarsHidden(isFullScreen);
}

Copy link

Copilot AI Nov 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new SetStatusBarsHidden method lacks XML documentation comments. According to the coding guidelines, public methods should have XML documentation. Since this method is currently public (though it should likely be private/internal), add documentation explaining:

  • The purpose of the method
  • The hidden parameter
  • Any exceptions that may be thrown

Example:

/// <summary>
/// Sets the visibility of system bars (status bar and navigation bar).
/// </summary>
/// <param name="hidden">If <see langword="true"/>, hides the system bars; otherwise, shows them.</param>
/// <exception cref="InvalidOperationException">Thrown when the current activity, DecorView, or InsetsController is null.</exception>
Suggested change
/// <summary>
/// Sets the visibility of system bars (status bar and navigation bar).
/// </summary>
/// <param name="hidden">If <see langword="true"/>, hides the system bars; otherwise, shows them.</param>
/// <exception cref="InvalidOperationException">Thrown when the current activity, DecorView, or InsetsController is null.</exception>

Copilot uses AI. Check for mistakes.
void SetSystemBarsVisibility()
public static void SetStatusBarsHidden(bool hidden)
Copy link

Copilot AI Nov 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method SetStatusBarsHidden is marked as public static, but it should be private or internal since it's an implementation detail of system bar visibility management. Making it public exposes internal Android-specific behavior that shouldn't be part of the public API surface. Consider changing the visibility to private or internal.

Suggested change
public static void SetStatusBarsHidden(bool hidden)
static void SetStatusBarsHidden(bool hidden)

Copilot uses AI. Check for mistakes.
{
var currentWindow = CurrentPlatformContext.CurrentWindow;
var windowInsetsControllerCompat = WindowCompat.GetInsetsController(currentWindow, currentWindow.DecorView);

var barTypes = WindowInsetsCompat.Type.StatusBars()
| WindowInsetsCompat.Type.SystemBars()
| WindowInsetsCompat.Type.NavigationBars();

if (isFullScreen)
{
WindowCompat.SetDecorFitsSystemWindows(currentWindow, false);
if (OperatingSystem.IsAndroidVersionAtLeast(30))
{
var windowInsets = currentWindow.DecorView.RootWindowInsets;
if (windowInsets is not null)
{
isSystemBarVisible = windowInsets.IsVisible(WindowInsetsCompat.Type.NavigationBars()) || windowInsets.IsVisible(WindowInsetsCompat.Type.StatusBars());

if (isSystemBarVisible)
{
currentWindow.InsetsController?.Hide(WindowInsets.Type.SystemBars());
}
}
}
else
{
defaultSystemUiVisibility = (int)currentWindow.DecorView.SystemUiFlags;

currentWindow.DecorView.SystemUiFlags = currentWindow.DecorView.SystemUiFlags
| SystemUiFlags.LayoutStable
| SystemUiFlags.LayoutHideNavigation
| SystemUiFlags.LayoutFullscreen
| SystemUiFlags.HideNavigation
| SystemUiFlags.Fullscreen
| SystemUiFlags.Immersive;
}

if (windowInsetsControllerCompat is not null)
{
windowInsetsControllerCompat.Hide(barTypes);
windowInsetsControllerCompat.SystemBarsBehavior = WindowInsetsControllerCompat.BehaviorShowTransientBarsBySwipe;
}

}
else
Window window = Platform.CurrentActivity?.Window ?? throw new InvalidOperationException("Current activity is null");
View decorView = window.DecorView ?? throw new InvalidOperationException("DecorView is null");
AndroidX.Core.View.WindowInsetsControllerCompat insetsController = WindowCompat.GetInsetsController(window, decorView) ?? throw new InvalidOperationException("InsetsController is null");
Comment on lines +142 to +144
Copy link

Copilot AI Nov 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variables window, decorView, and insetsController are declared with explicit types instead of using var. According to the .NET Foundation coding style guidelines followed by this project, local variables should use var when the type is obvious from the right-hand side. Consider changing to:

var window = Platform.CurrentActivity?.Window ?? throw new InvalidOperationException("Current activity is null");
var decorView = window.DecorView ?? throw new InvalidOperationException("DecorView is null");
var insetsController = WindowCompat.GetInsetsController(window, decorView) ?? throw new InvalidOperationException("InsetsController is null");
Suggested change
Window window = Platform.CurrentActivity?.Window ?? throw new InvalidOperationException("Current activity is null");
View decorView = window.DecorView ?? throw new InvalidOperationException("DecorView is null");
AndroidX.Core.View.WindowInsetsControllerCompat insetsController = WindowCompat.GetInsetsController(window, decorView) ?? throw new InvalidOperationException("InsetsController is null");
var window = Platform.CurrentActivity?.Window ?? throw new InvalidOperationException("Current activity is null");
var decorView = window.DecorView ?? throw new InvalidOperationException("DecorView is null");
var insetsController = WindowCompat.GetInsetsController(window, decorView) ?? throw new InvalidOperationException("InsetsController is null");

Copilot uses AI. Check for mistakes.
Comment on lines +142 to +144
Copy link

Copilot AI Nov 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new implementation creates window/decorView/insetsController variables on every call to SetStatusBarsHidden, which is inefficient compared to the previous approach that cached these references. Since this method is called from OnVisibilityChanged (which can be triggered frequently) and OnFullscreenButtonClick, consider caching these references to avoid repeated lookups and object creation on each call.

Copilot uses AI. Check for mistakes.
if (OperatingSystem.IsAndroidVersionAtLeast(26))
{
if (OperatingSystem.IsAndroidVersionAtLeast(30))
if (hidden)
{
if (isSystemBarVisible)
{
currentWindow.InsetsController?.Show(WindowInsets.Type.SystemBars());
}
window.ClearFlags(WindowManagerFlags.LayoutNoLimits);
window.SetFlags(WindowManagerFlags.Fullscreen, WindowManagerFlags.Fullscreen);
insetsController.SystemBarsBehavior = WindowInsetsControllerCompat.BehaviorShowTransientBarsBySwipe;
insetsController.Hide(WindowInsetsCompat.Type.SystemBars());
}
else
{
currentWindow.DecorView.SystemUiFlags = (SystemUiFlags)defaultSystemUiVisibility;
}

if (windowInsetsControllerCompat is not null)
{
windowInsetsControllerCompat.Show(barTypes);
windowInsetsControllerCompat.SystemBarsBehavior = WindowInsetsControllerCompat.BehaviorDefault;
window.ClearFlags(WindowManagerFlags.Fullscreen);
window.SetFlags(WindowManagerFlags.DrawsSystemBarBackgrounds, WindowManagerFlags.DrawsSystemBarBackgrounds);
insetsController.SystemBarsBehavior = WindowInsetsControllerCompat.BehaviorDefault;
insetsController.Show(WindowInsetsCompat.Type.SystemBars());
}
Comment on lines +140 to 160
Copy link

Copilot AI Nov 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The removal of WindowCompat.SetDecorFitsSystemWindows may cause layout issues. The previous implementation correctly managed whether the window content should fit within the system windows (status bar, navigation bar). Without this call:

  • In fullscreen mode, content may not properly extend behind system bars
  • When exiting fullscreen, the layout may not properly account for system bar insets

Other parts of the codebase (e.g., StatusBar.android.cs) still use WindowCompat.SetDecorFitsSystemWindows(window, true/false) to manage this behavior. Consider adding back:

if (hidden)
{
    WindowCompat.SetDecorFitsSystemWindows(window, false);
    // ... existing code
}
else
{
    // ... existing code
    WindowCompat.SetDecorFitsSystemWindows(window, true);
}

Copilot uses AI. Check for mistakes.

WindowCompat.SetDecorFitsSystemWindows(currentWindow, true);
}
Comment on lines +145 to 161
Copy link

Copilot AI Nov 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The version check OperatingSystem.IsAndroidVersionAtLeast(26) wraps all the logic, but the PR description states the code supports Android API 26+. If this is the minimum supported Android version for the entire library, this check is redundant since the code inside would always execute. If API 26 is not the minimum, consider what behavior should occur when running on versions below API 26 - currently, the method would silently do nothing, which could leave the app in an inconsistent state.

Copilot uses AI. Check for mistakes.
Comment on lines +145 to 161
Copy link

Copilot AI Nov 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The API version check for Android 26 is redundant since the project's SupportedOSPlatformVersion for Android is already set to 26.0 in the .csproj file. This means the app cannot run on Android versions below API 26, so the runtime check adds no value and should be removed. Simply execute the code in the if (hidden) and else blocks directly without the version check wrapper.

Copilot uses AI. Check for mistakes.
}

Expand Down
Loading