make channels from array into object
This commit is contained in:
parent
ab910619f8
commit
8f24a34a1d
|
@ -90,7 +90,7 @@ export type Action =
|
||||||
minecraftname: string,
|
minecraftname: string,
|
||||||
blockDm: boolean,
|
blockDm: boolean,
|
||||||
canvases: Object,
|
canvases: Object,
|
||||||
channels: Array,
|
channels: Object,
|
||||||
blocked: Array,
|
blocked: Array,
|
||||||
userlvl: number,
|
userlvl: number,
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, {
|
import React, {
|
||||||
useRef, useEffect, useState, useLayoutEffect,
|
useRef, useEffect,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
|
@ -23,7 +23,6 @@ const UserContextMenu = ({
|
||||||
close,
|
close,
|
||||||
}) => {
|
}) => {
|
||||||
const wrapperRef = useRef(null);
|
const wrapperRef = useRef(null);
|
||||||
const [channelArray, setChannelArray] = useState([]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleClickOutside = (event) => {
|
const handleClickOutside = (event) => {
|
||||||
|
@ -42,20 +41,6 @@ const UserContextMenu = ({
|
||||||
};
|
};
|
||||||
}, [wrapperRef]);
|
}, [wrapperRef]);
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
|
||||||
for (let i = 0; i < channels.length; i += 1) {
|
|
||||||
const chan = channels[i];
|
|
||||||
/*
|
|
||||||
* [cid, name, type, lastMessage]
|
|
||||||
*/
|
|
||||||
// eslint-disable-next-line eqeqeq
|
|
||||||
if (chan[0] == cid) {
|
|
||||||
setChannelArray(chan);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [channels.length]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={wrapperRef}
|
ref={wrapperRef}
|
||||||
|
@ -68,7 +53,7 @@ const UserContextMenu = ({
|
||||||
<div>
|
<div>
|
||||||
✔✘ Mute
|
✔✘ Mute
|
||||||
</div>
|
</div>
|
||||||
{(channelArray[2] !== 0)
|
{(channels[cid][1] !== 0)
|
||||||
&& (
|
&& (
|
||||||
<div
|
<div
|
||||||
role="button"
|
role="button"
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, {
|
import React, {
|
||||||
useRef, useState, useEffect, useCallback,
|
useRef, useState, useEffect, useCallback, useLayoutEffect,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { MdChat } from 'react-icons/md';
|
import { MdChat } from 'react-icons/md';
|
||||||
|
@ -44,8 +44,12 @@ const ChannelDropDown = ({
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useLayoutEffect(() => {
|
||||||
if (show) {
|
if (show) {
|
||||||
|
if (channels[chatChannel]) {
|
||||||
|
const chType = (channels[chatChannel][1] === 1) ? 1 : 0;
|
||||||
|
setType(chType);
|
||||||
|
}
|
||||||
document.addEventListener('mousedown', handleClickOutside);
|
document.addEventListener('mousedown', handleClickOutside);
|
||||||
document.addEventListener('touchstart', handleClickOutside);
|
document.addEventListener('touchstart', handleClickOutside);
|
||||||
} else {
|
} else {
|
||||||
|
@ -55,12 +59,10 @@ const ChannelDropDown = ({
|
||||||
}, [show]);
|
}, [show]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
for (let i = 0; i < channels.length; i += 1) {
|
if (channels[chatChannel]) {
|
||||||
if (channels[i][0] === chatChannel) {
|
setChatChannelName(channels[chatChannel][0]);
|
||||||
setChatChannelName(channels[i][1]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, [chatChannel, channels]);
|
}, [chatChannel]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
@ -104,8 +106,8 @@ const ChannelDropDown = ({
|
||||||
className="channeldds"
|
className="channeldds"
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
channels.filter((ch) => {
|
Object.keys(channels).filter((cid) => {
|
||||||
const chType = ch[2];
|
const chType = channels[cid][1];
|
||||||
if (type === 1 && chType === 1) {
|
if (type === 1 && chType === 1) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -113,24 +115,27 @@ const ChannelDropDown = ({
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}).map((ch) => (
|
}).map((cid) => {
|
||||||
<div
|
const [name,, lastTs] = channels[cid];
|
||||||
onClick={() => setChannel(ch[0])}
|
console.log(`name ${name} lastTC ${lastTs} compare to ${chatRead[cid]}`);
|
||||||
style={(ch[0] === chatChannel) ? {
|
return (
|
||||||
fontWeight: 'bold',
|
<div
|
||||||
fontSize: 17,
|
onClick={() => setChannel(cid)}
|
||||||
} : null}
|
className={
|
||||||
className={
|
`chn${
|
||||||
`chn${
|
(cid === chatChannel) ? ' selected' : ''
|
||||||
(ch[0] === chatChannel) ? ' selected' : ''
|
}`
|
||||||
}${
|
}
|
||||||
(chatRead[ch[0]] < ch[3]) ? ' unread' : ''
|
>
|
||||||
}`
|
{
|
||||||
}
|
(chatRead[cid] < lastTs) ? (
|
||||||
>
|
<span className="chnunread">※</span>
|
||||||
{ch[1]}
|
) : null
|
||||||
</div>
|
}
|
||||||
))
|
{name}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -114,16 +114,11 @@ const Chat = ({
|
||||||
* set channel to first available one
|
* set channel to first available one
|
||||||
*/
|
*/
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let i = 0;
|
if (!channels[chatChannel]) {
|
||||||
while (i < channels.length) {
|
const cids = Object.keys(channels);
|
||||||
// eslint-disable-next-line eqeqeq
|
if (cids.length) {
|
||||||
if (channels[i][0] == chatChannel) {
|
setChannel(cids[0]);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
if (i && i === channels.length) {
|
|
||||||
setChannel(channels[0][0]);
|
|
||||||
}
|
}
|
||||||
}, [chatChannel, channels]);
|
}, [chatChannel, channels]);
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,10 @@
|
||||||
*
|
*
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
import Sequelize from 'sequelize';
|
||||||
import logger from './logger';
|
import logger from './logger';
|
||||||
|
|
||||||
import { RegUser, Message } from '../data/models';
|
import { RegUser, Message, Channel } from '../data/models';
|
||||||
|
|
||||||
const MAX_BUFFER_TIME = 120000;
|
const MAX_BUFFER_TIME = 120000;
|
||||||
|
|
||||||
|
@ -62,6 +63,13 @@ class ChatMessageBuffer {
|
||||||
uid,
|
uid,
|
||||||
message,
|
message,
|
||||||
});
|
});
|
||||||
|
Channel.update({
|
||||||
|
lastMessage: Sequelize.literal('CURRENT_TIMESTAMP'),
|
||||||
|
}, {
|
||||||
|
where: {
|
||||||
|
id: cid,
|
||||||
|
},
|
||||||
|
});
|
||||||
const messages = this.buffer.get(cid);
|
const messages = this.buffer.get(cid);
|
||||||
if (messages) {
|
if (messages) {
|
||||||
messages.push([
|
messages.push([
|
||||||
|
|
|
@ -10,8 +10,7 @@ import { CHAT_CHANNELS, EVENT_USER_NAME, INFO_USER_NAME } from './constants';
|
||||||
|
|
||||||
export class ChatProvider {
|
export class ChatProvider {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.defaultChannels = [];
|
this.defaultChannels = {};
|
||||||
this.defaultChannelIds = [];
|
|
||||||
this.enChannelId = 0;
|
this.enChannelId = 0;
|
||||||
this.intChannelId = 0;
|
this.intChannelId = 0;
|
||||||
this.infoUserId = 1;
|
this.infoUserId = 1;
|
||||||
|
@ -48,8 +47,6 @@ export class ChatProvider {
|
||||||
|
|
||||||
async initialize() {
|
async initialize() {
|
||||||
// find or create default channels
|
// find or create default channels
|
||||||
this.defaultChannels.length = 0;
|
|
||||||
this.defaultChannelIds.length = 0;
|
|
||||||
for (let i = 0; i < CHAT_CHANNELS.length; i += 1) {
|
for (let i = 0; i < CHAT_CHANNELS.length; i += 1) {
|
||||||
const { name } = CHAT_CHANNELS[i];
|
const { name } = CHAT_CHANNELS[i];
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
@ -66,13 +63,11 @@ export class ChatProvider {
|
||||||
if (name === 'en') {
|
if (name === 'en') {
|
||||||
this.enChannelId = id;
|
this.enChannelId = id;
|
||||||
}
|
}
|
||||||
this.defaultChannels.push([
|
this.defaultChannels[id] = [
|
||||||
id,
|
|
||||||
name,
|
name,
|
||||||
type,
|
type,
|
||||||
lastTs,
|
lastTs,
|
||||||
]);
|
];
|
||||||
this.defaultChannelIds.push(id);
|
|
||||||
}
|
}
|
||||||
// find or create default users
|
// find or create default users
|
||||||
let name = INFO_USER_NAME;
|
let name = INFO_USER_NAME;
|
||||||
|
@ -106,7 +101,7 @@ export class ChatProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
userHasChannelAccess(user, cid, write = false) {
|
userHasChannelAccess(user, cid, write = false) {
|
||||||
if (this.defaultChannelIds.includes(cid)) {
|
if (this.defaultChannels[cid]) {
|
||||||
if (!write || user.regUser) {
|
if (!write || user.regUser) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,10 +31,10 @@ export default async function getMe(user) {
|
||||||
delete userdata.mcVerified;
|
delete userdata.mcVerified;
|
||||||
|
|
||||||
userdata.canvases = canvases;
|
userdata.canvases = canvases;
|
||||||
userdata.channels = [
|
userdata.channels = {
|
||||||
...chatProvider.defaultChannels,
|
...chatProvider.defaultChannels,
|
||||||
...userdata.channels,
|
...userdata.channels,
|
||||||
];
|
};
|
||||||
|
|
||||||
return userdata;
|
return userdata;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ class User {
|
||||||
// id should stay null if unregistered
|
// id should stay null if unregistered
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.ip = ip;
|
this.ip = ip;
|
||||||
this.channels = [];
|
this.channels = {};
|
||||||
this.channelIds = [];
|
this.channelIds = [];
|
||||||
this.blocked = [];
|
this.blocked = [];
|
||||||
this.ipSub = getIPv6Subnet(ip);
|
this.ipSub = getIPv6Subnet(ip);
|
||||||
|
@ -70,12 +70,11 @@ class User {
|
||||||
name = (dmu1.id === this.id) ? dmu2.name : dmu1.name;
|
name = (dmu1.id === this.id) ? dmu2.name : dmu1.name;
|
||||||
}
|
}
|
||||||
this.channelIds.push(id);
|
this.channelIds.push(id);
|
||||||
this.channels.push([
|
this.channels[id] = [
|
||||||
id,
|
|
||||||
name,
|
name,
|
||||||
type,
|
type,
|
||||||
lastTs,
|
lastTs,
|
||||||
]);
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (reguser.blocked) {
|
if (reguser.blocked) {
|
||||||
|
|
|
@ -6,7 +6,21 @@ import type { Action } from '../actions/types';
|
||||||
|
|
||||||
export type ChatState = {
|
export type ChatState = {
|
||||||
inputMessage: string,
|
inputMessage: string,
|
||||||
// [[cid, name, type, lastMessage], [cid2, name2, type2, lastMessage2],...]
|
/*
|
||||||
|
* {
|
||||||
|
* cid: [
|
||||||
|
* name,
|
||||||
|
* type,
|
||||||
|
* lastTs,
|
||||||
|
* ],
|
||||||
|
* cid2: [
|
||||||
|
* name,
|
||||||
|
* type,
|
||||||
|
* lastTs,
|
||||||
|
* ],
|
||||||
|
* ...
|
||||||
|
* }
|
||||||
|
*/
|
||||||
channels: Array,
|
channels: Array,
|
||||||
// [[uId, userName], [userId2, userName2],...]
|
// [[uId, userName], [userId2, userName2],...]
|
||||||
blocked: Array,
|
blocked: Array,
|
||||||
|
@ -16,7 +30,7 @@ export type ChatState = {
|
||||||
|
|
||||||
const initialState: ChatState = {
|
const initialState: ChatState = {
|
||||||
inputMessage: '',
|
inputMessage: '',
|
||||||
channels: [],
|
channels: {},
|
||||||
blocked: [],
|
blocked: [],
|
||||||
messages: {},
|
messages: {},
|
||||||
};
|
};
|
||||||
|
@ -56,22 +70,19 @@ export default function chat(
|
||||||
|
|
||||||
case 'ADD_CHAT_CHANNEL': {
|
case 'ADD_CHAT_CHANNEL': {
|
||||||
const { channel } = action;
|
const { channel } = action;
|
||||||
const cid = channel[0];
|
|
||||||
const channels = state.channels
|
|
||||||
.filter((ch) => (ch[0] !== cid));
|
|
||||||
channels.push(channel);
|
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
channels,
|
channels: {
|
||||||
|
...state.channels,
|
||||||
|
...channel,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'REMOVE_CHAT_CHANNEL': {
|
case 'REMOVE_CHAT_CHANNEL': {
|
||||||
const { cid } = action;
|
const { cid } = action;
|
||||||
const channels = state.channels.filter(
|
const channels = { ...state.channels };
|
||||||
// eslint-disable-next-line eqeqeq
|
delete channels[cid];
|
||||||
(chan) => (chan[0] != cid),
|
|
||||||
);
|
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
channels,
|
channels,
|
||||||
|
@ -106,7 +117,7 @@ export default function chat(
|
||||||
const {
|
const {
|
||||||
name, text, country, channel, user,
|
name, text, country, channel, user,
|
||||||
} = action;
|
} = action;
|
||||||
if (!state.messages[channel]) {
|
if (!state.messages[channel] || !state.channels[channel]) {
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
const messages = {
|
const messages = {
|
||||||
|
@ -119,8 +130,19 @@ export default function chat(
|
||||||
if (messages[channel].length > MAX_CHAT_MESSAGES) {
|
if (messages[channel].length > MAX_CHAT_MESSAGES) {
|
||||||
messages[channel].shift();
|
messages[channel].shift();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* update timestamp of last message
|
||||||
|
*/
|
||||||
|
const channelArray = [...state.channels[channel]];
|
||||||
|
channelArray[2] = Date.now();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
|
channels: {
|
||||||
|
...state.channels,
|
||||||
|
[channel]: channelArray,
|
||||||
|
},
|
||||||
messages,
|
messages,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,9 +109,15 @@ export default function gui(
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'SET_CHAT_CHANNEL': {
|
case 'SET_CHAT_CHANNEL': {
|
||||||
|
const { cid } = action;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
chatChannel: action.cid,
|
chatChannel: cid,
|
||||||
|
chatRead: {
|
||||||
|
...state.chatRead,
|
||||||
|
cid: Date.now(),
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,6 +145,42 @@ export default function gui(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 'RECEIVE_ME': {
|
||||||
|
const { channels } = action;
|
||||||
|
const cids = Object.keys(channels);
|
||||||
|
const chatRead = {...state.chatRead};
|
||||||
|
for (let i = 0; i < cids.length; i += 1) {
|
||||||
|
const cid = cids[i];
|
||||||
|
chatRead[cid] = 0;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
chatRead,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'ADD_CHAT_CHANNEL': {
|
||||||
|
const [cid] = Object.keys(action.channel);
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
chatRead: {
|
||||||
|
...state.chatRead,
|
||||||
|
[cid]: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'REMOVE_CHAT_CHANNEL': {
|
||||||
|
const { cid } = action;
|
||||||
|
const chatRead = { ...state.chatRead };
|
||||||
|
delete chatRead[cid];
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
chatRead,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
case 'PLACE_PIXEL': {
|
case 'PLACE_PIXEL': {
|
||||||
let { pixelsPlaced } = state;
|
let { pixelsPlaced } = state;
|
||||||
pixelsPlaced += 1;
|
pixelsPlaced += 1;
|
||||||
|
|
|
@ -105,7 +105,6 @@ async function startDm(req: Request, res: Response) {
|
||||||
raw: true,
|
raw: true,
|
||||||
});
|
});
|
||||||
const ChannelId = channel[0].id;
|
const ChannelId = channel[0].id;
|
||||||
const { lastMessage } = channel[0];
|
|
||||||
|
|
||||||
const promises = [
|
const promises = [
|
||||||
UserChannel.findOrCreate({
|
UserChannel.findOrCreate({
|
||||||
|
@ -127,12 +126,13 @@ async function startDm(req: Request, res: Response) {
|
||||||
|
|
||||||
// TODO: inform websocket to add channelId to user
|
// TODO: inform websocket to add channelId to user
|
||||||
res.json({
|
res.json({
|
||||||
channel: [
|
channel: {
|
||||||
ChannelId,
|
[ChannelId]: [
|
||||||
userName,
|
userName,
|
||||||
1,
|
1,
|
||||||
lastMessage,
|
Date.now(),
|
||||||
],
|
],
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -485,6 +485,15 @@ tr:nth-child(even) {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chn.selected, .chnunread {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 17px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chnunread {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
.usermessages {
|
.usermessages {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
|
|
@ -194,7 +194,7 @@ app.get('/', async (req, res) => {
|
||||||
// ip config
|
// ip config
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// use this if models changed:
|
// use this if models changed:
|
||||||
const promise = models.sync({ alter: { drop: true } })
|
const promise = models.sync({ alter: { drop: false } })
|
||||||
// const promise = models.sync()
|
// const promise = models.sync()
|
||||||
.catch((err) => logger.error(err.stack));
|
.catch((err) => logger.error(err.stack));
|
||||||
promise.then(() => {
|
promise.then(() => {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user