Repository: Same-Page/front-and-back
Branch: master
Commit: 967be22b5f1a
Files: 231
Total size: 1.9 MB
Directory structure:
gitextract_332hnacs/
├── .gitignore
├── .prettierrc
├── README.md
├── README_EN.md
├── chatbox/
│ ├── .gitignore
│ ├── .prettierrc
│ ├── .storybook/
│ │ ├── addons.js
│ │ └── config.js
│ ├── README.md
│ ├── package.json
│ ├── public/
│ │ ├── index.html
│ │ └── manifest.json
│ └── src/
│ ├── .eslintrc.json
│ ├── App.js
│ ├── components/
│ │ ├── Emoji/
│ │ │ ├── Emoji.css
│ │ │ ├── Emoji.js
│ │ │ └── index.js
│ │ ├── Iframe/
│ │ │ ├── Iframe.css
│ │ │ ├── Iframe.js
│ │ │ └── index.js
│ │ ├── InputWithPicker/
│ │ │ ├── InputWithPicker.css
│ │ │ ├── InputWithPicker.js
│ │ │ └── index.js
│ │ ├── MusicPlayer/
│ │ │ ├── MusicPlayer.css
│ │ │ ├── MusicPlayer.js
│ │ │ └── index.js
│ │ └── OutsideClickDetector.js
│ ├── config/
│ │ ├── index.js
│ │ ├── logger.js
│ │ └── urls.js
│ ├── containers/
│ │ ├── Account/
│ │ │ ├── Account.js
│ │ │ ├── AvatarUploader/
│ │ │ │ ├── AvatarUploader.css
│ │ │ │ ├── AvatarUploader.js
│ │ │ │ └── index.js
│ │ │ ├── Blacklist.js
│ │ │ ├── EditProfile.js
│ │ │ ├── Follow/
│ │ │ │ ├── Follow.css
│ │ │ │ ├── Follow.js
│ │ │ │ ├── event.js
│ │ │ │ └── index.js
│ │ │ ├── Login.js
│ │ │ ├── Profile/
│ │ │ │ ├── Profile.css
│ │ │ │ ├── Profile.js
│ │ │ │ └── index.js
│ │ │ ├── ResetPassword.js
│ │ │ └── index.js
│ │ ├── Chat/
│ │ │ ├── Body.css
│ │ │ ├── Body.js
│ │ │ ├── Chat.js
│ │ │ ├── Footer/
│ │ │ │ ├── Footer.css
│ │ │ │ ├── Footer.js
│ │ │ │ └── index.js
│ │ │ ├── Header/
│ │ │ │ ├── Header.css
│ │ │ │ ├── Header.js
│ │ │ │ ├── Invite.js
│ │ │ │ ├── RoomHeader.js
│ │ │ │ ├── RoomInfo.js
│ │ │ │ ├── Users.js
│ │ │ │ └── index.js
│ │ │ ├── Message/
│ │ │ │ ├── Body.css
│ │ │ │ ├── Body.js
│ │ │ │ ├── Message.css
│ │ │ │ ├── Message.js
│ │ │ │ └── index.js
│ │ │ ├── ResizableMedia.js
│ │ │ ├── View.js
│ │ │ └── index.js
│ │ ├── Comment/
│ │ │ ├── Body.js
│ │ │ ├── Comment.css
│ │ │ ├── Comment.js
│ │ │ ├── Header.js
│ │ │ ├── Message/
│ │ │ │ ├── Message.css
│ │ │ │ ├── Message.js
│ │ │ │ └── index.js
│ │ │ └── index.js
│ │ ├── Home/
│ │ │ ├── Comments/
│ │ │ │ ├── Comment.css
│ │ │ │ ├── Comments.js
│ │ │ │ └── index.js
│ │ │ ├── CreateRoom.js
│ │ │ ├── Danmus/
│ │ │ │ ├── Danmus.js
│ │ │ │ └── index.js
│ │ │ ├── Discover.js
│ │ │ ├── Home.css
│ │ │ ├── Home.js
│ │ │ ├── Rooms/
│ │ │ │ ├── Room.css
│ │ │ │ ├── Rooms.js
│ │ │ │ └── index.js
│ │ │ ├── RoomsWrapper.js
│ │ │ ├── Users/
│ │ │ │ ├── Users.css
│ │ │ │ ├── Users.js
│ │ │ │ └── index.js
│ │ │ ├── VideoRoom/
│ │ │ │ ├── VideoRoom.js
│ │ │ │ └── index.js
│ │ │ └── index.js
│ │ ├── Inbox/
│ │ │ ├── Conversation/
│ │ │ │ ├── Conversation.css
│ │ │ │ ├── Conversation.js
│ │ │ │ └── index.js
│ │ │ ├── Inbox.css
│ │ │ ├── Inbox.js
│ │ │ └── index.js
│ │ ├── Music/
│ │ │ ├── MusicTab.js
│ │ │ ├── Playlist/
│ │ │ │ ├── Playlist.css
│ │ │ │ ├── Playlist.js
│ │ │ │ └── index.js
│ │ │ └── index.js
│ │ ├── OtherProfile/
│ │ │ ├── AvatarWithHoverCard.js
│ │ │ ├── OtherProfile.js
│ │ │ ├── ProfileBody/
│ │ │ │ ├── ProfileBody.js
│ │ │ │ └── index.js
│ │ │ ├── ProfileCard.css
│ │ │ ├── ProfileCard.js
│ │ │ ├── ProfileMeta/
│ │ │ │ ├── ProfileMeta.js
│ │ │ │ └── index.js
│ │ │ └── index.js
│ │ └── Tab/
│ │ ├── Tab.css
│ │ ├── Tab.js
│ │ └── index.js
│ ├── context/
│ │ └── preference-context.js
│ ├── i18n/
│ │ ├── en.json
│ │ └── zh.json
│ ├── index.css
│ ├── index.js
│ ├── redux/
│ │ ├── actions/
│ │ │ ├── chat/
│ │ │ │ └── index.js
│ │ │ └── index.js
│ │ ├── reducers/
│ │ │ └── index.js
│ │ └── store/
│ │ └── index.js
│ ├── serviceWorker.js
│ ├── services/
│ │ ├── account.js
│ │ ├── comment.js
│ │ ├── danmu.js
│ │ ├── follow.js
│ │ ├── index.js
│ │ ├── message.js
│ │ ├── room.js
│ │ └── user.js
│ ├── socket/
│ │ ├── index.js
│ │ └── socket.js
│ ├── stories/
│ │ ├── IframeWithSrcInput.js
│ │ ├── data/
│ │ │ ├── chats.js
│ │ │ └── comments.js
│ │ ├── iframe.css
│ │ └── index.js
│ └── utils/
│ ├── pageTitle.js
│ ├── storage.js
│ └── url.js
├── extension/
│ ├── build/
│ │ ├── _locales/
│ │ │ ├── en/
│ │ │ │ └── messages.json
│ │ │ └── zh_CN/
│ │ │ └── messages.json
│ │ ├── background.js
│ │ ├── content-static/
│ │ │ ├── css/
│ │ │ │ └── main.css
│ │ │ └── js/
│ │ │ └── main.js
│ │ ├── manifest.json
│ │ ├── popup.css
│ │ ├── popup.html
│ │ ├── popup_menu/
│ │ │ ├── css/
│ │ │ │ └── main.css
│ │ │ └── js/
│ │ │ └── main.js
│ │ └── popup_old.js
│ └── popup/
│ ├── .gitignore
│ ├── README.md
│ ├── config/
│ │ ├── env.js
│ │ ├── jest/
│ │ │ ├── cssTransform.js
│ │ │ └── fileTransform.js
│ │ ├── paths.js
│ │ ├── webpack.config.js
│ │ └── webpackDevServer.config.js
│ ├── package.json
│ ├── public/
│ │ ├── index.html
│ │ └── manifest.json
│ ├── scripts/
│ │ ├── build.js
│ │ ├── start.js
│ │ └── test.js
│ └── src/
│ ├── App.js
│ ├── App.test.js
│ ├── index.css
│ ├── index.js
│ └── serviceWorker.js
└── inject-script/
├── .gitignore
├── .storybook/
│ ├── addons.js
│ ├── config.js
│ └── webpack_empty.config.js
├── README.md
├── config/
│ ├── env.js
│ ├── jest/
│ │ ├── cssTransform.js
│ │ └── fileTransform.js
│ ├── paths.js
│ ├── webpack.config.js
│ └── webpackDevServer.config.js
├── package.json
├── public/
│ ├── index.html
│ └── manifest.json
├── scripts/
│ ├── build.js
│ ├── start.js
│ └── test.js
├── src/
│ ├── config/
│ │ ├── iframe.js
│ │ ├── index.js
│ │ ├── logger.js
│ │ └── urls.js
│ ├── containers/
│ │ ├── App/
│ │ │ ├── App.js
│ │ │ ├── App.test.js
│ │ │ └── index.js
│ │ ├── ChatDanmu/
│ │ │ ├── AnimationDanmu.css
│ │ │ ├── AnimationDanmu.js
│ │ │ └── Danmu.js
│ │ ├── ChatIcon/
│ │ │ ├── ChatIcon.js
│ │ │ └── index.js
│ │ ├── ChatboxIframe/
│ │ │ ├── ChatboxIframe.css
│ │ │ ├── ChatboxIframe.js
│ │ │ └── index.js
│ │ ├── ImageModal/
│ │ │ ├── ImageModal.css
│ │ │ ├── ImageModal.js
│ │ │ └── index.js
│ │ ├── Room/
│ │ │ ├── Room.css
│ │ │ ├── Room.js
│ │ │ └── index.js
│ │ └── User/
│ │ ├── User.css
│ │ ├── User.js
│ │ └── index.js
│ ├── index.css
│ ├── index.js
│ ├── serviceWorker.js
│ ├── services/
│ │ ├── account/
│ │ │ ├── account.js
│ │ │ └── index.js
│ │ ├── room/
│ │ │ ├── index.js
│ │ │ └── room.js
│ │ ├── socket/
│ │ │ ├── index.js
│ │ │ └── socket.js
│ │ └── user/
│ │ ├── index.js
│ │ └── user.js
│ ├── storage.js
│ └── utils/
│ ├── iframe.js
│ └── url.js
└── stories/
└── index.stories.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
.DS_Store
client/extension/build/content-static/*
client/extension/build.zip
client/.vscode/launch.json
*.zip
================================================
FILE: .prettierrc
================================================
{
"trailingComma": "none",
"arrowParens": "avoid",
"semi": false,
"useTabs": true,
"printWidth": 80
}
================================================
FILE: README.md
================================================
#### [Read English Version](https://github.com/Same-Page/client/blob/master/README_EN.md)
# 一叶
《一叶》是一款[浏览器插件](https://chrome.google.com/webstore/detail/same-page/bldcellajihanglphncgjmceklbibjkk),它让你可以在任意网页上实时聊天。
你也可以将一叶聊天盒部署在你自己的网站上,一叶的前后端代码都是开源的。
主要功能包括有:
- 同网页聊天
- 同网站聊天
- 创建个性化房间
- 用户之间可以关注,发私信等
## 截图
## 项目结构
一叶的前端代码在本项目里。
Client 文件夹主要有 chatbox 和 inject-script 两部分,都是用 create-react-app 创建的。工作方法是首先在网页里引入 inject-script,然后 inject-script 运行时会生成一个包含了聊天盒的 iframe。
这种分离的设计有两个优点:
1. 聊天盒因为功能很多所以文件较大,所以不用在每次加载页面的时候就加载它,而是当用户想要使用的时候才打开。
2. Iframe 可以起到很好的隔离作用,你的网站和一叶之间不会互相影响,不论是 javascript 还是 css 样式。
Inject script 部分的文件比较小,它的功能有:
1. 在网页上增加一个按钮,点击按钮可以打开含有聊天盒的 iframe。
2. 自动连接聊天服务器,显示多少人在当前网页或网站,显示实时聊天弹幕。
## 如何开发与本地运行
### 本地运行客户端
前面提到了客户端分有 inject-script 和 chatbox 两部分,两者都要启动聊天盒才能正常使用。
首先运行 chatbox 部分
```
cd client/chatbox
npm install .
npm start
```
第一次运行需要先 `npm install .`安装依赖的库,之后则不用。项目会运行于 localhost:3000,但聊天盒并不能独立工作,接下来我们运行 injection-script 的部分。
```
cd client/inject-script
npm install .
npm start
```
现在如果你去 localhost:3210,就可以看到客户端正常运行了,点击右下角的圆圈打开聊天盒。
客户端默认会和官方的服务器通讯,而不是你的本地后端,你可以更改默认的设定,让客户端和你的本地后端通讯。如何运行后端代码请见后端的代码库
[聊天系统后端](https://github.com/Same-Page/chat-backend)
[基本系统后端](https://github.com/Same-Page/web-backend)
## 如何部署前端
### 生成客户端文件
Inject-script 和 chatbox 两部分要分别生成。
生成聊天盒的客户端文件。
```
cd client/chatbox
npm run build
```
生成 inject-script 的客户端文件。
```
cd client/inject-scirpt
npm run build
```
生成的文件在对应的 build 文件夹里,更多细节可以参考 Facebook 官方的 create-react-app 教程。
### 部署到你的网站上
将 inject-script 的`client/inject-scirpt/build/content-static`文件夹上传到你的服务器,确保可以以`your-website.com/build/content-static`的形式访问里面的文件. 接下来在你的网站里引入下面两行即可
```
```
如果聊天盒的部分也要使用你自己生成的版本,相似的,上传你的`client/chatbox/build/`文件夹到你的服务器,确保可以访问`your-website.com/build/static`里面的文件。同时要记得修改 injection script 中设置的 chatbox iframe 的地址指向你自己上传的这个版本,`your-website.com/build/index.html`,也可以在你的网站定义下面的设置。
```
window.spConfig = {
chatboxUrl: 'your-website.com/build/index.html'
}
```
================================================
FILE: README_EN.md
================================================
# Same Page
Same Page (previously called Chat Anywhere) is a [Chrome extension](https://chrome.google.com/webstore/detail/same-page/bldcellajihanglphncgjmceklbibjkk) that adds a chat box to any website. You can also customize the source code and use it on your own website.
## Project structure
This repository contains frontend code only.
The client folder includes the chat box and an injection script, both of them are built with create-react-app. The way it works is that once you include the injection script to your website, the script can create an iframe with chat box. This design has two major benefits:
1. The chat box's file size is quite big because it includes so many features, therefore you probably don't want to load it on every page load. It makes a lot more sense to load the chat box iframe only when user wants to use it.
2. Iframe provides great isolation of the chat box and your website, no need to worry about CSS or Javascript pollution.
The injection script itself is rather small, it's able to
1. Add a button that creates the iframe with chat box.
2. Connect to chat socket server and show how many users are on the same page or site.
3. Show Danmu (scrolling text) for live messages.
We include the 2nd and the 3rd functionality to the injection script rather than the chat box because they are very useful for the Chrome extension.
## How to develop and run locally
### Run the client locally
Remeber that the client contains two pieces, so there are two steps to run client locally.
First, run the chat box app
```
cd client/chatbox
npm install .
npm start
```
The first time you run this will be slower, because it needs to install all the packages needed. The chat box will be running on localhost:3000, but the chat box is not designed to be used by itself, instead, it must be used in an iframe. So the next thing you need to do is to run the injection script app.
```
cd client/injection-script
npm install .
npm start
```
Now you should see the client running on localhost:3210, the chatbox should also show up there.
The client is talking to the official backend by default. If you want the client to talk to your local backend, it's very easy. Instead of `npm start`, type `npm start:dev`. Then it will be talking to your localhost:8080 for websocket connections for live chat feature and localhost:8081 for ajax calls for all other purposes. So you need to have those running. Please read the next section to learn how to run backend locally.
### Run websocket server locally for live chat
```
cd server/chat-socket
npm install .
node index.js
```
### Run API backend locally
```
cd server/api
(Highly recommend that you create a Python virtual env first)
pip install -r requirements.txt
python run.py
```
## How to deploy frontend
### Build
Like mentioned before, the client has two parts - chat box and injection script. They need to be built separately.
To build the chat box.
```
cd client/chatbox
npm run build
```
To build the injection script.
```
cd client/injection-scirpt
npm run build
```
The final build is placed in the `/build` folder.
### Deploy
To use your own version of injection script, upload your `client/injection-scirpt/build/content-static` folder to your server so it's reachable as `your-website.com/build/content-static`. Then include the scripts by adding following lines to your website.
```
```
To use your own version of chat box, upload your `client/chatbox/build/content-static` folder to your server so it's reachable as `your-website.com/build/static`. You'll need to modify the injection script, specifically the iframe src to point to your own chat box, otherwise it will use the offical build of the chat box.
This doc needs update...
================================================
FILE: chatbox/.gitignore
================================================
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
================================================
FILE: chatbox/.prettierrc
================================================
{
"tabWidth": 2,
"semi": false
}
================================================
FILE: chatbox/.storybook/addons.js
================================================
import '@storybook/addon-actions/register';
import '@storybook/addon-links/register';
================================================
FILE: chatbox/.storybook/config.js
================================================
import { configure } from '@storybook/react';
function loadStories() {
require('../src/stories');
}
configure(loadStories, module);
================================================
FILE: chatbox/README.md
================================================
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
## Available Scripts
In the project directory, you can run:
### `npm start`
Runs the app in the development mode.
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
The page will reload if you make edits.
You will also see any lint errors in the console.
### `npm test`
Launches the test runner in the interactive watch mode.
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
### `npm run build`
Builds the app for production to the `build` folder.
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.
Your app is ready to be deployed!
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
### `npm run eject`
**Note: this is a one-way operation. Once you `eject`, you can’t go back!**
If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
## Learn More
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
To learn React, check out the [React documentation](https://reactjs.org/).
### Code Splitting
This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting
### Analyzing the Bundle Size
This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size
### Making a Progressive Web App
This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app
### Advanced Configuration
This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration
### Deployment
This section has moved here: https://facebook.github.io/create-react-app/docs/deployment
### `npm run build` fails to minify
This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify
================================================
FILE: chatbox/package.json
================================================
{
"name": "same-page",
"homepage": "./",
"version": "0.1.0",
"private": true,
"dependencies": {
"@material-ui/core": "^3.9.3",
"antd": "^3.16.1",
"axios": "^0.18.0",
"emoji-mart": "^2.11.0",
"fsevents": "^1.2.9",
"material-ui": "^0.20.2",
"moment": "^2.24.0",
"re-resizable": "^6.2.0",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-images-upload": "^1.2.6",
"react-intl": "^3.6.0",
"react-redux": "^6.0.1",
"react-scripts": "2.1.8",
"redux": "^4.0.1",
"rsuite": "^3.8.2",
"video.js": "^7.5.4",
"videojs-flash": "^2.2.0",
"videojs-playlist": "^4.3.1",
"videojs-youtube": "^2.6.0"
},
"scripts": {
"start:no_ssl": "react-scripts start",
"start": "export HTTPS=true; react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject-nonono": "react-scripts eject",
"storybook": "start-storybook -p 9009 -s public",
"build-storybook": "build-storybook -s public"
},
"eslintConfig": {
"extends": "react-app",
"plugins": [
"react-hooks"
],
"rules": {
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn"
}
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
],
"devDependencies": {
"@babel/core": "^7.4.3",
"@storybook/addon-actions": "^5.0.6",
"@storybook/addon-links": "^5.0.6",
"@storybook/addons": "^5.0.6",
"@storybook/react": "^5.0.6",
"babel-loader": "^8.0.5",
"eslint-config-airbnb": "^17.1.0",
"eslint-plugin-import": "^2.17.3",
"eslint-plugin-jsx-a11y": "^6.2.1",
"eslint-plugin-react": "^7.13.0",
"eslint-plugin-react-hooks": "^1.6.0"
}
}
================================================
FILE: chatbox/public/index.html
================================================
{intl.formatMessage({ id: "share.url.privacy" })}
{/* 邀请目的浏览相似内容的用户会进入该聊天室
*/} //{intl.formatMessage({ id: "keywords.of.room" })}
// {room.tags && room.tags.join(", ")} // {(!room.tags || !room.tags.length) && ( // {intl.formatMessage({ id: "no.keyword" })} // )} //
输入原始的视频或音频文件地址,比如
https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_5mb.mp4
直接输入含有视频或音频的网页地址,比如
https://music.163.com/#/song?id=640565
https://www.youtube.com/watch?v=txthoeUhyBI
component higher in the tree to provide a loading indicator or placeholder to display."+lt(c))}ja=!0,f=ia(f,c),l=s;do{switch(l.tag){case 3:l.effectTag|=2048,l.expirationTime=u,Zi(l,u=xa(l,f,u));break e;case 1:if(p=f,h=l.type,c=l.stateNode,0===(64&l.effectTag)&&("function"===typeof h.getDerivedStateFromError||null!==c&&"function"===typeof c.componentDidCatch&&(null===Ia||!Ia.has(c)))){l.effectTag|=2048,l.expirationTime=u,Zi(l,u=Sa(l,p,u));break e}}l=l.return}while(null!==l)}Ta=Ya(i);continue}o=!0,ju(y)}}break}if(Oa=!1,Ea.current=n,Ii=Li=zi=null,$o(),o)_a=null,e.finishedWork=null;else if(null!==Ta)e.finishedWork=null;else{if(null===(n=e.current.alternate)&&a("281"),_a=null,ja){if(o=e.latestPendingTime,i=e.latestSuspendedTime,u=e.latestPingedTime,0!==o&&o
)
}
let textContentClass = "sp-danmu-content-text"
if (this.props.danmu.self) {
textContentClass += " self"
// console.log(this.props.danmu);
}
textContentClass += " " + this.props.danmu.type
let content = (
)
if (this.props.danmu.img) {
content = (
)
}
return (
)
if (userCount > 0) {
iconContent = userCount
}
if (unreadMail) {
iconContent =
],
// }
const [showAvatars, setShowAvatars] = useState(spConfig.showAvatars)
const [roomType, setRoomType] = useState(spConfig.defaultChatView)
const getRoom = roomType => {
return rooms[roomType]
}
const getRoomFromId = id => {
// TODO
}
const removeUserMessage = (user, type) => {
const usersInRoom = getRoom(type)
const users = usersInRoom.map(u => {
if (u.id.toString() === user.id.toString()) {
delete u.delMessageTimeout
delete u.message
return {
...u
}
}
return u
})
setRooms({ ...rooms, [type]: users })
}
const room = getRoom(roomType)
// console.log("room")
// console.log(room)
useEffect(() => {
// not best practice, but much simpler than adding callbacks
// to socket, also socket gets re instantiate when reconnect
// Room component is never unmounted, no need to clean up
window.setUserMessage = (user, type, content) => {
const room = getRoom(type)
const users = room.map(u => {
if (u.id.toString() === user.id.toString()) {
// foundUser = true
if (u.delMessageTimeout) {
clearTimeout(u.delMessageTimeout)
}
return {
...u,
message: content.value || content.title || content.url,
delMessageTimeout: setTimeout(() => {
removeUserMessage(user, type)
}, MSG_TIMEOUT)
}
}
return u
})
setRooms({ ...rooms, [type]: users })
}
window.leftRoom = roomId => {
if (!roomId) {
setRooms({})
} else {
// TODO
// backend should return room type etc..
// setRooms({ ...rooms, [type]: [] })
}
}
window.setUsersInRoom = data => {
const res = {}
Object.keys(data).forEach(roomId => {
const room = data[roomId]
if (room.users) {
res[room.type] = room.users
}
})
setRooms({ ...rooms, ...res })
}
window.addUserToRoom = (type, user) => {
const room = getRoom(type)
if (room) {
const existingUser = room.filter(u => {
return u.id === user.id
})
if (existingUser.length) {
return
}
setRooms({ ...rooms, [type]: [...room, user] })
} else {
console.error(
`Failed to add user to room, room type ${type} not exist`
)
}
}
window.removeUserFromRoom = (type, user) => {
const room = getRoom(type)
if (room) {
// const newRoom =
// room.push(user)
const users = room.filter(u => {
return u.id !== user.id
})
setRooms({ ...rooms, [type]: [...users] })
} else {
console.error(
`Faileed to remove user from room, room type ${type} not exist`
)
}
}
}, [rooms])
useEffect(() => {
storageManager.get("showAvatars", showAvatars => {
if (showAvatars !== null) {
setShowAvatars(showAvatars)
}
})
storageManager.addEventListener("showAvatars", showAvatars => {
setShowAvatars(showAvatars)
})
window.addEventListener(
"message",
e => {
if (!e || !e.data) return
if (e.data.type === "sp-change-chat-view") {
const chatView = e.data.data
setRoomType(chatView)
}
},
false
)
}, [])
return (