Skip to content
Open
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
6 changes: 6 additions & 0 deletions Valour/Client.Maui/Platforms/Android/MainActivity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ protected override void OnResume()
AppLifecycle.NotifyResumed();
}

protected override void OnPause()
{
base.OnPause();
AppLifecycle.NotifyBackground();
}

protected override void OnActivityResult(int requestCode, Result resultCode, Intent? data)
{
if (requestCode == AudioPermissionChromeClient.FileChooserRequestCode)
Expand Down
15 changes: 14 additions & 1 deletion Valour/Client.Maui/Platforms/MacCatalyst/AppDelegate.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
using Foundation;
using Foundation;
using UIKit;

namespace Valour.Client.Maui;

[Register("AppDelegate")]
public class AppDelegate : MauiUIApplicationDelegate
{
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();

public override void DidEnterBackground(UIApplication application)
{
base.DidEnterBackground(application);
AppLifecycle.NotifyBackground();
}

public override void OnActivated(UIApplication application)
{
base.OnActivated(application);
AppLifecycle.NotifyResumed();
}
}
15 changes: 14 additions & 1 deletion Valour/Client.Maui/Platforms/iOS/AppDelegate.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
using Foundation;
using Foundation;
using UIKit;

namespace Valour.Client.Maui;

[Register("AppDelegate")]
public class AppDelegate : MauiUIApplicationDelegate
{
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();

public override void DidEnterBackground(UIApplication application)
{
base.DidEnterBackground(application);
AppLifecycle.NotifyBackground();
}

public override void OnActivated(UIApplication application)
{
base.OnActivated(application);
AppLifecycle.NotifyResumed();
}
}
52 changes: 27 additions & 25 deletions Valour/Client/AppLifecycle.cs
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
namespace Valour.Client;

/// <summary>
/// Static event bridge for native app lifecycle events (e.g. Android OnResume)
/// that need to reach Blazor components.
/// </summary>
public static class AppLifecycle
{
public static event Action? Resumed;

/// <summary>
/// Fired when a voice call begins. Platform projects can subscribe to start
/// keep-alive mechanisms (e.g. Android foreground service).
/// </summary>
public static event Action? CallStarted;

/// <summary>
/// Fired when a voice call ends.
/// </summary>
public static event Action? CallEnded;

public static void NotifyResumed() => Resumed?.Invoke();
public static void NotifyCallStarted() => CallStarted?.Invoke();
public static void NotifyCallEnded() => CallEnded?.Invoke();
}
namespace Valour.Client;

/// <summary>
/// Static event bridge for native app lifecycle events (e.g. Android OnResume)
/// that need to reach Blazor components.
/// </summary>
public static class AppLifecycle
{
public static event Action? Resumed;
public static event Action? Backgrounded;

/// <summary>
/// Fired when a voice call begins. Platform projects can subscribe to start
/// keep-alive mechanisms (e.g. Android foreground service).
/// </summary>
public static event Action? CallStarted;

/// <summary>
/// Fired when a voice call ends.
/// </summary>
public static event Action? CallEnded;

public static void NotifyResumed() => Resumed?.Invoke();
public static void NotifyBackground() => Backgrounded?.Invoke();
public static void NotifyCallStarted() => CallStarted?.Invoke();
public static void NotifyCallEnded() => CallEnded?.Invoke();
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@inherits WindowContentComponent<Channel>
@inherits WindowContentComponent<Channel>
@implements IAsyncDisposable
@inject IJSRuntime JsRuntime
@inject ValourClient Client
Expand Down Expand Up @@ -1258,6 +1258,27 @@
{
await InvokeAsync(async () =>
{
// Wait for the relevant node to finish reconnecting before we attempt recovery.
// On mobile resume, CheckConnections() is fired by BrowserUtils.OnRefocus but
// the SignalR reconnection is async. If we recover too early, we'll fetch stale
// data and miss messages that arrived during the reconnection gap.
var node = Channel?.PlanetId is not null
? Channel.Planet?.Node
: Client.PrimaryNode;

if (node?.IsReconnecting == true)
{
// Give the reconnect up to 5 seconds before proceeding anyway.
for (var i = 0; i < 50 && node.IsReconnecting; i++)
await Task.Delay(100);

if (node.IsReconnecting)
{
Client.Logger.Log<ChatWindowComponent>(
"Node still reconnecting after focus; attempting message recovery anyway.", "yellow");
}
}

if (Channel?.PlanetId is not null && Channel.ChannelType == ChannelTypeEnum.PlanetChat)
{
try
Expand Down