| .post .text p:first-child { | .post .text p:first-child { | ||||
| display: inline; | display: inline; | ||||
| } | } | ||||
| .badge { | |||||
| display: inline-flex; | |||||
| justify-content: center; | |||||
| align-items: center; | |||||
| color: white; | |||||
| background-color: silver; | |||||
| border: none; | |||||
| border-radius: 5px; | |||||
| font-family: verdana; | |||||
| font-size: xx-small; | |||||
| font-weight: bold; | |||||
| min-width: 15px; | |||||
| padding: 0 3px; | |||||
| margin: 3px 3px; | |||||
| line-height: 1.5; | |||||
| } | |||||
| .badge.on { | |||||
| background-color: crimson; | |||||
| } |
| } | } | ||||
| const ChatConfig = { | const ChatConfig = { | ||||
| isOn: false, | isOn: false, | ||||
| toggle() { | |||||
| ChatConfig.isOn = !ChatConfig.isOn | |||||
| }, | |||||
| view() { | view() { | ||||
| return m('button', {onclick: () => {ChatConfig.isOn = !ChatConfig.isOn}}, 'chat') | |||||
| } | |||||
| const on = Chat.unseenCount ? '.on' : '' | |||||
| return m('button', {onclick: this.toggle}, 'chat ', | |||||
| m('.badge' + on, Chat.unseenCount), | |||||
| ) | |||||
| }, | |||||
| } | } | ||||
| const Chat = { | const Chat = { | ||||
| posts: [], | posts: [], | ||||
| oncreate() { | |||||
| listen('post', ({detail}) => { | |||||
| this.posts.push(detail) | |||||
| m.redraw() | |||||
| }) | |||||
| listen('logout', () => { | |||||
| this.posts = [] | |||||
| }) | |||||
| marked.setOptions({ | |||||
| breaks: true, | |||||
| }) | |||||
| unseenCount: 0, | |||||
| originalTitle: 'pico.chat', | |||||
| onupdate: () => { | |||||
| if(document.hasFocus() && ChatConfig.isOn) { | |||||
| Chat.unseenCount = 0 | |||||
| } | |||||
| const extra = Chat.unseenCount ? ` (${Chat.unseenCount})` : `` | |||||
| document.title = Chat.originalTitle + extra | |||||
| }, | }, | ||||
| view() { | view() { | ||||
| return ChatConfig.isOn ? [ | return ChatConfig.isOn ? [ | ||||
| m('.not-chat', {onclick: () => ChatConfig.isOn = false}), | m('.not-chat', {onclick: () => ChatConfig.isOn = false}), | ||||
| m('.chat', | m('.chat', | ||||
| m('.posts', this.posts.map(post => m(Post, {post}))), | |||||
| m('.posts', Chat.posts.map(post => m(Post, {post}))), | |||||
| m(TextBox), | m(TextBox), | ||||
| ) | ) | ||||
| ] : null | ] : null | ||||
| }, | }, | ||||
| } | } | ||||
| addEventListener('focus', m.redraw) | |||||
| addEventListener('post', ({detail}) => { | |||||
| Chat.posts.push(detail) | |||||
| Chat.unseenCount += !(document.hasFocus() && ChatConfig.isOn) | |||||
| m.redraw() | |||||
| }) | |||||
| addEventListener('logout', () => { | |||||
| Chat.posts = [] | |||||
| Chat.unseenCount = 0 | |||||
| }) | |||||
| marked.setOptions({ | |||||
| breaks: true, | |||||
| }) |
| username: null, | username: null, | ||||
| websocket: null, | websocket: null, | ||||
| online: [], | online: [], | ||||
| messages: [], | |||||
| get isConnected() { | get isConnected() { | ||||
| return State.websocket && State.websocket.readyState === 1 | return State.websocket && State.websocket.readyState === 1 | ||||
| }, | }, | ||||
| } | } | ||||
| listen('login', ({detail}) => { | listen('login', ({detail}) => { | ||||
| State.username = detail.value | State.username = detail.value | ||||
| State.messages = [] | |||||
| }) | }) | ||||
| listen('logout', ({detail}) => { | listen('logout', ({detail}) => { | ||||
| State.online = [] | State.online = [] | ||||
| Object.assign(State, detail) | Object.assign(State, detail) | ||||
| }) | }) | ||||
| const doNotLog = new Set(['login', 'state', 'post', 'peerInfo', 'join', 'leave']) | const doNotLog = new Set(['login', 'state', 'post', 'peerInfo', 'join', 'leave']) | ||||
| /* | |||||
| * | |||||
| * ALERTS | |||||
| * | |||||
| */ | |||||
| State.unseen = 0 | |||||
| listen('beep', () => {State.unseen += !document.hasFocus(); updateTitle()}) | |||||
| listen('focus', () => {State.unseen = 0; updateTitle()}) | |||||
| const updateTitle = () => { | |||||
| document.title = location.href.split('//')[1] + (State.unseen ? ` (${State.unseen})` : ``) | |||||
| } | |||||
| /* | /* | ||||
| * | * | ||||
| * UTILS | * UTILS | ||||
| ), | ), | ||||
| State.isConnected ? [ | State.isConnected ? [ | ||||
| m('button', {onclick: Base.sendLogout}, 'pick name'), | m('button', {onclick: Base.sendLogout}, 'pick name'), | ||||
| m('button', {onclick: () => navigator.clipboard.writeText(location)}, 'copy url'), | |||||
| ] : null, | ] : null, | ||||
| State.isConnected ? m(VideoConfig) : null, | State.isConnected ? m(VideoConfig) : null, | ||||
| State.isConnected ? m(ChatConfig) : null, | State.isConnected ? m(ChatConfig) : null, |