[WIP] keep client fresh with junto info globally (#791)
* push state to client * junto status is live on map cards XD * little fixes * eslint stuff * remove object rest spread * i think this makes realtime work without needing babel-node
This commit is contained in:
parent
7a09a1c620
commit
fb427a11f0
20 changed files with 387 additions and 289 deletions
BIN
app/assets/images/junto.gif
Normal file
BIN
app/assets/images/junto.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
|
@ -11,20 +11,26 @@
|
|||
border-radius:2px;
|
||||
margin:16px;
|
||||
box-shadow: 0px 3px 3px rgba(0,0,0,0.23), 0 3px 3px rgba(0,0,0,0.16);
|
||||
}
|
||||
.map.newMap {
|
||||
|
||||
&.newMap {
|
||||
float: left;
|
||||
position: relative;
|
||||
}
|
||||
.map.newMap:hover {
|
||||
|
||||
&:hover {
|
||||
background: #dcdcdc;
|
||||
}
|
||||
.map.newMap a {
|
||||
|
||||
.newMapImage {
|
||||
background-position: 0 -72px;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
height: 340px;
|
||||
display: block;
|
||||
position: relative;
|
||||
}
|
||||
.newMap .newMapImage {
|
||||
}
|
||||
|
||||
.newMapImage {
|
||||
display: block;
|
||||
width: 72px;
|
||||
height: 72px;
|
||||
|
@ -36,36 +42,49 @@
|
|||
margin-left: -36px;
|
||||
top: 50%;
|
||||
margin-top: -36px;
|
||||
}
|
||||
.map:hover .newMapImage {
|
||||
background-position: 0 -72px;
|
||||
}
|
||||
.newMap span {
|
||||
}
|
||||
|
||||
span {
|
||||
font-family: 'din-regular', sans-serif;
|
||||
font-size: 18px;
|
||||
line-height: 22px;
|
||||
text-align: center;
|
||||
display: block;
|
||||
padding-top: 220px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mapCard {
|
||||
.mapCard {
|
||||
position:relative;
|
||||
width:100%;
|
||||
height:308px;
|
||||
padding: 0 0 16px 0;
|
||||
color: #424242;
|
||||
|
||||
.mapScreenshot {
|
||||
.mapHasMapper, .mapHasConversation {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
left: 5px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
.mapHasMapper {
|
||||
background: url('<%= asset_path('junto.png') %>');
|
||||
}
|
||||
.mapHasConversation {
|
||||
background: url('<%= asset_path('junto.gif') %>');
|
||||
}
|
||||
|
||||
.mapScreenshot {
|
||||
width: 100%;
|
||||
height: 220px;
|
||||
}
|
||||
}
|
||||
|
||||
.mapScreenshot img {
|
||||
.mapScreenshot img {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
.title {
|
||||
word-wrap: break-word;
|
||||
font-size:18px;
|
||||
line-height:22px;
|
||||
|
@ -80,43 +99,43 @@
|
|||
vertical-align: middle;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.creatorAndPerm {
|
||||
.creatorAndPerm {
|
||||
padding: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.creatorImage {
|
||||
.creatorImage {
|
||||
display: inline-block;
|
||||
border-radius: 16px;
|
||||
vertical-align: middle;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
span.creatorName {
|
||||
span.creatorName {
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.scroll {
|
||||
.scroll {
|
||||
display:block;
|
||||
font-family: helvetica, sans-serif;
|
||||
font-size: 12px;
|
||||
word-wrap: break-word;
|
||||
text-align: center;
|
||||
margin-top: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover .mainContent {
|
||||
&:hover .mainContent {
|
||||
filter: blur(2px);
|
||||
}
|
||||
}
|
||||
|
||||
&:hover .mapMetadata {
|
||||
&:hover .mapMetadata {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.mapMetadata {
|
||||
.mapMetadata {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
|
@ -130,15 +149,15 @@ span.creatorName {
|
|||
background: -webkit-linear-gradient(top, rgba(0,0,0,0.65) 0%,rgba(0,0,0,0.43) 81%,rgba(0,0,0,0) 100%);
|
||||
background: linear-gradient(to bottom, rgba(0,0,0,0.65) 0%,rgba(0,0,0,0.43) 81%,rgba(0,0,0,0) 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#a6000000', endColorstr='#00000000',GradientType=0 );
|
||||
}
|
||||
}
|
||||
|
||||
.metadataSection {
|
||||
.metadataSection {
|
||||
padding: 16px 0;
|
||||
width: 90px;
|
||||
float: left;
|
||||
font-family: 'din-medium', sans-serif;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,54 +1,53 @@
|
|||
/* EVENTS SENDABLE */
|
||||
export const REQUEST_LIVE_MAPS = 'REQUEST_LIVE_MAPS'
|
||||
export const JOIN_MAP = 'JOIN_MAP'
|
||||
export const LEAVE_MAP = 'LEAVE_MAP'
|
||||
export const CHECK_FOR_CALL = 'CHECK_FOR_CALL'
|
||||
export const ACCEPT_CALL = 'ACCEPT_CALL'
|
||||
export const DENY_CALL = 'DENY_CALL'
|
||||
export const DENY_INVITE = 'DENY_INVITE'
|
||||
export const INVITE_TO_JOIN = 'INVITE_TO_JOIN'
|
||||
export const INVITE_A_CALL = 'INVITE_A_CALL'
|
||||
export const JOIN_CALL = 'JOIN_CALL'
|
||||
export const LEAVE_CALL = 'LEAVE_CALL'
|
||||
export const SEND_MAPPER_INFO = 'SEND_MAPPER_INFO'
|
||||
export const SEND_COORDS = 'SEND_COORDS'
|
||||
export const CREATE_MESSAGE = 'CREATE_MESSAGE'
|
||||
export const DRAG_TOPIC = 'DRAG_TOPIC'
|
||||
export const CREATE_TOPIC = 'CREATE_TOPIC'
|
||||
export const UPDATE_TOPIC = 'UPDATE_TOPIC'
|
||||
export const REMOVE_TOPIC = 'REMOVE_TOPIC'
|
||||
export const DELETE_TOPIC = 'DELETE_TOPIC'
|
||||
export const CREATE_SYNAPSE = 'CREATE_SYNAPSE'
|
||||
export const UPDATE_SYNAPSE = 'UPDATE_SYNAPSE'
|
||||
export const REMOVE_SYNAPSE = 'REMOVE_SYNAPSE'
|
||||
export const DELETE_SYNAPSE = 'DELETE_SYNAPSE'
|
||||
export const UPDATE_MAP = 'UPDATE_MAP'
|
||||
module.exports = {
|
||||
JOIN_MAP: 'JOIN_MAP',
|
||||
CHECK_FOR_CALL: 'CHECK_FOR_CALL',
|
||||
LEAVE_MAP: 'LEAVE_MAP',
|
||||
ACCEPT_CALL: 'ACCEPT_CALL',
|
||||
DENY_CALL: 'DENY_CALL',
|
||||
DENY_INVITE: 'DENY_INVITE',
|
||||
INVITE_TO_JOIN: 'INVITE_TO_JOIN',
|
||||
INVITE_A_CALL: 'INVITE_A_CALL',
|
||||
JOIN_CALL: 'JOIN_CALL',
|
||||
LEAVE_CALL: 'LEAVE_CALL',
|
||||
SEND_MAPPER_INFO: 'SEND_MAPPER_INFO',
|
||||
SEND_COORDS: 'SEND_COORDS',
|
||||
CREATE_MESSAGE: 'CREATE_MESSAGE',
|
||||
DRAG_TOPIC: 'DRAG_TOPIC',
|
||||
CREATE_TOPIC: 'CREATE_TOPIC',
|
||||
UPDATE_TOPIC: 'UPDATE_TOPIC',
|
||||
REMOVE_TOPIC: 'REMOVE_TOPIC',
|
||||
DELETE_TOPIC: 'DELETE_TOPIC',
|
||||
CREATE_SYNAPSE: 'CREATE_SYNAPSE',
|
||||
UPDATE_SYNAPSE: 'UPDATE_SYNAPSE',
|
||||
REMOVE_SYNAPSE: 'REMOVE_SYNAPSE',
|
||||
DELETE_SYNAPSE: 'DELETE_SYNAPSE',
|
||||
UPDATE_MAP: 'UPDATE_MAP',
|
||||
|
||||
/* EVENTS RECEIVABLE */
|
||||
export const INVITED_TO_CALL = 'INVITED_TO_CALL'
|
||||
export const INVITED_TO_JOIN = 'INVITED_TO_JOIN'
|
||||
export const CALL_ACCEPTED = 'CALL_ACCEPTED'
|
||||
export const CALL_DENIED = 'CALL_DENIED'
|
||||
export const INVITE_DENIED = 'INVITE_DENIED'
|
||||
export const CALL_IN_PROGRESS = 'CALL_IN_PROGRESS'
|
||||
export const CALL_STARTED = 'CALL_STARTED'
|
||||
export const MAPPER_JOINED_CALL = 'MAPPER_JOINED_CALL'
|
||||
export const MAPPER_LEFT_CALL = 'MAPPER_LEFT_CALL'
|
||||
export const MAPPER_LIST_UPDATED = 'MAPPER_LIST_UPDATED'
|
||||
export const NEW_MAPPER = 'NEW_MAPPER'
|
||||
export const LOST_MAPPER = 'LOST_MAPPER'
|
||||
export const MESSAGE_CREATED = 'MESSAGE_CREATED'
|
||||
export const TOPIC_DRAGGED = 'TOPIC_DRAGGED'
|
||||
export const TOPIC_CREATED = 'TOPIC_CREATED'
|
||||
export const TOPIC_UPDATED = 'TOPIC_UPDATED'
|
||||
export const TOPIC_REMOVED = 'TOPIC_REMOVED'
|
||||
export const TOPIC_DELETED = 'TOPIC_DELETED'
|
||||
export const SYNAPSE_CREATED = 'SYNAPSE_CREATED'
|
||||
export const SYNAPSE_UPDATED = 'SYNAPSE_UPDATED'
|
||||
export const SYNAPSE_REMOVED = 'SYNAPSE_REMOVED'
|
||||
export const SYNAPSE_DELETED = 'SYNAPSE_DELETED'
|
||||
export const PEER_COORDS_UPDATED = 'PEER_COORDS_UPDATED'
|
||||
export const MAP_UPDATED = 'MAP_UPDATED'
|
||||
export const LIVE_MAPS_RECEIVED = 'LIVE_MAPS_RECEIVED'
|
||||
export const MAP_WENT_LIVE = 'MAP_WENT_LIVE'
|
||||
export const MAP_CEASED_LIVE = 'MAP_CEASED_LIVE'
|
||||
/* EVENTS RECEIVABLE */
|
||||
JUNTO_UPDATED: 'JUNTO_UPDATED',
|
||||
INVITED_TO_CALL: 'INVITED_TO_CALL',
|
||||
INVITED_TO_JOIN: 'INVITED_TO_JOIN',
|
||||
CALL_ACCEPTED: 'CALL_ACCEPTED',
|
||||
CALL_DENIED: 'CALL_DENIED',
|
||||
INVITE_DENIED: 'INVITE_DENIED',
|
||||
CALL_IN_PROGRESS: 'CALL_IN_PROGRESS',
|
||||
CALL_STARTED: 'CALL_STARTED',
|
||||
MAPPER_JOINED_CALL: 'MAPPER_JOINED_CALL',
|
||||
MAPPER_LEFT_CALL: 'MAPPER_LEFT_CALL',
|
||||
MAPPER_LIST_UPDATED: 'MAPPER_LIST_UPDATED',
|
||||
NEW_MAPPER: 'NEW_MAPPER',
|
||||
LOST_MAPPER: 'LOST_MAPPER',
|
||||
MESSAGE_CREATED: 'MESSAGE_CREATED',
|
||||
TOPIC_DRAGGED: 'TOPIC_DRAGGED',
|
||||
TOPIC_CREATED: 'TOPIC_CREATED',
|
||||
TOPIC_UPDATED: 'TOPIC_UPDATED',
|
||||
TOPIC_REMOVED: 'TOPIC_REMOVED',
|
||||
TOPIC_DELETED: 'TOPIC_DELETED',
|
||||
SYNAPSE_CREATED: 'SYNAPSE_CREATED',
|
||||
SYNAPSE_UPDATED: 'SYNAPSE_UPDATED',
|
||||
SYNAPSE_REMOVED: 'SYNAPSE_REMOVED',
|
||||
SYNAPSE_DELETED: 'SYNAPSE_DELETED',
|
||||
PEER_COORDS_UPDATED: 'PEER_COORDS_UPDATED',
|
||||
MAP_UPDATED: 'MAP_UPDATED'
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ import Views from '../Views'
|
|||
import Visualize from '../Visualize'
|
||||
|
||||
import {
|
||||
JUNTO_UPDATED,
|
||||
INVITED_TO_CALL,
|
||||
INVITED_TO_JOIN,
|
||||
CALL_ACCEPTED,
|
||||
|
@ -34,9 +35,9 @@ import {
|
|||
INVITE_DENIED,
|
||||
CALL_IN_PROGRESS,
|
||||
CALL_STARTED,
|
||||
MAPPER_LIST_UPDATED,
|
||||
MAPPER_JOINED_CALL,
|
||||
MAPPER_LEFT_CALL,
|
||||
MAPPER_LIST_UPDATED,
|
||||
NEW_MAPPER,
|
||||
LOST_MAPPER,
|
||||
MESSAGE_CREATED,
|
||||
|
@ -50,13 +51,11 @@ import {
|
|||
SYNAPSE_REMOVED,
|
||||
SYNAPSE_DELETED,
|
||||
PEER_COORDS_UPDATED,
|
||||
LIVE_MAPS_RECEIVED,
|
||||
MAP_WENT_LIVE,
|
||||
MAP_CEASED_LIVE,
|
||||
MAP_UPDATED
|
||||
} from './events'
|
||||
|
||||
import {
|
||||
juntoUpdated,
|
||||
invitedToCall,
|
||||
invitedToJoin,
|
||||
callAccepted,
|
||||
|
@ -64,9 +63,9 @@ import {
|
|||
inviteDenied,
|
||||
callInProgress,
|
||||
callStarted,
|
||||
mapperListUpdated,
|
||||
mapperJoinedCall,
|
||||
mapperLeftCall,
|
||||
mapperListUpdated,
|
||||
peerCoordsUpdated,
|
||||
newMapper,
|
||||
lostMapper,
|
||||
|
@ -81,13 +80,9 @@ import {
|
|||
synapseRemoved,
|
||||
synapseDeleted,
|
||||
mapUpdated,
|
||||
liveMapsReceived,
|
||||
mapWentLive,
|
||||
mapCeasedLive
|
||||
} from './receivable'
|
||||
|
||||
import {
|
||||
requestLiveMaps,
|
||||
joinMap,
|
||||
leaveMap,
|
||||
checkForCall,
|
||||
|
@ -98,8 +93,8 @@ import {
|
|||
inviteACall,
|
||||
joinCall,
|
||||
leaveCall,
|
||||
sendMapperInfo,
|
||||
sendCoords,
|
||||
sendMapperInfo,
|
||||
createMessage,
|
||||
dragTopic,
|
||||
createTopic,
|
||||
|
@ -114,6 +109,7 @@ import {
|
|||
} from './sendable'
|
||||
|
||||
let Realtime = {
|
||||
juntoState: { connectedPeople: {}, liveMaps: {} },
|
||||
videoId: 'video-wrapper',
|
||||
socket: null,
|
||||
webrtc: null,
|
||||
|
@ -499,12 +495,11 @@ let Realtime = {
|
|||
}
|
||||
|
||||
const sendables = [
|
||||
['requestLiveMaps',requestLiveMaps],
|
||||
['joinMap',joinMap],
|
||||
['leaveMap',leaveMap],
|
||||
['checkForCall',checkForCall],
|
||||
['acceptCall',acceptCall],
|
||||
['denyAll',denyCall],
|
||||
['denyCall',denyCall],
|
||||
['denyInvite',denyInvite],
|
||||
['inviteToJoin',inviteToJoin],
|
||||
['inviteACall',inviteACall],
|
||||
|
@ -529,6 +524,7 @@ sendables.forEach(sendable => {
|
|||
})
|
||||
|
||||
const subscribeToEvents = (Realtime, socket) => {
|
||||
socket.on(JUNTO_UPDATED, juntoUpdated(Realtime))
|
||||
socket.on(INVITED_TO_CALL, invitedToCall(Realtime))
|
||||
socket.on(INVITED_TO_JOIN, invitedToJoin(Realtime))
|
||||
socket.on(CALL_ACCEPTED, callAccepted(Realtime))
|
||||
|
@ -536,9 +532,9 @@ const subscribeToEvents = (Realtime, socket) => {
|
|||
socket.on(INVITE_DENIED, inviteDenied(Realtime))
|
||||
socket.on(CALL_IN_PROGRESS, callInProgress(Realtime))
|
||||
socket.on(CALL_STARTED, callStarted(Realtime))
|
||||
socket.on(MAPPER_LIST_UPDATED, mapperListUpdated(Realtime))
|
||||
socket.on(MAPPER_JOINED_CALL, mapperJoinedCall(Realtime))
|
||||
socket.on(MAPPER_LEFT_CALL, mapperLeftCall(Realtime))
|
||||
socket.on(MAPPER_LIST_UPDATED, mapperListUpdated(Realtime))
|
||||
socket.on(PEER_COORDS_UPDATED, peerCoordsUpdated(Realtime))
|
||||
socket.on(NEW_MAPPER, newMapper(Realtime))
|
||||
socket.on(LOST_MAPPER, lostMapper(Realtime))
|
||||
|
@ -553,9 +549,6 @@ const subscribeToEvents = (Realtime, socket) => {
|
|||
socket.on(SYNAPSE_REMOVED, synapseRemoved(Realtime))
|
||||
socket.on(SYNAPSE_DELETED, synapseDeleted(Realtime))
|
||||
socket.on(MAP_UPDATED, mapUpdated(Realtime))
|
||||
socket.on(LIVE_MAPS_RECEIVED, liveMapsReceived(Realtime))
|
||||
socket.on(MAP_WENT_LIVE, mapWentLive(Realtime))
|
||||
socket.on(MAP_CEASED_LIVE, mapCeasedLive(Realtime))
|
||||
}
|
||||
|
||||
export default Realtime
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
/* global $ */
|
||||
|
||||
/*
|
||||
everthing in this file happens as a result of websocket events
|
||||
*/
|
||||
|
||||
import { JUNTO_UPDATED } from './events'
|
||||
|
||||
import Active from '../Active'
|
||||
import GlobalUI from '../GlobalUI'
|
||||
import Control from '../Control'
|
||||
|
@ -12,6 +16,11 @@ import Synapse from '../Synapse'
|
|||
import Util from '../Util'
|
||||
import Visualize from '../Visualize'
|
||||
|
||||
export const juntoUpdated = self => state => {
|
||||
self.juntoState = state
|
||||
$(document).trigger(JUNTO_UPDATED)
|
||||
}
|
||||
|
||||
export const synapseRemoved = self => data => {
|
||||
var synapse = Metamaps.Synapses.get(data.mappableid)
|
||||
if (synapse) {
|
||||
|
@ -239,13 +248,13 @@ export const lostMapper = self => data => {
|
|||
export const mapperListUpdated = self => data => {
|
||||
// data.userid
|
||||
// data.username
|
||||
// data.userimage
|
||||
// data.avatar
|
||||
|
||||
self.mappersOnMap[data.userid] = {
|
||||
id: data.userid,
|
||||
name: data.username,
|
||||
username: data.username,
|
||||
image: data.userimage,
|
||||
image: data.avatar,
|
||||
color: Util.getPastelColor(),
|
||||
inConversation: data.userinconversation,
|
||||
coords: {
|
||||
|
@ -259,14 +268,14 @@ export const mapperListUpdated = self => data => {
|
|||
if (data.userinconversation) self.room.chat.mapperJoinedCall(data.userid)
|
||||
|
||||
// create a div for the collaborators compass
|
||||
self.createCompass(data.username, data.userid, data.userimage, self.mappersOnMap[data.userid].color)
|
||||
self.createCompass(data.username, data.userid, data.avatar, self.mappersOnMap[data.userid].color)
|
||||
}
|
||||
}
|
||||
|
||||
export const newMapper = self => data => {
|
||||
// data.userid
|
||||
// data.username
|
||||
// data.userimage
|
||||
// data.avatar
|
||||
// data.coords
|
||||
var firstOtherPerson = Object.keys(self.mappersOnMap).length === 0
|
||||
|
||||
|
@ -274,13 +283,12 @@ export const newMapper = self => data => {
|
|||
id: data.userid,
|
||||
name: data.username,
|
||||
username: data.username,
|
||||
image: data.userimage,
|
||||
image: data.avatar,
|
||||
color: Util.getPastelColor(),
|
||||
realtime: true,
|
||||
coords: {
|
||||
x: 0,
|
||||
y: 0
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// create an item for them in the realtime box
|
||||
|
@ -289,7 +297,7 @@ export const newMapper = self => data => {
|
|||
self.room.chat.addParticipant(self.mappersOnMap[data.userid])
|
||||
|
||||
// create a div for the collaborators compass
|
||||
self.createCompass(data.username, data.userid, data.userimage, self.mappersOnMap[data.userid].color)
|
||||
self.createCompass(data.username, data.userid, data.avatar, self.mappersOnMap[data.userid].color)
|
||||
|
||||
var notifyMessage = data.username + ' just joined the map'
|
||||
if (firstOtherPerson) {
|
||||
|
@ -324,7 +332,7 @@ export const invitedToCall = self => inviter => {
|
|||
self.soundId = self.room.chat.sound.play('sessioninvite')
|
||||
|
||||
var username = self.mappersOnMap[inviter].name
|
||||
var notifyText = '<img src="' + Metamaps.Erb['junto_spinner_darkgrey.gif'] + '" style="display: inline-block; margin-top: -12px; vertical-align: top;" />'
|
||||
var notifyText = '<img src="' + Metamaps.Erb['junto_spinner_darkgrey.gif'] + '" style="display: inline-block; margin-top: -12px; margin-bottom: -6px; vertical-align: top;" />'
|
||||
notifyText += username + ' is inviting you to a conversation. Join live?'
|
||||
notifyText += ' <button type="button" class="toast-button button" onclick="Metamaps.Realtime.acceptCall(' + inviter + ')">Yes</button>'
|
||||
notifyText += ' <button type="button" class="toast-button button btn-no" onclick="Metamaps.Realtime.denyCall(' + inviter + ')">No</button>'
|
||||
|
@ -391,6 +399,3 @@ export const callStarted = self => () => {
|
|||
self.room.conversationInProgress()
|
||||
}
|
||||
|
||||
export const liveMapsReceived = self => () => {}
|
||||
export const mapWentLive = self => () => {}
|
||||
export const mapCeasedLive = self => () => {}
|
||||
|
|
|
@ -2,7 +2,6 @@ import Active from '../Active'
|
|||
import GlobalUI from '../GlobalUI'
|
||||
|
||||
import {
|
||||
REQUEST_LIVE_MAPS,
|
||||
JOIN_MAP,
|
||||
LEAVE_MAP,
|
||||
CHECK_FOR_CALL,
|
||||
|
@ -28,15 +27,11 @@ import {
|
|||
UPDATE_MAP
|
||||
} from './events'
|
||||
|
||||
export const requestLiveMaps = self => () => {
|
||||
self.socket.emit(REQUEST_LIVE_MAPS)
|
||||
}
|
||||
|
||||
export const joinMap = self => () => {
|
||||
self.socket.emit(JOIN_MAP, {
|
||||
userid: Active.Mapper.id,
|
||||
username: Active.Mapper.get('name'),
|
||||
userimage: Active.Mapper.get('image'),
|
||||
avatar: Active.Mapper.get('image'),
|
||||
mapid: Active.Map.id,
|
||||
map: Active.Map.attributes
|
||||
})
|
||||
|
@ -55,7 +50,7 @@ export const sendMapperInfo = self => userid => {
|
|||
var update = {
|
||||
userToNotify: userid,
|
||||
username: Active.Mapper.get('name'),
|
||||
userimage: Active.Mapper.get('image'),
|
||||
avatar: Active.Mapper.get('image'),
|
||||
userid: Active.Mapper.id,
|
||||
userinconversation: self.inConversation,
|
||||
mapid: Active.Map.id
|
||||
|
|
|
@ -159,7 +159,7 @@ var Private = {
|
|||
var date = (m.timestamp.getMonth() + 1) + '/' + m.timestamp.getDate()
|
||||
date += ' ' + addZero(m.timestamp.getHours()) + ':' + addZero(m.timestamp.getMinutes())
|
||||
m.timestamp = date
|
||||
m.image = m.user_image || 'http://www.hotpepper.ca/wp-content/uploads/2014/11/default_profile_1_200x200.png' // TODO: remove
|
||||
m.image = m.user_image
|
||||
m.message = linker.link(m.message)
|
||||
var $html = $(this.messageTemplate(m))
|
||||
this.$messages.append($html)
|
||||
|
|
|
@ -4,6 +4,7 @@ import React from 'react'
|
|||
import ReactDOM from 'react-dom' // TODO ensure this isn't a double import
|
||||
|
||||
import Active from '../Active'
|
||||
import Realtime from '../Realtime'
|
||||
import Maps from '../../components/Maps'
|
||||
|
||||
/*
|
||||
|
@ -27,6 +28,8 @@ const ExploreMaps = {
|
|||
render: function (mapperObj, cb) {
|
||||
var self = ExploreMaps
|
||||
|
||||
if (!self.collection) return
|
||||
|
||||
if (typeof mapperObj === 'function') {
|
||||
cb = mapperObj
|
||||
mapperObj = null
|
||||
|
@ -36,6 +39,7 @@ const ExploreMaps = {
|
|||
currentUser: Active.Mapper,
|
||||
section: self.collection.id,
|
||||
maps: self.collection,
|
||||
juntoState: Realtime.juntoState,
|
||||
moreToLoad: self.collection.page != 'loadedAll',
|
||||
user: mapperObj,
|
||||
loadMore: self.loadMore
|
||||
|
|
|
@ -1,7 +1,18 @@
|
|||
/* global $ */
|
||||
|
||||
import ExploreMaps from './ExploreMaps'
|
||||
import ChatView from './ChatView'
|
||||
import VideoView from './VideoView'
|
||||
import Room from './Room'
|
||||
import { JUNTO_UPDATED } from '../Realtime/events'
|
||||
|
||||
const Views = { ExploreMaps, ChatView, VideoView, Room }
|
||||
const Views = {
|
||||
init: () => {
|
||||
$(document).on(JUNTO_UPDATED, () => ExploreMaps.render())
|
||||
},
|
||||
ExploreMaps,
|
||||
ChatView,
|
||||
VideoView,
|
||||
Room
|
||||
}
|
||||
export default Views
|
||||
|
|
|
@ -88,7 +88,7 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||
if (Metamaps.currentSection === 'explore') {
|
||||
const capitalize = Metamaps.currentPage.charAt(0).toUpperCase() + Metamaps.currentPage.slice(1)
|
||||
|
||||
Metamaps.Views.ExploreMaps.setCollection(Metamaps.Maps[capitalize])
|
||||
Views.ExploreMaps.setCollection(Metamaps.Maps[capitalize])
|
||||
if (Metamaps.currentPage === 'mapper') {
|
||||
Views.ExploreMaps.fetchUserThenRender()
|
||||
} else {
|
||||
|
|
|
@ -1,8 +1,19 @@
|
|||
import React, { Component, PropTypes } from 'react'
|
||||
import { find, values } from 'lodash'
|
||||
|
||||
const IN_CONVERSATION = 1 // shared with /realtime/reducer.js
|
||||
|
||||
const MapperList = (props) => {
|
||||
|
||||
}
|
||||
|
||||
class MapCard extends Component {
|
||||
render = () => {
|
||||
const { map, currentUser } = this.props
|
||||
const { map, juntoState, currentUser } = this.props
|
||||
|
||||
const hasMap = juntoState.liveMaps[map.id]
|
||||
const hasConversation = hasMap && find(values(hasMap), v => v === IN_CONVERSATION)
|
||||
const hasMapper = hasMap && !hasConversation
|
||||
|
||||
function capitalize (string) {
|
||||
return string.charAt(0).toUpperCase() + string.slice(1)
|
||||
|
@ -59,6 +70,8 @@ class MapCard extends Component {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{ hasMapper && <div className='mapHasMapper'></div> }
|
||||
{ hasConversation && <div className='mapHasConversation'></div> }
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
@ -69,6 +82,7 @@ class MapCard extends Component {
|
|||
|
||||
MapCard.propTypes = {
|
||||
map: PropTypes.object.isRequired,
|
||||
juntoState: PropTypes.object,
|
||||
currentUser: PropTypes.object
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ class Maps extends Component {
|
|||
}
|
||||
|
||||
render = () => {
|
||||
const { maps, currentUser, section, user, moreToLoad, loadMore } = this.props
|
||||
const { maps, currentUser, juntoState, section, user, moreToLoad, loadMore } = this.props
|
||||
const style = { width: this.state.mapsWidth + 'px' }
|
||||
|
||||
return (
|
||||
|
@ -50,7 +50,7 @@ class Maps extends Component {
|
|||
<div style={ style }>
|
||||
{ user ? <MapperCard user={ user } /> : null }
|
||||
{ currentUser && !user ? <div className="map newMap"><a href="/maps/new"><div className="newMapImage"></div><span>Create new map...</span></a></div> : null }
|
||||
{ maps.models.map(map => <MapCard key={ map.id } map={ map } currentUser={ currentUser } />) }
|
||||
{ maps.models.map(map => <MapCard key={ map.id } map={ map } juntoState={ juntoState } currentUser={ currentUser } />) }
|
||||
<div className='clearfloat'></div>
|
||||
{!moreToLoad ? null : [
|
||||
<button className="button loadMore" onClick={ loadMore }>load more</button>,
|
||||
|
@ -70,6 +70,7 @@ class Maps extends Component {
|
|||
Maps.propTypes = {
|
||||
section: PropTypes.string.isRequired,
|
||||
maps: PropTypes.object.isRequired,
|
||||
juntoState: PropTypes.object.isRequired,
|
||||
moreToLoad: PropTypes.bool.isRequired,
|
||||
user: PropTypes.object,
|
||||
currentUser: PropTypes.object,
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
"react": "15.3.2",
|
||||
"react-dom": "15.3.2",
|
||||
"react-dropzone": "3.6.0",
|
||||
"redux": "^3.6.0",
|
||||
"simplewebrtc": "2.2.0",
|
||||
"socket.io": "1.3.7",
|
||||
"underscore": "1.4.4",
|
||||
|
|
|
@ -1,17 +1,15 @@
|
|||
|
||||
import {
|
||||
const {
|
||||
// server sendable, client receivable
|
||||
TOPIC_UPDATED,
|
||||
TOPIC_DELETED,
|
||||
SYNAPSE_UPDATED,
|
||||
SYNAPSE_DELETED,
|
||||
LIVE_MAPS_RECEIVED,
|
||||
MAP_WENT_LIVE,
|
||||
MAP_CEASED_LIVE,
|
||||
MAP_UPDATED,
|
||||
JUNTO_UPDATED,
|
||||
|
||||
// server receivable, client sendable
|
||||
REQUEST_LIVE_MAPS,
|
||||
JOIN_CALL,
|
||||
LEAVE_CALL,
|
||||
JOIN_MAP,
|
||||
LEAVE_MAP,
|
||||
UPDATE_TOPIC,
|
||||
|
@ -19,43 +17,23 @@ import {
|
|||
UPDATE_SYNAPSE,
|
||||
DELETE_SYNAPSE,
|
||||
UPDATE_MAP
|
||||
} from '../frontend/src/Metamaps/Realtime/events'
|
||||
} = require('../frontend/src/Metamaps/Realtime/events')
|
||||
|
||||
const adjustAndBroadcast = (io, socket, state, event, data) => {
|
||||
if (event === JOIN_MAP) {
|
||||
if (!state.liveMaps[data.mapid]) {
|
||||
state.liveMaps[data.mapid] = data.map // { name: '', desc: '', numTopics: '' }
|
||||
state.liveMaps[data.mapid].mapper_count = 1
|
||||
io.sockets.emit(MAP_WENT_LIVE, state.liveMaps[data.mapid])
|
||||
}
|
||||
else {
|
||||
state.liveMaps[data.mapid].mapper_count++
|
||||
}
|
||||
}
|
||||
else if (event === LEAVE_MAP) {
|
||||
const mapid = socket.mapid
|
||||
if (state.liveMaps[mapid] && state.liveMaps[mapid].mapper_count == 1) {
|
||||
delete state.liveMaps[mapid]
|
||||
io.sockets.emit(MAP_CEASED_LIVE, { id: mapid })
|
||||
}
|
||||
else if (state.liveMaps[mapid]) {
|
||||
state.liveMaps[mapid].mapper_count--
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = function (io, state) {
|
||||
io.on('connection', function (socket) {
|
||||
|
||||
socket.on(REQUEST_LIVE_MAPS, function (activeUser) {
|
||||
//constrain response to maps visible to user
|
||||
var maps = Object.keys(state.liveMaps).map(function(key) { return state.liveMaps[key] })
|
||||
socket.emit(LIVE_MAPS_RECEIVED, maps)
|
||||
module.exports = function (io, store) {
|
||||
store.subscribe(() => {
|
||||
console.log(store.getState())
|
||||
io.sockets.emit(JUNTO_UPDATED, store.getState())
|
||||
})
|
||||
|
||||
socket.on(JOIN_MAP, data => adjustAndBroadcast(io, socket, state, JOIN_MAP, data))
|
||||
socket.on(LEAVE_MAP, () => adjustAndBroadcast(io, socket, state, LEAVE_MAP))
|
||||
socket.on('disconnect', () => adjustAndBroadcast(io, socket, state, LEAVE_MAP))
|
||||
io.on('connection', function (socket) {
|
||||
|
||||
io.sockets.emit(JUNTO_UPDATED, store.getState())
|
||||
|
||||
socket.on(JOIN_MAP, data => store.dispatch({ type: JOIN_MAP, payload: data }))
|
||||
socket.on(LEAVE_MAP, () => store.dispatch({ type: LEAVE_MAP, payload: socket }))
|
||||
socket.on(JOIN_CALL, data => store.dispatch({ type: JOIN_CALL, payload: data }))
|
||||
socket.on(LEAVE_CALL, () => store.dispatch({ type: LEAVE_CALL, payload: socket }))
|
||||
socket.on('disconnect', () => store.dispatch({ type: 'DISCONNECT', payload: socket }))
|
||||
|
||||
socket.on(UPDATE_TOPIC, function (data) {
|
||||
socket.broadcast.emit(TOPIC_UPDATED, data)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {
|
||||
const {
|
||||
INVITED_TO_CALL,
|
||||
INVITED_TO_JOIN,
|
||||
CALL_ACCEPTED,
|
||||
|
@ -17,11 +17,11 @@ import {
|
|||
INVITE_A_CALL,
|
||||
JOIN_CALL,
|
||||
LEAVE_CALL
|
||||
} from '../frontend/src/Metamaps/Realtime/events'
|
||||
} = require('../frontend/src/Metamaps/Realtime/events')
|
||||
|
||||
const { mapRoom, userMapRoom } = require('./rooms')
|
||||
|
||||
module.exports = function (io, state) {
|
||||
module.exports = function (io, store) {
|
||||
io.on('connection', function (socket) {
|
||||
|
||||
socket.on(CHECK_FOR_CALL, function (data) {
|
||||
|
@ -39,6 +39,8 @@ module.exports = function (io, state) {
|
|||
|
||||
socket.on(ACCEPT_CALL, function (data) {
|
||||
socket.broadcast.in(userMapRoom(data.inviter, data.mapid)).emit(CALL_ACCEPTED, data.invited)
|
||||
// convert this so that it broadcasts to all sockets and includes the map id
|
||||
// and who's participating
|
||||
socket.broadcast.in(mapRoom(data.mapid)).emit(CALL_STARTED)
|
||||
})
|
||||
|
||||
|
@ -51,12 +53,15 @@ module.exports = function (io, state) {
|
|||
})
|
||||
|
||||
socket.on(JOIN_CALL, function (data) {
|
||||
// convert this so that it broadcasts to all sockets and includes the map id
|
||||
// and info about who joined
|
||||
socket.broadcast.in(mapRoom(data.mapid)).emit(MAPPER_JOINED_CALL, data.id)
|
||||
})
|
||||
|
||||
socket.on(LEAVE_CALL, function (data) {
|
||||
// convert this so that it broadcasts to all sockets and includes the map id
|
||||
// and info about who joined
|
||||
socket.broadcast.in(mapRoom(data.mapid)).emit(MAPPER_LEFT_CALL, data.id)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
|
||||
import {
|
||||
const {
|
||||
MAPPER_LIST_UPDATED,
|
||||
NEW_MAPPER,
|
||||
LOST_MAPPER,
|
||||
|
@ -13,19 +12,19 @@ import {
|
|||
|
||||
JOIN_MAP,
|
||||
LEAVE_MAP,
|
||||
SEND_MAPPER_INFO,
|
||||
SEND_COORDS,
|
||||
SEND_MAPPER_INFO,
|
||||
CREATE_MESSAGE,
|
||||
DRAG_TOPIC,
|
||||
CREATE_TOPIC,
|
||||
REMOVE_TOPIC,
|
||||
CREATE_SYNAPSE,
|
||||
REMOVE_SYNAPSE
|
||||
} from '../frontend/src/Metamaps/Realtime/events'
|
||||
} = require('../frontend/src/Metamaps/Realtime/events')
|
||||
|
||||
const { mapRoom, userMapRoom } = require('./rooms')
|
||||
|
||||
module.exports = function (io, state) {
|
||||
module.exports = function (io, store) {
|
||||
io.on('connection', function (socket) {
|
||||
|
||||
// this will ping everyone on a map that there's a person just joined the map
|
||||
|
@ -33,11 +32,11 @@ module.exports = function (io, state) {
|
|||
socket.mapid = data.mapid
|
||||
socket.userid = data.userid
|
||||
socket.username = data.username
|
||||
socket.userimage = data.userimage
|
||||
socket.avatar = data.avatar
|
||||
var newUser = {
|
||||
userid: data.userid,
|
||||
username: data.username,
|
||||
userimage: data.userimage
|
||||
avatar: data.avatar
|
||||
}
|
||||
socket.join(mapRoom(data.mapid))
|
||||
socket.join(userMapRoom(data.userid, data.mapid))
|
||||
|
@ -63,7 +62,7 @@ module.exports = function (io, state) {
|
|||
userid: data.userid,
|
||||
username: data.username,
|
||||
userinconversation: data.userinconversation,
|
||||
userimage: data.userimage
|
||||
avatar: data.avatar
|
||||
}
|
||||
socket.broadcast.in(userMapRoom(data.userToNotify, data.mapid)).emit(MAPPER_LIST_UPDATED, existingUser)
|
||||
})
|
||||
|
|
|
@ -6,13 +6,14 @@ map = require('./map'),
|
|||
global = require('./global'),
|
||||
stunservers = [{"url": "stun:stun.l.google.com:19302"}]
|
||||
|
||||
var state = {
|
||||
connectedPeople: {},
|
||||
liveMaps: {}
|
||||
}
|
||||
signalling(io, stunservers, state)
|
||||
junto(io, state)
|
||||
map(io, state)
|
||||
global(io, state)
|
||||
io.listen(5001)
|
||||
const { createStore } = require('redux')
|
||||
const { reducer } = require('./reducer')
|
||||
|
||||
let store = createStore(reducer)
|
||||
|
||||
global(io, store)
|
||||
signalling(io, stunservers, store)
|
||||
junto(io, store)
|
||||
map(io, store)
|
||||
|
||||
io.listen(5001)
|
||||
|
|
75
realtime/reducer.js
Normal file
75
realtime/reducer.js
Normal file
|
@ -0,0 +1,75 @@
|
|||
const { omit, omitBy, isNil, mapValues } = require('lodash')
|
||||
const {
|
||||
JOIN_MAP,
|
||||
LEAVE_MAP,
|
||||
JOIN_CALL,
|
||||
LEAVE_CALL
|
||||
} = require('../frontend/src/Metamaps/Realtime/events')
|
||||
|
||||
const NOT_IN_CONVERSATION = 0
|
||||
const IN_CONVERSATION = 1
|
||||
|
||||
const addMapperToMap = (map, userId) => { return { ...map, [userId]: NOT_IN_CONVERSATION }}
|
||||
|
||||
const reducer = (state = { connectedPeople: {}, liveMaps: {} }, action) => {
|
||||
const { type, payload } = action
|
||||
const { connectedPeople, liveMaps } = state
|
||||
const map = payload && liveMaps[payload.mapid]
|
||||
const mapWillEmpty = map && Object.keys(map).length === 1
|
||||
const callWillFinish = map && (type === LEAVE_CALL || type === 'DISCONNECT') && Object.keys(map).length === 2
|
||||
|
||||
switch (type) {
|
||||
case JOIN_MAP:
|
||||
return Object.assign({}, state, {
|
||||
connectedPeople: Object.assign({}, connectedPeople, {
|
||||
[payload.userid]: {
|
||||
id: payload.userid,
|
||||
username: payload.username,
|
||||
avatar: payload.avatar
|
||||
}
|
||||
}),
|
||||
liveMaps: Object.assign({}, liveMaps, {
|
||||
[payload.mapid]: addMapperToMap(map || {}, payload.userid)
|
||||
})
|
||||
})
|
||||
case LEAVE_MAP:
|
||||
// if the map will empty, remove it from liveMaps, if the map will not empty, just remove the mapper
|
||||
const newLiveMaps = mapWillEmpty
|
||||
? omit(liveMaps, payload.mapid)
|
||||
: Object.assign({}, liveMaps, { [payload.mapid]: omit(map, payload.userid) })
|
||||
|
||||
return {
|
||||
connectedPeople: omit(connectedPeople, payload.userid),
|
||||
liveMaps: omitBy(newLiveMaps, isNil)
|
||||
}
|
||||
case JOIN_CALL:
|
||||
// update the user (payload.id is user id) in the given map to be marked in the conversation
|
||||
return Object.assign({}, state, {
|
||||
liveMaps: Object.assign({}, liveMaps, {
|
||||
[payload.mapid]: Object.assign({}, map, {
|
||||
[payload.id]: IN_CONVERSATION
|
||||
})
|
||||
})
|
||||
})
|
||||
case LEAVE_CALL:
|
||||
const newMap = callWillFinish
|
||||
? mapValues(map, () => NOT_IN_CONVERSATION)
|
||||
: Object.assign({}, map, { [payload.userid]: NOT_IN_CONVERSATION })
|
||||
|
||||
return Object.assign({}, state, {
|
||||
liveMaps: Object.assign({}, liveMaps, { map: newMap })
|
||||
})
|
||||
case 'DISCONNECT':
|
||||
const mapWithoutUser = omit(map, payload.userid)
|
||||
const newMap = callWillFinish ? mapValues(mapWithoutUser, () => NOT_IN_CONVERSATION) : mapWithoutUser
|
||||
const newLiveMaps = mapWillEmpty ? omit(liveMaps, payload.mapid) : Object.assign({}, liveMaps, { [payload.mapid]: newMap })
|
||||
return {
|
||||
connectedPeople: omit(connectedPeople, payload.userid),
|
||||
liveMaps: omitBy(newLiveMaps, isNil)
|
||||
}
|
||||
default:
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = reducer
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
module.exports = {
|
||||
mapRoom: mapId => `maps/${mapId}`,
|
||||
userMapRoom: (mapperId, mapId) => `mappers/${mapperId}/maps/${mapId}`,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
var uuid = require('node-uuid')
|
||||
const uuid = require('node-uuid')
|
||||
|
||||
// based off of https://github.com/andyet/signalmaster
|
||||
// since it was updated to socket.io 1.3.7
|
||||
|
@ -12,7 +12,6 @@ function safeCb(cb) {
|
|||
}
|
||||
|
||||
module.exports = function(io, stunservers, state) {
|
||||
|
||||
io.on('connection', function (socket) {
|
||||
socket.resources = {
|
||||
screen: false,
|
||||
|
|
Loading…
Reference in a new issue