diff --git a/BookAStar/BookAStar/BookAStar.csproj b/BookAStar/BookAStar/BookAStar.csproj index fad3da48..c9d2a431 100644 --- a/BookAStar/BookAStar/BookAStar.csproj +++ b/BookAStar/BookAStar/BookAStar.csproj @@ -62,12 +62,12 @@ - + + PrivateChatPage.xaml - diff --git a/BookAStar/BookAStar/Data/DataManager.cs b/BookAStar/BookAStar/Data/DataManager.cs index 630409bd..025e15b3 100644 --- a/BookAStar/BookAStar/Data/DataManager.cs +++ b/BookAStar/BookAStar/Data/DataManager.cs @@ -8,13 +8,13 @@ using NonCrUD; using ViewModels; using Model.Access; - using Model.Social.Chat; + using ViewModels.Messaging; public class DataManager { // TODO estimatetemplate rating service product tag public RemoteEntityRO BookQueries { get; set; } - public RemoteEntityRO ChatUsers { get; set; } + public ChatUserCollection ChatUsers { get; set; } public EstimateEntity Estimates { get; set; } public RemoteEntity Blogspot { get; set; } internal RemoteFilesEntity RemoteFiles { get; set; } @@ -52,8 +52,7 @@ PrivateMessages = new LocalEntity(m=> m.GetHashCode()); RemoteFiles = new RemoteFilesEntity (); BlackList = new RemoteEntity("blacklist",u => u.Id); - ChatUsers = new RemoteEntityRO - ("chat/users", u => u.UserId); + ChatUsers = new ChatUserCollection(); PrivateMessages.Load(); BookQueries.Load(); Estimates.Load(); @@ -64,6 +63,8 @@ EstimateLinesTemplates.Load(); RemoteFiles.Load(); BlackList.Load(); + ChatUsers.Load(); + BlackList.Load(); } } } diff --git a/BookAStar/BookAStar/Model/Social/Chat/ChatUserInfo.cs b/BookAStar/BookAStar/Model/Social/Chat/ChatUserInfo.cs deleted file mode 100644 index 2b14e6d9..00000000 --- a/BookAStar/BookAStar/Model/Social/Chat/ChatUserInfo.cs +++ /dev/null @@ -1,33 +0,0 @@ - -using YavscLib; - -namespace BookAStar.Model.Social.Chat -{ - public class ChatUserInfo : IChatUserInfo - { - public string Avatar - { - get; set; - } - - public IConnection[] Connections - { - get; set; - } - - public string[] Roles - { - get; set; - } - - public string UserId - { - get; set; - } - - public string UserName - { - get; set; - } - } -} diff --git a/BookAStar/BookAStar/Pages/Chat/ChatPage.xaml b/BookAStar/BookAStar/Pages/Chat/ChatPage.xaml index 8a6c3115..d1e95cd4 100644 --- a/BookAStar/BookAStar/Pages/Chat/ChatPage.xaml +++ b/BookAStar/BookAStar/Pages/Chat/ChatPage.xaml @@ -110,7 +110,7 @@ - + + --> + diff --git a/BookAStar/BookAStar/Pages/Chat/ChatPage.xaml.cs b/BookAStar/BookAStar/Pages/Chat/ChatPage.xaml.cs index 45c5dfa3..fe7c15bb 100644 --- a/BookAStar/BookAStar/Pages/Chat/ChatPage.xaml.cs +++ b/BookAStar/BookAStar/Pages/Chat/ChatPage.xaml.cs @@ -23,7 +23,6 @@ namespace BookAStar.Pages.Chat name: "...", icon: null, activated: () => { })); */ - BindingContext = new ChatViewModel(); App.ChatHubConnection.StateChanged += ChatHubConnection_StateChanged; sendButton.Clicked += async (sender, args) => { @@ -43,6 +42,8 @@ namespace BookAStar.Pages.Chat IsBusy = false; }; + chatUserList.BindingContext = DataManager.Instance.ChatUsers; + /* sendPVButton.Clicked += async (sender, args) => { @@ -62,7 +63,7 @@ namespace BookAStar.Pages.Chat } IsBusy = false; };*/ - + } private void ChatHubConnection_StateChanged(StateChange obj) diff --git a/BookAStar/BookAStar/ViewModels/Messaging/ChatUserCollection.cs b/BookAStar/BookAStar/ViewModels/Messaging/ChatUserCollection.cs new file mode 100644 index 00000000..a77f9523 --- /dev/null +++ b/BookAStar/BookAStar/ViewModels/Messaging/ChatUserCollection.cs @@ -0,0 +1,34 @@ +using BookAStar.Data; +using BookAStar.Model.Social.Chat; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Input; +using Xamarin.Forms; + +namespace BookAStar.ViewModels.Messaging +{ + public class ChatUserCollection : RemoteEntityRO + { + public ChatUserCollection() : base ("chat/users", u=>u.UserId) + { + + } + + public override void Merge(ChatUserInfo item) + { + var key = GetKey(item); + var existent = this.FirstOrDefault(u => u.UserId == key); + if (existent != null) { + existent.UserName = item.UserName; + existent.Roles = item.Roles; + existent.Avatar = item.Avatar; + existent.Connections = item.Connections; + } + else Add(item); + } + + } +} diff --git a/BookAStar/BookAStar/ViewModels/Messaging/ChatUserInfo.cs b/BookAStar/BookAStar/ViewModels/Messaging/ChatUserInfo.cs new file mode 100644 index 00000000..413666c3 --- /dev/null +++ b/BookAStar/BookAStar/ViewModels/Messaging/ChatUserInfo.cs @@ -0,0 +1,159 @@ + +using BookAStar.Helpers; +using System.Collections.ObjectModel; +using System.Linq; +using Xamarin.Forms; +using XLabs.Forms.Mvvm; +using YavscLib; +using System; +using Newtonsoft.Json; + +namespace BookAStar.Model.Social.Chat +{ + public class ChatUserInfo : ViewModel, IChatUserInfo + { + + public string avatar; + public string Avatar + { + get + { + return avatar; + } + set + { + var newSource = UserHelpers.Avatar(value); + SetProperty(ref avatar, value); + SetProperty(ref avatarSource, newSource, "AvatarSource"); + } + } + + ImageSource avatarSource; + [JsonIgnore] + public ImageSource AvatarSource + { + get + { + return avatarSource; + } + } + + public Connection [] Connections + { + get + { + return ObservableConnections?.ToArray(); + } + set + { + ObservableConnections = new ObservableCollection(value); + } + } + + ObservableCollection connections; + [JsonIgnore] + public ObservableCollection ObservableConnections + { + get + { + return connections; + } + set + { + SetProperty>(ref connections, value); + } + } + + string[] roles; + public string[] Roles + { + get + { + return roles; + } + set + { + SetProperty(ref roles, value); + NotifyPropertyChanged("RolesAsAString"); + } + } + + [JsonIgnore] + public string RolesAsAString + { + get + { + return string.Join(", ", Roles); + } + } + + string userId; + public string UserId + { + get + { + return userId; + } + set + { + SetProperty(ref userId, value); + } + } + + string userName; + public string UserName + { + get + { + return userName; + } + set + { + SetProperty(ref userName, value); + } + } + + public bool IsConnected { get + { + return Connections.Length > 0; + } } + + [JsonIgnore] + IConnection[] IChatUserInfo.Connections + { + get + { + return Connections; + } + + set + { + throw new NotImplementedException(); + } + } + + + public void OnConnected(string cxId) + { + // We do assume this cxId dosn't already exist in this list. + var cx = new Connection { ConnectionId = cxId, Connected = true }; + if (ObservableConnections == null) + ObservableConnections = new ObservableCollection(); + ObservableConnections.Add(cx); + if (this.ObservableConnections.Count == 1) + NotifyPropertyChanged("IsConnected"); + } + + public void OnDisconnected(string cxId) + { + var existentcx = Connections.FirstOrDefault(cx => cx.ConnectionId == cxId); + if (existentcx != null) + { + this.ObservableConnections.Remove(existentcx); + + if (this.ObservableConnections.Count == 0) + NotifyPropertyChanged("IsConnected"); + } + } + } +} diff --git a/BookAStar/BookAStar/ViewModels/Messaging/ChatViewModel.cs b/BookAStar/BookAStar/ViewModels/Messaging/ChatViewModel.cs index 615c6d98..a6ebaa38 100644 --- a/BookAStar/BookAStar/ViewModels/Messaging/ChatViewModel.cs +++ b/BookAStar/BookAStar/ViewModels/Messaging/ChatViewModel.cs @@ -7,6 +7,7 @@ using XLabs.Forms.Mvvm; namespace BookAStar.ViewModels.Messaging { using Data; + using Model.Social.Chat; using Model.Social.Messaging; class ChatViewModel: ViewModel @@ -14,7 +15,7 @@ namespace BookAStar.ViewModels.Messaging public ObservableCollection Messages { get; set; } public ObservableCollection Notifs { get; set; } public ObservableCollection PVs { get; set; } - public ObservableCollection Contacts { get; set; } + public ChatUserCollection ChatUsers { get; set; } private ConnectionState state; public ConnectionState State @@ -29,9 +30,7 @@ namespace BookAStar.ViewModels.Messaging Messages = new ObservableCollection(); Notifs = new ObservableCollection(); PVs = DataManager.Instance.PrivateMessages; - Contacts = - new ObservableCollection( - DataManager.Instance.Contacts.Select(c=>new UserViewModel { Data = c })); + ChatUsers = DataManager.Instance.ChatUsers; App.ChatHubProxy.On("addMessage", (n, m) => { Messages.Add(new ChatMessage @@ -60,24 +59,33 @@ namespace BookAStar.ViewModels.Messaging if (eventId == "connected") OnUserConnected(cxId, userName); else if (eventId == "disconnected") - OnUserDisconnected(userName); + OnUserDisconnected(cxId, userName); }); } private void OnUserConnected(string cxId, string userName) { - var user = Contacts.SingleOrDefault( - c => c.Data.UserName == userName); - if (user != null) - user.ConnexionId = cxId; + var user = ChatUsers.SingleOrDefault( + c => c.UserName == userName); + if (user == null) + { + user = new ChatUserInfo { + UserName = userName + }; + ChatUsers.Add(user); + } + user.OnConnected(cxId); } - private void OnUserDisconnected (string userName) + private void OnUserDisconnected (string cxId, string userName) { - var user = Contacts.SingleOrDefault( - c => c.Data.UserName == userName); - if (user != null) - user.ConnexionId = null; + var user = ChatUsers.SingleOrDefault( + c => c.UserName == userName); + if (user == null) + { + return; + } + user.OnDisconnected(cxId); } private void MainSettings_UserChanged(object sender, EventArgs e) diff --git a/BookAStar/BookAStar/ViewModels/Messaging/UserViewModel.cs b/BookAStar/BookAStar/ViewModels/Messaging/UserViewModel.cs deleted file mode 100644 index 0895802b..00000000 --- a/BookAStar/BookAStar/ViewModels/Messaging/UserViewModel.cs +++ /dev/null @@ -1,75 +0,0 @@ -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); - } - } - } -} diff --git a/BookAStar/BookAStar/Views/RatingView.xaml b/BookAStar/BookAStar/Views/RatingView.xaml index 6200d425..90efcced 100644 --- a/BookAStar/BookAStar/Views/RatingView.xaml +++ b/BookAStar/BookAStar/Views/RatingView.xaml @@ -15,7 +15,7 @@ - + diff --git a/BookAStar/BookAStar/Views/UserListView.xaml b/BookAStar/BookAStar/Views/UserListView.xaml index 348aa1e3..0931d857 100644 --- a/BookAStar/BookAStar/Views/UserListView.xaml +++ b/BookAStar/BookAStar/Views/UserListView.xaml @@ -15,16 +15,18 @@ - + - + diff --git a/BookAStar/BookAStar/Views/UserListView.xaml.cs b/BookAStar/BookAStar/Views/UserListView.xaml.cs index 18f5daac..507f7fef 100644 --- a/BookAStar/BookAStar/Views/UserListView.xaml.cs +++ b/BookAStar/BookAStar/Views/UserListView.xaml.cs @@ -1,4 +1,5 @@ using BookAStar.Model; +using BookAStar.ViewModels.Messaging; using System; using System.Collections; using System.Collections.Generic; @@ -6,7 +7,7 @@ using System.Collections.ObjectModel; using System.Linq; using System.Text; using System.Threading.Tasks; - +using System.Windows.Input; using Xamarin.Forms; namespace BookAStar.Views @@ -14,24 +15,57 @@ namespace BookAStar.Views public partial class UserListView : ContentView { public BindableProperty ItemsSourceProperty = BindableProperty.Create( - "ItemsSource", typeof(IEnumerable), typeof(UserListView)); + "ItemsSource", typeof(ChatUserCollection), typeof(UserListView), default(ChatUserCollection), + BindingMode.OneWay); + + public BindableProperty ItemSelectedProperty = BindableProperty.Create( + "ItemSelected", typeof(ICommand), typeof(UserListView), default(ICommand)); - public IEnumerable ItemsSource + public BindableProperty DisableSelectionProperty = BindableProperty.Create( + "DisableSelection", typeof(bool), typeof(UserListView), false); + + public ChatUserCollection ItemsSource { - get { return list.ItemsSource; } - set { list.ItemsSource = value; } + get { return (ChatUserCollection) GetValue(ItemsSourceProperty); } + set { SetValue(ItemsSourceProperty, value); } + } + + public ICommand ItemSelected + { + get { return (ICommand) GetValue(ItemSelectedProperty); } + set { SetValue(ItemSelectedProperty, value); } } - /* public IEnumerable ItemsSource + public bool DisableSelection { - get { return GetValue(ItemsSourceProperty) as IEnumerable; } - set { SetValue(ItemsSourceProperty, value); } + get { return (bool) GetValue(DisableSelectionProperty); } + set { SetValue(DisableSelectionProperty, value); } } - */ + public UserListView() { InitializeComponent(); - } + list.ItemSelected += OnUserSelected; + } + protected override void OnBindingContextChanged() + { + base.OnBindingContextChanged(); + ICommand dataCommand = (ICommand) BindingContext; + list.RefreshCommand = new Command( + () => { + dataCommand.Execute(null); + list.EndRefresh(); + }); + } + public void OnUserSelected(object sender, SelectedItemChangedEventArgs ev) + { + if (ItemSelected != null) + if (ItemSelected.CanExecute(ev.SelectedItem)) + { + ItemSelected.Execute(ev.SelectedItem); + } + if (DisableSelection) list.SelectedItem = null; + } } } diff --git a/YavscLib/project.lock.json b/YavscLib/project.lock.json index ecd73a7b..5e5bd0e5 100644 --- a/YavscLib/project.lock.json +++ b/YavscLib/project.lock.json @@ -3,20 +3,18 @@ "version": 2, "targets": { ".NETFramework,Version=v4.5.1": {}, - ".NETPortable,Version=v4.5,Profile=Profile111": {}, - ".NETFramework,Version=v4.5.1/debian.8-x86": {}, - ".NETFramework,Version=v4.5.1/debian.8-x64": {}, - ".NETPortable,Version=v4.5,Profile=Profile111/debian.8-x86": {}, - ".NETPortable,Version=v4.5,Profile=Profile111/debian.8-x64": {} + ".NETPortable,Version=v4.5,Profile=Profile111": {} }, "libraries": {}, "projectFileDependencyGroups": { "": [], ".NETFramework,Version=v4.5.1": [], ".NETPortable,Version=v4.5,Profile=Profile111": [ - "fx/System.Runtime >= 4.0.0", - "fx/System.Globalization >= 4.0.0", - "fx/System.Resources.ResourceManager >= 4.0.0" + "System.Globalization >= 4.0.0", + "System.Resources.ResourceManager >= 4.0.0", + "System.Runtime >= 4.0.0" ] - } + }, + "tools": {}, + "projectFileToolGroups": {} } \ No newline at end of file