Skip to content
Closed
Show file tree
Hide file tree
Changes from all 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
34 changes: 27 additions & 7 deletions JournalApp/Data/PreferenceService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public PreferenceService(ILogger<PreferenceService> logger, IPreferences prefere
_application.RequestedThemeChanged += Application_RequestedThemeChanged;
}

UpdateStatusBar();
UpdateSystemBars();
}

public AppTheme SelectedAppTheme
Expand Down Expand Up @@ -188,20 +188,40 @@ private void Application_RequestedThemeChanged(object sender, AppThemeChangedEve

private void OnThemeChanged()
{
UpdateStatusBar();
UpdateSystemBars();
ThemeChanged?.Invoke(this, IsDarkMode);
}

private void UpdateStatusBar()
private void UpdateSystemBars()
{
if (OperatingSystem.IsAndroid())
var surface = IsDarkMode ? GetTheme().PaletteDark.Background : GetTheme().PaletteLight.Background;

// The page shows through the safe area padding around the web view, so match it to the M3 surface tone for seamless bars.
if (App.Window?.Page is not null)
App.Window.Page.BackgroundColor = Color.FromRgb(surface.R, surface.G, surface.B);

#if ANDROID
logger.LogDebug("Updating system bars");

// Edge-to-edge bars are transparent overlays so icon contrast is the only knob on Android 15+.
var window = Platform.CurrentActivity?.Window;
if (window is not null)
{
var controller = AndroidX.Core.View.WindowCompat.GetInsetsController(window, window.DecorView);
controller.AppearanceLightStatusBars = !IsDarkMode;
controller.AppearanceLightNavigationBars = !IsDarkMode;
}

// Older versions still draw opaque bars so tint them to the M3 surface tone to blend into the page.
if (!OperatingSystem.IsAndroidVersionAtLeast(35))
{
logger.LogDebug("Updating status bar");
// Match the M3 surface tone so the status bar blends into the page header.
var surface = IsDarkMode ? GetTheme().PaletteDark.Background : GetTheme().PaletteLight.Background;
StatusBar.SetColor(Color.FromRgb(surface.R, surface.G, surface.B));
StatusBar.SetStyle(IsDarkMode ? StatusBarStyle.LightContent : StatusBarStyle.DarkContent);
#pragma warning disable CA1422 // Deprecated in API 35 which the surrounding check excludes.
window?.SetNavigationBarColor(Android.Graphics.Color.Rgb(surface.R, surface.G, surface.B));
#pragma warning restore CA1422
}
#endif
}

public string GetMoodColor(string emoji)
Expand Down
2 changes: 1 addition & 1 deletion JournalApp/MainPage.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace JournalApp;
namespace JournalApp;

public partial class MainPage : ContentPage
{
Expand Down
50 changes: 20 additions & 30 deletions JournalApp/wwwroot/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@
-webkit-tap-highlight-color: transparent;
}

/* Safe area insets are zero while the native page letterboxes the web view, but flow in via env() on WebViews that support it if edge-to-edge is ever enabled. */
:root {
--inset-top: env(safe-area-inset-top, 0px);
--inset-right: env(safe-area-inset-right, 0px);
--inset-bottom: env(safe-area-inset-bottom, 0px);
--inset-left: env(safe-area-inset-left, 0px);
}

body {
user-select: none;
--mud-palette-action-default: var(--mud-palette-text-primary);
Expand Down Expand Up @@ -71,24 +79,31 @@ body {
font-weight: 400;
}

/* The sticky header absorbs the top inset so the transparent status bar always sits on the app bar surface. */
.page-header {
z-index: var(--mud-zindex-appbar);
display: flex;
flex-direction: column;
padding: 0 !important;
padding-top: var(--inset-top) !important;
padding-left: var(--inset-left) !important;
padding-right: var(--inset-right) !important;
margin: 0 !important;
top: 0 !important;
position: sticky !important;
background-color: var(--mud-palette-background);
color: var(--mud-palette-text-primary);
}

/* The bottom inset keeps the last rows reachable while content scrolls under the transparent gesture bar. */
.page-body {
width: 100%;
max-width: 960px;
margin: 0 auto !important;
padding: 8px !important;
padding-bottom: 15vh !important;
padding-left: calc(8px + var(--inset-left)) !important;
padding-right: calc(8px + var(--inset-right)) !important;
padding-bottom: calc(15vh + var(--inset-bottom)) !important;
animation: fadeInUp 0.15s ease-out;
}

Expand Down Expand Up @@ -399,38 +414,13 @@ label.mud-switch.mud-disabled .mud-switch-span {
display: none;
left: 0;
padding: 1.25rem;
padding-bottom: calc(1.25rem + var(--inset-bottom));
position: fixed;
width: 100%;
z-index: 1000;
}

.status-bar-safe-area {
display: none;
}

@supports (-webkit-touch-callout: none) {
.status-bar-safe-area {
display: flex;
position: sticky;
top: 0;
height: env(safe-area-inset-top);
width: 100%;
z-index: 1;
}

.flex-column, .navbar-brand {
padding-left: env(safe-area-inset-left);
}
}

@media (prefers-color-scheme: dark) {
.status-bar-safe-area {
background-color: #181215;
}
}

@media (prefers-color-scheme: light) {
.status-bar-safe-area {
background-color: #FFF8F9;
}
/* Snackbars float above the gesture bar instead of under it. */
#mud-snackbar-container.mud-snackbar-location-bottom-center {
bottom: calc(24px + var(--inset-bottom));
}
2 changes: 0 additions & 2 deletions JournalApp/wwwroot/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@

<body>

<div class="status-bar-safe-area"></div>

<div id="app">
<div id="splash-screen">
<p id="loading-text">Getting things ready...</p>
Expand Down
Loading