Fixed issue with Horizontal list not refreshing. Added clientId to joinPartyResponse. Crashing on multiple user joins.
This commit is contained in:
parent
11a585ecc0
commit
d78dce44f0
@ -25,10 +25,10 @@ namespace Aurora.Design.Components.HorizontalList
|
||||
|
||||
public static readonly BindableProperty ItemsSourceProperty =
|
||||
BindableProperty.Create("ItemsSource",
|
||||
typeof(ObservableCollection<object>),
|
||||
typeof(HorizontalList),
|
||||
default(ObservableCollection<object>),
|
||||
BindingMode.TwoWay,
|
||||
returnType: typeof(ObservableCollection<object>),
|
||||
declaringType: typeof(HorizontalList),
|
||||
defaultValue: default(ObservableCollection<object>),
|
||||
defaultBindingMode: BindingMode.TwoWay,
|
||||
propertyChanged: ItemsSourceChanged);
|
||||
|
||||
public static readonly BindableProperty SelectedItemProperty =
|
||||
|
@ -14,7 +14,7 @@
|
||||
<DataTemplate>
|
||||
<Frame>
|
||||
<Label
|
||||
Text="{Binding Username}"/>
|
||||
Text="{Binding UserName}"/>
|
||||
</Frame>
|
||||
</DataTemplate>
|
||||
</hl:HorizontalList.ItemTemplate>
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using Xamarin.Forms;
|
||||
using Aurora.Proto.Party;
|
||||
|
||||
@ -9,10 +10,10 @@ namespace Aurora.Design.Components.MemberList
|
||||
public partial class MemberList : ContentView
|
||||
{
|
||||
private static ObservableCollection<PartyMember> _newSource;
|
||||
private static NotifyCollectionChangedEventHandler _collectionChangedHandler;
|
||||
public MemberList()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -44,6 +45,7 @@ namespace Aurora.Design.Components.MemberList
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Memberes changed event handler. Assign member list source.
|
||||
/// </summary>
|
||||
@ -57,7 +59,56 @@ namespace Aurora.Design.Components.MemberList
|
||||
if (membersList != null)
|
||||
{
|
||||
_newSource = newValue as ObservableCollection<PartyMember>;
|
||||
membersList.ItemsSource = newValue as ObservableCollection<object>;
|
||||
membersList.ItemsSource = new ObservableCollection<object>(_newSource);
|
||||
|
||||
//Setup collection changed listeners
|
||||
//TODO evaluate for memory leak
|
||||
_newSource.CollectionChanged += (sender, e) => HandleCollectionChanged(sender, e, bindable);
|
||||
}
|
||||
}
|
||||
|
||||
private static void HandleCollectionChanged(object sender, NotifyCollectionChangedEventArgs e, BindableObject bindable)
|
||||
{
|
||||
MemberList self = bindable as MemberList;
|
||||
var membersList = self.FindByName("MembersHorizontalList") as HorizontalList.HorizontalList;
|
||||
|
||||
switch (e.Action)
|
||||
{
|
||||
case NotifyCollectionChangedAction.Add:
|
||||
{
|
||||
foreach (PartyMember member in e.NewItems)
|
||||
{
|
||||
membersList.ItemsSource.Add(member);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case NotifyCollectionChangedAction.Remove:
|
||||
{
|
||||
foreach (PartyMember member in e.NewItems)
|
||||
{
|
||||
//Find all matches
|
||||
var sourceMembers = membersList.ItemsSource.Where((object obj) =>
|
||||
{
|
||||
bool match = false;
|
||||
if (obj is PartyMember)
|
||||
{
|
||||
PartyMember tmp = obj as PartyMember;
|
||||
match = tmp.Id == member.Id;
|
||||
}
|
||||
|
||||
return match;
|
||||
});
|
||||
|
||||
//Remove found matches
|
||||
foreach (object obj in sourceMembers)
|
||||
{
|
||||
membersList.ItemsSource.Remove(obj);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:hs="clr-namespace:Aurora.Design.Components.HostSelector"
|
||||
xmlns:hl="clr-namespace:Aurora.Design.Components.HorizontalList"
|
||||
xmlns:ml="clr-namespace:Aurora.Design.Components.MemberList"
|
||||
xmlns:renderedViews="clr-namespace:Sharpnado.Presentation.Forms.RenderedViews;assembly=Sharpnado.Presentation.Forms"
|
||||
xmlns:qu="clr-namespace:Aurora.Design.Components.Queue"
|
||||
x:Class="Aurora.Design.Views.Party.PartyView">
|
||||
@ -18,20 +18,9 @@
|
||||
IsVisible="{Binding IsNotSelectingHost}">
|
||||
<Label
|
||||
Text="Party Members"/>
|
||||
<hl:HorizontalList
|
||||
x:Name="MembersHorizontalList"
|
||||
ListOrientation="Horizontal"
|
||||
VerticalOptions="Start"
|
||||
ItemsSource="{Binding Members}">
|
||||
<hl:HorizontalList.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Frame>
|
||||
<Label
|
||||
Text="{Binding UserName}"/>
|
||||
</Frame>
|
||||
</DataTemplate>
|
||||
</hl:HorizontalList.ItemTemplate>
|
||||
</hl:HorizontalList>
|
||||
<ml:MemberList
|
||||
VerticalOptions="FillAndExpand"
|
||||
Members="{Binding Members}"/>
|
||||
<Label
|
||||
Text="Queue"/>
|
||||
<qu:Queue/>
|
||||
|
@ -39,11 +39,8 @@ namespace Aurora.Design.Views.Party
|
||||
{
|
||||
this.JoinCommand = new Command(OnJoinExecute, CanJoinExecute);
|
||||
this.HostCommand = new Command(OnHostExecute, CanHostExecute);
|
||||
_members = new ObservableCollection<PartyMember>
|
||||
{
|
||||
new PartyMember{UserName = "asdf"}
|
||||
};
|
||||
|
||||
_members = new ObservableCollection<PartyMember>();
|
||||
|
||||
SetState(PartyState.SelectingHost);
|
||||
}
|
||||
@ -142,17 +139,24 @@ namespace Aurora.Design.Views.Party
|
||||
/// <returns></returns>
|
||||
private async void JoinParty()
|
||||
{
|
||||
await _remotePartyClient.JoinPartyAsync(new JoinPartyRequest
|
||||
JoinPartyResponse resp = await _remotePartyClient.JoinPartyAsync(new JoinPartyRequest
|
||||
{
|
||||
UserName = SettingsService.Instance.Username,
|
||||
});
|
||||
|
||||
SettingsService.Instance.ClientId = resp.ClientId;
|
||||
|
||||
RefreshMembers();
|
||||
|
||||
//Subscribe to events
|
||||
SubscribeRequest req = new SubscribeRequest();
|
||||
req.EventTypes.Add(EventType.PartyMemberJoined);
|
||||
req.EventTypes.Add(EventType.PartyMemberLeft);
|
||||
if (!string.IsNullOrWhiteSpace(SettingsService.Instance.ClientId))
|
||||
{
|
||||
req.ClientId = SettingsService.Instance.ClientId;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_remoteEventsClient.SubscribeToEvents(req);
|
||||
@ -202,11 +206,13 @@ namespace Aurora.Design.Views.Party
|
||||
/// <returns></returns>
|
||||
private async void GetEvents()
|
||||
{
|
||||
using (AsyncServerStreamingCall<BaseEvent> eventStream = _remoteEventsClient.GetEvents(new Empty()))
|
||||
using (AsyncServerStreamingCall<BaseEvent> eventStream = _remoteEventsClient
|
||||
.GetEvents(new EventsRequest { ClientId = SettingsService.Instance.ClientId }))
|
||||
{
|
||||
while (!_eventCancellationTokenSource.Token.IsCancellationRequested)
|
||||
while (!_eventCancellationTokenSource.Token.IsCancellationRequested &&
|
||||
await eventStream.ResponseStream.MoveNext(_eventCancellationTokenSource.Token))
|
||||
{
|
||||
if (await eventStream.ResponseStream.MoveNext(_eventCancellationTokenSource.Token))
|
||||
try
|
||||
{
|
||||
//Convert derived event type
|
||||
BaseEvent e = eventStream.ResponseStream.Current;
|
||||
@ -233,6 +239,11 @@ namespace Aurora.Design.Views.Party
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(string.Format("EXCEPTION --- " + ex.Message));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
22
Aurora/Models/PartyMember.cs
Normal file
22
Aurora/Models/PartyMember.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
|
||||
namespace Aurora.Proto.Party
|
||||
{
|
||||
/// <summary>
|
||||
/// Partial PartyMember class with a constructor that generates a new id
|
||||
/// </summary>
|
||||
public partial class PartyMember
|
||||
{
|
||||
public PartyMember(string id)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(id))
|
||||
{
|
||||
Id = id;
|
||||
}
|
||||
else
|
||||
{
|
||||
Id = Guid.NewGuid().ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -7,22 +7,29 @@ import "Proto/party.proto";
|
||||
|
||||
service RemoteEventService {
|
||||
//Party Service
|
||||
rpc GetEvents(Aurora.Proto.General.Empty) returns (stream BaseEvent) {};
|
||||
rpc GetEvents(EventsRequest) returns (stream BaseEvent) {};
|
||||
rpc SubscribeToEvents(SubscribeRequest) returns(SubscriptionResponse);
|
||||
rpc UnsubscribeFromEvents(UnsubscribeRequest) returns (SubscriptionResponse);
|
||||
rpc UnsubscribeFromAll(UnsubscribeAllRequest) returns (SubscriptionResponse);
|
||||
}
|
||||
|
||||
message EventsRequest {
|
||||
string clientId = 1;
|
||||
}
|
||||
|
||||
/* Subscription messages */
|
||||
message SubscribeRequest {
|
||||
repeated EventType eventTypes = 1;
|
||||
string clientId = 2;
|
||||
}
|
||||
|
||||
message UnsubscribeRequest {
|
||||
repeated EventType eventTypes = 1;
|
||||
string clientId = 2;
|
||||
}
|
||||
|
||||
message UnsubscribeAllRequest {
|
||||
string clientId = 1;
|
||||
}
|
||||
|
||||
message SubscriptionResponse {
|
||||
@ -36,16 +43,18 @@ enum EventType {
|
||||
}
|
||||
message BaseEvent {
|
||||
EventType eventType = 1;
|
||||
string clientKey = 2;
|
||||
|
||||
oneof derivedEvent {
|
||||
PartyMemberJoinedEvent partyMemberJoinedEvent = 2;
|
||||
PartyMemberLeftEvent partyMemberLeftEvent = 3;
|
||||
PartyMemberJoinedEvent partyMemberJoinedEvent = 3;
|
||||
PartyMemberLeftEvent partyMemberLeftEvent = 4;
|
||||
}
|
||||
}
|
||||
|
||||
message PartyMemberJoinedEvent {
|
||||
Aurora.Proto.Party.PartyMember member = 2;
|
||||
Aurora.Proto.Party.PartyMember member = 3;
|
||||
}
|
||||
|
||||
message PartyMemberLeftEvent {
|
||||
Aurora.Proto.Party.PartyMember member = 2;
|
||||
Aurora.Proto.Party.PartyMember member = 3;
|
||||
}
|
@ -17,6 +17,7 @@ message JoinPartyRequest {
|
||||
|
||||
message JoinPartyResponse {
|
||||
PartyJoinedStatusEnum status = 1;
|
||||
string clientId = 2;
|
||||
}
|
||||
|
||||
message LeavePartyRequest {
|
||||
|
@ -22,17 +22,27 @@ namespace Aurora.RemoteImpl
|
||||
/// <param name="responseStream">The response stream</param>
|
||||
/// <param name="context">gRPC client context</param>
|
||||
/// <returns></returns>
|
||||
public async override Task GetEvents(Empty request, Grpc.Core.IServerStreamWriter<BaseEvent> responseStream, Grpc.Core.ServerCallContext context)
|
||||
public async override Task GetEvents(EventsRequest request, Grpc.Core.IServerStreamWriter<BaseEvent> responseStream, Grpc.Core.ServerCallContext context)
|
||||
{
|
||||
while (EventManager.Instance.GetSubscriptionCount(context.Peer) > 0)
|
||||
try
|
||||
{
|
||||
List<BaseEvent> events = EventManager.Instance.GetSessionEvents(context.Peer);
|
||||
while (EventManager.Instance.GetSubscriptionCount(Combine(new string[] { context.Peer, request.ClientId })) > 0)
|
||||
{
|
||||
Console.WriteLine("Peer " + context.Peer);
|
||||
//TODO this causes crashes when two or more members are connected
|
||||
//TODO Change this to events based stream instead of a poll based...
|
||||
List<BaseEvent> events = EventManager.Instance.GetSessionEvents(Combine(new string[] { context.Peer, request.ClientId }));
|
||||
foreach (BaseEvent currentEvent in events)
|
||||
{
|
||||
await responseStream.WriteAsync(currentEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Exception caught:" + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// RPC for subscribing to remote events
|
||||
@ -42,7 +52,7 @@ namespace Aurora.RemoteImpl
|
||||
/// <returns></returns>
|
||||
public override Task<SubscriptionResponse> SubscribeToEvents(SubscribeRequest request, Grpc.Core.ServerCallContext context)
|
||||
{
|
||||
EventManager.Instance.AddSubscriptionList(context.Peer, request.EventTypes.ToList());
|
||||
EventManager.Instance.AddSubscriptionList(Combine(new string[] { context.Peer, request.ClientId }), request.EventTypes.ToList());
|
||||
|
||||
return Task.FromResult(new SubscriptionResponse { Successful = true });
|
||||
}
|
||||
@ -58,7 +68,7 @@ namespace Aurora.RemoteImpl
|
||||
EventType[] eventTypes = null;
|
||||
request.EventTypes.CopyTo(eventTypes, 0);
|
||||
|
||||
EventManager.Instance.RemoveSubscriptionList(context.Peer, eventTypes.ToList());
|
||||
EventManager.Instance.RemoveSubscriptionList(Combine(new string[] { context.Peer, request.ClientId }), eventTypes.ToList());
|
||||
|
||||
return Task.FromResult(new SubscriptionResponse { Successful = true });
|
||||
}
|
||||
@ -71,10 +81,28 @@ namespace Aurora.RemoteImpl
|
||||
/// <returns></returns>
|
||||
public override Task<SubscriptionResponse> UnsubscribeFromAll(UnsubscribeAllRequest request, Grpc.Core.ServerCallContext context)
|
||||
{
|
||||
EventManager.Instance.RemoveAllSubscriptions(context.Peer);
|
||||
EventManager.Instance.RemoveAllSubscriptions(Combine(new string[] { context.Peer, request.ClientId }));
|
||||
|
||||
return Task.FromResult(new SubscriptionResponse { Successful = true });
|
||||
}
|
||||
|
||||
private string Combine(string[] args)
|
||||
{
|
||||
string outString = "";
|
||||
foreach (string arg in args)
|
||||
{
|
||||
if (arg == args.Last())
|
||||
{
|
||||
outString += arg;
|
||||
}
|
||||
else
|
||||
{
|
||||
outString += arg + ":";
|
||||
}
|
||||
}
|
||||
|
||||
return outString;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -21,15 +21,6 @@ namespace Aurora.RemoteImpl
|
||||
public RemotePartyServiceImpl()
|
||||
{
|
||||
_partyMembers = new ObservableCollection<PartyMember>();
|
||||
|
||||
//Add self to members list
|
||||
_partyMembers.Add(new PartyMember
|
||||
{
|
||||
UserName = SettingsService.Instance.Username,
|
||||
Id = "asdf",
|
||||
IpAddress = ServerService.Instance.Hostname,
|
||||
Port = ServerService.Instance.Port
|
||||
});
|
||||
}
|
||||
|
||||
public ObservableCollection<PartyMember> PartyMembers
|
||||
@ -42,7 +33,7 @@ namespace Aurora.RemoteImpl
|
||||
|
||||
public override Task<JoinPartyResponse> JoinParty(JoinPartyRequest request, Grpc.Core.ServerCallContext context)
|
||||
{
|
||||
PartyMember partyMember = new PartyMember()
|
||||
PartyMember partyMember = new PartyMember("")
|
||||
{
|
||||
UserName = request.UserName,
|
||||
IpAddress = context.Host,
|
||||
@ -61,7 +52,7 @@ namespace Aurora.RemoteImpl
|
||||
|
||||
EventManager.Instance.PushEvent(e);
|
||||
|
||||
JoinPartyResponse response = new JoinPartyResponse() { Status = PartyJoinedStatusEnum.Connected };
|
||||
JoinPartyResponse response = new JoinPartyResponse() { Status = PartyJoinedStatusEnum.Connected, ClientId = partyMember.Id };
|
||||
return Task.FromResult(response);
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,10 @@ namespace Aurora.Services
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The user's username. This is persisted.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public string Username
|
||||
{
|
||||
get { return AppSettings.GetValueOrDefault(_usernameKey, ""); }
|
||||
@ -41,11 +45,24 @@ namespace Aurora.Services
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The default port to use. This is persisted.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public int DefaultPort
|
||||
{
|
||||
get { return AppSettings.GetValueOrDefault(_defaultPortKey, 4005); }
|
||||
set { AppSettings.AddOrUpdateValue(_defaultPortKey, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The current sessions clientId. This is assigned by the server. This is not persisted.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public string ClientId
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user