mirror of
https://github.com/awatertrevi/xamarin-neo4j.git
synced 2026-09-22 09:05:29 +00:00
Design: dashboard-style ConnectionsPage with rich connection cards
- Add header with ProjectDiagram icon, app title, and connection count - Replace plain ListView with styled cards (Border + rounded corners) - Each card shows: database icon, name, host, scheme badge, secure lock - Inline edit/delete buttons on each card (pencil + trash icons) - Hide nav bar title (dashboard header replaces it) - Add computed properties: IsSecure, SchemeShortName, DisplayName - Add ConnectionCountLabel to ViewModel - Add OpenConnection command for card tap handling Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -27,6 +27,12 @@ namespace Xamarin.Neo4j.Models
|
||||
|
||||
public string Password { get; set; }
|
||||
|
||||
public bool IsSecure => Scheme?.Contains("+s") ?? false;
|
||||
|
||||
public string SchemeShortName => Scheme != null && Scheme.StartsWith("bolt") ? "bolt" : "neo4j";
|
||||
|
||||
public string DisplayName => string.IsNullOrWhiteSpace(Name) ? Host : Name;
|
||||
|
||||
public Tuple<string, bool, bool> ParseHost()
|
||||
{
|
||||
var fullHost = Scheme + Host;
|
||||
|
||||
@@ -3,30 +3,130 @@
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
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"
|
||||
x:Class="Xamarin.Neo4j.Pages.ConnectionsPage"
|
||||
x:Name="connectionsPage"
|
||||
Title="PocketGraph">
|
||||
Title=" ">
|
||||
|
||||
<ContentPage.ToolbarItems>
|
||||
<ToolbarItem Text="Settings" Order="Secondary" Command="{Binding Commands[OpenSettings]}" />
|
||||
</ContentPage.ToolbarItems>
|
||||
|
||||
<ContentPage.Content>
|
||||
<Grid>
|
||||
<ListView ItemsSource="{Binding ConnectionStrings}" HasUnevenRows="True" SelectionMode="None" ItemTapped="OpenSession" IsVisible="{Binding HasItems}">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<controls:ConnectionCell>
|
||||
<controls:ConnectionCell.ContextActions>
|
||||
<MenuItem Text="Edit" Command="{Binding BindingContext.Commands[EditConnectionString], Source={x:Reference connectionsPage}}" CommandParameter="{Binding .}" />
|
||||
<MenuItem Text="Delete" Command="{Binding BindingContext.Commands[DeleteConnectionString], Source={x:Reference connectionsPage}}" CommandParameter="{Binding .}" IsDestructive="true" />
|
||||
</controls:ConnectionCell.ContextActions>
|
||||
</controls:ConnectionCell>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
<Grid RowDefinitions="Auto,*">
|
||||
|
||||
<!-- Row 0: Dashboard header -->
|
||||
<StackLayout Grid.Row="0" Spacing="4" Padding="16,16,16,12" HorizontalOptions="Center">
|
||||
<Label Text="{x:Static fonts:FontAwesomeSolid.ProjectDiagram}"
|
||||
FontFamily="{StaticResource FontAwesomeSolid}"
|
||||
FontSize="32"
|
||||
TextColor="{DynamicResource PrimaryTextColor}"
|
||||
HorizontalOptions="Center"
|
||||
Margin="0,0,0,4" />
|
||||
<Label Text="PocketGraph"
|
||||
FontSize="22" FontAttributes="Bold"
|
||||
TextColor="{DynamicResource PrimaryTextColor}"
|
||||
HorizontalOptions="Center" />
|
||||
<Label Text="{Binding ConnectionCountLabel}"
|
||||
FontSize="13"
|
||||
TextColor="{DynamicResource SecondaryTextColor}"
|
||||
HorizontalOptions="Center" />
|
||||
</StackLayout>
|
||||
|
||||
<!-- Row 1: Connection cards + empty state + FAB -->
|
||||
<Grid Grid.Row="1">
|
||||
|
||||
<!-- Scrollable connection cards -->
|
||||
<ScrollView IsVisible="{Binding HasItems}">
|
||||
<StackLayout BindableLayout.ItemsSource="{Binding ConnectionStrings}"
|
||||
Spacing="0" Padding="0,0,0,80">
|
||||
<BindableLayout.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border Margin="16,0,16,8"
|
||||
BackgroundColor="{DynamicResource Extreme}"
|
||||
Stroke="{DynamicResource QueryTextBorder}"
|
||||
StrokeThickness="1"
|
||||
StrokeShape="RoundRectangle 10">
|
||||
<Grid ColumnDefinitions="Auto,*,Auto" Padding="14,12">
|
||||
<Grid.GestureRecognizers>
|
||||
<TapGestureRecognizer
|
||||
Command="{Binding BindingContext.Commands[OpenConnection], Source={x:Reference connectionsPage}}"
|
||||
CommandParameter="{Binding .}" />
|
||||
</Grid.GestureRecognizers>
|
||||
|
||||
<!-- Database icon -->
|
||||
<Border Grid.Column="0"
|
||||
WidthRequest="40" HeightRequest="40"
|
||||
StrokeThickness="0"
|
||||
StrokeShape="RoundRectangle 20"
|
||||
BackgroundColor="{DynamicResource QueryActionBar}"
|
||||
VerticalOptions="Center">
|
||||
<Label Text="{x:Static fonts:FontAwesomeSolid.Database}"
|
||||
FontFamily="{StaticResource FontAwesomeSolid}"
|
||||
FontSize="16"
|
||||
TextColor="{DynamicResource SecondaryTextColor}"
|
||||
HorizontalOptions="Center"
|
||||
VerticalOptions="Center" />
|
||||
</Border>
|
||||
|
||||
<!-- Name + Host + scheme badge inline -->
|
||||
<StackLayout Grid.Column="1" Spacing="3" Padding="12,0,8,0" VerticalOptions="Center">
|
||||
<Label Text="{Binding DisplayName}"
|
||||
FontSize="15" FontAttributes="Bold"
|
||||
TextColor="{DynamicResource PrimaryTextColor}"
|
||||
LineBreakMode="TailTruncation" MaxLines="1" />
|
||||
<StackLayout Orientation="Horizontal" Spacing="6">
|
||||
<Label Text="{Binding Host}"
|
||||
FontSize="12"
|
||||
TextColor="{DynamicResource SecondaryTextColor}"
|
||||
LineBreakMode="TailTruncation"
|
||||
VerticalOptions="Center" />
|
||||
<Label IsVisible="{Binding IsSecure}"
|
||||
Text="{x:Static fonts:FontAwesomeSolid.Lock}"
|
||||
FontFamily="{StaticResource FontAwesomeSolid}"
|
||||
FontSize="9"
|
||||
TextColor="{DynamicResource SecondaryTextColor}"
|
||||
VerticalOptions="Center" />
|
||||
<Border BackgroundColor="{DynamicResource QueryActionBar}"
|
||||
StrokeThickness="0"
|
||||
StrokeShape="RoundRectangle 6"
|
||||
Padding="6,2">
|
||||
<Label Text="{Binding SchemeShortName}"
|
||||
FontSize="9" FontAttributes="Bold"
|
||||
TextColor="{DynamicResource SecondaryTextColor}"
|
||||
VerticalOptions="Center" />
|
||||
</Border>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
|
||||
<!-- Edit / Delete -->
|
||||
<StackLayout Grid.Column="2" Orientation="Horizontal" Spacing="0" VerticalOptions="Center">
|
||||
<Button Text="{x:Static fonts:FontAwesomeSolid.PencilAlt}"
|
||||
FontFamily="{StaticResource FontAwesomeSolid}"
|
||||
FontSize="14"
|
||||
WidthRequest="38" HeightRequest="38"
|
||||
BackgroundColor="Transparent"
|
||||
TextColor="{DynamicResource SecondaryTextColor}"
|
||||
Padding="0"
|
||||
Command="{Binding BindingContext.Commands[EditConnectionString], Source={x:Reference connectionsPage}}"
|
||||
CommandParameter="{Binding .}" />
|
||||
<Button Text="{x:Static fonts:FontAwesomeSolid.TrashAlt}"
|
||||
FontFamily="{StaticResource FontAwesomeSolid}"
|
||||
FontSize="14"
|
||||
WidthRequest="38" HeightRequest="38"
|
||||
BackgroundColor="Transparent"
|
||||
TextColor="{DynamicResource SecondaryTextColor}"
|
||||
Padding="0"
|
||||
Command="{Binding BindingContext.Commands[DeleteConnectionString], Source={x:Reference connectionsPage}}"
|
||||
CommandParameter="{Binding .}" />
|
||||
</StackLayout>
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</BindableLayout.ItemTemplate>
|
||||
</StackLayout>
|
||||
</ScrollView>
|
||||
|
||||
<!-- Empty state -->
|
||||
<StackLayout IsVisible="{Binding IsEmpty}" VerticalOptions="Center" HorizontalOptions="Center" Spacing="12">
|
||||
<Label Text="{x:Static fonts:FontAwesomeSolid.Server}"
|
||||
FontFamily="{StaticResource FontAwesomeSolid}"
|
||||
@@ -50,11 +150,13 @@ x:Class="Xamarin.Neo4j.Pages.ConnectionsPage"
|
||||
FontSize="20"
|
||||
WidthRequest="56" HeightRequest="56"
|
||||
CornerRadius="28"
|
||||
BackgroundColor="{DynamicResource Accent}"
|
||||
BackgroundColor="{DynamicResource NavigationBarColor}"
|
||||
TextColor="White"
|
||||
VerticalOptions="End" HorizontalOptions="End"
|
||||
Margin="0,0,16,16"
|
||||
Command="{Binding Commands[AddConnection]}" />
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
</ContentPage.Content>
|
||||
</ContentPage>
|
||||
|
||||
@@ -42,9 +42,7 @@ namespace Xamarin.Neo4j.Pages
|
||||
ViewModel.LoadConnectionStrings();
|
||||
}
|
||||
|
||||
private void OpenSession(object sender, ItemTappedEventArgs e)
|
||||
{
|
||||
ViewModel.OpenSession((Neo4jConnectionString)e.Item);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,12 @@ namespace Xamarin.Neo4j.ViewModels
|
||||
LoadConnectionStrings();
|
||||
}));
|
||||
|
||||
Commands.Add("OpenConnection", new Command((o) =>
|
||||
{
|
||||
if (o is Neo4jConnectionString cs)
|
||||
OpenSession(cs);
|
||||
}));
|
||||
|
||||
Commands.Add("OpenSettings", new Command(async () =>
|
||||
{
|
||||
await Navigation.PushAsync(new SettingsPage());
|
||||
@@ -87,6 +93,7 @@ namespace Xamarin.Neo4j.ViewModels
|
||||
OnPropertyChanged(nameof(ConnectionStrings));
|
||||
OnPropertyChanged(nameof(IsEmpty));
|
||||
OnPropertyChanged(nameof(HasItems));
|
||||
OnPropertyChanged(nameof(ConnectionCountLabel));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,6 +101,20 @@ namespace Xamarin.Neo4j.ViewModels
|
||||
|
||||
public bool HasItems => !IsEmpty;
|
||||
|
||||
public string ConnectionCountLabel
|
||||
{
|
||||
get
|
||||
{
|
||||
var count = _connectionStrings?.Count() ?? 0;
|
||||
return count switch
|
||||
{
|
||||
0 => "No connections yet",
|
||||
1 => "1 connection",
|
||||
_ => $"{count} connections"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user