Our last step would be implementing image messages support. We will use the same package from the previous step to achieve that.
So we will use the same logic of taking the picture in the controller, and call the same newMessage()
server method:
1
2
3
4
5
6
7
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import Ionic from 'ionic-scripts';
import { _ } from 'meteor/underscore';
import { Meteor } from 'meteor/meteor';
import { MeteorCameraUI } from 'meteor/okland:camera-ui';
import { Controller } from 'angular-ecmascript/module-helpers';
import { Chats, Messages } from '../../../lib/collections';
...some lines skipped...
this.autoScroll();
}
sendPicture() {
MeteorCameraUI.getPicture({}, (err, data) => {
if (err) return this.handleError(err);
this.callMethod('newMessage', {
picture: data,
type: 'picture',
chatId: this.chatId
});
});
}
sendMessage() {
if (_.isEmpty(this.message)) return;
...some lines skipped...
this.$ionicScrollDelegate.$getByHandle('chatScroll').scrollBottom(animate);
}, 300);
}
handleError(err) {
if (err.error == 'cancel') return;
this.$log.error('Profile save error ', err);
this.$ionicPopup.alert({
title: err.reason || 'Save failed',
template: 'Please try again',
okType: 'button-positive button-clear'
});
}
}
ChatCtrl.$name = 'ChatCtrl';
ChatCtrl.$inject = ['$stateParams', '$timeout', '$ionicScrollDelegate', '$ionicPopup', '$log'];
And now we need to register an ng-click
event to the image button on the view:
28
29
30
31
32
33
34
<button ng-click="chat.sendMessage()" class="button button-clear button-positive">Send</button>
</span>
<span ng-if="!chat.message || chat.message.length === 0">
<button ng-click="chat.sendPicture()" class="button button-clear button-icon button-positive icon ion-ios-camera-outline"></button>
<i class="buttons-seperator icon ion-android-more-vertical"></i>
<button class="button button-clear button-icon button-positive icon ion-ios-mic-outline"></button>
</span>
In the server, we need to add a validation scheme for image messages in the newMessage()
method:
1
2
3
4
5
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import { Meteor } from 'meteor/meteor';
import { check } from 'meteor/check';
import { Chats, Messages } from '../lib/collections';
Meteor.methods({
...some lines skipped...
'Must be logged in to send message.');
}
check(message, Match.OneOf(
{
text: String,
type: String,
chatId: String
},
{
picture: String,
type: String,
chatId: String
}
));
message.timestamp = new Date();
message.userId = this.userId;
Our next step would be updating the chat view to support image messages:
6
7
8
9
10
11
12
13
14
15
16
17
<div class="message-list">
<div ng-repeat="message in chat.messages" class="message-wrapper">
<div class="message" ng-class="message.userId === $root.currentUser._id ? 'message-mine' : 'message-other'">
<ng-switch on="message.type">
<div ng-switch-when="text" class="text">{{ message.text }}</div>
<div ng-switch-when="picture" class="picture">
<img ng-src="{{ message.picture }}">
</div>
</ng-switch>
<span class="message-timestamp">{{ message.timestamp | amDateFormat: 'HH:mm' }}</span>
</div>
</div>
Let's add some css
to prevent images from looking silly:
66
67
68
69
70
71
72
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
background-image: url(/message-mine.png)
}
.text {
padding: 5px 7px;
word-wrap: break-word;
...some lines skipped...
}
}
.picture {
padding: 4px 4px 0;
img {
width: 220px;
height: 130px;
border-radius: 6px;
}
}
.message-timestamp {
position: absolute;
bottom: 2px;
We also want to add image icon on the chats list in case when the last message is an image message, so let's add it:
11
12
13
14
15
16
17
18
19
20
href="#/tab/chats/{{ chat._id }}">
<img ng-src="{{ chat | chatPicture }}">
<h2>{{ chat | chatName }}</h2>
<ng-switch on="chat.lastMessage.type">
<p ng-switch-when="text">{{ chat.lastMessage.text }}</p>
<p ng-switch-when="picture">image</p>
</ng-switch>
<span class="last-message-timestamp">{{ chat.lastMessage.timestamp | calendar }}</span>
<i class="icon ion-chevron-right icon-accessory"></i>
<ion-option-button class="button-assertive" ng-click="chats.remove(chat)">