Merge branch 'improvements/homescreen' into net9-upgradeyxc

.
klsdfhgölsdfhg <yxc<yxc<yxc

dfasdfasdf

:wq

:::::WQ

W
Q:WQ
W
Q:WQ:Wdfasdfasdf

:wq

:::::WQ

W
Q:WQ
W
Q:WQ:Wdfasdfasdf

:wq

:::::WQ

W
Q:WQ
W
Q:WQ:Wdfasdfasdf

:wq

:::::WQ

W
Q:WQ
W
Q:WQ:Wdfasdfasdf

:wq

:::::WQ

W
Q:WQ
W
Q:WQ:Wdfasdfasdf

:wq

:::::WQ

W
Q:WQ
W
Q:WQ:W:
This commit is contained in:
Max Mannstein 2025-08-09 16:22:56 +02:00
commit c49c043801
3 changed files with 223 additions and 245 deletions

View File

@ -112,6 +112,12 @@ namespace gehGassiApp.ViewModels
[ObservableProperty] [ObservableProperty]
private ObservableCollection<DogWalkerLookup> _walkers; private ObservableCollection<DogWalkerLookup> _walkers;
/// <summary>
/// First 10 walkers for the home screen display
/// </summary>
[ObservableProperty]
private ObservableCollection<DogWalkerLookup> _first10Walkers;
[ObservableProperty] [ObservableProperty]
private DogWalkerLookup _selectedWalker; private DogWalkerLookup _selectedWalker;
@ -541,6 +547,9 @@ namespace gehGassiApp.ViewModels
Walkers = requests.Value.ToObservableCollection(); Walkers = requests.Value.ToObservableCollection();
// Set First10Walkers for the home screen display
First10Walkers = requests.Value.Take(10).ToObservableCollection();
_total = requests.Total; _total = requests.Total;
_skip = requests.Skip + requests.Take; _skip = requests.Skip + requests.Take;
} }
@ -549,6 +558,7 @@ namespace gehGassiApp.ViewModels
_total = 0; _total = 0;
_skip = 0; _skip = 0;
Walkers = null; Walkers = null;
First10Walkers = null;
} }
} }
catch (Exception ex) catch (Exception ex)
@ -557,6 +567,7 @@ namespace gehGassiApp.ViewModels
_total = 0; _total = 0;
_skip = 0; _skip = 0;
Walkers = null; Walkers = null;
First10Walkers = null;
} }
} }

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<controls:BaseContentPage <controls:BaseContentPage
x:Class="gehGassiApp.Views.HomeView" x:Class="gehGassiApp.Views.HomeView"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
@ -23,20 +23,29 @@
</controls:BaseContentPage.TitleView> </controls:BaseContentPage.TitleView>
<ContentPage.Content> <ContentPage.Content>
<AbsoluteLayout>
<!-- Main scrollable content (full screen) -->
<RefreshView
x:Name="homeRefreshView"
AbsoluteLayout.LayoutBounds="0,0,1,1"
AbsoluteLayout.LayoutFlags="All"
BackgroundColor="#ffffff"
Command="{Binding RefreshWalkersCommand}"
IsRefreshing="{Binding WalkersRefreshing}">
<ScrollView>
<Grid <Grid
x:Name="rootHomeGrid" x:Name="rootHomeGrid"
Padding="20,20,20,0" Padding="20,20,20,90"
HorizontalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"
RowDefinitions="Auto,*" RowDefinitions="Auto,Auto"
VerticalOptions="FillAndExpand"> VerticalOptions="FillAndExpand">
<VerticalStackLayout <VerticalStackLayout
x:Name="rootVerticalStackLayout" x:Name="rootVerticalStackLayout"
Grid.Row="0" Grid.Row="0"
HorizontalOptions="Fill" HorizontalOptions="Fill"
SizeChanged="rootVerticalStackLayout_SizeChanged"
Spacing="0" Spacing="0"
VerticalOptions="FillAndExpand"> VerticalOptions="Start">
<Border x:Name="permissionStatusBorder" Style="{StaticResource PermissionStatusBorder}"> <Border x:Name="permissionStatusBorder" Style="{StaticResource PermissionStatusBorder}">
<Label Style="{StaticResource PermissionStatusLabel}" Text="{x:Static res:Text.Permission_Location_Error}" /> <Label Style="{StaticResource PermissionStatusLabel}" Text="{x:Static res:Text.Permission_Location_Error}" />
<Border.IsVisible> <Border.IsVisible>
@ -112,100 +121,49 @@
Style="{StaticResource H6_Blue}" Style="{StaticResource H6_Blue}"
Text="{x:Static res:Text.Common_DogWalkers_NearYou}" /> Text="{x:Static res:Text.Common_DogWalkers_NearYou}" />
<!-- Walker StackLayout (first 10) -->
<StackLayout
</VerticalStackLayout> x:Name="walkersStackLayout"
BindableLayout.ItemsSource="{Binding First10Walkers}"
<controls:EmptyListViewControl Spacing="12">
Grid.Row="1" <BindableLayout.ItemTemplate>
ImageHeight="150"
IsBusy="{Binding IsBusy}"
IsNotBusy="{Binding IsNotBusy}"
IsVisible="{Binding Walkers, Converter={StaticResource IsListNullOrEmptyConverter}}"
ListSource="{Binding Walkers}"
NotFoundImage="walking_dogs"
NotFoundText="{x:Static res:Text.Walker_NotFound}"
RefreshCommand="{Binding RefreshWalkersCommand}"
SearchImage="walking_dogs"
SearchText="{x:Static res:Text.Walker_Searching}" />
<RefreshView
x:Name="homeRefreshView"
Grid.Row="1"
BackgroundColor="#ffffff"
Command="{Binding RefreshWalkersCommand}"
HorizontalOptions="FillAndExpand"
IsRefreshing="{Binding WalkersRefreshing}"
IsVisible="{Binding Walkers, Converter={StaticResource IsListNotNullOrEmptyConverter}}"
Refreshing="RefreshView_Refreshing"
VerticalOptions="FillAndExpand">
<Grid HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<CollectionView
x:Name="homeCollectionView"
Background="#ffffff"
HorizontalOptions="FillAndExpand"
ItemsSource="{Binding Walkers}"
RemainingItemsThreshold="5"
RemainingItemsThresholdReachedCommand="{Binding LoadMoreCommand}"
Scrolled="homeCollectionView_Scrolled"
SelectedItem="{Binding SelectedWalker}"
SelectionMode="Single"
VerticalOptions="Fill"
VerticalScrollBarVisibility="Never">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical" VerticalItemSpacing="12" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate> <DataTemplate>
<!--<SwipeView BackgroundColor="{StaticResource Primary_White}" Margin="0,0,0,12"> <controls:WalkerListControl DogOwnerHasPremium="{Binding Source={RelativeSource AncestorType={x:Type viewmodels:HomeViewModel}}, Path=IsPremiumUser}" Walker="{Binding .}">
<SwipeView.LeftItems>
<SwipeItems>
<SwipeItemView Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodels:HomeViewModel}}, Path=BlockCommand}" CommandParameter="{Binding .}">
<StackLayout HorizontalOptions="Center" VerticalOptions="Center">
<Image Source="block_user" WidthRequest="24" HeightRequest="24" HorizontalOptions="Center" VerticalOptions="Center"/>
<Label Text="{x:Static res:Text.Common_Block}" HorizontalOptions="Center" Style="{StaticResource BodyS_GreyDark}"></Label>
</StackLayout>
</SwipeItemView>
</SwipeItems>
</SwipeView.LeftItems>
<SwipeView.RightItems>
<SwipeItems>
<SwipeItemView Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodels:HomeViewModel}}, Path=ReportCommand}" CommandParameter="{Binding .}">
<StackLayout HorizontalOptions="Center" VerticalOptions="Center">
<Image Source="report_user" WidthRequest="24" HeightRequest="24" HorizontalOptions="Center" VerticalOptions="Center"/>
<Label Text="{x:Static res:Text.Common_Report}" HorizontalOptions="Center" Style="{StaticResource BodyS_GreyDark}"></Label>
</StackLayout>
</SwipeItemView>
</SwipeItems>
</SwipeView.RightItems>-->
<controls:WalkerListControl DogOwnerHasPremium="{Binding IsPremiumUser}" Walker="{Binding .}">
<controls:WalkerListControl.GestureRecognizers> <controls:WalkerListControl.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodels:HomeViewModel}}, Path=WalkerSelectedCommand}" CommandParameter="{Binding .}" /> <TapGestureRecognizer Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodels:HomeViewModel}}, Path=WalkerSelectedCommand}" CommandParameter="{Binding .}" />
</controls:WalkerListControl.GestureRecognizers> </controls:WalkerListControl.GestureRecognizers>
</controls:WalkerListControl> </controls:WalkerListControl>
<!--<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="CommonStates">
<VisualState Name="Selected">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="{StaticResource Primary_White}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>-->
<!--</SwipeView>-->
</DataTemplate> </DataTemplate>
</CollectionView.ItemTemplate> </BindableLayout.ItemTemplate>
</CollectionView> </StackLayout>
<!-- "Alle anzeigen" Link Label -->
<Label
Margin="0,16,0,0"
Style="{StaticResource LinkLabelStyle}"
HorizontalOptions="Center"
Text="Alle anzeigen">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding NavigateCommand}" CommandParameter="{x:Static viewmodels:MenuSelected.Walkers}" />
</Label.GestureRecognizers>
</Label>
</VerticalStackLayout>
</Grid> </Grid>
</ScrollView>
</RefreshView> </RefreshView>
<!-- Floating Public Request Button (over content) -->
<Button <Button
Grid.Row="0" Margin="0,0,0,20"
Grid.RowSpan="2" AbsoluteLayout.LayoutBounds="0.5,1,300,90"
Margin="0,0,0,10" AbsoluteLayout.LayoutFlags="PositionProportional"
BackgroundColor="{StaticResource Primary}"
Command="{Binding CreatePublicWalkRequestCommand}" Command="{Binding CreatePublicWalkRequestCommand}"
ContentLayout="Left, 5" ContentLayout="Left, 5"
HorizontalOptions="CenterAndExpand" CornerRadius="15"
HorizontalOptions="Center"
LineBreakMode="TailTruncation" LineBreakMode="TailTruncation"
Text="{x:Static res:Text.PublicWalkRequest_Title}" Text="{x:Static res:Text.PublicWalkRequest_Title}"
VerticalOptions="End"> VerticalOptions="End">
@ -217,7 +175,7 @@
</Button.ImageSource> </Button.ImageSource>
</Button> </Button>
</Grid> </AbsoluteLayout>
</ContentPage.Content> </ContentPage.Content>

