|
- const State = {
- websocket: null,
- posts: [],
- users: [],
- }
- const autoFocus = (vnode) => {
- vnode.dom.focus()
- }
- const scrollIntoView = (vnode) => {
- vnode.dom.scrollIntoView()
- }
- const prettyTime = (ts) => {
- return ts.slice(11, 19)
- }
- const Login = {
- sendLogin: (e) => {
- e.preventDefault()
- const username = e.target.username.value
- localStorage.username = username
- connect(username)
- },
- sendLogout: (e) => {
- localStorage.removeItem('username')
- State.websocket.send(JSON.stringify({action: 'logout'}))
- State.posts = []
- },
- view() {
- return m('.login',
- m('form', {onsubmit: Login.sendLogin},
- m('input', {oncreate: autoFocus, name: 'username', autocomplete: 'off'}),
- m('button', 'Login'),
- ),
- State.kind === 'error' && m('.error', State.info),
- )
- },
- }
- const Chat = {
- sendPost: (e) => {
- e.preventDefault()
- const field = e.target.text
- State.websocket.send(JSON.stringify({action: 'post', text: field.value}))
- field.value = ''
- },
- view() {
- return m('.chat',
- m('.posts',
- State.posts.map(post => m('.post', {oncreate: scrollIntoView},
- m('.ts', prettyTime(post.ts)),
- m('.source', post.source),
- m('.text', post.text),
- )),
- ),
- m('form.actions', {onsubmit: Chat.sendPost},
- m('input', {oncreate: autoFocus, name: 'text', autocomplete: 'off'}),
- m('button', 'Send'),
- ),
- m('.users',
- m('button', {onclick: Login.sendLogout}, 'Logout'),
- m('ul.user-list', State.users.map(username => m('li', username)))
- ),
- )
- },
- }
- const Main = {
- view() {
- const connected = State.websocket && State.websocket.readyState === 1
- return connected ? m(Chat) : m(Login)
- },
- }
- m.mount(document.body, Main)
-
- const connect = (username) => {
- State.websocket = new WebSocket(wsUrl)
- State.websocket.onopen = (e) => {
- State.websocket.send(JSON.stringify({action: 'login', username}))
- }
- State.websocket.onmessage = (e) => {
- const message = JSON.parse(e.data)
- if(message.kind === 'post') {
- State.posts.push(message)
- }
- else if(message.kind === 'update') {
- Object.assign(State, message)
- if(message.info) {
- State.posts.push({ts: message.ts, source: '~', text: message.info})
- }
- }
- else if(message.kind === 'error') {
- Object.assign(State, message)
- Login.sendLogout()
- }
- else {
- console.log(message)
- }
- m.redraw()
- }
- State.websocket.onclose = (e) => {
- if(!e.wasClean) {
- setTimeout(connect, 100, username)
- }
- m.redraw()
- }
- }
- const wsUrl = location.toString().replace('http', 'ws')
- if(localStorage.username) {
- connect(localStorage.username)
- }
|