From 74ca7e4638ec1fb7b13f9a01f7a254c62d65ee8e Mon Sep 17 00:00:00 2001 From: keyldev Date: Wed, 1 Jul 2026 22:37:43 +0300 Subject: [PATCH 1/2] fix(mobile): engage camera-page responsive layout on Loaded - ApplyResponsiveLayout now runs on Loaded (+ deterministic mobile fallback when width unmeasured), not only on SizeChanged, so the page reliably switches to the scrollable phone layout and the Majestic panel below the video is reachable --- .../Views/Pages/SingleCameraPage.axaml.cs | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/OpenIPC.Viewer.App/Views/Pages/SingleCameraPage.axaml.cs b/src/OpenIPC.Viewer.App/Views/Pages/SingleCameraPage.axaml.cs index f476e03..ba1acc9 100644 --- a/src/OpenIPC.Viewer.App/Views/Pages/SingleCameraPage.axaml.cs +++ b/src/OpenIPC.Viewer.App/Views/Pages/SingleCameraPage.axaml.cs @@ -56,16 +56,24 @@ public SingleCameraPage() // panel, and a Grid alone would just run the panel off the bottom. Switch the // video row to a fixed 16:9 preview and let PageScroll scroll; on wider // viewports keep the fill layout (star row, scrolling disabled). - private void OnPageSizeChanged(object? sender, SizeChangedEventArgs e) + private void OnPageSizeChanged(object? sender, SizeChangedEventArgs e) => + ApplyResponsiveLayout(e.NewSize.Width); + + private void ApplyResponsiveLayout(double width) { - var width = e.NewSize.Width; + // Width can be 0 before the first arrange (e.g. when called from Loaded). + // A mobile head is always a phone-width viewport, so fall back to the + // mobile layout there — this guarantees the page scrolls and the Majestic + // panel below the video is reachable even if SizeChanged hasn't fired yet. if (width <= 0) - return; + width = OpenIPC.Viewer.App.Services.OverlayDialogPresenter.IsMobile ? 400 : 1000; var videoRow = RootGrid.RowDefinitions[1]; if (width < MobileBreakpoint) { - videoRow.Height = new GridLength(System.Math.Round(width * 9.0 / 16.0)); + var videoHeight = System.Math.Round(width * 9.0 / 16.0); + if (videoHeight < 160) videoHeight = 200; // sane floor before real measure + videoRow.Height = new GridLength(videoHeight); PageScroll.VerticalScrollBarVisibility = Avalonia.Controls.Primitives.ScrollBarVisibility.Auto; } else @@ -89,6 +97,11 @@ private async void OnTalkReleased(object? sender, PointerEventArgs e) private async void OnLoaded(object? sender, RoutedEventArgs e) { + // Engage the responsive layout up front — SizeChanged only fires on a + // change, which on some Android layouts may not happen before the page + // is shown, leaving it in the desktop (fill, no-scroll) state. + ApplyResponsiveLayout(Bounds.Width); + if (Vm is { } vm) await vm.ActivateAsync(CancellationToken.None); } From 38124316e5d12bc2606cce515d612558d992f19b Mon Sep 17 00:00:00 2001 From: keyldev Date: Wed, 1 Jul 2026 22:46:44 +0300 Subject: [PATCH 2/2] fix(android): allow cleartext HTTP (Majestic panel + snapshots dead on-device) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - targetSdk 36 blocks cleartext http:// by default, silently killing every camera HTTP call on Android (Majestic config.json never loaded, image.jpg snapshots failed) while RTSP video still worked. Cameras are LAN devices with no TLS → usesCleartextTraffic=true. --- .../Properties/AndroidManifest.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/OpenIPC.Viewer.Android/Properties/AndroidManifest.xml b/src/OpenIPC.Viewer.Android/Properties/AndroidManifest.xml index f6990a3..8c342c3 100644 --- a/src/OpenIPC.Viewer.Android/Properties/AndroidManifest.xml +++ b/src/OpenIPC.Viewer.Android/Properties/AndroidManifest.xml @@ -22,7 +22,14 @@ android:roundIcon="@mipmap/icon" android:allowBackup="true" android:supportsRtl="true" - android:name=".MainApplication"> + android:name=".MainApplication" + android:usesCleartextTraffic="true"> +