View File

@ -10,9 +10,11 @@ public partial class HomeView : BaseContentPage
IDeviceInstallationService _deviceInstallationService; IDeviceInstallationService _deviceInstallationService;
IDeviceInstallationService DeviceInstallationService => _deviceInstallationService ??= ServiceHelper.GetService<IDeviceInstallationService>(); IDeviceInstallationService DeviceInstallationService => _deviceInstallationService ??= ServiceHelper.GetService<IDeviceInstallationService>();
private HomeViewModel ViewModel => BindingContext as HomeViewModel; private HomeViewModel ViewModel => BindingContext as HomeViewModel;
private bool _isRowHidden = false;
private double _initialRowHeight; // COMMENTED OUT: Animation variables for collapsing header
private bool _animationRunning = false; //private bool _isRowHidden = false;
//private double _initialRowHeight;
//private bool _animationRunning = false;
/// <summary> /// <summary>
/// Erstellt eine Instanz /// Erstellt eine Instanz
@ -31,10 +33,13 @@ public partial class HomeView : BaseContentPage
await ViewModel.InitializeAsync(this); await ViewModel.InitializeAsync(this);
var width = DeviceDisplay.Current.MainDisplayInfo.Width / DeviceDisplay.Current.MainDisplayInfo.Density; var width = DeviceDisplay.Current.MainDisplayInfo.Width / DeviceDisplay.Current.MainDisplayInfo.Density;
ViewModel.NextWalkWidth = width * 0.8; ViewModel.NextWalkWidth = width * 0.8;
_isRowHidden = false;
_initialRowHeight = 0; // COMMENTED OUT: Animation initialization
_animationRunning = false; //_isRowHidden = false;
rootVerticalStackLayout.HeightRequest = -1; //_initialRowHeight = 0;
//_animationRunning = false;
//rootVerticalStackLayout.HeightRequest = -1;
#if IOS #if IOS
if (DeviceInstallationService.NotificationsSupported) if (DeviceInstallationService.NotificationsSupported)
{ {
@ -50,74 +55,78 @@ public partial class HomeView : BaseContentPage
await ViewModel.DisappearingAsync(this); await ViewModel.DisappearingAsync(this);
} }
//Workaround für den IOS-Bug der Höhenberechnung! Siehe https://github.com/dotnet/maui/issues/8820 // COMMENTED OUT: Workaround für den IOS-Bug der Höhenberechnung! Siehe https://github.com/dotnet/maui/issues/8820
private void rootVerticalStackLayout_SizeChanged(object sender, EventArgs e) //private void rootVerticalStackLayout_SizeChanged(object sender, EventArgs e)
{ //{
if(!_isRowHidden && rootVerticalStackLayout.Height > _initialRowHeight) // if(!_isRowHidden && rootVerticalStackLayout.Height > _initialRowHeight)
_initialRowHeight = rootVerticalStackLayout.Height; // _initialRowHeight = rootVerticalStackLayout.Height;
} //}
private async void homeCollectionView_Scrolled(object sender, ItemsViewScrolledEventArgs e) // COMMENTED OUT: Scroll handler for collapsing animation
{ //private async void homeCollectionView_Scrolled(object sender, ItemsViewScrolledEventArgs e)
if(_animationRunning) //{
return; // if(_animationRunning)
// return;
//
// if (e.VerticalDelta > 0 && e.VerticalOffset >= 50 && !_isRowHidden)
// {
// await HideHeader();
// }
// else if (e.VerticalDelta < 0 && e.VerticalOffset <= 50 && _isRowHidden)
// {
// await ShowHeader();
// }
//}
if (e.VerticalDelta > 0 && e.VerticalOffset >= 50 && !_isRowHidden) // COMMENTED OUT: Show header animation
{ //private async Task ShowHeader()
await HideHeader(); //{
} // homeRefreshView.IsEnabled = false;
else if (e.VerticalDelta < 0 && e.VerticalOffset <= 50 && _isRowHidden) // homeCollectionView.IsEnabled = false;
{ // _isRowHidden = false;
await ShowHeader(); // _animationRunning = true;
} // var animation = new Animation(v => rootVerticalStackLayout.HeightRequest = v, 0, _initialRowHeight);
}
private async Task ShowHeader() // MainThread.BeginInvokeOnMainThread(() =>
{ // {
homeRefreshView.IsEnabled = false; // animation.Commit(this, "HideRowAnimation", length: 500, easing: Easing.SinIn);
homeCollectionView.IsEnabled = false; //
_isRowHidden = false; // });
_animationRunning = true;
var animation = new Animation(v => rootVerticalStackLayout.HeightRequest = v, 0, _initialRowHeight);
MainThread.BeginInvokeOnMainThread(() => // await Task.Delay(500);
{ // _animationRunning = false;
animation.Commit(this, "HideRowAnimation", length: 500, easing: Easing.SinIn); // homeCollectionView.IsEnabled = true;
// homeRefreshView.IsEnabled = true;
//}
}); // COMMENTED OUT: Hide header animation
//private async Task HideHeader()
//{
// homeRefreshView.IsEnabled = false;
// homeCollectionView.IsEnabled = false;
// _isRowHidden = true;
// _animationRunning = true;
// var animation = new Animation(v => rootVerticalStackLayout.HeightRequest = v, _initialRowHeight, 0);
//
// MainThread.BeginInvokeOnMainThread(() =>
// {
// animation.Commit(this, "HideRowAnimation", length: 500, easing: Easing.SinOut);
//
// });
//
// await Task.Delay(500);
// _animationRunning = false;
// homeCollectionView.IsEnabled = true;
// homeRefreshView.IsEnabled = true;
//}
await Task.Delay(500); // COMMENTED OUT: RefreshView refreshing handler
_animationRunning = false; //private async void RefreshView_Refreshing(object sender, EventArgs e)
homeCollectionView.IsEnabled = true; //{
homeRefreshView.IsEnabled = true; // if (_isRowHidden)
} // {
// await ShowHeader();
private async Task HideHeader() // }
{ //}
homeRefreshView.IsEnabled = false;
homeCollectionView.IsEnabled = false;
_isRowHidden = true;
_animationRunning = true;
var animation = new Animation(v => rootVerticalStackLayout.HeightRequest = v, _initialRowHeight, 0);
MainThread.BeginInvokeOnMainThread(() =>
{
animation.Commit(this, "HideRowAnimation", length: 500, easing: Easing.SinOut);
});
await Task.Delay(500);
_animationRunning = false;
homeCollectionView.IsEnabled = true;
homeRefreshView.IsEnabled = true;
}
private async void RefreshView_Refreshing(object sender, EventArgs e)
{
if (_isRowHidden)
{
await ShowHeader();
}
}
} }