How to keep track of chat messages seen by user - angularjs

I am building a simple Chat App using Firebase and Ionic. I am trying to keep track of number of messages that are unread for different groups that the user is member of (like WhatsApp).
I have the messages linked to $scope through $firebaseArray
$scope.messages = $firebaseArray(<ref to message path in firebase>);
$scope.messages is iterated over and shown in the view. When a new message arrives it automatically shows up in the group being viewed. I want to keep track of messages not viewed. I am not quite sure of the best way to keep track of which messages the user has seen. I see suggestions here to keep track of timestamp when a user last visited a group but am wondering if there is a better/simpler solution to this.
The things that come to mind that I need to do are -
Setup some sort of monitoring for all groups the user is member of not just the one being viewed by the user. If user is member of 50 groups I need to monitor all 50 of them individually (wonder what, if any, performance implications that has). Here I will need to setup a child_added monitoring for each of the groups the user is member of
Track timestamp for last time a user was in a group
As the user switches groups, change the $firebaseArray to monitor the new group and cancel the $firebaseArray setup for the previous. Change the child_added monitoring for the new group to the group being viewed previously
If the user moves to another part of the app where he is not looking at any group messages (perhaps in a setting section) then again be aware of that and monitor all groups - remove the firebeaseArray from the group last being viewed and add a child_added monitoring when user moves away
If the user goes to another application and pushes the Chat application in the background then I am a little unsure of what to do
How does the code determine that the group whose messages the user was looking at is no longer active and new messages coming in now need to be counted
I am assuming I need to monitor for the App Pause and Resume events to address that. Is there a better way?
Trying to keep my code simple but feels like monitoring for unread messages is a significant chunk of work. Thanks for any ideas or pointers to sample code or to simplify this.
-S

Related

Clear previous Alexa Cards

Is there a way to tell Alexa to either remove previous cards when I send a new one?
I have an skill which sends kind of a status each time you run a command, and typical use case is to do multiple actions in a session, each of which I'd like to send a card. It gets really cluttered since they all just add on to each other. I'd like to just either update the first card, or remove it and make a new one each time.
That is not possible with the current API. I think anyone using skills is already used to the flood of cards that come after each interaction.

Firebase having thousands of on() event listeners good design

