mirror of
https://github.com/awatertrevi/xamarin-neo4j.git
synced 2026-09-22 09:05:29 +00:00
Compare commits
4 Commits
adding-and
...
obfuscate-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fb361f0f4c | ||
|
|
927e7627a6 | ||
|
|
14d755f8bb | ||
|
|
fb504a88c2 |
1
.github/workflows/deploy-playstore.yml
vendored
1
.github/workflows/deploy-playstore.yml
vendored
@@ -67,4 +67,5 @@ jobs:
|
|||||||
releaseFiles: Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.Android/bin/Release/net10.0-android/publish/*-Signed.aab
|
releaseFiles: Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.Android/bin/Release/net10.0-android/publish/*-Signed.aab
|
||||||
track: internal
|
track: internal
|
||||||
status: completed
|
status: completed
|
||||||
|
changesNotSentForReview: true
|
||||||
whatsNewDirectory: Xamarin.Neo4j/distribution/whatsnew
|
whatsNewDirectory: Xamarin.Neo4j/distribution/whatsnew
|
||||||
|
|||||||
30
README.md
30
README.md
@@ -50,6 +50,36 @@ dotnet test Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.Tests/
|
|||||||
dotnet test Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.IntegrationTests/
|
dotnet test Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.IntegrationTests/
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Android DEX shrinking & obfuscation (R8)
|
||||||
|
|
||||||
|
Release builds of the Android head run R8 over the Java/DEX side
|
||||||
|
(`AndroidLinkTool=r8` in `Xamarin.Neo4j.Android.csproj`). Play Console's *DEX code
|
||||||
|
optimization* report scores obfuscation at ~1% on a stock .NET MAUI build: .NET for
|
||||||
|
Android runs no DEX shrinker by default, and even with R8 on, the ProGuard config the
|
||||||
|
SDK generates hardcodes `-dontobfuscate` — a flag nothing later in the config list can
|
||||||
|
undo. The `_AndroidObfuscateDex` target therefore drops that file from R8's `--pg-conf`
|
||||||
|
list and substitutes `Xamarin.Neo4j.Android/proguard_xamarin.cfg` (the same file minus
|
||||||
|
that line), plus a generated file carrying the `-printmapping`/`-keepattributes` tail
|
||||||
|
the SDK would have appended. Measured on the Release APK: **49.8% of DEX classes
|
||||||
|
renamed, up from ~0%**.
|
||||||
|
|
||||||
|
Only library-internal classes are renamed: the trimmer emits a `-keep` rule for every
|
||||||
|
Java type the managed bindings reference, aapt2 one for every class named in a layout
|
||||||
|
or the manifest, and each Android Callable Wrapper gets its own.
|
||||||
|
`Xamarin.Neo4j.Android/proguard.cfg` covers what those miss — things resolved by name
|
||||||
|
from native code. Add to it if a Release build dies with `ClassNotFoundException`,
|
||||||
|
`NoSuchFieldError` or `NoSuchMethodError` where a Debug build does not.
|
||||||
|
|
||||||
|
`mapping.txt` is embedded in the AAB
|
||||||
|
(`BUNDLE-METADATA/com.android.tools.build.obfuscation/proguard.map`), so Play Console
|
||||||
|
retraces obfuscated Java stacks by itself. Managed (C#) stack traces are unaffected —
|
||||||
|
R8 only touches DEX.
|
||||||
|
|
||||||
|
Local Release builds must be clean: aapt2's keep rules are registered as a `FileWrite`,
|
||||||
|
so an incremental build that skips the resource link has `IncrementalClean` delete them.
|
||||||
|
The target caches a copy outside `FileWrites` and errors out if even that is missing —
|
||||||
|
delete `Xamarin.Neo4j.Android/obj/Release` if it fires.
|
||||||
|
|
||||||
## Technology Stack
|
## Technology Stack
|
||||||
|
|
||||||
- .NET MAUI
|
- .NET MAUI
|
||||||
|
|||||||
@@ -38,7 +38,9 @@ namespace Xamarin.Neo4j.Android
|
|||||||
var statusBarColor = isDark
|
var statusBarColor = isDark
|
||||||
? AColor.ParseColor("#0c0c0c")
|
? AColor.ParseColor("#0c0c0c")
|
||||||
: AColor.ParseColor("#f5f5f5");
|
: AColor.ParseColor("#f5f5f5");
|
||||||
|
#pragma warning disable CA1422
|
||||||
Window.SetStatusBarColor(statusBarColor);
|
Window.SetStatusBarColor(statusBarColor);
|
||||||
|
#pragma warning restore CA1422
|
||||||
|
|
||||||
var controller = new WindowInsetsControllerCompat(Window, Window.DecorView);
|
var controller = new WindowInsetsControllerCompat(Window, Window.DecorView);
|
||||||
controller.AppearanceLightStatusBars = !isDark;
|
controller.AppearanceLightStatusBars = !isDark;
|
||||||
@@ -58,7 +60,7 @@ namespace Xamarin.Neo4j.Android
|
|||||||
|
|
||||||
// MAUI creates its toolbar programmatically so theme-based tinting doesn't reach
|
// MAUI creates its toolbar programmatically so theme-based tinting doesn't reach
|
||||||
// the overflow icon. Walk the view tree and apply the tint directly.
|
// the overflow icon. Walk the view tree and apply the tint directly.
|
||||||
private static void TintToolbarIcons(ViewGroup? parent)
|
private static void TintToolbarIcons(ViewGroup parent)
|
||||||
{
|
{
|
||||||
if (parent == null) return;
|
if (parent == null) return;
|
||||||
for (var i = 0; i < parent.ChildCount; i++)
|
for (var i = 0; i < parent.ChildCount; i++)
|
||||||
|
|||||||
@@ -22,11 +22,11 @@ namespace Xamarin.Neo4j.Android.Services
|
|||||||
{
|
{
|
||||||
var context = global::Android.App.Application.Context;
|
var context = global::Android.App.Application.Context;
|
||||||
var info = context.PackageManager.GetPackageInfo(context.PackageName, 0);
|
var info = context.PackageManager.GetPackageInfo(context.PackageName, 0);
|
||||||
#pragma warning disable CS0618
|
#pragma warning disable CS0618, CA1416, CA1422
|
||||||
return Build.VERSION.SdkInt >= BuildVersionCodes.P
|
return Build.VERSION.SdkInt >= BuildVersionCodes.P
|
||||||
? info.LongVersionCode.ToString()
|
? info.LongVersionCode.ToString()
|
||||||
: info.VersionCode.ToString();
|
: info.VersionCode.ToString();
|
||||||
#pragma warning restore CS0618
|
#pragma warning restore CS0618, CA1416, CA1422
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,4 +53,56 @@
|
|||||||
<ProjectReference Include="..\Xamarin.Neo4j\Xamarin.Neo4j.csproj" />
|
<ProjectReference Include="..\Xamarin.Neo4j\Xamarin.Neo4j.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<!-- Android Release: shrink and obfuscate the Java/DEX half of the app with
|
||||||
|
R8. .NET for Android runs no DEX shrinker by default, so Play Console's
|
||||||
|
"DEX code optimization" report scores obfuscation at ~1%. The trimmer emits
|
||||||
|
a keep rule for every Java type the managed bindings reference
|
||||||
|
(obj/.../proguard/proguard_project_references.cfg), aapt2 one for every
|
||||||
|
class named in a layout, and each Android Callable Wrapper gets its own,
|
||||||
|
so only library-internal classes are renamed. -->
|
||||||
|
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
|
||||||
|
<AndroidLinkTool>r8</AndroidLinkTool>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProguardConfiguration Include="proguard.cfg" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<!-- Swap the SDK's generated proguard_xamarin.cfg (which hardcodes
|
||||||
|
-dontobfuscate, a flag nothing later in the config list can undo) for our
|
||||||
|
copy without it, and regenerate the -printmapping/-keepattributes tail the
|
||||||
|
SDK appends to that same file so crash stacks stay retraceable. -->
|
||||||
|
<Target Name="_AndroidObfuscateDex" AfterTargets="_CalculateProguardConfigurationFiles" Condition="'$(AndroidLinkTool)' == 'r8'">
|
||||||
|
<PropertyGroup>
|
||||||
|
<_AndroidObfuscationProguardConfig>$(IntermediateOutputPath)proguard\proguard_obfuscate.cfg</_AndroidObfuscationProguardConfig>
|
||||||
|
<_AndroidAaptProguardRules>$(IntermediateOutputPath)proguard\aapt_rules.cached.txt</_AndroidAaptProguardRules>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<_AndroidObfuscationProguardLines Include="-ignorewarnings" Condition="'$(AndroidR8IgnoreWarnings)' == 'True'" />
|
||||||
|
<_AndroidObfuscationProguardLines Include="-keepattributes SourceFile" />
|
||||||
|
<_AndroidObfuscationProguardLines Include="-keepattributes LineNumberTable" />
|
||||||
|
<!-- Absolute: R8 resolves a relative -printmapping against the directory
|
||||||
|
of the config file that declares it, not the working directory. -->
|
||||||
|
<_AndroidObfuscationProguardLines Include="-printmapping "$([System.IO.Path]::Combine('$(MSBuildProjectDirectory)', '$(AndroidProguardMappingFile)'))"" Condition="'$(AndroidProguardMappingFile)' != ''" />
|
||||||
|
</ItemGroup>
|
||||||
|
<MakeDir Directories="$(IntermediateOutputPath)proguard" />
|
||||||
|
<WriteLinesToFile File="$(_AndroidObfuscationProguardConfig)" Lines="@(_AndroidObfuscationProguardLines)" Overwrite="true" WriteOnlyWhenDifferent="true" />
|
||||||
|
<!-- aapt2 derives keep rules for every class named in a layout or the
|
||||||
|
manifest, but the SDK adds them to @(ProguardConfiguration) inside
|
||||||
|
_CreateBaseApkWithAapt2 and registers the file as a FileWrite, so an
|
||||||
|
incremental Release build that skips the resource link both loses the
|
||||||
|
item and has IncrementalClean delete the file, shipping an APK that
|
||||||
|
dies inflating androidx.appcompat.widget.FitWindowsFrameLayout. Keep a
|
||||||
|
copy outside FileWrites and feed R8 that one instead. -->
|
||||||
|
<Copy SourceFiles="$(IntermediateOutputPath)aapt_rules.txt" DestinationFiles="$(_AndroidAaptProguardRules)" SkipUnchangedFiles="true" Condition="Exists('$(IntermediateOutputPath)aapt_rules.txt')" />
|
||||||
|
<Error Condition="!Exists('$(_AndroidAaptProguardRules)')" Text="R8 is enabled but no aapt2 keep rules are available: delete obj\$(Configuration) and publish again to force a full resource link." />
|
||||||
|
<ItemGroup>
|
||||||
|
<_ProguardConfiguration Remove="$(IntermediateOutputPath)proguard\proguard_xamarin.cfg" />
|
||||||
|
<_ProguardConfiguration Remove="$(IntermediateOutputPath)aapt_rules.txt" />
|
||||||
|
<_ProguardConfiguration Include="$(MSBuildProjectDirectory)\proguard_xamarin.cfg" />
|
||||||
|
<_ProguardConfiguration Include="$(_AndroidObfuscationProguardConfig)" />
|
||||||
|
<_ProguardConfiguration Include="$(_AndroidAaptProguardRules)" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# App-level R8 keep rules, on top of the ones .NET for Android generates
|
||||||
|
# (see proguard_xamarin.cfg and the _AndroidObfuscateDex target in the csproj).
|
||||||
|
|
||||||
|
# The .NET runtime resolves this one by name from native code -- no DEX
|
||||||
|
# reference points at it, so R8 renames it and startup dies with
|
||||||
|
# "ClassNotFoundException: net.dot.android.ApplicationRegistration".
|
||||||
|
# The SDK's own config only covers net.dot.jni.** and net.dot.android.crypto.**,
|
||||||
|
# because upstream never obfuscates.
|
||||||
|
-keep class net.dot.android.** { *; <init>(...); }
|
||||||
|
|
||||||
|
# The trimmer's generated keep rules (proguard_project_references.cfg) cover the
|
||||||
|
# Java *methods* the bindings call, but not their fields -- upstream never
|
||||||
|
# obfuscates, so the gap never showed. A bound property backed by a Java field
|
||||||
|
# reads it through JNI by name, and renaming breaks that:
|
||||||
|
# NoSuchFieldError: no "Landroidx/lifecycle/Lifecycle$State;" field "DESTROYED"
|
||||||
|
# NoSuchFieldError: no "I" field "left" in class "Landroidx/core/graphics/Insets;"
|
||||||
|
# Only the API surface a binding can reach needs it; private fields still get
|
||||||
|
# renamed, and class names -- what Play's report counts -- are untouched by this.
|
||||||
|
-keepclassmembers class * {
|
||||||
|
public <fields>;
|
||||||
|
protected <fields>;
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
# Verbatim copy of the ProGuard configuration .NET for Android generates at
|
||||||
|
# obj/<Config>/<TFM>/proguard/proguard_xamarin.cfg, minus its hardcoded
|
||||||
|
# "-dontobfuscate". ProGuard has no switch that undoes that flag, so the only
|
||||||
|
# way to let R8 rename DEX classes is to drop the file that sets it from R8's
|
||||||
|
# --pg-conf list and substitute this one (see the _AndroidObfuscateDex target
|
||||||
|
# in the csproj).
|
||||||
|
#
|
||||||
|
# Taken from Microsoft.Android.Sdk 36.1.69 (.NET 10). When the Android SDK pack
|
||||||
|
# is updated, diff this against the generated file after a Release build --
|
||||||
|
# a keep rule added upstream and missed here means a runtime JNI failure.
|
||||||
|
# The trailing -ignorewarnings/-keepattributes/-printmapping lines the SDK
|
||||||
|
# appends to that file are regenerated by the csproj target instead.
|
||||||
|
|
||||||
|
-keep class android.support.multidex.MultiDexApplication { <init>(); }
|
||||||
|
-keep class net.dot.jni.** { *; <init>(); }
|
||||||
|
-keep class mono.MonoRuntimeProvider* { *; <init>(...); }
|
||||||
|
-keep class mono.MonoPackageManager { *; <init>(...); }
|
||||||
|
-keep class mono.MonoPackageManager_Resources { *; <init>(...); }
|
||||||
|
-keep class mono.android.** { *; <init>(...); }
|
||||||
|
-keep class mono.java.** { *; <init>(...); }
|
||||||
|
-keep class mono.javax.** { *; <init>(...); }
|
||||||
|
-keep class net.dot.jni.ManagedPeer { *; <init>(...); }
|
||||||
|
-keep class xamarin.android.net.ServerCertificateCustomValidator_TrustManager { *; <init>(...); }
|
||||||
|
-keep class xamarin.android.net.ServerCertificateCustomValidator_TrustManager_FakeSSLSession { *; <init>(...); }
|
||||||
|
-keep class xamarin.android.net.ServerCertificateCustomValidator_AlwaysAcceptingHostnameVerifier { *; <init>(...); }
|
||||||
|
|
||||||
|
-keep class android.runtime.** { <init>(...); }
|
||||||
|
-keep class assembly_mono_android.android.runtime.** { <init>(...); }
|
||||||
|
# hash for android.runtime and assembly_mono_android.android.runtime.
|
||||||
|
-keep class md52ce486a14f4bcd95899665e9d932190b.** { *; <init>(...); }
|
||||||
|
-keepclassmembers class md52ce486a14f4bcd95899665e9d932190b.** { *; <init>(...); }
|
||||||
|
|
||||||
|
# .NET runtime
|
||||||
|
-keep class net.dot.android.crypto.** { *; <init>(...); }
|
||||||
|
|
||||||
|
# Android's template misses fluent setters...
|
||||||
|
-keepclassmembers class * extends android.view.View {
|
||||||
|
*** set*(...);
|
||||||
|
}
|
||||||
|
|
||||||
|
# also misses those inflated custom layout stuff from xml...
|
||||||
|
-keepclassmembers class * extends android.view.View {
|
||||||
|
<init>(android.content.Context,android.util.AttributeSet);
|
||||||
|
<init>(android.content.Context,android.util.AttributeSet,int);
|
||||||
|
}
|
||||||
@@ -21,7 +21,9 @@ namespace Xamarin.Neo4j
|
|||||||
SetTheme(Current.RequestedTheme);
|
SetTheme(Current.RequestedTheme);
|
||||||
RequestedThemeChanged += (s, e) => SetTheme(e.RequestedTheme);
|
RequestedThemeChanged += (s, e) => SetTheme(e.RequestedTheme);
|
||||||
|
|
||||||
|
#pragma warning disable CS0618
|
||||||
MainPage = new NavigationPage(new ConnectionsPage());
|
MainPage = new NavigationPage(new ConnectionsPage());
|
||||||
|
#pragma warning restore CS0618
|
||||||
|
|
||||||
// SetTheme ran before MainPage was assigned, so apply bar colours now.
|
// SetTheme ran before MainPage was assigned, so apply bar colours now.
|
||||||
ApplyNavBarColors();
|
ApplyNavBarColors();
|
||||||
@@ -47,7 +49,7 @@ namespace Xamarin.Neo4j
|
|||||||
// theme changes while the app is backgrounded are picked up on return.
|
// theme changes while the app is backgrounded are picked up on return.
|
||||||
public void ApplyNavBarColors()
|
public void ApplyNavBarColors()
|
||||||
{
|
{
|
||||||
if (MainPage is NavigationPage navPage)
|
if (Windows.Count > 0 && Windows[0].Page is NavigationPage navPage)
|
||||||
{
|
{
|
||||||
if (Resources.TryGetValue("NavigationBarColor", out var navColor) && navColor is Color color)
|
if (Resources.TryGetValue("NavigationBarColor", out var navColor) && navColor is Color color)
|
||||||
navPage.BarBackgroundColor = color;
|
navPage.BarBackgroundColor = color;
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
<ViewCell xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
<ViewCell xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
xmlns:fonts="clr-namespace:Xamarin.Neo4j.Fonts;assembly=Xamarin.Neo4j"
|
xmlns:fonts="clr-namespace:Xamarin.Neo4j.Fonts;assembly=Xamarin.Neo4j"
|
||||||
|
xmlns:models="clr-namespace:Xamarin.Neo4j.Models;assembly=Xamarin.Neo4j"
|
||||||
|
x:DataType="models:Neo4jConnectionString"
|
||||||
x:Class="Xamarin.Neo4j.Controls.ConnectionCell">
|
x:Class="Xamarin.Neo4j.Controls.ConnectionCell">
|
||||||
<Grid Padding="15, 10">
|
<Grid Padding="15, 10">
|
||||||
<StackLayout Spacing="2">
|
<StackLayout Spacing="2">
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ using Microsoft.Maui.Controls.Xaml;
|
|||||||
namespace Xamarin.Neo4j.Controls
|
namespace Xamarin.Neo4j.Controls
|
||||||
{
|
{
|
||||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||||
|
#pragma warning disable CS0618
|
||||||
public partial class ConnectionCell : ViewCell
|
public partial class ConnectionCell : ViewCell
|
||||||
{
|
{
|
||||||
public ConnectionCell()
|
public ConnectionCell()
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<ViewCell xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Xamarin.Neo4j.Controls.LicenseCell">
|
<ViewCell xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
|
xmlns:models="clr-namespace:Xamarin.Neo4j.Models;assembly=Xamarin.Neo4j"
|
||||||
|
x:DataType="models:License"
|
||||||
|
x:Class="Xamarin.Neo4j.Controls.LicenseCell">
|
||||||
<StackLayout Padding="15, 15, 15, 0">
|
<StackLayout Padding="15, 15, 15, 0">
|
||||||
<Label FontAttributes="Bold" TextColor="{DynamicResource Accent}" Text="{Binding Name}">
|
<Label FontAttributes="Bold" TextColor="{DynamicResource Accent}" Text="{Binding Name}">
|
||||||
<Label.GestureRecognizers>
|
<Label.GestureRecognizers>
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ using Microsoft.Maui.Controls.Xaml;
|
|||||||
namespace Xamarin.Neo4j.Controls
|
namespace Xamarin.Neo4j.Controls
|
||||||
{
|
{
|
||||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||||
|
#pragma warning disable CS0618
|
||||||
public partial class LicenseCell : ViewCell
|
public partial class LicenseCell : ViewCell
|
||||||
{
|
{
|
||||||
public LicenseCell()
|
public LicenseCell()
|
||||||
|
|||||||
@@ -2,12 +2,15 @@
|
|||||||
|
|
||||||
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
|
xmlns:models="clr-namespace:Xamarin.Neo4j.Models;assembly=Xamarin.Neo4j"
|
||||||
|
xmlns:controls="clr-namespace:Xamarin.Neo4j.Controls;assembly=Xamarin.Neo4j"
|
||||||
|
x:DataType="models:QueryResult"
|
||||||
x:Class="Xamarin.Neo4j.Controls.QueryResultView"
|
x:Class="Xamarin.Neo4j.Controls.QueryResultView"
|
||||||
x:Name="self">
|
x:Name="self">
|
||||||
<Grid VerticalOptions="Start">
|
<Grid VerticalOptions="Start">
|
||||||
|
|
||||||
<!-- Graph WebView -->
|
<!-- Graph WebView -->
|
||||||
<WebView x:Name="graphView"
|
<WebView x:Name="graphView" x:DataType="{x:Null}"
|
||||||
HorizontalOptions="FillAndExpand"
|
HorizontalOptions="FillAndExpand"
|
||||||
IsVisible="{Binding CanDisplayGraph}"
|
IsVisible="{Binding CanDisplayGraph}"
|
||||||
HeightRequest="{Binding GraphViewHeight, Source={x:Reference self}}" />
|
HeightRequest="{Binding GraphViewHeight, Source={x:Reference self}}" />
|
||||||
|
|||||||
@@ -666,7 +666,7 @@ namespace Xamarin.Neo4j.Fonts
|
|||||||
public const string Divide = "\uf529";
|
public const string Divide = "\uf529";
|
||||||
public const string DoorClosed = "\uf52a";
|
public const string DoorClosed = "\uf52a";
|
||||||
public const string DoorOpen = "\uf52b";
|
public const string DoorOpen = "\uf52b";
|
||||||
public const string Equals = "\uf52c";
|
public new const string Equals = "\uf52c";
|
||||||
public const string Feather = "\uf52d";
|
public const string Feather = "\uf52d";
|
||||||
public const string Frog = "\uf52e";
|
public const string Frog = "\uf52e";
|
||||||
public const string GasPump = "\uf52f";
|
public const string GasPump = "\uf52f";
|
||||||
|
|||||||
@@ -18,5 +18,7 @@ namespace Xamarin.Neo4j.Models
|
|||||||
public bool Default { get; set; }
|
public bool Default { get; set; }
|
||||||
|
|
||||||
public string DisplayName => Name + (Default ? " 🏠" : string.Empty);
|
public string DisplayName => Name + (Default ? " 🏠" : string.Empty);
|
||||||
|
|
||||||
|
public override string ToString() => DisplayName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
xmlns:fonts="clr-namespace:Xamarin.Neo4j.Fonts;assembly=Xamarin.Neo4j"
|
xmlns:fonts="clr-namespace:Xamarin.Neo4j.Fonts;assembly=Xamarin.Neo4j"
|
||||||
|
xmlns:vm="clr-namespace:Xamarin.Neo4j.ViewModels;assembly=Xamarin.Neo4j"
|
||||||
|
x:DataType="vm:AddConnectionViewModel"
|
||||||
Title="Add Connection"
|
Title="Add Connection"
|
||||||
x:Class="Xamarin.Neo4j.Pages.AddConnectionPage">
|
x:Class="Xamarin.Neo4j.Pages.AddConnectionPage">
|
||||||
<ContentPage.Content>
|
<ContentPage.Content>
|
||||||
|
|||||||
@@ -3,6 +3,9 @@
|
|||||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
xmlns:fonts="clr-namespace:Xamarin.Neo4j.Fonts;assembly=Xamarin.Neo4j"
|
xmlns:fonts="clr-namespace:Xamarin.Neo4j.Fonts;assembly=Xamarin.Neo4j"
|
||||||
|
xmlns:vm="clr-namespace:Xamarin.Neo4j.ViewModels;assembly=Xamarin.Neo4j"
|
||||||
|
xmlns:models="clr-namespace:Xamarin.Neo4j.Models;assembly=Xamarin.Neo4j"
|
||||||
|
x:DataType="vm:ConnectionsViewModel"
|
||||||
x:Class="Xamarin.Neo4j.Pages.ConnectionsPage"
|
x:Class="Xamarin.Neo4j.Pages.ConnectionsPage"
|
||||||
x:Name="connectionsPage"
|
x:Name="connectionsPage"
|
||||||
Title=" ">
|
Title=" ">
|
||||||
@@ -33,7 +36,7 @@
|
|||||||
<StackLayout BindableLayout.ItemsSource="{Binding ConnectionStrings}"
|
<StackLayout BindableLayout.ItemsSource="{Binding ConnectionStrings}"
|
||||||
Spacing="0" Padding="0,16,0,80">
|
Spacing="0" Padding="0,16,0,80">
|
||||||
<BindableLayout.ItemTemplate>
|
<BindableLayout.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate x:DataType="models:Neo4jConnectionString">
|
||||||
<Border Margin="16,0,16,8"
|
<Border Margin="16,0,16,8"
|
||||||
BackgroundColor="{DynamicResource Extreme}"
|
BackgroundColor="{DynamicResource Extreme}"
|
||||||
Stroke="{DynamicResource QueryTextBorder}"
|
Stroke="{DynamicResource QueryTextBorder}"
|
||||||
@@ -41,7 +44,7 @@
|
|||||||
StrokeShape="RoundRectangle 10">
|
StrokeShape="RoundRectangle 10">
|
||||||
<Grid ColumnDefinitions="Auto,*,Auto" Padding="14,12">
|
<Grid ColumnDefinitions="Auto,*,Auto" Padding="14,12">
|
||||||
<Grid.GestureRecognizers>
|
<Grid.GestureRecognizers>
|
||||||
<TapGestureRecognizer
|
<TapGestureRecognizer x:DataType="{x:Null}"
|
||||||
Command="{Binding BindingContext.Commands[OpenConnection], Source={x:Reference connectionsPage}}"
|
Command="{Binding BindingContext.Commands[OpenConnection], Source={x:Reference connectionsPage}}"
|
||||||
CommandParameter="{Binding .}" />
|
CommandParameter="{Binding .}" />
|
||||||
</Grid.GestureRecognizers>
|
</Grid.GestureRecognizers>
|
||||||
@@ -92,7 +95,7 @@
|
|||||||
|
|
||||||
<!-- Edit / Delete -->
|
<!-- Edit / Delete -->
|
||||||
<StackLayout Grid.Column="2" Orientation="Horizontal" Spacing="0" VerticalOptions="Center">
|
<StackLayout Grid.Column="2" Orientation="Horizontal" Spacing="0" VerticalOptions="Center">
|
||||||
<Button Text="{x:Static fonts:FontAwesomeSolid.PencilAlt}"
|
<Button x:DataType="{x:Null}" Text="{x:Static fonts:FontAwesomeSolid.PencilAlt}"
|
||||||
FontFamily="{StaticResource FontAwesomeSolid}"
|
FontFamily="{StaticResource FontAwesomeSolid}"
|
||||||
FontSize="14"
|
FontSize="14"
|
||||||
WidthRequest="38" HeightRequest="38"
|
WidthRequest="38" HeightRequest="38"
|
||||||
@@ -101,7 +104,7 @@
|
|||||||
Padding="0"
|
Padding="0"
|
||||||
Command="{Binding BindingContext.Commands[EditConnectionString], Source={x:Reference connectionsPage}}"
|
Command="{Binding BindingContext.Commands[EditConnectionString], Source={x:Reference connectionsPage}}"
|
||||||
CommandParameter="{Binding .}" />
|
CommandParameter="{Binding .}" />
|
||||||
<Button Text="{x:Static fonts:FontAwesomeSolid.TrashAlt}"
|
<Button x:DataType="{x:Null}" Text="{x:Static fonts:FontAwesomeSolid.TrashAlt}"
|
||||||
FontFamily="{StaticResource FontAwesomeSolid}"
|
FontFamily="{StaticResource FontAwesomeSolid}"
|
||||||
FontSize="14"
|
FontSize="14"
|
||||||
WidthRequest="38" HeightRequest="38"
|
WidthRequest="38" HeightRequest="38"
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
|
xmlns:vm="clr-namespace:Xamarin.Neo4j.ViewModels;assembly=Xamarin.Neo4j"
|
||||||
|
x:DataType="vm:GraphViewModel"
|
||||||
Title="Graph"
|
Title="Graph"
|
||||||
x:Class="Xamarin.Neo4j.Pages.GraphPage">
|
x:Class="Xamarin.Neo4j.Pages.GraphPage">
|
||||||
<ContentPage.Content>
|
<ContentPage.Content>
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
xmlns:controls="clr-namespace:Xamarin.Neo4j.Controls"
|
xmlns:controls="clr-namespace:Xamarin.Neo4j.Controls"
|
||||||
|
xmlns:vm="clr-namespace:Xamarin.Neo4j.ViewModels;assembly=Xamarin.Neo4j"
|
||||||
|
x:DataType="vm:LicensesViewModel"
|
||||||
Title="Software Licenses"
|
Title="Software Licenses"
|
||||||
x:Class="Xamarin.Neo4j.Pages.LicensesPage">
|
x:Class="Xamarin.Neo4j.Pages.LicensesPage">
|
||||||
<ContentPage.Content>
|
<ContentPage.Content>
|
||||||
|
|||||||
@@ -3,6 +3,9 @@
|
|||||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
xmlns:fonts="clr-namespace:Xamarin.Neo4j.Fonts;assembly=Xamarin.Neo4j"
|
xmlns:fonts="clr-namespace:Xamarin.Neo4j.Fonts;assembly=Xamarin.Neo4j"
|
||||||
|
xmlns:vm="clr-namespace:Xamarin.Neo4j.ViewModels;assembly=Xamarin.Neo4j"
|
||||||
|
xmlns:models="clr-namespace:Xamarin.Neo4j.Models;assembly=Xamarin.Neo4j"
|
||||||
|
x:DataType="vm:QueriesViewModel"
|
||||||
Title="Queries"
|
Title="Queries"
|
||||||
x:Name="queriesPage"
|
x:Name="queriesPage"
|
||||||
x:Class="Xamarin.Neo4j.Pages.QueriesPage">
|
x:Class="Xamarin.Neo4j.Pages.QueriesPage">
|
||||||
@@ -17,10 +20,10 @@
|
|||||||
<Grid>
|
<Grid>
|
||||||
<ListView ItemsSource="{Binding Queries}" ItemTapped="StartSessionWithQuery" IsVisible="{Binding HasItems}">
|
<ListView ItemsSource="{Binding Queries}" ItemTapped="StartSessionWithQuery" IsVisible="{Binding HasItems}">
|
||||||
<ListView.ItemTemplate>
|
<ListView.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate x:DataType="models:Query">
|
||||||
<TextCell Text="{Binding Name}" Detail="{Binding QueryText}">
|
<TextCell Text="{Binding Name}" Detail="{Binding QueryText}">
|
||||||
<TextCell.ContextActions>
|
<TextCell.ContextActions>
|
||||||
<MenuItem Text="Delete" Command="{Binding BindingContext.Commands[DeleteQuery], Source={x:Reference queriesPage} }" CommandParameter="{Binding .}" IsDestructive="true" />
|
<MenuItem x:DataType="{x:Null}" Text="Delete" Command="{Binding BindingContext.Commands[DeleteQuery], Source={x:Reference queriesPage} }" CommandParameter="{Binding .}" IsDestructive="true" />
|
||||||
</TextCell.ContextActions>
|
</TextCell.ContextActions>
|
||||||
</TextCell>
|
</TextCell>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
|||||||
@@ -4,6 +4,9 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
xmlns:fonts="clr-namespace:Xamarin.Neo4j.Fonts;assembly=Xamarin.Neo4j"
|
xmlns:fonts="clr-namespace:Xamarin.Neo4j.Fonts;assembly=Xamarin.Neo4j"
|
||||||
xmlns:controls="clr-namespace:Xamarin.Neo4j.Controls;assembly=Xamarin.Neo4j"
|
xmlns:controls="clr-namespace:Xamarin.Neo4j.Controls;assembly=Xamarin.Neo4j"
|
||||||
|
xmlns:vm="clr-namespace:Xamarin.Neo4j.ViewModels;assembly=Xamarin.Neo4j"
|
||||||
|
xmlns:models="clr-namespace:Xamarin.Neo4j.Models;assembly=Xamarin.Neo4j"
|
||||||
|
x:DataType="vm:SessionViewModel"
|
||||||
x:Class="Xamarin.Neo4j.Pages.SessionPage"
|
x:Class="Xamarin.Neo4j.Pages.SessionPage"
|
||||||
x:Name="sessionPage">
|
x:Name="sessionPage">
|
||||||
<NavigationPage.TitleView>
|
<NavigationPage.TitleView>
|
||||||
@@ -21,7 +24,7 @@
|
|||||||
</Label.FormattedText>
|
</Label.FormattedText>
|
||||||
</Label>
|
</Label>
|
||||||
|
|
||||||
<Picker x:Name="databasePicker" ItemsSource="{Binding AvailableDatabases}" ItemDisplayBinding="{Binding DisplayName}" SelectedItem="{Binding CurrentDatabase}" IsVisible="False" />
|
<Picker x:Name="databasePicker" ItemsSource="{Binding AvailableDatabases}" SelectedItem="{Binding CurrentDatabase}" IsVisible="False" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</NavigationPage.TitleView>
|
</NavigationPage.TitleView>
|
||||||
|
|
||||||
@@ -82,11 +85,11 @@
|
|||||||
IsVisible="{Binding HasSavedQueries}"
|
IsVisible="{Binding HasSavedQueries}"
|
||||||
Spacing="0">
|
Spacing="0">
|
||||||
<BindableLayout.ItemTemplate>
|
<BindableLayout.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate x:DataType="models:Query">
|
||||||
<Grid ColumnDefinitions="*,Auto" Padding="0,10">
|
<Grid ColumnDefinitions="*,Auto" Padding="0,10">
|
||||||
<StackLayout Grid.Column="0" Spacing="2">
|
<StackLayout Grid.Column="0" Spacing="2">
|
||||||
<StackLayout.GestureRecognizers>
|
<StackLayout.GestureRecognizers>
|
||||||
<TapGestureRecognizer
|
<TapGestureRecognizer x:DataType="{x:Null}"
|
||||||
Command="{Binding BindingContext.Commands[LoadQuery], Source={x:Reference sessionPage}}"
|
Command="{Binding BindingContext.Commands[LoadQuery], Source={x:Reference sessionPage}}"
|
||||||
CommandParameter="{Binding .}" />
|
CommandParameter="{Binding .}" />
|
||||||
</StackLayout.GestureRecognizers>
|
</StackLayout.GestureRecognizers>
|
||||||
@@ -97,7 +100,7 @@
|
|||||||
MaxLines="1"
|
MaxLines="1"
|
||||||
LineBreakMode="TailTruncation" />
|
LineBreakMode="TailTruncation" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<Button Grid.Column="1"
|
<Button Grid.Column="1" x:DataType="{x:Null}"
|
||||||
Text="{x:Static fonts:FontAwesomeSolid.TrashAlt}"
|
Text="{x:Static fonts:FontAwesomeSolid.TrashAlt}"
|
||||||
FontFamily="{StaticResource FontAwesomeSolid}"
|
FontFamily="{StaticResource FontAwesomeSolid}"
|
||||||
FontSize="16"
|
FontSize="16"
|
||||||
@@ -144,7 +147,7 @@
|
|||||||
|
|
||||||
<StackLayout BindableLayout.ItemsSource="{Binding QueryResults}" Spacing="0">
|
<StackLayout BindableLayout.ItemsSource="{Binding QueryResults}" Spacing="0">
|
||||||
<BindableLayout.ItemTemplate>
|
<BindableLayout.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate x:DataType="models:QueryResult">
|
||||||
<Border Margin="12,0,12,6"
|
<Border Margin="12,0,12,6"
|
||||||
BackgroundColor="{DynamicResource Extreme}"
|
BackgroundColor="{DynamicResource Extreme}"
|
||||||
Stroke="{DynamicResource QueryTextBorder}"
|
Stroke="{DynamicResource QueryTextBorder}"
|
||||||
@@ -152,7 +155,7 @@
|
|||||||
StrokeShape="RoundRectangle 4">
|
StrokeShape="RoundRectangle 4">
|
||||||
<StackLayout Spacing="0">
|
<StackLayout Spacing="0">
|
||||||
<!-- Action row -->
|
<!-- Action row -->
|
||||||
<Grid ColumnDefinitions="*,*,*,*,Auto" Padding="4,0">
|
<Grid ColumnDefinitions="*,*,*,*,Auto" Padding="4,0" x:DataType="{x:Null}">
|
||||||
<Button Grid.Column="0"
|
<Button Grid.Column="0"
|
||||||
Text="{x:Static fonts:FontAwesomeSolid.Star}"
|
Text="{x:Static fonts:FontAwesomeSolid.Star}"
|
||||||
FontFamily="{StaticResource FontAwesomeSolid}" FontSize="13"
|
FontFamily="{StaticResource FontAwesomeSolid}" FontSize="13"
|
||||||
@@ -204,14 +207,14 @@
|
|||||||
LineBreakMode="TailTruncation"
|
LineBreakMode="TailTruncation"
|
||||||
MaxLines="1">
|
MaxLines="1">
|
||||||
<Label.GestureRecognizers>
|
<Label.GestureRecognizers>
|
||||||
<TapGestureRecognizer
|
<TapGestureRecognizer x:DataType="{x:Null}"
|
||||||
Command="{Binding BindingContext.Commands[LoadResultQuery], Source={x:Reference sessionPage}}"
|
Command="{Binding BindingContext.Commands[LoadResultQuery], Source={x:Reference sessionPage}}"
|
||||||
CommandParameter="{Binding .}" />
|
CommandParameter="{Binding .}" />
|
||||||
</Label.GestureRecognizers>
|
</Label.GestureRecognizers>
|
||||||
</Label>
|
</Label>
|
||||||
|
|
||||||
<!-- Result content -->
|
<!-- Result content -->
|
||||||
<controls:QueryResultView
|
<controls:QueryResultView x:DataType="{x:Null}"
|
||||||
GraphViewHeight="{Binding BindingContext.GraphViewHeight, Source={x:Reference sessionPage}}" />
|
GraphViewHeight="{Binding BindingContext.GraphViewHeight, Source={x:Reference sessionPage}}" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</Border>
|
</Border>
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
xmlns:fonts="clr-namespace:Xamarin.Neo4j.Fonts;assembly=Xamarin.Neo4j"
|
xmlns:fonts="clr-namespace:Xamarin.Neo4j.Fonts;assembly=Xamarin.Neo4j"
|
||||||
|
xmlns:vm="clr-namespace:Xamarin.Neo4j.ViewModels;assembly=Xamarin.Neo4j"
|
||||||
|
x:DataType="vm:SettingsViewModel"
|
||||||
Title="Settings"
|
Title="Settings"
|
||||||
x:Class="Xamarin.Neo4j.Pages.SettingsPage">
|
x:Class="Xamarin.Neo4j.Pages.SettingsPage">
|
||||||
<ContentPage.IconImageSource>
|
<ContentPage.IconImageSource>
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ namespace Xamarin.Neo4j.ViewModels
|
|||||||
|
|
||||||
var (_, message) = await _neo4jService.EstablishConnection(connectionString);
|
var (_, message) = await _neo4jService.EstablishConnection(connectionString);
|
||||||
|
|
||||||
await Application.Current.MainPage.DisplayAlert("", message, "OK");
|
await Application.Current.Windows[0].Page.DisplayAlertAsync("", message, "OK");
|
||||||
}));
|
}));
|
||||||
|
|
||||||
Commands.Add("Save", new Command(async () =>
|
Commands.Add("Save", new Command(async () =>
|
||||||
@@ -76,7 +76,7 @@ namespace Xamarin.Neo4j.ViewModels
|
|||||||
await Navigation.PushAsync(new SessionPage(connectionString));
|
await Navigation.PushAsync(new SessionPage(connectionString));
|
||||||
|
|
||||||
else
|
else
|
||||||
await Application.Current.MainPage.DisplayAlert("", message, "OK");
|
await Application.Current.Windows[0].Page.DisplayAlertAsync("", message, "OK");
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ namespace Xamarin.Neo4j.ViewModels
|
|||||||
{
|
{
|
||||||
if (ConnectionStringManager.ActiveConnectionString == null)
|
if (ConnectionStringManager.ActiveConnectionString == null)
|
||||||
{
|
{
|
||||||
await Application.Current.MainPage.DisplayAlert("", "Please select a connection before starting a session.", "OK");
|
await Application.Current.Windows[0].Page.DisplayAlertAsync("", "Please select a connection before starting a session.", "OK");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ namespace Xamarin.Neo4j.ViewModels
|
|||||||
if (!(o is Query query))
|
if (!(o is Query query))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var confirmed = await Application.Current.MainPage.DisplayAlert(
|
var confirmed = await Application.Current.Windows[0].Page.DisplayAlertAsync(
|
||||||
"Delete Query",
|
"Delete Query",
|
||||||
$"Delete \"{query.Name}\"?",
|
$"Delete \"{query.Name}\"?",
|
||||||
"Delete", "Cancel");
|
"Delete", "Cancel");
|
||||||
@@ -115,7 +115,7 @@ namespace Xamarin.Neo4j.ViewModels
|
|||||||
Commands.Add("SaveQuery", new Command(async (o) =>
|
Commands.Add("SaveQuery", new Command(async (o) =>
|
||||||
{
|
{
|
||||||
if (!(o is QueryResult result)) return;
|
if (!(o is QueryResult result)) return;
|
||||||
var name = await Application.Current.MainPage.DisplayPromptAsync(
|
var name = await Application.Current.Windows[0].Page.DisplayPromptAsync(
|
||||||
"Save Query", "What would you like to call this query?");
|
"Save Query", "What would you like to call this query?");
|
||||||
if (!string.IsNullOrWhiteSpace(name))
|
if (!string.IsNullOrWhiteSpace(name))
|
||||||
{
|
{
|
||||||
@@ -163,7 +163,7 @@ namespace Xamarin.Neo4j.ViewModels
|
|||||||
|
|
||||||
if (!isConnected)
|
if (!isConnected)
|
||||||
{
|
{
|
||||||
await Application.Current.MainPage.DisplayAlert("", message, "OK");
|
await Application.Current.Windows[0].Page.DisplayAlertAsync("", message, "OK");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ namespace Xamarin.Neo4j.ViewModels
|
|||||||
|
|
||||||
if (!Email.Default.IsComposeSupported)
|
if (!Email.Default.IsComposeSupported)
|
||||||
{
|
{
|
||||||
await Application.Current.MainPage.DisplayAlert(
|
await Application.Current.Windows[0].Page.DisplayAlertAsync(
|
||||||
"No Email App", "No email client is configured on this device.", "OK");
|
"No Email App", "No email client is configured on this device.", "OK");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -96,7 +96,7 @@ namespace Xamarin.Neo4j.ViewModels
|
|||||||
|
|
||||||
Commands.Add("ClearConnections", new Command(async () =>
|
Commands.Add("ClearConnections", new Command(async () =>
|
||||||
{
|
{
|
||||||
var clear = await Application.Current.MainPage.DisplayAlert(
|
var clear = await Application.Current.Windows[0].Page.DisplayAlertAsync(
|
||||||
"Clear Connections",
|
"Clear Connections",
|
||||||
"Are you sure you want to remove all saved connections?",
|
"Are you sure you want to remove all saved connections?",
|
||||||
"Clear", "Cancel");
|
"Clear", "Cancel");
|
||||||
@@ -109,7 +109,7 @@ namespace Xamarin.Neo4j.ViewModels
|
|||||||
|
|
||||||
Commands.Add("ClearQueries", new Command(async () =>
|
Commands.Add("ClearQueries", new Command(async () =>
|
||||||
{
|
{
|
||||||
var clear = await Application.Current.MainPage.DisplayAlert(
|
var clear = await Application.Current.Windows[0].Page.DisplayAlertAsync(
|
||||||
"Clear Saved Queries",
|
"Clear Saved Queries",
|
||||||
"Are you sure you want to remove all saved queries?",
|
"Are you sure you want to remove all saved queries?",
|
||||||
"Clear", "Cancel");
|
"Clear", "Cancel");
|
||||||
|
|||||||
@@ -5,6 +5,15 @@
|
|||||||
<UseMaui>true</UseMaui>
|
<UseMaui>true</UseMaui>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<Nullable>disable</Nullable>
|
<Nullable>disable</Nullable>
|
||||||
|
<MauiEnableXamlCBindingWithSourceCompilation>true</MauiEnableXamlCBindingWithSourceCompilation>
|
||||||
|
<!-- XC0023: elements inside DataTemplates that bind to both the item model and the parent
|
||||||
|
page ViewModel via Source={x:Reference} cannot share a single compiled DataType.
|
||||||
|
x:DataType="{x:Null}" on those elements is intentional; suppress the hint. -->
|
||||||
|
<NoWarn>$(NoWarn);XC0023</NoWarn>
|
||||||
|
<!-- CS0618: ViewCell is deprecated but converting ListView to CollectionView is a larger
|
||||||
|
refactor. The MAUI XAML source generator emits this on the generated partial class
|
||||||
|
for ConnectionCell/LicenseCell which we cannot annotate directly. -->
|
||||||
|
<NoWarn>$(NoWarn);CS0618</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
@@ -15,6 +24,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Maui.Controls" Version="10.0.20" />
|
<PackageReference Include="Microsoft.Maui.Controls" Version="10.0.20" />
|
||||||
<PackageReference Include="Neo4jClient" Version="4.1.18" />
|
<PackageReference Include="Neo4jClient" Version="4.1.18" />
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
3687
landing/package-lock.json
generated
3687
landing/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -13,6 +13,6 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/sitemap": "^3.7.2",
|
"@astrojs/sitemap": "^3.7.2",
|
||||||
"astro": "^6.1.2"
|
"astro": "^7.0.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user