From 1277f208f78a7a1baf92ea082f18571d7ed07350 Mon Sep 17 00:00:00 2001 From: MoonLeeeaf <150461955+MoonLeeeaf@users.noreply.github.com> Date: Sun, 30 Mar 2025 12:17:48 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E5=B9=B6=E5=85=A5=E5=8E=9F=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E7=9A=84=E5=8F=B2=E5=B1=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/client-side.js | 19 ++ client/custom-elements-index.js | 164 ++++++++++++ client/global-appconfig.js | 13 + client/icon.ico | Bin 0 -> 29488 bytes client/index.html | 448 ++++++++++++++++++++++++++++++++ client/signin.html | 62 +++++ client/style-shared.css | 87 +++++++ client/ui-controller-index.js | 190 ++++++++++++++ client/ui-controller-shared.js | 41 +++ client/utils-shared.js | 30 +++ 10 files changed, 1054 insertions(+) create mode 100644 client/client-side.js create mode 100644 client/custom-elements-index.js create mode 100644 client/global-appconfig.js create mode 100644 client/icon.ico create mode 100644 client/index.html create mode 100644 client/signin.html create mode 100644 client/style-shared.css create mode 100644 client/ui-controller-index.js create mode 100644 client/ui-controller-shared.js create mode 100644 client/utils-shared.js diff --git a/client/client-side.js b/client/client-side.js new file mode 100644 index 0000000..3130a0f --- /dev/null +++ b/client/client-side.js @@ -0,0 +1,19 @@ +/* + * ©2024 The LingChair Project + * + * Make a more colorful world... + * + * License - Apache License 2.0 + * Author - @MoonLeeeaf + * Organization - @LingChair + */ + +class Client { + +} + +class ClientUser { + +} + + diff --git a/client/custom-elements-index.js b/client/custom-elements-index.js new file mode 100644 index 0000000..72e213e --- /dev/null +++ b/client/custom-elements-index.js @@ -0,0 +1,164 @@ +/* + * ©2024 The LingChair Project + * + * Make a more colorful world... + * + * License - Apache License 2.0 + * Author - @MoonLeeeaf + * Organization - @LingChair + */ + +class MessageNormal extends HTMLElement { + static observedAttributes = ['avatar', 'sender-name', 'sender-id', 'msg', 'direction'] + constructor() { + super() + + const shadow = this.attachShadow({ mode: "open" }) + } + connectedCallback() { + const shadow = this.shadowRoot + + shadow.appendChild($('#message-normal-template').get(0).content.cloneNode(true)) + + $(shadow).find('#sender-name-left').hide() + + this.update() + } + attributeChangedCallback(_name, _oldValue, _newValue) { + this.update() + } + update() { + const shadow = this.shadowRoot + + // 消息视图的的左右方向 + let isRightDirection = this.getAttribute('direction') == 'right' + $(shadow).find('#_direction_1').css('justify-content', isRightDirection ? 'flex-end' : 'flex-start') + $(shadow).find('#_direction_2').css('justify-content', isRightDirection ? 'flex-end' : 'flex-start') + + $(shadow).find('#_direction_3').css('align-self', isRightDirection ? 'flex-end' : 'flex-start') + $(shadow).find('#_direction_3').css('margin-left', isRightDirection ? '' : '55px') + $(shadow).find('#_direction_3').css('margin-right', isRightDirection ? '55px' : '') + + $(shadow).find('#sender-name-left')[isRightDirection ? 'show' : 'hide']() + $(shadow).find('#sender-name-right')[isRightDirection ? 'hide' : 'show']() + + // 头像 + let avatar = $(shadow).find('#avatar') + this.hasAttribute('avatar') ? avatar.attr('src', this.getAttribute('avatar')) : avatar.text((this.getAttribute('sender-name') || '').substring(0, 1)) + + // 发送者 + $(shadow).find('#sender-name-left').text(this.getAttribute('sender-name')) + $(shadow).find('#sender-name-right').text(this.getAttribute('sender-name')) + $(shadow).find('#sender-id').text(this.getAttribute('sender-id')) + + // 消息 + this.hasAttribute('msg') && $(shadow).find('#msg').text(this.getAttribute('msg')) + } +} + +class MessageSystem extends HTMLElement { + constructor() { + super() + + const shadow = this.attachShadow({ mode: "open" }) + } + connectedCallback() { + const shadow = this.shadowRoot + shadow.appendChild($('#message-system-template').get(0).content.cloneNode(true)) + } +} + +class MessageHolder extends HTMLElement { + constructor() { + super() + + const shadow = this.attachShadow({ mode: "open" }) + } + connectedCallback() { + const shadow = this.shadowRoot + shadow.appendChild($('#message-holder-template').get(0).content.cloneNode(true)) + } + addMessage({ senderId = '', senderName = '', msg = '', avatar, direction = 'left' }, atStart) { + const v = new MessageNormal() + $(v).attr('sender-id', senderId).attr('sender-name', senderName).attr('avatar', avatar).attr('direction', direction).text(msg) + $(this)[atStart ? 'prepend' : 'append'](v) + } + addSystemMessage(msg, atStart) { + const v = new MessageSystem() + $(v).text(msg) + $(this)[atStart ? 'prepend' : 'append'](v) + } + getMessages(withSystemMessage) { + let ls = [] + $(this).find('message-normal' + withSystemMessage ? ', message-system' : '').each((_i, e) => { + let a = $(e) + ls.push({ + senderName: a.attr('sender-name'), + avatar: a.attr('avatar'), + senderId: a.attr('sender-id'), + direction: a.attr('direction'), + }) + }) + } +} + +customElements.define('message-normal', MessageNormal) +customElements.define('message-system', MessageSystem) +customElements.define('message-holder', MessageHolder) + +customElements.define('main-navigation-item', class extends mdui.NavigationRailItem { + static observedAttributes = ['img', 'id', 'text'] + constructor() { + super() + + const shadow = this.attachShadow({ mode: "open" }) + } + connectedCallback() { + // 现在这是 mdui-navigation-rail-item, 不应该加到shadow而是自身 + // 害得我修了好久 + + this.appendChild($('#main-navigation-item-template').get(0).content.cloneNode(true)) + + const self = this + const avatar = $(this).find('#avatar') + const avatarImg = $(this).find('#img') + avatarImg.bind('error', () => { + avatar.text((self.getAttribute('text') || '').substring(0, 1)) + }) + + this.myUpdate() + super.connectedCallback() + } + attributeChangedCallback(_name, _oldValue, _newValue) { + this.myUpdate() + super.attributeChangedCallback() + } + myUpdate() { + this.hasAttribute('img') ? $(this).find('#img').attr('src', this.getAttribute('img')) : $(this).find('#avatar').text((this.getAttribute('text') || '').substring(0, 1)) + $(this).find('#tip').attr('content', this.getAttribute('text')) + this.hasAttribute('id') && $(this).attr('value', this.getAttribute('id')) + } +}) + +customElements.define('message-img', class extends HTMLElement { + constructor() { + super() + } + connectedCallback() { + let e = new Image() + e.style.maxWidth = "100%" + e.style.maxHeight = "90%" + e.style.marginTop = "13px" + e.style.borderRadius = "var(--mdui-shape-corner-medium)" + e.src = $(this).attr('src') + e.alt = $(this).attr('alt') + e.onerror = () => { + $(this).html(`
`) + $(this).attr('alt', '图像损坏') + } + e.onclick = () => { + openImageViewer($(this).attr('src')) + } + this.appendChild(e) + } +}) diff --git a/client/global-appconfig.js b/client/global-appconfig.js new file mode 100644 index 0000000..be8c975 --- /dev/null +++ b/client/global-appconfig.js @@ -0,0 +1,13 @@ +/* + * ©2024 The LingChair Project + * + * Make a more colorful world... + * + * License - Apache License 2.0 + * Author - @MoonLeeeaf + * Organization - @LingChair + */ + +fetch('client_config.json').then((re) => re.json()).then((config) => { + +}) diff --git a/client/icon.ico b/client/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..8677e11738c87fe9d29ce57d150663b36637234f GIT binary patch literal 29488 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

x>t0*LRBWY;mk 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 mC(dQF=HfT+O%)nkD)&xqUK9 + + + + + + + + + + + + + + + + + + + + + + TheWhiteSilk + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ + + + + + + + + + - + + + + 详细列表 + + + + + 最近 + 联系人 + 群聊 + + + + + + + + 关于 + + + + + + + + + + + + + + 关闭 + + + + + + + +
+ + +
+ LingChair +
+ + Nightly +
+ + 在 GitHub 查看源码 + +
+
+
+
+ + + + + + + + + + + +
+ + + + + + + 主面板 + + + 院审 +
+
+ + + + + 资料 + + + 设置 + + + + +
+ + + 加载更多 +
+ + 我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神 + + 启动 + + 我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神 + + 原神 被 测试 踢出了群聊 + + 满月姐姐满月姐姐满月姐姐满月姐姐满月姐姐满月姐姐满月姐姐满月姐姐满月姐姐满月姐姐满月姐姐满月姐姐满月姐姐满月姐姐满月姐姐满月姐姐满月姐姐满月姐姐满月姐姐满月姐姐满月姐姐 + + 启动 + 阿弥诺斯 + + 我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神我要玩原神 + + 我要玩原神
+ +
+ 我要玩院审😭👊
+ +
+
+
+ + + + + + + + + + + 插入图片 + + + 插入音频 + + + 插入文件 + + + 插入链接 + + + + + 插入名片 + + + + + 展开输入框 + + + + + +
+
+ + + + + + + + + \ No newline at end of file diff --git a/client/signin.html b/client/signin.html new file mode 100644 index 0000000..4dcf9c1 --- /dev/null +++ b/client/signin.html @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + 登录到 铃之椅 + + + + + + + +
+

登录到 铃之椅

+ + + + +
+ 登录账号 +
+
+ 注册账号 +
+
+ 游客登录 +
+
+ ©2024 满月叶 + + + + + + + + \ No newline at end of file diff --git a/client/style-shared.css b/client/style-shared.css new file mode 100644 index 0000000..9c3f342 --- /dev/null +++ b/client/style-shared.css @@ -0,0 +1,87 @@ +/* + * ©2024 The LingChair Project + * + * Make a more colorful world... + * + * License - Apache License 2.0 + * Author - @MoonLeeeaf + * Organization - @LingChair + */ + +/* 滑条*/ +.no-scroll-bar::-webkit-scrollbar { + width: 0px !important; +} + +/* https://blog.csdn.net/qq_39347364/article/details/111996581*/ +*::-webkit-scrollbar { + width: 7px; + height: 10px; +} + +*::-webkit-scrollbar-track { + width: 6px; + background: rgba(#101F1C, 0.1); + -webkit-border-radius: 2em; + -moz-border-radius: 2em; + border-radius: 2em; +} + +*::-webkit-scrollbar-thumb { + background-color: rgba(144, 147, 153, .5); + background-clip: padding-box; + min-height: 28px; + -webkit-border-radius: 2em; + -moz-border-radius: 2em; + border-radius: 2em; + transition: background-color .3s; + cursor: pointer; +} + +*::-webkit-scrollbar-thumb:hover { + background-color: rgba(144, 147, 153, .3); +} + +/* 使用系统字体 在部分系统表现很好*/ +/* 我们至今仍未能知道桌面端浏览器字体的秘密*/ +*:not(.material-icons, .mdui-icon, mdui-icon, .fa, .google-symbols) { + font-family: -apple-system, system-ui, -webkit-system-font !important; +} + +body { + display: flex; + margin: 0 0 0 0; +} + +/* 防止小尺寸图片模糊*/ +* { + image-rendering: -moz-crisp-edges; + image-rendering: -o-crisp-edges; + image-rendering: -webkit-optimize-contrast; + image-rendering: crisp-edges; + -ms-interpolation-mode: nearest-neighbor; +} + +/* 与窗口同大小*/ +.size-as-window { + width: var(--window-width); + height: var(--window-height); +} + +/* Flex - 铺满*/ +.fill-width { + width: 100%; +} + +.fill-height { + height: 100%; +} + +/* 链接使用主题色*/ +a { + color: rgb(var(--mdui-color-primary)); +} + +.contents-only { + display: contents; +} \ No newline at end of file diff --git a/client/ui-controller-index.js b/client/ui-controller-index.js new file mode 100644 index 0000000..ac10b0b --- /dev/null +++ b/client/ui-controller-index.js @@ -0,0 +1,190 @@ +/* + * ©2024 The LingChair Project + * + * Make a more colorful world... + * + * License - Apache License 2.0 + * Author - @MoonLeeeaf + * Organization - @LingChair + */ + +/** + * ======================================================== + * 侧边导航栏列表 + * ======================================================== + */ + +// 按钮:查看详细列表 +$('#switch-navigation-list-info-menuicon').parent().click(() => { + let list = $('#nav-list-information-dialog > mdui-list').empty() + let selected = $('#switch-navigation-list-menu').get(0).value + $('#main-navigation-list-' + selected + " > main-navigation-item").each((_i, e) => { + let i = $.parseHTML(``) + let a = $.parseHTML(``) + let img = new Image() + img.style.cssText = `width: 100%; height: 100%; object-fit: contain;` + img.src = e.getAttribute('img') + img.onerror = () => { + $(a).text((e.getAttribute('text') || '').substring(0, 1)) + } + $(a).append(img) + $(i).append(e.getAttribute('text')) + $(i).append(a) + list.append(i) + }) + $('#nav-list-information-dialog').attr('headline', (function () { + let t + switch (selected + '') { + case "1": + t = '最近' + break; + case "2": + t = '联系人' + break; + case "3": + t = '群组' + break; + } + return t + })()) + $('#nav-list-information-dialog').attr('open', true) +}) + +// 切换列表选项 +let lastValue = $('#switch-navigation-list-menu').get(0).value +$('#switch-navigation-list-menu').on('change', (e) => { + // 当前选择的值 + let value = e.target.value + + // 特殊:详细列表 + if (value == 0) { + // 选回原来的选项 + e.target.value = lastValue + value = lastValue + $('#switch-navigation-list-menu > mdui-menu-item[value=' + value + ']').get(0).selected = true + $('#switch-navigation-list-menu > mdui-menu-item[value=0]').get(0).selected = false + // 错误示范: 在这里写点击事件 + } + + // 禁止空选择 + if (value == null) { + e.target.value = lastValue + value = lastValue + $('#switch-navigation-list-menu > mdui-menu-item[value=' + value + ']').get(0).selected = true + } + + // 显示指定的列表 + $('#main-navigation-list-1').hide() + $('#main-navigation-list-2').hide() + $('#main-navigation-list-3').hide() + $('#main-navigation-list-' + value).show() + + // 修改图标 + let icon = (function () { + let ico + switch (value + '') { + case "1": + ico = 'watch_later--outlined' + break; + case "2": + ico = 'contacts--outlined' + break; + case "3": + ico = 'group--outlined' + break; + } + return ico + })() + $('#switch-navigation-list-button').attr('icon', icon) + $('#switch-navigation-list-info-menuicon').attr('name', icon) + + // 更新最后的值用以防止空选择 + lastValue = value +}) + +// 最开始只选择 最近, 隐藏其他列表 +$('#main-navigation-list-2').hide() +$('#main-navigation-list-3').hide() + +// 子项目被点击时 +$('mdui-navigation-rail').on('click', (event) => { + let e = event.target + let tagName = e.tagName.toLowerCase() + while (tagName != 'main-navigation-item') { + e = e.parentNode + tagName = (e.tagName || 'mdui-navigation-rail').toLowerCase() + if (tagName == 'mdui-navigation-rail') return + } + // 获取到Item + +}) + +/** + * ======================================================== + * 输入框与消息编辑 + * ======================================================== + */ + +windowOnResizingCallbacks.push((w, h) => { + $('#input_message').width(w - ($('mdui-navigation-rail').width() + $('#send_message').width() * 2 + 100)) +}) + +/** + * ======================================================== + * 消息列表 + * ======================================================== + */ + +function scrollMessageHolderToBottom() { + window.scrollBy({ + top: 1145141919810, + behavior: "smooth", + }) +} + +/** + * ======================================================== + * 图片查看对话框 + * ======================================================== + */ + +function openImageViewer(src) { + $('#image-viewer-dialog-inner').empty() + + let e = new Image() + e.src = src + e.onerror = () => { + $('#image-viewer-dialog-inner').empty() + $('#image-viewer-dialog-inner').append($.parseHTML(``)) + } + $('#image-viewer-dialog-inner').append(e) + + e.onload = () => $('#image-viewer-dialog-inner').get(0).setTransform({ + scale: 0.6, + x: $(window).width() / 2 - (e.width / 4), + y: $(window).height() / 2 - (e.height / 3), + }) + $('#image-viewer-dialog').get(0).open = true +} + +/** + * ======================================================== + * 下载 + * ======================================================== + */ + +async function downloadFromUrl(src) { + let re = await fetch(src) + let blob = await re.blob() + let url = URL.createObjectURL(blob) + $('#download-helper').attr('download', url).attr('href', url).get(0).click() + setTimeout(() => URL.revokeObjectURL(url), 10000) +} + +/** + * ======================================================== + * 杂项 + * ======================================================== + */ + +// mdui.setColorScheme("#FFB4AA") diff --git a/client/ui-controller-shared.js b/client/ui-controller-shared.js new file mode 100644 index 0000000..4f6ecb1 --- /dev/null +++ b/client/ui-controller-shared.js @@ -0,0 +1,41 @@ +/* + * ©2024 The LingChair Project + * + * Make a more colorful world... + * + * License - Apache License 2.0 + * Author - @MoonLeeeaf + * Organization - @LingChair + */ + +/** + * ======================================================== + * 窗口大小 + * ======================================================== + */ + +// 在窗口加载完毕后会将所有页面大小变化的回调都调用一次 +const windowOnResizingCallbacks = [] + +function updateWindowSize() { + document.body.style.setProperty('--window-width', `${window.innerWidth}px`) + document.body.style.setProperty('--window-height', `${window.innerHeight}px`) + windowOnResizingCallbacks.forEach((v) => v(window.innerWidth, window.innerHeight)) +} +window.addEventListener('resize', updateWindowSize) +// 初步确定(值有偏差) +$(() => updateWindowSize()) +// 完全确定(值已经确定) +window.addEventListener('load', updateWindowSize) + +/** + * ======================================================== + * Shadow 元素辅助代码 + * ======================================================== + */ + +// 将组件添加到影子DOM中 +$(() => $('* > shadow-inner').each((_i, v) => { + $(v.parentElement.shadowRoot).append(v.children) + v.parentNode.removeChild(v) +})) diff --git a/client/utils-shared.js b/client/utils-shared.js new file mode 100644 index 0000000..99ea501 --- /dev/null +++ b/client/utils-shared.js @@ -0,0 +1,30 @@ +/* + * ©2024 The LingChair Project + * + * Make a more colorful world... + * + * License - Apache License 2.0 + * Author - @MoonLeeeaf + * Organization - @LingChair + */ + +/** + * ======================================================== + * 移动端检测 + * ======================================================== + */ + +const isMobile = () => ('ontouchstart' in document.documentElement) + +/** + * ======================================================== + * 移动端调试 + * ======================================================== + */ + +if (isMobile()) { + let a = document.createElement('script') + a.src = "https://unpkg.com/eruda/eruda.js" + a.onload = () => eruda.init() + document.head.appendChild(a) +}