forked from sagi/seepur
DB changes and namings. mainly to start working on the activity and call/sync. Still WIP
This commit is contained in:
parent
42a7f567c8
commit
04d7211de1
16 changed files with 156 additions and 102 deletions
|
@ -76,8 +76,8 @@ class ClientApiController {
|
||||||
}
|
}
|
||||||
const call = await Call.create({
|
const call = await Call.create({
|
||||||
state: 'NEW',
|
state: 'NEW',
|
||||||
user_1: user.id,
|
parent_id: user.id,
|
||||||
user_2: body.connection_id,
|
guest_id: body.connection_id,
|
||||||
child_id: body.child_id
|
child_id: body.child_id
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -49,11 +49,23 @@ class CallSession {
|
||||||
this.callModel = callModel;
|
this.callModel = callModel;
|
||||||
this.hostId = 2;
|
this.hostId = 2;
|
||||||
this.state = callModel.state;
|
this.state = callModel.state;
|
||||||
this.user_1 = {id: callModel.user_1, socket: null, userModel: null};
|
this.sessionState = {page: 'lobby', activity: {type: null, model: null}};
|
||||||
this.user_2 = {id: callModel.user_2, socket: null, userModel: null};
|
this.parent = {
|
||||||
|
id: callModel.parent_id,
|
||||||
|
socket: null,
|
||||||
|
userModel: null,
|
||||||
|
isParent: true
|
||||||
|
};
|
||||||
|
this.guest = {
|
||||||
|
id: callModel.guest_id,
|
||||||
|
socket: null,
|
||||||
|
userModel: null,
|
||||||
|
isParent: false
|
||||||
|
};
|
||||||
this.startTime = Date.now();
|
this.startTime = Date.now();
|
||||||
this.heartbeat =
|
this.heartbeat =
|
||||||
setInterval(this.onHeartbeat.bind(this), 1000); // Every second
|
setInterval(this.onHeartbeat.bind(this), 1000); // Every second
|
||||||
|
this.userMap = new Map(); // Reference to this.parent/guest by userId;
|
||||||
}
|
}
|
||||||
onHeartbeat() {
|
onHeartbeat() {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
|
@ -69,51 +81,50 @@ class CallSession {
|
||||||
return this.endCall();
|
return this.endCall();
|
||||||
}
|
}
|
||||||
removeUser(user) {
|
removeUser(user) {
|
||||||
let userIndex = -1;
|
let userToRemove = this.userMap.get(user.id);
|
||||||
if (this.user_1.id === user.id)
|
userToRemove.userModel = null;
|
||||||
userIndex = 1;
|
userToRemove.socket = null;
|
||||||
else if (this.user_2.id === user.id)
|
this.userMap.delete(user.id);
|
||||||
userIndex = 2;
|
|
||||||
if (userIndex < 0) return false;
|
|
||||||
this[`user_${userIndex}`].userModel = null;
|
|
||||||
this[`user_${userIndex}`].socket = null;
|
|
||||||
this.updateState();
|
this.updateState();
|
||||||
if (this.state === 'ENDED') this.endCall();
|
if (this.state === 'ENDED') this.endCall();
|
||||||
}
|
}
|
||||||
async registerUser(user, socket) {
|
async registerUser(user, socket) {
|
||||||
if (!this.child) this.child = await Child.find(this.callModel.child_id);
|
if (!this.child) this.child = await this.callModel.child().fetch();
|
||||||
let userIndex = -1;
|
let isParent = this.parent.id === user.id;
|
||||||
if (this.user_1.id === user.id)
|
let peerId = isParent ? this.guest.id : this.parent.id;
|
||||||
userIndex = 1;
|
if (isParent) {
|
||||||
else if (this.user_2.id === user.id)
|
this.parent.userModel = user;
|
||||||
userIndex = 2;
|
this.parent.socket = socket;
|
||||||
if (userIndex < 0) return false;
|
this.userMap.set(user.id, this.parent);
|
||||||
const otherUser = userIndex === 1 ? 2 : 1;
|
} else {
|
||||||
this[`user_${userIndex}`].userModel = user;
|
this.guest.userModel = user;
|
||||||
this[`user_${userIndex}`].socket = socket;
|
this.guest.socket = socket;
|
||||||
|
this.userMap.set(user.id, this.guest);
|
||||||
|
peerId = this.parent.id;
|
||||||
|
}
|
||||||
|
|
||||||
socket.on('wrtc:sdp:offer', this.onSdpOffer.bind(this));
|
socket.on('wrtc:sdp:offer', this.onSdpOffer.bind(this));
|
||||||
socket.on('wrtc:sdp:answer', this.onSdpAnswer.bind(this));
|
socket.on('wrtc:sdp:answer', this.onSdpAnswer.bind(this));
|
||||||
socket.on('wrtc:ice', this.onIceCandidate.bind(this));
|
socket.on('wrtc:ice', this.onIceCandidate.bind(this));
|
||||||
socket.on('call:host:changed', this.onHostChanged.bind(this));
|
socket.on('call:host:changed', this.onHostChanged.bind(this));
|
||||||
socket
|
socket.on('book:action:flip-page', this.onActionBookFlip.bind(this));
|
||||||
.on('book:action:flip-page', this.onActionBookFlip.bind(this))
|
|
||||||
await this.updateState();
|
await this.updateState();
|
||||||
if (this.state === 'STARTED') {
|
if (this.state === 'STARTED') {
|
||||||
await this.sendStandby(socket, userIndex);
|
await this.sendStandby(socket, user.id, peerId);
|
||||||
// Send event to other user about the call
|
// Send event to other user about the call
|
||||||
console.log(
|
console.log(`trying to find peer's ${peerId} channel...`);
|
||||||
`trying to find user ${this[`user_${otherUser}`].id} channel...`);
|
const otherUserChannel = UserChannel.getUserChannel(peerId);
|
||||||
const otherUserChannel =
|
|
||||||
UserChannel.getUserChannel(this[`user_${otherUser}`].id);
|
|
||||||
if (otherUserChannel) {
|
if (otherUserChannel) {
|
||||||
// console.log(otherUserChannel);
|
// console.log(otherUserChannel);
|
||||||
console.log('Sending notification to other user');
|
console.log(`Sending notification to peer ${peerId}`);
|
||||||
const payload = {callId: this.callId, child: this.child.toJSON()};
|
const payload = {callId: this.callId, child: this.child.toJSON()};
|
||||||
console.dir(payload);
|
console.dir(payload);
|
||||||
otherUserChannel.emit('call:incoming', payload);
|
otherUserChannel.emit('call:incoming', payload);
|
||||||
}
|
}
|
||||||
} else if (this.state === 'IN_PROGRESS')
|
} else if (this.state === 'IN_PROGRESS') {
|
||||||
await this.sendStart(socket, userIndex);
|
await this.sendStart(socket, user.id, peerId);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
endCall() {
|
endCall() {
|
||||||
|
@ -122,31 +133,34 @@ class CallSession {
|
||||||
this.callModel.state = this.state;
|
this.callModel.state = this.state;
|
||||||
this.callModel.save();
|
this.callModel.save();
|
||||||
}
|
}
|
||||||
if (this.user_1.socket) this.user_1.socket.close();
|
if (this.parent.socket) this.parent.socket.close();
|
||||||
if (this.user_2.socket) this.user_2.socket.close();
|
if (this.guest.socket) this.guest.socket.close();
|
||||||
clearInterval(this.heartbeat);
|
clearInterval(this.heartbeat);
|
||||||
this.onCallEndedCallback(this.callId);
|
this.onCallEndedCallback(this.callId);
|
||||||
}
|
}
|
||||||
|
|
||||||
async sendStandby(socket, userIndex) {
|
async sendStandby(socket, userId, peerId) {
|
||||||
console.log(`Call #${this.callId} sendStandby -> ${userIndex}`);
|
console.log(`Call #${this.callId} sendStandby -> ${userId}`);
|
||||||
const iceServers = (await IceServer.all()).rows.map(i => i.toJSON());
|
const iceServers = (await IceServer.all()).rows.map(i => i.toJSON());
|
||||||
|
console.log(await this.callModel.parent().fetch());
|
||||||
socket.emit('call:standby', {
|
socket.emit('call:standby', {
|
||||||
iceServers,
|
iceServers,
|
||||||
id: userIndex,
|
peerId,
|
||||||
child: this.child.toJSON(),
|
child: this.child.toJSON(),
|
||||||
users: await this.callModel.getUsers(),
|
users: await Promise.all(
|
||||||
|
[this.callModel.parent().fetch(), this.callModel.guest().fetch()]),
|
||||||
hostId: this.hostId
|
hostId: this.hostId
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async sendStart(socket, userIndex) {
|
async sendStart(socket, userId, peerId) {
|
||||||
console.log(`Call #${this.callId} sendStart -> ${userIndex}`);
|
console.log(`Call #${this.callId} sendStart -> ${userId}`);
|
||||||
const iceServers = (await IceServer.all()).rows.map(i => i.toJSON());
|
const iceServers = (await IceServer.all()).rows.map(i => i.toJSON());
|
||||||
socket.emit('call:start', {
|
socket.emit('call:start', {
|
||||||
iceServers,
|
iceServers,
|
||||||
id: userIndex,
|
peerId,
|
||||||
child: this.child.toJSON(),
|
child: this.child.toJSON(),
|
||||||
users: await this.callModel.getUsers(),
|
users: await Promise.all(
|
||||||
|
[this.callModel.parent().fetch(), this.callModel.guest().fetch()]),
|
||||||
hostId: this.hostId
|
hostId: this.hostId
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -171,44 +185,39 @@ class CallSession {
|
||||||
console.log(`Call #${this.callId} state=${this.state}`);
|
console.log(`Call #${this.callId} state=${this.state}`);
|
||||||
}
|
}
|
||||||
areAllPartnersConnected() {
|
areAllPartnersConnected() {
|
||||||
return !!this.user_1.socket && !!this.user_2.socket;
|
return !!this.parent.socket && !!this.guest.socket;
|
||||||
}
|
}
|
||||||
async onIceCandidate(payload) {
|
async onIceCandidate(payload) {
|
||||||
const {from = payload.id, ice} = payload;
|
const {peerId, userId, ice} = payload;
|
||||||
const to = from === 1 ? 2 : 1;
|
this.userMap.get(peerId).socket.emit('wrtc:ice', {ice});
|
||||||
this[`user_${to}`].socket.emit('wrtc:ice', {ice});
|
console.log(`[Signal] [onIceCandidate] ${userId} -> ${peerId}`);
|
||||||
console.log(`[Signal] [onIceCandidate] ${from} -> ${to}`);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
async onSdpOffer(payload) {
|
async onSdpOffer(payload) {
|
||||||
const {from = payload.id, sdp} = payload;
|
const {peerId, userId, sdp} = payload;
|
||||||
const to = from === 1 ? 2 : 1;
|
this.userMap.get(peerId).socket.emit('wrtc:sdp:offer', {sdp});
|
||||||
this[`user_${to}`].socket.emit('wrtc:sdp:offer', {sdp});
|
console.log(`[Signal] [onSdpOffer] ${userId} -> ${peerId}`);
|
||||||
console.log(`[Signal] [onSdpOffer] ${from} -> ${to}`);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async onSdpAnswer(payload) {
|
async onSdpAnswer(payload) {
|
||||||
const {from = payload.id, sdp} = payload;
|
const {peerId, userId, sdp} = payload;
|
||||||
const to = from === 1 ? 2 : 1;
|
this.userMap.get(peerId).socket.emit('wrtc:sdp:answer', {sdp});
|
||||||
this[`user_${to}`].socket.emit('wrtc:sdp:answer', {sdp});
|
console.log(`[Signal] [onSdpAnswer] ${userId} -> ${peerId}`);
|
||||||
console.log(`[Signal] [onSdpAnswer] ${from} -> ${to}`);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
onActionBookFlip(payload) {
|
onActionBookFlip(payload) {
|
||||||
const {from = payload.id, direction} = payload;
|
const {peerId, userId, direction} = payload;
|
||||||
const to = from === 1 ? 2 : 1;
|
this.userMap.get(peerId).socket.emit('book:action:flip-page', {direction});
|
||||||
this[`user_${to}`].socket.emit('book:action:flip-page', {direction});
|
console.log(`[Signal] [book] [action] [flip] [${direction}] ${userId} -> ${
|
||||||
console.log(
|
peerId}`);
|
||||||
`[Signal] [book] [action] [flip] [${direction}] ${from} -> ${to}`);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
async onHostChanged(payload) {
|
async onHostChanged(payload) {
|
||||||
const {from = payload.id, hostId} = payload;
|
const {peerId, hostId} = payload;
|
||||||
const to = from === 1 ? 2 : 1;
|
|
||||||
this.hostId = hostId;
|
this.hostId = hostId;
|
||||||
this[`user_${to}`].socket.emit('call:host:changed', {hostId});
|
this.userMap.get(peerId).socket.emit('call:host:changed', {hostId});
|
||||||
console.log(
|
console.log(
|
||||||
`[Signal] [host] [changed] [hostId=${hostId}] ${from} -> ${to}`);
|
`[Signal] [host] [changed] [hostId=${hostId}] ${from} -> ${to}`);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -20,7 +20,7 @@ class WsCallAuth {
|
||||||
throw new Error('Call not found');
|
throw new Error('Call not found');
|
||||||
}
|
}
|
||||||
if (call.state === 'ENDED') throw new Error('This call has ended');
|
if (call.state === 'ENDED') throw new Error('This call has ended');
|
||||||
if (user.id === call.user_1 || user.id === call.user_2) {
|
if (user.id === call.parent_id || user.id === call.guest_id) {
|
||||||
ctx.call = call;
|
ctx.call = call;
|
||||||
await next()
|
await next()
|
||||||
}
|
}
|
||||||
|
|
20
app/Models/ActivityLog.js
Normal file
20
app/Models/ActivityLog.js
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/** @type {typeof import('@adonisjs/lucid/src/Lucid/Model')} */
|
||||||
|
const Model = use('Model')
|
||||||
|
|
||||||
|
class ActivityLog extends Model {
|
||||||
|
async call() {
|
||||||
|
return this.belongsTo('App/Models/Call');
|
||||||
|
}
|
||||||
|
async resource() {
|
||||||
|
switch (this.type) {
|
||||||
|
case 'BOOK':
|
||||||
|
return this.belongsTo('App/Models/Book');
|
||||||
|
default:
|
||||||
|
throw new Error('Unknown Resource Type');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = ActivityLog
|
|
@ -5,6 +5,7 @@ const Model = use('Model')
|
||||||
|
|
||||||
class Book extends Model {
|
class Book extends Model {
|
||||||
user() {
|
user() {
|
||||||
|
if (!this.user_id) return null;
|
||||||
return this.belongsTo('App/Models/User');
|
return this.belongsTo('App/Models/User');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,13 +5,14 @@ const Model = use('Model')
|
||||||
const User = use('App/Models/User');
|
const User = use('App/Models/User');
|
||||||
|
|
||||||
class Call extends Model {
|
class Call extends Model {
|
||||||
async getUsers() {
|
parent() {
|
||||||
const users = [
|
return this.belongsTo('App/Models/User', 'parent_id');
|
||||||
(await User.find(this.user_1)).toJSON(),
|
}
|
||||||
(await User.find(this.user_2)).toJSON()
|
guest() {
|
||||||
];
|
return this.belongsTo('App/Models/User', 'guest_id');
|
||||||
|
}
|
||||||
return users;
|
child() {
|
||||||
|
return this.belongsTo('App/Models/Child');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,13 +8,13 @@ class CallSchema extends Schema {
|
||||||
this.create('calls', (table) => {
|
this.create('calls', (table) => {
|
||||||
table.increments();
|
table.increments();
|
||||||
table.string('state').notNullable();
|
table.string('state').notNullable();
|
||||||
table.bigInteger('user_1').notNullable();
|
table.bigInteger('parent_id').notNullable();
|
||||||
table.bigInteger('user_2').notNullable();
|
table.bigInteger('guest_id').notNullable();
|
||||||
table.bigInteger('child_id').notNullable();
|
table.bigInteger('child_id').notNullable();
|
||||||
table.timestamps();
|
table.timestamps();
|
||||||
table.index(['child_id']);
|
table.index(['child_id']);
|
||||||
table.index(['user_1']);
|
table.index(['parent_id']);
|
||||||
table.index(['user_2']);
|
table.index(['guest_id']);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,10 @@ class BookSchema extends Schema {
|
||||||
up() {
|
up() {
|
||||||
this.create('books', (table) => {
|
this.create('books', (table) => {
|
||||||
table.increments()
|
table.increments()
|
||||||
table.bigInteger('user_id').notNullable();
|
table.bigInteger('user_id');
|
||||||
table.integer('pages').notNullable();
|
table.integer('pages').notNullable();
|
||||||
table.string('book_folder').notNullable();
|
table.string('book_folder').notNullable();
|
||||||
|
table.boolean('ltr').default(true);
|
||||||
table.timestamps()
|
table.timestamps()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
22
database/migrations/1587931580121_activity_log_schema.js
Normal file
22
database/migrations/1587931580121_activity_log_schema.js
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/** @type {import('@adonisjs/lucid/src/Schema')} */
|
||||||
|
const Schema = use('Schema')
|
||||||
|
|
||||||
|
class ActivityLogSchema extends Schema {
|
||||||
|
up() {
|
||||||
|
this.create('activity_logs', (table) => {
|
||||||
|
table.increments();
|
||||||
|
table.bigInteger('call_id').notNullable();
|
||||||
|
table.string('type', 60).notNullable();
|
||||||
|
table.bigInteger('resource_id').notNullable();
|
||||||
|
table.timestamps(); // created_at = start time, updated_at = end time
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
down() {
|
||||||
|
this.drop('activity_logs');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = ActivityLogSchema
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -10,11 +10,11 @@ export default class CallManager {
|
||||||
private emitter = new EventEmitter();
|
private emitter = new EventEmitter();
|
||||||
private pc: RTCPeerConnection;
|
private pc: RTCPeerConnection;
|
||||||
public child;
|
public child;
|
||||||
public guest = { avatar: '' };
|
public peer = { avatar: '' };
|
||||||
public isHost = false;
|
public isHost = false;
|
||||||
constructor(private ws: WebSocketService, private callId: number, private userId: number) {
|
constructor(private ws: WebSocketService, private callId: number, private userId: number) {
|
||||||
this.inCall = false;
|
this.inCall = false;
|
||||||
this.peerId = -1;
|
this.peerId = null;
|
||||||
this.pc = null;
|
this.pc = null;
|
||||||
this.remoteStream = new MediaStream();
|
this.remoteStream = new MediaStream();
|
||||||
}
|
}
|
||||||
|
@ -55,19 +55,20 @@ export default class CallManager {
|
||||||
}
|
}
|
||||||
private send(event: string, payload: { [key: string]: any }) {
|
private send(event: string, payload: { [key: string]: any }) {
|
||||||
this.signalingChannel.emit(event, {
|
this.signalingChannel.emit(event, {
|
||||||
id: this.peerId,
|
userId: this.userId,
|
||||||
|
peerId: this.peerId,
|
||||||
...payload
|
...payload
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
async onCallStart(payload: { iceServers: RTCIceServer[], id: number, users: any[], child: any, hostId: number }) {
|
async onCallStart(payload: { iceServers: RTCIceServer[], peerId: number, users: any[], child: any, hostId: number }) {
|
||||||
console.log('onCallStart');
|
console.log('onCallStart');
|
||||||
console.log(payload);
|
console.log(payload);
|
||||||
this.peerId = payload.id;
|
this.peerId = payload.peerId;
|
||||||
this.isHost = this.peerId === payload.hostId;
|
this.isHost = this.peerId === payload.hostId;
|
||||||
this.pc = new RTCPeerConnection({ iceServers: payload.iceServers });
|
this.pc = new RTCPeerConnection({ iceServers: payload.iceServers });
|
||||||
this.child = payload.child;
|
this.child = payload.child;
|
||||||
payload.users.forEach(u => {
|
payload.users.forEach(u => {
|
||||||
if (u.id !== this.userId) this.guest = u;
|
if (u.id === this.peerId) this.peer = u;
|
||||||
});
|
});
|
||||||
this.emit(ECallEvents.CALL_HOST_CHANGED, { hostId: payload.hostId });
|
this.emit(ECallEvents.CALL_HOST_CHANGED, { hostId: payload.hostId });
|
||||||
console.log('Created PeerConnection');
|
console.log('Created PeerConnection');
|
||||||
|
@ -83,15 +84,15 @@ export default class CallManager {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async onCallStandby(payload: { iceServers: RTCIceServer[], id: number, users: any[], child: any, hostId: number }) {
|
async onCallStandby(payload: { iceServers: RTCIceServer[], peerId: number, users: any[], child: any, hostId: number }) {
|
||||||
console.log('onCallStandby');
|
console.log('onCallStandby');
|
||||||
console.log(payload);
|
console.log(payload);
|
||||||
this.peerId = payload.id;
|
this.peerId = payload.peerId;
|
||||||
this.isHost = this.peerId === payload.hostId;
|
this.isHost = this.peerId === payload.hostId;
|
||||||
this.pc = new RTCPeerConnection({ iceServers: payload.iceServers });
|
this.pc = new RTCPeerConnection({ iceServers: payload.iceServers });
|
||||||
this.child = payload.child;
|
this.child = payload.child;
|
||||||
payload.users.forEach(u => {
|
payload.users.forEach(u => {
|
||||||
if (u.id !== this.userId) this.guest = u;
|
if (u.id === this.peerId) this.peer = u;
|
||||||
});
|
});
|
||||||
this.emit(ECallEvents.CALL_HOST_CHANGED, { hostId: payload.hostId });
|
this.emit(ECallEvents.CALL_HOST_CHANGED, { hostId: payload.hostId });
|
||||||
console.log('Created PeerConnection');
|
console.log('Created PeerConnection');
|
||||||
|
@ -174,8 +175,7 @@ export default class CallManager {
|
||||||
|
|
||||||
changeHost() {
|
changeHost() {
|
||||||
this.isHost = !this.isHost;
|
this.isHost = !this.isHost;
|
||||||
const guestPeerId = this.peerId === 1 ? 2 : 1;
|
const hostId = this.isHost ? this.userId : this.peerId;
|
||||||
const hostId = this.isHost ? this.peerId : guestPeerId;
|
|
||||||
this.emit(ECallEvents.CALL_HOST_CHANGED, { hostId });
|
this.emit(ECallEvents.CALL_HOST_CHANGED, { hostId });
|
||||||
this.send('call:host:changed', { hostId });
|
this.send('call:host:changed', { hostId });
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
<div class="me">
|
<div class="me">
|
||||||
<figure class="image is-24x24">
|
<figure class="image is-24x24">
|
||||||
<img
|
<img
|
||||||
:src="isHost? user.avatar : callManager.guest.avatar"
|
:src="isHost? user.avatar : callManager.peer.avatar"
|
||||||
class="is-rounded is-avatar"
|
class="is-rounded is-avatar"
|
||||||
@click="changeHost()"
|
@click="changeHost()"
|
||||||
/>
|
/>
|
||||||
|
@ -150,7 +150,7 @@ export default {
|
||||||
onRemoteHostChanged(payload) {
|
onRemoteHostChanged(payload) {
|
||||||
console.log("-----------");
|
console.log("-----------");
|
||||||
console.log(payload);
|
console.log(payload);
|
||||||
this.guest = this.callManager.guest;
|
this.peer = this.callManager.peer;
|
||||||
this.isHost = this.callManager.isHost;
|
this.isHost = this.callManager.isHost;
|
||||||
},
|
},
|
||||||
changeHost() {
|
changeHost() {
|
||||||
|
|
|
@ -44,7 +44,7 @@ Seepur | Our Time together
|
||||||
<p>
|
<p>
|
||||||
With Seepur you can simply choose your grandchild/niece/nephew you wish to connect with, click on your chosen activity for the day, and share a fun experience together.
|
With Seepur you can simply choose your grandchild/niece/nephew you wish to connect with, click on your chosen activity for the day, and share a fun experience together.
|
||||||
</p>
|
</p>
|
||||||
<a href="#" class="button m-t-md">More...</a>
|
{{-- <a href="#" class="button m-t-md">More...</a> --}}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
|
@ -108,7 +108,7 @@ Seepur | Our Time together
|
||||||
Make an actual impact on the child by creating shared memories. You will be surprised how engaged and comunicative a little child could be during active sessions.
|
Make an actual impact on the child by creating shared memories. You will be surprised how engaged and comunicative a little child could be during active sessions.
|
||||||
With the great combination of video calling and your shared view of the book pages, you can make the story come alive by using different voices for different characters, and even acting out parts of the story, as if you’re right there by their side.
|
With the great combination of video calling and your shared view of the book pages, you can make the story come alive by using different voices for different characters, and even acting out parts of the story, as if you’re right there by their side.
|
||||||
</p>
|
</p>
|
||||||
<a href="#" class="button m-t-md">More...</a>
|
{{-- <a href="#" class="button m-t-md">More...</a> --}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
@ -120,7 +120,7 @@ Seepur | Our Time together
|
||||||
<p>
|
<p>
|
||||||
Seepur is all about you and the child. You can upload your own books and read together, create puzzles with your own photos and more!
|
Seepur is all about you and the child. You can upload your own books and read together, create puzzles with your own photos and more!
|
||||||
</p>
|
</p>
|
||||||
<a href="#" class="button m-t-md">More...</a>
|
{{-- <a href="#" class="button m-t-md">More...</a> --}}
|
||||||
</div>
|
</div>
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<figure class="image is-5by4">
|
<figure class="image is-5by4">
|
||||||
|
|
Loading…
Reference in a new issue