Skip to content

Commit

Permalink
Added view for place detail (#14)
Browse files Browse the repository at this point in the history
* Added view for place detail
* Place detail view
* Page viewmodels renaming
  • Loading branch information
MoudryDaniel committed Dec 5, 2023
1 parent b3b956e commit 6098ed7
Show file tree
Hide file tree
Showing 18 changed files with 207 additions and 108 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

using ShareLoc.Client.App.Services;
using ShareLoc.Client.App.ViewModels;
using ShareLoc.Client.App.Views;
using ShareLoc.Client.App.Views.Pages;
using ShareLoc.Client.DAL;

Expand All @@ -11,14 +12,16 @@ public static class ServiceCollectionExtensions
{
public static IServiceCollection AddViewsAndViewModels(this IServiceCollection services)
{
services.AddScoped<MainMenuPage, MainMenuViewModel>();
services.AddScoped<MyPlacesPage, MyPlacesViewModel>();
services.AddScoped<MainMenuPage, MainMenuPageViewModel>();
services.AddScoped<MyPlacesPage, MyPlacesPageViewModel>();
services.AddScoped<MyGuessesPage, MyGuessesViewModel>();
services.AddScoped<PlaceDetailPage, PlaceDetailViewModel>();
services.AddScoped<PlaceDetailPage, PlaceDetailPageViewModel>();
services.AddScoped<PlaceDetailView, PlaceDetailViewModel>();

services.AddTransient<CreatePlacePage>();
services.AddTransient<CreatePlaceViewModel>();


return services;
}

Expand Down
6 changes: 6 additions & 0 deletions src/Client/ShareLoc.Client.App/Models/PlaceModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,10 @@ public PlaceModel(PlaceEntity placeEntity)
public DateTime CreatedUTC => _placeEntity.CratedUTC;

public bool IsShared => _placeEntity.IsShared;

public double Latitude => _placeEntity.Latitude;

public double Longitude => _placeEntity.Longitude;

public string Message => _placeEntity.Message;
}
56 changes: 25 additions & 31 deletions src/Client/ShareLoc.Client.App/ViewModels/CreatePlaceViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
using ShareLoc.Client.BL.Services;
using ShareLoc.Shared.Common.Models;
using CommunityToolkit.Mvvm.ComponentModel;
using System.Diagnostics;
using ShareLoc.Client.App.Models;
using ShareLoc.Client.DAL.Entities;

namespace ShareLoc.Client.App.ViewModels;
public sealed partial class CreatePlaceViewModel : BaseViewModel
Expand All @@ -16,50 +17,41 @@ public sealed partial class CreatePlaceViewModel : BaseViewModel
private readonly LocalDbService _localDbService;

[ObservableProperty]
public ImageSource? photo;
private PlaceDetailViewModel _placeDetailViewModel;
[ObservableProperty]
public string mapHtml = "";
[ObservableProperty]
public string message = "Guess where I am!";
private string _message = string.Empty;

public Location? Location
{
get => _location;
set
{
_location = value;
MapHtml = GenerateHtml();
}
}
private Location? _location;
private byte[]? _photoBytes;
private PlaceRequest? _placeRequest;
private Guid? _localPlaceId;
private PlaceRequest? _placeRequest = null;
private byte[]? _photoBytes = null;

public CreatePlaceViewModel(ApiClient apiClient, INavigationService navigationService, LocalDbService localDbService, IAlertService alertService)
public CreatePlaceViewModel(ApiClient apiClient, INavigationService navigationService, LocalDbService localDbService, IAlertService alertService, PlaceDetailViewModel placeDetailViewModel)
{
_apiClient = apiClient;
_navigationService = navigationService;
_localDbService = localDbService;
_alertService = alertService;

PlaceDetailViewModel = placeDetailViewModel;
}

protected override async Task LoadAsync(CancellationToken ct)
{
Location? location = null;
ImageSource? photo = null;
await MainThread.InvokeOnMainThreadAsync(async () =>
{
Location = await GetLocation();
Photo = await TakePhoto();
location = await GetLocation();
photo = await TakePhoto();
});

if (Location is null)
if (location is null)
{
await _alertService.ShowAlertAsync("Error", "Location not found", "OK");
await _navigationService!.ReturnToRootAsync();
return;
}
if (Photo is null)
if (photo is null)
{
await _navigationService!.ReturnToRootAsync();
return;
Expand All @@ -68,21 +60,23 @@ await MainThread.InvokeOnMainThreadAsync(async () =>
_placeRequest = new PlaceRequest()
{
Image = _photoBytes!,
Latitude = Location!.Latitude,
Longitude = Location!.Longitude,
Message = Message,
Latitude = location!.Latitude,
Longitude = location!.Longitude,
Message = PlaceDetailViewModel.Message!
};

_localPlaceId = await SavePlaceRequest();
if (_localPlaceId is null)
PlaceEntity? placeEntity = await SavePlaceRequest();
if (placeEntity is null)
{
await _alertService.ShowAlertAsync("Error", "Error while creating place", "OK");
await _navigationService!.ReturnToRootAsync();
return;
}

PlaceDetailViewModel.PlaceModel = new PlaceModel(placeEntity);
}

private async Task<Guid?> SavePlaceRequest()
private async Task<PlaceEntity?> SavePlaceRequest()
{
var response = await _localDbService.SavePlaceAsync(_placeRequest!);
if (!response.IsT0)
Expand Down Expand Up @@ -110,7 +104,7 @@ function getMarkerObject(color) {{
}}
function loadMap() {{
const center = SMap.Coords.fromWGS84('{Location!.Longitude.ToString()}', '{Location!.Latitude.ToString()}');
const center = SMap.Coords.fromWGS84('{_placeRequest!.Longitude}', '{_placeRequest.Latitude}');
map = new SMap(JAK.gel(""map""), center, 12);
map.addDefaultLayer(SMap.DEF_BASE).enable();
Expand Down Expand Up @@ -177,7 +171,7 @@ public async Task ShareUrl()
response.Switch(
async (serverId) =>
{
await _localDbService.SharePlaceAsync(_localPlaceId!.Value, serverId, DateTime.UtcNow);
await _localDbService.SharePlaceAsync(PlaceDetailViewModel.PlaceModel!.LocalId, serverId, DateTime.UtcNow);
await Share.RequestAsync(new ShareTextRequest
{
// eg. a2934fa2-6f7e-4ac9-8210-681814ac86c4
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@

namespace ShareLoc.Client.App.ViewModels;

public sealed partial class MainMenuViewModel : BaseViewModel
public sealed partial class MainMenuPageViewModel : BaseViewModel
{
private readonly INavigationService _navigationService;

public string AppVersion => AppInfo.Current.VersionString;

public MainMenuViewModel(INavigationService navigationService)
public MainMenuPageViewModel(INavigationService navigationService)
{
_navigationService = navigationService;
}
Expand All @@ -20,7 +20,7 @@ public MainMenuViewModel(INavigationService navigationService)
public Task GoToCreatePlacePage() => _navigationService.GoToAsync<CreatePlacePage, CreatePlaceViewModel>();

[RelayCommand]
public Task GoToMyPlacesPage() => _navigationService.GoToAsync<MyPlacesPage, MyPlacesViewModel>();
public Task GoToMyPlacesPage() => _navigationService.GoToAsync<MyPlacesPage, MyPlacesPageViewModel>();

[RelayCommand]
public Task GoToMyGuessesPage() => _navigationService.GoToAsync<MyGuessesPage, MyGuessesViewModel>();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
namespace ShareLoc.Client.App.ViewModels;

public sealed class MyGuessesViewModel : BaseViewModel
public sealed class MyGuessesViewModel
: BaseViewModel
{
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace ShareLoc.Client.App.ViewModels;

public sealed partial class MyPlacesViewModel : BaseViewModel
public sealed partial class MyPlacesPageViewModel : BaseViewModel
{
private readonly LocalDbService _dbService;
private readonly INavigationService _navigationService;
Expand All @@ -17,7 +17,7 @@ public sealed partial class MyPlacesViewModel : BaseViewModel
[ObservableProperty]
private List<PlaceModel> _myPlaces = [];

public MyPlacesViewModel(INavigationService navigationService, LocalDbService dbService, PlaceDetailViewModel placeDetailViewModel)
public MyPlacesPageViewModel(INavigationService navigationService, LocalDbService dbService, PlaceDetailViewModel placeDetailViewModel)
{
_dbService = dbService;
_navigationService = navigationService;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
namespace ShareLoc.Client.App.ViewModels;

public sealed partial class PlaceDetailPageViewModel : BaseViewModel
{
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,78 @@ namespace ShareLoc.Client.App.ViewModels;

public sealed partial class PlaceDetailViewModel : BaseViewModel
{
private PlaceModel? _placeModel = null;
public PlaceModel? PlaceModel
{
get => _placeModel;
set
{
if (value == null) return;

SetProperty(ref _placeModel, value, nameof(PlaceModel));

MapHtml = GenerateHtml(value.Longitude, value.Latitude);
Image = value.Image;
Message = value.Message;
IsShared = value.IsShared;
}
}

[ObservableProperty]
private string? _mapHtml = string.Empty;
[ObservableProperty]
private byte[]? _image = null;
[ObservableProperty]
private string? _message = "Guess where I am!";
[ObservableProperty]
private PlaceModel? _placeModel;
private bool _isShared = false;

private static string GenerateHtml(double longitude, double latitude)
{
return $@"
<![CDATA[
<html>
<link rel=""preconnect"" href=""https://fonts.googleapis.com"">
<link rel=""preconnect"" href=""https://fonts.gstatic.com"" crossorigin>
<script src=""https://api.mapy.cz/loader.js""></script>
<script>
function getMarkerObject(color) {{
const svgCode = `<svg fill=""${{color}}"" viewBox=""0 0 1920 1920"" width=""30"" height=""30"" xmlns=""http://www.w3.org/2000/svg"" stroke=""#00ff40""><g id=""SVGRepo_bgCarrier"" stroke-width=""0""></g><g id=""SVGRepo_tracerCarrier"" stroke-linecap=""round"" stroke-linejoin=""round""></g><g id=""SVGRepo_iconCarrier""> <path d=""M956.952 0c-362.4 0-657 294.6-657 656.88 0 180.6 80.28 347.88 245.4 511.56 239.76 237.96 351.6 457.68 351.6 691.56v60h120v-60c0-232.8 110.28-446.16 357.6-691.44 165.12-163.8 245.4-331.08 245.4-511.68 0-362.28-294.6-656.88-663-656.88"" fill-rule=""evenodd""></path> </g></svg>`;
const marker = JAK.mel(""div"");
marker.innerHTML = svgCode;
return marker;
}}
function loadMap() {{
const center = SMap.Coords.fromWGS84('{longitude}', '{latitude}');
map = new SMap(JAK.gel(""map""), center, 12);
map.addDefaultLayer(SMap.DEF_BASE).enable();
map.addDefaultControls();
const sync = new SMap.Control.Sync();
map.addControl(sync);
targetLayer = new SMap.Layer.HUD();
map.addLayer(targetLayer);
targetLayer.enable();
var markerLayer = new SMap.Layer.Marker();
map.addLayer(markerLayer);
markerLayer.enable();
var znacka = new SMap.Marker(center, null, {{anchor: {{left:10, bottom: 1}}}});
markerLayer.addMarker(znacka);
}}
Loader.lang = ""en"";
Loader.load();
window.onload = async function() {{loadMap();}};
</script>
<body>
<div id=""map"" style=""width:100%; height:100%;""></div>
</body>
</html>
";
}
}
32 changes: 5 additions & 27 deletions src/Client/ShareLoc.Client.App/Views/Pages/CreatePlacePage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,16 @@
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:viewModels="clr-namespace:ShareLoc.Client.App.ViewModels"
xmlns:views="clr-namespace:ShareLoc.Client.App.Views"
x:DataType="viewModels:CreatePlaceViewModel"
x:Class="ShareLoc.Client.App.Views.Pages.CreatePlacePage"
Title="Create Place">

<VerticalStackLayout VerticalOptions="Center">
<Grid HorizontalOptions="FillAndExpand">
<Image
x:Name="photo"
Source="{Binding Photo}"
HorizontalOptions="Start"
VerticalOptions="Start"
WidthRequest="150"
Margin="20"
ZIndex="9999"
/>
<WebView HeightRequest="300" AbsoluteLayout.LayoutBounds="0, 0, 300, 300" ZIndex="0" x:Name="map">
<WebView.Source>
<HtmlWebViewSource Html="{Binding MapHtml}">
</HtmlWebViewSource>
</WebView.Source>
</WebView>
</Grid>
<Label
Text="Are you sure your location is correct?"
FontSize="Caption"
Margin="20"
/>
<Entry Text="{Binding Message}"
Placeholder="Enter a message"
Margin="20"
/>
<views:PlaceDetailView BindingContext="{Binding PlaceDetailViewModel}" />

<Button
Text="Share URL"
Text="Share"
Margin="20"
Command="{Binding ShareUrlCommand}"
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,38 +1,9 @@
using ShareLoc.Client.App.Services;

namespace ShareLoc.Client.App.Views.Pages;

public sealed partial class CreatePlacePage : ContentPage
{
private readonly INavigationService _navigationService;
public CreatePlacePage(INavigationService navigationService)
public CreatePlacePage()
{
InitializeComponent();

_navigationService = navigationService;
// Make Image expand to fill the whole screen on tap and collapse on tap again
var tapGestureRecognizer = new TapGestureRecognizer();
tapGestureRecognizer.Tapped += OnImageTapped!;
photo.GestureRecognizers.Add(tapGestureRecognizer);
}

private void OnImageTapped(object sender, EventArgs e)
{
if (sender is not Image photo) return;

var windowWidth = _navigationService.GetCurrentPage().Width;
var mapHeight = map.Height;
var scale = Math.Min(windowWidth / photo.Width, mapHeight / photo.Height);

if (photo.Scale == 1)
{
photo.ScaleTo(scale * 0.8, 250, Easing.CubicInOut);
photo.TranslateTo((windowWidth - photo.Width * 0.8) / 2, (mapHeight - photo.Height) / 2, 250, Easing.CubicInOut);
}
else
{
photo.ScaleTo(1, 250, Easing.CubicInOut);
photo.TranslateTo(0, 0, 250, Easing.CubicInOut);
}
}
}
5 changes: 3 additions & 2 deletions src/Client/ShareLoc.Client.App/Views/Pages/MainMenuPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:viewModels="clr-namespace:ShareLoc.Client.App.ViewModels"
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
x:DataType="viewModels:MainMenuViewModel"
x:DataType="viewModels:MainMenuPageViewModel"
x:Class="ShareLoc.Client.App.Views.Pages.MainMenuPage"
Title="ShareLoc">

Expand All @@ -26,6 +26,7 @@
</Label.FormattedText>
</Label>
</VerticalStackLayout>

</VerticalStackLayout>

</ContentPage>
Loading

0 comments on commit 6098ed7

Please sign in to comment.