Merge branch 'vnext' of github.com:pazof/yavsc into vnext

vnext
Paul Schneider 8 years ago
commit 7f34437f6c
35 changed files with 547 additions and 254 deletions

@ -323,7 +323,7 @@ namespace BookAStar.Droid
clientId: "d9be5e97-c19d-42e4-b444-0e65863b19e1",
clientSecret: "blouh",
scope: "profile",
authorizeUrl: new Uri("http://dev.pschneider.fr/authorize"),
authorizeUrl: new Uri(Constants.AuthorizeUrl),
redirectUrl: new Uri("http://dev.pschneider.fr/oauth/success"),
accessTokenUrl: new Uri("http://dev.pschneider.fr/token"));
public void AddAccount()
@ -348,65 +348,48 @@ namespace BookAStar.Droid
{
using (var client = new HttpClient())
{
// get me
// var request = new OAuth2Request("GET", new Uri(Constants.UserInfoUrl), null, eventArgs.Account);
var request = new HttpRequestMessage(HttpMethod.Get, Constants.UserInfoUrl);
request.Headers.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", tokens.AccessToken);
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
string userJson = await response.Content.ReadAsStringAsync();
JObject jactiveUser = JObject.Parse(userJson);
Account acc = eventArgs.Account;
var uid = jactiveUser["Id"].Value<string>();
var username = jactiveUser["UserName"].Value<string>();
var roles = jactiveUser["Roles"].Values<string>().ToList();
var emails = jactiveUser["EMails"].Values<string>().ToList();
var newuser = new User
using (var request = new HttpRequestMessage(HttpMethod.Get, Constants.UserInfoUrl))
{
UserName = username,
EMails = emails,
Roles = roles,
Id = uid,
YavscTokens = tokens
};
MainSettings.SaveUser(newuser);
accStore.Save(acc, Constants.ApplicationName);
request.Headers.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", tokens.AccessToken);
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
string userJson = await response.Content.ReadAsStringAsync();
JObject jactiveUser = JObject.Parse(userJson);
Account acc = eventArgs.Account;
var uid = jactiveUser["Id"].Value<string>();
var username = jactiveUser["UserName"].Value<string>();
var roles = jactiveUser["Roles"].Values<string>().ToList();
var emails = jactiveUser["EMails"].Values<string>().ToList();
var avatar = jactiveUser["Avatar"].Value<string>();
var address = jactiveUser["Avatar"].Value<string>();
var newuser = new User
{
UserName = username,
EMails = emails,
Roles = roles,
Id = uid,
YavscTokens = tokens,
Avatar = avatar,
Address = address
};
MainSettings.SaveUser(newuser);
accStore.Save(acc, Constants.ApplicationName);
}
}
}
}
);
});
}
};
auth.Error += Auth_Error;
StartActivity(loginIntent);
}
public static void PopulateUserWithAccount(User u, Account a)
{
u.YavscTokens = new Model.Auth.Account.Tokens
{
AccessToken =
a.Properties["access_token"],
RefreshToken =
a.Properties["refresh_token"],
ExpiresIn =
int.Parse(a.Properties["expires_in"]),
TokenType = a.Properties["token_type"]
};
u.UserName = a.Username;
}
private void Auth_Error(object sender, AuthenticatorErrorEventArgs e)
{
// TODO handle

@ -200,7 +200,7 @@ namespace BookAStar.Rendering
var uriImageLoader = imagesource as UriImageSource;
if (uriImageLoader != null && uriImageLoader.Uri != null)
{
using (var client = UserHelpers.CreateClient())
using (var client = UserHelpers.CreateJsonClient())
{
using (var response = await client.GetAsync(uriImageLoader.Uri))
{

@ -44,19 +44,21 @@ namespace BookAStar.Droid.Services
if (topic == "BookQuery")
{
DateTime eventdate;
var sdatestr = data.GetString("EventDate");
DateTime.TryParse(sdatestr, out eventdate);
var locationJson = data.GetString("Location");
var location = JsonConvert.DeserializeObject<Location>(locationJson);
var cid = long.Parse(data.GetString("Id"));
var clientJson = data.GetString("Client");
var client = JsonConvert.DeserializeObject<ClientProviderInfo>(clientJson);
var bq = new BookQueryData
{
Id = cid,
Location = location
Location = location,
Client = client,
Reason = data.GetString("Reason")
};
SendBookQueryNotification(bq);
}
else
@ -89,7 +91,7 @@ namespace BookAStar.Droid.Services
var multiple = count > 1;
var title =
multiple ? $"{count} demandes" : bquery.Client.UserName;
var message = $"{bquery.EventDate} {bquery.Client.UserName} {bquery.Location.Address}";
var message = $"{bquery.EventDate} {bquery.Client.UserName} {bquery.Location.Address}\n {bquery.Reason}";
var intent = new Intent(this, typeof(MainActivity));
intent.AddFlags(ActivityFlags.ClearTop);

@ -9,7 +9,7 @@
<ResourceDictionary>
<Color x:Key="PageBackgroundColor">#FFAAAAFF</Color>
<Color x:Key="ContentBackgroundColor">#80AFAFAF</Color>
<Color x:Key="ContentBackgroundColor">#80FFFFFF</Color>
<Color x:Key="BackgroundColor">#FFFFFFFF</Color>
<Color x:Key="LabelBackgroundColor">#FFFFFFFF</Color>
@ -25,9 +25,9 @@
<Color x:Key="EmphasisTextColor">#800080</Color>
<OnPlatform x:TypeArguments="Font" Android="Large" iOS="Large" WinPhone="Large" x:Key="HeaderFont" />
<OnPlatform x:TypeArguments="Font" Android="90" iOS="90" WinPhone="90" x:Key="LargeFontSize" />
<OnPlatform x:TypeArguments="Font" Android="50" iOS="50" WinPhone="50" x:Key="MediumFontSize" />
<OnPlatform x:TypeArguments="Font" Android="40" iOS="40" WinPhone="40" x:Key="SmallFontSize" />
<OnPlatform x:TypeArguments="x:Double" Android="22" iOS="22" WinPhone="22" x:Key="LargeFontSize" />
<OnPlatform x:TypeArguments="x:Double" Android="16" iOS="16" WinPhone="16" x:Key="MediumFontSize" />
<OnPlatform x:TypeArguments="x:Double" Android="14" iOS="14" WinPhone="14" x:Key="SmallFontSize" />
<OnPlatform x:TypeArguments="x:Double" Android="130" iOS="130" WinPhone="130" x:Key="BigUserAvatarSize" />
<Style x:Key="LabelPageHeadingStyle" TargetType="Label">

@ -28,6 +28,8 @@ namespace BookAStar
using ViewModels.EstimateAndBilling;
using Pages.EstimatePages;
using ViewModels;
using Pages.Chat;
using System.Collections.Generic;
public partial class App : Application // superclass new in 1.3
{
@ -93,16 +95,21 @@ namespace BookAStar
// TODO special startup pages as
// notification details or wizard setup page
}
private INavigation Navigation
{
get
{
return masterDetail.Detail.Navigation;
}
}
// Called on rotation
private void OnSuspended(object sender, EventArgs e)
{
// TODO save the navigation stack
int position = 0;
foreach (Page page in MainPage.Navigation.NavigationStack)
DataManager.Current.AppState.Clear();
foreach (Page page in Navigation.NavigationStack)
{
DataManager.Current.AppState.Add(
new PageState
{
@ -141,7 +148,7 @@ namespace BookAStar
{
ViewFactory.EnableCache = true;
ViewFactory.Register<ChatPage, ChatViewModel>(
r=> new ChatViewModel { ChatUser = MainSettings.UserName }
r=> new ChatViewModel { }
);
ViewFactory.Register<DashboardPage, DashboardViewModel>(
resolver => new DashboardViewModel());
@ -183,13 +190,14 @@ namespace BookAStar
private void ShowPage(Page page)
{
if (masterDetail.Detail.Navigation.NavigationStack.Contains(page))
if (Navigation.NavigationStack.Contains(page))
{
if (masterDetail.Detail.Navigation.NavigationStack.Last() == page) return;
masterDetail.Detail.Navigation.RemovePage(page);
if (Navigation.NavigationStack.Last() == page) return;
Navigation.RemovePage(page);
page.Parent = null;
}
masterDetail.Detail.Navigation.PushAsync(page);
Navigation.PushAsync(page);
}
private void BuildMainPage()
@ -261,11 +269,11 @@ namespace BookAStar
masterDetail.ToolbarItems.Add(tiPubChat);
this.MainPage = masterDetail;
NavigationService = new NavigationService(masterDetail.Detail.Navigation);
NavigationService = new NavigationService(Navigation);
}
public static Task<string> DisplayActionSheet(string title, string cancel, string destruction, string [] buttons)
{
var currentPage = CurrentApp.masterDetail.Detail.Navigation.NavigationStack.Last();
var currentPage = App.CurrentApp.Navigation.NavigationStack.Last();
return currentPage.DisplayActionSheet(title, cancel, destruction, buttons);
}
@ -347,13 +355,13 @@ namespace BookAStar
private void MainSettings_UserChanged(object sender, EventArgs e)
{
if (MainSettings.CurrentUser == null)
if (chatHubConnection != null)
{
chatHubConnection.Dispose();
chatHubConnection = null;
chatHubProxy = null;
}
else
if (MainSettings.CurrentUser != null)
{
var token = MainSettings.CurrentUser.YavscTokens.AccessToken;
SetupHubConnection();

@ -61,6 +61,10 @@
<Compile Include="Model\Settings\SignatureSettings.cs" />
<Compile Include="Model\Social\Messaging\ChatStatus.cs" />
<Compile Include="Model\Social\Messaging\PrivateMessage.cs" />
<Compile Include="Pages\Chat\PrivateChatPage.xaml.cs">
<DependentUpon>PrivateChatPage.xaml</DependentUpon>
</Compile>
<Compile Include="ViewModels\Messaging\UserViewModel.cs" />
<Compile Include="ViewModels\Validation\Error.cs" />
<Compile Include="ViewModels\Validation\ModelState.cs" />
<Compile Include="ViewModels\PageState.cs" />
@ -135,7 +139,7 @@
<Compile Include="Pages\EstimatePages\BookQueryPage.xaml.cs">
<DependentUpon>BookQueryPage.xaml</DependentUpon>
</Compile>
<Compile Include="Pages\ChatPage.xaml.cs">
<Compile Include="Pages\Chat\ChatPage.xaml.cs">
<DependentUpon>ChatPage.xaml</DependentUpon>
</Compile>
<Compile Include="Pages\EstimatePages\EditBillingLinePage.xaml.cs">
@ -426,7 +430,7 @@
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Pages\ChatPage.xaml">
<EmbeddedResource Include="Pages\Chat\ChatPage.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
<SubType>Designer</SubType>
</EmbeddedResource>
@ -500,6 +504,12 @@
<Name>YavscLib</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Pages\Chat\PrivateChatPage.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
<Import Project="..\..\packages\Xamarin.Forms.2.3.2.127\build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.targets" Condition="Exists('..\..\packages\Xamarin.Forms.2.3.2.127\build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">

@ -26,6 +26,11 @@ namespace BookAStar
#endif
#endif
#endif
public static readonly string SignInUrl = YavscHomeUrl + "/signin";
public static readonly string AuthorizeUrl = YavscHomeUrl + "/authorize";
public static readonly string RedirectUrl = YavscHomeUrl + "/oauth/success";
public static readonly string AccessTokenUrl = YavscHomeUrl + "/token";
public static readonly string YavscApiUrl = YavscHomeUrl + "/api";
public static readonly string MobileRegistrationUrl = YavscApiUrl + "/gcm/register";
public static readonly string UserInfoUrl = YavscApiUrl + "/me";

@ -28,7 +28,7 @@ namespace BookAStar.Data
}
this.Add(estimate);
}
using (HttpClient client = UserHelpers.CreateClient())
using (HttpClient client = UserHelpers.CreateJsonClient())
{
try
{

@ -17,7 +17,7 @@ namespace BookAStar.Data.NonCrUD
public override async void Execute(object parameter)
{
BeforeExecute();
using (var client = UserHelpers.CreateClient())
using (var client = UserHelpers.CreateJsonClient())
{
// Get the whole data
try

@ -49,7 +49,7 @@ namespace BookAStar.Data
public virtual async void Execute(object parameter)
{
BeforeExecute();
using (HttpClient client = UserHelpers.CreateClient())
using (HttpClient client = UserHelpers.CreateJsonClient())
{
// Get the whole data
try
@ -105,7 +105,7 @@ namespace BookAStar.Data
// Get the whole data
var uri = GetUri(key);
using (HttpClient client = UserHelpers.CreateClient())
using (HttpClient client = UserHelpers.CreateJsonClient())
{
using (var response = await client.GetAsync(uri))
{
@ -128,7 +128,7 @@ namespace BookAStar.Data
bool created = false;
BeforeExecute();
using (HttpClient client = UserHelpers.CreateClient())
using (HttpClient client = UserHelpers.CreateJsonClient())
{
var stringContent = JsonConvert.SerializeObject(item);
@ -164,7 +164,7 @@ namespace BookAStar.Data
BeforeExecute();
var uri = GetUri(GetKey(item));
using (HttpClient client = UserHelpers.CreateClient())
using (HttpClient client = UserHelpers.CreateJsonClient())
{
HttpContent content = new StringContent(
JsonConvert.SerializeObject(item), Encoding.UTF8, "application/json"
@ -203,7 +203,7 @@ namespace BookAStar.Data
{
BeforeExecute();
var uri = GetUri(key);
using (HttpClient client = UserHelpers.CreateClient())
using (HttpClient client = UserHelpers.CreateJsonClient())
{
using (var response = await client.DeleteAsync(uri))
{

@ -17,18 +17,35 @@ namespace BookAStar.Helpers
{
var result = avatarPath == null ?
ImageSource.FromResource( "BookAStar.Images.Users.icon_user.png") :
avatarPath.StartsWith("res://") ?
ImageSource.FromResource(avatarPath.Substring(6)) :
ImageSource.FromUri(new Uri(avatarPath));
ImageSource.FromUri(new Uri(Constants.YavscHomeUrl+"/Avatars/"+avatarPath)) ;
return result;
}
public static HttpClient CreateClient()
public static ImageSource SmallAvatar(string avatarPath, string username)
{
return avatarPath == null ?
ImageSource.FromResource("BookAStar.Images.Users.icon_user.png") :
ImageSource.FromUri(new Uri($"{Constants.YavscHomeUrl}/Avatars/{username}.s.png"));
}
public static ImageSource ExtraSmallAvatar(string avatarPath, string username)
{
return avatarPath == null ?
ImageSource.FromResource("BookAStar.Images.Users.icon_user.png") :
ImageSource.FromUri(new Uri($"{Constants.YavscHomeUrl}/Avatars/{username}.xs.png"));
}
public static HttpClient CreateJsonClient()
{
return CreateJsonClient(MainSettings.CurrentUser.YavscTokens.AccessToken);
}
public static HttpClient CreateJsonClient(string accessToken)
{
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue(
"Bearer", MainSettings.CurrentUser.YavscTokens.AccessToken);
"Bearer", accessToken);
client.DefaultRequestHeaders.Add("Accept", "application/json");
return client;
}
@ -42,7 +59,7 @@ namespace BookAStar.Helpers
/// <returns></returns>
public static async Task<bool> Upload(Stream inputStream, string fileName)
{
using (var client = CreateClient())
using (var client = CreateJsonClient())
{
using (var content =
new MultipartFormDataContent("Upload----" + DateTime.Now.ToString(CultureInfo.InvariantCulture)))

@ -1,12 +1,7 @@
using BookAStar.Helpers;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace BookAStar.Model.Auth.Account
@ -81,6 +76,20 @@ namespace BookAStar.Model.Auth.Account
OnPropertyChanged("Avatar");
}
}
private string address;
public string Address
{
get
{
return address;
}
set
{
address = value;
OnPropertyChanged("Address");
}
}
[JsonIgnore]
public ImageSource AvatarSource
{

@ -4,12 +4,13 @@ using System;
namespace BookAStar.Model
{
public class BookQueryData : IBookQueryData
public class BookQueryData
{
public ClientProviderInfo Client { get; set; }
public Location Location { get; set; }
public long Id { get; set; }
public DateTime EventDate { get; set; }
public decimal? Previsionnal { get; set; }
public string Reason { get; set; }
}
}

@ -12,22 +12,14 @@ namespace BookAStar.Model
public string Avatar { get; set; }
public string UserId { get; set; }
// TODO Get User Professional status existence as a boolean
// And hack the avatar with
public int Rate { get; set; }
public string EMail { get; set; }
public string Phone { get; set; }
public Location BillingAddress { get; set; }
// TODO Get User Professional status existence as a boolean
// And hack the avatar with
[JsonIgnore]
public ImageSource AvatarOrNot
{
get
{
return UserHelpers.Avatar(Avatar);
}
}
public string ChatHubConnectionId { get; set; }
public override string ToString()
{

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="BookAStar.Pages.ChatPage"
x:Class="BookAStar.Pages.Chat.ChatPage"
xmlns:views="clr-namespace:BookAStar.Views;assembly=BookAStar"
xmlns:controls="clr-namespace:XLabs.Forms.Controls;assembly=XLabs.Forms"
xmlns:toolkit="clr-namespace:XLabs.Forms.Mvvm;assembly=XLabs.Forms"
@ -105,10 +105,8 @@
<Entry x:Name="pvEntry" Placeholder = "enter your private message"
VerticalOptions = "Center"
HorizontalOptions = "FillAndExpand"></Entry>
<!--
<controls:ExtendedPicker x:Name="contactPicker" Display="{Binding UserName}"></controls:ExtendedPicker>
-->
<controls:ExtendedPicker x:Name="contactPicker" ItemsSource="{Binding Contacts}" />
<Button x:Name="sendPVButton" Text = "Send" HorizontalOptions = "End"
VerticalOptions = "Center"></Button>
</StackLayout>

@ -3,7 +3,7 @@ using System.Diagnostics;
using Microsoft.AspNet.SignalR.Client;
using Xamarin.Forms;
namespace BookAStar.Pages
namespace BookAStar.Pages.Chat
{
using Data;
using System.Linq;
@ -19,7 +19,7 @@ namespace BookAStar.Pages
Title = "Chat";
BindingContext = new ChatViewModel();
App.ChatHubConnection.StateChanged += ChatHubConnection_StateChanged;
sendButton.Clicked += async (sender, args) =>
{
IsBusy = true;
@ -38,17 +38,15 @@ namespace BookAStar.Pages
IsBusy = false;
};
/*
sendPVButton.Clicked += async (sender, args) =>
{
string userName = contactPicker.SelectedItem as string;
if (string.IsNullOrEmpty(userName)) return;
var user = DataManager.Current.Contacts.Single(
c => c.UserName == userName);
if (string.IsNullOrEmpty(user.ChatHubConnectionId)) return;
IsBusy = true;
try
{
await App.ChatHubProxy.Invoke<string>("SendPV", user.ChatHubConnectionId, pvEntry.Text);
pvEntry.Text = null;
@ -58,7 +56,7 @@ namespace BookAStar.Pages
Debug.WriteLine(ex);
}
IsBusy = false;
};
};*/
}

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="BookAStar.Pages.Chat.PrivateChatPage">
<Label Text="{Binding MainText}" VerticalOptions="Center" HorizontalOptions="Center" />
</ContentPage>

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace BookAStar.Pages.Chat
{
public partial class PrivateChatPage : ContentPage
{
public PrivateChatPage()
{
InitializeComponent();
}
}
}

@ -30,29 +30,34 @@
<ScrollView>
<StackLayout Padding="10,10,10,10" x:Name="mainLayout">
<ListView RefreshCommand="{Binding RefreshQueries}" IsPullToRefreshEnabled="True"
ItemsSource="{Binding Queries}" x:Name="list" ItemTapped="OnViewDetail" HasUnevenRows="true" RowHeight="80">
<ListView.ItemTemplate HeightRequest="80" VerticalOptions="StartAndExpand">
ItemsSource="{Binding Queries}" x:Name="list" ItemTapped="OnViewDetail" HasUnevenRows="true"
SeparatorVisibility="Default" SeparatorColor="Black">
<ListView.ItemTemplate VerticalOptions="StartAndExpand">
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout Orientation="Horizontal" Padding="10,10,10,10" VerticalOptions="StartAndExpand">
<StackLayout Orientation="Vertical"
HeightRequest="80" VerticalOptions="StartAndExpand">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Grid.Row="0" Grid.Column="0" Grid.RowSpan="3" Source="{Binding Avatar}" />
<Label Grid.Row="3" Grid.Column="0" Grid.RowSpan="2" Text="{Binding Client.UserName}" Style="{StaticResource labelStyle}"></Label>
<Label Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2" Grid.RowSpan="2" Text="{Binding Data.Reason}"></Label>
<Label Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" LineBreakMode="WordWrap" Text="{Binding EventDate, StringFormat='{0:dddd d MMMM à HH:mm}'}" FontFamily="Italic"/>
<Label Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="2" LineBreakMode="WordWrap" Text="{Binding Location.Address}"/>
<Label Grid.Row="4" Grid.Column="1" Text="{Binding Previsionnal}" />
<Label Grid.Row="4" Grid.Column="2" Text="{Binding Id}" />
</Grid>
<StackLayout Orientation="Vertical" >
<Image Source="{Binding Client.Avatar}" />
<Label Text="{Binding Client.UserName}"
Style="{StaticResource labelStyle}"></Label>
</StackLayout>
<Label LineBreakMode="WordWrap" Text="{Binding EventDate, StringFormat='{0:dddd d MMMM à HH:mm}'}" FontSize="12" FontFamily="Italic"/>
</StackLayout>
<StackLayout Orientation="Vertical" HorizontalOptions="FillAndExpand">
<Label LineBreakMode="WordWrap" Text="{Binding Location.Address}"/>
<Label Text="{Binding Previsionnal}" />
<Label Text="{Binding Id}" HorizontalTextAlignment="End"/>
</StackLayout>
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>

@ -26,8 +26,8 @@ namespace BookAStar.Pages
private void OnViewDetail(object sender, ItemTappedEventArgs e)
{
BookQueryData data = e.Item as BookQueryData;
App.NavigationService.NavigateTo<BookQueryPage>(true,data);
var item = e.Item as BookQueryViewModel;
App.NavigationService.NavigateTo<BookQueryPage>(true,item);
}
}
}

@ -19,20 +19,24 @@
<StackLayout x:Name="bookQueryLayout">
<StackLayout Orientation="Vertical">
<Image Source="{Binding Client.AvatarOrNot}" Aspect="AspectFit" VisualElement.HeightRequest="{StaticResource BigUserAvatarSize}"/>
<Image Source="{Binding Avatar}" Aspect="AspectFit" VisualElement.HeightRequest="{StaticResource BigUserAvatarSize}"/>
<Label Text="{Binding Client.UserName}" />
<Label Text="{Binding EventDate, StringFormat='le {0:dddd d MMMM yyyy à hh:mm}'}" />
<Label Text="{Binding Data.Reason}" />
<Label Text="{Binding Location.Address}" />
<Label Text="{Binding Previsional}" />
</StackLayout>
<StackLayout Orientation="Vertical" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" >
<maps:Map x:Name="map" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"></maps:Map>
<StackLayout Orientation="Horizontal">
<Button Text="{Binding EditEstimateButtonText}" Clicked="OnEditEstimate" />
<Button Text="{x:Static local:Strings.DeclineQuery}" Clicked="OnDropQuery" />
<Button Text="{x:Static local:Strings.BlockThisUser}" Clicked="OnBlockThisUser" />
<Button Text="{x:Static local:Strings.ViewEstimate}"
BorderRadius="50" BorderWidth="2" BorderColor="Aqua" x:Name ="btn"
IsEnabled="{Binding EstimationDone}"
VisualElement.IsVisible="{Binding EstimationDone}"
Clicked="OnViewEstimate" Image="exclam.png" />
<Button Text="{Binding EditEstimateButtonText}" Clicked="OnEditEstimate" />
</StackLayout>
</StackLayout>
</StackLayout>

@ -47,14 +47,14 @@ namespace BookAStar.Pages
{
InitializeComponent();
}
public BookQueryPage(BookQueryData bookQuery=null)
public BookQueryPage(BookQueryViewModel bookQuery =null)
{
InitializeComponent();
// when TODO update?
// Task.Run( async () => { bookQuery = await App.CurrentApp.DataManager.BookQueries.Get(bookQueryId); });
BindingContext = new BookQueryViewModel(bookQuery);
BindingContext = bookQuery;
}
private void OnEditEstimate(object sender, EventArgs ev)
@ -112,5 +112,13 @@ namespace BookAStar.Pages
}
base.OnSizeAllocated(width, height);
}
private void OnBlockThisUser(object sender, EventArgs ev)
{
throw new NotImplementedException();
}
private void OnDropQuery(object sender, EventArgs ev)
{
throw new NotImplementedException();
}
}
}

@ -3,7 +3,7 @@
xmlns:local="clr-namespace:BookAStar;assembly=BookAStar"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="BookAStar.Pages.UserProfile.AccountChooserPage"
Title="Paramètres Booking star" Style="{StaticResource PageStyle}"
Title="{x:Static local:Strings.UserAccounts}" Style="{StaticResource PageStyle}"
xmlns:lc="clr-namespace:XLabs.Forms.Controls;assembly=XLabs.Forms"
xmlns:lb="clr-namespace:XLabs.Forms.Behaviors;assembly=XLabs.Forms">
@ -20,17 +20,18 @@
</StackLayout>
</ListView.Header>
<ListView.ItemTemplate HeightRequest="60" VerticalOptions="StartAndExpand">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid Padding="5"
ColumnSpacing="10"
RowSpacing="2" >
<Image Source="{Binding AvatarSource}" HeightRequest="80"
x:Name="avatarImage"/>
<Label Grid.Column="0" Text="{Binding UserName}" >
<Image Grid.Column="0" Source="{Binding AvatarSource}" HeightRequest="80" />
<Label Grid.Column="1" Text="{Binding UserName}" >
</Label>
<Label Grid.Column="2" Text="{Binding EMails.ToString()}" />
<Label Grid.Column="3" Text="{Binding Roles.ToString()}" />
<Label Grid.Column="4" Text="{Binding Address}" />
</Grid>
</ViewCell>
</DataTemplate>

@ -21,34 +21,32 @@
<ContentPage.Content>
<ScrollView>
<StackLayout BoxView.Color="{StaticResource ContentBackgroundColor}">
<Label Text="{Binding UserName}" Style="{StaticResource LabelPageHeadingStyle}"
HorizontalTextAlignment="Center"
LineBreakMode="WordWrap" XAlign="Center"
></Label>
<Image Source="{Binding Avatar}" HeightRequest="{StaticResource BigUserAvatarSize}" />
<Button Text="{Binding UserName}" Clicked="OnRefreshQuery" />
<Button Text="{Binding UserFilesText}" Clicked="OnManageFiles" />
<StackLayout VisualElement.IsVisible="{Binding HaveAnUser}">
<Button Text="{Binding PerformerStatus}" Clicked="OnViewPerformerStatus" />
<Button Text="{Binding UserQueries}" Clicked="OnViewUserQueries"
VisualElement.IsVisible="{Binding UserIsPro}"/>
<Image Source="{Binding Avatar}"
VisualElement.HeightRequest="{StaticResource BigUserAvatarSize}" />
<views:RatingView Rating="{Binding Rating, Mode=TwoWay}" x:Name="ratingView" />
<Button Text="{Binding PerformerStatus}" Clicked="OnViewPerformerStatus" />
<Button Text="{Binding UserQueries}" Clicked="OnViewUserQueries"
VisualElement.IsVisible="{Binding UserIsPro}"/>
<Button Text="{Binding UserFilesLabel}" Clicked="OnManageFiles" />
<StackLayout Orientation="Horizontal" VisualElement.IsVisible="{Binding HaveAnUser}">
<StackLayout Orientation="Horizontal">
<Label Text="Recevoir les notifications push" StyleClass="Header" />
<Switch IsToggled="{Binding ReceivePushNotifications, Mode=TwoWay}"
HorizontalOptions="End" />
</StackLayout>
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Utiliser ma position" StyleClass="Header" />
<Switch HorizontalOptions="End" IsToggled="{Binding AllowUseMyPosition, Mode=TwoWay}"/>
</StackLayout>
<StackLayout Orientation="Horizontal" VerticalOptions="Start"
VisualElement.IsVisible="{Binding UserIsPro}" >
<Label Text="Ne recevoir de demande de devis que de la part de professionnels uniquement" />
<Switch HorizontalOptions="End" IsToggled="{Binding AllowProBookingOnly, Mode=TwoWay}"/>
<StackLayout VisualElement.IsVisible="{Binding UserIsPro}" >
<Label Text="{x:Static local:Strings.Profprof}" Style="{StaticResource LabelStyle}"/>
<views:RatingView Rating="{Binding Rating, Mode=TwoWay}" x:Name="ratingView" />
<StackLayout Orientation="Horizontal" VerticalOptions="Start">
<Label Text="{x:Static local:Strings.ClientProRequest}" />
<Switch HorizontalOptions="End" IsToggled="{Binding AllowProBookingOnly, Mode=TwoWay}" />
</StackLayout>
</StackLayout>
</StackLayout>
</ScrollView>

@ -5,6 +5,10 @@ using XLabs.Forms.Behaviors;
namespace BookAStar.Pages.UserProfile
{
using Data;
using Helpers;
using Newtonsoft.Json.Linq;
using System.Linq;
using System.Net.Http;
using ViewModels.UserProfile;
public partial class DashboardPage : ContentPage
@ -18,11 +22,36 @@ namespace BookAStar.Pages.UserProfile
protected override void OnBindingContextChanged()
{
base.OnBindingContextChanged();
// Assert ((DashboardViewModel)BindingContext!=null)
((DashboardViewModel)BindingContext).UserNameGesture
= new RelayGesture( (gesture,arg) => {
ShowPage<AccountChooserPage>(null, true);
});
}
public async void OnRefreshQuery(object sender, EventArgs e)
{
IsBusy = true;
using (var client = UserHelpers.CreateJsonClient())
{
using (var request = new HttpRequestMessage(HttpMethod.Get, Constants.UserInfoUrl))
{
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
string userJson = await response.Content.ReadAsStringAsync();
JObject jactiveUser = JObject.Parse(userJson);
var username = jactiveUser["UserName"].Value<string>();
var roles = jactiveUser["Roles"].Values<string>().ToList();
var emails = jactiveUser["EMails"].Values<string>().ToList();
var avatar = jactiveUser["Avatar"].Value<string>();
var address = jactiveUser["Avatar"].Value<string>();
var me = MainSettings.CurrentUser;
me.Address = address;
me.Avatar = avatar;
me.EMails = emails;
me.UserName = username;
me.Roles = roles;
MainSettings.SaveUser(me);
}
}
}
IsBusy = false;
}
public void OnManageFiles(object sender, EventArgs e)

@ -171,21 +171,34 @@ namespace BookAStar
public static event EventHandler<EventArgs> UserChanged;
/// <summary>
/// Saves the given user account in the account list.
/// An existent presenting the same Id will be dropped.
/// </summary>
/// <param name="user"></param>
public static void SaveUser(User user)
{
var existent = AccountList.FirstOrDefault(u => u.UserName == user.UserName);
var existent = AccountList.FirstOrDefault(u => u.Id == user.Id);
if (existent != null)
AccountList.Remove(existent);
AccountList.Add(user);
var json = JsonConvert.SerializeObject(AccountList.ToArray());
AppSettings.AddOrUpdateValue(UserListsKey, json);
}
/// <summary>
/// Gets an account connection info, given its name
/// </summary>
/// <param name="username"></param>
/// <returns></returns>
public static User GetUser(string username)
{
return AccountList.FirstOrDefault(a => a.UserName == username);
}
// FIXME real time usage
/// <summary>
/// Enables/disables push notifications
/// </summary>
public static bool PushNotifications
{
get
@ -203,6 +216,10 @@ namespace BookAStar
}
}
// FIXME real time usage
/// <summary>
/// Enables/disables GPS usage
/// </summary>
public static bool AllowGPSUsage
{
get
@ -218,7 +235,11 @@ namespace BookAStar
value);
}
}
// TODO make it a server side user's parameter
/// <summary>
/// Only allow professionals to ask for user's services
/// </summary>
public static bool AllowProBookingOnly
{
get

@ -70,6 +70,15 @@ namespace BookAStar {
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à Bloquer cet utilisateur.
/// </summary>
public static string BlockThisUser {
get {
return ResourceManager.GetString("BlockThisUser", resourceCulture);
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à Annuler la validation.
/// </summary>
@ -79,6 +88,15 @@ namespace BookAStar {
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à Restreindre la demande aux clients professionnels.
/// </summary>
public static string ClientProRequest {
get {
return ResourceManager.GetString("ClientProRequest", resourceCulture);
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à La création a échoué, contenu envoyé: {stringContent} @ Uri: {ControllerUri.AbsoluteUri}: Erreur : {errcontent}.
/// </summary>
@ -88,6 +106,15 @@ namespace BookAStar {
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à Décliner cette proposition (envoyer un refus, et archiver la demande).
/// </summary>
public static string DeclineQuery {
get {
return ResourceManager.GetString("DeclineQuery", resourceCulture);
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à Faire un devis.
/// </summary>
@ -214,6 +241,15 @@ namespace BookAStar {
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à Profile professionnel.
/// </summary>
public static string Profprof {
get {
return ResourceManager.GetString("Profprof", resourceCulture);
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à Signer.
/// </summary>
@ -259,6 +295,15 @@ namespace BookAStar {
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à Comptes utilisateur.
/// </summary>
public static string UserAccounts {
get {
return ResourceManager.GetString("UserAccounts", resourceCulture);
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à Voir les devis validés.
/// </summary>
@ -268,6 +313,15 @@ namespace BookAStar {
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à Vos fichiers .
/// </summary>
public static string YourFiles {
get {
return ResourceManager.GetString("YourFiles", resourceCulture);
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à Votre texte a été taillé car il était trop long..
/// </summary>

@ -191,4 +191,22 @@
<data name="MinMaxIntError" xml:space="preserve">
<value>Veuillez saisir une valeur entre {0} et {1}.</value>
</data>
<data name="YourFiles" xml:space="preserve">
<value>Vos fichiers </value>
</data>
<data name="Profprof" xml:space="preserve">
<value>Profile professionnel</value>
</data>
<data name="ClientProRequest" xml:space="preserve">
<value>Restreindre la demande aux clients professionnels</value>
</data>
<data name="UserAccounts" xml:space="preserve">
<value>Comptes utilisateur</value>
</data>
<data name="BlockThisUser" xml:space="preserve">
<value>Bloquer cet utilisateur</value>
</data>
<data name="DeclineQuery" xml:space="preserve">
<value>Décliner cette proposition (envoyer un refus, et archiver la demande)</value>
</data>
</root>

@ -5,18 +5,24 @@ namespace BookAStar.ViewModels.EstimateAndBilling
{
using Data;
using Model;
using System.Linq;
public class BookQueriesViewModel : XLabs.Forms.Mvvm.ViewModel
{
public BookQueriesViewModel()
{
queries = new ObservableCollection<BookQueryViewModel>
(DataManager.Current.BookQueries.Select(
q =>
new BookQueryViewModel(q)));
}
private ObservableCollection<BookQueryViewModel> queries;
public ObservableCollection<BookQueryData> Queries
public ObservableCollection<BookQueryViewModel> Queries
{
get
{
return DataManager.Current.BookQueries;
return queries;
}
}

@ -6,14 +6,16 @@ using XLabs.Forms.Mvvm;
namespace BookAStar.ViewModels.EstimateAndBilling
{
using Data;
using Helpers;
using Interfaces;
using Model;
using Model.Social;
using Model.Workflow;
using System.Collections.ObjectModel;
using System.Linq;
using Xamarin.Forms;
class BookQueryViewModel : ViewModel, IBookQueryData
public class BookQueryViewModel : ViewModel, IBookQueryData
{
public BookQueryViewModel()
{
@ -41,6 +43,20 @@ namespace BookAStar.ViewModels.EstimateAndBilling
}
}
public ClientProviderInfo Client { get; set; }
public ImageSource Avatar
{
get
{
return UserHelpers.Avatar(Client.Avatar);
}
}
public ImageSource SmallAvatar
{
get
{
return UserHelpers.SmallAvatar(Client.Avatar, Client.UserName);
}
}
public Location Location { get; set; }
public long Id { get; set; }
public DateTime EventDate { get; set; }

@ -136,18 +136,20 @@ namespace BookAStar.ViewModels.EstimateAndBilling
{
get
{
/*
OnPlatform<Font> lfs = (OnPlatform<Font>)App.Current.Resources["MediumFontSize"];
*/
OnPlatform<double> mfs = (OnPlatform < double > ) App.Current.Resources["MediumFontSize"];
Color etc = (Color) App.Current.Resources["EmphasisTextColor"];
return new FormattedString
{
Spans = {
new Span { Text = "Total TTC: " },
new Span { Text = Data.Total.ToString(),
ForegroundColor = etc,
FontSize = (double) lfs.Android.FontSize },
new Span { Text = "€", FontSize = (double) lfs.Android.FontSize }
FontSize = mfs },
new Span { Text = "€", FontSize = mfs }
}
};
}

@ -7,7 +7,6 @@ using XLabs.Forms.Mvvm;
namespace BookAStar.ViewModels.Messaging
{
using Data;
using Model;
using Model.Social.Messaging;
class ChatViewModel: ViewModel
@ -15,19 +14,8 @@ namespace BookAStar.ViewModels.Messaging
public ObservableCollection<ChatMessage> Messages { get; set; }
public ObservableCollection<ChatMessage> Notifs { get; set; }
public ObservableCollection<ChatMessage> PVs { get; set; }
public ObservableCollection<ClientProviderInfo> Contacts { get; set; }
private string chatUser;
public string ChatUser
{
get
{
return chatUser;
}
set
{
SetProperty<string>(ref chatUser, value);
}
}
public ObservableCollection<UserViewModel> Contacts { get; set; }
private ConnectionState state;
public ConnectionState State
{
@ -41,7 +29,9 @@ namespace BookAStar.ViewModels.Messaging
Messages = new ObservableCollection<ChatMessage>();
Notifs = new ObservableCollection<ChatMessage>();
PVs = DataManager.Current.PrivateMessages;
Contacts = DataManager.Current.Contacts;
Contacts =
new ObservableCollection<UserViewModel>(
DataManager.Current.Contacts.Select(c=>new UserViewModel { Data = c }));
App.ChatHubProxy.On<string, string>("addMessage", (n, m) =>
{
Messages.Add(new ChatMessage
@ -54,45 +44,44 @@ namespace BookAStar.ViewModels.Messaging
App.ChatHubProxy.On<string, string, string>("notify", (eventId, cxId, userName) =>
{
var msg = new ChatMessage
{
Message = eventId,
SenderId = userName,
Date = DateTime.Now
};
// TODO make admin possible
// by assigning a server side username to anonymous.
// From now, don't log anonymous
if (!string.IsNullOrEmpty(userName))
if (string.IsNullOrEmpty(userName))
{
Notifs.Add(new ChatMessage
{
Message = eventId,
SenderId = userName,
Date = DateTime.Now
});
if (eventId == "connected")
OnUserConnected(cxId, userName);
else if (eventId == "disconnected")
OnUserDisconnected(userName);
msg.SenderId = $"({cxId})";
}
Notifs.Add(msg);
if (eventId == "connected")
OnUserConnected(cxId, userName);
else if (eventId == "disconnected")
OnUserDisconnected(userName);
});
ChatUser = MainSettings.UserName;
}
private void OnUserConnected(string cxId, string userName)
{
var user = Contacts.SingleOrDefault(
c => c.UserName == userName);
c => c.Data.UserName == userName);
if (user != null)
user.ChatHubConnectionId = cxId;
user.ConnexionId = cxId;
}
private void OnUserDisconnected (string userName)
{
var user = Contacts.SingleOrDefault(
c => c.UserName == userName);
c => c.Data.UserName == userName);
if (user != null)
user.ChatHubConnectionId = null;
user.ConnexionId = null;
}
private void MainSettings_UserChanged(object sender, EventArgs e)
{
ChatUser = MainSettings.UserName;
}
private void ChatHubConnection_StateChanged(StateChange obj)

@ -0,0 +1,75 @@
using BookAStar.Helpers;
using BookAStar.Model;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using XLabs.Forms.Mvvm;
namespace BookAStar.ViewModels.Messaging
{
class UserViewModel : ViewModel
{
private ClientProviderInfo data;
public ClientProviderInfo Data {
get
{
return data;
}
set
{
SetProperty(ref data, value);
NotifyPropertyChanged("Avatar");
}
}
private string connexionId;
public string ConnexionId
{
get
{
return connexionId;
}
set
{
SetProperty(ref connexionId, value);
NotifyPropertyChanged("Connected");
}
}
public bool Connected
{
get { return connexionId != null; }
}
[JsonIgnore]
public ImageSource Avatar
{
get
{
return UserHelpers.Avatar(Data.Avatar);
}
}
[JsonIgnore]
public ImageSource SmallAvatar
{
get
{
return UserHelpers.SmallAvatar(Data.Avatar, Data.UserName);
}
}
[JsonIgnore]
public ImageSource ExtraSmallAvatar
{
get
{
return UserHelpers.ExtraSmallAvatar(Data.Avatar, Data.UserName);
}
}
}
}

@ -13,6 +13,7 @@ namespace BookAStar.ViewModels.UserProfile
using Helpers;
using Model.Auth.Account;
using Pages.UserProfile;
using System.Threading.Tasks;
internal class DashboardViewModel : ViewModel
{
@ -97,7 +98,6 @@ namespace BookAStar.ViewModels.UserProfile
if (user!=null)
{
user.PropertyChanged += User_PropertyChanged;
}
UpdateUserMeta();
@ -173,39 +173,53 @@ namespace BookAStar.ViewModels.UserProfile
private void UpdateUserMeta ()
{
string newStatusString;
long newQueryCount;
bool newUserIsPro;
ImageSource newAvatar;
string newQueriesButtonText;
bool newHaveAnUser = user == null;
if (newHaveAnUser) {
newQueryCount = 0;
newUserIsPro = false;
newStatusString = null;
newAvatar = null;
newQueriesButtonText = null;
}
else
{
newUserIsPro = UserIsPro;
Task.Run( ()=> {
string newStatusString;
long newQueryCount;
bool newUserIsPro;
ImageSource newAvatar;
string newQueriesButtonText;
bool newHaveAnUser = user == null;
if (newHaveAnUser)
{
newQueryCount = 0;
newUserIsPro = false;
newStatusString = null;
newAvatar = null;
newQueriesButtonText = null;
}
else
{
newUserIsPro = UserIsPro;
newQueryCount = newUserIsPro ? DataManager.Current.BookQueries.Count : 0;
newQueryCount = newUserIsPro ? DataManager.Current.BookQueries.Count : 0;
newStatusString = newUserIsPro ?
$"Profile professionel renseigné" :
"Profile professionel non renseigné";
newQueriesButtonText = newUserIsPro ?
$"{newQueryCount} demandes valides en cours" :
"Profile professionel non renseigné";
newAvatar = UserHelpers.Avatar(user.Avatar);
}
SetProperty<bool>(ref haveAnUser, newHaveAnUser, "HaveAnUser");
SetProperty<bool>(ref userIsPro, newUserIsPro, "UserIsPro");
SetProperty<string>(ref performerStatus, newStatusString, "PerformerStatus");
SetProperty<string>(ref userQueries, newQueriesButtonText, "UserQueries");
SetProperty<long>(ref queryCount, newQueryCount, "QueryCount");
try
{
SetProperty<ImageSource>(ref avatar, newAvatar, "Avatar");
}
catch (TaskCanceledException)
{ }
NotifyPropertyChanged("UserName");
NotifyPropertyChanged("UserId");
NotifyPropertyChanged("HaveAnUser");
NotifyPropertyChanged("UserIsPro");
});
newStatusString = newUserIsPro ?
$"Profile professionel renseigné" :
"Profile professionel non renseigné";
newQueriesButtonText = newUserIsPro ?
$"{newQueryCount} demandes valides en cours" :
"Profile professionel non renseigné";
newAvatar = UserHelpers.Avatar(user.Avatar);
}
SetProperty<bool>(ref haveAnUser, newHaveAnUser, "HaveAnUser");
SetProperty<bool>(ref userIsPro, newUserIsPro, "UserIsPro");
SetProperty<string>(ref performerStatus, newStatusString, "PerformerStatus");
SetProperty<string>(ref userQueries, newQueriesButtonText, "UserQueries");
SetProperty<long>(ref queryCount, newQueryCount, "QueryCount");
SetProperty<ImageSource>(ref avatar, newAvatar, "Avatar");
}
private void User_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
@ -214,6 +228,12 @@ namespace BookAStar.ViewModels.UserProfile
}
public RelayGesture UserNameGesture { get; set; }
public string UserFilesText
{
get
{
return Strings.YourFiles;
}
}
}
}

@ -15,7 +15,7 @@
</ContentView.Resources>
<ContentView.Content>
<StackLayout>
<StackLayout Orientation="Horizontal" >
<StackLayout Orientation="Horizontal" VisualElement.HeightRequest="{StaticResource SmallFontSize}" >
<Grid>
<Grid.Behaviors>
<behaviors:StarBehavior x:Name="starOne" GroupName="myStar"/>

Loading…