right: 0; | right: 0; | ||||
top: 0; | top: 0; | ||||
} | } | ||||
.not-chat { | |||||
z-index: 999; | |||||
background-color: rgba(0, 0, 0, 0.8); | |||||
position: fixed; | |||||
height: 100vh; | |||||
width: 100vw; | |||||
right: 0; | |||||
top: 0; | |||||
} | |||||
.chat .actions { | .chat .actions { | ||||
display: grid; | display: grid; | ||||
grid-template-columns: 1fr auto; | grid-template-columns: 1fr auto; | ||||
margin: 3px 3px; | margin: 3px 3px; | ||||
line-height: 1.5; | line-height: 1.5; | ||||
} | } | ||||
.badge.on { | |||||
.badge.hot { | |||||
background-color: crimson; | background-color: crimson; | ||||
} | } |
} | } | ||||
} | } | ||||
const ChatConfig = { | const ChatConfig = { | ||||
isOn: false, | |||||
toggle() { | |||||
ChatConfig.isOn = !ChatConfig.isOn | |||||
}, | |||||
view() { | view() { | ||||
const on = Chat.unseenCount ? '.on' : '' | |||||
return m('button', {onclick: this.toggle}, 'chat ', | |||||
m('.badge' + on, Chat.unseenCount), | |||||
const onclick = () => {Chat.isOn = !Chat.isOn} | |||||
const hot = Chat.unseenCount ? '.hot' : '' | |||||
return m('button', {onclick}, 'chat ', | |||||
m('.badge' + hot, Chat.unseenCount), | |||||
) | ) | ||||
}, | }, | ||||
} | } | ||||
unseenCount: 0, | unseenCount: 0, | ||||
originalTitle: 'pico.chat', | originalTitle: 'pico.chat', | ||||
onupdate: () => { | onupdate: () => { | ||||
if(document.hasFocus() && ChatConfig.isOn) { | |||||
if(document.hasFocus() && Chat.isOn) { | |||||
Chat.unseenCount = 0 | Chat.unseenCount = 0 | ||||
textbox.focus() | |||||
} | } | ||||
const extra = Chat.unseenCount ? ` (${Chat.unseenCount})` : `` | const extra = Chat.unseenCount ? ` (${Chat.unseenCount})` : `` | ||||
document.title = Chat.originalTitle + extra | document.title = Chat.originalTitle + extra | ||||
}, | }, | ||||
view() { | view() { | ||||
return ChatConfig.isOn ? [ | |||||
m('.not-chat', {onclick: () => ChatConfig.isOn = false}), | |||||
m('.chat', | |||||
m('.posts', Chat.posts.map(post => m(Post, {post}))), | |||||
m(TextBox), | |||||
) | |||||
] : null | |||||
return m('.chat', | |||||
m('.posts', Chat.posts.map(post => m(Post, {post}))), | |||||
m(TextBox), | |||||
) | |||||
}, | }, | ||||
} | } | ||||
addEventListener('focus', m.redraw) | addEventListener('focus', m.redraw) |
const VolumeMap = { | const VolumeMap = { | ||||
isOn: false, | |||||
size: 200, | size: 200, | ||||
positions: new Map(), | positions: new Map(), | ||||
toggle() { | |||||
VolumeMap.isOn = !VolumeMap.isOn | |||||
}, | |||||
onremove() { | onremove() { | ||||
VolumeMap.positions.clear() | VolumeMap.positions.clear() | ||||
}, | }, |
* BASE | * BASE | ||||
* | * | ||||
*/ | */ | ||||
const Shadow = { | |||||
oncreate({dom, attrs}) { | |||||
dom.listener = () => attrs.app.isOn = !attrs.app.isOn | |||||
addEventListener(attrs.key, dom.listener) | |||||
}, | |||||
onremove({dom, attrs}) { | |||||
removeEventListener(attrs.key, dom.listener) | |||||
}, | |||||
view({attrs}) { | |||||
const style = { | |||||
zIndex: 999, | |||||
backgroundColor: 'rgba(0, 0, 0, 0.8)', | |||||
visibility: attrs.app.isOn ? 'unset' : 'hidden', | |||||
position: 'fixed', | |||||
height: '100vh', | |||||
width: '100vw', | |||||
right: 0, | |||||
top: 0, | |||||
} | |||||
const onclick = ({target: {classList}}) => { | |||||
classList.contains('shadow') && signal({kind: attrs.key}) | |||||
} | |||||
return m('.shadow', {style, onclick}, m(attrs.app)) | |||||
}, | |||||
} | |||||
const Settings = { | const Settings = { | ||||
get(key) { | get(key) { | ||||
try { | try { | ||||
m('button', {onclick: Base.sendLogout}, 'settings'), | m('button', {onclick: Base.sendLogout}, 'settings'), | ||||
m(VideoConfig), | m(VideoConfig), | ||||
m(ChatConfig), | m(ChatConfig), | ||||
m('button', {onclick: VolumeMap.toggle}, 'volume'), | |||||
] : [ | ] : [ | ||||
m('form.login', | m('form.login', | ||||
{onsubmit: Base.sendLogin}, | {onsubmit: Base.sendLogin}, | ||||
m('span.error', State.info), | m('span.error', State.info), | ||||
), | ), | ||||
State.isConnected ? [ | State.isConnected ? [ | ||||
m(StreamContainer), | |||||
m(Chat), | |||||
params.get('map') === 'true' ? m(VolumeMap) : null, | |||||
m(StreamContainer, {key: 'lolo'}), | |||||
m(Shadow, {key: 'chat-shadow', app: Chat}), | |||||
m(Shadow, {key: 'map-shadow', app: VolumeMap}), | |||||
] : m(Settings), | ] : m(Settings), | ||||
) | ) | ||||
}, | }, |