diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.iOS/CustomRenderers/QueryEditorRenderer.cs b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.iOS/CustomRenderers/QueryEditorRenderer.cs
new file mode 100644
index 0000000..5041dc2
--- /dev/null
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.iOS/CustomRenderers/QueryEditorRenderer.cs
@@ -0,0 +1,23 @@
+//
+// QueryEditorRenderer.cs
+//
+// Trevi Awater
+// 13-01-2022
+//
+// © Xamarin.Neo4j.iOS
+//
+
+using UIKit;
+using Xamarin.Forms;
+using Xamarin.Forms.Platform.iOS;
+using Xamarin.Neo4j.Controls;
+using Xamarin.Neo4j.iOS.CustomRenderers;
+
+[assembly: ExportRenderer(typeof(QueryEditor), typeof(QueryEditorRenderer))]
+namespace Xamarin.Neo4j.iOS.CustomRenderers
+{
+ public class QueryEditorRenderer : EditorRenderer
+ {
+
+ }
+}
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.iOS/Info.plist b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.iOS/Info.plist
index b2b5fdb..8bc61f1 100644
--- a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.iOS/Info.plist
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.iOS/Info.plist
@@ -2,43 +2,43 @@
- UIDeviceFamily
-
- 1
- 2
-
- UISupportedInterfaceOrientations
-
- UIInterfaceOrientationPortrait
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
-
- UISupportedInterfaceOrientations~ipad
-
- UIInterfaceOrientationPortrait
- UIInterfaceOrientationPortraitUpsideDown
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
-
- MinimumOSVersion
- 14.2
- CFBundleDisplayName
- Pocket Graph
- CFBundleIdentifier
- nl.resoftware.xamarin-neo4j
- CFBundleVersion
- 1.0
- UILaunchStoryboardName
- LaunchScreen
- CFBundleName
- Pocket Graph
- XSAppIconAssets
- Assets.xcassets/AppIcon.appiconset
- UIAppFonts
-
- iconize-fontawesome-regular.ttf
- iconize-fontawesome-solid.ttf
- iconize-fontawesome-brands.ttf
-
+ UIDeviceFamily
+
+ 1
+ 2
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ MinimumOSVersion
+ 14.2
+ CFBundleDisplayName
+ PocketGraph
+ CFBundleIdentifier
+ nl.resoftware.pocketgraph
+ CFBundleVersion
+ 1.0.1
+ UILaunchStoryboardName
+ LaunchScreen
+ CFBundleName
+ PocketGraph
+ XSAppIconAssets
+ Assets.xcassets/AppIcon.appiconset
+ UIAppFonts
+
+ iconize-fontawesome-regular.ttf
+ iconize-fontawesome-solid.ttf
+ iconize-fontawesome-brands.ttf
+
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.iOS/LaunchScreen.storyboard b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.iOS/LaunchScreen.storyboard
new file mode 100644
index 0000000..bc4ed80
--- /dev/null
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.iOS/LaunchScreen.storyboard
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.iOS/Resources/LaunchScreen.storyboard b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.iOS/Resources/LaunchScreen.storyboard
deleted file mode 100644
index a639c2f..0000000
--- a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.iOS/Resources/LaunchScreen.storyboard
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.iOS/Resources/logo.png b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.iOS/Resources/logo.png
new file mode 100644
index 0000000..2ecad28
Binary files /dev/null and b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.iOS/Resources/logo.png differ
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.iOS/Resources/resoftware.png b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.iOS/Resources/resoftware.png
new file mode 100644
index 0000000..1cc029b
Binary files /dev/null and b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.iOS/Resources/resoftware.png differ
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.iOS/Services/ScreenSizeService.cs b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.iOS/Services/ScreenSizeService.cs
new file mode 100644
index 0000000..91fc48f
--- /dev/null
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.iOS/Services/ScreenSizeService.cs
@@ -0,0 +1,30 @@
+//
+// ScreenSizeService.cs
+//
+// Trevi Awater
+// 13-01-2022
+//
+// © Xamarin.Neo4j.iOS
+//
+
+using UIKit;
+using Xamarin.Forms;
+using Xamarin.Neo4j.iOS.Services;
+using Xamarin.Neo4j.Services;
+
+[assembly: Dependency(typeof(ScreenSizeService))]
+namespace Xamarin.Neo4j.iOS.Services
+{
+ public class ScreenSizeService : IScreenSizeService
+ {
+ public int GetScreenHeight()
+ {
+ return (int)UIScreen.MainScreen.Bounds.Height;
+ }
+
+ public int GetScreenWidth()
+ {
+ return (int)UIScreen.MainScreen.Bounds.Width;
+ }
+ }
+}
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.iOS/Xamarin.Neo4j.iOS.csproj b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.iOS/Xamarin.Neo4j.iOS.csproj
index 2d0b30f..0ac2af9 100644
--- a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.iOS/Xamarin.Neo4j.iOS.csproj
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.iOS/Xamarin.Neo4j.iOS.csproj
@@ -94,8 +94,10 @@
SdkOnly
+
+
@@ -119,7 +121,7 @@
-
+
false
@@ -143,6 +145,8 @@
+
+
\ No newline at end of file
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/App.xaml b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/App.xaml
index 56b5a4d..9ef1bfc 100644
--- a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/App.xaml
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/App.xaml
@@ -2,36 +2,4 @@
-
- #e4ecf5
- #31333b
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/App.xaml.cs b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/App.xaml.cs
index 7344dc9..618c42f 100644
--- a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/App.xaml.cs
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/App.xaml.cs
@@ -2,6 +2,7 @@
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using Xamarin.Neo4j.Pages;
+using Xamarin.Neo4j.Themes;
[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
@@ -13,9 +14,24 @@ namespace Xamarin.Neo4j
{
InitializeComponent();
+ SetTheme(Current.RequestedTheme);
+
MainPage = new NavigationPage(new RootPage());
}
+
+ private void SetTheme(OSAppTheme theme)
+ {
+ Resources = theme switch
+ {
+ OSAppTheme.Dark => new DarkTheme(),
+ OSAppTheme.Light => new LightTheme(),
+
+ _ => new LightTheme()
+ };
+ }
+
+
protected override void OnStart()
{
// Handle when your app starts
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Controls/ConnectionCell.xaml b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Controls/ConnectionCell.xaml
new file mode 100644
index 0000000..53a88c0
--- /dev/null
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Controls/ConnectionCell.xaml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Controls/ConnectionCell.xaml.cs b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Controls/ConnectionCell.xaml.cs
new file mode 100644
index 0000000..3aa7cb7
--- /dev/null
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Controls/ConnectionCell.xaml.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms;
+using Xamarin.Forms.Xaml;
+
+namespace Xamarin.Neo4j.Controls
+{
+ [XamlCompilation(XamlCompilationOptions.Compile)]
+ public partial class ConnectionCell : ViewCell
+ {
+ public ConnectionCell()
+ {
+ InitializeComponent();
+
+ isActiveIndicator.SetBinding(VisualElement.IsVisibleProperty, new Binding(nameof(IsActive), source: this));
+ }
+
+ #region Bindable Properties
+
+ public bool IsActive
+ {
+ get => (bool)GetValue(IsActiveProperty);
+ set => SetValue(IsActiveProperty, value);
+ }
+
+ public static BindableProperty IsActiveProperty = BindableProperty.Create("IsActive", typeof(bool),
+ typeof(ConnectionCell), false, BindingMode.OneWay);
+
+ #endregion
+ }
+}
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Controls/QueryBuilder.xaml b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Controls/QueryBuilder.xaml
deleted file mode 100644
index f937c3b..0000000
--- a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Controls/QueryBuilder.xaml
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Controls/QueryBuilder.xaml.cs b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Controls/QueryBuilder.xaml.cs
deleted file mode 100644
index d320fb4..0000000
--- a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Controls/QueryBuilder.xaml.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-using Xamarin.Forms;
-using Xamarin.Forms.Xaml;
-
-namespace Xamarin.Neo4j.Controls
-{
- [XamlCompilation(XamlCompilationOptions.Compile)]
- public partial class QueryBuilder : ContentView
- {
- public event EventHandler ExecuteQuery;
-
- public QueryBuilder()
- {
- InitializeComponent();
-
- editor.SetBinding(Editor.TextProperty, new Binding(nameof(Query), source: this));
- }
-
- #region Bindable Properties
-
- public string Query
- {
- get => (string)GetValue(QueryProperty);
- set => SetValue(QueryProperty, value);
- }
-
- public static BindableProperty QueryProperty = BindableProperty.Create("Query", typeof(string),
- typeof(QueryBuilder), string.Empty, BindingMode.TwoWay);
-
- #endregion
-
- private void InvokeExecuteQuery (object sender, EventArgs e)
- {
- ExecuteQuery?.Invoke(sender, e);
- }
- }
-}
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Controls/QueryEditor.cs b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Controls/QueryEditor.cs
new file mode 100644
index 0000000..b6867c4
--- /dev/null
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Controls/QueryEditor.cs
@@ -0,0 +1,31 @@
+//
+// QueryEditor.cs
+//
+// Trevi Awater
+// 13-01-2022
+//
+// © Xamarin.Neo4j
+//
+
+using System;
+using Xamarin.Forms;
+
+namespace Xamarin.Neo4j.Controls
+{
+ public class QueryEditor : Editor
+ {
+ public double MaxHeight { get; set; }
+
+ protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
+ {
+ var sizeRequest = base.OnMeasure(widthConstraint, heightConstraint);
+
+ var newHeight = sizeRequest.Request.Height;
+
+ if (newHeight > MaxHeight)
+ newHeight = MaxHeight;
+
+ return new SizeRequest(new Size(sizeRequest.Request.Width, newHeight));
+ }
+ }
+}
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Controls/QueryResultCell.xaml b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Controls/QueryResultCell.xaml
deleted file mode 100644
index 9a66a92..0000000
--- a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Controls/QueryResultCell.xaml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Controls/QueryResultCell.xaml.cs b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Controls/QueryResultCell.xaml.cs
deleted file mode 100644
index aab2477..0000000
--- a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Controls/QueryResultCell.xaml.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-using Xamarin.Forms;
-using Xamarin.Forms.Xaml;
-using Xamarin.Neo4j.Models;
-using Xamarin.Neo4j.Pages;
-
-namespace Xamarin.Neo4j.Controls
-{
- [XamlCompilation(XamlCompilationOptions.Compile)]
- public partial class QueryResultCell : ViewCell
- {
- public QueryResult QueryResult => (QueryResult) BindingContext;
-
- public QueryResultCell()
- {
- InitializeComponent();
-
-
- }
-
- private async void OpenNeovis(object sender, EventArgs e)
- {
- await App.Current.MainPage.Navigation.PushAsync(new VisualizationPage(QueryResult));
- }
- }
-}
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Controls/QueryResultView.xaml b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Controls/QueryResultView.xaml
new file mode 100644
index 0000000..b59ea6a
--- /dev/null
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Controls/QueryResultView.xaml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Controls/QueryResultView.xaml.cs b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Controls/QueryResultView.xaml.cs
new file mode 100644
index 0000000..9590d1f
--- /dev/null
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Controls/QueryResultView.xaml.cs
@@ -0,0 +1,103 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using Acr.UserDialogs;
+using Xamarin.Forms;
+using Xamarin.Forms.Xaml;
+using Xamarin.Neo4j.Managers;
+using Xamarin.Neo4j.Models;
+using Xamarin.Neo4j.Pages;
+using Xamarin.Neo4j.Utilities;
+
+namespace Xamarin.Neo4j.Controls
+{
+ [XamlCompilation(XamlCompilationOptions.Compile)]
+ public partial class QueryResultView : ContentView
+ {
+ private QueryResult QueryResult => (QueryResult) BindingContext;
+
+ public event EventHandler> CloseRequested;
+
+ private string _neovisHtml;
+
+ public QueryResultView()
+ {
+ InitializeComponent();
+ }
+
+ protected override void OnPropertyChanged(string propertyName = null)
+ {
+ base.OnPropertyChanged(propertyName);
+
+ if (propertyName == nameof(BindingContext))
+ {
+ ParseNeovisHtml();
+
+ graphView.Source = new HtmlWebViewSource()
+ {
+ Html = _neovisHtml
+ };
+ }
+ }
+
+ private void ParseNeovisHtml()
+ {
+ var assembly = Assembly.GetExecutingAssembly();
+ var resourceName = "Xamarin.Neo4j.Visualization.neovis.html";
+
+ using (var stream = assembly.GetManifestResourceStream(resourceName))
+ using (var reader = new StreamReader(stream))
+ {
+ var result = reader.ReadToEnd();
+
+ result = result.Replace("{{host}}", QueryResult.ConnectionString.Host);
+ result = result.Replace("{{port}}", QueryResult.ConnectionString.Port.ToString());
+ result = result.Replace("{{database}}", QueryResult.ConnectionString.Database);
+ result = result.Replace("{{username}}", QueryResult.ConnectionString.Username);
+ result = result.Replace("{{password}}", QueryResult.ConnectionString.Password);
+ result = result.Replace("{{encryption}}", QueryResult.ConnectionString.Encrypted ? "ENCRYPTION_ON" : "ENCRYPTION_OFF");
+ result = result.Replace("{{query}}", QueryResult.Query);
+ result = result.Replace("{{backgroundColor}}", App.Current.RequestedTheme == OSAppTheme.Dark ? "#292C31" : "#FFFFFF");
+
+ _neovisHtml = result;
+ }
+ }
+
+
+ private async void OpenNeovis(object sender, EventArgs e)
+ {
+ await Application.Current.MainPage.Navigation.PushAsync(new GraphPage(_neovisHtml));
+ }
+
+ private async void SaveQuery(object sender, EventArgs e)
+ {
+ var queryNameResult = await UserDialogs.Instance.PromptAsync("How should the query be called?");
+
+ if (queryNameResult.Ok)
+ {
+ var query = new Query()
+ {
+ Id = Guid.NewGuid(),
+ QueryText = QueryResult.Query,
+ Name = queryNameResult.Value,
+ };
+
+ SavedQueryManager.AddSavedQuery(query);
+ }
+ }
+
+ private void CloseResultView(object sender, EventArgs e)
+ {
+ CloseRequested?.Invoke(sender, new GenericEventArgs(QueryResult));
+ }
+
+ private async void OpenTableView(object sender, EventArgs e)
+ {
+ await Application.Current.MainPage.Navigation.PushAsync(new TablePage(QueryResult));
+ }
+ }
+}
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Converters/IsActiveConnectionConverter.cs b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Converters/IsActiveConnectionConverter.cs
new file mode 100644
index 0000000..a014874
--- /dev/null
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Converters/IsActiveConnectionConverter.cs
@@ -0,0 +1,33 @@
+//
+// IsActiveConnectionConverter.cs
+//
+// Trevi Awater
+// 13-01-2022
+//
+// © Xamarin.Neo4j
+//
+
+using System;
+using System.Globalization;
+using Xamarin.Forms;
+using Xamarin.Neo4j.Managers;
+using Xamarin.Neo4j.Models;
+
+namespace Xamarin.Neo4j.Converters
+{
+ public class IsActiveConnectionConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (value is Neo4jConnectionString targetConnection)
+ return targetConnection.Id == ConnectionStringManager.ActiveConnectionString?.Id;
+
+ return false;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotSupportedException();
+ }
+ }
+}
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Converters/JsonConvertConverter.cs b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Converters/JsonConvertConverter.cs
new file mode 100644
index 0000000..f8f7266
--- /dev/null
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Converters/JsonConvertConverter.cs
@@ -0,0 +1,29 @@
+//
+// JsonConvertConverter.cs
+//
+// Trevi Awater
+// 13-01-2022
+//
+// © Xamarin.Neo4j
+//
+
+using System;
+using System.Globalization;
+using Newtonsoft.Json;
+using Xamarin.Forms;
+
+namespace Xamarin.Neo4j.Converters
+{
+ public class JsonConvertConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ return JsonConvert.SerializeObject(value, Formatting.Indented);
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Managers/ConnectionStringManager.cs b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Managers/ConnectionStringManager.cs
index c01e884..8e4939a 100644
--- a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Managers/ConnectionStringManager.cs
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Managers/ConnectionStringManager.cs
@@ -22,6 +22,8 @@ namespace Xamarin.Neo4j.Managers
{
private const string ConnectionStringsKey = "connection_strings";
+ public static Neo4jConnectionString ActiveConnectionString { get; set; }
+
public static async Task> GetConnectionStrings()
{
var json = await SecureStorage.GetAsync(ConnectionStringsKey);
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Managers/SavedQueryManager.cs b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Managers/SavedQueryManager.cs
new file mode 100644
index 0000000..0f69268
--- /dev/null
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Managers/SavedQueryManager.cs
@@ -0,0 +1,59 @@
+//
+// SavedQueryManager.cs
+//
+// Trevi Awater
+// 11-01-2022
+//
+// © Xamarin.Neo4j
+//
+
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Newtonsoft.Json;
+using Xamarin.Essentials;
+using Xamarin.Neo4j.Models;
+
+namespace Xamarin.Neo4j.Managers
+{
+ public class SavedQueryManager
+ {
+ private const string SavedQueriesKey = "saved_queries";
+
+ public static List GetSavedQueries()
+ {
+ var json = Preferences.Get(SavedQueriesKey, null);
+
+ if (string.IsNullOrEmpty(json))
+ return new List();
+
+ return JsonConvert.DeserializeObject>(json);
+ }
+
+ public static void AddSavedQuery(Query query)
+ {
+ var savedQueries = GetSavedQueries();
+
+ savedQueries.Add(query);
+
+ SaveSavedQueries(savedQueries);
+ }
+
+ private static void SaveSavedQueries(IEnumerable savedQueries)
+ {
+ var json = JsonConvert.SerializeObject(savedQueries);
+
+ Preferences.Set(SavedQueriesKey, json);
+ }
+
+ public static void DeleteSavedQuery(Query query)
+ {
+ var savedQueries = GetSavedQueries();
+
+ savedQueries = savedQueries.Where(cs => cs.Id != query.Id)
+ .ToList();
+
+ SaveSavedQueries(savedQueries);
+ }
+ }
+}
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Models/Query.cs b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Models/Query.cs
new file mode 100644
index 0000000..d740250
--- /dev/null
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Models/Query.cs
@@ -0,0 +1,22 @@
+//
+// Query.cs
+//
+// Trevi Awater
+// 11-01-2022
+//
+// © Xamarin.Neo4j
+//
+
+using System;
+
+namespace Xamarin.Neo4j.Models
+{
+ public class Query
+ {
+ public Guid Id { get; set; }
+
+ public string Name { get; set; }
+
+ public string QueryText { get; set; }
+ }
+}
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Models/QueryResult.cs b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Models/QueryResult.cs
index 6345228..ea2955d 100644
--- a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Models/QueryResult.cs
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Models/QueryResult.cs
@@ -7,6 +7,7 @@
// © Xamarin.Neo4j
//
+using System;
using System.Collections;
using System.Collections.Generic;
using Neo4j.Driver;
@@ -15,16 +16,18 @@ namespace Xamarin.Neo4j.Models
{
public class QueryResult
{
+ public Guid Id { get; set; }
+
public bool Success { get; set; }
+ public bool CanDisplayGraph { get; set; }
+
public string ErrorMessage { get; set; }
public string Query { get; set; }
public Neo4jConnectionString ConnectionString { get; set; }
- public IEnumerable Nodes { get; set; }
-
- public IEnumerable Relationships { get; set; }
+ public Dictionary> Results { get; set; }
}
}
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/AddConnectionPage.xaml b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/AddConnectionPage.xaml
index 27112ab..91c11d7 100644
--- a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/AddConnectionPage.xaml
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/AddConnectionPage.xaml
@@ -32,17 +32,9 @@
-
-
-
-
-
-
-
-
-
-
-
+
+
+
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/ConnectionsPage.xaml b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/ConnectionsPage.xaml
index bde5c7a..10d2859 100644
--- a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/ConnectionsPage.xaml
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/ConnectionsPage.xaml
@@ -3,9 +3,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
+
+
-
-
+
+
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/ConnectionsPage.xaml.cs b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/ConnectionsPage.xaml.cs
index 1032c40..982d22b 100644
--- a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/ConnectionsPage.xaml.cs
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/ConnectionsPage.xaml.cs
@@ -6,6 +6,7 @@ using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
+using Xamarin.Neo4j.Managers;
using Xamarin.Neo4j.Models;
using Xamarin.Neo4j.ViewModels;
@@ -30,11 +31,9 @@ namespace Xamarin.Neo4j.Pages
base.OnAppearing();
}
- private async void StartSession(object sender, ItemTappedEventArgs e)
+ private void SetActive(object sender, ItemTappedEventArgs e)
{
- var connectionString = (Neo4jConnectionString)e.Item;
-
- await Navigation.PushAsync(new SessionPage(connectionString));
+ ViewModel.SetActiveConnectionString((Neo4jConnectionString)e.Item);
}
}
}
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/VisualizationPage.xaml b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/GraphPage.xaml
similarity index 85%
rename from Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/VisualizationPage.xaml
rename to Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/GraphPage.xaml
index 62849ff..5b6ef2d 100644
--- a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/VisualizationPage.xaml
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/GraphPage.xaml
@@ -3,7 +3,7 @@
+ x:Class="Xamarin.Neo4j.Pages.GraphPage">
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/VisualizationPage.xaml.cs b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/GraphPage.xaml.cs
similarity index 65%
rename from Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/VisualizationPage.xaml.cs
rename to Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/GraphPage.xaml.cs
index a0d49c0..8433a04 100644
--- a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/VisualizationPage.xaml.cs
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/GraphPage.xaml.cs
@@ -12,13 +12,13 @@ using Xamarin.Neo4j.ViewModels;
namespace Xamarin.Neo4j.Pages
{
[XamlCompilation(XamlCompilationOptions.Compile)]
- public partial class VisualizationPage : ContentPage
+ public partial class GraphPage : ContentPage
{
- public VisualizationPage(QueryResult queryResult)
+ public GraphPage(string html)
{
InitializeComponent();
- BindingContext = new VisualizationViewModel(Navigation, queryResult);
+ BindingContext = new GraphViewModel(Navigation, html);
}
}
}
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/QueriesPage.xaml b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/QueriesPage.xaml
index 2b0a9a1..4e3507f 100644
--- a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/QueriesPage.xaml
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/QueriesPage.xaml
@@ -4,6 +4,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:fonts="clr-namespace:Xamarin.Neo4j.Fonts;assembly=Xamarin.Neo4j"
Title="Queries"
+ x:Name="queriesPage"
x:Class="Xamarin.Neo4j.Pages.QueriesPage">
-
-
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/QueriesPage.xaml.cs b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/QueriesPage.xaml.cs
index d1fd713..84ba7da 100644
--- a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/QueriesPage.xaml.cs
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/QueriesPage.xaml.cs
@@ -6,6 +6,7 @@ using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
+using Xamarin.Neo4j.Models;
using Xamarin.Neo4j.ViewModels;
namespace Xamarin.Neo4j.Pages
@@ -13,11 +14,25 @@ namespace Xamarin.Neo4j.Pages
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class QueriesPage : ContentPage
{
+ private QueriesViewModel ViewModel => (QueriesViewModel)BindingContext;
+
public QueriesPage()
{
InitializeComponent();
BindingContext = new QueriesViewModel(Navigation);
}
+
+ protected override void OnAppearing()
+ {
+ ViewModel.LoadQueries();
+
+ base.OnAppearing();
+ }
+
+ private void StartSessionWithQuery(object sender, ItemTappedEventArgs e)
+ {
+ ViewModel.StartSession((Query)e.Item);
+ }
}
}
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/RootPage.xaml b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/RootPage.xaml
index ed32a4e..895f784 100644
--- a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/RootPage.xaml
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/RootPage.xaml
@@ -7,5 +7,6 @@
+
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/SessionPage.xaml b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/SessionPage.xaml
index 64cf8ec..9bfdf69 100644
--- a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/SessionPage.xaml
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/SessionPage.xaml
@@ -4,6 +4,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:fonts="clr-namespace:Xamarin.Neo4j.Fonts;assembly=Xamarin.Neo4j"
xmlns:controls="clr-namespace:Xamarin.Neo4j.Controls;assembly=Xamarin.Neo4j"
+ xmlns:pancakeView="clr-namespace:Xamarin.Forms.PancakeView;assembly=Xamarin.Forms.PancakeView"
x:Class="Xamarin.Neo4j.Pages.SessionPage">
@@ -24,17 +25,35 @@
+
+
+
+
+
+
+
+
-
+
+
+
+
+
-
-
+
+
+
+
+
+
-
+
-
-
+
+
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/SessionPage.xaml.cs b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/SessionPage.xaml.cs
index 159622d..6cb7668 100644
--- a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/SessionPage.xaml.cs
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/SessionPage.xaml.cs
@@ -7,6 +7,7 @@ using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using Xamarin.Neo4j.Models;
+using Xamarin.Neo4j.Utilities;
using Xamarin.Neo4j.ViewModels;
namespace Xamarin.Neo4j.Pages
@@ -16,11 +17,16 @@ namespace Xamarin.Neo4j.Pages
{
private SessionViewModel ViewModel => (SessionViewModel) BindingContext;
- public SessionPage(Neo4jConnectionString connectionString)
+ public SessionPage(Neo4jConnectionString connectionString, string initialQuery = null)
{
InitializeComponent();
- BindingContext = new SessionViewModel(Navigation, connectionString);
+ BindingContext = new SessionViewModel(Navigation, connectionString, initialQuery);
+
+ MessagingCenter.Subscribe(this, "ResetScroll", (sender) =>
+ {
+ resultsCollection.ScrollTo(0, 0, ScrollToPosition.Start, true);
+ });
}
private void FocusDatabasePicker(object sender, EventArgs e)
@@ -28,9 +34,9 @@ namespace Xamarin.Neo4j.Pages
databasePicker.Focus();
}
- private void OnExecuteQuery(object sender, EventArgs e)
+ private void CloseResultView(object sender, GenericEventArgs e)
{
- ViewModel.ExecuteQuery();
+ ViewModel.DeleteQueryResult(e.Data);
}
}
}
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/SettingsPage.xaml b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/SettingsPage.xaml
new file mode 100644
index 0000000..9d601e7
--- /dev/null
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/SettingsPage.xaml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/SettingsPage.xaml.cs b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/SettingsPage.xaml.cs
new file mode 100644
index 0000000..e5dc3d1
--- /dev/null
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/SettingsPage.xaml.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms;
+using Xamarin.Forms.Xaml;
+using Xamarin.Neo4j.ViewModels;
+
+namespace Xamarin.Neo4j.Pages
+{
+ [XamlCompilation(XamlCompilationOptions.Compile)]
+ public partial class SettingsPage : ContentPage
+ {
+ public SettingsPage()
+ {
+ InitializeComponent();
+
+ BindingContext = new SettingsViewModel(Navigation);
+ }
+ }
+}
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/TablePage.xaml b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/TablePage.xaml
new file mode 100644
index 0000000..f66de7a
--- /dev/null
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/TablePage.xaml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/TablePage.xaml.cs b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/TablePage.xaml.cs
new file mode 100644
index 0000000..252e318
--- /dev/null
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Pages/TablePage.xaml.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms;
+using Xamarin.Forms.Xaml;
+using Xamarin.Neo4j.Models;
+using Xamarin.Neo4j.ViewModels;
+
+namespace Xamarin.Neo4j.Pages
+{
+ [XamlCompilation(XamlCompilationOptions.Compile)]
+ public partial class TablePage : ContentPage
+ {
+ public TablePage(QueryResult queryResult)
+ {
+ InitializeComponent();
+
+ BindingContext = new TableViewModel(Navigation, queryResult);
+ }
+ }
+}
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Services/Interfaces/IScreenSizeService.cs b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Services/Interfaces/IScreenSizeService.cs
new file mode 100644
index 0000000..0efbff7
--- /dev/null
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Services/Interfaces/IScreenSizeService.cs
@@ -0,0 +1,9 @@
+namespace Xamarin.Neo4j.Services
+{
+ public interface IScreenSizeService
+ {
+ int GetScreenHeight();
+
+ int GetScreenWidth();
+ }
+}
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Services/Neo4jService.cs b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Services/Neo4jService.cs
index 365cbfc..c61468b 100644
--- a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Services/Neo4jService.cs
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j/Services/Neo4jService.cs
@@ -87,16 +87,21 @@ namespace Xamarin.Neo4j.Services
public async Task ExecuteQuery(string query, Neo4jConnectionString connectionString)
{
+ var results = new Dictionary>();
+
+ var canDisplayGraph = false;
+
try
{
var session = GraphClient.Driver.AsyncSession(d => d.WithDatabase(connectionString.Database));
var cursor = await session.RunAsync(query);
- var nodes = new List();
- var relationships = new List();
-
while (await cursor.FetchAsync())
{
+ foreach (var key in cursor.Current.Keys)
+ if (results.ContainsKey(key) == false)
+ results.Add(key, new List