Skip to content
Merged
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
16 changes: 9 additions & 7 deletions backend/FwLite/FwLiteMaui/App.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
using FwLiteShared.Services;

namespace FwLiteMaui;

public partial class App : Application
{
public IServiceProvider ServiceProvider { get; }
private readonly MainPage _mainPage;
public static string? OverrideStartupUrl { get; set; }

public App(MainPage mainPage, IPreferencesService preferences)
public App(MainPage mainPage, IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
_mainPage = mainPage;
var lastUrl = preferences.Get(nameof(PreferenceKey.AppLastUrl));
if (lastUrl?.StartsWith('/') == true)
{
mainPage.StartPath = lastUrl;
}
InitializeComponent();
}

internal void LoadAppUrl(string url)
{
_mainPage.LoadAppUrl(url);
}

protected override Window CreateWindow(IActivationState? activationState)
{
return CreateWindow(_mainPage);
Expand Down
44 changes: 39 additions & 5 deletions backend/FwLite/FwLiteMaui/MainPage.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,28 +1,62 @@
using FwLiteShared.Services;
using Microsoft.AspNetCore.Components.WebView;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.JSInterop;

namespace FwLiteMaui;

public partial class MainPage : ContentPage
{
public MainPage()
private readonly ILogger<MainPage> _logger;

public MainPage(IPreferencesService preferences, ILogger<MainPage> logger)
{
_logger = logger;
InitializeComponent();
var lastUrlFromPrefs = preferences.Get(nameof(PreferenceKey.AppLastUrl));
blazorWebView.BlazorWebViewInitializing += BlazorWebViewInitializing;
blazorWebView.BlazorWebViewInitialized += BlazorWebViewInitialized;
blazorWebView.BlazorWebViewInitialized += (s, e) =>
{
// Decide initial StartPath here (after Android intent is processed) to avoid cold-start race
var initial = App.OverrideStartupUrl ?? lastUrlFromPrefs ?? "/";
//only change it if it's still the default, might have been changed already, for example when opening a new window
if (blazorWebView.StartPath == "/")
blazorWebView.StartPath = initial;
App.OverrideStartupUrl = null;
};
blazorWebView.UrlLoading += BlazorWebViewOnUrlLoading;
}



internal string StartPath
{
get => blazorWebView.StartPath;
set => blazorWebView.StartPath = value;
}

internal void LoadAppUrl(string url)
{
blazorWebView.StartPath = url;
_ = blazorWebView.TryDispatchAsync(services =>
{
var jsRuntime = services.GetService<IJSRuntime>();
if (jsRuntime != null)
_ = NavigateAsync(jsRuntime, url);
});
}

private async Task NavigateAsync(IJSRuntime jsRuntime, string url)
{
try
{
await jsRuntime.InvokeVoidAsync("lexbox.SvelteNavigate", url, new { replace = true });
}
catch (Exception e)
{
_logger.LogError(e, "Failed to navigate to {Url} via SvelteNavigate", url);
}
}

#if ANDROID || WINDOWS
private partial void BlazorWebViewInitializing(object? sender, BlazorWebViewInitializingEventArgs e);
private partial void BlazorWebViewInitialized(object? sender, BlazorWebViewInitializedEventArgs e);
Expand Down
36 changes: 36 additions & 0 deletions backend/FwLite/FwLiteMaui/MauiProgram.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using FwLiteShared.Services;
using Microsoft.Extensions.Logging;
using Microsoft.Maui.LifecycleEvents;

Expand Down Expand Up @@ -52,6 +53,41 @@ public static MauiApp CreateMauiApp()
builder.ConfigureEssentials(essentialsBuilder =>
{
essentialsBuilder.UseVersionTracking();

// Register all shortcuts from a single central place
foreach (var action in Shortcuts.Declarations)
{
essentialsBuilder.AddAppAction(action);
}

essentialsBuilder.OnAppAction(action =>
{
var app = (App?)Application.Current;
if (app is null) return;
if (Shortcuts.TryGetUrl(action.Id, out var url))
{
app.Dispatcher.Dispatch(() =>
{
app.LoadAppUrl(url);
});
}
else if (action.Id == Shortcuts.ShareLogOut)
{
_ = app.Dispatcher.DispatchAsync(async () =>
{
try
{
await app.ServiceProvider.GetRequiredService<ITroubleshootingService>()
.ShareLogFile();
}
catch (Exception e)
{
app.ServiceProvider.GetService<ILogger<App>>()?
.LogError(e, "Failed to share log file from app action");
}
});
}
});
});
builder.Services.AddFwLiteMauiServices(builder.Configuration, builder.Logging);

Expand Down
25 changes: 25 additions & 0 deletions backend/FwLite/FwLiteMaui/Platforms/Android/MainActivity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,41 @@ namespace FwLiteMaui;
[Activity(Theme = "@style/Maui.SplashTheme",
MainLauncher = true,
LaunchMode = LaunchMode.SingleTop,
ResizeableActivity = true,
ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode |
ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
[IntentFilter([Platform.Intent.ActionAppAction],
Categories = [Intent.CategoryDefault])]
public class MainActivity : MauiAppCompatActivity
{
protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState);

if (Intent?.Action == Platform.Intent.ActionAppAction)
{
//name comes from internal maui code: https://github.com/dotnet/maui/blob/271d2505eb436600bb84002c8941670abb0ae23b/src/Essentials/src/AppActions/AppActions.android.cs#L83
var actionId = Intent.GetStringExtra("EXTRA_XE_APP_ACTION_ID");
if (Shortcuts.TryGetUrl(actionId, out var url))
{
App.OverrideStartupUrl = url;
}
}

ApplyBrandedSystemBars();
}

protected override void OnResume()
{
base.OnResume();
Platform.OnResume(this);
}

protected override void OnNewIntent(Intent? intent)
{
base.OnNewIntent(intent);
Platform.OnNewIntent(intent);
}
public override void OnConfigurationChanged(Configuration newConfig)
{
base.OnConfigurationChanged(newConfig);
Expand Down
35 changes: 35 additions & 0 deletions backend/FwLite/FwLiteMaui/Shortcuts.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
namespace FwLiteMaui;

public static class Shortcuts
{
public const string Home = "home";
public const string ShareLogOut = "share-log-out";

private static readonly IReadOnlyDictionary<string, string> IdToUrl = new Dictionary<string, string>
{
[Home] = "/",
};

// Titles/subtitles shown in the system UI (if supported)
public static readonly IReadOnlyList<AppAction> Declarations =
[
new(Home, "Home"),
new(ShareLogOut, "Share Debug Log"),
];

public static bool TryGetUrl(string? id, out string url)
{
if (id is null)
{
url = string.Empty;
return false;
}
if (IdToUrl.TryGetValue(id, out var found))
{
url = found;
return true;
}
url = string.Empty;
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ static int Fail(string message)
if (cctor is null || !cctor.HasBody)
return Fail("SqlTransparentExpression .cctor not found (or has no body).");

if (cctor.Body.Instructions.Count == 1 && cctor.Body.Instructions[0].OpCode == OpCodes.Ret)
{
Console.WriteLine($"Already patched (inferred from IL): {dllPath}");
File.WriteAllText(markerPath, DateTime.UtcNow.ToString("O"));
return 0;
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

// Sanity-check the cctor shape: at least one stsfld targeting the _ctor field.
// If upstream renames _ctor or restructures the field init, we want to know.
var storesCtorField = cctor.Body.Instructions.Any(ins =>
Expand Down
2 changes: 2 additions & 0 deletions frontend/viewer/src/lib/services/service-declaration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ declare global {
ServiceProvider: LexboxServiceProvider;
Search: { openSearch: (search: string) => void };
IsDotnetHosted?: boolean;
// Expose svelte-routing navigate for native hosts (MAUI) and other integrations
SvelteNavigate?: (url: string, options?: { replace?: boolean }) => void;
/* eslint-enable @typescript-eslint/naming-convention */
}

Expand Down
4 changes: 4 additions & 0 deletions frontend/viewer/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import '@formatjs/intl-durationformat/polyfill';

import App from './App.svelte';
import {mount} from 'svelte';
import {navigate} from 'svelte-routing';
import {setupDotnetServiceProvider} from './lib/services/service-provider-dotnet';
import {setupServiceProvider} from '$lib/services/service-provider';
import {setupBrowserAppServices} from '$lib/services/browser-app-services';
Expand All @@ -20,6 +21,9 @@ if (!window.lexbox.IsDotnetHosted) {
}
useEventBus();

// Wire up globally-accessible helpers for hosts (e.g., MAUI)
window.lexbox.SvelteNavigate = (url: string, options?: { replace?: boolean }) => navigate(url, options);

//don't mount the app until after we've loaded the local
void setLanguage('default')
.then(() => {
Expand Down
Loading