Application interface
You have included features of screens and application icon, to be able to install it in both Windows and mobile.
A very different interface has been defined to the usual phprunner to show all the contacts of the logged user. The image of group contact, square and red border and individual contact, round with blue border has been used. The order of appearance is by date of the last received message and a green ball will appear, with the messages that have not been read of that contact.
The total of unread messages appears at the header. This number will be updated when new messages arrive, without the user having to do anything.
Selected The contact shows the messages exchanged with it. The last one appears the first one. If it has never been shown, a green ball will appear on the left of the message. Along with the author, the date and time of the message appears. If the author and date is the same as the previous one, is not shown to facilitate reading.
On the right is the message in HTML, and under the handheld you will be the attached files that has said message.
Right now, it has a basic operation, but it can be expanded according to the needs of your project.
Both on this screen and in the previous one, the number of messages pending Read (Green Ball) is refreshed and the notifications of new messages at the lower right edge of the screen are displayed. If you click on the notification, the page is refreshed in which the user is and the new content is displayed.
Technical solution
The data model that I have used is this:
With this model it is facilitated that the same message is shown (with different states) for each of the recipients. It is the way not to duplicate the contents, this being the broadest information of the entire system.
In the "contact" table, the user's relationship information is maintained and the information of a group. We can appreciate in the code, that the information is displayed depending on the contact type. In all contact type cases, the "member" table is always used to contain all users of that contact.
In the table "message", the general data of the messages are available, but we help each other from several tables.
- "recipients" to manage the information of all recipients and the status of that message for each recipient.
- "contents" to store and manage the message (which can be large) and the attached files. The denormalization of this table is done to improve returns from the database manager.
The following plugins have been used in development (which you can download from this portal):
- summernote.- To enter the text of the messages.
- switch.- As an interface, for the decision in the contents.
Also, the JavaScript notify.js library has been used. https://github.com/jpillora/notifyjs as a manager of notifications. (On mobile devices, these notifications do not occur but do not generate error).
For those who are learning Phprunner, I recommend the revision of the code of this example. It is little code, but it is full of details, functionalities or uses that are not in the Phprunner manual and facilitates a lot of ideas to use in other projects.
Equity some examples of programming:
chat_ajax.php Program that resolves automatic requests that makes the browser without user interaction.
<?php
@ini_set("display_errors","1");
@ini_set("display_startup_errors","1");
require_once("include/dbcommon.php");
header("Expires: Thu, 01 Jan 1970 00:00:01 GMT");
$id_user = $_SESSION['id_user'];
$rs = DB::Query("SELECT count(*) count FROM recipients WHERE isRead = 0 AND user_id = $id_user");
$data = $rs->fetchAssoc();
$count = $data['count'];
$message = '*';
$rs2 = DB::Query("SELECT count(*) count FROM recipients WHERE isNotified = 0 AND user_id = $id_user order by dateAdd desc");
$data2 = $rs2->fetchAssoc();
$count2 = $data2['count'];
$rs2 = DB::Query("SELECT * FROM recipients WHERE isNotified = 0 AND user_id = $id_user order by dateAdd desc");
if ( $count2 <> 0 ){ // There are messages to notify
$data2 = $rs2->fetchAssoc();
$id_recipients = $data2['id_recipients'];
$data = array();
$keyvalues = array();
$data["isNotified"] = "1";
$keyvalues["id_recipients"] = $id_recipients;
DB::Update("recipients", $data, $keyvalues );
$id_contact = $data2['contact_id'];
$sql = <<<EOT
SELECT
contact.id_contact,
contact.administrator_id,
contact.isGroup,
if(contact.isGroup = 1, contact.nameGroup, user.name) AS name
FROM contact AS contact
JOIN member AS member ON ( member.contact_id = contact.id_contact )
JOIN user user ON ( member.user_id = user.id_user )
WHERE (contact.isDelete = 0 and user.id_user <> $id_user and contact.id_contact = $id_contact)
EOT;
$rs = DB::Query($sql);
$data = $rs->fetchAssoc();
$name = $data['name'];
$message = "You have received a new message from: '$name'";
}
echo "$count;$message;";
?>
Phprunner creates the mfhandler.php file to manage the rise and down of files. To eliminate restrictions on showing the users' photos I created the custom_mfhandler.php file.
To show at the header the total number of messages that are unread and schedule the refreshment of the data and notifications I have programmed notify_snnipet:
$id_user = $_SESSION['id_user'];
$rs = DB::Query("SELECT count(*) count FROM recipients WHERE isRead = 0 AND user_id = $id_user");
$data = $rs->fetchAssoc();
echo ' <b>Message Pending Reading:</b> <span id="pending_reading" class="badge badge-info">'.$data['count'].'</span>';
$js = <<<EOT
<script src="notify/notify.js"></script>
<script>
// -----------------------------------------------------------------------------------------------------
var site ='chat_ajax.php'; // To recover accountant new messages
var HttpClient = function() {
this.get = function(aUrl, aCallback) {
var anHttpRequest = new XMLHttpRequest();
anHttpRequest.onreadystatechange = function() {
if (anHttpRequest.readyState == 4 && anHttpRequest.status == 200)
aCallback(anHttpRequest.responseText);
}
anHttpRequest.open( "GET", aUrl, true );
anHttpRequest.send( null );
}
}
// -----------------------------------------------------------------------------------------------------
function onShowNotification () {
console.log('notification is shown!');
}
function onCloseNotification () {
console.log('notification is closed!');
}
function onClickNotification () {
window.location.reload(false);
console.log('notification was clicked!');
}
function onErrorNotification () {
console.error('Error showing notification. You may need to request permission.');
}
function onPermissionGranted () {
console.log('Permission has been granted by the user');
doNotification();
}
function onPermissionDenied () {
console.warn('Permission has been denied by the user');
}
function doNotification (response='') {
if (!Notify.needsPermission) {
var myNotification = new Notify('PHPRuner CHAT', {
body: 'Notice: '+response,
// tag: task,
notifyShow: onShowNotification,
notifyClose: onCloseNotification,
notifyClick: onClickNotification,
notifyError: onErrorNotification,
timeout: 10
});
myNotification.show();
} else if (Notify.isSupported()) {
Notify.requestPermission(onPermissionGranted, onPermissionDenied);
}
}
function loadlink(){
var client = new HttpClient();
client.get(site, function(response) {
console.log('Response: '+response);
resp = response.split(';');
if ( resp[1] != '*' ){
doNotification(resp[1]);
}
$('#pending_reading').text(resp[0]); // Update count total within reading
})
}
loadlink(); // This will run on page load
setInterval(function(){
loadlink(); // this will run after every 15 seconds
}, 15000);
</script>
EOT;
echo $js;
As you can see, events on notifications are completely controlled and the information changes control times can be adapted.
I'm not going to put much more code because all he is full of details, but for the "powerful" sample that can be phprunner, I leave the query's of the "contact" and "message" tables:
SELECT
id_contact,
contact.administrator_id,
contact.isGroup,
contact.nameGroup,
contact.user_id,
contact.photo,
contact.isDelete,
user1.name AS name1,
user2.name AS name2,
member.user_id AS member_user_id,
statistics.lastMessage,
(statistics.countMessage - statistics.sumRead) pendingMessage
FROM contact
LEFT OUTER JOIN `user` AS user1 ON contact.administrator_id = user1.id_user
LEFT OUTER JOIN `user` AS user2 ON contact.user_id = user2.id_user
INNER JOIN member ON contact.id_contact = member.contact_id
LEFT JOIN (
SELECT user_id, contact_id, max(dateAdd) lastMessage, count(isRead) countMessage, sum(isRead) sumRead
FROM recipients
group by user_id, contact_id) statistics
on (statistics.user_id = member.user_id and statistics.contact_id = contact.id_contact)
-----------------------------------------------------------------------------------------
SELECT
message.id_message,
message.author_id,
message.contact_id,
message.isDelete,
message.dateAdd,
SUBSTRING(message.dateAdd, 1, 10) AS dateCreation,
concat(SUBSTRING(message.dateAdd,1,16), ':00') AS timeCreation,
message.dateDelete,
contents.id_contents,
contents.message_id,
contents.text,
0 AS isAttached,
contents.attachedfiles,
recipients.id_recipients,
recipients.user_id,
recipients.isRead,
recipients.isNotified
FROM message
LEFT OUTER JOIN contents ON message.id_message = contents.message_id
LEFT OUTER JOIN recipients ON message.id_message = recipients.message_id
I hope you like the example, above all, that you are useful and for any questions or what you need, you can contact me through email fernandohumanes@gmail.com.
As always, I leave all the code so that or you can download and install in your Windows and you can make all the changes that your system requires.