This commit is contained in:
syuilo 2018-03-11 18:08:26 +09:00
parent 04cc63ac64
commit bd79352e80
7 changed files with 89 additions and 7 deletions

View file

@ -2,7 +2,7 @@ import $ from 'cafy';
import Matching, { pack as packMatching } from '../../models/othello-matching'; import Matching, { pack as packMatching } from '../../models/othello-matching';
import Game, { pack as packGame } from '../../models/othello-game'; import Game, { pack as packGame } from '../../models/othello-game';
import User from '../../models/user'; import User from '../../models/user';
import { publishOthelloStream } from '../../event'; import publishUserStream, { publishOthelloStream } from '../../event';
import { eighteight } from '../../../common/othello/maps'; import { eighteight } from '../../../common/othello/maps';
module.exports = (params, user) => new Promise(async (res, rej) => { module.exports = (params, user) => new Promise(async (res, rej) => {
@ -48,6 +48,14 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
res(await packGame(game, user)); res(await packGame(game, user));
publishOthelloStream(exist.parent_id, 'matched', await packGame(game, exist.parent_id)); publishOthelloStream(exist.parent_id, 'matched', await packGame(game, exist.parent_id));
const other = await Matching.count({
child_id: user._id
});
if (other == 0) {
publishUserStream(user._id, 'othello_no_invites');
}
} else { } else {
// Fetch child // Fetch child
const child = await User.findOne({ const child = await User.findOne({
@ -77,7 +85,11 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
// Reponse // Reponse
res(); res();
const packed = await packMatching(matching, child);
// 招待 // 招待
publishOthelloStream(child._id, 'invited', await packMatching(matching, child)); publishOthelloStream(child._id, 'invited', packed);
publishUserStream(child._id, 'othello_invited', packed);
} }
}); });

View file

@ -32,6 +32,8 @@ export const pack = (
const _matching = deepcopy(matching); const _matching = deepcopy(matching);
// Rename _id to id
_matching.id = _matching._id;
delete _matching._id; delete _matching._id;
// Populate user // Populate user

View file

@ -1,5 +1,8 @@
import * as mongo from 'mongodb';
import * as websocket from 'websocket'; import * as websocket from 'websocket';
import * as redis from 'redis'; import * as redis from 'redis';
import Matching, { pack } from '../models/othello-matching';
import publishUserStream from '../event';
export default function(request: websocket.request, connection: websocket.connection, subscriber: redis.RedisClient, user: any): void { export default function(request: websocket.request, connection: websocket.connection, subscriber: redis.RedisClient, user: any): void {
// Subscribe othello stream // Subscribe othello stream
@ -7,4 +10,20 @@ export default function(request: websocket.request, connection: websocket.connec
subscriber.on('message', (_, data) => { subscriber.on('message', (_, data) => {
connection.send(data); connection.send(data);
}); });
connection.on('message', async (data) => {
const msg = JSON.parse(data.utf8Data);
switch (msg.type) {
case 'ping':
if (msg.id == null) return;
const matching = await Matching.findOne({
parent_id: user._id,
child_id: new mongo.ObjectID(msg.id)
});
if (matching == null) return;
publishUserStream(matching.child_id, 'othello_invited', await pack(matching, matching.child_id));
break;
}
});
} }

View file

@ -78,7 +78,8 @@ export default Vue.extend({
matching: null, matching: null,
invitations: [], invitations: [],
connection: null, connection: null,
connectionId: null connectionId: null,
pingClock: null
}; };
}, },
watch: { watch: {
@ -112,17 +113,29 @@ export default Vue.extend({
(this as any).api('othello/invitations').then(invitations => { (this as any).api('othello/invitations').then(invitations => {
this.invitations = this.invitations.concat(invitations); this.invitations = this.invitations.concat(invitations);
}); });
this.pingClock = setInterval(() => {
if (this.matching) {
this.connection.send({
type: 'ping',
id: this.matching.id
});
}
}, 3000);
}, },
beforeDestroy() { beforeDestroy() {
this.connection.off('matched', this.onMatched); this.connection.off('matched', this.onMatched);
this.connection.off('invited', this.onInvited); this.connection.off('invited', this.onInvited);
(this as any).os.streams.othelloStream.dispose(this.connectionId); (this as any).os.streams.othelloStream.dispose(this.connectionId);
clearInterval(this.pingClock);
}, },
methods: { methods: {
go(game) { go(game) {
(this as any).api('othello/games/show', { (this as any).api('othello/games/show', {
game_id: game.id game_id: game.id
}).then(game => { }).then(game => {
this.matching = null;
this.game = game; this.game = game;
}); });
}, },
@ -154,11 +167,13 @@ export default Vue.extend({
user_id: invitation.parent.id user_id: invitation.parent.id
}).then(game => { }).then(game => {
if (game) { if (game) {
this.matching = null;
this.game = game; this.game = game;
} }
}); });
}, },
onMatched(game) { onMatched(game) {
this.matching = null;
this.game = game; this.game = game;
}, },
onInvited(invite) { onInvited(invite) {

View file

@ -56,6 +56,8 @@ export default Vue.extend({
this.connection.on('read_all_messaging_messages', this.onReadAllMessagingMessages); this.connection.on('read_all_messaging_messages', this.onReadAllMessagingMessages);
this.connection.on('unread_messaging_message', this.onUnreadMessagingMessage); this.connection.on('unread_messaging_message', this.onUnreadMessagingMessage);
this.connection.on('othello_invited', this.onOthelloInvited);
this.connection.on('othello_no_invites', this.onOthelloNoInvites);
// Fetch count of unread messaging messages // Fetch count of unread messaging messages
(this as any).api('messaging/unread').then(res => { (this as any).api('messaging/unread').then(res => {
@ -69,16 +71,26 @@ export default Vue.extend({
if ((this as any).os.isSignedIn) { if ((this as any).os.isSignedIn) {
this.connection.off('read_all_messaging_messages', this.onReadAllMessagingMessages); this.connection.off('read_all_messaging_messages', this.onReadAllMessagingMessages);
this.connection.off('unread_messaging_message', this.onUnreadMessagingMessage); this.connection.off('unread_messaging_message', this.onUnreadMessagingMessage);
this.connection.off('othello_invited', this.onOthelloInvited);
this.connection.off('othello_no_invites', this.onOthelloNoInvites);
(this as any).os.stream.dispose(this.connectionId); (this as any).os.stream.dispose(this.connectionId);
} }
}, },
methods: { methods: {
onUnreadMessagingMessage() {
this.hasUnreadMessagingMessages = true;
},
onReadAllMessagingMessages() { onReadAllMessagingMessages() {
this.hasUnreadMessagingMessages = false; this.hasUnreadMessagingMessages = false;
}, },
onUnreadMessagingMessage() { onOthelloInvited() {
this.hasUnreadMessagingMessages = true; this.hasGameInvitations = true;
},
onOthelloNoInvites() {
this.hasGameInvitations = false;
}, },
messaging() { messaging() {

View file

@ -6,7 +6,7 @@
<p ref="welcomeback" v-if="os.isSignedIn">おかえりなさい<b>{{ os.i.name }}</b>さん</p> <p ref="welcomeback" v-if="os.isSignedIn">おかえりなさい<b>{{ os.i.name }}</b>さん</p>
<div class="content" ref="mainContainer"> <div class="content" ref="mainContainer">
<button class="nav" @click="$parent.isDrawerOpening = true">%fa:bars%</button> <button class="nav" @click="$parent.isDrawerOpening = true">%fa:bars%</button>
<template v-if="hasUnreadNotifications || hasUnreadMessagingMessages">%fa:circle%</template> <template v-if="hasUnreadNotifications || hasUnreadMessagingMessages || hasGameInvitations">%fa:circle%</template>
<h1> <h1>
<slot>Misskey</slot> <slot>Misskey</slot>
</h1> </h1>
@ -26,6 +26,7 @@ export default Vue.extend({
return { return {
hasUnreadNotifications: false, hasUnreadNotifications: false,
hasUnreadMessagingMessages: false, hasUnreadMessagingMessages: false,
hasGameInvitations: false,
connection: null, connection: null,
connectionId: null connectionId: null
}; };
@ -39,6 +40,8 @@ export default Vue.extend({
this.connection.on('unread_notification', this.onUnreadNotification); this.connection.on('unread_notification', this.onUnreadNotification);
this.connection.on('read_all_messaging_messages', this.onReadAllMessagingMessages); this.connection.on('read_all_messaging_messages', this.onReadAllMessagingMessages);
this.connection.on('unread_messaging_message', this.onUnreadMessagingMessage); this.connection.on('unread_messaging_message', this.onUnreadMessagingMessage);
this.connection.on('othello_invited', this.onOthelloInvited);
this.connection.on('othello_no_invites', this.onOthelloNoInvites);
// Fetch count of unread notifications // Fetch count of unread notifications
(this as any).api('notifications/get_unread_count').then(res => { (this as any).api('notifications/get_unread_count').then(res => {
@ -107,6 +110,8 @@ export default Vue.extend({
this.connection.off('unread_notification', this.onUnreadNotification); this.connection.off('unread_notification', this.onUnreadNotification);
this.connection.off('read_all_messaging_messages', this.onReadAllMessagingMessages); this.connection.off('read_all_messaging_messages', this.onReadAllMessagingMessages);
this.connection.off('unread_messaging_message', this.onUnreadMessagingMessage); this.connection.off('unread_messaging_message', this.onUnreadMessagingMessage);
this.connection.off('othello_invited', this.onOthelloInvited);
this.connection.off('othello_no_invites', this.onOthelloNoInvites);
(this as any).os.stream.dispose(this.connectionId); (this as any).os.stream.dispose(this.connectionId);
} }
}, },
@ -122,6 +127,12 @@ export default Vue.extend({
}, },
onUnreadMessagingMessage() { onUnreadMessagingMessage() {
this.hasUnreadMessagingMessages = true; this.hasUnreadMessagingMessages = true;
},
onOthelloInvited() {
this.hasGameInvitations = true;
},
onOthelloNoInvites() {
this.hasGameInvitations = false;
} }
} }
}); });

View file

@ -18,7 +18,7 @@
<li><router-link to="/">%fa:home%%i18n:mobile.tags.mk-ui-nav.home%%fa:angle-right%</router-link></li> <li><router-link to="/">%fa:home%%i18n:mobile.tags.mk-ui-nav.home%%fa:angle-right%</router-link></li>
<li><router-link to="/i/notifications">%fa:R bell%%i18n:mobile.tags.mk-ui-nav.notifications%<template v-if="hasUnreadNotifications">%fa:circle%</template>%fa:angle-right%</router-link></li> <li><router-link to="/i/notifications">%fa:R bell%%i18n:mobile.tags.mk-ui-nav.notifications%<template v-if="hasUnreadNotifications">%fa:circle%</template>%fa:angle-right%</router-link></li>
<li><router-link to="/i/messaging">%fa:R comments%%i18n:mobile.tags.mk-ui-nav.messaging%<template v-if="hasUnreadMessagingMessages">%fa:circle%</template>%fa:angle-right%</router-link></li> <li><router-link to="/i/messaging">%fa:R comments%%i18n:mobile.tags.mk-ui-nav.messaging%<template v-if="hasUnreadMessagingMessages">%fa:circle%</template>%fa:angle-right%</router-link></li>
<li><router-link to="/othello">%fa:gamepad%ゲーム%fa:angle-right%</router-link></li> <li><router-link to="/othello">%fa:gamepad%ゲーム<template v-if="hasGameInvitations">%fa:circle%</template>%fa:angle-right%</router-link></li>
</ul> </ul>
<ul> <ul>
<li><a :href="chUrl" target="_blank">%fa:tv%%i18n:mobile.tags.mk-ui-nav.ch%%fa:angle-right%</a></li> <li><a :href="chUrl" target="_blank">%fa:tv%%i18n:mobile.tags.mk-ui-nav.ch%%fa:angle-right%</a></li>
@ -47,6 +47,7 @@ export default Vue.extend({
return { return {
hasUnreadNotifications: false, hasUnreadNotifications: false,
hasUnreadMessagingMessages: false, hasUnreadMessagingMessages: false,
hasGameInvitations: false,
connection: null, connection: null,
connectionId: null, connectionId: null,
aboutUrl: `${docsUrl}/${lang}/about`, aboutUrl: `${docsUrl}/${lang}/about`,
@ -62,6 +63,8 @@ export default Vue.extend({
this.connection.on('unread_notification', this.onUnreadNotification); this.connection.on('unread_notification', this.onUnreadNotification);
this.connection.on('read_all_messaging_messages', this.onReadAllMessagingMessages); this.connection.on('read_all_messaging_messages', this.onReadAllMessagingMessages);
this.connection.on('unread_messaging_message', this.onUnreadMessagingMessage); this.connection.on('unread_messaging_message', this.onUnreadMessagingMessage);
this.connection.on('othello_invited', this.onOthelloInvited);
this.connection.on('othello_no_invites', this.onOthelloNoInvites);
// Fetch count of unread notifications // Fetch count of unread notifications
(this as any).api('notifications/get_unread_count').then(res => { (this as any).api('notifications/get_unread_count').then(res => {
@ -84,6 +87,8 @@ export default Vue.extend({
this.connection.off('unread_notification', this.onUnreadNotification); this.connection.off('unread_notification', this.onUnreadNotification);
this.connection.off('read_all_messaging_messages', this.onReadAllMessagingMessages); this.connection.off('read_all_messaging_messages', this.onReadAllMessagingMessages);
this.connection.off('unread_messaging_message', this.onUnreadMessagingMessage); this.connection.off('unread_messaging_message', this.onUnreadMessagingMessage);
this.connection.off('othello_invited', this.onOthelloInvited);
this.connection.off('othello_no_invites', this.onOthelloNoInvites);
(this as any).os.stream.dispose(this.connectionId); (this as any).os.stream.dispose(this.connectionId);
} }
}, },
@ -104,6 +109,12 @@ export default Vue.extend({
}, },
onUnreadMessagingMessage() { onUnreadMessagingMessage() {
this.hasUnreadMessagingMessages = true; this.hasUnreadMessagingMessages = true;
},
onOthelloInvited() {
this.hasGameInvitations = true;
},
onOthelloNoInvites() {
this.hasGameInvitations = false;
} }
} }
}); });