We need to run some operation on our Firebase DB and manipulate data after certain input is given by user from the Mobile Device modifying a flag.
Currently we are using on() to listen to particular flag in each users node. We are running this listener from a Nodejs server hosted on Heruku.
If we plan to have 100 thousand users we will have 100 thousand listener. One listener for each users flag which is waiting to be manipulated by user on the Mobile device.
Is this a good design in terms of Firebase?
Ideally we can create a REST API which is called by users and then on the Node JS server we can manipulate the data.
What is the best way to run background operation on Data on Firebase based on user input?
We were using Parse earlier and it was easy to achieve this using Parse Cloud code. With Firebase we are having issues because of this.
If we plan to have 100 thousand users we will have 100 thousand listener. One listener for each users flag which is waiting to be manipulated by user on the Mobile device.
This sounds like a bad data design. While it is definitely possible to listen for changes to hundreds of thousands of items, it shouldn't require hundreds of thousands listeners.
My guess (because you didn't include a snippet of your JSON) is that you have a structure similar to this:
users
$uid
name: "user6155746"
flag: "no"
And you're attaching a listener in just the flag of each user with something like:
ref.child('users').on('child_added', function(userSnapshot) {
userSnapshot.ref().child('flag').on('value', function(flagSnapshot) {
console.log('the flag changed to '+flagSnapshot.val());
});
})
In code this is simple, in practice you'll have a hard time managing the "flag listeners". When will you remove them? Do you keep a list of them?
All of these things become a list simpler if you isolate the information that you're interested in in the JSON tree:
users
$uid
name: "user6155746"
userFlags
$uid: "no"
Now you can just listen on userFlags to see if the flag of any user has changed:
ref.child('userFlags').on('child_changed', function(userSnapshot) {
console.log('Flag of user '+userSnapshot.key()+' changed to '+userSnapshot.val());
});
With this you have a single listener, monitoring the flag of potentially hundreds of thousands of users.

Keeping repository synced with multiple clients

I have a WPF application that uses entity framework. I am going to be implementing a repository pattern to make interactions with EF simple and more testable. Multiple clients can use this application and connect to the same database and do CRUD operations. I am trying to think of a way to synchronize clients repositories when one makes a change to the database. Could anyone give me some direction on how one would solve this type of issue, and some possible patterns that would be beneficial for this type of problem?
I would be very open to any information/books on how to keep clients synchronized, and even be alerted of things other clients are doing(The only thing I could think of was having a server process running that passes messages around). Thank you
The easiest way by far to keep every client UI up to date is just to simply refresh the data every so often. If it's really that important, you can set a DispatcherTimer to tick every minute when you can get the latest data that is being displayed.
Clearly, I'm not suggesting that you refresh an item that is being edited, but if you get the fresh data, you can certainly compare collections with what's being displayed currently. Rather than just replacing the old collection items with the new, you can be more user friendly and just add the new ones, remove the deleted ones and update the newer ones.
You could even detect whether an item being currently edited has been saved by another user since the current user opened it and alert them to the fact. So rather than concentrating on some system to track all data changes, you should put your effort into being able to detect changes between two sets of data and then seamlessly integrating it into the current UI state.
UPDATE >>>
There is absolutely no benefit from holding a complete set of data in your application (or repository). In fact, you may well find that it adds detrimental effects, due to the extra RAM requirements. If you are polling data every few minutes, then it will always be up to date anyway.
So rather than asking for all of the data all of the time, just ask for what the user wants to see (dependant on which view they are currently in) and update it every now and then. I do this by simply fetching the same data that the view requires when it is first opened. I wrote some methods that compare every property of every item with their older counterparts in the UI and switch old for new.
Think of the Equals method... You could do something like this:
public override bool Equals(Release otherRelease)
{
return base.Equals(otherRelease) && Title == otherRelease.Title &&
Artist.Equals(otherRelease.Artist) && Artists.Equals(otherRelease.Artists);
}
(Don't actually use the Equals method though, or you'll run into problems later). And then something like this:
if (!oldRelease.Equals(newRelease)) oldRelease.UpdatePropertyValues(newRelease);
And/Or this:
if (!oldReleases.Contains(newRelease) oldReleases.Add(newRelease);
I'm guessing that you get the picture now.

Lock a record from other users when editing by single user in CakePHP 2.4

I am implementing a CakePHP 2.4 app.
I have User and Article as Models.
I have no articles/view action; only articles/edit and articles/delete actions.
When any User accesses the articles/edit webpage regardless as a GET or POST, that particular Article is locked from editing/deleting by other Users.
The following is the crucial part I need advice on.
If a User stays on articles/edit/23 but there is no activity for 30 minutes,
-- OR --
When the User leaves articles/edit/23 page,
then the articles/23 is now available for edit/delete by other Users.
Off the top of my mind, i know that in articles table, i need a field called currently_locked_by field that holds the user_id of the User currently in control.
My problem is with detecting the session inactivity and knowing that the User has left the edit page.
I am defining session inactivity in the edit page as when the User does not type anything in any input elements or changes any dropdown selection or checks/uncheck any checkbox.
Suggestions?
You could create a lock table with a combination of the user, resource and lock time. (Regarding your spec's when to start the inactivity - I recommend going simpler to start: "when they person loads the page". Otherwise you are also writing javascript to write to your database at the end of every field change.)
Whenever a person goes to the edit page,
They check that table for the resource and lock time. If the record does not exist or the lock time has been exceeded it is safe for them to edit.
If they can edit, then they insert a record as needed (and delete any records with that resource.)
This should take care of the timeout requirement as long you make sure the person still has a lock (or another hasn't locked the record) when they try to save their changes.
One technique to handle the leaving of pages, is to put in a beforeFilter test that removes all locks for that person. The downsides
You still can't tell if the person leaves and goes to some external
site.
The beforeFilter does add overhead to every page view.
If your users run two or more tabs, then navigating other tabs will
release the lock.
You could also just have every outbound link on that page release the lock (like going to an interstitial page) and let any departures via closing the tab, using address bar, etc timeout. (It depends on how your users work.)

Swipe-delete messages only for current user

thanks for taking time looking at my question.
Ok so I'm working on this iPhone app. I'm responsible for the server side code. Client side is asking for a solution to delete private messages from the app. I have created a HTTP DELETE for them that deletes a specific message. But this request deletes the message from the database and that makes the message disappear for both users and not only the one that have choosen to delete it.
I've been thinking but I can't seem to find the best solution for this. What I need is a solution to only delete the message for the current user.
Should I add some columns in the database that tells which user the private message should be shown for? And when a user deletes the message from the app it only stops showing on that users phone. Or is there a better solution for this?
I need help with some brainstorming. I hope it is an OK question.
Thanks!
A physical delete should probably be avoided. The first couple of reasons I can think of:
how can you do proper testing/audit if the information you're looking for is gone?
legal issues: do you need some levels of data retention?
You can implement some form of logical delete, for example with an extra relation such as UserMessage( UserID, MessageID, MessageStatus ), where MessageStatus could be "unread", "read", "deleted", "important", "spam", etc. (you can map the status to an arbitrary integer if you prefer). When a user deletes a message, you simply change its status in the UserMessage relation, and from the UI side you hide messages which are marked as "deleted".

Resources