diff --git a/public/client.js b/public/client.js index 76f6aae..d6f0e56 100644 --- a/public/client.js +++ b/public/client.js @@ -9,7 +9,16 @@ export default class ClientList { const host = window.location.host this.clientlist = [] this.element = List({ - classList: ['userlist'], + style: { + position: 'fixed', + top: '0', + right: '0', + display: 'flex', + flexDirection: 'wrap', + alignItems: 'center', + listStyle: 'none', + padding: '0 1rem', + } }) document.body.appendChild(this.element) @@ -118,12 +127,12 @@ export default class ClientList { await webrtc.setLocalDescription(offer) this.clientlist.push({ id: data.id, name: data.name, webrtc, channels }) websocket.send(JSON.stringify({ type: 'offer', id: data.id, offer })) - this.add(data) + this.push(data) return } if (data.type === 'push') { console.debug('新上线客户端:', data) - return this.add(data) + return this.push(data) } if (data.type === 'pull') { console.debug('移除客户端:', data) @@ -165,46 +174,9 @@ export default class ClientList { } this.websocket = linkStart() - // 插入css样式 - const style = document.createElement('style') - style.textContent = ` - ul.userlist { - position: fixed; - top: 0; - right: 0; - display: flex; - flex-direction: wrap; - align-items: center; - list-style: none; - padding: 0 1rem; - } - ul.userlist li { - cursor: pointer; - display: flex; - flex-direction: column; - align-items: center; - font-size: 12px; - border-radius: 8px; - } - ul.userlist li:first-child { - color: #2e7d3c; - } - ul.userlist li:hover { - background-color: #eee; - } - ul.userlist > * { - margin: 0 8px; - } - ul.userlist li img { - width: 32px; - height: 32px; - border-radius: 50%; - } - ` - document.head.appendChild(style) // 也插入自己的信息 const avatar = localStorage.getItem('avatar') - this.add({ id: 'self', name: username, avatar }) + this.push({ id: 'self', name: username, avatar }, true) } getAvatar(id) { } setAvatar(user) { @@ -222,9 +194,19 @@ export default class ClientList { setChannel(name, option) { this.channels[name] = option } - add(item) { + // 新上线客户端 + push(item, self=false) { this.element.appendChild(ListItem({ id: item.id, + style: { + margin: '0 8px', + cursor: 'pointer', + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + fontSize: '12px', + borderRadius: '8px', + }, onclick: event => document.body.appendChild(Dialog({ children: [ Avatar({ @@ -235,10 +217,10 @@ export default class ClientList { borderRadius: '8px', margin: '0 auto', display: 'block', - cursor: 'pointer' + cursor: 'pointer', }, onclick: event => { - console.log('点击上传图片') + if (!self) return console.log('只能修改自己的头像') const input = document.createElement('input') input.type = 'file' input.accept = 'image/*' @@ -266,6 +248,7 @@ export default class ClientList { position: 'absolute', bottom: '-2px', }, + readOnly: !self, // 如果不是自己, 则不可编辑 value: item.name ?? item.id, type: 'text', placeholder: '请设置你的昵称', @@ -278,7 +261,13 @@ export default class ClientList { })), children: [ Avatar({ - src: item.avatar ?? '/favicon.ico' + src: item.avatar ?? '/favicon.ico', + style: { + width: '32px', + height: '32px', + borderRadius: '50%', + cursor: 'pointer', + }, }), Span({ textContent: item.name ?? item.id diff --git a/public/weigets.js b/public/weigets.js index 24339aa..af05b60 100644 --- a/public/weigets.js +++ b/public/weigets.js @@ -1,10 +1,11 @@ -export function createElement({ innerText, textContent, onclick, onchange, onkeydown, children = [], dataset, style, classList = [], ...attributes }, tagName = 'div') { +export function createElement({ innerText, textContent, onclick, onchange, onkeydown, readOnly, children = [], dataset, style, classList = [], ...attributes }, tagName = 'div') { const element = document.createElement(tagName) for (const key in attributes) element.setAttribute(key, attributes[key]) if (style) Object.assign(element.style, style) if (classList.length) element.classList.add(...classList) if (textContent) element.textContent = textContent if (innerText) element.innerText = innerText + if (readOnly) element.readOnly = readOnly if (onkeydown) element.onkeydown = onkeydown if (onchange) element.onchange = onchange if (onclick) element.onclick = onclick @@ -55,6 +56,8 @@ export function Dialog(options) { transition: 'all 0.5s' }, onclick: async event => { + // 判断必须是点击自身, 而不是子元素 + if (event.target !== event.currentTarget) return await event.target.animate([{ opacity: 1 }, { opacity: 0 }], { duration: 100 }).finished await event.target.remove() },