コード例 #1
0
ファイル: Presence.cs プロジェクト: Mazyod/PhoenixSharp
        // lower-level public static API

        /**
         * Used to sync the list of presences on the server
         * with the client's state. An optional `onJoin` and `onLeave` callback can
         * be provided to react to changes in the client's local presences across
         * disconnects and reconnects with the server.
         */
        public static State SyncState(
            State currentState,
            State newState,
            OnJoinDelegate onJoin   = null,
            OnLeaveDelegate onLeave = null
            )
        {
            var joins  = new State();
            var leaves = new State();

            foreach (var key in currentState.Keys.Where(key => !newState.ContainsKey(key)))
            {
                leaves[key] = currentState[key];
            }

            foreach (var key in newState.Keys)
            {
                var newPresence = newState[key];
                var found       = currentState.TryGetValue(key, out var currentPresence);
                if (found)
                {
                    var newRefs     = newPresence.Metas.Select(m => m["phx_ref"]).ToList();
                    var curRefs     = currentPresence.Metas.Select(m => m["phx_ref"]).ToList();
                    var joinedMetas = newPresence.Metas.Where(m => curRefs.IndexOf(m["phx_ref"]) < 0).ToList();
                    var leftMetas   = currentPresence.Metas.Where(m => !newRefs.Contains(m["phx_ref"])).ToList();
                    if (joinedMetas.Count > 0)
                    {
                        joins[key] = new MetadataContainer {
                            Metas = joinedMetas
                        };
                    }

                    if (leftMetas.Count > 0)
                    {
                        leaves[key] = new MetadataContainer {
                            Metas = leftMetas
                        };
                    }
                }
                else
                {
                    joins[key] = newPresence;
                }
            }

            var diff = new Diff {
                Joins = joins, Leaves = leaves
            };

            return(SyncDiff(new State(currentState), diff, onJoin, onLeave));
        }
コード例 #2
0
        public static State SyncState(State currentState, State newState, OnJoinDelegate onJoin, OnLeaveDelegate onLeave)
        {
            var state  = Clone(currentState);
            var joins  = new State();
            var leaves = new State();

            foreach (var entry in state)
            {
                if (!newState.ContainsKey(entry.Key))
                {
                    leaves[entry.Key] = entry.Value;
                }
            }
            foreach (var entry in newState)
            {
                if (state.ContainsKey(entry.Key))
                {
                    var currentItem = state[entry.Key];
                    var newRefs     = entry.Value["metas"].Select(m => m["phx_ref"]).ToList();
                    var curRefs     = currentItem["metas"].Select(m => m["phx_ref"]).ToList();
                    var joinedMetas = entry.Value["metas"].Where(m => !curRefs.Contains(m["phx_ref"])).ToList();
                    var leftMetas   = currentItem["metas"].Where(m => !newRefs.Contains(m["phx_ref"])).ToList();
                    if (joinedMetas.Count() > 0)
                    {
                        joins[entry.Key]          = entry.Value;
                        joins[entry.Key]["metas"] = joinedMetas;
                    }
                    if (leftMetas.Count() > 0)
                    {
                        leaves[entry.Key]          = Clone(currentItem);
                        leaves[entry.Key]["metas"] = leftMetas;
                    }
                }
                else
                {
                    joins[entry.Key] = entry.Value;
                }
            }
            var diff = new Diff();

            diff["joins"]  = joins;
            diff["leaves"] = leaves;
            return(SyncDiff(state, diff, onJoin, onLeave));
        }
コード例 #3
0
        private (Presence, Channel) NewPresence(string id, OnJoinDelegate onJoin = null, OnLeaveDelegate onLeave = null, OnSyncDelegate onSync = null)
        {
            var socketFactory = new DotNetWebSocketFactory();
            var socket        = new Socket(socketFactory, new Socket.Options
            {
                channelRejoinInterval = TimeSpan.FromMilliseconds(200),
                logger = new BasicLogger()
            });
            var url = string.Format("ws://{0}/phoenix_sharp_test", host);

            socket.Connect(url);
            Assert.IsTrue(socket.state == Socket.State.Open);
            var channel  = socket.MakeChannel("presence");
            var presence = new Presence(channel);

            if (onJoin != null)
            {
                presence.onJoin = onJoin;
            }
            if (onLeave != null)
            {
                presence.onLeave = onLeave;
            }
            if (onSync != null)
            {
                presence.onSync = onSync;
            }

            Reply?joinOkReply    = null;
            Reply?joinErrorReply = null;

            channel.Join(new Dictionary <string, object> {
                { "id", id }
            })
            .Receive(Reply.Status.Ok, r => joinOkReply       = r)
            .Receive(Reply.Status.Error, r => joinErrorReply = r);
            Assert.That(() => joinOkReply.HasValue, Is.True.After(networkDelay, 10));
            return(presence, channel);
        }
コード例 #4
0
        public static State SyncDiff(State currentState, Diff diff, OnJoinDelegate onJoin, OnLeaveDelegate onLeave)
        {
            var state = Clone(currentState);

            foreach (var entry in diff["joins"])
            {
                Item currentItem = null;
                if (state.ContainsKey(entry.Key))
                {
                    currentItem = state[entry.Key];
                }
                state[entry.Key] = entry.Value;
                if (currentItem != null)
                {
                    var joinedRefs = state[entry.Key]["metas"].Select(m => m["phx_ref"]).ToList();
                    var curMetas   = currentItem["metas"].Where(m => !joinedRefs.Contains(m["phx_ref"])).ToList();
                    state[entry.Key]["metas"] = curMetas.Concat(state[entry.Key]["metas"]).ToList();
                }
                onJoin?.Invoke(entry.Key, currentItem, entry.Value);
            }
            foreach (var entry in diff["leaves"])
            {
                if (!state.ContainsKey(entry.Key))
                {
                    continue;
                }
                var currentItem  = state[entry.Key];
                var refsToRemove = entry.Value["metas"].Select(m => m["phx_ref"]).ToList();
                currentItem["metas"] = currentItem["metas"].Where(m => !refsToRemove.Contains(m["phx_ref"])).ToList();
                onLeave?.Invoke(entry.Key, currentItem, entry.Value);
                if (currentItem["metas"].Count() == 0)
                {
                    state.Remove(entry.Key);
                }
            }
            return(state);
        }
コード例 #5
0
 public Task <IAsyncDisposable> OnJoin(OnJoinDelegate handler)
 {
     return(InnerSubscribe(handler, x => x.OnJoin(default(WampSessionDetails))));
 }